From 3e4fb93a594f11a80904653396698d6c70e07cb0 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Sat, 31 Oct 2020 20:44:44 +0100 Subject: Initial public release --- src/macros.rs | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/macros.rs (limited to 'src/macros.rs') diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..f6925a0 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,205 @@ +#[macro_export] +macro_rules! declare_simple_unit { + ($unit_enum:ident, $si_unit:ident, $si_symbol:literal) => { + #[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] + pub enum $unit_enum { + Base(f64, fn(f64) -> f64, &'static str), + Canonical(f64), + $si_unit(f64) + } + + impl Unit<$unit_enum> for $unit_enum { + fn to_si_unit(&self) -> $unit_enum { + match self { + $unit_enum::Base(_, _, _) => self.clone(), + $unit_enum::Canonical(value) => $unit_enum::Base(value.clone(), |x| x, $si_symbol), + $unit_enum::$si_unit(value) => $unit_enum::Base(value.clone(), |x| x, $si_symbol), + } + } + } + + declare_unit_basics!($unit_enum); + }; +} + +#[macro_export] +macro_rules! declare_unit_basics { + ($unit_enum:ident) => { + impl Primitive for $unit_enum { + fn to_si_primitive(&self) -> f64 { + match self.to_si_unit() { + $unit_enum::Base(value, _, _) => value, + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl Add for $unit_enum { + type Output = $unit_enum; + + fn add(self, rhs: Self) -> Self::Output { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => $unit_enum::Base(value + rhs.to_si_primitive(), from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl AddAssign for $unit_enum { + fn add_assign(&mut self, rhs: Self) { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => *self = $unit_enum::Base(value + rhs.to_si_primitive(), from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl Sub for $unit_enum { + type Output = $unit_enum; + + fn sub(self, rhs: Self) -> Self::Output { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => $unit_enum::Base(value - rhs.to_si_primitive(), from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl SubAssign for $unit_enum { + fn sub_assign(&mut self, rhs: Self) { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => *self = $unit_enum::Base(value - rhs.to_si_primitive(), from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl Mul<$unit_enum> for f64 { + type Output = $unit_enum; + + fn mul(self, rhs: $unit_enum) -> Self::Output { + match rhs.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => $unit_enum::Base(self * value, from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl Mul for $unit_enum { + type Output = $unit_enum; + + fn mul(self, rhs: f64) -> Self::Output { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => $unit_enum::Base(value * rhs, from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl MulAssign for $unit_enum { + fn mul_assign(&mut self, rhs: f64) { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => *self = $unit_enum::Base(rhs * value, from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl Div for $unit_enum { + type Output = $unit_enum; + + fn div(self, rhs: f64) -> Self::Output { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => $unit_enum::Base(value / rhs, from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl DivAssign for $unit_enum { + fn div_assign(&mut self, rhs: f64) { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => *self = $unit_enum::Base(value / rhs, from_si, symbol), + _ => panic!("non si unit post to_si_unit() call"), + } + } + } + + impl Div<$unit_enum> for $unit_enum { + type Output = f64; + + fn div(self, rhs: $unit_enum) -> Self::Output { + self.to_si_primitive() / rhs.to_si_primitive() + } + } + + impl Display for $unit_enum { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self.to_si_unit() { + $unit_enum::Base(value, from_si, symbol) => write!(f, "{}[{}]", from_si(value), symbol), + _ => panic!("Display: non si unit post to_si_unit() call"), + } + } + } + + pub use $unit_enum::*; + }; +} + +#[macro_export] +macro_rules! declare_unit_square { + ($base:ident, $product:ident) => { + impl Mul<$base> for $base { + type Output = $product; + + fn mul(self, rhs: $base) -> Self::Output { + $product::Canonical(self.to_si_primitive() * rhs.to_si_primitive()) + } + } + + impl Div<$base> for $product { + type Output = $base; + + fn div(self, rhs: $base) -> Self::Output { + $base::Canonical(self.to_si_primitive() / rhs.to_si_primitive()) + } + } + }; +} + +#[macro_export] +macro_rules! declare_unit_multiplication { + ($factor_a:ident, $factor_b:ident, $product:ident) => { + impl Mul<$factor_a> for $factor_b { + type Output = $product; + + fn mul(self, rhs: $factor_a) -> Self::Output { + $product::Canonical(self.to_si_primitive() * rhs.to_si_primitive()) + } + } + + impl Mul<$factor_b> for $factor_a { + type Output = $product; + + fn mul(self, rhs: $factor_b) -> Self::Output { + $product::Canonical(self.to_si_primitive() * rhs.to_si_primitive()) + } + } + + impl Div<$factor_a> for $product { + type Output = $factor_b; + + fn div(self, rhs: $factor_a) -> Self::Output { + $factor_b::Canonical(self.to_si_primitive() / rhs.to_si_primitive()) + } + } + + impl Div<$factor_b> for $product { + type Output = $factor_a; + + fn div(self, rhs: $factor_b) -> Self::Output { + $factor_a::Canonical(self.to_si_primitive() / rhs.to_si_primitive()) + } + } + }; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf