Skip to main content

microcad_lang/ty/
quantity_type.rs

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