1use crate::assert_positive_float;
2use core::{cmp, fmt, ops};
3
4#[derive(Clone, Copy, Debug)]
88pub struct Current {
89 raw: u64,
90}
91
92impl Current {
93 #[inline]
98 pub const fn from_micro_amps(value: u64) -> Self {
99 Self { raw: value }
100 }
101
102 #[inline]
104 pub const fn micro_amps(&self) -> u64 {
105 self.raw
106 }
107
108 #[inline]
110 pub fn milli_amps(&self) -> f64 {
111 self.raw as f64 / 1_000f64
112 }
113
114 #[inline]
116 pub fn amps(&self) -> f64 {
117 self.raw as f64 / 1_000_000f64
118 }
119
120 #[inline]
122 pub const fn is_zero(&self) -> bool {
123 self.raw == 0
124 }
125
126 #[inline]
128 pub const fn zero() -> Self {
129 Self::from_micro_amps(0)
130 }
131}
132
133impl PartialEq for Current {
134 #[inline]
135 fn eq(&self, other: &Self) -> bool {
136 self.raw == other.raw
137 }
138}
139
140impl Eq for Current {}
141
142impl PartialOrd for Current {
143 #[inline]
144 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
145 self.raw.partial_cmp(&other.raw)
146 }
147}
148
149impl Ord for Current {
150 #[inline]
151 fn cmp(&self, other: &Self) -> cmp::Ordering {
152 self.raw.cmp(&other.raw)
153 }
154}
155
156impl ops::Add for Current {
157 type Output = Self;
158
159 #[inline]
161 fn add(self, other: Self) -> Self {
162 self.raw
163 .checked_add(other.raw)
164 .map(Self::from_micro_amps)
165 .expect("Overflow when adding current values")
166 }
167}
168
169impl ops::Sub for Current {
170 type Output = Self;
171
172 #[inline]
174 fn sub(self, other: Self) -> Self {
175 self.raw
176 .checked_sub(other.raw)
177 .map(Self::from_micro_amps)
178 .expect("Overflow when subtracting current values")
179 }
180}
181
182macro_rules! impl_mul_for_integer {
183 ($i:ty) => {
184 impl ops::Mul<$i> for Current {
185 type Output = Self;
186
187 #[inline]
188 #[allow(unused_comparisons)]
189 fn mul(self, scale_factor: $i) -> Self {
190 if scale_factor < 0 {
191 panic!("Cannot multiply current value by negative value")
192 }
193 self.raw
194 .checked_mul(scale_factor as u64)
195 .map(Self::from_micro_amps)
196 .expect("Overflow when multiplying current value")
197 }
198 }
199 };
200}
201
202impl_mul_for_integer!(u8);
203impl_mul_for_integer!(u16);
204impl_mul_for_integer!(u32);
205impl_mul_for_integer!(u64);
206impl_mul_for_integer!(i8);
207impl_mul_for_integer!(i16);
208impl_mul_for_integer!(i32);
209impl_mul_for_integer!(i64);
210
211impl ops::Mul<f32> for Current {
212 type Output = Self;
213
214 #[inline]
216 fn mul(self, scale_factor: f32) -> Self {
217 self * scale_factor as f64
218 }
219}
220
221impl ops::Mul<f64> for Current {
222 type Output = Self;
223
224 #[inline]
226 fn mul(self, scale_factor: f64) -> Self {
227 let result = match scale_factor {
228 _ if scale_factor.is_infinite() => {
229 panic!("Cannot multiply current value by infinity")
230 }
231 _ if scale_factor.is_nan() => panic!("Cannot multiply current value by NaN"),
232 _ if scale_factor.is_sign_negative() => {
233 panic!("Cannot multiply current value by negative value")
234 }
235 _ => self.raw as f64 * scale_factor,
236 };
237
238 Self::from_micro_amps(result as u64)
239 }
240}
241
242macro_rules! impl_div_for_integer {
243 ($i:ty) => {
244 impl ops::Div<$i> for Current {
245 type Output = Self;
246
247 #[inline]
249 #[allow(unused_comparisons)]
250 fn div(self, divisor: $i) -> Self {
251 if divisor == 0 {
252 panic!("Cannot divide current value by zero");
253 } else if divisor < 0 {
254 panic!("Cannot divide current value by negative value");
255 }
256 self.raw
257 .checked_div(divisor as u64)
258 .map(Self::from_micro_amps)
259 .expect("Overflow when dividing current value")
260 }
261 }
262 };
263}
264
265impl_div_for_integer!(u8);
266impl_div_for_integer!(u16);
267impl_div_for_integer!(u32);
268impl_div_for_integer!(u64);
269impl_div_for_integer!(i8);
270impl_div_for_integer!(i16);
271impl_div_for_integer!(i32);
272impl_div_for_integer!(i64);
273
274impl ops::Div<f32> for Current {
275 type Output = Self;
276
277 #[inline]
279 fn div(self, divisor: f32) -> Self {
280 self / divisor as f64
281 }
282}
283
284impl ops::Div<f64> for Current {
285 type Output = Self;
286
287 #[inline]
289 fn div(self, divisor: f64) -> Self {
290 let result = match divisor {
291 _ if divisor == 0f64 => panic!("Cannot divide current value by zero"),
292 _ if divisor.is_infinite() => {
293 panic!("Cannot divide current value by infinity")
294 }
295 _ if divisor.is_nan() => panic!("Cannot divide current value by NaN"),
296 _ if divisor.is_sign_negative() => {
297 panic!("Cannot divide current value by negative value")
298 }
299 _ => (self.raw as f64) / divisor,
300 };
301
302 Self::from_micro_amps(result as u64)
303 }
304}
305
306pub trait FromInteger {
308 fn micro_amps(self) -> Current;
310
311 fn milli_amps(self) -> Current;
313
314 fn amps(self) -> Current;
316}
317
318macro_rules! impl_current_from_integer {
319 ($i:ty) => {
320 impl FromInteger for $i {
321 #[inline]
322 fn micro_amps(self) -> Current {
323 Current::from_micro_amps(self as u64)
324 }
325
326 #[inline]
327 fn milli_amps(self) -> Current {
328 let milliamps = (self as u64)
329 .checked_mul(1_000)
330 .expect("Overflow when converting milliamps to microamps");
331 Current::from_micro_amps(milliamps)
332 }
333
334 #[inline]
335 fn amps(self) -> Current {
336 let milliamps = (self as u64)
337 .checked_mul(1_000_000)
338 .expect("Overflow when converting amps to microamps");
339 Current::from_micro_amps(milliamps)
340 }
341 }
342 };
343}
344
345impl_current_from_integer!(u8);
346impl_current_from_integer!(u16);
347impl_current_from_integer!(u32);
348impl_current_from_integer!(u64);
349impl_current_from_integer!(i8);
350impl_current_from_integer!(i16);
351impl_current_from_integer!(i32);
352impl_current_from_integer!(i64);
353
354pub trait FromFloat {
356 fn micro_amps(self) -> Current;
360
361 fn milli_amps(self) -> Current;
365
366 fn amps(self) -> Current;
370}
371
372macro_rules! impl_current_from_float {
373 ($f:ty) => {
374 impl FromFloat for $f {
375 #[inline]
376 fn micro_amps(self) -> Current {
377 assert_positive_float!(self);
378 Current::from_micro_amps(self as u64)
379 }
380
381 #[inline]
382 fn milli_amps(self) -> Current {
383 assert_positive_float!(self);
384 let milliamps = (self as f64) * 1_000f64;
385 Current::from_micro_amps(milliamps as u64)
386 }
387
388 #[inline]
389 fn amps(self) -> Current {
390 assert_positive_float!(self);
391 let milliamps = (self as f64) * 1_000_000f64;
392 Current::from_micro_amps(milliamps as u64)
393 }
394 }
395 };
396}
397
398impl_current_from_float!(f32);
399impl_current_from_float!(f64);
400
401impl fmt::Display for Current {
402 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403 let (value, unit) = match self.raw {
404 0..=999 => (self.raw as f64, "μA"),
405 1_000..=999_999 => ((self.raw as f64) / 1_000f64, "mA"),
406 _ => ((self.raw as f64) / 1_000_000f64, "A"),
407 };
408
409 write!(f, "{value:.2} {unit}")
410 }
411}