1use super::{Unit, UnitNumber, UnitComplex};
2use paste::paste;
3
4macro_rules! define_unit {
5 ($name:ident, $symbol:literal) => {
6 paste! {
7 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
8 pub struct [<$name Unit>];
9
10 impl Unit for [<$name Unit>] {
11 fn name() -> &'static str {
12 $symbol
13 }
14 }
15
16 pub type $name = UnitNumber<[<$name Unit>]>;
17 pub type [<$name Phasor>] = UnitComplex<[<$name Unit>]>;
18 }
19 };
20}
21
22define_unit!(Voltage, "V");
23define_unit!(Current, "A");
24define_unit!(Resistance, "Ω");
25define_unit!(Capacitance, "F");
26define_unit!(Inductance, "H");
27define_unit!(Charge, "Q");
28define_unit!(Power, "W");
29define_unit!(Energy, "J");
30define_unit!(Time, "s");
31define_unit!(Frequency, "Hz");
32define_unit!(Length, "m");
33define_unit!(Area, "m²");
34define_unit!(Force, "N");
35define_unit!(Pressure, "Pa");
36define_unit!(MagneticFlux, "Wb");
37define_unit!(FluxDensity, "T");
38define_unit!(Conductance, "S");
39define_unit!(Velocity, "m/s");
40define_unit!(Accel, "m/s²");
41define_unit!(Temperature, "K");
42define_unit!(Angle, "rad");
43
44#[cfg(test)]
45mod tests {
46 use std::str::FromStr;
47
48 use crate::{i, num, r, u, vel};
49
50 use super::*;
51
52 #[test]
53 fn test_voltage_parsing() {
54 let v = Voltage::from_str("5.6V").unwrap();
55 assert_eq!(v.number, num!(5.6));
56
57 let v = Voltage::from_str("3.3mV").unwrap();
58 assert_eq!(v.number, num!(3.3 m));
59 }
60
61 #[test]
62 fn test_resistance_parsing() {
63 let r = Resistance::from_str("10Ω").unwrap();
64 assert_eq!(r.number, num!(10));
65
66 let r = Resistance::from_str("2.2KΩ").unwrap();
67 assert_eq!(r.number, num!(2.2 k));
68 }
69
70 #[test]
71 fn test_invalid_unit() {
72 let result = Voltage::from_str("5.6A");
73 assert!(result.is_err());
74 assert_eq!(result.unwrap_err(), "Expect end with 'V'");
75 }
76
77 #[test]
78 fn test_unit_with_whitespace() {
79 let v = Voltage::from_str(" 1.2uV ").unwrap();
80 assert_eq!(v.number, num!(1.2 u));
81 }
82
83 #[test]
84 fn test_same_unit_add_sub() {
85 let q1 = u!(10. mQ);
86 let q2 = u!(5.0 mQ);
87 let q3 = q1 + q2;
88 assert_eq!(format!("{:.1}", q3), "15.0mQ");
89
90 let t1 = u!(2. us);
91 let t2 = u!(3. us);
92 let t3 = t2 - t1;
93 assert_eq!(format!("{:.0}", t3), "1us");
94
95 let v1 = u!(1.5 V);
96 let v2 = u!(0.5 V);
97 assert_eq!((v1 + v2).to_string(), "2V");
98
99 let i1 = u!(1 A);
100 let i2 = u!(0.1 A);
101 assert_eq!(format!("{:.2}", i1 - i2), "900.00mA");
102
103 let r1 = u!(100. Ω);
104 let r2 = u!(200. Ω);
105 assert_eq!((r1 + r2).to_string(), "300Ω");
106
107 let c1 = u!(10.0 F);
108 let c2 = u!(5.0 F);
109 assert_eq!(format!("{:.0}", c1 - c2), "5F");
110
111 let e1 = u!(1.2 J);
112 let e2 = u!(0.8 J);
113 assert_eq!((e1 + e2).to_string(), "2J");
114
115 let f1 = u!(9.8 N);
116 let f2 = u!(0.2 N);
117 assert_eq!(format!("{:.1}", f1 - f2), "9.6N");
118
119 let t1 = u!(300. K);
120 let t2 = u!(273. K);
121 assert_eq!(format!("{:.0}", t1 - t2), "27K");
122
123 let a1 = u!(1. rad);
124 let a2 = u!(2. rad);
125 assert_eq!((a1 + a2).to_string(), "3rad");
126 }
127
128 #[test]
129 fn test_display_default() {
130 let v = Voltage::new(3.1415926);
131 assert_eq!(v.to_string(), "3.1415926V");
132
133 let i = Current::new(0.005);
134 assert_eq!(i.to_string(), "0.005A");
135
136 let r = Resistance::new(220.0);
137 assert_eq!(r.to_string(), "220Ω");
138 }
139
140 #[test]
141 fn test_display_precision() {
142 let v = Voltage::new(3.1415926);
143 assert_eq!(format!("{:.2}", v), "3.14V");
144 assert_eq!(format!("{:.4}", v), "3.1416V");
145
146 let i = Current::new(0.0001234);
147 assert_eq!(format!("{:.6}", i), "0.000123A");
148 }
149
150 #[test]
151 fn test_display_zero_and_negative() {
152 let v = Voltage::new(0.0);
153 assert_eq!(v.to_string(), "0V");
154
155 let i = Current::new(-1.23);
156 assert_eq!(i.to_string(), "-1.23A");
157 }
158
159 #[test]
160 fn test_display_scientific_values() {
161 let big = Voltage::new(1e6);
162 assert_eq!(format!("{}", big), "1000000V");
163
164 let small = Current::new(1e-9);
165 assert_eq!(format!("{:.2}", small), "0.00A"); }
167
168 #[test]
169 fn test_display_various_units() {
170 let e = Energy::new(12.5);
171 assert_eq!(e.to_string(), "12.5J");
172
173 let t = Time::new(0.001);
174 assert_eq!(format!("{:.3}", t), "0.001s");
175
176 let f = Force::new(9.81);
177 assert_eq!(f.to_string(), "9.81N");
178
179 let p = Pressure::new(101325.0);
180 assert_eq!(format!("{:.0}", p), "101325Pa");
181 }
182
183 #[test]
184 fn test_ohms_law_voltage() {
185 let i = Current::new(num!(2.0));
186 let r = Resistance::new(num!(5.0));
187 let v = r * i;
188 assert_eq!(v.value(), num!(10.0));
189
190 let i = u!(2.0 A);
191 let r = u!(5.0 Ω);
192 let v = r * i;
193 assert_eq!(v.value(), num!(10.0));
194
195 let i = i!(2.0);
196 let r = r!(5.0);
197 let v = r * i;
198 assert_eq!(v.value(), num!(10.0));
199
200 let i = 2.0;
201 let i = u!(i A);
202 let r = r!(5.0);
203 let v = r * i;
204 assert_eq!(v.value(), num!(10.0));
205 }
206
207 #[test]
208 fn test_power_from_voltage_current() {
209 let v = Voltage::new(num!(3.0));
210 let i = Current::new(num!(2.0));
211 let p = v * i;
212 assert_eq!(p.value(), num!(6.0));
213
214 let v = u!(3.0 v);
215 let i = u!(2.0 A);
216 let p = v * i;
217 assert_eq!(p.value(), num!(6.0));
218 }
219
220 #[test]
221 fn test_energy_from_power_time() {
222 let p = Power::new(num!(5.0));
223 let t = Time::new(num!(10.0));
224 let e = p * t;
225 assert_eq!(e.value(), num!(50.0));
226
227 let p = u!(5.0 mW);
228 let t = u!(10. s);
229 let e = p * t;
230 assert_eq!(e.value(), num!(50.0 m));
231 }
232
233 #[test]
234 fn test_charge_from_capacitance_voltage() {
235 let c = Capacitance::new(num!(1.5));
236 let v = Voltage::new(num!(4.0));
237 let q = c * v;
238 assert_eq!(q.value(), num!(6.0));
239
240 let c = u!(1.5 pF);
241 let v = Voltage::new(num!(4.0));
242 let q = c * v;
243 assert_eq!(q.value(), num!(6.0 p));
244 }
245
246 #[test]
247 fn test_current_from_charge_time() {
248 let q = Charge::new(num!(10.0));
249 let t = Time::new(num!(2.0));
250 let i = q / t;
251 assert_eq!(i.value(), num!(5.0));
252
253 let q = u!(10.0 mQ);
254 let t = u!(2. us);
255 let i = q / t;
256 assert_eq!(i.value(), num!(5.0 k));
257 }
258
259 #[test]
260 fn test_power_from_force_velocity() {
261 let f = Force::new(num!(3.0));
262 let v = Velocity::new(num!(4.0));
263 let p = f * v;
264 assert_eq!(p.value(), num!(12.0));
265 }
266
267 #[test]
268 fn test_energy_from_force_length() {
269 let f = Force::new(num!(10.0));
270 let d = Length::new(num!(2.0));
271 let e = f * d;
272 assert_eq!(e.value(), num!(20.0));
273 }
274
275 #[test]
276 fn test_velocity_time() {
277 let v = vel!(100);
278 let t = u!(5 s);
279 let s = v * t;
280 assert_eq!(s, u!(500 m));
281
282 let v = vel!(100);
283 let t = u!(5 s);
284 let s = v * t;
285 assert_eq!(s, u!(500 m));
286 }
287
288 #[test]
289 fn test_pressure_from_force_area() {
290 let f = Force::new(num!(100.0));
291 let a = Area::new(num!(5.0));
292 let p = f / a;
293 assert_eq!(p.value(), num!(20.0));
294 }
295
296 #[test]
297 fn test_flux_from_density_area() {
298 let b = FluxDensity::new(num!(2.0));
299 let a = Area::new(num!(3.0));
300 let phi = b * a;
301 assert_eq!(phi.value(), num!(6.0));
302 }
303
304 #[test]
305 fn test_serialize_deserialize_unit_voltage() {
306 let v = Voltage::from_str("5.0V").unwrap();
307 let json = serde_json::to_string(&v).unwrap();
308 assert_eq!(json, "\"5V\"");
309 let parsed: Voltage = serde_json::from_str(&json).unwrap();
310 assert_eq!(parsed, v);
311 }
312
313 #[test]
314 fn test_serialize_deserialize_unit_current() {
315 let i = Current::from_str("2.2mA").unwrap();
316 let json = serde_json::to_string(&i).unwrap();
317 assert_eq!(json, "\"2.2mA\"");
318 let parsed: Current = serde_json::from_str(&json).unwrap();
319 assert_eq!(parsed, i);
320 }
321
322 #[test]
323 fn test_serialize_deserialize_unit_unicode() {
324 let r = Resistance::from_str("10kΩ").unwrap();
325 let json = serde_json::to_string(&r).unwrap();
326 assert_eq!(json, "\"10KΩ\"");
327 let parsed: Resistance = serde_json::from_str(&json).unwrap();
328 assert_eq!(parsed, r);
329 }
330
331 #[test]
332 fn test_deserialize_invalid_unit() {
333 let result: Result<Voltage, _> = serde_json::from_str("\"3.3A\""); assert!(result.is_err());
335 }
336
337 #[test]
338 fn test_div_self() {
339 let t1 = u!(100 s);
340 let t2 = u!(100 s);
341 let s = t1 / t2;
342 assert_eq!(s, num!(1))
343 }
344}