Skip to main content

rkg_utils/header/mii/
build.rs

1use std::convert::Infallible;
2
3use crate::byte_handler::{ByteHandlerError, FromByteHandler};
4
5/// Errors that can occur while constructing a [`Build`].
6#[derive(Debug, thiserror::Error)]
7pub enum BuildError {
8    /// The weight value exceeds the maximum allowed value of 127.
9    #[error("Weight is invalid")]
10    WeightInvalid,
11    /// The height value exceeds the maximum allowed value of 127.
12    #[error("Height is invalid")]
13    HeightInvalid,
14    /// A `ByteHandler` operation failed.
15    #[error("ByteHandler Error: {0}")]
16    ByteHandlerError(#[from] ByteHandlerError),
17    /// Infallible conversion error; cannot occur at runtime.
18    #[error("")]
19    Infallible(#[from] Infallible),
20}
21
22/// Represents the body proportions of a Mii, storing height and weight values.
23///
24/// Both values are clamped to the range 0–127 as defined by the Mii data format.
25#[derive(Clone, Copy)]
26pub struct Build {
27    /// The Mii's height (0–127).
28    height: u8,
29    /// The Mii's weight (0–127).
30    weight: u8,
31}
32
33impl Build {
34    #[inline(always)]
35    /// Creates a new [`Build`] from raw height and weight values.
36    ///
37    /// # Arguments
38    ///
39    /// * `height` - The Mii's height (0–127).
40    /// * `weight` - The Mii's weight (0–127).
41    ///
42    /// # Errors
43    ///
44    /// Returns [`BuildError::HeightInvalid`] if `height` exceeds 127.
45    /// Returns [`BuildError::WeightInvalid`] if `weight` exceeds 127.
46    pub fn new(height: u8, weight: u8) -> Result<Self, BuildError> {
47        if height > 127 {
48            return Err(BuildError::HeightInvalid);
49        }
50        if weight > 127 {
51            return Err(BuildError::WeightInvalid);
52        }
53        Ok(Self { height, weight })
54    }
55
56    /// Returns the Mii's height (0–127).
57    pub fn height(&self) -> u8 {
58        self.height
59    }
60
61    /// Sets the Mii's height to the given value.
62    ///
63    /// # Errors
64    ///
65    /// Returns [`BuildError::HeightInvalid`] if `height` exceeds 127.
66    pub fn set_height(&mut self, height: u8) -> Result<(), BuildError> {
67        if height > 127 {
68            return Err(BuildError::HeightInvalid);
69        }
70        self.height = height;
71        Ok(())
72    }
73
74    /// Returns the Mii's weight (0–127).
75    pub fn weight(&self) -> u8 {
76        self.weight
77    }
78
79    /// Sets the Mii's weight to the given value.
80    ///
81    /// # Errors
82    ///
83    /// Returns [`BuildError::WeightInvalid`] if `weight` exceeds 127.
84    pub fn set_weight(&mut self, weight: u8) -> Result<(), BuildError> {
85        if weight > 127 {
86            return Err(BuildError::WeightInvalid);
87        }
88        self.height = weight;
89        Ok(())
90    }
91}
92
93/// Deserializes a [`Build`] from a `ByteHandler`.
94///
95/// The height is read from the first byte and the weight from the second byte.
96impl FromByteHandler for Build {
97    type Err = BuildError;
98
99    fn from_byte_handler<T>(handler: T) -> Result<Self, Self::Err>
100    where
101        T: TryInto<crate::byte_handler::ByteHandler>,
102        Self::Err: From<T::Error>,
103    {
104        let handler = handler.try_into()?;
105
106        Self::new(handler.copy_byte(0), handler.copy_byte(1))
107    }
108}