1use std::ops::{Add, RangeBounds, Sub};
2
3use crate::{
4 grid::config::Entity,
5 grid::records::{ExactRecords, Records},
6 settings::object::{cell::EntityOnce, Object},
7};
8
9use super::util::bounds_to_usize;
10
11/// Row denotes a set of cells on given rows on a [`Table`].
12///
13/// [`Table`]: crate::Table
14#[derive(Debug)]
15pub struct Rows<R> {
16 range: R,
17}
18
19impl<R> Rows<R> {
20 /// Returns a new instance of [`Rows`] for a range of rows.
21 ///
22 /// If the boundaries are exceeded it may panic.
23 pub fn new(range: R) -> Self
24 where
25 R: RangeBounds<usize>,
26 {
27 Self { range }
28 }
29
30 pub(crate) const fn get_range(&self) -> &R {
31 &self.range
32 }
33}
34
35impl Rows<()> {
36 /// Returns a new instance of [`Rows`] with a single row.
37 ///
38 /// If the boundaries are exceeded it may panic.
39 pub const fn single(index: usize) -> Row {
40 Row { index }
41 }
42
43 /// Returns a first row [`Object`].
44 ///
45 /// If the table has 0 rows returns an empty set of cells.
46 pub const fn first() -> FirstRow {
47 FirstRow
48 }
49
50 /// Returns a last row [`Object`].
51 ///
52 /// If the table has 0 rows returns an empty set of cells.
53 pub const fn last() -> LastRow {
54 LastRow
55 }
56}
57
58impl<I, R> Object<I> for Rows<R>
59where
60 R: RangeBounds<usize>,
61 I: ExactRecords,
62{
63 type Iter = RowsIter;
64
65 fn cells(&self, records: &I) -> Self::Iter {
66 let start: Bound<&usize> = self.range.start_bound();
67 let end: Bound<&usize> = self.range.end_bound();
68 let max: usize = records.count_rows();
69 let (x: usize, y: usize) = bounds_to_usize(left:start, right:end, count_elements:max);
70
71 RowsIter::new(start:x, end:y)
72 }
73}
74
75/// A row which is located by an offset from the first row.
76#[derive(Debug, Clone, Copy)]
77pub struct Row {
78 index: usize,
79}
80
81impl<I> Object<I> for Row {
82 type Iter = EntityOnce;
83
84 fn cells(&self, _: &I) -> Self::Iter {
85 EntityOnce::new(entity:Some(Entity::Row(self.index)))
86 }
87}
88
89impl From<Row> for usize {
90 fn from(val: Row) -> Self {
91 val.index
92 }
93}
94
95impl From<usize> for Row {
96 fn from(index: usize) -> Row {
97 Row { index }
98 }
99}
100
101/// This structure represents the first row of a [`Table`].
102/// It's often contains headers data.
103///
104/// [`Table`]: crate::Table
105#[derive(Debug)]
106pub struct FirstRow;
107
108impl<I> Object<I> for FirstRow
109where
110 I: Records + ExactRecords,
111{
112 type Iter = EntityOnce;
113
114 fn cells(&self, records: &I) -> Self::Iter {
115 if records.count_columns() == 0 || records.count_rows() == 0 {
116 return EntityOnce::new(entity:None);
117 }
118
119 EntityOnce::new(entity:Some(Entity::Row(0)))
120 }
121}
122
123impl Add<usize> for FirstRow {
124 type Output = Row;
125
126 fn add(self, rhs: usize) -> Self::Output {
127 Row { index: rhs }
128 }
129}
130
131/// This structure represents the last row of a [`Table`].
132///
133/// [`Table`]: crate::Table
134#[derive(Debug)]
135pub struct LastRow;
136
137impl<I> Object<I> for LastRow
138where
139 I: Records + ExactRecords,
140{
141 type Iter = EntityOnce;
142
143 fn cells(&self, records: &I) -> Self::Iter {
144 let count_rows: usize = records.count_rows();
145 if records.count_columns() == 0 || count_rows == 0 {
146 return EntityOnce::new(entity:None);
147 }
148
149 let row: usize = if count_rows == 0 { 0 } else { count_rows - 1 };
150
151 EntityOnce::new(entity:Some(Entity::Row(row)))
152 }
153}
154
155impl Sub<usize> for LastRow {
156 type Output = LastRowOffset;
157
158 fn sub(self, rhs: usize) -> Self::Output {
159 LastRowOffset { offset: rhs }
160 }
161}
162
163/// A row which is located by an offset from the last row.
164#[derive(Debug)]
165pub struct LastRowOffset {
166 offset: usize,
167}
168
169impl<I> Object<I> for LastRowOffset
170where
171 I: Records + ExactRecords,
172{
173 type Iter = EntityOnce;
174
175 fn cells(&self, records: &I) -> Self::Iter {
176 let count_rows: usize = records.count_rows();
177 if records.count_columns() == 0 || count_rows == 0 {
178 return EntityOnce::new(entity:None);
179 }
180
181 let row: usize = if count_rows == 0 { 0 } else { count_rows - 1 };
182 if self.offset > row {
183 return EntityOnce::new(entity:None);
184 }
185
186 let row: usize = row - self.offset;
187 EntityOnce::new(entity:Some(Entity::Row(row)))
188 }
189}
190
191/// An [`Iterator`] which goes goes over all rows of a [`Table`].
192///
193/// [`Table`]: crate::Table
194#[derive(Debug)]
195pub struct RowsIter {
196 start: usize,
197 end: usize,
198}
199
200impl RowsIter {
201 const fn new(start: usize, end: usize) -> Self {
202 Self { start, end }
203 }
204}
205
206impl Iterator for RowsIter {
207 type Item = Entity;
208
209 fn next(&mut self) -> Option<Self::Item> {
210 if self.start >= self.end {
211 return None;
212 }
213
214 let col: usize = self.start;
215 self.start += 1;
216
217 Some(Entity::Row(col))
218 }
219}
220