tabled/features/
locator.rs
1use std::{
4 iter::Once,
5 ops::{Range, RangeBounds},
6};
7
8use papergrid::{records::Records, Entity};
9
10use crate::{
11 object::{
12 bounds_to_usize, Column, Columns, FirstColumn, FirstRow, LastColumn, LastRow, Object, Row,
13 Rows,
14 },
15 Table,
16};
17
18pub trait Locator {
21 type Coordinate;
23 type IntoIter: IntoIterator<Item = Self::Coordinate>;
26
27 fn locate<R>(&mut self, records: R) -> Self::IntoIter
29 where
30 R: Records;
31}
32
33impl<B> Locator for Columns<B>
34where
35 B: RangeBounds<usize>,
36{
37 type Coordinate = usize;
38 type IntoIter = Range<usize>;
39
40 fn locate<R>(&mut self, records: R) -> Self::IntoIter
41 where
42 R: Records,
43 {
44 let (from, to) = bounds_to_usize(
45 self.get_range().start_bound(),
46 self.get_range().end_bound(),
47 records.count_columns(),
48 );
49
50 from..to
51 }
52}
53
54impl Locator for Column {
55 type Coordinate = usize;
56 type IntoIter = Once<usize>;
57
58 fn locate<R>(&mut self, _: R) -> Self::IntoIter
59 where
60 R: Records,
61 {
62 std::iter::once((*self).into())
63 }
64}
65
66impl Locator for FirstColumn {
67 type Coordinate = usize;
68 type IntoIter = Once<usize>;
69
70 fn locate<R>(&mut self, _: R) -> Self::IntoIter
71 where
72 R: Records,
73 {
74 std::iter::once(0)
75 }
76}
77
78impl Locator for LastColumn {
79 type Coordinate = usize;
80 type IntoIter = Once<usize>;
81
82 fn locate<R>(&mut self, records: R) -> Self::IntoIter
83 where
84 R: Records,
85 {
86 if records.count_columns() > 0 {
87 std::iter::once(records.count_columns() - 1)
88 } else {
89 std::iter::once(0)
90 }
91 }
92}
93
94impl<B> Locator for Rows<B>
95where
96 B: RangeBounds<usize>,
97{
98 type Coordinate = usize;
99 type IntoIter = Range<usize>;
100
101 fn locate<R>(&mut self, records: R) -> Self::IntoIter
102 where
103 R: Records,
104 {
105 let (from, to) = bounds_to_usize(
106 self.get_range().start_bound(),
107 self.get_range().end_bound(),
108 records.count_columns(),
109 );
110
111 from..to
112 }
113}
114
115impl Locator for Row {
116 type Coordinate = usize;
117 type IntoIter = Once<usize>;
118
119 fn locate<R>(&mut self, _: R) -> Self::IntoIter
120 where
121 R: Records,
122 {
123 std::iter::once((*self).into())
124 }
125}
126
127impl Locator for FirstRow {
128 type Coordinate = usize;
129 type IntoIter = Once<usize>;
130
131 fn locate<R>(&mut self, _: R) -> Self::IntoIter
132 where
133 R: Records,
134 {
135 std::iter::once(0)
136 }
137}
138
139impl Locator for LastRow {
140 type Coordinate = usize;
141 type IntoIter = Once<usize>;
142
143 fn locate<R>(&mut self, records: R) -> Self::IntoIter
144 where
145 R: Records,
146 {
147 if records.count_rows() > 0 {
148 std::iter::once(records.count_rows() - 1)
149 } else {
150 std::iter::once(0)
151 }
152 }
153}
154
155#[derive(Debug, Clone, Copy)]
160pub struct ByColumnName<S>(S);
161
162impl<S> ByColumnName<S> {
163 pub fn new(text: S) -> Self
165 where
166 S: AsRef<str>,
167 {
168 Self(text)
169 }
170}
171
172impl<S> Locator for ByColumnName<S>
173where
174 S: AsRef<str>,
175{
176 type Coordinate = usize;
177 type IntoIter = Vec<usize>;
178
179 fn locate<R>(&mut self, records: R) -> Self::IntoIter
180 where
181 R: Records,
182 {
183 (0..records.count_columns())
185 .filter(|col| records.get_text((0, *col)) == self.0.as_ref())
186 .collect::<Vec<_>>()
187 }
188}
189
190impl<S> Object for ByColumnName<S>
191where
192 S: AsRef<str>,
193{
194 type Iter = std::vec::IntoIter<Entity>;
195
196 fn cells<R>(&self, table: &Table<R>) -> Self::Iter
197 where
198 R: Records,
199 {
200 (0..table.count_columns())
202 .filter(|col| table.get_records().get_text((0, *col)) == self.0.as_ref())
203 .map(Entity::Column)
204 .collect::<Vec<_>>()
205 .into_iter()
206 }
207}