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}