use std::fmt::Debug;
use std::ops::Deref;
use std::sync::Arc;
use arcref::ArcRef;
use parking_lot::RwLock;
use vortex_error::VortexExpect;
use vortex_utils::aliases::dash_map::DashMap;
pub type Id = ArcRef<str>;
#[derive(Clone, Debug)]
pub struct Registry<T>(Arc<DashMap<Id, T>>);
impl<T> Default for Registry<T> {
fn default() -> Self {
Self(Default::default())
}
}
impl<T: Clone> Registry<T> {
pub fn empty() -> Self {
Self(Default::default())
}
pub fn ids(&self) -> impl Iterator<Item = Id> + '_ {
self.0.iter().map(|i| i.key().clone())
}
pub fn items(&self) -> impl Iterator<Item = T> + '_ {
self.0.iter().map(|i| i.value().clone())
}
pub fn find_many<'a>(
&self,
ids: impl IntoIterator<Item = &'a Id>,
) -> impl Iterator<Item = Option<impl Deref<Target = T>>> {
ids.into_iter().map(|id| self.0.get(id))
}
pub fn find(&self, id: &Id) -> Option<T> {
self.0.get(id).as_deref().cloned()
}
pub fn register(&self, id: impl Into<Id>, item: impl Into<T>) {
self.0.insert(id.into(), item.into());
}
pub fn with(self, id: impl Into<Id>, item: impl Into<T>) -> Self {
self.register(id, item.into());
self
}
}
#[derive(Clone, Debug)]
pub struct ReadContext {
ids: Arc<[Id]>,
}
impl ReadContext {
pub fn new(ids: impl Into<Arc<[Id]>>) -> Self {
Self { ids: ids.into() }
}
pub fn resolve(&self, idx: u16) -> Option<Id> {
self.ids.get(idx as usize).cloned()
}
pub fn ids(&self) -> &[Id] {
&self.ids
}
}
#[derive(Clone, Debug)]
pub struct Context<T> {
ids: Arc<RwLock<Vec<Id>>>,
registry: Option<Registry<T>>,
}
impl<T> Default for Context<T> {
fn default() -> Self {
Self {
ids: Arc::new(RwLock::new(Vec::new())),
registry: None,
}
}
}
impl<T: Clone> Context<T> {
pub fn new(ids: Vec<Id>) -> Self {
Self {
ids: Arc::new(RwLock::new(ids)),
registry: None,
}
}
pub fn empty() -> Self {
Self::default()
}
pub fn with_registry(mut self, registry: Registry<T>) -> Self {
self.registry = Some(registry);
self
}
pub fn intern(&self, id: &Id) -> Option<u16> {
if let Some(registry) = &self.registry
&& registry.find(id).is_none()
{
return None;
}
let mut ids = self.ids.write();
if let Some(idx) = ids.iter().position(|e| e == id) {
return Some(u16::try_from(idx).vortex_expect("Cannot have more than u16::MAX items"));
}
let idx = ids.len();
assert!(
idx < u16::MAX as usize,
"Cannot have more than u16::MAX items"
);
ids.push(id.clone());
Some(u16::try_from(idx).vortex_expect("checked already"))
}
pub fn to_ids(&self) -> Vec<Id> {
self.ids.read().clone()
}
}