use std::{any::Any, hash::Hash, marker::PhantomData, sync::Arc};
use serde::{de::DeserializeOwned, Serialize};
use crate::{
inner::AtomoInner,
serder::SerdeBackend,
table::{ResolvedTableReference, TableSelector},
DefaultSerdeBackend,
};
pub type TableId = u8;
pub struct QueryPerm;
pub struct UpdatePerm;
pub struct Atomo<O, S: SerdeBackend = DefaultSerdeBackend> {
inner: Arc<AtomoInner<S>>,
ownership: PhantomData<O>,
}
impl<S: SerdeBackend> Clone for Atomo<QueryPerm, S> {
fn clone(&self) -> Self {
Self::new(self.inner.clone())
}
}
impl<O, S: SerdeBackend> Atomo<O, S> {
#[inline]
pub(crate) fn new(inner: Arc<AtomoInner<S>>) -> Self {
Self {
inner,
ownership: PhantomData,
}
}
pub fn query(&self) -> Atomo<QueryPerm, S> {
Atomo::new(self.inner.clone())
}
pub fn resolve<K, V>(&self, name: impl AsRef<str>) -> ResolvedTableReference<K, V>
where
K: Hash + Eq + Serialize + DeserializeOwned + Any,
V: Serialize + DeserializeOwned + Any,
{
self.inner.resolve::<K, V>(name)
}
}
impl<S: SerdeBackend> Atomo<QueryPerm, S> {
pub fn run<F, R>(&self, query: F) -> R
where
F: Fn(&mut TableSelector<S>) -> R,
{
let mut selector = TableSelector::new(self.inner.clone());
query(&mut selector)
}
}
impl<S: SerdeBackend> Atomo<UpdatePerm, S> {
pub fn run<F, R>(&mut self, mutation: F) -> R
where
F: Fn(&mut TableSelector<S>) -> R,
{
let mut selector = TableSelector::new(self.inner.clone());
let response = mutation(&mut selector);
let (batch, keys) = selector.into_raw();
let inverse = self.inner.compute_inverse(&batch);
self.inner.snapshot_list.push(inverse, keys, || {
self.inner.perform_batch(batch);
});
response
}
}
mod doc_tests {
fn _ensure_update_perm_not_clone() {}
}