use std::collections::HashMap;
use std::sync::Arc;
use crate::scope::ScopeGuard;
use crate::storage;
use crate::value::ContextValue;
#[derive(Clone)]
pub struct ContextSnapshot {
pub(crate) values: Arc<HashMap<&'static str, Box<dyn ContextValue>>>,
pub(crate) scope_chain: Vec<String>,
}
impl ContextSnapshot {
pub fn empty() -> Self {
Self {
values: Arc::new(HashMap::new()),
scope_chain: Vec::new(),
}
}
pub fn scope_chain(&self) -> &[String] {
&self.scope_chain
}
}
impl Default for ContextSnapshot {
fn default() -> Self {
Self::empty()
}
}
pub fn snapshot() -> ContextSnapshot {
let values = storage::collect_values();
let scope_chain = storage::collect_scope_chain();
ContextSnapshot {
values: Arc::new(values),
scope_chain,
}
}
pub fn attach(snap: ContextSnapshot) -> ScopeGuard {
let guard = storage::enter_scope();
if !snap.scope_chain.is_empty() {
storage::set_remote_chain(snap.scope_chain.clone());
}
for (key, val) in snap.values.iter() {
storage::set_value(key, val.clone_boxed());
}
guard
}
pub fn wrap_with_context<F, T>(f: F) -> impl FnOnce() -> T + Send
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
let snap = snapshot();
move || {
let _guard = attach(snap);
f()
}
}
pub fn wrap_with_context_fn<F, T>(f: F) -> impl Fn() -> T + Send + Sync
where
F: Fn() -> T + Send + Sync + 'static,
T: Send + 'static,
{
let snap = snapshot();
move || {
let _guard = attach(snap.clone());
f()
}
}