summaryrefslogtreecommitdiffstats
path: root/src/macros.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/macros.rs')
-rw-r--r--src/macros.rs205
1 files changed, 205 insertions, 0 deletions
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<f64> 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<f64> 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<f64> 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<f64> 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