fire_http/
state.rs

1use std::{
2	any::{Any, TypeId},
3	cell::RefCell,
4	collections::{HashMap, HashSet},
5	mem::ManuallyDrop,
6};
7
8pub struct State {
9	inner: HashMap<TypeId, Box<dyn Any + Send>>,
10}
11
12impl State {
13	pub fn new() -> Self {
14		Self {
15			inner: HashMap::new(),
16		}
17	}
18
19	pub fn insert<T>(&mut self, data: T)
20	where
21		T: Any + Send,
22	{
23		self.inner.insert(TypeId::of::<T>(), Box::new(data));
24	}
25
26	pub fn contains<T>(&self) -> bool
27	where
28		T: Any + Send,
29	{
30		self.inner.contains_key(&TypeId::of::<T>())
31	}
32
33	pub fn get<T>(&self) -> Option<&T>
34	where
35		T: Any + Send,
36	{
37		self.inner
38			.get(&TypeId::of::<T>())
39			.map(|b| b.downcast_ref::<T>().unwrap())
40	}
41
42	pub fn remove<T>(&mut self) -> Option<T>
43	where
44		T: Any + Send,
45	{
46		self.inner
47			.remove(&TypeId::of::<T>())
48			.map(|b| *b.downcast::<T>().unwrap())
49	}
50}
51
52pub struct StateValidation {
53	inner: HashSet<TypeId>,
54}
55
56impl StateValidation {
57	pub fn new() -> Self {
58		Self {
59			inner: HashSet::new(),
60		}
61	}
62
63	pub fn insert<T>(&mut self)
64	where
65		T: Any + Send,
66	{
67		self.inner.insert(TypeId::of::<T>());
68	}
69
70	pub fn remove<T>(&mut self)
71	where
72		T: Any + Send,
73	{
74		self.inner.remove(&TypeId::of::<T>());
75	}
76
77	pub fn validate<T>(&self) -> bool
78	where
79		T: Any + Send,
80	{
81		self.inner.contains(&TypeId::of::<T>())
82	}
83}
84
85/// A mutable memory location with dynamically checked borrow rules
86///
87/// This is similar to `RefCell` but instead of returned wrapped
88/// reference, it returns the value directly.
89///
90/// This means that once the value is borrowed to read it will never
91/// get available again.
92#[derive(Debug)]
93pub struct StateRefCell<T> {
94	inner: RefCell<Option<T>>,
95}
96
97impl<T> StateRefCell<T> {
98	pub const fn new(val: T) -> Self {
99		Self {
100			inner: RefCell::new(Some(val)),
101		}
102	}
103
104	/// ## Panics
105	/// Panics if the value is currently borrowed.
106	pub fn replace(&self, val: T) -> Option<T> {
107		self.inner.replace(Some(val))
108	}
109
110	/// ## Panics
111	/// Panics if the value is currently mutably borrowed.
112	pub fn get(&self) -> &T {
113		self.try_get().expect("already mutably borrowed")
114	}
115
116	/// Tries to get the value if it is not currently borrowed.
117	pub fn try_get(&self) -> Option<&T> {
118		let r = self.inner.try_borrow().ok()?;
119
120		if r.is_none() {
121			return None;
122		}
123
124		let r = ManuallyDrop::new(r);
125		// since the borrow counter does not get decreased because of the
126		// ManuallyDrop and the lifetime not getting expanded this is safe
127		let v = unsafe { &*(&**r as *const Option<T>) }.as_ref().unwrap();
128
129		Some(v)
130	}
131
132	/// ## Panics
133	/// Panics if the value is currently borrowed.
134	pub fn get_mut(&self) -> &mut T {
135		let r = self.inner.borrow_mut();
136		let mut r = ManuallyDrop::new(r);
137		// since the borrow counter does not get decreased because of the
138		// ManuallyDrop and the lifetime not getting expanded this is safe
139		unsafe { &mut *(&mut **r as *mut Option<T>) }
140			.as_mut()
141			.expect("already borrowed")
142	}
143
144	/// ## Panics
145	/// Panics if the value is currently borrowed.
146	pub fn take(&mut self) -> T {
147		self.inner.replace(None).expect("already borrowed")
148	}
149
150	pub fn into_inner(self) -> T {
151		self.inner.into_inner().expect("already borrowed")
152	}
153}