pub mod registry;
use std::any::{Any, TypeId, type_name};
use std::fmt::Debug;
use std::hash::{BuildHasherDefault, Hasher};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use dashmap::{DashMap, Entry};
use vortex_error::{VortexExpect, vortex_panic};
#[derive(Clone, Debug)]
pub struct VortexSession(Arc<SessionVars>);
impl VortexSession {
pub fn empty() -> Self {
Self(Default::default())
}
pub fn with<V: SessionVar + Default>(self) -> Self {
match self.0.entry(TypeId::of::<V>()) {
Entry::Occupied(_) => {
vortex_panic!(
"Session variable of type {} already exists",
type_name::<V>()
);
}
Entry::Vacant(e) => {
e.insert(Box::new(V::default()));
}
}
self
}
}
pub trait SessionExt: Sized + private::Sealed {
fn session(&self) -> VortexSession;
fn get<V: SessionVar>(&self) -> Ref<'_, V>;
fn get_mut<V: SessionVar>(&self) -> RefMut<'_, V>;
}
mod private {
pub trait Sealed {}
impl Sealed for super::VortexSession {}
}
impl SessionExt for VortexSession {
fn session(&self) -> VortexSession {
self.clone()
}
fn get<V: SessionVar>(&self) -> Ref<'_, V> {
Ref(self
.0
.get(&TypeId::of::<V>())
.unwrap_or_else(|| {
vortex_panic!("Session has not been initialized with {}", type_name::<V>())
})
.map(|v| {
(**v)
.as_any()
.downcast_ref::<V>()
.vortex_expect("Type mismatch - this is a bug")
}))
}
fn get_mut<V: SessionVar>(&self) -> RefMut<'_, V> {
RefMut(
self.0
.get_mut(&TypeId::of::<V>())
.unwrap_or_else(|| {
vortex_panic!("Session has not been initialized with {}", type_name::<V>())
})
.map(|v| {
(**v)
.as_any_mut()
.downcast_mut::<V>()
.vortex_expect("Type mismatch - this is a bug")
}),
)
}
}
type SessionVars = DashMap<TypeId, Box<dyn SessionVar>, BuildHasherDefault<IdHasher>>;
#[derive(Default)]
struct IdHasher(u64);
impl Hasher for IdHasher {
#[inline]
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, _: &[u8]) {
unreachable!("TypeId calls write_u64");
}
#[inline]
fn write_u64(&mut self, id: u64) {
self.0 = id;
}
}
pub trait SessionVar: Any + Send + Sync + Debug + 'static {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T: Send + Sync + Debug + 'static> SessionVar for T {
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub struct Ref<'a, T>(dashmap::mapref::one::MappedRef<'a, TypeId, Box<dyn SessionVar>, T>);
impl<'a, T> Deref for Ref<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a, T> Ref<'a, T> {
pub fn map<F, U>(self, f: F) -> Ref<'a, U>
where
F: FnOnce(&T) -> &U,
{
Ref(self.0.map(f))
}
}
pub struct RefMut<'a, T>(dashmap::mapref::one::MappedRefMut<'a, TypeId, Box<dyn SessionVar>, T>);
impl<'a, T> Deref for RefMut<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a, T> DerefMut for RefMut<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}
impl<'a, T> RefMut<'a, T> {
pub fn map<F, U>(self, f: F) -> RefMut<'a, U>
where
F: FnOnce(&mut T) -> &mut U,
{
RefMut(self.0.map(f))
}
}