1use std::convert::Infallible;
2
3use crate::byte_handler::{ByteHandlerError, FromByteHandler};
4
5#[derive(Clone, Copy)]
8pub struct Head {
9 shape: HeadShape,
11 skin_tone: SkinTone,
13 face_features: FaceFeatures,
15}
16
17#[derive(thiserror::Error, Debug)]
19pub enum HeadError {
20 #[error("Shape is invalid")]
22 ShapeInvalid,
23 #[error("SkinTone is invalid")]
25 SkinToneInvalid,
26 #[error("FaceFeatures is invalid")]
28 FaceFeaturesInvalid,
29 #[error("ByteHandler Error: {0}")]
31 ByteHandlerError(#[from] ByteHandlerError),
32 #[error("")]
34 Infallible(#[from] Infallible),
35}
36
37impl Head {
38 pub fn new(shape: HeadShape, skin_tone: SkinTone, face_features: FaceFeatures) -> Self {
46 Self {
47 shape,
48 skin_tone,
49 face_features,
50 }
51 }
52
53 pub fn shape(&self) -> HeadShape {
55 self.shape
56 }
57
58 pub fn skin_tone(&self) -> SkinTone {
60 self.skin_tone
61 }
62
63 pub fn face_features(&self) -> FaceFeatures {
65 self.face_features
66 }
67
68 pub fn set_shape(&mut self, shape: HeadShape) {
70 self.shape = shape;
71 }
72
73 pub fn set_skin_tone(&mut self, skin_tone: SkinTone) {
75 self.skin_tone = skin_tone;
76 }
77
78 pub fn set_face_features(&mut self, face_features: FaceFeatures) {
80 self.face_features = face_features;
81 }
82}
83
84impl FromByteHandler for Head {
90 type Err = HeadError;
91 fn from_byte_handler<T>(handler: T) -> Result<Self, Self::Err>
92 where
93 T: TryInto<crate::byte_handler::ByteHandler>,
94 Self::Err: From<T::Error>,
95 {
96 let mut handler = handler.try_into()?;
97 handler.shift_right(5);
98 let shape_value = handler.copy_byte(0);
99 handler.shift_right(1);
100 let byte = handler.copy_byte(1);
101
102 Ok(Head {
103 shape: HeadShape::try_from(shape_value).map_err(|_| HeadError::ShapeInvalid)?,
104 skin_tone: SkinTone::try_from((byte >> 4) & 0x07)
105 .map_err(|_| HeadError::SkinToneInvalid)?,
106 face_features: FaceFeatures::try_from(byte & 0x0F)
107 .map_err(|_| HeadError::FaceFeaturesInvalid)?,
108 })
109 }
110}
111
112#[derive(Clone, Copy, PartialEq, Debug)]
114pub enum HeadShape {
115 Sharp,
116 Rounded,
117 SharpRoundedSmall,
118 Large,
119 SharpSmall,
120 Flat,
121 Angular,
122 FlatRounded,
123}
124
125impl TryFrom<u8> for HeadShape {
129 type Error = ();
130 fn try_from(value: u8) -> Result<Self, Self::Error> {
131 match value {
132 0x00 => Ok(Self::Sharp),
133 0x01 => Ok(Self::Rounded),
134 0x02 => Ok(Self::SharpRoundedSmall),
135 0x03 => Ok(Self::Large),
136 0x04 => Ok(Self::SharpSmall),
137 0x05 => Ok(Self::Flat),
138 0x06 => Ok(Self::Angular),
139 0x07 => Ok(Self::FlatRounded),
140 _ => Err(()),
141 }
142 }
143}
144
145impl From<HeadShape> for u8 {
147 fn from(value: HeadShape) -> Self {
148 match value {
149 HeadShape::Sharp => 0x00,
150 HeadShape::Rounded => 0x01,
151 HeadShape::SharpRoundedSmall => 0x02,
152 HeadShape::Large => 0x03,
153 HeadShape::SharpSmall => 0x04,
154 HeadShape::Flat => 0x05,
155 HeadShape::Angular => 0x06,
156 HeadShape::FlatRounded => 0x07,
157 }
158 }
159}
160
161#[derive(Clone, Copy, PartialEq, Debug)]
163pub enum SkinTone {
164 Beige,
165 Natural,
166 WarmIvory,
167 Ivory,
168 Honey,
169 Chestnut,
170}
171
172impl TryFrom<u8> for SkinTone {
176 type Error = ();
177 fn try_from(value: u8) -> Result<Self, Self::Error> {
178 match value {
179 0x00 => Ok(Self::Beige),
180 0x01 => Ok(Self::Natural),
181 0x02 => Ok(Self::WarmIvory),
182 0x03 => Ok(Self::Ivory),
183 0x04 => Ok(Self::Honey),
184 0x05 => Ok(Self::Chestnut),
185 _ => Err(()),
186 }
187 }
188}
189
190impl From<SkinTone> for u8 {
192 fn from(value: SkinTone) -> Self {
193 match value {
194 SkinTone::Beige => 0x00,
195 SkinTone::Natural => 0x01,
196 SkinTone::WarmIvory => 0x02,
197 SkinTone::Ivory => 0x03,
198 SkinTone::Honey => 0x04,
199 SkinTone::Chestnut => 0x05,
200 }
201 }
202}
203
204#[derive(Clone, Copy, PartialEq, Debug)]
208pub enum FaceFeatures {
209 None,
211 CheekPorcelain,
213 CheekPorcelainEyeShadowBlue,
215 Freckles,
216 UnderTheEyes,
218 FacialPain,
220 Cheeks,
222 Chin,
224 BrowDroop,
226 LionsManeBeard,
228 MouthFrown,
230 FoldsCrowsFrown,
232}
233
234impl TryFrom<u8> for FaceFeatures {
238 type Error = ();
239 fn try_from(value: u8) -> Result<Self, Self::Error> {
240 match value {
241 0x00 => Ok(Self::None),
242 0x01 => Ok(Self::CheekPorcelain),
243 0x02 => Ok(Self::CheekPorcelainEyeShadowBlue),
244 0x03 => Ok(Self::Freckles),
245 0x04 => Ok(Self::UnderTheEyes),
246 0x05 => Ok(Self::FacialPain),
247 0x06 => Ok(Self::Cheeks),
248 0x07 => Ok(Self::Chin),
249 0x08 => Ok(Self::BrowDroop),
250 0x09 => Ok(Self::LionsManeBeard),
251 0x0A => Ok(Self::MouthFrown),
252 0x0B => Ok(Self::FoldsCrowsFrown),
253 _ => Err(()),
254 }
255 }
256}
257
258impl From<FaceFeatures> for u8 {
260 fn from(value: FaceFeatures) -> Self {
261 match value {
262 FaceFeatures::None => 0x00,
263 FaceFeatures::CheekPorcelain => 0x01,
264 FaceFeatures::CheekPorcelainEyeShadowBlue => 0x02,
265 FaceFeatures::Freckles => 0x03,
266 FaceFeatures::UnderTheEyes => 0x04,
267 FaceFeatures::FacialPain => 0x05,
268 FaceFeatures::Cheeks => 0x06,
269 FaceFeatures::Chin => 0x07,
270 FaceFeatures::BrowDroop => 0x08,
271 FaceFeatures::LionsManeBeard => 0x09,
272 FaceFeatures::MouthFrown => 0x0A,
273 FaceFeatures::FoldsCrowsFrown => 0x0B,
274 }
275 }
276}