#[macro_export]
macro_rules! define_global_property {
($global_property:ident, $value:ty, $validate: expr) => {
#[derive(Copy, Clone)]
pub struct $global_property;
impl $crate::global_properties::GlobalProperty for $global_property {
type Value = $value;
fn id() -> usize {
static INDEX: std::sync::atomic::AtomicUsize =
std::sync::atomic::AtomicUsize::new(usize::MAX);
let index = INDEX.load(std::sync::atomic::Ordering::Relaxed);
if index != usize::MAX {
return index;
}
$crate::global_properties::initialize_global_property_id(&INDEX)
}
fn new() -> Self {
$global_property
}
fn name() -> &'static str {
let full = std::any::type_name::<Self>();
full.rsplit("::").next().unwrap()
}
fn validate(
val: &$value,
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
$validate(val)
}
}
$crate::paste::paste! {
$crate::ctor::declarative::ctor!{
#[ctor(unsafe)]
fn [<$global_property:snake _register>]() {
let module = module_path!();
let mut name = module.split("::").next().unwrap().to_string();
name += ".";
name += stringify!($global_property);
<$global_property as $crate::global_properties::GlobalProperty>::id();
$crate::global_properties::add_global_property::<$global_property>(&name);
}
}
}
};
($global_property: ident, $value: ty) => {
$crate::define_global_property!($global_property, $value, |_| { Ok(()) });
};
}