tabled/settings/object/
rows.rs

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 one(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 = self.range.start_bound();
67        let end = self.range.end_bound();
68        let max = records.count_rows();
69        let (x, y) = bounds_to_usize(start, end, max);
70
71        RowsIter::new(x, 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(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(None);
117        }
118
119        EntityOnce::new(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 = records.count_rows();
145        if records.count_columns() == 0 || count_rows == 0 {
146            return EntityOnce::new(None);
147        }
148
149        let row = count_rows - 1;
150
151        EntityOnce::new(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::sub(rhs)
160    }
161}
162
163impl Add<usize> for LastRow {
164    type Output = LastRowOffset;
165
166    fn add(self, rhs: usize) -> Self::Output {
167        LastRowOffset::add(rhs)
168    }
169}
170
171/// A row which is located by an offset from the last row.
172#[derive(Debug)]
173pub struct LastRowOffset {
174    offset: usize,
175    sign: bool,
176}
177
178impl LastRowOffset {
179    fn sub(offset: usize) -> Self {
180        Self {
181            offset,
182            sign: false,
183        }
184    }
185
186    fn add(offset: usize) -> Self {
187        Self { offset, sign: true }
188    }
189}
190
191impl<I> Object<I> for LastRowOffset
192where
193    I: Records + ExactRecords,
194{
195    type Iter = EntityOnce;
196
197    fn cells(&self, records: &I) -> Self::Iter {
198        let count_rows = records.count_rows();
199        if records.count_columns() == 0 || count_rows == 0 {
200            return EntityOnce::new(None);
201        }
202
203        let last_row = count_rows - 1;
204
205        if self.sign {
206            let row = last_row + self.offset;
207            EntityOnce::new(Some(Entity::Row(row)))
208        } else {
209            if self.offset > last_row {
210                return EntityOnce::new(None);
211            }
212
213            let row = last_row - self.offset;
214            EntityOnce::new(Some(Entity::Row(row)))
215        }
216    }
217}
218
219/// An [`Iterator`] which goes goes over all rows of a [`Table`].
220///
221/// [`Table`]: crate::Table
222#[derive(Debug)]
223pub struct RowsIter {
224    start: usize,
225    end: usize,
226}
227
228impl RowsIter {
229    const fn new(start: usize, end: usize) -> Self {
230        Self { start, end }
231    }
232}
233
234impl Iterator for RowsIter {
235    type Item = Entity;
236
237    fn next(&mut self) -> Option<Self::Item> {
238        if self.start >= self.end {
239            return None;
240        }
241
242        let col = self.start;
243        self.start += 1;
244
245        Some(Entity::Row(col))
246    }
247}