macro_stateful/
lib.rs

1pub use ctor::ctor;
2use std::sync::Mutex;
3
4#[doc(hidden)]
5pub struct StateFull<T>(Mutex<Option<T>>);
6
7#[doc(hidden)]
8impl<T> StateFull<T> {
9    pub const fn new() -> Self {
10        Self(Mutex::new(None))
11    }
12    pub fn set_value<F: Fn(&mut Option<T>)>(&self, f: F) {
13        let mut data = self.0.lock().unwrap();
14        f(&mut data);
15    }
16
17    pub fn take(&self) -> Option<T> {
18        self.0.lock().unwrap().take()
19    }
20}
21
22#[macro_export]
23macro_rules! take_out {
24    ($id:ident) => {
25        $id::get().take()
26    };
27}
28
29#[macro_export]
30macro_rules! set_state {
31    ($id:ident,$fun:expr) => {
32        const _: () = {
33            #[$crate::ctor]
34            static STATIC_DYNAMIC_CTOR: () = {
35                $id::get().set_value($fun);
36            };
37        };
38    };
39}
40
41#[macro_export]
42macro_rules! define_state {
43    ($id:ident:$typ:ty $(= $init:expr)?) => {
44        #[allow(non_camel_case_types)]
45        struct $id;
46        impl $id {
47            pub fn get() -> &'static $crate::StateFull<$typ> {
48                static SINGLETON: $crate::StateFull<$typ> = $crate::StateFull::new();
49                $(SINGLETON.set_value(|v| {
50                    if v.is_none() {
51                        *v = Some($init);
52                    }
53                });)?
54                &SINGLETON
55            }
56        }
57    };
58}