use std::{marker::PhantomData, vec};
use uuid::Uuid;
pub use cursor::*;
pub use error::*;
use crate::entity::Entity;
use crate::serializer::Serializer;
use crate::storage::{self, Storage};
mod cursor;
mod error;
#[derive(Debug, Clone)]
pub struct Collection<T, S, R> {
storage: S,
_t: PhantomData<T>,
_r: PhantomData<R>,
}
impl<T, S, R> Collection<T, S, R>
where T: Entity,
S: Storage,
R: Serializer {
pub fn new(storage: S) -> Self {
Self {
storage,
_t: PhantomData,
_r: PhantomData,
}
}
pub fn find(&self, id: Uuid) -> Result<T> {
let reader = self.storage.read(id)?;
Ok(R::deserialize(reader)?)
}
pub fn find_all(&self) -> Result<CollectionCursor<T, S, S::Iterator, R>> {
CollectionCursor::new(&self.storage)
}
pub fn insert(&mut self, entity: &mut T) -> Result<()> {
let (id, writer) = self.storage.new()?;
let old_id = entity.id(); entity.set_id(Some(id));
match R::serialize(writer, entity) {
Ok(_) => Ok(()),
Err(e) => {
entity.set_id(old_id); Err(e.into())
}
}
}
pub fn update(&mut self, entity: &T) -> Result<()> {
let id = entity.id().ok_or(CollectionError::unidentified())?;
let writer = self.storage.overwrite(id)?;
Ok(R::serialize(writer, entity)?)
}
pub fn upsert(&mut self, entity: &T) -> Result<()> {
let id = entity.id().ok_or(CollectionError::unidentified())?;
let writer = self.storage.write(id)?;
Ok(R::serialize(writer, entity)?)
}
pub fn delete(&mut self, id: Uuid) -> Result<bool> {
Ok(self.storage.delete(id)?)
}
pub fn clear(&mut self) -> Result<()> {
Ok(self.storage.clear()?)
}
}
#[derive(Debug)]
pub struct CollectionCursor<'a, T, S, I, R> {
storage: &'a S,
iterator: I,
_t: PhantomData<T>,
_r: PhantomData<R>,
}
impl<'a, T, S, R> CollectionCursor<'a, T, S, S::Iterator, R>
where T: Entity,
S: Storage,
R: Serializer {
fn new(storage: &'a S) -> Result<Self> {
let iterator = storage.iter()?;
Ok(Self {
storage,
iterator,
_t: PhantomData,
_r: PhantomData,
})
}
#[inline]
pub fn shuffled(self) -> CollectionCursor<'a, T, S, vec::IntoIter<storage::Result<Uuid>>, R> {
use rand::seq::SliceRandom;
let Self { storage, iterator, .. } = self;
let mut entries: Vec<storage::Result<Uuid>> = iterator.collect();
entries.shuffle(&mut rand::thread_rng());
CollectionCursor {
storage,
iterator: entries.into_iter(),
_t: PhantomData,
_r: PhantomData,
}
}
}
impl<'a, T, S, I, R> Cursor for CollectionCursor<'a, T, S, I, R>
where T: Entity,
S: Storage,
I: Iterator<Item=storage::Result<Uuid>>,
R: Serializer {
type Item = T;
#[inline]
fn next(&mut self) -> Result<Option<Self::Item>> {
let Self { storage, iterator, .. } = self;
let into_entity = |result: storage::Result<Uuid>| -> Result<Self::Item> {
result
.map_err(From::from)
.and_then(|id| {
storage.read(id).map_err(From::from)
})
.and_then(|reader| {
R::deserialize(reader).map_err(From::from)
})
};
let ignore_not_found = |result: &Result<Self::Item>| -> bool {
match result {
Err(e) if e.is_not_found() => false,
_ => true
}
};
iterator
.next()
.map(into_entity)
.filter(ignore_not_found)
.transpose()
}
}