papergrid/config/
position.rs

1use core::ops::{Add, AddAssign, Sub, SubAssign};
2
3/// Position is a (row, col) position on a Grid.
4///
5/// For example such table has 4 cells.
6/// Which indexes are (0, 0), (0, 1), (1, 0), (1, 1).
7///
8/// ```text
9/// ┌───┬───┐
10/// │ 0 │ 1 │
11/// ├───┼───┤
12/// │ 1 │ 2 │
13/// └───┴───┘
14/// ```
15#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
16pub struct Position {
17    /// Row.
18    pub row: usize,
19    /// Column.
20    pub col: usize,
21}
22
23impl Position {
24    /// Creates a new [`Position`] object.
25    pub const fn new(row: usize, col: usize) -> Self {
26        Self { row, col }
27    }
28
29    /// A check whether a given cell has intersection with any other cell.
30    ///
31    /// # Example
32    ///
33    /// ```
34    /// # use papergrid::config::Position;
35    /// let p = Position::new(3, 3);
36    ///
37    /// assert!(p.has_intersection(p));
38    /// assert!(p.has_intersection(Position::new(1, 1)));
39    /// assert!(p.has_intersection(Position::new(3, 10)));
40    /// assert!(p.has_intersection(Position::new(10, 3)));
41    ///
42    /// assert!(!p.has_intersection(Position::new(4, 4)));
43    /// ```
44    pub const fn has_intersection(&self, point: Position) -> bool {
45        self.row >= point.row || self.col >= point.col
46    }
47
48    /// A check whether a given cell has intersection with any other cell.
49    ///
50    /// # Example
51    ///
52    /// ```
53    /// # use papergrid::config::Position;
54    /// let p = Position::new(3, 3);
55    ///
56    /// assert!(p.has_coverage(Position::new(1, 1)));
57    ///
58    /// assert!(!p.has_coverage(Position::new(3, 3)));
59    /// assert!(!p.has_coverage(Position::new(1, 10)));
60    /// assert!(!p.has_coverage(p));
61    /// ```
62    pub const fn has_coverage(&self, point: Position) -> bool {
63        self.row > point.row && self.col > point.col
64    }
65}
66
67impl Add<Position> for Position {
68    type Output = Position;
69
70    fn add(self, rhs: Self) -> Self::Output {
71        Self::new(self.row + rhs.row, self.col + rhs.col)
72    }
73}
74
75impl Add<(usize, usize)> for Position {
76    type Output = Position;
77
78    fn add(self, rhs: (usize, usize)) -> Self::Output {
79        Self::new(self.row + rhs.0, self.col + rhs.1)
80    }
81}
82
83impl Sub<Position> for Position {
84    type Output = Position;
85
86    fn sub(self, rhs: Self) -> Self::Output {
87        Self::new(self.row - rhs.row, self.col - rhs.col)
88    }
89}
90
91impl Sub<(usize, usize)> for Position {
92    type Output = Position;
93
94    fn sub(self, rhs: (usize, usize)) -> Self::Output {
95        Self::new(self.row - rhs.0, self.col - rhs.1)
96    }
97}
98
99impl AddAssign<Position> for Position {
100    fn add_assign(&mut self, rhs: Position) {
101        self.row += rhs.row;
102        self.col += rhs.col;
103    }
104}
105
106impl AddAssign<(usize, usize)> for Position {
107    fn add_assign(&mut self, rhs: (usize, usize)) {
108        self.row += rhs.0;
109        self.col += rhs.1;
110    }
111}
112
113impl SubAssign<Position> for Position {
114    fn sub_assign(&mut self, rhs: Position) {
115        self.row -= rhs.row;
116        self.col -= rhs.col;
117    }
118}
119
120impl SubAssign<(usize, usize)> for Position {
121    fn sub_assign(&mut self, rhs: (usize, usize)) {
122        self.row -= rhs.0;
123        self.col -= rhs.1;
124    }
125}
126
127impl From<(usize, usize)> for Position {
128    fn from(value: (usize, usize)) -> Self {
129        Self::new(value.0, value.1)
130    }
131}
132
133impl From<Position> for (usize, usize) {
134    fn from(val: Position) -> Self {
135        (val.row, val.col)
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_ordering() {
145        assert!(Position::new(1, 1) < Position::new(2, 2));
146        assert!(Position::new(2, 1) < Position::new(2, 2));
147        assert!(Position::new(1, 2) < Position::new(2, 2));
148
149        assert!(Position::new(2, 2) == Position::new(2, 2));
150
151        assert!(Position::new(3, 3) > Position::new(2, 2));
152        assert!(Position::new(3, 1) > Position::new(2, 2));
153
154        assert!(Position::new(1, 3) < Position::new(2, 2));
155
156        assert!(Position::new(0, 10000) < Position::new(4, 4));
157    }
158}