Diffstat (limited to 'tests/common/mod.rs')
| -rw-r--r-- | tests/common/mod.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..8b9fb03 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,83 @@ +#![allow(unused)] + +use core::{ + any::{Any, TypeId}, + ops::Deref, +}; +use std::{ + collections::HashMap, + sync::{Mutex, MutexGuard, OnceLock, RwLock}, +}; + +pub mod builder; +pub mod protocol; + +pub struct StaticTypeMap { + map: OnceLock<RwLock<HashMap<TypeId, &'static (dyn Any + Send + Sync)>>>, +} + +impl StaticTypeMap { + pub const fn new() -> Self { + Self { + map: OnceLock::new(), + } + } + + pub fn get_or_init<T: Send + Sync + 'static, F: FnOnce() -> T>(&self, f: F) -> &'static T { + let map_init = || RwLock::new(HashMap::new()); + + let map = self.map.get_or_init(map_init).read().unwrap(); + + if let Some(once) = map.get(&TypeId::of::<T>()) { + return once.downcast_ref::<T>().unwrap(); + } + + drop(map); + + let mut map = self.map.get_or_init(map_init).write().unwrap(); + let once = &*Box::leak(Box::new(f())); + map.insert(TypeId::of::<T>(), once); + + once + } +} + +pub struct ContextLock<T> { + lock: Mutex<T>, + checkpoint: fn(&T), +} + +impl<T> ContextLock<T> { + pub const fn new(context: T, checkpoint: fn(&T)) -> Self { + Self { + lock: Mutex::new(context), + checkpoint, + } + } + + pub fn lock(&self) -> ContextGuard<'_, T> { + ContextGuard { + lock: self, + guard: self.lock.lock().unwrap(), + } + } +} + +pub struct ContextGuard<'a, T> { + lock: &'a ContextLock<T>, + guard: MutexGuard<'a, T>, +} + +impl<'a, T> Drop for ContextGuard<'a, T> { + fn drop(&mut self) { + (self.lock.checkpoint)(&*self.guard) + } +} + +impl<'a, T> Deref for ContextGuard<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.guard + } +} |