1use super::DisplayWithUnit;
2
3#[must_use]
19#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
20pub struct Area(pub(crate) f64);
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum AreaUnit {
25 SquareMeter,
27 SquareMillimeter,
29 SquareCentimeter,
31 SquareKilometer,
33 SquareFoot,
35 SquareInch,
37}
38
39impl AreaUnit {
40 const fn symbol(self) -> &'static str {
41 match self {
42 Self::SquareMeter => "m^2",
43 Self::SquareMillimeter => "mm^2",
44 Self::SquareCentimeter => "cm^2",
45 Self::SquareKilometer => "km^2",
46 Self::SquareFoot => "ft^2",
47 Self::SquareInch => "in^2",
48 }
49 }
50
51 const fn m2_per_unit(self) -> f64 {
52 match self {
53 Self::SquareMeter => 1.0,
54 Self::SquareMillimeter => 1e-6,
55 Self::SquareCentimeter => 1e-4,
56 Self::SquareKilometer => 1_000_000.0,
57 Self::SquareFoot => 0.092_903_04,
58 Self::SquareInch => 0.000_645_16,
59 }
60 }
61}
62
63impl Area {
64 pub const fn from_m2(val: f64) -> Self {
66 Self(val)
67 }
68
69 pub const fn from_km2(val: f64) -> Self {
71 Self(val * 1_000_000.0)
72 }
73
74 pub const fn from_mm2(val: f64) -> Self {
76 Self(val * 1e-6)
77 }
78
79 pub const fn from_cm2(val: f64) -> Self {
81 Self(val * 1e-4)
82 }
83
84 pub const fn from_ft2(val: f64) -> Self {
86 Self(val * 0.092_903_04)
87 }
88
89 pub const fn from_in2(val: f64) -> Self {
91 Self(val * 0.000_645_16)
92 }
93
94 pub const fn in_m2(self) -> f64 {
96 self.0
97 }
98
99 pub const fn in_km2(self) -> f64 {
101 self.0 / 1_000_000.0
102 }
103
104 pub const fn in_mm2(self) -> f64 {
106 self.0 / 1e-6
107 }
108
109 pub const fn in_cm2(self) -> f64 {
111 self.0 / 1e-4
112 }
113
114 pub const fn in_ft2(self) -> f64 {
116 self.0 / 0.092_903_04
117 }
118
119 pub const fn in_in2(self) -> f64 {
121 self.0 / 0.000_645_16
122 }
123
124 pub fn in_unit(self, unit: AreaUnit) -> f64 {
126 self.0 / unit.m2_per_unit()
127 }
128
129 pub fn display_as(self, unit: AreaUnit) -> DisplayWithUnit {
131 DisplayWithUnit {
132 value: self.in_unit(unit),
133 symbol: unit.symbol(),
134 }
135 }
136
137 pub fn abs(self) -> Self {
139 Self(self.0.abs())
140 }
141}
142
143impl_quantity_display!(Area, "m²");
144
145impl_common_ops!(Area);
146
147#[must_use]
163#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
164pub struct Volume(pub(crate) f64);
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub enum VolumeUnit {
169 CubicMeter,
171 Liter,
173 CubicCentimeter,
175 CubicFoot,
177 GallonUs,
179}
180
181impl VolumeUnit {
182 const fn symbol(self) -> &'static str {
183 match self {
184 Self::CubicMeter => "m^3",
185 Self::Liter => "L",
186 Self::CubicCentimeter => "cm^3",
187 Self::CubicFoot => "ft^3",
188 Self::GallonUs => "gal",
189 }
190 }
191
192 const fn m3_per_unit(self) -> f64 {
193 match self {
194 Self::CubicMeter => 1.0,
195 Self::Liter => 1e-3,
196 Self::CubicCentimeter => 1e-6,
197 Self::CubicFoot => 0.028_316_846_592,
198 Self::GallonUs => 0.003_785_411_784,
199 }
200 }
201}
202
203impl Volume {
204 pub const fn from_m3(val: f64) -> Self {
206 Self(val)
207 }
208
209 pub const fn from_l(val: f64) -> Self {
211 Self(val * 1e-3)
212 }
213
214 pub const fn from_cm3(val: f64) -> Self {
216 Self(val * 1e-6)
217 }
218
219 pub const fn from_ft3(val: f64) -> Self {
221 Self(val * 0.028_316_846_592)
222 }
223
224 pub const fn from_gal(val: f64) -> Self {
226 Self(val * 0.003_785_411_784)
227 }
228
229 pub const fn in_m3(self) -> f64 {
231 self.0
232 }
233
234 pub const fn in_l(self) -> f64 {
236 self.0 / 1e-3
237 }
238
239 pub const fn in_cm3(self) -> f64 {
241 self.0 / 1e-6
242 }
243
244 pub const fn in_ft3(self) -> f64 {
246 self.0 / 0.028_316_846_592
247 }
248
249 pub const fn in_gal(self) -> f64 {
251 self.0 / 0.003_785_411_784
252 }
253
254 pub fn in_unit(self, unit: VolumeUnit) -> f64 {
256 self.0 / unit.m3_per_unit()
257 }
258
259 pub fn display_as(self, unit: VolumeUnit) -> DisplayWithUnit {
261 DisplayWithUnit {
262 value: self.in_unit(unit),
263 symbol: unit.symbol(),
264 }
265 }
266
267 pub fn abs(self) -> Self {
269 Self(self.0.abs())
270 }
271}
272
273impl_quantity_display!(Volume, "m³");
274
275impl_common_ops!(Volume);
276
277#[must_use]
292#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
293pub struct Density(pub(crate) f64);
294
295#[derive(Debug, Clone, Copy, PartialEq, Eq)]
297pub enum DensityUnit {
298 KgPerM3,
300 GramPerCm3,
302 PoundPerFt3,
304}
305
306impl DensityUnit {
307 const fn symbol(self) -> &'static str {
308 match self {
309 Self::KgPerM3 => "kg/m^3",
310 Self::GramPerCm3 => "g/cm^3",
311 Self::PoundPerFt3 => "lb/ft^3",
312 }
313 }
314}
315
316impl Density {
317 pub const fn from_kgpm3(val: f64) -> Self {
319 Self(val)
320 }
321
322 pub const fn from_gpcm3(val: f64) -> Self {
324 Self(val * 1e3)
325 }
326
327 pub const fn from_lbpft3(val: f64) -> Self {
329 Self(val * 16.018_463)
330 }
331
332 pub const fn in_kgpm3(self) -> f64 {
334 self.0
335 }
336
337 pub const fn in_gpcm3(self) -> f64 {
339 self.0 / 1e3
340 }
341
342 pub const fn in_lbpft3(self) -> f64 {
344 self.0 / 16.018_463
345 }
346
347 pub const fn display_as(self, unit: DensityUnit) -> DisplayWithUnit {
349 match unit {
350 DensityUnit::KgPerM3 => DisplayWithUnit {
351 value: self.0,
352 symbol: unit.symbol(),
353 },
354 DensityUnit::GramPerCm3 => DisplayWithUnit {
355 value: self.in_gpcm3(),
356 symbol: unit.symbol(),
357 },
358 DensityUnit::PoundPerFt3 => DisplayWithUnit {
359 value: self.in_lbpft3(),
360 symbol: unit.symbol(),
361 },
362 }
363 }
364
365 pub fn abs(self) -> Self {
367 Self(self.0.abs())
368 }
369}
370
371impl_quantity_display!(Density, "kg/m³");
372
373impl_common_ops!(Density);