1use core::{hash::BuildHasherDefault, marker::PhantomData, mem, mem::ManuallyDrop, ptr};
8
9use bumpalo::Bump;
10use hashbrown::HashMap;
11use rustc_hash::FxHasher;
12use type_key::TypeKey;
13
14#[derive(Debug)]
15pub struct RawStore<'a> {
17 map: HashMap<TypeKey, ManuallyDealloc, BuildHasherDefault<FxHasher>>,
18
19 bump: ManuallyDrop<Bump>,
20 _phantom: PhantomData<&'a ()>,
21}
22
23impl<'a> RawStore<'a> {
24 pub fn new() -> Self {
25 Self {
26 map: HashMap::default(),
27
28 bump: ManuallyDrop::new(Bump::new()),
29 _phantom: PhantomData,
30 }
31 }
32
33 pub fn get<T: 'a>(&self, key: &TypeKey) -> Option<*const T> {
34 Some(self.map.get(key)?.ptr().cast::<T>())
35 }
36
37 pub fn insert<T: 'a>(&mut self, key: TypeKey, value: T) -> *const T {
41 let value =
43 unsafe { ManuallyDealloc(mem::transmute(self.bump.alloc(value) as &mut dyn Erased)) };
44 let ptr = value.ptr();
45
46 self.map.insert(key, value);
47
48 ptr.cast::<T>()
49 }
50
51 pub fn reset(&mut self) {
52 self.map.clear();
53 self.bump.reset();
54 }
55}
56
57impl Default for RawStore<'_> {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl Drop for RawStore<'_> {
64 fn drop(&mut self) {
65 self.map.clear();
66
67 unsafe { ManuallyDrop::drop(&mut self.bump) }
69 }
70}
71
72trait Erased {}
73impl<T> Erased for T {}
74
75#[derive(Debug)]
76#[repr(transparent)]
77struct ManuallyDealloc(*mut dyn Erased);
83
84impl ManuallyDealloc {
85 pub const fn ptr(&self) -> *const dyn Erased {
86 self.0.cast_const()
87 }
88}
89
90impl Drop for ManuallyDealloc {
91 fn drop(&mut self) {
92 unsafe { ptr::drop_in_place(self.0) }
94 }
95}