1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
use std::{
any::{Any, TypeId},
collections::HashMap,
ops::Deref,
};
#[cfg(test)]
mod tests;
/// A shared state storage for use in [`crate::Handler`] trait implementations.
#[derive(Debug, Default)]
pub struct Context {
items: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
}
impl Context {
/// Returns an immutable reference to the value of type `T`.
pub fn get<T: 'static>(&self) -> Option<&T> {
self.items
.get(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast_ref())
}
/// Inserts a value of type `T` into the context.
///
/// # Arguments
///
/// * `value` - The value to insert.
///
/// Returns a previously inserted value if it exists.
pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) -> Option<T> {
self.items
.insert(TypeId::of::<T>(), Box::new(value))
.and_then(|boxed| <Box<dyn Any + 'static>>::downcast(boxed).ok().map(|boxed| *boxed))
}
}
/// A link to a value of type `T` stored in the [`Context`].
///
/// The link implements [`crate::TryFromInput`] trait,
/// enabling you to use `Ref<T>` as the type of an argument in your
/// [`crate::Handler`] trait implementations.
///
/// Keep in mind that each time a handler is called with `Ref<T>` as an argument,
/// the underlying value is cloned.
#[derive(Clone)]
pub struct Ref<T: Clone>(T);
impl<T: Clone> Ref<T> {
pub(super) fn new(object: T) -> Self {
Self(object)
}
}
impl<T: Clone> Deref for Ref<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}