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}