use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::ops::Deref;
use std::sync::Arc;
use crate::Delivery;
#[derive(Default)]
pub(crate) struct State {
map: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
}
impl State {
pub(crate) fn insert<T: Any + Send + Sync>(&mut self, value: T) {
self.map.insert(TypeId::of::<T>(), Arc::new(value));
}
pub(crate) fn get<T: Any + Send + Sync>(&self) -> Option<&T> {
self.map
.get(&TypeId::of::<T>())
.and_then(|value| value.downcast_ref::<T>())
}
}
pub struct JobContext<'a> {
state: &'a State,
delivery: &'a Delivery,
}
impl<'a> JobContext<'a> {
pub(crate) fn new(state: &'a State, delivery: &'a Delivery) -> Self {
Self { state, delivery }
}
pub fn state<T: Any + Send + Sync>(&self) -> &T {
self.try_state().unwrap_or_else(|| {
panic!(
"no application state of type `{}` registered on the JobRunner",
std::any::type_name::<T>()
)
})
}
pub fn try_state<T: Any + Send + Sync>(&self) -> Option<&T> {
self.state.get::<T>()
}
}
impl Deref for JobContext<'_> {
type Target = Delivery;
fn deref(&self) -> &Delivery {
self.delivery
}
}