#[macro_export]
macro_rules! units {
(
$(
$(#[$meta:meta])*
$name:ident : $dim:ty {
symbol: $sym:ident
$(, display: $disp:literal)?
$(, scale: $sn:literal $(/ $sd:literal)?)?
$(, offset: $on:literal $(/ $od:literal)?)?
$(, prefixes: $pfx:ident)?
$(,)?
}
),* $(,)?
) => {
$(
$crate::__private::paste! {
$(#[$meta])*
pub enum [<$name:camel>] {}
impl $crate::unit::UnitDef for [<$name:camel>] {
type Dim = $dim;
const SCALE_NUM: i128 = $crate::unit::reduce_num(
$crate::__danwi_ratio_num!($($sn $(/ $sd)?)?),
$crate::__danwi_ratio_den!($($sn $(/ $sd)?)?),
);
const SCALE_DEN: i128 = $crate::unit::reduce_den(
$crate::__danwi_ratio_num!($($sn $(/ $sd)?)?),
$crate::__danwi_ratio_den!($($sn $(/ $sd)?)?),
);
const OFFSET_NUM: i128 = $crate::__danwi_offset_num!($($on $(/ $od)?)?);
const OFFSET_DEN: i128 = $crate::__danwi_offset_den!($($on $(/ $od)?)?);
const SYMBOL: &'static str = $crate::__danwi_symbol_str!($sym $(, $disp)?);
}
const _: () = assert!(
<[<$name:camel>] as $crate::unit::UnitDef>::OFFSET_DEN > 0,
"unit offset denominator must be positive",
);
$crate::__danwi_validate_prefixes! { ($($pfx)?) }
$crate::__danwi_if_all! { ($($pfx)?)
impl $crate::unit::prefix::Prefixable for [<$name:camel>] {}
const _: () = assert!(
<[<$name:camel>] as $crate::unit::UnitDef>::OFFSET_NUM == 0,
"`prefixes: all` requires a zero-offset unit",
);
}
}
)*
pub mod constants {
#![allow(non_upper_case_globals)]
use super::*;
$(
$crate::__private::paste! {
pub const $sym: $crate::unit::Unit<[<$name:camel>]> =
$crate::unit::Unit::new();
}
$crate::__danwi_if_all! { ($($pfx)?)
$crate::__danwi_per_prefix! { const [$name $sym] }
}
)*
}
pub mod types {
pub use super::*;
$crate::__danwi_if_f32! {
pub mod f32 {
pub use super::*;
$(
$crate::__private::paste! {
pub type [<$name:camel>] = $crate::Quantity<
f32,
<super::super::[<$name:camel>] as $crate::unit::UnitDef>::Dim,
>;
}
)*
}
}
$crate::__danwi_if_f64! {
pub mod f64 {
pub use super::*;
$(
$crate::__private::paste! {
pub type [<$name:camel>] = $crate::Quantity<
f64,
<super::super::[<$name:camel>] as $crate::unit::UnitDef>::Dim,
>;
}
)*
}
}
}
pub mod ext {
#![allow(non_snake_case)]
use super::{constants::*, *};
$crate::__danwi_if_f32! {
pub trait F32QuantityExt {
$( $crate::__danwi_ext_decl! { ($($pfx)?) f32, $name, $sym } )*
}
impl F32QuantityExt for f32 {
$( $crate::__danwi_ext_impl! { ($($pfx)?) f32, $name, $sym } )*
}
}
$crate::__danwi_if_f64! {
pub trait F64QuantityExt {
$( $crate::__danwi_ext_decl! { ($($pfx)?) f64, $name, $sym } )*
}
impl F64QuantityExt for f64 {
$( $crate::__danwi_ext_impl! { ($($pfx)?) f64, $name, $sym } )*
}
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_ratio_num {
() => {
1
};
($n:literal) => {
$n
};
($n:literal / $d:literal) => {
$n
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_ratio_den {
() => {
1
};
($n:literal) => {
1
};
($n:literal / $d:literal) => {
$d
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_offset_num {
() => {
0
};
($n:literal) => {
$n
};
($n:literal / $d:literal) => {
$n
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_offset_den {
() => {
1
};
($n:literal) => {
1
};
($n:literal / $d:literal) => {
$d
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_symbol_str {
($sym:ident) => {
stringify!($sym)
};
($sym:ident, $disp:literal) => {
$disp
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_validate_prefixes {
(()) => {};
((all)) => {};
((none)) => {};
(($bad:ident)) => {
compile_error!(concat!(
"`prefixes` must be `all` or `none`, got `",
stringify!($bad),
"`",
));
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_if_all {
(() $($body:tt)*) => {};
((none) $($body:tt)*) => {};
((all) $($body:tt)*) => { $($body)* };
(($bad:ident) $($body:tt)*) => {}; }
#[cfg(feature = "f32")]
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_if_f32 {
($($body:tt)*) => { $($body)* };
}
#[cfg(not(feature = "f32"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_if_f32 {
($($body:tt)*) => {};
}
#[cfg(feature = "f64")]
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_if_f64 {
($($body:tt)*) => { $($body)* };
}
#[cfg(not(feature = "f64"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_if_f64 {
($($body:tt)*) => {};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_per_prefix {
($kind:ident [$($ctx:tt)*]) => {
$crate::__danwi_prefix_item! { $kind [$($ctx)*] Q quetta Quetta }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] R ronna Ronna }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] Y yotta Yotta }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] Z zetta Zetta }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] E exa Exa }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] P peta Peta }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] T tera Tera }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] G giga Giga }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] M mega Mega }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] k kilo Kilo }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] h hecto Hecto }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] da deca Deca }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] d deci Deci }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] c centi Centi }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] m milli Milli }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] u micro Micro }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] n nano Nano }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] p pico Pico }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] f femto Femto }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] atto atto Atto }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] z zepto Zepto }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] y yocto Yocto }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] r ronto Ronto }
$crate::__danwi_prefix_item! { $kind [$($ctx)*] q quecto Quecto }
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_prefix_item {
(const [$name:ident $sym:ident] $psym:ident $pname:ident $ptype:ident) => {
$crate::__private::paste! {
pub const [<$psym $sym>]: $crate::unit::Unit<
$crate::unit::prefix::$ptype<[<$name:camel>]>,
> = $crate::unit::Unit::new();
}
};
(decl [$fl:ty, $name:ident $sym:ident] $psym:ident $pname:ident $ptype:ident) => {
$crate::__private::paste! {
fn [<$psym $sym>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>;
fn [<$pname $name:lower>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>;
}
};
(impl [$fl:ty, $name:ident $sym:ident] $psym:ident $pname:ident $ptype:ident) => {
$crate::__private::paste! {
#[inline(always)]
fn [<$psym $sym>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>
{
self * [<$psym $sym>]
}
#[inline(always)]
fn [<$pname $name:lower>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>
{
self * [<$psym $sym>]
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_ext_decl {
(() $fl:ty, $name:ident, $sym:ident) => {
$crate::__danwi_ext_decl! { (none) $fl, $name, $sym }
};
((none) $fl:ty, $name:ident, $sym:ident) => {
$crate::__private::paste! {
fn [<$name:lower>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>;
}
};
((all) $fl:ty, $name:ident, $sym:ident) => {
$crate::__private::paste! {
fn $sym(self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>;
fn [<$name:lower>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>;
}
$crate::__danwi_per_prefix! { decl [$fl, $name $sym] }
};
(($bad:ident) $fl:ty, $name:ident, $sym:ident) => {};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __danwi_ext_impl {
(() $fl:ty, $name:ident, $sym:ident) => {
$crate::__danwi_ext_impl! { (none) $fl, $name, $sym }
};
((none) $fl:ty, $name:ident, $sym:ident) => {
$crate::__private::paste! {
#[inline(always)]
fn [<$name:lower>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>
{
self * $sym
}
}
};
((all) $fl:ty, $name:ident, $sym:ident) => {
$crate::__private::paste! {
#[inline(always)]
fn $sym(self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>
{
self * $sym
}
#[inline(always)]
fn [<$name:lower>](self)
-> $crate::Quantity<$fl, <[<$name:camel>] as $crate::unit::UnitDef>::Dim>
{
self * $sym
}
}
$crate::__danwi_per_prefix! { impl [$fl, $name $sym] }
};
(($bad:ident) $fl:ty, $name:ident, $sym:ident) => {};
}