pub mod error;
mod value;
mod registry;
mod scope;
mod storage;
mod snapshot;
mod wire;
mod helpers;
#[cfg(feature = "context-key")]
mod context_key;
mod config;
#[cfg(feature = "context-future")]
mod context_future;
#[macro_use]
mod macros;
pub use error::ContextError;
pub use scope::ScopeGuard;
pub use snapshot::ContextSnapshot;
#[cfg(feature = "context-key")]
pub use context_key::ContextKey;
pub use registry::{RegistryBuilder, RegistrationOptions,
initialize, try_initialize};
#[cfg(test)]
pub(crate) use registry::{register, try_register, register_with, try_register_with,
register_local, try_register_local,
register_migration, try_register_migration};
pub use storage::{enter_scope, scope, force_thread_local};
#[cfg(feature = "tokio")]
pub use storage::scope_async;
pub use snapshot::{snapshot, attach, wrap_with_context, wrap_with_context_fn};
pub use helpers::spawn_with_context;
#[cfg(feature = "tokio")]
pub use helpers::{with_context, spawn_with_context_async};
#[cfg(feature = "context-future")]
pub use context_future::{ContextFuture, with_context_future};
pub use wire::{serialize_context, deserialize_context, make_wire_bytes};
#[cfg(feature = "base64")]
pub use wire::{serialize_context_string, deserialize_context_string};
pub use config::{set_max_context_size, max_context_size};
use std::any::TypeId;
pub fn get_context<T>(key: &'static str) -> T
where
T: Clone + Default + Send + Sync + 'static,
{
try_get_context::<T>(key)
.expect("dcontext::get_context: key not registered")
.unwrap_or_default()
}
pub fn try_get_context<T>(key: &'static str) -> Result<Option<T>, ContextError>
where
T: Clone + Default + Send + Sync + 'static,
{
let boxed = storage::get_value(key);
match boxed {
Some(val) => {
let any_ref = val.as_any();
match any_ref.downcast_ref::<T>() {
Some(typed) => Ok(Some(typed.clone())),
None => {
let registered_name =
registry::with_registration(key, |r| r.type_name).unwrap_or("unknown");
Err(ContextError::TypeMismatch(
key.to_string(),
registered_name.to_string(),
std::any::type_name::<T>().to_string(),
))
}
}
}
None => {
match registry::with_registration(key, |r| (r.type_id, r.type_name)) {
None => Err(ContextError::NotRegistered(key.to_string())),
Some((tid, type_name)) if tid != TypeId::of::<T>() => {
Err(ContextError::TypeMismatch(
key.to_string(),
type_name.to_string(),
std::any::type_name::<T>().to_string(),
))
}
Some(_) => Ok(None),
}
}
}
}
pub fn set_context<T>(key: &'static str, value: T)
where
T: Clone + Send + Sync + serde::Serialize + serde::de::DeserializeOwned + 'static,
{
try_set_context(key, value).expect("dcontext::set_context failed");
}
pub fn try_set_context<T>(key: &'static str, value: T) -> Result<(), ContextError>
where
T: Clone + Send + Sync + serde::Serialize + serde::de::DeserializeOwned + 'static,
{
match registry::with_registration(key, |r| (r.type_id, r.type_name)) {
None => return Err(ContextError::NotRegistered(key.to_string())),
Some((tid, type_name)) if tid != TypeId::of::<T>() => {
return Err(ContextError::TypeMismatch(
key.to_string(),
type_name.to_string(),
std::any::type_name::<T>().to_string(),
));
}
Some(_) => {}
}
storage::set_value(key, Box::new(value));
Ok(())
}
pub fn set_context_local<T>(key: &'static str, value: T)
where
T: Clone + Send + Sync + 'static,
{
try_set_context_local(key, value).expect("dcontext::set_context_local failed");
}
pub fn try_set_context_local<T>(key: &'static str, value: T) -> Result<(), ContextError>
where
T: Clone + Send + Sync + 'static,
{
match registry::with_registration(key, |r| (r.type_id, r.type_name)) {
None => return Err(ContextError::NotRegistered(key.to_string())),
Some((tid, type_name)) if tid != TypeId::of::<T>() => {
return Err(ContextError::TypeMismatch(
key.to_string(),
type_name.to_string(),
std::any::type_name::<T>().to_string(),
));
}
Some(_) => {}
}
storage::set_value(key, Box::new(crate::value::LocalValue(value)));
Ok(())
}
#[cfg(test)]
mod tests;