1use 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)]
26pub 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
37impl 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
50impl 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)]
60pub struct EntityIterator {
61 entity: Entity,
62 count_rows: usize,
63 count_cols: usize,
64 i: usize,
65 j: usize,
66}
67
68impl 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