1use kittycad_unit_conversion_derive::UnitConversion;
2use parse_display_derive::{Display, FromStr};
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6#[cfg(feature = "cxx")]
7use crate::impl_extern_type;
8
9#[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)]
27#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
28#[display(style = "snake_case")]
29#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
30#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
31#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
32#[cfg_attr(
33 feature = "python",
34 pyo3::pyclass(eq, from_py_object),
35 pyo3_stub_gen::derive::gen_stub_pyclass_enum
36)]
37pub enum UnitLength {
38 #[serde(rename = "cm")]
40 #[display("cm")]
41 Centimeters,
42 #[serde(rename = "ft")]
44 #[display("ft")]
45 Feet,
46 #[serde(rename = "in")]
48 #[display("in")]
49 Inches,
50 #[default]
52 #[serde(rename = "m")]
53 #[display("m")]
54 Meters,
55 #[serde(rename = "mm")]
57 #[display("mm")]
58 Millimeters,
59 #[serde(rename = "yd")]
61 #[display("yd")]
62 Yards,
63}
64
65impl UnitLength {
66 pub fn as_measurement(self, value: f64) -> measurements::Length {
68 match self {
69 Self::Centimeters => measurements::Length::from_centimeters(value),
70 Self::Feet => measurements::Length::from_feet(value),
71 Self::Inches => measurements::Length::from_inches(value),
72 Self::Meters => measurements::Length::from_meters(value),
73 Self::Millimeters => measurements::Length::from_millimeters(value),
74 Self::Yards => measurements::Length::from_yards(value),
75 }
76 }
77}
78
79#[cfg(feature = "cxx")]
80impl_extern_type! {
81 [Trivial]
82 UnitLength = "Enums::_UnitLength"
83}
84
85#[derive(
87 Default,
88 Display,
89 FromStr,
90 Copy,
91 Eq,
92 PartialEq,
93 Debug,
94 JsonSchema,
95 Deserialize,
96 Serialize,
97 Clone,
98 Ord,
99 PartialOrd,
100 UnitConversion,
101 Hash,
102)]
103#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
104#[serde(rename_all = "snake_case")]
105#[display(style = "snake_case")]
106#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
107#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
108#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
109#[cfg_attr(
110 feature = "python",
111 pyo3::pyclass(eq, from_py_object),
112 pyo3_stub_gen::derive::gen_stub_pyclass_enum
113)]
114pub enum UnitAngle {
115 #[default]
117 #[display("deg")]
118 Degrees,
119 #[display("rad")]
121 Radians,
122}
123
124#[derive(
126 Display,
127 FromStr,
128 Copy,
129 Eq,
130 PartialEq,
131 Debug,
132 JsonSchema,
133 Deserialize,
134 Serialize,
135 Clone,
136 Ord,
137 PartialOrd,
138 UnitConversion,
139 Default,
140 Hash,
141)]
142#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
143#[serde(rename_all = "snake_case")]
144#[display(style = "snake_case")]
145#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
146#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
147#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
148#[cfg_attr(
149 feature = "python",
150 pyo3::pyclass(eq, from_py_object),
151 pyo3_stub_gen::derive::gen_stub_pyclass_enum
152)]
153pub enum UnitArea {
154 #[serde(rename = "cm2")]
156 #[display("cm2")]
157 SquareCentimeters,
158 #[serde(rename = "dm2")]
160 #[display("dm2")]
161 SquareDecimeters,
162 #[serde(rename = "ft2")]
164 #[display("ft2")]
165 SquareFeet,
166 #[serde(rename = "in2")]
168 #[display("in2")]
169 SquareInches,
170 #[serde(rename = "km2")]
172 #[display("km2")]
173 SquareKilometers,
174 #[default]
176 #[serde(rename = "m2")]
177 #[display("m2")]
178 SquareMeters,
179 #[serde(rename = "mm2")]
181 #[display("mm2")]
182 SquareMillimeters,
183 #[serde(rename = "yd2")]
185 #[display("yd2")]
186 SquareYards,
187}
188
189impl UnitArea {
190 pub fn as_measurement(self, value: f64) -> measurements::Area {
192 match self {
193 Self::SquareCentimeters => measurements::Area::from_square_centimeters(value),
194 Self::SquareDecimeters => measurements::Area::from_square_decimeters(value),
195 Self::SquareFeet => measurements::Area::from_square_feet(value),
196 Self::SquareInches => measurements::Area::from_square_inches(value),
197 Self::SquareKilometers => measurements::Area::from_square_kilometers(value),
198 Self::SquareMeters => measurements::Area::from_square_meters(value),
199 Self::SquareMillimeters => measurements::Area::from_square_millimeters(value),
200 Self::SquareYards => measurements::Area::from_square_yards(value),
201 }
202 }
203}
204
205#[derive(
207 Display,
208 Copy,
209 Eq,
210 PartialEq,
211 Debug,
212 JsonSchema,
213 Deserialize,
214 Serialize,
215 Clone,
216 Ord,
217 PartialOrd,
218 Default,
219 UnitConversion,
220 Hash,
221)]
222#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
223#[display(style = "snake_case")]
224#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
225#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
226#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
227#[cfg_attr(
228 feature = "python",
229 pyo3::pyclass(eq, from_py_object),
230 pyo3_stub_gen::derive::gen_stub_pyclass_enum
231)]
232pub enum UnitDensity {
233 #[serde(rename = "lb:ft3")]
235 #[display("lb:ft3")]
236 PoundsPerCubicFeet,
237
238 #[default]
240 #[serde(rename = "kg:m3")]
241 #[display("kg:m3")]
242 KilogramsPerCubicMeter,
243}
244
245impl std::str::FromStr for UnitDensity {
246 type Err = parse_display::ParseError;
247
248 fn from_str(s: &str) -> Result<Self, Self::Err> {
249 match s {
250 "lbft3" | "lb:ft3" | "lb-ft3" => Ok(Self::PoundsPerCubicFeet),
251 "kgm3" | "kg:m3" | "kg-m3" => Ok(Self::KilogramsPerCubicMeter),
252 _other => Err(Default::default()),
253 }
254 }
255}
256
257impl UnitDensity {
258 pub fn as_measurement(self, value: f64) -> measurements::Density {
260 match self {
261 Self::PoundsPerCubicFeet => measurements::Density::from_pounds_per_cubic_feet(value),
262 Self::KilogramsPerCubicMeter => measurements::Density::from_kilograms_per_cubic_meter(value),
263 }
264 }
265}
266
267#[derive(
269 Default,
270 Display,
271 FromStr,
272 Copy,
273 Eq,
274 PartialEq,
275 Debug,
276 JsonSchema,
277 Deserialize,
278 Serialize,
279 Clone,
280 Ord,
281 PartialOrd,
282 UnitConversion,
283 Hash,
284)]
285#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
286#[serde(rename_all = "snake_case")]
287#[display(style = "snake_case")]
288#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
289#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
290#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
291#[cfg_attr(
292 feature = "python",
293 pyo3::pyclass(eq, from_py_object),
294 pyo3_stub_gen::derive::gen_stub_pyclass_enum
295)]
296pub enum UnitMass {
297 #[default]
299 #[serde(rename = "g")]
300 #[display("g")]
301 Grams,
302 #[serde(rename = "kg")]
304 #[display("kg")]
305 Kilograms,
306 #[serde(rename = "lb")]
308 #[display("lb")]
309 Pounds,
310}
311
312impl UnitMass {
313 pub fn as_measurement(self, value: f64) -> measurements::Mass {
315 match self {
316 Self::Grams => measurements::Mass::from_grams(value),
317 Self::Kilograms => measurements::Mass::from_kilograms(value),
318 Self::Pounds => measurements::Mass::from_pounds(value),
319 }
320 }
321}
322
323#[derive(
325 Default,
326 Display,
327 FromStr,
328 Copy,
329 Eq,
330 PartialEq,
331 Debug,
332 JsonSchema,
333 Deserialize,
334 Serialize,
335 Clone,
336 Ord,
337 PartialOrd,
338 UnitConversion,
339 Hash,
340)]
341#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
342#[display(style = "snake_case")]
343#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
344#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
345#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
346#[cfg_attr(
347 feature = "python",
348 pyo3::pyclass(eq, from_py_object),
349 pyo3_stub_gen::derive::gen_stub_pyclass_enum
350)]
351pub enum UnitVolume {
352 #[serde(rename = "mm3")]
354 #[display("mm3")]
355 CubicMillimeters,
356 #[serde(rename = "cm3")]
358 #[display("cm3")]
359 CubicCentimeters,
360 #[serde(rename = "ft3")]
362 #[display("ft3")]
363 CubicFeet,
364 #[serde(rename = "in3")]
366 #[display("in3")]
367 CubicInches,
368 #[default]
370 #[serde(rename = "m3")]
371 #[display("m3")]
372 CubicMeters,
373 #[serde(rename = "yd3")]
375 #[display("yd3")]
376 CubicYards,
377 #[serde(rename = "usfloz")]
379 #[display("usfloz")]
380 FluidOunces,
381 #[serde(rename = "usgal")]
383 #[display("usgal")]
384 Gallons,
385 #[serde(rename = "l")]
387 #[display("l")]
388 Liters,
389 #[serde(rename = "ml")]
391 #[display("ml")]
392 Milliliters,
393}
394
395impl UnitVolume {
396 pub fn as_measurement(self, value: f64) -> measurements::Volume {
398 match self {
399 Self::CubicMillimeters => measurements::Volume::from_cubic_millimeters(value),
400 Self::CubicCentimeters => measurements::Volume::from_cubic_centimeters(value),
401 Self::CubicFeet => measurements::Volume::from_cubic_feet(value),
402 Self::CubicInches => measurements::Volume::from_cubic_inches(value),
403 Self::CubicMeters => measurements::Volume::from_cubic_meters(value),
404 Self::CubicYards => measurements::Volume::from_cubic_yards(value),
405 Self::FluidOunces => measurements::Volume::from_fluid_ounces(value),
406 Self::Gallons => measurements::Volume::from_gallons(value),
407 Self::Liters => measurements::Volume::from_liters(value),
408 Self::Milliliters => measurements::Volume::from_milliliters(value),
409 }
410 }
411}