1use crate::{syntax::*, ty::*};
7
8#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
10pub enum Unit {
11 #[default]
14 None,
15 Percent,
17
18 Meter,
21 Centimeter,
23 Millimeter,
25 Micrometer,
27 Inch,
29 Foot,
31 Yard,
33
34 Deg,
37 DegS,
39 Grad,
41 Turns,
43 Rad,
45
46 Gram,
49 Kilogram,
51 Pound,
53 Ounce,
55
56 Meter2,
59 Centimeter2,
61 Millimeter2,
63 Micrometer2,
65 Inch2,
67 Foot2,
69 Yard2,
71
72 Meter3,
75 Centimeter3,
77 Millimeter3,
79 Micrometer3,
81 Inch3,
83 Foot3,
85 Yard3,
87 Liter,
89 Centiliter,
91 Milliliter,
93 Microliter,
95
96 GramPerMeter3,
98 GramPerMillimeter3,
100}
101
102impl std::fmt::Display for Unit {
103 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
104 match self {
105 Self::None => write!(f, ""),
107 Self::Percent => write!(f, "%"),
108
109 Self::Meter => write!(f, "m"),
111 Self::Centimeter => write!(f, "cm"),
112 Self::Millimeter => write!(f, "mm"),
113 Self::Micrometer => write!(f, "µm"),
114 Self::Inch => write!(f, "in"),
115 Self::Foot => write!(f, "ft"),
116 Self::Yard => write!(f, "yd"),
117
118 Self::Deg => write!(f, "deg"),
120 Self::DegS => write!(f, "°"),
121 Self::Grad => write!(f, "grad"),
122 Self::Turns => write!(f, "turns"),
123 Self::Rad => write!(f, "rad"),
124
125 Self::Gram => write!(f, "g"),
127 Self::Kilogram => write!(f, "kg"),
128 Self::Pound => write!(f, "lb"),
129 Self::Ounce => write!(f, "oz"),
130
131 Self::Meter2 => write!(f, "m³"),
133 Self::Centimeter2 => write!(f, "cm²"),
134 Self::Millimeter2 => write!(f, "mm²"),
135 Self::Micrometer2 => write!(f, "µm²"),
136 Self::Inch2 => write!(f, "in²"),
137 Self::Foot2 => write!(f, "ft²"),
138 Self::Yard2 => write!(f, "yd²"),
139
140 Self::Meter3 => write!(f, "m³"),
142 Self::Centimeter3 => write!(f, "cm³"),
143 Self::Millimeter3 => write!(f, "mm³"),
144 Self::Micrometer3 => write!(f, "µm³"),
145 Self::Inch3 => write!(f, "in³"),
146 Self::Foot3 => write!(f, "ft³"),
147 Self::Yard3 => write!(f, "yd³"),
148
149 Self::Milliliter => write!(f, "ml"),
150 Self::Centiliter => write!(f, "cl"),
151 Self::Liter => write!(f, "l"),
152 Self::Microliter => write!(f, "µl"),
153
154 Self::GramPerMeter3 => write!(f, "g/m³"),
156 Self::GramPerMillimeter3 => write!(f, "g/mm³"),
157 }
158 }
159}
160
161impl Unit {
162 pub fn ty(self) -> Type {
164 match self {
165 Self::None | Self::Percent => Type::Quantity(QuantityType::Scalar),
166 Self::Meter
167 | Self::Centimeter
168 | Self::Millimeter
169 | Self::Micrometer
170 | Self::Inch
171 | Self::Foot
172 | Self::Yard => Type::Quantity(QuantityType::Length),
173 Self::Deg | Self::DegS | Self::Grad | Self::Turns | Self::Rad => {
174 Type::Quantity(QuantityType::Angle)
175 }
176 Self::Gram | Self::Kilogram | Self::Pound | Self::Ounce => {
177 Type::Quantity(QuantityType::Weight)
178 }
179 Self::Meter2
180 | Self::Centimeter2
181 | Self::Millimeter2
182 | Self::Micrometer2
183 | Self::Inch2
184 | Self::Foot2
185 | Self::Yard2 => Type::Quantity(QuantityType::Area),
186 Self::Meter3
187 | Self::Centimeter3
188 | Self::Millimeter3
189 | Self::Micrometer3
190 | Self::Inch3
191 | Self::Foot3
192 | Self::Yard3
193 | Self::Liter
194 | Self::Centiliter
195 | Self::Milliliter
196 | Self::Microliter => Type::Quantity(QuantityType::Volume),
197 Self::GramPerMeter3 | Self::GramPerMillimeter3 => Type::Quantity(QuantityType::Density),
198 }
199 }
200
201 pub fn normalize(self, x: f64) -> f64 {
203 match self {
204 Self::None => x,
206 Self::Percent => x * 0.01_f64,
207
208 Self::Meter => x * 1_000_f64,
210 Self::Centimeter => x * 10_f64,
211 Self::Millimeter => x,
212 Self::Micrometer => x / 1_000_f64,
213 Self::Inch => x * 25.4_f64,
214 Self::Foot => x * 304.8_f64,
215 Self::Yard => x * 914.4_f64,
216
217 Self::Deg | Self::DegS => x / 180. * std::f64::consts::PI,
219 Self::Grad => x / 200. * std::f64::consts::PI,
220 Self::Turns => x * 2.0 * std::f64::consts::PI,
221 Self::Rad => x,
222
223 Self::Gram => x,
225 Self::Kilogram => x * 1_000_f64,
226 Self::Pound => x * 453.59237_f64,
227 Self::Ounce => x * 28.349_523_125_f64,
228
229 Self::Meter2 => x * 1_000_000_f64,
231 Self::Centimeter2 => x * 100_f64,
232 Self::Millimeter2 => x,
233 Self::Micrometer2 => x * 0.000_000_1,
234 Self::Inch2 => x * 645.16_f64,
235 Self::Foot2 => x * 92_903_043.04_f64,
236 Self::Yard2 => x * 836_127.36_f64,
237
238 Self::Meter3 => x * 1_000_000_000_f64,
240 Self::Centimeter3 => x * 1_000_f64,
241 Self::Millimeter3 => x,
242 Self::Micrometer3 => x * 0.000_000_000_1,
243 Self::Inch3 => x * 16_387.06_f64,
244 Self::Foot3 => x * 28_316_846.592_f64,
245 Self::Yard3 => x * 764_554_857.984_f64,
246 Self::Liter => x * 1_000_000_f64,
247 Self::Centiliter => x * 10_000_f64,
248 Self::Milliliter => x * 1_000_f64,
249 Self::Microliter => x * 1_000_000.0_f64,
250
251 Self::GramPerMeter3 => 1_000_000_000_f64,
253 Self::GramPerMillimeter3 => 1_f64,
254 }
255 }
256}
257
258impl TreeDisplay for Unit {
259 fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result {
260 if !matches!(self, Unit::None) {
261 writeln!(f, "{:depth$}Unit: {}", "", self)
262 } else {
263 Ok(())
264 }
265 }
266}