Skip to main content

kcl_api/
units.rs

1use kittycad_unit_conversion_derive::UnitConversion;
2use parse_display_derive::Display;
3use parse_display_derive::FromStr;
4use schemars::JsonSchema;
5use serde::Deserialize;
6use serde::Serialize;
7use ts_rs::TS;
8
9/// The valid types of length units.
10#[derive(
11    Default,
12    Display,
13    FromStr,
14    Copy,
15    Eq,
16    PartialEq,
17    Debug,
18    JsonSchema,
19    Deserialize,
20    Serialize,
21    Clone,
22    Ord,
23    PartialOrd,
24    UnitConversion,
25    Hash,
26    TS,
27)]
28#[display(style = "snake_case")]
29#[ts(export_to = "ModelingCmd.ts")]
30#[cfg_attr(
31    feature = "pyo3",
32    pyo3::pyclass(eq, from_py_object),
33    pyo3_stub_gen::derive::gen_stub_pyclass_enum
34)]
35pub enum UnitLength {
36    /// Centimeters <https://en.wikipedia.org/wiki/Centimeter>
37    #[serde(rename = "cm")]
38    #[display("cm")]
39    Centimeters,
40    /// Feet <https://en.wikipedia.org/wiki/Foot_(unit)>
41    #[serde(rename = "ft")]
42    #[display("ft")]
43    Feet,
44    /// Inches <https://en.wikipedia.org/wiki/Inch>
45    #[serde(rename = "in")]
46    #[display("in")]
47    Inches,
48    /// Meters <https://en.wikipedia.org/wiki/Meter>
49    #[default]
50    #[serde(rename = "m")]
51    #[display("m")]
52    Meters,
53    /// Millimeters <https://en.wikipedia.org/wiki/Millimeter>
54    #[serde(rename = "mm")]
55    #[display("mm")]
56    Millimeters,
57    /// Yards <https://en.wikipedia.org/wiki/Yard>
58    #[serde(rename = "yd")]
59    #[display("yd")]
60    Yards,
61}
62
63impl UnitLength {
64    /// Convert to measurement.
65    pub fn as_measurement(self, value: f64) -> measurements::Length {
66        match self {
67            Self::Centimeters => measurements::Length::from_centimeters(value),
68            Self::Feet => measurements::Length::from_feet(value),
69            Self::Inches => measurements::Length::from_inches(value),
70            Self::Meters => measurements::Length::from_meters(value),
71            Self::Millimeters => measurements::Length::from_millimeters(value),
72            Self::Yards => measurements::Length::from_yards(value),
73        }
74    }
75}
76
77/// The valid types of angle formats.
78#[derive(
79    Default,
80    Display,
81    FromStr,
82    Copy,
83    Eq,
84    PartialEq,
85    Debug,
86    JsonSchema,
87    Deserialize,
88    Serialize,
89    Clone,
90    Ord,
91    PartialOrd,
92    UnitConversion,
93    Hash,
94    TS,
95)]
96#[serde(rename_all = "snake_case")]
97#[display(style = "snake_case")]
98#[ts(export_to = "ModelingCmd.ts")]
99#[cfg_attr(
100    feature = "pyo3",
101    pyo3::pyclass(eq, from_py_object),
102    pyo3_stub_gen::derive::gen_stub_pyclass_enum
103)]
104pub enum UnitAngle {
105    /// Degrees <https://en.wikipedia.org/wiki/Degree_(angle)>
106    #[default]
107    #[display("deg")]
108    Degrees,
109    /// Radians <https://en.wikipedia.org/wiki/Radian>
110    #[display("rad")]
111    Radians,
112}
113
114/// The valid types of area units.
115#[derive(
116    Display,
117    FromStr,
118    Copy,
119    Eq,
120    PartialEq,
121    Debug,
122    JsonSchema,
123    Deserialize,
124    Serialize,
125    Clone,
126    Ord,
127    PartialOrd,
128    UnitConversion,
129    Default,
130    Hash,
131    TS,
132)]
133#[serde(rename_all = "snake_case")]
134#[display(style = "snake_case")]
135#[ts(export_to = "ModelingCmd.ts")]
136#[cfg_attr(
137    feature = "pyo3",
138    pyo3::pyclass(eq, from_py_object),
139    pyo3_stub_gen::derive::gen_stub_pyclass_enum
140)]
141pub enum UnitArea {
142    /// Square centimeters <https://en.wikipedia.org/wiki/Square_centimeter>
143    #[serde(rename = "cm2")]
144    #[display("cm2")]
145    SquareCentimeters,
146    /// Square decimeters <https://en.wikipedia.org/wiki/Square_decimeter>
147    #[serde(rename = "dm2")]
148    #[display("dm2")]
149    SquareDecimeters,
150    /// Square feet <https://en.wikipedia.org/wiki/Square_foot>
151    #[serde(rename = "ft2")]
152    #[display("ft2")]
153    SquareFeet,
154    /// Square inches <https://en.wikipedia.org/wiki/Square_inch>
155    #[serde(rename = "in2")]
156    #[display("in2")]
157    SquareInches,
158    /// Square kilometers <https://en.wikipedia.org/wiki/Square_kilometer>
159    #[serde(rename = "km2")]
160    #[display("km2")]
161    SquareKilometers,
162    /// Square meters <https://en.wikipedia.org/wiki/Square_meter>
163    #[default]
164    #[serde(rename = "m2")]
165    #[display("m2")]
166    SquareMeters,
167    /// Square millimeters <https://en.wikipedia.org/wiki/Square_millimeter>
168    #[serde(rename = "mm2")]
169    #[display("mm2")]
170    SquareMillimeters,
171    /// Square yards <https://en.wikipedia.org/wiki/Square_mile>
172    #[serde(rename = "yd2")]
173    #[display("yd2")]
174    SquareYards,
175}
176
177impl UnitArea {
178    /// Convert to measurement.
179    pub fn as_measurement(self, value: f64) -> measurements::Area {
180        match self {
181            Self::SquareCentimeters => measurements::Area::from_square_centimeters(value),
182            Self::SquareDecimeters => measurements::Area::from_square_decimeters(value),
183            Self::SquareFeet => measurements::Area::from_square_feet(value),
184            Self::SquareInches => measurements::Area::from_square_inches(value),
185            Self::SquareKilometers => measurements::Area::from_square_kilometers(value),
186            Self::SquareMeters => measurements::Area::from_square_meters(value),
187            Self::SquareMillimeters => measurements::Area::from_square_millimeters(value),
188            Self::SquareYards => measurements::Area::from_square_yards(value),
189        }
190    }
191}
192
193/// The valid types for density units.
194#[derive(
195    Display,
196    Copy,
197    Eq,
198    PartialEq,
199    Debug,
200    JsonSchema,
201    Deserialize,
202    Serialize,
203    Clone,
204    Ord,
205    PartialOrd,
206    Default,
207    UnitConversion,
208    Hash,
209    TS,
210)]
211#[display(style = "snake_case")]
212#[ts(export_to = "ModelingCmd.ts")]
213#[cfg_attr(
214    feature = "pyo3",
215    pyo3::pyclass(eq, from_py_object),
216    pyo3_stub_gen::derive::gen_stub_pyclass_enum
217)]
218pub enum UnitDensity {
219    /// Pounds per cubic feet.
220    #[serde(rename = "lb:ft3")]
221    #[display("lb:ft3")]
222    PoundsPerCubicFeet,
223
224    /// Kilograms per cubic meter.
225    #[default]
226    #[serde(rename = "kg:m3")]
227    #[display("kg:m3")]
228    KilogramsPerCubicMeter,
229}
230
231impl std::str::FromStr for UnitDensity {
232    type Err = parse_display::ParseError;
233
234    fn from_str(s: &str) -> Result<Self, Self::Err> {
235        match s {
236            "lbft3" | "lb:ft3" | "lb-ft3" => Ok(Self::PoundsPerCubicFeet),
237            "kgm3" | "kg:m3" | "kg-m3" => Ok(Self::KilogramsPerCubicMeter),
238            _other => Err(Default::default()),
239        }
240    }
241}
242
243impl UnitDensity {
244    /// Convert to measurement.
245    pub fn as_measurement(self, value: f64) -> measurements::Density {
246        match self {
247            Self::PoundsPerCubicFeet => measurements::Density::from_pounds_per_cubic_feet(value),
248            Self::KilogramsPerCubicMeter => measurements::Density::from_kilograms_per_cubic_meter(value),
249        }
250    }
251}
252
253/// The valid types of mass units.
254#[derive(
255    Default,
256    Display,
257    FromStr,
258    Copy,
259    Eq,
260    PartialEq,
261    Debug,
262    JsonSchema,
263    Deserialize,
264    Serialize,
265    Clone,
266    Ord,
267    PartialOrd,
268    UnitConversion,
269    Hash,
270    TS,
271)]
272#[serde(rename_all = "snake_case")]
273#[display(style = "snake_case")]
274#[ts(export_to = "ModelingCmd.ts")]
275#[cfg_attr(
276    feature = "pyo3",
277    pyo3::pyclass(eq, from_py_object),
278    pyo3_stub_gen::derive::gen_stub_pyclass_enum
279)]
280pub enum UnitMass {
281    /// Grams <https://en.wikipedia.org/wiki/Gram>
282    #[default]
283    #[serde(rename = "g")]
284    #[display("g")]
285    Grams,
286    /// Kilograms <https://en.wikipedia.org/wiki/Kilogram>
287    #[serde(rename = "kg")]
288    #[display("kg")]
289    Kilograms,
290    /// Pounds <https://en.wikipedia.org/wiki/Pound_(mass)>
291    #[serde(rename = "lb")]
292    #[display("lb")]
293    Pounds,
294}
295
296impl UnitMass {
297    /// Convert to measurement.
298    pub fn as_measurement(self, value: f64) -> measurements::Mass {
299        match self {
300            Self::Grams => measurements::Mass::from_grams(value),
301            Self::Kilograms => measurements::Mass::from_kilograms(value),
302            Self::Pounds => measurements::Mass::from_pounds(value),
303        }
304    }
305}
306
307/// The valid types of volume units.
308#[derive(
309    Default,
310    Display,
311    FromStr,
312    Copy,
313    Eq,
314    PartialEq,
315    Debug,
316    JsonSchema,
317    Deserialize,
318    Serialize,
319    Clone,
320    Ord,
321    PartialOrd,
322    UnitConversion,
323    Hash,
324    TS,
325)]
326#[display(style = "snake_case")]
327#[ts(export_to = "ModelingCmd.ts")]
328#[cfg_attr(
329    feature = "pyo3",
330    pyo3::pyclass(eq, from_py_object),
331    pyo3_stub_gen::derive::gen_stub_pyclass_enum
332)]
333pub enum UnitVolume {
334    /// Cubic millimeters (mm³)
335    #[serde(rename = "mm3")]
336    #[display("mm3")]
337    CubicMillimeters,
338    /// Cubic centimeters (cc or cm³) <https://en.wikipedia.org/wiki/Cubic_centimeter>
339    #[serde(rename = "cm3")]
340    #[display("cm3")]
341    CubicCentimeters,
342    /// Cubic feet (ft³) <https://en.wikipedia.org/wiki/Cubic_foot>
343    #[serde(rename = "ft3")]
344    #[display("ft3")]
345    CubicFeet,
346    /// Cubic inches (cu in or in³) <https://en.wikipedia.org/wiki/Cubic_inch>
347    #[serde(rename = "in3")]
348    #[display("in3")]
349    CubicInches,
350    /// Cubic meters (m³) <https://en.wikipedia.org/wiki/Cubic_meter>
351    #[default]
352    #[serde(rename = "m3")]
353    #[display("m3")]
354    CubicMeters,
355    /// Cubic yards (yd³) <https://en.wikipedia.org/wiki/Cubic_yard>
356    #[serde(rename = "yd3")]
357    #[display("yd3")]
358    CubicYards,
359    /// US Fluid Ounces (fl oz) <https://en.wikipedia.org/wiki/Fluid_ounce>
360    #[serde(rename = "usfloz")]
361    #[display("usfloz")]
362    FluidOunces,
363    /// US Gallons (gal US) <https://en.wikipedia.org/wiki/Gallon>
364    #[serde(rename = "usgal")]
365    #[display("usgal")]
366    Gallons,
367    /// Liters (l) <https://en.wikipedia.org/wiki/Litre>
368    #[serde(rename = "l")]
369    #[display("l")]
370    Liters,
371    /// Milliliters (ml) <https://en.wikipedia.org/wiki/Litre>
372    #[serde(rename = "ml")]
373    #[display("ml")]
374    Milliliters,
375}
376
377impl UnitVolume {
378    /// Convert to measurement.
379    pub fn as_measurement(self, value: f64) -> measurements::Volume {
380        match self {
381            Self::CubicMillimeters => measurements::Volume::from_cubic_millimeters(value),
382            Self::CubicCentimeters => measurements::Volume::from_cubic_centimeters(value),
383            Self::CubicFeet => measurements::Volume::from_cubic_feet(value),
384            Self::CubicInches => measurements::Volume::from_cubic_inches(value),
385            Self::CubicMeters => measurements::Volume::from_cubic_meters(value),
386            Self::CubicYards => measurements::Volume::from_cubic_yards(value),
387            Self::FluidOunces => measurements::Volume::from_fluid_ounces(value),
388            Self::Gallons => measurements::Volume::from_gallons(value),
389            Self::Liters => measurements::Volume::from_liters(value),
390            Self::Milliliters => measurements::Volume::from_milliliters(value),
391        }
392    }
393}