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}