1use core::fmt;
2use std::str::FromStr;
3
4use kcl_error::CompilationIssue;
5use kcl_error::SourceRange;
6use serde::Deserialize;
7use serde::Serialize;
8
9use crate::NumericType;
10use crate::UnitAngle;
11use crate::UnitLength;
12use crate::UnitType;
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, ts_rs::TS)]
15#[repr(u32)]
16pub enum NumericSuffix {
17 None,
18 Count,
19 Length,
20 Angle,
21 Mm,
22 Cm,
23 M,
24 Inch,
25 Ft,
26 Yd,
27 Deg,
28 Rad,
29 Unknown,
30}
31
32impl NumericSuffix {
33 #[allow(dead_code)]
34 pub fn is_none(self) -> bool {
35 self == Self::None
36 }
37
38 pub fn is_some(self) -> bool {
39 self != Self::None
40 }
41
42 pub fn digestable_id(&self) -> &[u8] {
43 match self {
44 NumericSuffix::None => &[],
45 NumericSuffix::Count => b"_",
46 NumericSuffix::Unknown => b"?",
47 NumericSuffix::Length => b"Length",
48 NumericSuffix::Angle => b"Angle",
49 NumericSuffix::Mm => b"mm",
50 NumericSuffix::Cm => b"cm",
51 NumericSuffix::M => b"m",
52 NumericSuffix::Inch => b"in",
53 NumericSuffix::Ft => b"ft",
54 NumericSuffix::Yd => b"yd",
55 NumericSuffix::Deg => b"deg",
56 NumericSuffix::Rad => b"rad",
57 }
58 }
59}
60
61impl FromStr for NumericSuffix {
62 type Err = CompilationIssue;
63
64 fn from_str(s: &str) -> Result<Self, Self::Err> {
65 match s {
66 "_" | "Count" => Ok(NumericSuffix::Count),
67 "Length" => Ok(NumericSuffix::Length),
68 "Angle" => Ok(NumericSuffix::Angle),
69 "mm" | "millimeters" => Ok(NumericSuffix::Mm),
70 "cm" | "centimeters" => Ok(NumericSuffix::Cm),
71 "m" | "meters" => Ok(NumericSuffix::M),
72 "inch" | "in" => Ok(NumericSuffix::Inch),
73 "ft" | "feet" => Ok(NumericSuffix::Ft),
74 "yd" | "yards" => Ok(NumericSuffix::Yd),
75 "deg" | "degrees" => Ok(NumericSuffix::Deg),
76 "rad" | "radians" => Ok(NumericSuffix::Rad),
77 "?" => Ok(NumericSuffix::Unknown),
78 _ => Err(CompilationIssue::err(SourceRange::default(), "invalid unit of measure")),
79 }
80 }
81}
82
83impl fmt::Display for NumericSuffix {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 match self {
86 NumericSuffix::None => Ok(()),
87 NumericSuffix::Count => write!(f, "_"),
88 NumericSuffix::Unknown => write!(f, "_?"),
89 NumericSuffix::Length => write!(f, "Length"),
90 NumericSuffix::Angle => write!(f, "Angle"),
91 NumericSuffix::Mm => write!(f, "mm"),
92 NumericSuffix::Cm => write!(f, "cm"),
93 NumericSuffix::M => write!(f, "m"),
94 NumericSuffix::Inch => write!(f, "in"),
95 NumericSuffix::Ft => write!(f, "ft"),
96 NumericSuffix::Yd => write!(f, "yd"),
97 NumericSuffix::Deg => write!(f, "deg"),
98 NumericSuffix::Rad => write!(f, "rad"),
99 }
100 }
101}
102
103impl From<UnitLength> for NumericSuffix {
104 fn from(value: UnitLength) -> Self {
105 match value {
106 UnitLength::Millimeters => NumericSuffix::Mm,
107 UnitLength::Centimeters => NumericSuffix::Cm,
108 UnitLength::Meters => NumericSuffix::M,
109 UnitLength::Inches => NumericSuffix::Inch,
110 UnitLength::Feet => NumericSuffix::Ft,
111 UnitLength::Yards => NumericSuffix::Yd,
112 }
113 }
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, ts_rs::TS)]
117pub struct NumericSuffixTypeConvertError;
118
119impl TryFrom<NumericType> for NumericSuffix {
120 type Error = NumericSuffixTypeConvertError;
121
122 fn try_from(value: NumericType) -> Result<Self, Self::Error> {
123 match value {
124 NumericType::Known(UnitType::Count) => Ok(NumericSuffix::Count),
125 NumericType::Known(UnitType::Length(unit_length)) => Ok(NumericSuffix::from(unit_length)),
126 NumericType::Known(UnitType::GenericLength) => Ok(NumericSuffix::Length),
127 NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => Ok(NumericSuffix::Deg),
128 NumericType::Known(UnitType::Angle(UnitAngle::Radians)) => Ok(NumericSuffix::Rad),
129 NumericType::Known(UnitType::GenericAngle) => Ok(NumericSuffix::Angle),
130 NumericType::Default { .. } => Ok(NumericSuffix::None),
131 NumericType::Unknown => Ok(NumericSuffix::Unknown),
132 NumericType::Any => Err(NumericSuffixTypeConvertError),
133 }
134 }
135}