macro_rules! define_groups {
($($(#[$attr:meta])*
$vis:vis mod $module:ident ($($import:tt),* $(,)?);)*) => {
$($(#[$attr])*
$vis mod $module {
$(define_groups!(@ $import);)*
})*
};
(@ [$($utype:ident),* $(,)?]) => {
pub use super::types::{$($utype),*};
};
(@ $module:ident) => {
pub use super::$module::units::*;
};
(@ ($group:ident)) => {
pub use super::$group::*;
};
}
macro_rules! define_symbols {
($(
$(#[$attr_mod:meta])*
$vis:vis mod $module:ident // Define module name.
for type $utype:tt // Specify unit type this module focuses on.
$(in mod $parent:ident)? // Specify a "parent" to borrow type aliases from.
$(as $($alias_type:ident),+)? {
$($(type $alias_priv:ident = $upriv:tt;)+)? $($(use $import_from:ident;)+)? $($(#[$attr_const:meta])*
const $alias_const:ident $(: $atype:tt)? = $val:tt;)* }
)*) => {
$(
#[allow(unused_imports)] $vis use self::$module::types::*;
#[allow(unused_imports)] $vis use self::$module::units::*;
#[allow(unused_imports)]
$(#[$attr_mod])*
$vis mod $module {
pub use types::*;
pub use units::*;
pub mod types {
$(pub use super::super::$parent::types::*;)*
$($(pub type $alias_priv = super::super::$upriv;)+)?
$($(
#[doc = concat!(
"Type alias for [`",
stringify!($utype),
"`](super::super::",
stringify!($utype),
")."
)]
pub type $alias_type = super::super::$utype;
)+)?
}
pub mod units {
$($(pub use super::super::$import_from::units::*;)+)?
use super::super::*;
$(define_symbols!(
@ $utype;
$(#[$attr_const])*
$alias_const $(: $atype)? = $val
);)*
}
}
)*
pub mod types {
$($(pub use super::$module::types::{$($alias_type),+};)?)*
}
};
(@ $utype:tt; $(#[$attr:meta])* $alias:ident = $variant:ident) => {
#[doc = concat!(
"Unit alias for [`", stringify!($variant), "`]",
"(super::super::", stringify!($utype), "::", stringify!($variant), ")."
)]
pub const $alias: super::super::$utype = <$utype>::$variant;
};
(@ $utype:tt; $(#[$attr:meta])* $alias:ident = ($($unit:tt)*)) => {
$(#[$attr])*
pub const $alias: super::super::$utype = unit!($($unit)*);
};
(@ $utype:tt; $(#[$attr:meta])* $alias:ident = $value:expr) => {
$(#[$attr])*
pub const $alias: super::super::$utype = $value;
};
(@ $utype:tt; $(#[$attr:meta])* $alias:ident: $atype:tt = $($unit:tt)*) => {
$(#[$attr])*
pub const $alias: utype!($atype) = unit!($($unit)*);
};
}