1 | use super::Position; |
2 | |
3 | /// Entity a structure which represent a set of cells. |
4 | /// |
5 | /// For example such table: |
6 | /// |
7 | /// ```text |
8 | /// ┌───┬───┐ |
9 | /// │ 0 │ 1 │ |
10 | /// ├───┼───┤ |
11 | /// │ 1 │ 2 │ |
12 | /// └───┴───┘ |
13 | /// ``` |
14 | /// |
15 | /// - has 4 cells. |
16 | /// Which indexes are (0, 0), (0, 1), (1, 0), (1, 1). |
17 | /// |
18 | /// - has 2 rows. |
19 | /// Which indexes are 0, 1. |
20 | /// |
21 | /// - has 2 column. |
22 | /// Which indexes are 0, 1. |
23 | /// |
24 | /// In [`Entity`] terms, all cells on the grid we call `Global`. |
25 | #[derive (PartialEq, Eq, Debug, Hash, Clone, Copy)] |
26 | pub enum Entity { |
27 | /// All cells on the grid. |
28 | Global, |
29 | /// All cells in a column on the grid. |
30 | Column(usize), |
31 | /// All cells in a row on the grid. |
32 | Row(usize), |
33 | /// A particular cell (row, column) on the grid. |
34 | Cell(usize, usize), |
35 | } |
36 | |
37 | impl Entity { |
38 | /// Iterate over cells which are covered via the [`Entity`]. |
39 | pub fn iter(&self, count_rows: usize, count_cols: usize) -> EntityIterator { |
40 | EntityIterator { |
41 | entity: *self, |
42 | count_rows, |
43 | count_cols, |
44 | i: 0, |
45 | j: 0, |
46 | } |
47 | } |
48 | } |
49 | |
50 | impl From<Position> for Entity { |
51 | fn from((row: usize, col: usize): Position) -> Self { |
52 | Self::Cell(row, col) |
53 | } |
54 | } |
55 | |
56 | /// An iterator over cells. |
57 | /// |
58 | /// Produced from [`Entity::iter`]. |
59 | #[derive (Debug, Clone)] |
60 | pub struct EntityIterator { |
61 | entity: Entity, |
62 | count_rows: usize, |
63 | count_cols: usize, |
64 | i: usize, |
65 | j: usize, |
66 | } |
67 | |
68 | impl Iterator for EntityIterator { |
69 | type Item = Position; |
70 | |
71 | fn next(&mut self) -> Option<Self::Item> { |
72 | if self.count_rows == 0 || self.count_cols == 0 { |
73 | return None; |
74 | } |
75 | |
76 | match self.entity { |
77 | Entity::Cell(row, col) => { |
78 | self.count_cols = 0; |
79 | self.count_rows = 0; |
80 | |
81 | Some((row, col)) |
82 | } |
83 | Entity::Column(col) => { |
84 | if self.i >= self.count_rows { |
85 | return None; |
86 | } |
87 | |
88 | let i = self.i; |
89 | self.i += 1; |
90 | |
91 | Some((i, col)) |
92 | } |
93 | Entity::Row(row) => { |
94 | if self.j >= self.count_cols { |
95 | return None; |
96 | } |
97 | |
98 | let j = self.j; |
99 | self.j += 1; |
100 | |
101 | Some((row, j)) |
102 | } |
103 | Entity::Global => { |
104 | if self.j >= self.count_cols { |
105 | self.j = 0; |
106 | self.i += 1; |
107 | |
108 | if self.i >= self.count_rows { |
109 | return None; |
110 | } |
111 | } |
112 | |
113 | let j = self.j; |
114 | self.j += 1; |
115 | |
116 | Some((self.i, j)) |
117 | } |
118 | } |
119 | } |
120 | } |
121 | |