deep_bind/
lib.rs

1#[cfg(test)]
2mod tests;
3
4#[macro_export]
5macro_rules! contextual {
6    {$($visibility:vis $interface_name:ident($context_name:ident) : $data_type:ty = $initial_value:expr;)+} =>{
7        $(
8            contextual!($visibility $interface_name($context_name): $data_type = $initial_value);
9        )+
10    };
11
12    ($visibility:vis $interface_name:ident($context_name:ident) : $data_type:ty = $initial_value:expr) => {
13        thread_local! {
14            $visibility static $context_name: std::cell::RefCell<$data_type>
15                = std::cell::RefCell::new($initial_value);
16        }
17
18        $visibility struct $interface_name;
19
20        #[allow(dead_code)]
21        impl $interface_name {
22            /// Get a clone of the current context value.
23            pub fn clone() -> $data_type {
24                $context_name.with(|ctx| ctx.borrow().clone())
25            }
26
27            /// Provide a context value to a function and any functions that it calls.
28            /// After the function returns, the context value is restored to its previous value.
29            pub fn replace_within<ContextZone: FnOnce() -> Ret, Ret>(
30                data: $data_type,
31                f: ContextZone,
32            ) -> Ret {
33                $context_name.with(|ctx| {
34                    let old_data = ctx.replace(data);
35                    let ret = f();
36                    ctx.replace(old_data);
37                    ret
38                })
39            }
40        }
41    };
42}