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 single(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: usize = records.count_columns();
67 let start: Bound<&usize> = self.range.start_bound();
68 let end: Bound<&usize> = self.range.end_bound();
69 let (x: usize, y: usize) = bounds_to_usize(left:start, right:end, count_elements:max);
70
71 ColumnsIter::new(start:x, end: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(entity:None);
88 }
89
90 EntityOnce::new(entity: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(entity:None);
115 }
116
117 let col: usize = records.count_columns().saturating_sub(1);
118 EntityOnce::new(entity: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 { offset: rhs }
127 }
128}
129
130/// Column represents a single column on a grid.
131#[derive(Debug, Clone, Copy)]
132pub struct Column(usize);
133
134impl<I> Object<I> for Column {
135 type Iter = EntityOnce;
136
137 fn cells(&self, _: &I) -> Self::Iter {
138 EntityOnce::new(entity:Some(Entity::Column(self.0)))
139 }
140}
141
142impl From<usize> for Column {
143 fn from(i: usize) -> Self {
144 Self(i)
145 }
146}
147
148impl From<Column> for usize {
149 fn from(val: Column) -> Self {
150 val.0
151 }
152}
153
154/// `LastColumnOffset` represents a single column on a grid indexed via offset from the last column.
155#[derive(Debug)]
156pub struct LastColumnOffset {
157 offset: usize,
158}
159
160impl<I> Object<I> for LastColumnOffset
161where
162 I: Records + ExactRecords,
163{
164 type Iter = EntityOnce;
165
166 fn cells(&self, records: &I) -> Self::Iter {
167 if records.count_rows() == 0 || records.count_columns() == 0 {
168 return EntityOnce::new(entity:None);
169 }
170
171 let col: usize = records.count_columns().saturating_sub(1);
172 if self.offset > col {
173 return EntityOnce::new(entity:None);
174 }
175
176 let col: usize = col - self.offset;
177 EntityOnce::new(entity:Some(Entity::Column(col)))
178 }
179}
180
181/// An [`Iterator`] which goes goes over columns of a [`Table`].
182///
183/// [`Table`]: crate::Table
184#[derive(Debug)]
185pub struct ColumnsIter {
186 start: usize,
187 end: usize,
188}
189
190impl ColumnsIter {
191 const fn new(start: usize, end: usize) -> Self {
192 Self { start, end }
193 }
194}
195
196impl Iterator for ColumnsIter {
197 type Item = Entity;
198
199 fn next(&mut self) -> Option<Self::Item> {
200 if self.start >= self.end {
201 return None;
202 }
203
204 let col: usize = self.start;
205 self.start += 1;
206
207 Some(Entity::Column(col))
208 }
209}
210