danwi 0.4.2

Zero-cost dimensional analysis library with SI units, compile-time checking, and no_std support
Documentation
//! Kinds distinguish quantities whose dimensions coincide but whose
//! meanings differ (torque vs energy, both M·L²·T⁻²).
//!
//! Every quantity has a kind; the default [`Anon`] is invisible and behaves
//! exactly like a crate without kinds. A named kind only mixes with itself:
//! adding torque to torque works, adding torque to energy does not compile,
//! and multiplication requires erasing the kind first with
//! [`erase_kind`](crate::Quantity::erase_kind). Enter a kind explicitly with
//! [`cast_kind`](crate::Quantity::cast_kind):
//!
//! ```
//! use danwi::{kind::Torque, prelude::*};
//!
//! let torque = (50.0.N() * 0.4.m()).cast_kind::<Torque>();
//! assert_eq!(torque + torque, (40.0.J()).cast_kind());
//! assert_eq!(torque.erase_kind(), 20.0.J());
//! ```
//!
//! Custom kinds are declared with [`kinds!`](crate::kinds):
//!
//! ```
//! danwi::kinds! {
//!     /// Radioactive activity (Bq), distinguished from frequency.
//!     Activity;
//! }
//!
//! use danwi::{Quantity, dimension::Frequency, prelude::*};
//!
//! let decay: Quantity<f64, Frequency, Activity> = (37.0.kHz()).cast_kind();
//! assert_eq!((decay + decay).value(), 74_000.0);
//! ```

/// Kind arithmetic for `+`. `Lhs + Rhs` is only defined for kind pairs that
/// implement this; the output kind is the associated type.
pub trait KindAdd<Rhs = Self> {
    type Output;
}

/// Kind arithmetic for `-`.
pub trait KindSub<Rhs = Self> {
    type Output;
}

/// Kind arithmetic for `*`. Only [`Anon`] multiplies; named kinds must be
/// erased first.
pub trait KindMul<Rhs = Self> {
    type Output;
}

/// Kind arithmetic for `/`.
pub trait KindDiv<Rhs = Self> {
    type Output;
}

/// The anonymous kind: the default for every quantity, with unrestricted
/// arithmetic. Quantities only leave it via
/// [`cast_kind`](crate::Quantity::cast_kind).
pub enum Anon {}

impl KindAdd for Anon {
    type Output = Anon;
}
impl KindSub for Anon {
    type Output = Anon;
}
impl KindMul for Anon {
    type Output = Anon;
}
impl KindDiv for Anon {
    type Output = Anon;
}

/// Declare kinds: zero-sized markers that add and subtract with themselves
/// and nothing else.
///
/// ```
/// danwi::kinds! {
///     /// Moment of force (N·m), distinguished from energy.
///     Torque;
/// }
/// ```
#[macro_export]
macro_rules! kinds {
    ($($(#[$meta:meta])* $name:ident);* $(;)?) => {
        $(
            $(#[$meta])*
            pub enum $name {}

            impl $crate::kind::KindAdd for $name {
                type Output = $name;
            }

            impl $crate::kind::KindSub for $name {
                type Output = $name;
            }
        )*
    };
}

crate::kinds! {
    /// Moment of force (N·m), distinguished from energy.
    Torque;
}