microcad_lang/ty/
quantity_type.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! µcad quantity type
5
6use strum::IntoStaticStr;
7
8/// A quantity type with
9#[derive(Clone, Debug, IntoStaticStr, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub enum QuantityType {
11    /// A unitless scalar value.
12    Scalar,
13    /// Length in mm.
14    Length,
15    /// Area in mm².
16    Area,
17    /// Volume in mm³.
18    Volume,
19    /// Density in g/mm³
20    Density,
21    /// An angle in radians.
22    Angle,
23    /// Weight of a specific volume of material.
24    Weight,
25    /// An invalid, unsupported quantity type.
26    Invalid,
27}
28
29impl QuantityType {
30    /// Return base unit
31    pub fn base_unit(&self) -> &'static str {
32        match self {
33            QuantityType::Scalar => "",
34            QuantityType::Length => "mm",
35            QuantityType::Area => "mm²",
36            QuantityType::Volume => "mm³",
37            QuantityType::Density => "g/mm³",
38            QuantityType::Angle => "rad",
39            QuantityType::Weight => "g",
40            QuantityType::Invalid => todo!(),
41        }
42    }
43}
44
45impl std::fmt::Display for QuantityType {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        let name: &'static str = self.into();
48        write!(f, "{name}")
49    }
50}
51
52impl std::ops::Mul for QuantityType {
53    type Output = QuantityType;
54
55    fn mul(self, rhs: Self) -> Self::Output {
56        if self == Self::Invalid || rhs == Self::Invalid {
57            return Self::Invalid;
58        }
59        if self == QuantityType::Scalar {
60            return rhs;
61        }
62        if rhs == QuantityType::Scalar {
63            return self;
64        }
65
66        match (self, rhs) {
67            (QuantityType::Length, QuantityType::Length) => QuantityType::Area,
68            (QuantityType::Length, QuantityType::Area)
69            | (QuantityType::Area, QuantityType::Length) => QuantityType::Volume,
70            (_, _) => QuantityType::Invalid,
71        }
72    }
73}
74
75impl std::ops::Div for QuantityType {
76    type Output = QuantityType;
77
78    fn div(self, rhs: Self) -> Self::Output {
79        if rhs == self {
80            return QuantityType::Scalar;
81        }
82        if rhs == QuantityType::Scalar {
83            return self;
84        }
85
86        match (self, rhs) {
87            (QuantityType::Volume, QuantityType::Length) => QuantityType::Area,
88            (QuantityType::Volume, QuantityType::Area) => QuantityType::Length,
89            (_, _) => QuantityType::Invalid,
90        }
91    }
92}