1use crate::layout::{Position, Rect};
2
3pub struct Rows {
5 rect: Rect,
7 current_row_fwd: u16,
9 current_row_back: u16,
11}
12
13impl Rows {
14 pub const fn new(rect: Rect) -> Self {
16 Self {
17 rect,
18 current_row_fwd: rect.y,
19 current_row_back: rect.bottom(),
20 }
21 }
22}
23
24impl Iterator for Rows {
25 type Item = Rect;
26
27 fn next(&mut self) -> Option<Self::Item> {
31 if self.current_row_fwd >= self.current_row_back {
32 return None;
33 }
34 let row = Rect::new(self.rect.x, self.current_row_fwd, self.rect.width, 1);
35 self.current_row_fwd += 1;
36 Some(row)
37 }
38
39 fn size_hint(&self) -> (usize, Option<usize>) {
40 let start_count = self.current_row_fwd.saturating_sub(self.rect.top());
41 let end_count = self.rect.bottom().saturating_sub(self.current_row_back);
42 let count = self
43 .rect
44 .height
45 .saturating_sub(start_count)
46 .saturating_sub(end_count) as usize;
47 (count, Some(count))
48 }
49}
50
51impl DoubleEndedIterator for Rows {
52 fn next_back(&mut self) -> Option<Self::Item> {
56 if self.current_row_back <= self.current_row_fwd {
57 return None;
58 }
59 self.current_row_back -= 1;
60 let row = Rect::new(self.rect.x, self.current_row_back, self.rect.width, 1);
61 Some(row)
62 }
63}
64
65pub struct Columns {
67 rect: Rect,
69 current_column_fwd: u16,
71 current_column_back: u16,
73}
74
75impl Columns {
76 pub const fn new(rect: Rect) -> Self {
78 Self {
79 rect,
80 current_column_fwd: rect.x,
81 current_column_back: rect.right(),
82 }
83 }
84}
85
86impl Iterator for Columns {
87 type Item = Rect;
88
89 fn next(&mut self) -> Option<Self::Item> {
93 if self.current_column_fwd >= self.current_column_back {
94 return None;
95 }
96 let column = Rect::new(self.current_column_fwd, self.rect.y, 1, self.rect.height);
97 self.current_column_fwd += 1;
98 Some(column)
99 }
100
101 fn size_hint(&self) -> (usize, Option<usize>) {
102 let start_count = self.current_column_fwd.saturating_sub(self.rect.left());
103 let end_count = self.rect.right().saturating_sub(self.current_column_back);
104 let count = self
105 .rect
106 .width
107 .saturating_sub(start_count)
108 .saturating_sub(end_count) as usize;
109 (count, Some(count))
110 }
111}
112
113impl DoubleEndedIterator for Columns {
114 fn next_back(&mut self) -> Option<Self::Item> {
118 if self.current_column_back <= self.current_column_fwd {
119 return None;
120 }
121 self.current_column_back -= 1;
122 let column = Rect::new(self.current_column_back, self.rect.y, 1, self.rect.height);
123 Some(column)
124 }
125}
126
127pub struct Positions {
131 rect: Rect,
133 current_position: Position,
135}
136
137impl Positions {
138 pub const fn new(rect: Rect) -> Self {
140 Self {
141 rect,
142 current_position: Position::new(rect.x, rect.y),
143 }
144 }
145}
146
147impl Iterator for Positions {
148 type Item = Position;
149
150 fn next(&mut self) -> Option<Self::Item> {
154 if self.current_position.y >= self.rect.bottom() {
155 return None;
156 }
157 let position = self.current_position;
158 self.current_position.x += 1;
159 if self.current_position.x >= self.rect.right() {
160 self.current_position.x = self.rect.x;
161 self.current_position.y += 1;
162 }
163 Some(position)
164 }
165
166 fn size_hint(&self) -> (usize, Option<usize>) {
167 let row_count = self.rect.bottom().saturating_sub(self.current_position.y);
168 if row_count == 0 {
169 return (0, Some(0));
170 }
171 let column_count = self.rect.right().saturating_sub(self.current_position.x);
172 let count = (row_count - 1)
174 .saturating_mul(self.rect.width)
175 .saturating_add(column_count) as usize;
176 (count, Some(count))
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn rows() {
186 let rect = Rect::new(0, 0, 2, 3);
187 let mut rows = Rows::new(rect);
188 assert_eq!(rows.size_hint(), (3, Some(3)));
189 assert_eq!(rows.next(), Some(Rect::new(0, 0, 2, 1)));
190 assert_eq!(rows.size_hint(), (2, Some(2)));
191 assert_eq!(rows.next(), Some(Rect::new(0, 1, 2, 1)));
192 assert_eq!(rows.size_hint(), (1, Some(1)));
193 assert_eq!(rows.next(), Some(Rect::new(0, 2, 2, 1)));
194 assert_eq!(rows.size_hint(), (0, Some(0)));
195 assert_eq!(rows.next(), None);
196 assert_eq!(rows.size_hint(), (0, Some(0)));
197 assert_eq!(rows.next_back(), None);
198 assert_eq!(rows.size_hint(), (0, Some(0)));
199 }
200
201 #[test]
202 fn rows_back() {
203 let rect = Rect::new(0, 0, 2, 3);
204 let mut rows = Rows::new(rect);
205 assert_eq!(rows.size_hint(), (3, Some(3)));
206 assert_eq!(rows.next_back(), Some(Rect::new(0, 2, 2, 1)));
207 assert_eq!(rows.size_hint(), (2, Some(2)));
208 assert_eq!(rows.next_back(), Some(Rect::new(0, 1, 2, 1)));
209 assert_eq!(rows.size_hint(), (1, Some(1)));
210 assert_eq!(rows.next_back(), Some(Rect::new(0, 0, 2, 1)));
211 assert_eq!(rows.size_hint(), (0, Some(0)));
212 assert_eq!(rows.next_back(), None);
213 assert_eq!(rows.size_hint(), (0, Some(0)));
214 assert_eq!(rows.next(), None);
215 assert_eq!(rows.size_hint(), (0, Some(0)));
216 }
217
218 #[test]
219 fn rows_meet_in_the_middle() {
220 let rect = Rect::new(0, 0, 2, 4);
221 let mut rows = Rows::new(rect);
222 assert_eq!(rows.size_hint(), (4, Some(4)));
223 assert_eq!(rows.next(), Some(Rect::new(0, 0, 2, 1)));
224 assert_eq!(rows.size_hint(), (3, Some(3)));
225 assert_eq!(rows.next_back(), Some(Rect::new(0, 3, 2, 1)));
226 assert_eq!(rows.size_hint(), (2, Some(2)));
227 assert_eq!(rows.next(), Some(Rect::new(0, 1, 2, 1)));
228 assert_eq!(rows.size_hint(), (1, Some(1)));
229 assert_eq!(rows.next_back(), Some(Rect::new(0, 2, 2, 1)));
230 assert_eq!(rows.size_hint(), (0, Some(0)));
231 assert_eq!(rows.next(), None);
232 assert_eq!(rows.size_hint(), (0, Some(0)));
233 assert_eq!(rows.next_back(), None);
234 assert_eq!(rows.size_hint(), (0, Some(0)));
235 }
236
237 #[test]
238 fn columns() {
239 let rect = Rect::new(0, 0, 3, 2);
240 let mut columns = Columns::new(rect);
241 assert_eq!(columns.size_hint(), (3, Some(3)));
242 assert_eq!(columns.next(), Some(Rect::new(0, 0, 1, 2)));
243 assert_eq!(columns.size_hint(), (2, Some(2)));
244 assert_eq!(columns.next(), Some(Rect::new(1, 0, 1, 2)));
245 assert_eq!(columns.size_hint(), (1, Some(1)));
246 assert_eq!(columns.next(), Some(Rect::new(2, 0, 1, 2)));
247 assert_eq!(columns.size_hint(), (0, Some(0)));
248 assert_eq!(columns.next(), None);
249 assert_eq!(columns.size_hint(), (0, Some(0)));
250 assert_eq!(columns.next_back(), None);
251 assert_eq!(columns.size_hint(), (0, Some(0)));
252 }
253
254 #[test]
255 fn columns_back() {
256 let rect = Rect::new(0, 0, 3, 2);
257 let mut columns = Columns::new(rect);
258 assert_eq!(columns.size_hint(), (3, Some(3)));
259 assert_eq!(columns.next_back(), Some(Rect::new(2, 0, 1, 2)));
260 assert_eq!(columns.size_hint(), (2, Some(2)));
261 assert_eq!(columns.next_back(), Some(Rect::new(1, 0, 1, 2)));
262 assert_eq!(columns.size_hint(), (1, Some(1)));
263 assert_eq!(columns.next_back(), Some(Rect::new(0, 0, 1, 2)));
264 assert_eq!(columns.size_hint(), (0, Some(0)));
265 assert_eq!(columns.next_back(), None);
266 assert_eq!(columns.size_hint(), (0, Some(0)));
267 assert_eq!(columns.next(), None);
268 assert_eq!(columns.size_hint(), (0, Some(0)));
269 }
270
271 #[test]
272 fn columns_meet_in_the_middle() {
273 let rect = Rect::new(0, 0, 4, 2);
274 let mut columns = Columns::new(rect);
275 assert_eq!(columns.size_hint(), (4, Some(4)));
276 assert_eq!(columns.next(), Some(Rect::new(0, 0, 1, 2)));
277 assert_eq!(columns.size_hint(), (3, Some(3)));
278 assert_eq!(columns.next_back(), Some(Rect::new(3, 0, 1, 2)));
279 assert_eq!(columns.size_hint(), (2, Some(2)));
280 assert_eq!(columns.next(), Some(Rect::new(1, 0, 1, 2)));
281 assert_eq!(columns.size_hint(), (1, Some(1)));
282 assert_eq!(columns.next_back(), Some(Rect::new(2, 0, 1, 2)));
283 assert_eq!(columns.size_hint(), (0, Some(0)));
284 assert_eq!(columns.next(), None);
285 assert_eq!(columns.size_hint(), (0, Some(0)));
286 assert_eq!(columns.next_back(), None);
287 assert_eq!(columns.size_hint(), (0, Some(0)));
288 }
289
290 #[test]
294 fn columns_max() {
295 let rect = Rect::new(0, 0, u16::MAX, 1);
296 let mut columns = Columns::new(rect).skip(usize::from(u16::MAX - 1));
297 assert_eq!(columns.next(), Some(Rect::new(u16::MAX - 1, 0, 1, 1)));
298 assert_eq!(columns.next(), None);
299 }
300
301 #[test]
305 fn columns_min() {
306 let rect = Rect::new(0, 0, u16::MAX, 1);
307 let mut columns = Columns::new(rect).rev().skip(usize::from(u16::MAX - 1));
308 assert_eq!(columns.next(), Some(Rect::new(0, 0, 1, 1)));
309 assert_eq!(columns.next(), None);
310 assert_eq!(columns.next(), None);
311 }
312
313 #[test]
314 fn positions() {
315 let rect = Rect::new(0, 0, 2, 2);
316 let mut positions = Positions::new(rect);
317 assert_eq!(positions.size_hint(), (4, Some(4)));
318 assert_eq!(positions.next(), Some(Position::new(0, 0)));
319 assert_eq!(positions.size_hint(), (3, Some(3)));
320 assert_eq!(positions.next(), Some(Position::new(1, 0)));
321 assert_eq!(positions.size_hint(), (2, Some(2)));
322 assert_eq!(positions.next(), Some(Position::new(0, 1)));
323 assert_eq!(positions.size_hint(), (1, Some(1)));
324 assert_eq!(positions.next(), Some(Position::new(1, 1)));
325 assert_eq!(positions.size_hint(), (0, Some(0)));
326 assert_eq!(positions.next(), None);
327 assert_eq!(positions.size_hint(), (0, Some(0)));
328 }
329}