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
95/// This structure represents the first row of a [`Table`].
96/// It's often contains headers data.
97///
98/// [`Table`]: crate::Table
99#[derive(Debug)]
100pub struct FirstRow;
101
102impl<I> Object<I> for FirstRow
103where
104 I: Records + ExactRecords,
105{
106 type Iter = EntityOnce;
107
108 fn cells(&self, records: &I) -> Self::Iter {
109 if records.count_columns() == 0 || records.count_rows() == 0 {
110 return EntityOnce::new(entity:None);
111 }
112
113 EntityOnce::new(entity:Some(Entity::Row(0)))
114 }
115}
116
117impl Add<usize> for FirstRow {
118 type Output = Row;
119
120 fn add(self, rhs: usize) -> Self::Output {
121 Row { index: rhs }
122 }
123}
124
125/// This structure represents the last row of a [`Table`].
126///
127/// [`Table`]: crate::Table
128#[derive(Debug)]
129pub struct LastRow;
130
131impl<I> Object<I> for LastRow
132where
133 I: Records + ExactRecords,
134{
135 type Iter = EntityOnce;
136
137 fn cells(&self, records: &I) -> Self::Iter {
138 let count_rows: usize = records.count_rows();
139 if records.count_columns() == 0 || count_rows == 0 {
140 return EntityOnce::new(entity:None);
141 }
142
143 let row: usize = if count_rows == 0 { 0 } else { count_rows - 1 };
144
145 EntityOnce::new(entity:Some(Entity::Row(row)))
146 }
147}
148
149impl Sub<usize> for LastRow {
150 type Output = LastRowOffset;
151
152 fn sub(self, rhs: usize) -> Self::Output {
153 LastRowOffset { offset: rhs }
154 }
155}
156
157/// A row which is located by an offset from the last row.
158#[derive(Debug)]
159pub struct LastRowOffset {
160 offset: usize,
161}
162
163impl<I> Object<I> for LastRowOffset
164where
165 I: Records + ExactRecords,
166{
167 type Iter = EntityOnce;
168
169 fn cells(&self, records: &I) -> Self::Iter {
170 let count_rows: usize = records.count_rows();
171 if records.count_columns() == 0 || count_rows == 0 {
172 return EntityOnce::new(entity:None);
173 }
174
175 let row: usize = if count_rows == 0 { 0 } else { count_rows - 1 };
176 if self.offset > row {
177 return EntityOnce::new(entity:None);
178 }
179
180 let row: usize = row - self.offset;
181 EntityOnce::new(entity:Some(Entity::Row(row)))
182 }
183}
184
185/// An [`Iterator`] which goes goes over all rows of a [`Table`].
186///
187/// [`Table`]: crate::Table
188#[derive(Debug)]
189pub struct RowsIter {
190 start: usize,
191 end: usize,
192}
193
194impl RowsIter {
195 const fn new(start: usize, end: usize) -> Self {
196 Self { start, end }
197 }
198}
199
200impl Iterator for RowsIter {
201 type Item = Entity;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 if self.start >= self.end {
205 return None;
206 }
207
208 let col: usize = self.start;
209 self.start += 1;
210
211 Some(Entity::Row(col))
212 }
213}
214