1pub mod registry;
5
6use std::any::{Any, TypeId, type_name};
7use std::fmt::Debug;
8use std::hash::{BuildHasherDefault, Hasher};
9use std::ops::{Deref, DerefMut};
10use std::sync::Arc;
11
12use dashmap::{DashMap, Entry};
13use vortex_error::{VortexExpect, vortex_panic};
14
15#[derive(Clone, Debug)]
20pub struct VortexSession(Arc<SessionVars>);
21
22impl VortexSession {
23 pub fn empty() -> Self {
27 Self(Default::default())
28 }
29
30 pub fn with<V: SessionVar + Default>(self) -> Self {
36 match self.0.entry(TypeId::of::<V>()) {
37 Entry::Occupied(_) => {
38 vortex_panic!(
39 "Session variable of type {} already exists",
40 type_name::<V>()
41 );
42 }
43 Entry::Vacant(e) => {
44 e.insert(Box::new(V::default()));
45 }
46 }
47 self
48 }
49}
50
51pub trait SessionExt: Sized + private::Sealed {
53 fn session(&self) -> VortexSession;
55
56 fn get<V: SessionVar>(&self) -> Ref<'_, V>;
58
59 fn get_mut<V: SessionVar>(&self) -> RefMut<'_, V>;
63}
64
65mod private {
66 pub trait Sealed {}
67 impl Sealed for super::VortexSession {}
68}
69
70impl SessionExt for VortexSession {
71 fn session(&self) -> VortexSession {
72 self.clone()
73 }
74
75 fn get<V: SessionVar>(&self) -> Ref<'_, V> {
77 Ref(self
78 .0
79 .get(&TypeId::of::<V>())
80 .unwrap_or_else(|| {
81 vortex_panic!("Session has not been initialized with {}", type_name::<V>())
82 })
83 .map(|v| {
84 (**v)
85 .as_any()
86 .downcast_ref::<V>()
87 .vortex_expect("Type mismatch - this is a bug")
88 }))
89 }
90
91 fn get_mut<V: SessionVar>(&self) -> RefMut<'_, V> {
95 RefMut(
96 self.0
97 .get_mut(&TypeId::of::<V>())
98 .unwrap_or_else(|| {
99 vortex_panic!("Session has not been initialized with {}", type_name::<V>())
100 })
101 .map(|v| {
102 (**v)
103 .as_any_mut()
104 .downcast_mut::<V>()
105 .vortex_expect("Type mismatch - this is a bug")
106 }),
107 )
108 }
109}
110
111type SessionVars = DashMap<TypeId, Box<dyn SessionVar>, BuildHasherDefault<IdHasher>>;
113
114#[derive(Default)]
118struct IdHasher(u64);
119
120impl Hasher for IdHasher {
121 #[inline]
122 fn finish(&self) -> u64 {
123 self.0
124 }
125
126 fn write(&mut self, _: &[u8]) {
127 unreachable!("TypeId calls write_u64");
128 }
129
130 #[inline]
131 fn write_u64(&mut self, id: u64) {
132 self.0 = id;
133 }
134}
135
136pub trait SessionVar: Any + Send + Sync + Debug + 'static {
138 fn as_any(&self) -> &dyn Any;
139 fn as_any_mut(&mut self) -> &mut dyn Any;
140}
141
142impl<T: Send + Sync + Debug + 'static> SessionVar for T {
143 fn as_any(&self) -> &dyn Any {
144 self
145 }
146
147 fn as_any_mut(&mut self) -> &mut dyn Any {
148 self
149 }
150}
151
152pub struct Ref<'a, T>(dashmap::mapref::one::MappedRef<'a, TypeId, Box<dyn SessionVar>, T>);
155impl<'a, T> Deref for Ref<'a, T> {
156 type Target = T;
157
158 fn deref(&self) -> &Self::Target {
159 &self.0
160 }
161}
162impl<'a, T> Ref<'a, T> {
163 pub fn map<F, U>(self, f: F) -> Ref<'a, U>
165 where
166 F: FnOnce(&T) -> &U,
167 {
168 Ref(self.0.map(f))
169 }
170}
171
172pub struct RefMut<'a, T>(dashmap::mapref::one::MappedRefMut<'a, TypeId, Box<dyn SessionVar>, T>);
173impl<'a, T> Deref for RefMut<'a, T> {
174 type Target = T;
175
176 fn deref(&self) -> &Self::Target {
177 &self.0
178 }
179}
180impl<'a, T> DerefMut for RefMut<'a, T> {
181 fn deref_mut(&mut self) -> &mut Self::Target {
182 self.0.deref_mut()
183 }
184}
185impl<'a, T> RefMut<'a, T> {
186 pub fn map<F, U>(self, f: F) -> RefMut<'a, U>
188 where
189 F: FnOnce(&mut T) -> &mut U,
190 {
191 RefMut(self.0.map(f))
192 }
193}