Skip to main content

sokoban_elements/
size2d.rs

1use std::fmt;
2use std::fmt::Display;
3use std::num::TryFromIntError;
4
5/// 2D size of game boards.
6#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct Size2D {
8    pub width:  usize,
9    pub height: usize,
10}
11
12impl Size2D {
13    pub fn new(width: usize, height: usize) -> Self { Self { width, height } }
14
15    /// Returns the total number of cells in the board.
16    pub fn size(&self) -> usize {
17        // Having this method return `usize` instead of Option<usize> is deliberate
18        // choice of convenience. This is meant to measure sizes of Sokoban boards and,
19        // in real world, these boards are much smaller than `usize::MAX`.
20        self.width.saturating_mul(self.height)
21    }
22}
23
24impl Display for Size2D {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        write!(f, "{}x{}", self.width, self.height)
27    }
28}
29
30impl From<(u8, u8)> for Size2D {
31    fn from(value: (u8, u8)) -> Self {
32        Self {
33            width:  value.0.into(),
34            height: value.1.into(),
35        }
36    }
37}
38
39impl From<(u16, u16)> for Size2D {
40    fn from(value: (u16, u16)) -> Self {
41        Self {
42            width:  value.0.into(),
43            height: value.1.into(),
44        }
45    }
46}
47
48impl TryFrom<(u32, u32)> for Size2D {
49    type Error = TryFromIntError;
50
51    /// `value` is `(width, height)`
52    fn try_from(value: (u32, u32)) -> Result<Self, Self::Error> {
53        Ok(Size2D {
54            width:  value.0.try_into()?,
55            height: value.1.try_into()?,
56        })
57    }
58}
59
60impl TryFrom<(u64, u64)> for Size2D {
61    type Error = TryFromIntError;
62
63    /// `value` is `(width, height)`
64    fn try_from(value: (u64, u64)) -> Result<Self, Self::Error> {
65        Ok(Size2D {
66            width:  value.0.try_into()?,
67            height: value.1.try_into()?,
68        })
69    }
70}
71
72impl From<(usize, usize)> for Size2D {
73    fn from(value: (usize, usize)) -> Self {
74        Self {
75            width:  value.0,
76            height: value.1,
77        }
78    }
79}