1#[cfg(feature = "chumsky")]
4use chumsky::{
5 prelude::{choice, just, Simple},
6 Parser,
7};
8
9#[derive(Debug, Clone, Hash, PartialEq, Eq, strum::FromRepr, strum::EnumIs)]
11pub enum AvatarAttachmentPoint {
12 Skull = 2,
14 Nose = 17,
16 Mouth = 11,
18 Tongue = 52,
20 Chin = 12,
22 Jaw = 47,
24 LeftEar = 13,
26 RightEar = 14,
28 AltLeftEar = 48,
30 AltRightEar = 49,
32 LeftEye = 15,
34 RightEye = 16,
36 AltLeftEye = 50,
38 AltRightEye = 51,
40 Neck = 39,
42 LeftShoulder = 3,
44 RightShoulder = 4,
46 LeftUpperArm = 20,
48 RightUpperArm = 18,
50 LeftLowerArm = 21,
52 RightLowerArm = 19,
54 LeftHand = 5,
56 RightHand = 6,
58 LeftRingFinger = 41,
60 RightRingFinger = 42,
62 LeftWing = 45,
64 RightWing = 46,
66 Chest = 1,
68 LeftPec = 29,
70 RightPec = 30,
72 Stomach = 28,
74 Spine = 9,
76 TailBase = 43,
78 TailTip = 44,
80 AvatarCenter = 40,
82 Pelvis = 10,
84 Groin = 53,
86 LeftHip = 25,
88 RightHip = 22,
90 LeftUpperLeg = 26,
92 RightUpperLeg = 23,
94 LeftLowerLeg = 24,
96 RightLowerLeg = 27,
98 LeftFoot = 7,
100 RightFoot = 8,
102 LeftHindFoot = 54,
104 RightHindFoot = 55,
106}
107
108impl AvatarAttachmentPoint {
109 #[must_use]
111 pub fn requires_bento(&self) -> bool {
112 matches!(
113 self,
114 AvatarAttachmentPoint::Tongue
115 | AvatarAttachmentPoint::AltLeftEar
116 | AvatarAttachmentPoint::AltRightEar
117 | AvatarAttachmentPoint::AltLeftEye
118 | AvatarAttachmentPoint::AltRightEye
119 | AvatarAttachmentPoint::LeftRingFinger
120 | AvatarAttachmentPoint::RightRingFinger
121 | AvatarAttachmentPoint::LeftWing
122 | AvatarAttachmentPoint::RightWing
123 | AvatarAttachmentPoint::TailBase
124 | AvatarAttachmentPoint::TailTip
125 | AvatarAttachmentPoint::Groin
126 | AvatarAttachmentPoint::LeftHindFoot
127 | AvatarAttachmentPoint::RightHindFoot
128 )
129 }
130}
131
132impl std::fmt::Display for AvatarAttachmentPoint {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 match self {
135 AvatarAttachmentPoint::Skull => write!(f, "Skull"),
136 AvatarAttachmentPoint::Nose => write!(f, "Nose"),
137 AvatarAttachmentPoint::Mouth => write!(f, "Mouth"),
138 AvatarAttachmentPoint::Tongue => write!(f, "Tongue"),
139 AvatarAttachmentPoint::Chin => write!(f, "Chin"),
140 AvatarAttachmentPoint::Jaw => write!(f, "Jaw"),
141 AvatarAttachmentPoint::LeftEar => write!(f, "Left Ear"),
142 AvatarAttachmentPoint::RightEar => write!(f, "Right Ear"),
143 AvatarAttachmentPoint::AltLeftEar => write!(f, "Alt Left Ear"),
144 AvatarAttachmentPoint::AltRightEar => write!(f, "Alt Right Ear"),
145 AvatarAttachmentPoint::LeftEye => write!(f, "Left Eye"),
146 AvatarAttachmentPoint::RightEye => write!(f, "Right Eye"),
147 AvatarAttachmentPoint::AltLeftEye => write!(f, "Alt Left Eye"),
148 AvatarAttachmentPoint::AltRightEye => write!(f, "Alt Right Eye"),
149 AvatarAttachmentPoint::Neck => write!(f, "Neck"),
150 AvatarAttachmentPoint::LeftShoulder => write!(f, "Left Shoulder"),
151 AvatarAttachmentPoint::RightShoulder => write!(f, "Right Shoulder"),
152 AvatarAttachmentPoint::LeftUpperArm => write!(f, "L Upper Arm"),
153 AvatarAttachmentPoint::RightUpperArm => write!(f, "R Upper Arm"),
154 AvatarAttachmentPoint::LeftLowerArm => write!(f, "L Lower Arm"),
155 AvatarAttachmentPoint::RightLowerArm => write!(f, "R Lower Arm"),
156 AvatarAttachmentPoint::LeftHand => write!(f, "Left Hand"),
157 AvatarAttachmentPoint::RightHand => write!(f, "Right Hand"),
158 AvatarAttachmentPoint::LeftRingFinger => write!(f, "Left Ring Finger"),
159 AvatarAttachmentPoint::RightRingFinger => write!(f, "Right Ring Finger"),
160 AvatarAttachmentPoint::LeftWing => write!(f, "Left Wing"),
161 AvatarAttachmentPoint::RightWing => write!(f, "Right Wing"),
162 AvatarAttachmentPoint::Chest => write!(f, "Chest"),
163 AvatarAttachmentPoint::LeftPec => write!(f, "Left Pec"),
164 AvatarAttachmentPoint::RightPec => write!(f, "Right Pec"),
165 AvatarAttachmentPoint::Stomach => write!(f, "Stomach"),
166 AvatarAttachmentPoint::Spine => write!(f, "Spine"),
167 AvatarAttachmentPoint::TailBase => write!(f, "Tail Base"),
168 AvatarAttachmentPoint::TailTip => write!(f, "Tail Tip"),
169 AvatarAttachmentPoint::AvatarCenter => write!(f, "Avatar Center"),
170 AvatarAttachmentPoint::Pelvis => write!(f, "Pelvis"),
171 AvatarAttachmentPoint::Groin => write!(f, "Groin"),
172 AvatarAttachmentPoint::LeftHip => write!(f, "Left Hip"),
173 AvatarAttachmentPoint::RightHip => write!(f, "Right Hip"),
174 AvatarAttachmentPoint::LeftUpperLeg => write!(f, "L Upper Leg"),
175 AvatarAttachmentPoint::RightUpperLeg => write!(f, "R Upper Leg"),
176 AvatarAttachmentPoint::LeftLowerLeg => write!(f, "L Lower Leg"),
177 AvatarAttachmentPoint::RightLowerLeg => write!(f, "R Lower Leg"),
178 AvatarAttachmentPoint::LeftFoot => write!(f, "Left Foot"),
179 AvatarAttachmentPoint::RightFoot => write!(f, "Right Foot"),
180 AvatarAttachmentPoint::LeftHindFoot => write!(f, "Left Hind Foot"),
181 AvatarAttachmentPoint::RightHindFoot => write!(f, "Right Hind Foot"),
182 }
183 }
184}
185
186#[derive(Debug, Clone)]
188pub struct AvatarAttachmentPointParseError {
189 value: String,
191}
192
193impl std::fmt::Display for AvatarAttachmentPointParseError {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 write!(
196 f,
197 "Could not parse as AvatarAttachmentPoint: {}",
198 self.value
199 )
200 }
201}
202
203impl std::str::FromStr for AvatarAttachmentPoint {
204 type Err = AvatarAttachmentPointParseError;
205
206 fn from_str(s: &str) -> Result<Self, Self::Err> {
207 match s {
208 "ATTACH_HEAD" | "Skull" | "head" => Ok(AvatarAttachmentPoint::Skull),
209 "ATTACH_NOSE" | "Nose" | "nose" => Ok(AvatarAttachmentPoint::Nose),
210 "ATTACH_MOUTH" | "Mouth" | "mouth" => Ok(AvatarAttachmentPoint::Mouth),
211 "ATTACH_FACE_TONGUE" | "Tongue" | "tongue" => Ok(AvatarAttachmentPoint::Tongue),
212 "ATTACH_CHIN" | "Chin" | "chin" => Ok(AvatarAttachmentPoint::Chin),
213 "ATTACH_FACE_JAW" | "Jaw" | "jaw" => Ok(AvatarAttachmentPoint::Jaw),
214 "ATTACH_LEAR" | "Left Ear" | "left ear" => Ok(AvatarAttachmentPoint::LeftEar),
215 "ATTACH_REAR" | "Right Ear" | "right ear" => Ok(AvatarAttachmentPoint::RightEar),
216 "ATTACH_FACE_LEAR" | "Alt Left Ear" | "left ear (extended)" => {
217 Ok(AvatarAttachmentPoint::AltLeftEar)
218 }
219 "ATTACH_FACE_REAR" | "Alt Right Ear" | "right ear (extended)" => {
220 Ok(AvatarAttachmentPoint::AltRightEar)
221 }
222 "ATTACH_LEYE" | "Left Eye" | "left eye" => Ok(AvatarAttachmentPoint::LeftEye),
223 "ATTACH_REYE" | "Right Eye" | "right eye" => Ok(AvatarAttachmentPoint::RightEye),
224 "ATTACH_FACE_LEYE" | "Alt Left Eye" | "left eye (extended)" => {
225 Ok(AvatarAttachmentPoint::AltLeftEye)
226 }
227 "ATTACH_FACE_REYE" | "Alt Right Eye" | "right eye (extended)" => {
228 Ok(AvatarAttachmentPoint::AltRightEye)
229 }
230 "ATTACH_NECK" | "Neck" | "neck" => Ok(AvatarAttachmentPoint::Neck),
231 "ATTACH_LSHOULDER" | "Left Shoulder" | "left shoulder" => {
232 Ok(AvatarAttachmentPoint::LeftShoulder)
233 }
234 "ATTACH_RSHOULDER" | "Right Shoulder" | "right shoulder" => {
235 Ok(AvatarAttachmentPoint::RightShoulder)
236 }
237 "ATTACH_LUARM" | "L Upper Arm" | "left upper arm" => {
238 Ok(AvatarAttachmentPoint::LeftUpperArm)
239 }
240 "ATTACH_RUARM" | "R Upper Arm" | "right upper arm" => {
241 Ok(AvatarAttachmentPoint::RightUpperArm)
242 }
243 "ATTACH_LLARM" | "L Lower Arm" | "left lower arm" => {
244 Ok(AvatarAttachmentPoint::LeftLowerArm)
245 }
246 "ATTACH_RLARM" | "R Lower Arm" | "right lower arm" => {
247 Ok(AvatarAttachmentPoint::RightLowerArm)
248 }
249 "ATTACH_LHAND" | "Left Hand" | "left hand" => Ok(AvatarAttachmentPoint::LeftHand),
250 "ATTACH_RHAND" | "Right Hand" | "right hand" => Ok(AvatarAttachmentPoint::RightHand),
251 "ATTACH_LHAND_RING1" | "Left Ring Finger" | "left ring finger" => {
252 Ok(AvatarAttachmentPoint::LeftRingFinger)
253 }
254 "ATTACH_RHAND_RING1" | "Right Ring Finger" | "right ring finger" => {
255 Ok(AvatarAttachmentPoint::RightRingFinger)
256 }
257 "ATTACH_LWING" | "Left Wing" | "left wing" => Ok(AvatarAttachmentPoint::LeftWing),
258 "ATTACH_RWING" | "Right Wing" | "right wing" => Ok(AvatarAttachmentPoint::RightWing),
259 "ATTACH_CHEST" | "Chest" | "chest/sternum" | "chest" | "sternum" => {
260 Ok(AvatarAttachmentPoint::Chest)
261 }
262 "ATTACH_LEFT_PEC" | "Left Pec" | "left pectoral" => Ok(AvatarAttachmentPoint::LeftPec),
263 "ATTACH_RIGHT_PEC" | "Right Pec" | "right pectoral" => {
264 Ok(AvatarAttachmentPoint::RightPec)
265 }
266 "ATTACH_BELLY" | "Stomach" | "belly/stomach/tummy" | "belly" | "stomach" | "tummy" => {
267 Ok(AvatarAttachmentPoint::Stomach)
268 }
269 "ATTACH_BACK" | "Spine" | "back" => Ok(AvatarAttachmentPoint::Spine),
270 "ATTACH_TAIL_BASE" | "Tail Base" | "tail base" => Ok(AvatarAttachmentPoint::TailBase),
271 "ATTACH_TAIL_TIP" | "Tail Tip" | "tail tip" => Ok(AvatarAttachmentPoint::TailTip),
272 "ATTACH_AVATAR_CENTER"
273 | "Avatar Center"
274 | "avatar center/root"
275 | "avatar center"
276 | "root" => Ok(AvatarAttachmentPoint::AvatarCenter),
277 "ATTACH_PELVIS" | "Pelvis" | "pelvis" => Ok(AvatarAttachmentPoint::Pelvis),
278 "ATTACH_GROIN" | "Groin" | "groin" => Ok(AvatarAttachmentPoint::Groin),
279 "ATTACH_LHIP" | "Left Hip" | "left hip" => Ok(AvatarAttachmentPoint::LeftHip),
280 "ATTACH_RHIP" | "Right Hip" | "right hip" => Ok(AvatarAttachmentPoint::RightHip),
281 "ATTACH_LULEG" | "L Upper Leg" | "left upper leg" => {
282 Ok(AvatarAttachmentPoint::LeftUpperLeg)
283 }
284 "ATTACH_RULEG" | "R Upper Leg" | "right upper leg" => {
285 Ok(AvatarAttachmentPoint::RightUpperLeg)
286 }
287 "ATTACH_RLLEG" | "R Lower Leg" | "right lower leg" => {
288 Ok(AvatarAttachmentPoint::LeftLowerLeg)
289 }
290 "ATTACH_LLLEG" | "L Lower Leg" | "left lower leg" => {
291 Ok(AvatarAttachmentPoint::RightLowerLeg)
292 }
293 "ATTACH_LFOOT" | "Left Foot" | "left foot" => Ok(AvatarAttachmentPoint::LeftFoot),
294 "ATTACH_RFOOT" | "Right Foot" | "right foot" => Ok(AvatarAttachmentPoint::RightFoot),
295 "ATTACH_HIND_LFOOT" | "Left Hind Foot" | "left hind foot" => {
296 Ok(AvatarAttachmentPoint::LeftHindFoot)
297 }
298 "ATTACH_HIND_RFOOT" | "Right Hind Foot" | "right hind foot" => {
299 Ok(AvatarAttachmentPoint::RightHindFoot)
300 }
301 _ => Err(AvatarAttachmentPointParseError {
302 value: s.to_string(),
303 }),
304 }
305 }
306}
307
308#[cfg(feature = "chumsky")]
314#[must_use]
315pub fn avatar_attachment_point_parser(
316) -> impl Parser<char, AvatarAttachmentPoint, Error = Simple<char>> {
317 choice([
318 just("ATTACH_HEAD")
319 .or(just("Skull"))
320 .or(just("head"))
321 .to(AvatarAttachmentPoint::Skull)
322 .boxed(),
323 just("ATTACH_NOSE")
324 .or(just("Nose"))
325 .or(just("nose"))
326 .to(AvatarAttachmentPoint::Nose)
327 .boxed(),
328 just("ATTACH_MOUTH")
329 .or(just("Mouth"))
330 .or(just("mouth"))
331 .to(AvatarAttachmentPoint::Mouth)
332 .boxed(),
333 just("ATTACH_FACE_TONGUE")
334 .or(just("Tongue"))
335 .or(just("tongue"))
336 .to(AvatarAttachmentPoint::Tongue)
337 .boxed(),
338 just("ATTACH_CHIN")
339 .or(just("Chin"))
340 .or(just("chin"))
341 .to(AvatarAttachmentPoint::Chin)
342 .boxed(),
343 just("ATTACH_FACE_JAW")
344 .or(just("Jaw"))
345 .or(just("jaw"))
346 .to(AvatarAttachmentPoint::Jaw)
347 .boxed(),
348 just("ATTACH_LEAR")
349 .or(just("Left Ear"))
350 .or(just("left ear"))
351 .to(AvatarAttachmentPoint::LeftEar)
352 .boxed(),
353 just("ATTACH_REAR")
354 .or(just("Right Ear"))
355 .or(just("right ear"))
356 .to(AvatarAttachmentPoint::RightEar)
357 .boxed(),
358 just("ATTACH_FACE_LEAR")
359 .or(just("Alt Left Ear"))
360 .or(just("left ear (extended)"))
361 .to(AvatarAttachmentPoint::AltLeftEar)
362 .boxed(),
363 just("ATTACH_FACE_REAR")
364 .or(just("Alt Right Ear"))
365 .or(just("right ear (extended)"))
366 .to(AvatarAttachmentPoint::AltRightEar)
367 .boxed(),
368 just("ATTACH_LEYE")
369 .or(just("Left Eye"))
370 .or(just("left eye"))
371 .to(AvatarAttachmentPoint::LeftEye)
372 .boxed(),
373 just("ATTACH_REYE")
374 .or(just("Right Eye"))
375 .or(just("right eye"))
376 .to(AvatarAttachmentPoint::RightEye)
377 .boxed(),
378 just("ATTACH_FACE_LEYE")
379 .or(just("Alt Left Eye"))
380 .or(just("left eye (extended)"))
381 .to(AvatarAttachmentPoint::AltLeftEye)
382 .boxed(),
383 just("ATTACH_FACE_REYE")
384 .or(just("Alt Right Eye"))
385 .or(just("right eye (extended)"))
386 .to(AvatarAttachmentPoint::AltRightEye)
387 .boxed(),
388 just("ATTACH_NECK")
389 .or(just("Neck"))
390 .or(just("neck"))
391 .to(AvatarAttachmentPoint::Neck)
392 .boxed(),
393 just("ATTACH_LSHOULDER")
394 .or(just("Left Shoulder"))
395 .or(just("left shoulder"))
396 .to(AvatarAttachmentPoint::LeftShoulder)
397 .boxed(),
398 just("ATTACH_RSHOULDER")
399 .or(just("Right Shoulder"))
400 .or(just("right shoulder"))
401 .to(AvatarAttachmentPoint::RightShoulder)
402 .boxed(),
403 just("ATTACH_LUARM")
404 .or(just("L Upper Arm"))
405 .or(just("left upper arm"))
406 .to(AvatarAttachmentPoint::LeftUpperArm)
407 .boxed(),
408 just("ATTACH_RUARM")
409 .or(just("R Upper Arm"))
410 .or(just("right upper arm"))
411 .to(AvatarAttachmentPoint::RightUpperArm)
412 .boxed(),
413 just("ATTACH_LLARM")
414 .or(just("L Lower Arm"))
415 .or(just("left lower arm"))
416 .to(AvatarAttachmentPoint::LeftLowerArm)
417 .boxed(),
418 just("ATTACH_RLARM")
419 .or(just("R Lower Arm"))
420 .or(just("right lower arm"))
421 .to(AvatarAttachmentPoint::RightLowerArm)
422 .boxed(),
423 just("ATTACH_LHAND")
424 .or(just("Left Hand"))
425 .or(just("left hand"))
426 .to(AvatarAttachmentPoint::LeftHand)
427 .boxed(),
428 just("ATTACH_RHAND")
429 .or(just("Right Hand"))
430 .or(just("right hand"))
431 .to(AvatarAttachmentPoint::RightHand)
432 .boxed(),
433 just("ATTACH_LHAND_RING1")
434 .or(just("Left Ring Finger"))
435 .or(just("left ring finger"))
436 .to(AvatarAttachmentPoint::LeftRingFinger)
437 .boxed(),
438 just("ATTACH_RHAND_RING1")
439 .or(just("Right Ring Finger"))
440 .or(just("right ring finger"))
441 .to(AvatarAttachmentPoint::RightRingFinger)
442 .boxed(),
443 just("ATTACH_LWING")
444 .or(just("Left Wing"))
445 .or(just("left wing"))
446 .to(AvatarAttachmentPoint::LeftWing)
447 .boxed(),
448 just("ATTACH_RWING")
449 .or(just("Right Wing"))
450 .or(just("right wing"))
451 .to(AvatarAttachmentPoint::RightWing)
452 .boxed(),
453 just("ATTACH_CHEST")
454 .or(just("Chest"))
455 .or(just("chest/sternum"))
456 .or(just("chest"))
457 .or(just("sternum"))
458 .to(AvatarAttachmentPoint::Chest)
459 .boxed(),
460 just("ATTACH_LEFT_PEC")
461 .or(just("Left Pec"))
462 .or(just("left pectoral"))
463 .to(AvatarAttachmentPoint::LeftPec)
464 .boxed(),
465 just("ATTACH_RIGHT_PEC")
466 .or(just("Right Pec"))
467 .or(just("right pectoral"))
468 .to(AvatarAttachmentPoint::RightPec)
469 .boxed(),
470 just("ATTACH_BELLY")
471 .or(just("Stomach"))
472 .or(just("belly/stomach/tummy"))
473 .or(just("belly"))
474 .or(just("stomach"))
475 .or(just("tummy"))
476 .to(AvatarAttachmentPoint::Stomach)
477 .boxed(),
478 just("ATTACH_BACK")
479 .or(just("Spine"))
480 .or(just("back"))
481 .to(AvatarAttachmentPoint::Spine)
482 .boxed(),
483 just("ATTACH_TAIL_BASE")
484 .or(just("Tail Base"))
485 .or(just("tail base"))
486 .to(AvatarAttachmentPoint::TailBase)
487 .boxed(),
488 just("ATTACH_TAIL_TIP")
489 .or(just("Tail Tip"))
490 .or(just("tail tip"))
491 .to(AvatarAttachmentPoint::TailTip)
492 .boxed(),
493 just("ATTACH_AVATAR_CENTER")
494 .or(just("Avatar Center"))
495 .or(just("avatar center/root"))
496 .or(just("avatar center"))
497 .or(just("root"))
498 .to(AvatarAttachmentPoint::AvatarCenter)
499 .boxed(),
500 just("ATTACH_PELVIS")
501 .or(just("Pelvis"))
502 .or(just("pelvis"))
503 .to(AvatarAttachmentPoint::Pelvis)
504 .boxed(),
505 just("ATTACH_GROIN")
506 .or(just("Groin"))
507 .or(just("groin"))
508 .to(AvatarAttachmentPoint::Groin)
509 .boxed(),
510 just("ATTACH_LHIP")
511 .or(just("Left Hip"))
512 .or(just("left hip"))
513 .to(AvatarAttachmentPoint::LeftHip)
514 .boxed(),
515 just("ATTACH_RHIP")
516 .or(just("Right Hip"))
517 .or(just("right hip"))
518 .to(AvatarAttachmentPoint::RightHip)
519 .boxed(),
520 just("ATTACH_LULEG")
521 .or(just("L Upper Leg"))
522 .or(just("left upper leg"))
523 .to(AvatarAttachmentPoint::LeftUpperLeg)
524 .boxed(),
525 just("ATTACH_RULEG")
526 .or(just("R Upper Leg"))
527 .or(just("right upper leg"))
528 .to(AvatarAttachmentPoint::RightUpperLeg)
529 .boxed(),
530 just("ATTACH_RLLEG")
531 .or(just("R Lower Leg"))
532 .or(just("right lower leg"))
533 .to(AvatarAttachmentPoint::LeftLowerLeg)
534 .boxed(),
535 just("ATTACH_LLLEG")
536 .or(just("L Lower Leg"))
537 .or(just("left lower leg"))
538 .to(AvatarAttachmentPoint::RightLowerLeg)
539 .boxed(),
540 just("ATTACH_LFOOT")
541 .or(just("Left Foot"))
542 .or(just("left foot"))
543 .to(AvatarAttachmentPoint::LeftFoot)
544 .boxed(),
545 just("ATTACH_RFOOT")
546 .or(just("Right Foot"))
547 .or(just("right foot"))
548 .to(AvatarAttachmentPoint::RightFoot)
549 .boxed(),
550 just("ATTACH_HIND_LFOOT")
551 .or(just("Left Hind Foot"))
552 .or(just("left hind foot"))
553 .to(AvatarAttachmentPoint::LeftHindFoot)
554 .boxed(),
555 just("ATTACH_HIND_RFOOT")
556 .or(just("Right Hind Foot"))
557 .or(just("right hind foot"))
558 .to(AvatarAttachmentPoint::RightHindFoot)
559 .boxed(),
560 ])
561}
562
563#[derive(Debug, Clone, Hash, PartialEq, Eq, strum::FromRepr, strum::EnumIs)]
565pub enum HudAttachmentPoint {
566 Center2 = 31,
568 TopRight = 32,
570 Top = 33,
572 TopLeft = 34,
574 Center = 35,
576 BottomLeft = 36,
578 Bottom = 37,
580 BottomRight = 38,
582}
583
584impl std::fmt::Display for HudAttachmentPoint {
585 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
586 match self {
587 HudAttachmentPoint::Center2 => write!(f, "HUD Center 2"),
588 HudAttachmentPoint::TopRight => write!(f, "HUD Top Right"),
589 HudAttachmentPoint::Top => write!(f, "HUD Top"),
590 HudAttachmentPoint::TopLeft => write!(f, "HUD Top Left"),
591 HudAttachmentPoint::Center => write!(f, "HUD Center"),
592 HudAttachmentPoint::BottomLeft => write!(f, "HUD Bottom Left"),
593 HudAttachmentPoint::Bottom => write!(f, "HUD Bottom"),
594 HudAttachmentPoint::BottomRight => write!(f, "HUD Bottom Right"),
595 }
596 }
597}
598
599#[derive(Debug, Clone)]
601pub struct HudAttachmentPointParseError {
602 value: String,
604}
605
606impl std::fmt::Display for HudAttachmentPointParseError {
607 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
608 write!(f, "Could not parse as HudAttachmentPoint: {}", self.value)
609 }
610}
611
612impl std::str::FromStr for HudAttachmentPoint {
613 type Err = HudAttachmentPointParseError;
614
615 fn from_str(s: &str) -> Result<Self, Self::Err> {
616 match s {
617 "ATTACH_HUD_CENTER_2" | "HUD Center 2" | "Center 2" => Ok(HudAttachmentPoint::Center2),
618 "ATTACH_HUD_TOP_RIGHT" | "HUD Top Right" | "Top Right" => {
619 Ok(HudAttachmentPoint::TopRight)
620 }
621 "ATTACH_HUD_TOP_CENTER" | "HUD Top" | "Top" => Ok(HudAttachmentPoint::Top),
622 "ATTACH_HUD_TOP_LEFT" | "HUD Top Left" | "Top Left" => Ok(HudAttachmentPoint::TopLeft),
623 "ATTACH_HUD_CENTER_1" | "HUD Center" | "Center" => Ok(HudAttachmentPoint::Center),
624 "ATTACH_HUD_BOTTOM_LEFT" | "HUD Bottom Left" | "Bottom Left" => {
625 Ok(HudAttachmentPoint::BottomLeft)
626 }
627 "ATTACH_HUD_BOTTOM" | "HUD Bottom" | "Bottom" => Ok(HudAttachmentPoint::Bottom),
628 "ATTACH_HUD_BOTTOM_RIGHT" | "HUD Bottom Right " | "Bottom Right" => {
629 Ok(HudAttachmentPoint::BottomRight)
630 }
631 _ => Err(HudAttachmentPointParseError {
632 value: s.to_string(),
633 }),
634 }
635 }
636}
637
638#[cfg(feature = "chumsky")]
644#[must_use]
645pub fn hud_attachment_point_parser() -> impl Parser<char, HudAttachmentPoint, Error = Simple<char>>
646{
647 choice([
648 just("ATTACH_HUD_CENTER_2")
649 .or(just("HUD Center 2"))
650 .or(just("Center 2"))
651 .to(HudAttachmentPoint::Center2),
652 just("ATTACH_HUD_TOP_RIGHT")
653 .or(just("HUD Top Right"))
654 .or(just("Top Right"))
655 .to(HudAttachmentPoint::TopRight),
656 just("ATTACH_HUD_TOP_LEFT")
657 .or(just("HUD Top Left"))
658 .or(just("Top Left"))
659 .to(HudAttachmentPoint::TopLeft),
660 just("ATTACH_HUD_TOP_CENTER")
661 .or(just("HUD Top"))
662 .or(just("Top"))
663 .to(HudAttachmentPoint::Top),
664 just("ATTACH_HUD_CENTER_1")
665 .or(just("HUD Center"))
666 .or(just("Center"))
667 .to(HudAttachmentPoint::Center),
668 just("ATTACH_HUD_BOTTOM_LEFT")
669 .or(just("HUD Bottom Left"))
670 .or(just("Bottom Left"))
671 .to(HudAttachmentPoint::BottomLeft),
672 just("ATTACH_HUD_BOTTOM_RIGHT")
673 .or(just("HUD Bottom Right "))
674 .or(just("Bottom Right"))
675 .to(HudAttachmentPoint::BottomRight),
676 just("ATTACH_HUD_BOTTOM")
677 .or(just("HUD Bottom"))
678 .or(just("Bottom"))
679 .to(HudAttachmentPoint::Bottom),
680 ])
681}
682
683#[derive(Debug, Clone, Hash, PartialEq, Eq)]
685pub enum AttachmentPoint {
686 Avatar(AvatarAttachmentPoint),
688 Hud(HudAttachmentPoint),
690}
691
692impl AttachmentPoint {
693 #[must_use]
699 pub fn from_repr(repr: usize) -> Option<AttachmentPoint> {
700 AvatarAttachmentPoint::from_repr(repr)
701 .map(Self::Avatar)
702 .or_else(|| HudAttachmentPoint::from_repr(repr).map(Self::Hud))
703 }
704}
705
706impl std::fmt::Display for AttachmentPoint {
707 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
708 match self {
709 AttachmentPoint::Avatar(avatar_attachment_point) => {
710 write!(f, "{}", avatar_attachment_point)
711 }
712 AttachmentPoint::Hud(hud_attachment_point) => write!(f, "{}", hud_attachment_point),
713 }
714 }
715}
716
717#[derive(Debug, Clone)]
719pub struct AttachmentPointParseError {
720 value: String,
722}
723
724impl std::fmt::Display for AttachmentPointParseError {
725 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
726 write!(f, "Could not parse as AttachmentPoint: {}", self.value)
727 }
728}
729
730impl std::str::FromStr for AttachmentPoint {
731 type Err = AttachmentPointParseError;
732
733 fn from_str(s: &str) -> Result<Self, Self::Err> {
734 if let Ok(avatar_attachment_point) =
735 <AvatarAttachmentPoint as std::str::FromStr>::from_str(s)
736 {
737 Ok(Self::Avatar(avatar_attachment_point))
738 } else if let Ok(hud_attachment_point) =
739 <HudAttachmentPoint as std::str::FromStr>::from_str(s)
740 {
741 Ok(Self::Hud(hud_attachment_point))
742 } else {
743 Err(AttachmentPointParseError {
744 value: s.to_string(),
745 })
746 }
747 }
748}
749
750#[cfg(feature = "chumsky")]
756#[must_use]
757pub fn attachment_point_parser() -> impl Parser<char, AttachmentPoint, Error = Simple<char>> {
758 avatar_attachment_point_parser()
759 .map(AttachmentPoint::Avatar)
760 .or(hud_attachment_point_parser().map(AttachmentPoint::Hud))
761}
762
763#[cfg(test)]
764mod test {
765 #[cfg(feature = "chumsky")]
766 use super::{attachment_point_parser, AttachmentPoint, HudAttachmentPoint};
767 #[cfg(feature = "chumsky")]
768 use chumsky::Parser as _;
769 #[cfg(feature = "chumsky")]
770 use pretty_assertions::assert_eq;
771
772 #[cfg(feature = "chumsky")]
773 #[test]
774 fn test_parse_attachment_point_bottom_left() {
775 assert_eq!(
776 attachment_point_parser().parse("Bottom Left"),
777 Ok(AttachmentPoint::Hud(HudAttachmentPoint::BottomLeft)),
778 )
779 }
780
781 #[cfg(feature = "chumsky")]
782 #[test]
783 fn test_parse_attachment_point_bottom() {
784 assert_eq!(
785 attachment_point_parser().parse("Bottom"),
786 Ok(AttachmentPoint::Hud(HudAttachmentPoint::Bottom)),
787 )
788 }
789
790 #[cfg(feature = "chumsky")]
791 #[test]
792 fn test_parse_attachment_point_bottom_right() {
793 assert_eq!(
794 attachment_point_parser().parse("Bottom Right"),
795 Ok(AttachmentPoint::Hud(HudAttachmentPoint::BottomRight)),
796 )
797 }
798}