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 pub fn clone() -> $data_type {
24 $context_name.with(|ctx| ctx.borrow().clone())
25 }
26
27 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}