eng_units/units/
mass_unit.rs1use crate::units::AmountOfSubstanceUnit;
18use crate::units::ElectricCurrentUnit;
19use crate::units::IsEngUnitType;
20use crate::units::LengthUnit;
21use crate::units::LuminousIntensityUnit;
22use crate::units::TemperatureDeltaUnit;
23use crate::units::TimeUnit;
24
25#[macro_export]
27macro_rules! mass {
28 ($value:literal, $unit:expr) => {{
29 let mut unit = EngUnit::new();
30 unit.value = $value;
31 unit.mass_count = 1;
32 if $unit == MassUnit::None {
33 unit.mass_count = 0;
34 }
35 unit.mass_unit = $unit;
36 unit
37 }};
38}
39
40#[macro_export]
41macro_rules! mass_kg {
42 ($value:expr) => {{
43 let mut unit = EngUnit::new();
44 unit.value = $value;
45 unit.mass_count = 1;
46 unit.mass_unit = MassUnit::Kilogram;
47 unit
48 }};
49}
50
51#[macro_export]
52macro_rules! mass_lb {
53 ($value:expr) => {{
54 let mut unit = EngUnit::new();
55 unit.value = $value;
56 unit.mass_count = 1;
57 unit.mass_unit = MassUnit::Pound;
58 unit
59 }};
60}
61
62#[derive(Copy, Clone, Debug, PartialEq)]
63pub enum MassUnit {
64 Kilogram,
65 Pound,
66 None,
67}
68
69impl<
70 T: IsEngUnitType
71 + Into<AmountOfSubstanceUnit>
72 + Into<ElectricCurrentUnit>
73 + Into<LengthUnit>
74 + Into<LuminousIntensityUnit>
75 + Into<MassUnit>
76 + Into<TemperatureDeltaUnit>
77 + Into<TimeUnit>,
78 > From<&T> for MassUnit
79{
80 fn from(value: &T) -> Self {
81 if T::is_amount_unit() {
82 value.into()
83 } else {
84 Self::None
85 }
86 }
87}
88impl IsEngUnitType for MassUnit {
89 fn is_mass_unit() -> bool {
90 true
91 }
92}
93impl From<AmountOfSubstanceUnit> for MassUnit {
94 fn from(_: AmountOfSubstanceUnit) -> Self {
95 MassUnit::None
96 }
97}
98impl From<ElectricCurrentUnit> for MassUnit {
99 fn from(_: ElectricCurrentUnit) -> Self {
100 MassUnit::None
101 }
102}
103impl From<LengthUnit> for MassUnit {
104 fn from(_: LengthUnit) -> Self {
105 MassUnit::None
106 }
107}
108impl From<LuminousIntensityUnit> for MassUnit {
109 fn from(_: LuminousIntensityUnit) -> Self {
110 MassUnit::None
111 }
112}
113impl From<TemperatureDeltaUnit> for MassUnit {
114 fn from(_: TemperatureDeltaUnit) -> Self {
115 MassUnit::None
116 }
117}
118impl From<TimeUnit> for MassUnit {
119 fn from(_: TimeUnit) -> Self {
120 MassUnit::None
121 }
122}
123
124pub const KILOGRAM_TO_POUND: f64 = 2.204_622_62;
125
126impl MassUnit {
127 pub fn to_string(&self) -> &'static str {
128 match self {
129 MassUnit::Kilogram => "kg",
130 MassUnit::Pound => "lb",
131 MassUnit::None => "",
132 }
133 }
134
135 pub fn conversion_factor(from: &MassUnit, to: &MassUnit) -> f64 {
136 match from {
137 MassUnit::Kilogram => match to {
138 MassUnit::Kilogram => 1.0,
139 MassUnit::Pound => KILOGRAM_TO_POUND,
140 MassUnit::None => 1.0,
141 },
142 MassUnit::Pound => match to {
143 MassUnit::Pound => 1.0,
144 MassUnit::Kilogram => 1.0 / KILOGRAM_TO_POUND,
145 MassUnit::None => 1.0,
146 },
147 MassUnit::None => 1.0,
148 }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use crate::units::amount_of_substance_unit::AmountOfSubstanceUnit;
155 use crate::units::electric_current_unit::ElectricCurrentUnit;
156 use crate::units::length_unit::LengthUnit;
157 use crate::units::luminous_intensity_unit::LuminousIntensityUnit;
158 use crate::units::mass_unit::MassUnit;
159 use crate::units::temperature_unit::TemperatureDeltaUnit;
160 use crate::units::time_unit::TimeUnit;
161 use crate::units::EngUnit;
162
163 #[test]
164 fn test_new() {
165 let unit = mass!(123.45, MassUnit::Kilogram);
166 assert_eq!(123.45, unit.value);
167 assert_eq!("123.45 kg", unit.to_string());
168 assert_eq!(TimeUnit::None, unit.time_unit);
169 assert_eq!(AmountOfSubstanceUnit::None, unit.amount_of_substance_unit);
170 assert_eq!(ElectricCurrentUnit::None, unit.electric_current_unit);
171 assert_eq!(LengthUnit::None, unit.length_unit);
172 assert_eq!(LuminousIntensityUnit::None, unit.luminous_intensity_unit);
173 assert_eq!(MassUnit::Kilogram, unit.mass_unit);
174 assert_eq!(TemperatureDeltaUnit::None, unit.temperature_unit);
175 assert_eq!(TimeUnit::None, unit.time_unit);
176 assert_eq!(0, unit.temperature_count);
177 assert_eq!(0, unit.time_count);
178 assert_eq!(0, unit.length_count);
179 assert_eq!(1, unit.mass_count);
180 assert_eq!(0, unit.luminous_intensity_count);
181 assert_eq!(0, unit.amount_of_substance_count);
182 assert_eq!(0, unit.electric_current_count);
183 }
184
185 #[test]
186 fn test_value() {
187 let m1 = mass!(123.45, MassUnit::Kilogram);
188 assert_eq!(123.45, m1.value);
189 }
190
191 #[test]
192 fn test_kg_to_str() {
193 let m1 = mass!(1.0, MassUnit::Kilogram);
194 assert_eq!("1.00 kg", m1.to_string());
195 }
196
197 #[test]
198 fn test_lb_to_str() {
199 let m1 = mass!(1.0, MassUnit::Pound);
200 assert_eq!("1.00 lb", m1.to_string());
201 }
202
203 #[test]
204 fn test_none_to_str() {
205 let m1 = mass!(1.0, MassUnit::None);
206 assert_eq!("1.00", m1.to_string());
207 }
208
209 #[test]
210 fn test_latex() {
211 let m1 = mass!(1.0, MassUnit::Kilogram);
212 assert_eq!("$1\\ kg$", m1.to_latex())
213 }
214
215 #[test]
216 fn test_unit_to_str_kg() {
217 let m1 = mass!(1.0, MassUnit::Kilogram);
218 assert_eq!("kg", m1.unit_to_string());
219 }
220
221 #[test]
222 fn test_unit_to_str_lb() {
223 let m1 = mass!(1.0, MassUnit::Pound);
224 assert_eq!("lb", m1.unit_to_string());
225 }
226
227 #[test]
228 fn test_unit_to_str_none() {
229 let m1 = mass!(1.0, MassUnit::None);
230 assert_eq!("", m1.unit_to_string());
231 assert_eq!("", MassUnit::to_string(&MassUnit::None));
232 }
233
234 #[test]
235 fn test_conversion_kg_lb() {
236 let m1 = mass!(1.0, MassUnit::Kilogram);
237 let m2 = m1.convert(MassUnit::Pound);
238 assert_eq!(1.0, m1.value);
239 assert_eq!(2.204_622_62, m2.value);
240 assert_eq!(MassUnit::Kilogram, m1.mass_unit);
241 assert_eq!(MassUnit::Pound, m2.mass_unit);
242 assert_eq!("1.00 kg", m1.to_string());
243 assert_eq!("2.20 lb", m2.to_string());
244 }
245
246 #[test]
247 fn test_conversion_lb_kg() {
248 let m1 = mass!(1.0, MassUnit::Pound);
249 let m2 = m1.convert(MassUnit::Kilogram);
250 assert_eq!(1.0, m1.value);
251 let expected = 0.45359237;
252 assert!(f64::abs(expected - m2.value) < 0.00001);
253 assert_eq!(MassUnit::Pound, m1.mass_unit);
254 assert_eq!(MassUnit::Kilogram, m2.mass_unit);
255 assert_eq!("1.00 lb", m1.to_string());
256 assert_eq!("0.45 kg", m2.to_string());
257 }
258}