Migrated from uom to custom quantity implementation.

This commit is contained in:
Zachary Sunforge
2024-07-09 22:37:00 -07:00
parent 8a23429e5f
commit da5fca74ef
15 changed files with 612 additions and 132 deletions

205
src/quantity/mod.rs Normal file
View File

@ -0,0 +1,205 @@
mod irradiance;
mod resistance;
mod temperature;
mod voltage;
mod volume_rate;
#[cfg(feature = "defmt")]
pub use defmt_impl::*;
pub use irradiance::*;
pub use resistance::*;
pub use temperature::*;
pub use voltage::*;
pub use volume_rate::*;
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 {
//----- Temperature ----------------------------------
#[inline(always)]
fn kelvins(self) -> Kelvins<Self> {
Kelvins(self)
}
#[inline(always)]
fn deci_kelvins(self) -> DeciKelvins<Self> {
DeciKelvins(self)
}
#[inline(always)]
fn degrees_celsius(self) -> DegreesCelsius<Self> {
DegreesCelsius(self)
}
#[inline(always)]
fn deci_degrees_celsius(self) -> DeciDegreesCelsius<Self> {
DeciDegreesCelsius(self)
}
//----- Voltage ----------------------------------
#[inline(always)]
fn volts(self) -> Volts<Self> {
Volts(self)
}
#[inline(always)]
fn millivolts(self) -> MilliVolts<Self> {
MilliVolts(self)
}
//----- Resistance ----------------------------------
#[inline(always)]
fn ohms(self) -> Ohms<Self> {
Ohms(self)
}
//----- Volume rate ----------------------------------
#[inline(always)]
fn liters_per_minute(self) -> LitersPerMinute<Self> {
LitersPerMinute(self)
}
//----- Irradiance ----------------------------------
#[inline(always)]
fn watts_per_square_meter(self) -> WattsPerSquareMeter<Self> {
WattsPerSquareMeter(self)
}
}
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<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<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());
}
}
}