Skip to main content

rkg_utils/header/mii/
mole.rs

1use std::convert::Infallible;
2
3use crate::byte_handler::{ByteHandlerError, FromByteHandler};
4
5/// Represents the mole customization options of a Mii,
6/// including whether a mole is shown and its position and size.
7#[derive(Clone, Copy)]
8pub struct Mole {
9    /// Whether the mole is visible on the Mii's face.
10    has_mole: bool,
11    /// Horizontal position of the mole (0–16).
12    x: u8,
13    /// Vertical position of the mole (0–30).
14    y: u8,
15    /// Mole size (0–8).
16    size: u8,
17}
18
19impl Mole {
20    /// Creates a new [`Mole`] from its individual components.
21    ///
22    /// # Arguments
23    ///
24    /// * `has_mole` - Whether the mole is visible.
25    /// * `x` - Horizontal position (0–16).
26    /// * `y` - Vertical position (0–30).
27    /// * `size` - Mole size (0–8).
28    ///
29    /// # Errors
30    ///
31    /// Returns [`MoleError::XInvalid`] if `x` exceeds 16.
32    /// Returns [`MoleError::YInvalid`] if `y` exceeds 30.
33    /// Returns [`MoleError::SizeInvalid`] if `size` exceeds 8.
34    pub fn new(has_mole: bool, x: u8, y: u8, size: u8) -> Result<Self, MoleError> {
35        if x > 16 {
36            return Err(MoleError::XInvalid);
37        }
38        if y > 30 {
39            return Err(MoleError::YInvalid);
40        }
41        if size > 8 {
42            return Err(MoleError::SizeInvalid);
43        }
44        Ok(Self {
45            has_mole,
46            x,
47            y,
48            size,
49        })
50    }
51
52    /// Returns whether the mole is visible on the Mii's face.
53    pub fn has_mole(&self) -> bool {
54        self.has_mole
55    }
56
57    /// Returns the horizontal position of the mole (0–16).
58    pub fn x(&self) -> u8 {
59        self.x
60    }
61
62    /// Returns the vertical position of the mole (0–30).
63    pub fn y(&self) -> u8 {
64        self.y
65    }
66
67    /// Returns the mole size (0–8).
68    pub fn size(&self) -> u8 {
69        self.size
70    }
71
72    /// Sets whether the mole is visible on the Mii's face.
73    pub fn set_has_mole(&mut self, has_mole: bool) {
74        self.has_mole = has_mole;
75    }
76
77    /// Sets the horizontal position of the mole.
78    ///
79    /// # Errors
80    ///
81    /// Returns [`MoleError::XInvalid`] if `x` exceeds 16.
82    pub fn set_x(&mut self, x: u8) -> Result<(), MoleError> {
83        if x > 16 {
84            return Err(MoleError::XInvalid);
85        }
86        self.x = x;
87        Ok(())
88    }
89
90    /// Sets the vertical position of the mole.
91    ///
92    /// # Errors
93    ///
94    /// Returns [`MoleError::YInvalid`] if `y` exceeds 30.
95    pub fn set_y(&mut self, y: u8) -> Result<(), MoleError> {
96        if y > 30 {
97            return Err(MoleError::YInvalid);
98        }
99        self.y = y;
100        Ok(())
101    }
102
103    /// Sets the mole size.
104    ///
105    /// # Errors
106    ///
107    /// Returns [`MoleError::SizeInvalid`] if `size` exceeds 8.
108    pub fn set_size(&mut self, size: u8) -> Result<(), MoleError> {
109        if size > 8 {
110            return Err(MoleError::SizeInvalid);
111        }
112        self.size = size;
113        Ok(())
114    }
115}
116
117/// Deserializes a [`Mole`] from a `ByteHandler`.
118///
119/// Extracts the mole visibility flag, horizontal position, vertical position,
120/// and size from the packed Mii binary format using bit shifts and masks.
121impl FromByteHandler for Mole {
122    type Err = MoleError;
123    fn from_byte_handler<T>(handler: T) -> Result<Self, Self::Err>
124    where
125        T: TryInto<crate::byte_handler::ByteHandler>,
126        Self::Err: From<T::Error>,
127    {
128        let mut handler = handler.try_into()?;
129        let has_mole = handler.read_bool(15);
130        handler.shift_right(1);
131        let x = handler.copy_byte(1) & 0x1F;
132        handler.shift_right(2);
133        let y = handler.copy_byte(1) >> 3;
134        let size = handler.copy_byte(0) & 0x0F;
135        Self::new(has_mole, x, y, size)
136    }
137}
138
139/// Errors that can occur while constructing or deserializing a [`Mole`].
140#[derive(thiserror::Error, Debug)]
141pub enum MoleError {
142    /// The size value exceeds the maximum of 8.
143    #[error("Size is invalid")]
144    SizeInvalid,
145    /// The vertical position exceeds the maximum of 30.
146    #[error("Y position is invalid")]
147    YInvalid,
148    /// The horizontal position exceeds the maximum of 16.
149    #[error("X position is invalid")]
150    XInvalid,
151    /// A `ByteHandler` operation failed.
152    #[error("ByteHandler Error: {0}")]
153    ByteHandlerError(#[from] ByteHandlerError),
154    /// Infallible conversion error; cannot occur at runtime.
155    #[error("")]
156    Infallible(#[from] Infallible),
157}