measurements/
current.rs

1//! Types and constants for handling electrical current.
2
3use super::measurement::*;
4
5/// The `Current` struct can be used to deal with electric potential difference
6/// in a common way.
7///
8/// # Example
9///
10/// ```
11/// use measurements::Current;
12///
13/// let amperes = Current::from_milliamperes(35.0);
14/// let a = amperes.as_amperes();
15/// let u_a = amperes.as_microamperes();
16/// println!("35 mA correspond to {} A or {} µA", a, u_a);
17/// ```
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19#[derive(Copy, Clone, Debug, Default)]
20pub struct Current {
21    amperes: f64,
22}
23
24impl Current {
25    /// Create a new Current from a floating point value in amperes
26    pub fn from_amperes(amperes: f64) -> Self {
27        Current { amperes }
28    }
29
30    /// Create a new Current from a floating point value in milliamperes
31    pub fn from_milliamperes(milliamperes: f64) -> Self {
32        Self::from_amperes(milliamperes / 1000.0)
33    }
34
35    /// Create a new Current from a floating point value in microamperes
36    pub fn from_microamperes(microamperes: f64) -> Self {
37        Self::from_amperes(microamperes / 1000.0 / 1000.0)
38    }
39
40    /// Create a new Current from a floating point value in nanoamperes
41    pub fn from_nanoamperes(nanoamperes: f64) -> Self {
42        Self::from_amperes(nanoamperes / 1_000_000_000.0)
43    }
44
45    /// Convert this Current into a floating point value in amperes
46    pub fn as_amperes(&self) -> f64 {
47        self.amperes
48    }
49
50    /// Convert this Current into a floating point value in milliamperes
51    pub fn as_milliamperes(&self) -> f64 {
52        self.amperes * 1000.0
53    }
54
55    /// Convert this Current into a floating point value in microamperes
56    pub fn as_microamperes(&self) -> f64 {
57        self.amperes * 1000.0 * 1000.0
58    }
59
60    /// Convert this Current into a floating point value in nanoamperes
61    pub fn as_nanoamperes(&self) -> f64 {
62        self.amperes * 1_000_000_000.0
63    }
64}
65
66impl Measurement for Current {
67    fn get_appropriate_units(&self) -> (&'static str, f64) {
68        // Smallest to Largest
69        let list = [
70            ("fA", 1e-15),
71            ("pA", 1e-12),
72            ("nA", 1e-9),
73            ("\u{00B5}A", 1e-6),
74            ("mA", 1e-3),
75            ("A", 1e0),
76            ("kA", 1e3),
77            ("MA", 1e6),
78            ("GA", 1e9),
79            ("TA", 1e12),
80            ("PA", 1e15),
81            ("EA", 1e18),
82        ];
83        self.pick_appropriate_units(&list)
84    }
85
86    fn get_base_units_name(&self) -> &'static str {
87        "A"
88    }
89
90    fn as_base_units(&self) -> f64 {
91        self.amperes
92    }
93
94    fn from_base_units(units: f64) -> Self {
95        Self::from_amperes(units)
96    }
97}
98
99implement_measurement! { Current }
100
101#[cfg(test)]
102mod test {
103    use crate::{current::*, test_utils::assert_almost_eq};
104
105    #[test]
106    pub fn as_amperes() {
107        let u = Current::from_milliamperes(1234.0);
108        assert_almost_eq(u.as_amperes(), 1.234);
109    }
110
111    #[test]
112    pub fn as_milliamperes() {
113        let u = Current::from_amperes(1.234);
114        assert_almost_eq(u.as_milliamperes(), 1234.0);
115    }
116
117    #[test]
118    pub fn as_microamperes() {
119        let u = Current::from_amperes(0.001);
120        assert_almost_eq(u.as_microamperes(), 1000.0);
121    }
122
123    #[test]
124    pub fn as_nanoamperes() {
125        let u = Current::from_amperes(0.000001);
126        assert_almost_eq(u.as_nanoamperes(), 1000.0);
127    }
128
129    // Traits
130    #[test]
131    fn add() {
132        let a = Current::from_amperes(2.0);
133        let b = Current::from_milliamperes(4000.0);
134        let c = a + b;
135        assert_almost_eq(c.as_amperes(), 6.0);
136    }
137
138    #[test]
139    fn sub() {
140        let a = Current::from_amperes(2.0);
141        let b = Current::from_milliamperes(4000.0);
142        let c = a - b;
143        assert_almost_eq(c.as_amperes(), -2.0);
144    }
145
146    #[test]
147    fn mul() {
148        let a = Current::from_milliamperes(2000.0);
149        let b = 4.0 * a;
150        assert_almost_eq(b.as_amperes(), 8.0);
151    }
152
153    #[test]
154    fn div() {
155        let a = Current::from_amperes(2.0);
156        let b = Current::from_milliamperes(4000.0);
157        let c = a / b;
158        let d = a / 2.0;
159        assert_almost_eq(c, 0.5);
160        assert_almost_eq(d.as_amperes(), 1.0);
161    }
162
163    #[test]
164    fn eq() {
165        let a = Current::from_microamperes(1_000_000.0);
166        let b = Current::from_milliamperes(1_000.0);
167        let c = Current::from_nanoamperes(1_000_000_000.0);
168        assert_eq!(a, b);
169        assert_eq!(b, c);
170        assert_eq!(a, c);
171    }
172
173    #[test]
174    fn neq() {
175        let a = Current::from_amperes(2.0);
176        let b = Current::from_milliamperes(2.0);
177        assert_ne!(a, b);
178    }
179
180    #[test]
181    fn cmp() {
182        let a = Current::from_amperes(2.0);
183        let b = Current::from_amperes(4.0);
184        assert_eq!(a < b, true);
185        assert_eq!(a <= b, true);
186        assert_eq!(a > b, false);
187        assert_eq!(a >= b, false);
188    }
189}