Skip to main content

grid_map/dim/
dim.rs

1use crate::{DimLocs, Loc, Scale};
2use std::fmt::{Debug, Display, Formatter};
3
4/// Two-dimensional grid dimensions.
5#[derive(Copy, Clone, Eq, PartialEq, Hash, Default)]
6pub struct Dim {
7    pub w: Scale,
8    pub h: Scale,
9}
10
11impl Dim {
12    //! Construction
13
14    /// Creates new dimensions.
15    pub const fn new(w: Scale, h: Scale) -> Self {
16        Self { w, h }
17    }
18}
19
20impl From<(Scale, Scale)> for Dim {
21    fn from((w, h): (Scale, Scale)) -> Self {
22        Self { w, h }
23    }
24}
25
26impl From<Dim> for (Scale, Scale) {
27    fn from(dims: Dim) -> Self {
28        (dims.w, dims.h)
29    }
30}
31
32impl Dim {
33    //! Properties
34
35    /// Gets the size.
36    pub const fn size(self) -> usize {
37        self.w as usize * self.h as usize
38    }
39
40    /// Checks if the `loc` is within the dimensions.
41    pub const fn contains(self, loc: Loc) -> bool {
42        loc.x < self.w && loc.y < self.h
43    }
44}
45
46impl Dim {
47    //! Iteration
48
49    /// Creates an iterator for the locations within the dimensions.
50    pub fn locs(self) -> DimLocs {
51        DimLocs::from(self)
52    }
53}
54
55impl Debug for Dim {
56    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57        write!(f, "{}", self)
58    }
59}
60
61impl Display for Dim {
62    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63        write!(f, "{}x{}", self.w, self.h)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use crate::{Dim, Loc, Scale};
70
71    #[test]
72    fn size() {
73        let test_cases: &[(Scale, Scale, usize)] = &[
74            (3, 4, 12), // standard
75            (0, 5, 0),  // zero width
76            (5, 0, 0),  // zero height
77            (1, 1, 1),  // minimum non-zero
78            (
79                Scale::MAX,
80                Scale::MAX,
81                Scale::MAX as usize * Scale::MAX as usize,
82            ), // max scale
83        ];
84
85        for &(w, h, expected) in test_cases {
86            assert_eq!(Dim::new(w, h).size(), expected);
87        }
88    }
89
90    #[test]
91    fn contains() {
92        let test_cases: &[(Dim, Loc, bool)] = &[
93            (Dim::new(3, 3), Loc::new(0, 0), true),  // origin
94            (Dim::new(3, 3), Loc::new(2, 2), true),  // max corner
95            (Dim::new(3, 3), Loc::new(1, 0), true),  // interior
96            (Dim::new(3, 3), Loc::new(3, 0), false), // x out of bounds
97            (Dim::new(3, 3), Loc::new(0, 3), false), // y out of bounds
98            (Dim::new(3, 3), Loc::new(3, 3), false), // both out of bounds
99            (Dim::new(0, 0), Loc::new(0, 0), false), // zero dimensions
100        ];
101
102        for &(dim, loc, expected) in test_cases {
103            assert_eq!(dim.contains(loc), expected);
104        }
105    }
106}