Files
physical/src/quantity/mod.rs
2024-11-12 12:37:32 -08:00

169 lines
4.7 KiB
Rust

mod irradiance;
mod resistance;
mod temperature;
mod voltage;
mod volume_rate;
mod pressure;
#[cfg(feature = "defmt")]
pub use defmt_impl::*;
pub use irradiance::*;
pub use resistance::*;
pub use temperature::*;
pub use voltage::*;
pub use volume_rate::*;
pub use pressure::*;
use core::fmt::Display;
use core::marker::PhantomData;
use core::ops::{Add, Sub};
use num_traits::{FromPrimitive, Num, NumCast};
const DECA: u8 = 10;
const DECI: u8 = 10;
const HECTO: u8 = 100;
const CENTI: u8 = 100;
const KILO: u16 = 1_000;
const MILLI: u16 = 1_000;
const MEGA: u32 = 1_000_000;
const MICRO: u32 = 1_000_000;
const GIGA: u32 = 1_000_000_000;
const NANO: u32 = 1_000_000_000;
pub trait Quantity<V: Value>: Copy + PartialEq + PartialOrd + Add + Sub {
fn value(self) -> V;
fn symbol() -> &'static str;
/// Returns a wrapper that implements [Display] and [defmt::Format] for [Quantity]s with core number values.
///
/// - `rounding` - Sets the number of decimal places to round to when formatting (currently ignored with defmt).
#[inline(always)]
fn fmt(self, rounding: Option<usize>) -> Fmt<V, Self> {
Fmt::new(self, rounding)
}
}
pub trait Value: Num + Copy + PartialOrd + FromPrimitive + NumCast + Display {}
impl<V> Value for V where V: Num + Copy + PartialOrd + FromPrimitive + NumCast + Display {}
#[derive(Copy, Clone)]
pub struct Fmt<V: Value, Q: Quantity<V>> {
quantity: Q,
rounding: Option<usize>,
_phantom: PhantomData<V>,
}
impl<V: Value, Q: Quantity<V>> Fmt<V, Q> {
#[inline(always)]
fn new(quantity: Q, rounding: Option<usize>) -> Self {
Self {
quantity,
rounding,
_phantom: PhantomData,
}
}
}
impl<V: Value, Q: Quantity<V>> Display for Fmt<V, Q> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.rounding {
Some(places) => {
write!(f, "{:.prec$} {}", self.quantity.value(), Q::symbol(), prec = places)
},
None => write!(f, "{} {}", self.quantity.value(), Q::symbol()),
}
}
}
#[cfg(feature = "defmt")]
mod defmt_impl {
use super::*;
use defmt::{write, Format, Formatter};
impl<Q: Quantity<u8>> Format for Fmt<u8, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<u16>> Format for Fmt<u16, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<u32>> Format for Fmt<u32, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<u64>> Format for Fmt<u64, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<u128>> Format for Fmt<u128, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<usize>> Format for Fmt<usize, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<i8>> Format for Fmt<i8, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<i16>> Format for Fmt<i16, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<i32>> Format for Fmt<i32, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<i64>> Format for Fmt<i64, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<i128>> Format for Fmt<i128, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<isize>> Format for Fmt<isize, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<f32>> Format for Fmt<f32, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
impl<Q: Quantity<f64>> Format for Fmt<f64, Q> {
fn format(&self, fmt: Formatter) {
write!(fmt, "{} {}", self.quantity.value(), Q::symbol());
}
}
}