use crate::{
ShallowClone,
core::{DefaultStore, SEAL, store::Store},
};
use super::{
QueryResult, QueryResultDistinct,
index::{Index, Insert, Remove, Update},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Key {
id: u64,
}
impl Key {
pub fn unsafe_from_u64(id: u64) -> Self {
Key { id }
}
pub fn as_u64(&self) -> u64 {
self.id
}
}
#[derive(Clone)]
pub struct Collection<In, Ix, S = DefaultStore<In>> {
index: Ix,
data: S,
next_key_id: u64,
_marker: core::marker::PhantomData<fn() -> In>,
}
impl<In, Ix> Collection<In, Ix> {
pub fn new(ix: Ix) -> Self
where
In: 'static,
Ix: Index<In>,
DefaultStore<In>: Store<In>,
{
Collection::new_with_empty_store(ix)
}
}
impl<In, Ix, S> ShallowClone for Collection<In, Ix, S>
where
In: Clone,
Ix: ShallowClone,
S: ShallowClone,
{
}
impl<In, Ix, S: Default> Collection<In, Ix, S> {
pub fn new_with_empty_store(ix: Ix) -> Self {
Collection {
data: S::default(),
next_key_id: 0,
index: ix,
_marker: core::marker::PhantomData,
}
}
}
impl<In, Ix, S> Collection<In, Ix, S>
where
S: Store<In>,
In: 'static,
Ix: Index<In>,
{
pub fn new_with_store(store: S, mut ix: Ix) -> Self {
let mut max_key_id = 0;
for (k, v) in store.iter() {
max_key_id = max_key_id.max(k.id);
ix.insert(SEAL, &Insert { key: k, new: v });
}
Collection {
data: store,
next_key_id: max_key_id + 1,
index: ix,
_marker: core::marker::PhantomData,
}
}
}
impl<In, Ix, S> Collection<In, Ix, S> {
pub fn store(&self) -> &S {
&self.data
}
pub fn extract_store(self) -> S {
self.data
}
pub fn unsafe_mut_store(&mut self) -> &mut S {
&mut self.data
}
}
impl<In, Ix, S> Collection<In, Ix, S>
where
In: 'static,
Ix: Index<In>,
S: Store<In>,
{
pub fn get_by_key(&self, key: Key) -> Option<&In> {
self.data.get(key)
}
pub fn insert(&mut self, value: In) -> Key {
let key = self.mk_key();
let existing = self.data.insert(key, value);
debug_assert!(existing.is_none());
self.index.insert(
SEAL,
&Insert {
key,
new: self.data.get_unwrapped(key),
},
);
key
}
pub fn insert_all<I>(&mut self, iter: I)
where
I: Iterator<Item = In>,
{
for item in iter {
self.insert(item);
}
}
pub fn iter(&self) -> impl Iterator<Item = (Key, &In)> {
self.data.iter()
}
pub fn update_by_key_mut<F>(&mut self, key: Key, f: F)
where
F: FnOnce(&mut Option<In>),
{
let mut existing = self.delete_by_key(key);
f(&mut existing);
if let Some(existing) = existing {
self.data.insert(key, existing);
self.index.insert(
SEAL,
&Insert {
key,
new: self.data.get_unwrapped(key),
},
);
}
}
pub fn update_by_key<F>(&mut self, key: Key, f: F)
where
F: FnOnce(Option<&In>) -> In,
{
let existing = self.data.get(key);
let new = f(existing);
match existing {
Some(existing) => {
self.index.update(
SEAL,
&Update {
key,
new: &new,
existing,
},
);
self.data.insert(key, new);
}
None => {
self.index.insert(SEAL, &Insert { key, new: &new });
self.data.insert(key, new);
}
};
}
pub fn adjust_by_key_mut<F>(&mut self, key: Key, f: F)
where
F: FnOnce(&mut In),
{
if let Some(mut existing) = self.delete_by_key(key) {
f(&mut existing);
self.data.insert(key, existing);
self.index.insert(
SEAL,
&Insert {
key,
new: self.data.get_unwrapped(key),
},
);
}
}
pub fn adjust_by_key<F>(&mut self, key: Key, f: F)
where
F: FnOnce(&In) -> In,
{
if let Some(existing) = self.data.get(key) {
let new = f(existing);
self.index.update(
SEAL,
&Update {
key,
new: &new,
existing,
},
);
self.data.insert(key, new);
}
}
pub fn delete_by_key(&mut self, key: Key) -> Option<In> {
let existing = self.data.remove(key);
if let Some(ref existing) = existing {
self.index.remove(SEAL, &Remove { key, existing });
}
existing
}
pub fn query<Res>(&self, f: impl FnOnce(&Ix) -> Res) -> Res::Resolved<&In>
where
Res: QueryResult,
{
let res = f(&self.index);
res.map(|k| self.data.get_unwrapped(k))
}
pub fn query_keys<Res>(&self, f: impl FnOnce(&Ix) -> Res) -> Res::Resolved<Key>
where
Res: QueryResult,
{
let res = f(&self.index);
res.map(|k| k)
}
pub fn query_with_keys<Res>(&self, f: impl FnOnce(&Ix) -> Res) -> Res::Resolved<(Key, &In)>
where
Res: QueryResult,
{
let res = f(&self.index);
res.map(|k| (k, self.data.get_unwrapped(k)))
}
pub fn delete<Res>(&mut self, f: impl FnOnce(&Ix) -> Res) -> usize
where
Res: QueryResult,
{
let mut affected_count = 0;
let res = f(&self.index);
res.map(|key| {
self.delete_by_key(key);
affected_count += 1;
});
affected_count
}
pub fn update<Res, F>(
&mut self,
f: impl FnOnce(&Ix) -> Res,
update_fn: impl Fn(&In) -> In,
) -> Res::Resolved<()>
where
Res: QueryResultDistinct,
{
let res = f(&self.index);
res.map(|key| {
self.data.update(key, |existing| {
let new = update_fn(existing);
self.index.update(
SEAL,
&Update {
key,
new: &new,
existing,
},
);
new
});
})
}
pub fn take<Res>(&mut self, f: impl FnOnce(&Ix) -> Res) -> Res::Resolved<In>
where
Res: QueryResultDistinct,
{
let res = f(&self.index);
res.map(|k| self.delete_by_key(k).unwrap())
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
fn mk_key(&mut self) -> Key {
let k = Key {
id: self.next_key_id,
};
self.next_key_id += 1;
k
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_len() {
let mut collection = Collection::new(());
assert_eq!(collection.len(), 0);
collection.insert(1);
assert_eq!(collection.len(), 1);
collection.insert(2);
assert_eq!(collection.len(), 2);
let key = collection.insert(3);
assert_eq!(collection.len(), 3);
collection.delete_by_key(key);
assert_eq!(collection.len(), 2);
}
}