1pub mod registry;
5
6use std::any::Any;
7use std::any::TypeId;
8use std::any::type_name;
9use std::fmt::Debug;
10use std::hash::BuildHasherDefault;
11use std::hash::Hasher;
12use std::ops::Deref;
13use std::ops::DerefMut;
14use std::sync::Arc;
15
16use dashmap::DashMap;
17use dashmap::Entry;
18use vortex_error::VortexExpect;
19use vortex_error::vortex_panic;
20
21#[derive(Clone, Debug)]
26pub struct VortexSession(Arc<SessionVars>);
27
28impl VortexSession {
29 pub fn empty() -> Self {
33 Self(Default::default())
34 }
35
36 pub fn with<V: SessionVar + Default>(self) -> Self {
42 match self.0.entry(TypeId::of::<V>()) {
43 Entry::Occupied(_) => {
44 vortex_panic!(
45 "Session variable of type {} already exists",
46 type_name::<V>()
47 );
48 }
49 Entry::Vacant(e) => {
50 e.insert(Box::new(V::default()));
51 }
52 }
53 self
54 }
55}
56
57pub trait SessionExt: Sized + private::Sealed {
59 fn session(&self) -> VortexSession;
61
62 fn get<V: SessionVar + Default>(&self) -> Ref<'_, V>;
64
65 fn get_opt<V: SessionVar>(&self) -> Option<Ref<'_, V>>;
67
68 fn get_mut<V: SessionVar + Default>(&self) -> RefMut<'_, V>;
72
73 fn get_mut_opt<V: SessionVar>(&self) -> Option<RefMut<'_, V>>;
77}
78
79mod private {
80 pub trait Sealed {}
81 impl Sealed for super::VortexSession {}
82}
83
84impl SessionExt for VortexSession {
85 fn session(&self) -> VortexSession {
86 self.clone()
87 }
88
89 fn get<V: SessionVar + Default>(&self) -> Ref<'_, V> {
91 if let Some(v) = self.0.get(&TypeId::of::<V>()) {
94 return Ref(v.map(|v| {
95 (**v)
96 .as_any()
97 .downcast_ref::<V>()
98 .vortex_expect("Type mismatch - this is a bug")
99 }));
100 }
101
102 Ref(self
104 .0
105 .entry(TypeId::of::<V>())
106 .or_insert_with(|| Box::new(V::default()))
107 .downgrade()
108 .map(|v| {
109 (**v)
110 .as_any()
111 .downcast_ref::<V>()
112 .vortex_expect("Type mismatch - this is a bug")
113 }))
114 }
115
116 fn get_opt<V: SessionVar>(&self) -> Option<Ref<'_, V>> {
117 self.0.get(&TypeId::of::<V>()).map(|v| {
118 Ref(v.map(|v| {
119 (**v)
120 .as_any()
121 .downcast_ref::<V>()
122 .vortex_expect("Type mismatch - this is a bug")
123 }))
124 })
125 }
126
127 fn get_mut<V: SessionVar + Default>(&self) -> RefMut<'_, V> {
131 RefMut(
132 self.0
133 .entry(TypeId::of::<V>())
134 .or_insert_with(|| Box::new(V::default()))
135 .map(|v| {
136 (**v)
137 .as_any_mut()
138 .downcast_mut::<V>()
139 .vortex_expect("Type mismatch - this is a bug")
140 }),
141 )
142 }
143
144 fn get_mut_opt<V: SessionVar>(&self) -> Option<RefMut<'_, V>> {
145 self.0.get_mut(&TypeId::of::<V>()).map(|v| {
146 RefMut(v.map(|v| {
147 (**v)
148 .as_any_mut()
149 .downcast_mut::<V>()
150 .vortex_expect("Type mismatch - this is a bug")
151 }))
152 })
153 }
154}
155
156type SessionVars = DashMap<TypeId, Box<dyn SessionVar>, BuildHasherDefault<IdHasher>>;
158
159#[derive(Default)]
163struct IdHasher(u64);
164
165impl Hasher for IdHasher {
166 #[inline]
167 fn finish(&self) -> u64 {
168 self.0
169 }
170
171 fn write(&mut self, _: &[u8]) {
172 unreachable!("TypeId calls write_u64");
173 }
174
175 #[inline]
176 fn write_u64(&mut self, id: u64) {
177 self.0 = id;
178 }
179}
180
181pub trait SessionVar: Any + Send + Sync + Debug + 'static {
183 fn as_any(&self) -> &dyn Any;
184 fn as_any_mut(&mut self) -> &mut dyn Any;
185}
186
187impl<T: Send + Sync + Debug + 'static> SessionVar for T {
188 fn as_any(&self) -> &dyn Any {
189 self
190 }
191
192 fn as_any_mut(&mut self) -> &mut dyn Any {
193 self
194 }
195}
196
197pub struct Ref<'a, T>(dashmap::mapref::one::MappedRef<'a, TypeId, Box<dyn SessionVar>, T>);
200impl<'a, T> Deref for Ref<'a, T> {
201 type Target = T;
202
203 fn deref(&self) -> &Self::Target {
204 &self.0
205 }
206}
207impl<'a, T> Ref<'a, T> {
208 pub fn map<F, U>(self, f: F) -> Ref<'a, U>
210 where
211 F: FnOnce(&T) -> &U,
212 {
213 Ref(self.0.map(f))
214 }
215}
216
217pub struct RefMut<'a, T>(dashmap::mapref::one::MappedRefMut<'a, TypeId, Box<dyn SessionVar>, T>);
218impl<'a, T> Deref for RefMut<'a, T> {
219 type Target = T;
220
221 fn deref(&self) -> &Self::Target {
222 &self.0
223 }
224}
225impl<'a, T> DerefMut for RefMut<'a, T> {
226 fn deref_mut(&mut self) -> &mut Self::Target {
227 self.0.deref_mut()
228 }
229}
230impl<'a, T> RefMut<'a, T> {
231 pub fn map<F, U>(self, f: F) -> RefMut<'a, U>
233 where
234 F: FnOnce(&mut T) -> &mut U,
235 {
236 RefMut(self.0.map(f))
237 }
238}