Skip to main content

grid_map/dir/
square.rs

1use std::fmt::{Display, Formatter};
2
3/// A direction on a square grid.
4#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
5pub enum Dir {
6    North,
7    East,
8    South,
9    West,
10}
11
12impl Dir {
13    //! Constants
14
15    /// All directions.
16    pub const ALL: [Dir; 4] = [Dir::North, Dir::East, Dir::South, Dir::West];
17}
18
19impl Dir {
20    //! Properties
21
22    /// Gets the opposite direction.
23    pub const fn opposite(self) -> Self {
24        match self {
25            Dir::North => Dir::South,
26            Dir::East => Dir::West,
27            Dir::South => Dir::North,
28            Dir::West => Dir::East,
29        }
30    }
31
32    /// Gets the direction to the left (counter-clockwise).
33    pub const fn left(self) -> Self {
34        match self {
35            Dir::North => Dir::West,
36            Dir::East => Dir::North,
37            Dir::South => Dir::East,
38            Dir::West => Dir::South,
39        }
40    }
41
42    /// Gets the direction to the right (clockwise).
43    pub const fn right(self) -> Self {
44        match self {
45            Dir::North => Dir::East,
46            Dir::East => Dir::South,
47            Dir::South => Dir::West,
48            Dir::West => Dir::North,
49        }
50    }
51}
52
53impl Display for Dir {
54    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55        write!(f, "{:?}", self)
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use crate::Dir;
62
63    #[test]
64    fn opposite_roundtrip() {
65        for dir in Dir::ALL {
66            assert_eq!(dir.opposite().opposite(), dir);
67        }
68    }
69
70    #[test]
71    fn opposite_not_self() {
72        for dir in Dir::ALL {
73            assert_ne!(dir.opposite(), dir);
74        }
75    }
76
77    #[test]
78    fn left_right_inverse() {
79        for dir in Dir::ALL {
80            assert_eq!(dir.left().right(), dir);
81            assert_eq!(dir.right().left(), dir);
82        }
83    }
84
85    #[test]
86    fn four_rights_make_a_circle() {
87        for dir in Dir::ALL {
88            assert_eq!(dir.right().right().right().right(), dir);
89        }
90    }
91
92    #[test]
93    fn four_lefts_make_a_circle() {
94        for dir in Dir::ALL {
95            assert_eq!(dir.left().left().left().left(), dir);
96        }
97    }
98
99    #[test]
100    fn all_unique() {
101        for (i, a) in Dir::ALL.iter().enumerate() {
102            for (j, b) in Dir::ALL.iter().enumerate() {
103                if i != j {
104                    assert_ne!(a, b);
105                }
106            }
107        }
108    }
109}