Skip to main content

ferrex_model/image/
dimensions.rs

1use std::num::NonZeroU32;
2
3/// Non-zero pixel dimensions for a decoded image.
4///
5/// This is intentionally independent of `ImageSize`, because `ImageSize` is a
6/// *requested* or *logical* size (e.g. "original", "w780"), while decoded
7/// dimensions are the authoritative width/height of the actual bytes stored.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[cfg_attr(
11    feature = "rkyv",
12    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
13)]
14#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
15pub struct ImageDimensions {
16    pub width: NonZeroU32,
17    pub height: NonZeroU32,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum ImageDimensionsError {
22    ZeroWidth,
23    ZeroHeight,
24}
25
26impl ImageDimensions {
27    pub const fn new(width: NonZeroU32, height: NonZeroU32) -> Self {
28        Self { width, height }
29    }
30
31    pub const fn width_u32(self) -> u32 {
32        self.width.get()
33    }
34
35    pub const fn height_u32(self) -> u32 {
36        self.height.get()
37    }
38
39    pub const fn as_u32_tuple(self) -> (u32, u32) {
40        (self.width.get(), self.height.get())
41    }
42}
43
44impl TryFrom<(u32, u32)> for ImageDimensions {
45    type Error = ImageDimensionsError;
46
47    fn try_from(value: (u32, u32)) -> Result<Self, Self::Error> {
48        let (width, height) = value;
49        let width =
50            NonZeroU32::new(width).ok_or(ImageDimensionsError::ZeroWidth)?;
51        let height =
52            NonZeroU32::new(height).ok_or(ImageDimensionsError::ZeroHeight)?;
53        Ok(Self { width, height })
54    }
55}