1use std::convert::Infallible;
2
3use crate::{
4 byte_handler::{ByteHandlerError, FromByteHandler},
5 header::mii::hair::HairColor,
6};
7
8#[derive(Clone, Copy)]
13pub struct Eyebrows {
14 rotation: u8,
16 size: u8,
18 x: u8,
20 y: u8,
22 eyebrow_color: HairColor,
24 eyebrow_type: EyebrowType,
26}
27
28impl Eyebrows {
29 pub fn new(
47 rotation: u8,
48 size: u8,
49 x: u8,
50 y: u8,
51 eyebrow_color: HairColor,
52 eyebrow_type: EyebrowType,
53 ) -> Result<Self, EyebrowsError> {
54 if rotation > 11 {
55 return Err(EyebrowsError::RotationInvalid);
56 }
57 if size > 8 {
58 return Err(EyebrowsError::SizeInvalid);
59 }
60 if x > 12 {
61 return Err(EyebrowsError::XInvalid);
62 }
63 if !(3..=18).contains(&y) {
64 return Err(EyebrowsError::YInvalid);
65 }
66
67 Ok(Self {
68 rotation,
69 size,
70 x,
71 y,
72 eyebrow_color,
73 eyebrow_type,
74 })
75 }
76
77 pub fn rotation(&self) -> u8 {
79 self.rotation
80 }
81
82 pub fn size(&self) -> u8 {
84 self.size
85 }
86
87 pub fn x(&self) -> u8 {
89 self.x
90 }
91
92 pub fn y(&self) -> u8 {
94 self.y
95 }
96
97 pub fn eyebrow_color(&self) -> HairColor {
99 self.eyebrow_color
100 }
101
102 pub fn eyebrow_type(&self) -> EyebrowType {
104 self.eyebrow_type
105 }
106
107 pub fn set_rotation(&mut self, rotation: u8) -> Result<(), EyebrowsError> {
113 if rotation > 11 {
114 return Err(EyebrowsError::RotationInvalid);
115 }
116 self.rotation = rotation;
117 Ok(())
118 }
119
120 pub fn set_size(&mut self, size: u8) -> Result<(), EyebrowsError> {
126 if size > 8 {
127 return Err(EyebrowsError::SizeInvalid);
128 }
129 self.size = size;
130 Ok(())
131 }
132
133 pub fn set_x(&mut self, x: u8) -> Result<(), EyebrowsError> {
139 if x > 12 {
140 return Err(EyebrowsError::XInvalid);
141 }
142 self.x = x;
143 Ok(())
144 }
145
146 pub fn set_y(&mut self, y: u8) -> Result<(), EyebrowsError> {
152 if !(3..=18).contains(&y) {
153 return Err(EyebrowsError::YInvalid);
154 }
155 self.y = y;
156 Ok(())
157 }
158
159 pub fn set_eyebrow_color(&mut self, eyebrow_color: HairColor) {
161 self.eyebrow_color = eyebrow_color;
162 }
163
164 pub fn set_eyebrow_type(&mut self, eyebrow_type: EyebrowType) {
166 self.eyebrow_type = eyebrow_type;
167 }
168}
169
170#[derive(thiserror::Error, Debug)]
172pub enum EyebrowsError {
173 #[error("Type is invalid")]
175 TypeInvalid,
176 #[error("Color is invalid")]
178 ColorInvalid,
179 #[error("Rotation is invalid")]
181 RotationInvalid,
182 #[error("Size is invalid")]
184 SizeInvalid,
185 #[error("Y position is invalid")]
187 YInvalid,
188 #[error("X position is invalid")]
190 XInvalid,
191 #[error("ByteHandler Error: {0}")]
193 ByteHandlerError(#[from] ByteHandlerError),
194 #[error("")]
196 Infallible(#[from] Infallible),
197}
198
199impl FromByteHandler for Eyebrows {
204 type Err = EyebrowsError;
205 fn from_byte_handler<T>(handler: T) -> Result<Self, Self::Err>
206 where
207 T: TryInto<crate::byte_handler::ByteHandler>,
208 Self::Err: From<T::Error>,
209 {
210 let mut handler = handler.try_into()?;
211
212 let x = handler.copy_byte(3) & 0x0F;
213 let eyebrow_type = EyebrowType::try_from(handler.copy_byte(0) >> 3)
214 .map_err(|_| EyebrowsError::TypeInvalid)?;
215 let eyebrow_color = HairColor::try_from(handler.copy_byte(2) >> 5)
216 .map_err(|_| EyebrowsError::ColorInvalid)?;
217 handler.shift_right(1);
218 let y = handler.copy_byte(3) >> 3;
219 let size = handler.copy_byte(2) & 0x0F;
220 handler.shift_right(2);
221 let rotation = handler.copy_byte(1) >> 3;
222 Self::new(rotation, size, x, y, eyebrow_color, eyebrow_type)
223 }
224}
225
226#[derive(Clone, Copy, Debug, PartialEq)]
228pub enum EyebrowType {
229 FlatAngledLarge,
230 LowArchRoundedThin,
231 SoftAngledLarge,
232 MediumArchRoundedThin,
233 RoundedMedium,
234 LowArchMedium,
235 RoundedThin,
236 UpThin,
237 MediumArchRoundedMedium,
238 RoundedLarge,
239 UpLarge,
240 FlatAngledLargeInverted,
241 MediumArchFlat,
242 AngledThin,
243 HorizontalLarge,
244 HighArchFlat,
245 Flat,
246 MediumArchLarge,
247 LowArchThin,
248 RoundedThinInverted,
249 HighArchLarge,
250 Hairy,
251 Dotted,
252 None,
253}
254
255impl TryFrom<u8> for EyebrowType {
259 type Error = ();
260 fn try_from(value: u8) -> Result<Self, Self::Error> {
261 match value {
262 0x06 => Ok(Self::FlatAngledLarge),
263 0x00 => Ok(Self::LowArchRoundedThin),
264 0x0C => Ok(Self::SoftAngledLarge),
265 0x01 => Ok(Self::MediumArchRoundedThin),
266 0x09 => Ok(Self::RoundedMedium),
267 0x13 => Ok(Self::LowArchMedium),
268 0x07 => Ok(Self::RoundedThin),
269 0x15 => Ok(Self::UpThin),
270 0x08 => Ok(Self::MediumArchRoundedMedium),
271 0x11 => Ok(Self::RoundedLarge),
272 0x05 => Ok(Self::UpLarge),
273 0x04 => Ok(Self::FlatAngledLargeInverted),
274 0x0B => Ok(Self::MediumArchFlat),
275 0x0A => Ok(Self::AngledThin),
276 0x02 => Ok(Self::HorizontalLarge),
277 0x03 => Ok(Self::HighArchFlat),
278 0x0E => Ok(Self::Flat),
279 0x14 => Ok(Self::MediumArchLarge),
280 0x0F => Ok(Self::LowArchThin),
281 0x0D => Ok(Self::RoundedThinInverted),
282 0x16 => Ok(Self::HighArchLarge),
283 0x12 => Ok(Self::Hairy),
284 0x10 => Ok(Self::Dotted),
285 0x17 => Ok(Self::None),
286 _ => Err(()),
287 }
288 }
289}
290
291impl From<EyebrowType> for u8 {
293 fn from(value: EyebrowType) -> Self {
294 match value {
295 EyebrowType::FlatAngledLarge => 0x06,
296 EyebrowType::LowArchRoundedThin => 0x00,
297 EyebrowType::SoftAngledLarge => 0x0C,
298 EyebrowType::MediumArchRoundedThin => 0x01,
299 EyebrowType::RoundedMedium => 0x09,
300 EyebrowType::LowArchMedium => 0x13,
301 EyebrowType::RoundedThin => 0x07,
302 EyebrowType::UpThin => 0x15,
303 EyebrowType::MediumArchRoundedMedium => 0x08,
304 EyebrowType::RoundedLarge => 0x11,
305 EyebrowType::UpLarge => 0x05,
306 EyebrowType::FlatAngledLargeInverted => 0x04,
307 EyebrowType::MediumArchFlat => 0x0B,
308 EyebrowType::AngledThin => 0x0A,
309 EyebrowType::HorizontalLarge => 0x02,
310 EyebrowType::HighArchFlat => 0x03,
311 EyebrowType::Flat => 0x0E,
312 EyebrowType::MediumArchLarge => 0x14,
313 EyebrowType::LowArchThin => 0x0F,
314 EyebrowType::RoundedThinInverted => 0x0D,
315 EyebrowType::HighArchLarge => 0x16,
316 EyebrowType::Hairy => 0x12,
317 EyebrowType::Dotted => 0x10,
318 EyebrowType::None => 0x17,
319 }
320 }
321}