tabled/settings/object/
columns.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/// Column denotes a set of cells on given columns on a [`Table`].
12///
13/// [`Table`]: crate::Table
14#[derive(Debug)]
15pub struct Columns<R> {
16    range: R,
17}
18
19impl<R> Columns<R> {
20    /// Returns a new instance of [`Columns`] for a range of columns.
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) fn get_range(&self) -> &R {
31        &self.range
32    }
33}
34
35impl Columns<()> {
36    /// Returns a new instance of [`Columns`] for a single column.
37    ///
38    /// If the boundaries are exceeded it may panic.
39    pub fn one(index: usize) -> Column {
40        Column(index)
41    }
42
43    /// Returns a new instance of [`Columns`] for a first column.
44    ///
45    /// If the boundaries are exceeded the object will produce no cells.
46    pub fn first() -> FirstColumn {
47        FirstColumn
48    }
49
50    /// Returns a new instance of [`Columns`] for a last column.
51    ///
52    /// If the boundaries are exceeded the object will produce no cells.
53    pub fn last() -> LastColumn {
54        LastColumn
55    }
56}
57
58impl<I, R> Object<I> for Columns<R>
59where
60    R: RangeBounds<usize>,
61    I: Records,
62{
63    type Iter = ColumnsIter;
64
65    fn cells(&self, records: &I) -> Self::Iter {
66        let max = records.count_columns();
67        let start = self.range.start_bound();
68        let end = self.range.end_bound();
69        let (x, y) = bounds_to_usize(start, end, max);
70
71        ColumnsIter::new(x, y)
72    }
73}
74
75/// `FirstColumn` represents the first column on a grid.
76#[derive(Debug)]
77pub struct FirstColumn;
78
79impl<I> Object<I> for FirstColumn
80where
81    I: Records + ExactRecords,
82{
83    type Iter = EntityOnce;
84
85    fn cells(&self, records: &I) -> Self::Iter {
86        if records.count_rows() == 0 || records.count_columns() == 0 {
87            return EntityOnce::new(None);
88        }
89
90        EntityOnce::new(Some(Entity::Column(0)))
91    }
92}
93
94impl Add<usize> for FirstColumn {
95    type Output = Column;
96
97    fn add(self, rhs: usize) -> Self::Output {
98        Column(rhs)
99    }
100}
101
102/// `LastColumn` represents the last column on a grid.
103#[derive(Debug)]
104pub struct LastColumn;
105
106impl<I> Object<I> for LastColumn
107where
108    I: Records + ExactRecords,
109{
110    type Iter = EntityOnce;
111
112    fn cells(&self, records: &I) -> Self::Iter {
113        if records.count_rows() == 0 || records.count_columns() == 0 {
114            return EntityOnce::new(None);
115        }
116
117        let col = records.count_columns().saturating_sub(1);
118        EntityOnce::new(Some(Entity::Column(col)))
119    }
120}
121
122impl Sub<usize> for LastColumn {
123    type Output = LastColumnOffset;
124
125    fn sub(self, rhs: usize) -> Self::Output {
126        LastColumnOffset::sub(rhs)
127    }
128}
129
130impl Add<usize> for LastColumn {
131    type Output = LastColumnOffset;
132
133    fn add(self, rhs: usize) -> Self::Output {
134        LastColumnOffset::add(rhs)
135    }
136}
137
138/// Column represents a single column on a grid.
139#[derive(Debug, Clone, Copy)]
140pub struct Column(usize);
141
142impl<I> Object<I> for Column {
143    type Iter = EntityOnce;
144
145    fn cells(&self, _: &I) -> Self::Iter {
146        EntityOnce::new(Some(Entity::Column(self.0)))
147    }
148}
149
150impl From<usize> for Column {
151    fn from(i: usize) -> Self {
152        Self(i)
153    }
154}
155
156impl From<Column> for usize {
157    fn from(val: Column) -> Self {
158        val.0
159    }
160}
161
162/// `LastColumnOffset` represents a single column on a grid indexed via offset from the last column.
163#[derive(Debug)]
164pub struct LastColumnOffset {
165    offset: usize,
166    sign: bool,
167}
168
169impl LastColumnOffset {
170    fn sub(offset: usize) -> Self {
171        Self {
172            offset,
173            sign: false,
174        }
175    }
176
177    fn add(offset: usize) -> Self {
178        Self { offset, sign: true }
179    }
180}
181
182impl<I> Object<I> for LastColumnOffset
183where
184    I: Records,
185{
186    type Iter = EntityOnce;
187
188    fn cells(&self, records: &I) -> Self::Iter {
189        let count_cols = records.count_columns();
190        if count_cols == 0 {
191            return EntityOnce::new(None);
192        }
193
194        let last_col = count_cols - 1;
195
196        if self.sign {
197            let col = last_col + self.offset;
198            EntityOnce::new(Some(Entity::Column(col)))
199        } else {
200            if self.offset > last_col {
201                return EntityOnce::new(None);
202            }
203
204            let col = last_col - self.offset;
205            EntityOnce::new(Some(Entity::Column(col)))
206        }
207    }
208}
209
210/// An [`Iterator`] which goes goes over columns of a [`Table`].
211///
212/// [`Table`]: crate::Table
213#[derive(Debug)]
214pub struct ColumnsIter {
215    start: usize,
216    end: usize,
217}
218
219impl ColumnsIter {
220    const fn new(start: usize, end: usize) -> Self {
221        Self { start, end }
222    }
223}
224
225impl Iterator for ColumnsIter {
226    type Item = Entity;
227
228    fn next(&mut self) -> Option<Self::Item> {
229        if self.start >= self.end {
230            return None;
231        }
232
233        let col = self.start;
234        self.start += 1;
235
236        Some(Entity::Column(col))
237    }
238}