1 | //! This module contains a list of primitives that implement a [`Object`] trait. |
2 | //! They help to locate a necessary segment on a [`Table`]. |
3 | //! |
4 | //! [`Table`]: crate::Table |
5 | |
6 | mod cell; |
7 | mod columns; |
8 | mod frame; |
9 | mod rows; |
10 | mod segment; |
11 | pub(crate) mod util; |
12 | |
13 | use std::{collections::HashSet, marker::PhantomData}; |
14 | |
15 | use self::segment::SectorCellsIter; |
16 | |
17 | use crate::{ |
18 | grid::config::{Entity, EntityIterator}, |
19 | grid::records::{ExactRecords, Records}, |
20 | }; |
21 | |
22 | pub use cell::{Cell, EntityOnce}; |
23 | pub use columns::{Column, Columns, ColumnsIter, FirstColumn, LastColumn, LastColumnOffset}; |
24 | pub use frame::{Frame, FrameIter}; |
25 | pub use rows::{FirstRow, LastRow, LastRowOffset, Row, Rows, RowsIter}; |
26 | pub use segment::{SectorIter, Segment, SegmentAll}; |
27 | |
28 | /// Object helps to locate a necessary part of a [`Table`]. |
29 | /// |
30 | /// [`Table`]: crate::Table |
31 | pub trait Object<R> { |
32 | /// An [`Iterator`] which returns a list of cells. |
33 | type Iter: Iterator<Item = Entity>; |
34 | |
35 | /// Cells returns a set of coordinates of cells. |
36 | fn cells(&self, records: &R) -> Self::Iter; |
37 | |
38 | /// Combines cells. |
39 | /// It doesn't repeat cells. |
40 | fn and<O>(self, rhs: O) -> UnionCombination<Self, O, R> |
41 | where |
42 | Self: Sized, |
43 | { |
44 | UnionCombination::new(self, rhs) |
45 | } |
46 | |
47 | /// Excludes rhs cells from this cells. |
48 | fn not<O>(self, rhs: O) -> DiffCombination<Self, O, R> |
49 | where |
50 | Self: Sized, |
51 | { |
52 | DiffCombination::new(self, rhs) |
53 | } |
54 | |
55 | /// Returns cells which are present in both [`Object`]s only. |
56 | fn intersect<O>(self, rhs: O) -> IntersectionCombination<Self, O, R> |
57 | where |
58 | Self: Sized, |
59 | { |
60 | IntersectionCombination::new(self, rhs) |
61 | } |
62 | |
63 | /// Returns cells which are not present in target [`Object`]. |
64 | fn inverse(self) -> InversionCombination<Self, R> |
65 | where |
66 | Self: Sized, |
67 | { |
68 | InversionCombination::new(self) |
69 | } |
70 | } |
71 | |
72 | /// Combination struct used for chaining [`Object`]'s. |
73 | /// |
74 | /// Combines 2 sets of cells into one. |
75 | /// |
76 | /// Duplicates are removed from the output set. |
77 | #[derive (Debug)] |
78 | pub struct UnionCombination<L, R, I> { |
79 | lhs: L, |
80 | rhs: R, |
81 | _records: PhantomData<I>, |
82 | } |
83 | |
84 | impl<L, R, I> UnionCombination<L, R, I> { |
85 | fn new(lhs: L, rhs: R) -> Self { |
86 | Self { |
87 | lhs, |
88 | rhs, |
89 | _records: PhantomData, |
90 | } |
91 | } |
92 | } |
93 | |
94 | impl<I, L, R> Object<I> for UnionCombination<L, R, I> |
95 | where |
96 | L: Object<I>, |
97 | R: Object<I>, |
98 | I: Records + ExactRecords, |
99 | { |
100 | type Iter = UnionIter<L::Iter, R::Iter>; |
101 | |
102 | fn cells(&self, records: &I) -> Self::Iter { |
103 | let lhs: >::Iter = self.lhs.cells(records); |
104 | let rhs: >::Iter = self.rhs.cells(records); |
105 | |
106 | UnionIter::new(lhs, rhs, records.count_rows(), count_cols:records.count_columns()) |
107 | } |
108 | } |
109 | |
110 | /// Difference struct used for chaining [`Object`]'s. |
111 | /// |
112 | /// Returns cells from 1st set with removed ones from the 2nd set. |
113 | #[derive (Debug)] |
114 | pub struct DiffCombination<L, R, I> { |
115 | lhs: L, |
116 | rhs: R, |
117 | _records: PhantomData<I>, |
118 | } |
119 | |
120 | impl<L, R, I> DiffCombination<L, R, I> { |
121 | fn new(lhs: L, rhs: R) -> Self { |
122 | Self { |
123 | lhs, |
124 | rhs, |
125 | _records: PhantomData, |
126 | } |
127 | } |
128 | } |
129 | |
130 | impl<I, L, R> Object<I> for DiffCombination<L, R, I> |
131 | where |
132 | L: Object<I>, |
133 | R: Object<I>, |
134 | I: Records + ExactRecords, |
135 | { |
136 | type Iter = DiffIter<L::Iter>; |
137 | |
138 | fn cells(&self, records: &I) -> Self::Iter { |
139 | let lhs: >::Iter = self.lhs.cells(records); |
140 | let rhs: >::Iter = self.rhs.cells(records); |
141 | |
142 | DiffIter::new(lhs, rhs, records.count_rows(), count_cols:records.count_columns()) |
143 | } |
144 | } |
145 | |
146 | /// Intersection struct used for chaining [`Object`]'s. |
147 | /// |
148 | /// Returns cells which are present in 2 sets. |
149 | /// But not in one of them |
150 | #[derive (Debug)] |
151 | pub struct IntersectionCombination<L, R, I> { |
152 | lhs: L, |
153 | rhs: R, |
154 | _records: PhantomData<I>, |
155 | } |
156 | |
157 | impl<L, R, I> IntersectionCombination<L, R, I> { |
158 | fn new(lhs: L, rhs: R) -> Self { |
159 | Self { |
160 | lhs, |
161 | rhs, |
162 | _records: PhantomData, |
163 | } |
164 | } |
165 | } |
166 | |
167 | impl<I, L, R> Object<I> for IntersectionCombination<L, R, I> |
168 | where |
169 | L: Object<I>, |
170 | R: Object<I>, |
171 | I: Records + ExactRecords, |
172 | { |
173 | type Iter = IntersectIter<L::Iter>; |
174 | |
175 | fn cells(&self, records: &I) -> Self::Iter { |
176 | let lhs: >::Iter = self.lhs.cells(records); |
177 | let rhs: >::Iter = self.rhs.cells(records); |
178 | |
179 | IntersectIter::new(lhs, rhs, records.count_rows(), count_cols:records.count_columns()) |
180 | } |
181 | } |
182 | |
183 | /// Inversion struct used for chaining [`Object`]'s. |
184 | /// |
185 | /// Returns cells which are present in 2 sets. |
186 | /// But not in one of them |
187 | #[derive (Debug)] |
188 | pub struct InversionCombination<O, I> { |
189 | obj: O, |
190 | _records: PhantomData<I>, |
191 | } |
192 | |
193 | impl<O, I> InversionCombination<O, I> { |
194 | fn new(obj: O) -> Self { |
195 | Self { |
196 | obj, |
197 | _records: PhantomData, |
198 | } |
199 | } |
200 | } |
201 | |
202 | impl<I, O> Object<I> for InversionCombination<O, I> |
203 | where |
204 | O: Object<I>, |
205 | I: Records + ExactRecords, |
206 | { |
207 | type Iter = InversionIter; |
208 | |
209 | fn cells(&self, records: &I) -> Self::Iter { |
210 | let obj: >::Iter = self.obj.cells(records); |
211 | |
212 | InversionIter::new(obj, records.count_rows(), records.count_columns()) |
213 | } |
214 | } |
215 | |
216 | /// An [`Iterator`] which goes over a combination [`Object::Iter`]. |
217 | #[derive (Debug)] |
218 | pub struct UnionIter<L, R> { |
219 | lhs: Option<L>, |
220 | rhs: R, |
221 | seen: HashSet<(usize, usize)>, |
222 | current: Option<EntityIterator>, |
223 | count_rows: usize, |
224 | count_cols: usize, |
225 | } |
226 | |
227 | impl<L, R> UnionIter<L, R> |
228 | where |
229 | L: Iterator<Item = Entity>, |
230 | R: Iterator<Item = Entity>, |
231 | { |
232 | fn new(lhs: L, rhs: R, count_rows: usize, count_cols: usize) -> Self { |
233 | let size: usize = match lhs.size_hint() { |
234 | (s1: usize, Some(s2: usize)) if s1 == s2 => s1, |
235 | _ => 0, |
236 | }; |
237 | |
238 | Self { |
239 | lhs: Some(lhs), |
240 | rhs, |
241 | seen: HashSet::with_capacity(size), |
242 | current: None, |
243 | count_rows, |
244 | count_cols, |
245 | } |
246 | } |
247 | } |
248 | |
249 | impl<L, R> Iterator for UnionIter<L, R> |
250 | where |
251 | L: Iterator<Item = Entity>, |
252 | R: Iterator<Item = Entity>, |
253 | { |
254 | type Item = Entity; |
255 | |
256 | fn next(&mut self) -> Option<Self::Item> { |
257 | if let Some(iter) = self.current.as_mut() { |
258 | for p in iter.by_ref() { |
259 | if self.lhs.is_none() && self.seen.contains(&p) { |
260 | continue; |
261 | } |
262 | |
263 | let _ = self.seen.insert(p); |
264 | return Some(Entity::Cell(p.0, p.1)); |
265 | } |
266 | } |
267 | |
268 | if let Some(lhs) = self.lhs.as_mut() { |
269 | for entity in lhs.by_ref() { |
270 | let mut iter = entity.iter(self.count_rows, self.count_cols); |
271 | if let Some(p) = iter.by_ref().next() { |
272 | let _ = self.seen.insert(p); |
273 | self.current = Some(iter); |
274 | return Some(Entity::Cell(p.0, p.1)); |
275 | } |
276 | } |
277 | |
278 | self.lhs = None; |
279 | } |
280 | |
281 | for entity in self.rhs.by_ref() { |
282 | let mut iter = entity.iter(self.count_rows, self.count_cols); |
283 | |
284 | for p in iter.by_ref() { |
285 | if !self.seen.contains(&p) { |
286 | let _ = self.seen.insert(p); |
287 | self.current = Some(iter); |
288 | return Some(Entity::Cell(p.0, p.1)); |
289 | } |
290 | } |
291 | } |
292 | |
293 | None |
294 | } |
295 | } |
296 | |
297 | /// An [`Iterator`] which goes over only cells which are present in first [`Object::Iter`] but not second. |
298 | #[derive (Debug)] |
299 | pub struct DiffIter<L> { |
300 | lhs: L, |
301 | seen: HashSet<(usize, usize)>, |
302 | count_rows: usize, |
303 | count_cols: usize, |
304 | current: Option<EntityIterator>, |
305 | } |
306 | |
307 | impl<L> DiffIter<L> |
308 | where |
309 | L: Iterator<Item = Entity>, |
310 | { |
311 | fn new<R>(lhs: L, rhs: R, count_rows: usize, count_cols: usize) -> Self |
312 | where |
313 | R: Iterator<Item = Entity>, |
314 | { |
315 | let size: usize = match rhs.size_hint() { |
316 | (s1: usize, Some(s2: usize)) if s1 == s2 => s1, |
317 | _ => 0, |
318 | }; |
319 | |
320 | let mut seen: HashSet<(usize, usize)> = HashSet::with_capacity(size); |
321 | for entity: Entity in rhs { |
322 | seen.extend(entity.iter(count_rows, count_cols)); |
323 | } |
324 | |
325 | Self { |
326 | lhs, |
327 | seen, |
328 | count_rows, |
329 | count_cols, |
330 | current: None, |
331 | } |
332 | } |
333 | } |
334 | |
335 | impl<L> Iterator for DiffIter<L> |
336 | where |
337 | L: Iterator<Item = Entity>, |
338 | { |
339 | type Item = Entity; |
340 | |
341 | fn next(&mut self) -> Option<Self::Item> { |
342 | if let Some(iter) = self.current.as_mut() { |
343 | for p in iter.by_ref() { |
344 | if !self.seen.contains(&p) { |
345 | return Some(Entity::Cell(p.0, p.1)); |
346 | } |
347 | } |
348 | } |
349 | |
350 | for entity in self.lhs.by_ref() { |
351 | let mut iter = entity.iter(self.count_rows, self.count_cols); |
352 | |
353 | for p in iter.by_ref() { |
354 | if !self.seen.contains(&p) { |
355 | self.current = Some(iter); |
356 | return Some(Entity::Cell(p.0, p.1)); |
357 | } |
358 | } |
359 | } |
360 | |
361 | None |
362 | } |
363 | } |
364 | |
365 | /// An [`Iterator`] which goes goes over cells which are present in both [`Object::Iter`]ators. |
366 | #[derive (Debug)] |
367 | pub struct IntersectIter<L> { |
368 | lhs: L, |
369 | seen: HashSet<(usize, usize)>, |
370 | count_rows: usize, |
371 | count_cols: usize, |
372 | current: Option<EntityIterator>, |
373 | } |
374 | |
375 | impl<L> IntersectIter<L> |
376 | where |
377 | L: Iterator<Item = Entity>, |
378 | { |
379 | fn new<R>(lhs: L, rhs: R, count_rows: usize, count_cols: usize) -> Self |
380 | where |
381 | R: Iterator<Item = Entity>, |
382 | { |
383 | let size: usize = match rhs.size_hint() { |
384 | (s1: usize, Some(s2: usize)) if s1 == s2 => s1, |
385 | _ => 0, |
386 | }; |
387 | |
388 | let mut seen: HashSet<(usize, usize)> = HashSet::with_capacity(size); |
389 | for entity: Entity in rhs { |
390 | seen.extend(entity.iter(count_rows, count_cols)); |
391 | } |
392 | |
393 | Self { |
394 | lhs, |
395 | seen, |
396 | count_rows, |
397 | count_cols, |
398 | current: None, |
399 | } |
400 | } |
401 | } |
402 | |
403 | impl<L> Iterator for IntersectIter<L> |
404 | where |
405 | L: Iterator<Item = Entity>, |
406 | { |
407 | type Item = Entity; |
408 | |
409 | fn next(&mut self) -> Option<Self::Item> { |
410 | if let Some(iter) = self.current.as_mut() { |
411 | for p in iter.by_ref() { |
412 | if self.seen.contains(&p) { |
413 | return Some(Entity::Cell(p.0, p.1)); |
414 | } |
415 | } |
416 | } |
417 | |
418 | for entity in self.lhs.by_ref() { |
419 | let mut iter = entity.iter(self.count_rows, self.count_cols); |
420 | |
421 | for p in iter.by_ref() { |
422 | if self.seen.contains(&p) { |
423 | self.current = Some(iter); |
424 | return Some(Entity::Cell(p.0, p.1)); |
425 | } |
426 | } |
427 | } |
428 | |
429 | None |
430 | } |
431 | } |
432 | |
433 | /// An [`Iterator`] which goes goes over cells which are not present an [`Object::Iter`]ator. |
434 | #[derive (Debug)] |
435 | pub struct InversionIter { |
436 | all: SectorCellsIter, |
437 | seen: HashSet<(usize, usize)>, |
438 | } |
439 | |
440 | impl InversionIter { |
441 | fn new<O>(obj: O, count_rows: usize, count_columns: usize) -> Self |
442 | where |
443 | O: Iterator<Item = Entity>, |
444 | { |
445 | let size: usize = match obj.size_hint() { |
446 | (s1: usize, Some(s2: usize)) if s1 == s2 => s1, |
447 | _ => 0, |
448 | }; |
449 | |
450 | let mut seen: HashSet<(usize, usize)> = HashSet::with_capacity(size); |
451 | for entity: Entity in obj { |
452 | seen.extend(entity.iter(count_rows, count_cols:count_columns)); |
453 | } |
454 | |
455 | let all: SectorCellsIter = SectorCellsIter::new(rows_start:0, rows_end:count_rows, cols_start:0, cols_end:count_columns); |
456 | |
457 | Self { all, seen } |
458 | } |
459 | } |
460 | |
461 | impl Iterator for InversionIter { |
462 | type Item = Entity; |
463 | |
464 | fn next(&mut self) -> Option<Self::Item> { |
465 | for p: (usize, usize) in self.all.by_ref() { |
466 | if !self.seen.contains(&p) { |
467 | return Some(Entity::Cell(p.0, p.1)); |
468 | } |
469 | } |
470 | |
471 | None |
472 | } |
473 | } |
474 | |
475 | #[cfg (test)] |
476 | mod tests { |
477 | use crate::grid::records::vec_records::VecRecords; |
478 | |
479 | use super::*; |
480 | |
481 | #[test ] |
482 | fn cell_test() { |
483 | assert_eq!(vec_cells((0, 0), 2, 3), [Entity::Cell(0, 0)]); |
484 | assert_eq!(vec_cells((1, 1), 2, 3), [Entity::Cell(1, 1)]); |
485 | assert_eq!(vec_cells((1, 1), 0, 0), [Entity::Cell(1, 1)]); |
486 | assert_eq!(vec_cells((1, 100), 2, 3), [Entity::Cell(1, 100)]); |
487 | assert_eq!(vec_cells((100, 1), 2, 3), [Entity::Cell(100, 1)]); |
488 | } |
489 | |
490 | #[test ] |
491 | fn columns_test() { |
492 | assert_eq!( |
493 | vec_cells(Columns::new(..), 2, 3), |
494 | [Entity::Column(0), Entity::Column(1), Entity::Column(2)] |
495 | ); |
496 | assert_eq!( |
497 | vec_cells(Columns::new(1..), 2, 3), |
498 | [Entity::Column(1), Entity::Column(2)] |
499 | ); |
500 | assert_eq!(vec_cells(Columns::new(2..), 2, 3), [Entity::Column(2)]); |
501 | assert_eq!(vec_cells(Columns::new(3..), 2, 3), []); |
502 | assert_eq!(vec_cells(Columns::new(3..), 0, 0), []); |
503 | assert_eq!(vec_cells(Columns::new(0..1), 2, 3), [Entity::Column(0)]); |
504 | assert_eq!(vec_cells(Columns::new(1..2), 2, 3), [Entity::Column(1)]); |
505 | assert_eq!(vec_cells(Columns::new(2..3), 2, 3), [Entity::Column(2)]); |
506 | assert_eq!(vec_cells(Columns::new(..), 0, 0), []); |
507 | assert_eq!(vec_cells(Columns::new(..), 2, 0), []); |
508 | assert_eq!(vec_cells(Columns::new(..), 0, 3), []); |
509 | } |
510 | |
511 | #[test ] |
512 | fn first_column_test() { |
513 | assert_eq!(vec_cells(Columns::first(), 5, 2), [Entity::Column(0)]); |
514 | assert_eq!(vec_cells(Columns::first(), 0, 0), []); |
515 | assert_eq!(vec_cells(Columns::first(), 10, 0), []); |
516 | assert_eq!(vec_cells(Columns::first(), 0, 10), []); |
517 | } |
518 | |
519 | #[test ] |
520 | fn last_column_test() { |
521 | assert_eq!(vec_cells(Columns::last(), 5, 2), [Entity::Column(1)]); |
522 | assert_eq!(vec_cells(Columns::last(), 5, 29), [Entity::Column(28)]); |
523 | assert_eq!(vec_cells(Columns::last(), 0, 0), []); |
524 | assert_eq!(vec_cells(Columns::last(), 10, 0), []); |
525 | assert_eq!(vec_cells(Columns::last(), 0, 10), []); |
526 | } |
527 | |
528 | #[test ] |
529 | fn last_column_sub_test() { |
530 | assert_eq!(vec_cells(Columns::last(), 5, 2), [Entity::Column(1)]); |
531 | assert_eq!(vec_cells(Columns::last() - 0, 5, 2), [Entity::Column(1)]); |
532 | assert_eq!(vec_cells(Columns::last() - 1, 5, 2), [Entity::Column(0)]); |
533 | assert_eq!(vec_cells(Columns::last() - 2, 5, 2), []); |
534 | assert_eq!(vec_cells(Columns::last() - 100, 5, 2), []); |
535 | } |
536 | |
537 | #[test ] |
538 | fn first_column_add_test() { |
539 | assert_eq!(vec_cells(Columns::first(), 5, 2), [Entity::Column(0)]); |
540 | assert_eq!(vec_cells(Columns::first() + 0, 5, 2), [Entity::Column(0)]); |
541 | assert_eq!(vec_cells(Columns::first() + 1, 5, 2), [Entity::Column(1)]); |
542 | assert_eq!(vec_cells(Columns::first() + 2, 5, 2), [Entity::Column(2)]); |
543 | assert_eq!( |
544 | vec_cells(Columns::first() + 100, 5, 2), |
545 | [Entity::Column(100)] |
546 | ); |
547 | } |
548 | |
549 | #[test ] |
550 | fn rows_test() { |
551 | assert_eq!( |
552 | vec_cells(Rows::new(..), 2, 3), |
553 | [Entity::Row(0), Entity::Row(1)] |
554 | ); |
555 | assert_eq!(vec_cells(Rows::new(1..), 2, 3), [Entity::Row(1)]); |
556 | assert_eq!(vec_cells(Rows::new(2..), 2, 3), []); |
557 | assert_eq!(vec_cells(Rows::new(2..), 0, 0), []); |
558 | assert_eq!(vec_cells(Rows::new(0..1), 2, 3), [Entity::Row(0)],); |
559 | assert_eq!(vec_cells(Rows::new(1..2), 2, 3), [Entity::Row(1)],); |
560 | assert_eq!(vec_cells(Rows::new(..), 0, 0), []); |
561 | assert_eq!(vec_cells(Rows::new(..), 0, 3), []); |
562 | assert_eq!( |
563 | vec_cells(Rows::new(..), 2, 0), |
564 | [Entity::Row(0), Entity::Row(1)] |
565 | ); |
566 | } |
567 | |
568 | #[test ] |
569 | fn last_row_test() { |
570 | assert_eq!(vec_cells(Rows::last(), 5, 2), [Entity::Row(4)]); |
571 | assert_eq!(vec_cells(Rows::last(), 100, 2), [Entity::Row(99)]); |
572 | assert_eq!(vec_cells(Rows::last(), 0, 0), []); |
573 | assert_eq!(vec_cells(Rows::last(), 5, 0), []); |
574 | assert_eq!(vec_cells(Rows::last(), 0, 2), []); |
575 | } |
576 | |
577 | #[test ] |
578 | fn first_row_test() { |
579 | assert_eq!(vec_cells(Rows::first(), 5, 2), [Entity::Row(0)]); |
580 | assert_eq!(vec_cells(Rows::first(), 100, 2), [Entity::Row(0)]); |
581 | assert_eq!(vec_cells(Rows::first(), 0, 0), []); |
582 | assert_eq!(vec_cells(Rows::first(), 5, 0), []); |
583 | assert_eq!(vec_cells(Rows::first(), 0, 2), []); |
584 | } |
585 | |
586 | #[test ] |
587 | fn last_row_sub_test() { |
588 | assert_eq!(vec_cells(Rows::last(), 5, 2), [Entity::Row(4)]); |
589 | assert_eq!(vec_cells(Rows::last() - 0, 5, 2), [Entity::Row(4)]); |
590 | assert_eq!(vec_cells(Rows::last() - 1, 5, 2), [Entity::Row(3)]); |
591 | assert_eq!(vec_cells(Rows::last() - 2, 5, 2), [Entity::Row(2)]); |
592 | assert_eq!(vec_cells(Rows::last() - 3, 5, 2), [Entity::Row(1)]); |
593 | assert_eq!(vec_cells(Rows::last() - 4, 5, 2), [Entity::Row(0)]); |
594 | assert_eq!(vec_cells(Rows::last() - 5, 5, 2), []); |
595 | assert_eq!(vec_cells(Rows::last() - 100, 5, 2), []); |
596 | assert_eq!(vec_cells(Rows::last() - 1, 0, 0), []); |
597 | assert_eq!(vec_cells(Rows::last() - 1, 5, 0), []); |
598 | assert_eq!(vec_cells(Rows::last() - 1, 0, 2), []); |
599 | } |
600 | |
601 | #[test ] |
602 | fn first_row_add_test() { |
603 | assert_eq!(vec_cells(Rows::first(), 5, 2), [Entity::Row(0)]); |
604 | assert_eq!(vec_cells(Rows::first() + 0, 5, 2), [Entity::Row(0)]); |
605 | assert_eq!(vec_cells(Rows::first() + 1, 5, 2), [Entity::Row(1)]); |
606 | assert_eq!(vec_cells(Rows::first() + 2, 5, 2), [Entity::Row(2)]); |
607 | assert_eq!(vec_cells(Rows::first() + 3, 5, 2), [Entity::Row(3)]); |
608 | assert_eq!(vec_cells(Rows::first() + 4, 5, 2), [Entity::Row(4)]); |
609 | assert_eq!(vec_cells(Rows::first() + 5, 5, 2), [Entity::Row(5)]); |
610 | assert_eq!(vec_cells(Rows::first() + 100, 5, 2), [Entity::Row(100)]); |
611 | assert_eq!(vec_cells(Rows::first() + 1, 0, 0), [Entity::Row(1)]); |
612 | assert_eq!(vec_cells(Rows::first() + 1, 5, 0), [Entity::Row(1)]); |
613 | assert_eq!(vec_cells(Rows::first() + 1, 0, 2), [Entity::Row(1)]); |
614 | } |
615 | |
616 | #[test ] |
617 | fn frame_test() { |
618 | assert_eq!( |
619 | vec_cells(Frame, 2, 3), |
620 | [ |
621 | Entity::Cell(0, 0), |
622 | Entity::Cell(0, 1), |
623 | Entity::Cell(0, 2), |
624 | Entity::Cell(1, 0), |
625 | Entity::Cell(1, 1), |
626 | Entity::Cell(1, 2) |
627 | ] |
628 | ); |
629 | assert_eq!(vec_cells(Frame, 0, 0), []); |
630 | assert_eq!(vec_cells(Frame, 2, 0), []); |
631 | assert_eq!(vec_cells(Frame, 0, 2), []); |
632 | } |
633 | |
634 | #[test ] |
635 | fn segment_test() { |
636 | assert_eq!( |
637 | vec_cells(Segment::new(.., ..), 2, 3), |
638 | [ |
639 | Entity::Cell(0, 0), |
640 | Entity::Cell(0, 1), |
641 | Entity::Cell(0, 2), |
642 | Entity::Cell(1, 0), |
643 | Entity::Cell(1, 1), |
644 | Entity::Cell(1, 2) |
645 | ] |
646 | ); |
647 | assert_eq!( |
648 | vec_cells(Segment::new(1.., ..), 2, 3), |
649 | [Entity::Cell(1, 0), Entity::Cell(1, 1), Entity::Cell(1, 2)] |
650 | ); |
651 | assert_eq!(vec_cells(Segment::new(2.., ..), 2, 3), []); |
652 | |
653 | assert_eq!( |
654 | vec_cells(Segment::new(.., 1..), 2, 3), |
655 | [ |
656 | Entity::Cell(0, 1), |
657 | Entity::Cell(0, 2), |
658 | Entity::Cell(1, 1), |
659 | Entity::Cell(1, 2) |
660 | ] |
661 | ); |
662 | assert_eq!( |
663 | vec_cells(Segment::new(.., 2..), 2, 3), |
664 | [Entity::Cell(0, 2), Entity::Cell(1, 2)] |
665 | ); |
666 | assert_eq!(vec_cells(Segment::new(.., 3..), 2, 3), []); |
667 | |
668 | assert_eq!( |
669 | vec_cells(Segment::new(1.., 1..), 2, 3), |
670 | [Entity::Cell(1, 1), Entity::Cell(1, 2)] |
671 | ); |
672 | assert_eq!( |
673 | vec_cells(Segment::new(1..2, 1..2), 2, 3), |
674 | [Entity::Cell(1, 1)] |
675 | ); |
676 | |
677 | assert_eq!(vec_cells(Segment::new(5.., 5..), 2, 3), []); |
678 | } |
679 | |
680 | #[test ] |
681 | fn object_and_test() { |
682 | assert_eq!( |
683 | vec_cells(Cell::new(0, 0).and(Cell::new(0, 0)), 2, 3), |
684 | [Entity::Cell(0, 0)] |
685 | ); |
686 | assert_eq!( |
687 | vec_cells(Cell::new(0, 0).and(Cell::new(1, 2)), 2, 3), |
688 | [Entity::Cell(0, 0), Entity::Cell(1, 2)] |
689 | ); |
690 | assert_eq!(vec_cells(Cell::new(0, 0).and(Cell::new(1, 2)), 0, 0), []); |
691 | } |
692 | |
693 | #[test ] |
694 | fn object_not_test() { |
695 | assert_eq!(vec_cells(Rows::first().not(Cell::new(0, 0)), 0, 0), []); |
696 | assert_eq!(vec_cells(Cell::new(0, 0).not(Cell::new(0, 0)), 2, 3), []); |
697 | assert_eq!( |
698 | vec_cells(Rows::first().not(Cell::new(0, 0)), 2, 3), |
699 | [Entity::Cell(0, 1), Entity::Cell(0, 2)] |
700 | ); |
701 | assert_eq!( |
702 | vec_cells(Columns::single(1).not(Rows::single(1)), 3, 3), |
703 | [Entity::Cell(0, 1), Entity::Cell(2, 1)] |
704 | ); |
705 | assert_eq!( |
706 | vec_cells(Rows::single(1).not(Columns::single(1)), 3, 3), |
707 | [Entity::Cell(1, 0), Entity::Cell(1, 2)] |
708 | ); |
709 | } |
710 | |
711 | #[test ] |
712 | fn object_intersect_test() { |
713 | assert_eq!( |
714 | vec_cells(Rows::first().intersect(Cell::new(0, 0)), 0, 0), |
715 | [] |
716 | ); |
717 | assert_eq!( |
718 | vec_cells(Segment::all().intersect(Rows::single(1)), 2, 3), |
719 | [Entity::Cell(1, 0), Entity::Cell(1, 1), Entity::Cell(1, 2)] |
720 | ); |
721 | assert_eq!( |
722 | vec_cells(Cell::new(0, 0).intersect(Cell::new(0, 0)), 2, 3), |
723 | [Entity::Cell(0, 0)] |
724 | ); |
725 | assert_eq!( |
726 | vec_cells(Rows::first().intersect(Cell::new(0, 0)), 2, 3), |
727 | [Entity::Cell(0, 0)] |
728 | ); |
729 | // maybe we somehow shall not limit the rows/columns by the max count? |
730 | assert_eq!( |
731 | vec_cells(Rows::single(1).intersect(Columns::single(1)), 2, 1), |
732 | [] |
733 | ); |
734 | } |
735 | |
736 | #[test ] |
737 | fn object_inverse_test() { |
738 | assert_eq!(vec_cells(Segment::all().inverse(), 2, 3), []); |
739 | assert_eq!( |
740 | vec_cells(Cell::new(0, 0).inverse(), 2, 3), |
741 | [ |
742 | Entity::Cell(0, 1), |
743 | Entity::Cell(0, 2), |
744 | Entity::Cell(1, 0), |
745 | Entity::Cell(1, 1), |
746 | Entity::Cell(1, 2) |
747 | ] |
748 | ); |
749 | assert_eq!( |
750 | vec_cells(Rows::first().inverse(), 2, 3), |
751 | [Entity::Cell(1, 0), Entity::Cell(1, 1), Entity::Cell(1, 2)] |
752 | ); |
753 | assert_eq!(vec_cells(Rows::first().inverse(), 0, 0), []); |
754 | } |
755 | |
756 | fn vec_cells<O: Object<VecRecords<String>>>( |
757 | o: O, |
758 | count_rows: usize, |
759 | count_cols: usize, |
760 | ) -> Vec<Entity> { |
761 | let data = vec![vec![String::default(); count_cols]; count_rows]; |
762 | let records = VecRecords::new(data); |
763 | o.cells(&records).collect::<Vec<_>>() |
764 | } |
765 | } |
766 | |