ixa/macros/
define_global_property.rs

1/// Defines a global property with the following parameters:
2/// * `$global_property`: Name for the identifier type of the global property
3/// * `$value`: The type of the property's value
4/// * `$validate`: A function (or closure) that checks the validity of the property and returns
5///   `Result<(), Box<dyn std::error::Error + 'static>>` (optional)
6///
7/// Validator code is client code, so it should create and box its own error values.
8/// Ixa wraps any returned error in
9/// [`IxaError::IllegalGlobalPropertyValue`](crate::error::IxaError::IllegalGlobalPropertyValue)
10/// when the property is set or loaded.
11#[macro_export]
12macro_rules! define_global_property {
13    ($global_property:ident, $value:ty, $validate: expr) => {
14        #[derive(Copy, Clone)]
15        pub struct $global_property;
16
17        impl $crate::global_properties::GlobalProperty for $global_property {
18            type Value = $value;
19
20            fn new() -> Self {
21                $global_property
22            }
23
24            fn name() -> &'static str {
25                let full = std::any::type_name::<Self>();
26                full.rsplit("::").next().unwrap()
27            }
28
29            fn validate(val: &$value) -> Result<(), Box<dyn std::error::Error + 'static>> {
30                $validate(val)
31            }
32        }
33
34        $crate::paste::paste! {
35            $crate::ctor::declarative::ctor!{
36                #[ctor]
37                fn [<$global_property:snake _register>]() {
38                    let module = module_path!();
39                    let mut name = module.split("::").next().unwrap().to_string();
40                    name += ".";
41                    name += stringify!($global_property);
42                    $crate::global_properties::add_global_property::<$global_property>(&name);
43                }
44            }
45        }
46    };
47
48    ($global_property: ident, $value: ty) => {
49        define_global_property!($global_property, $value, |_| { Ok(()) });
50    };
51}