use std::{marker::PhantomData, sync::Arc};
use parking_lot::RwLock;
use super::{blocks::Blocks, Handle};
#[derive(Debug)]
pub struct Store<T> {
inner: StoreInner<T>,
}
impl<T> Store<T> {
pub fn new() -> Self {
let block_size = 16384;
Self {
inner: Arc::new(RwLock::new(Blocks::new(block_size))),
}
}
pub fn insert(&self, object: T) -> Handle<T> {
let mut blocks = self.inner.write();
let ptr = blocks.push(object);
Handle {
store: self.inner.clone(),
ptr,
}
}
pub fn iter(&self) -> Iter<T> {
Iter {
store: self.inner.clone(),
next_block: 0,
next_object: 0,
_a: PhantomData,
}
}
pub fn reserve(&self) -> Reservation<T> {
let mut blocks = self.inner.write();
let (index, ptr) = blocks.reserve();
Reservation {
store: self.inner.clone(),
index,
ptr,
}
}
}
impl<T> Default for Store<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T> IntoIterator for &'a Store<T> {
type Item = Handle<T>;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct Iter<'a, T> {
store: StoreInner<T>,
next_block: usize,
next_object: usize,
_a: PhantomData<&'a ()>,
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = Handle<T>;
fn next(&mut self) -> Option<Self::Item> {
let blocks = self.store.read();
let block = blocks.get(self.next_block)?;
let object = block.get(self.next_object);
self.next_object += 1;
if self.next_object >= block.len() {
self.next_block += 1;
}
Some(Handle {
store: self.store.clone(),
ptr: object,
})
}
}
pub struct Reservation<T> {
store: StoreInner<T>,
ptr: *mut Option<T>,
index: (usize, usize),
}
impl<T> Reservation<T> {
pub fn handle(&self) -> Handle<T> {
Handle {
store: self.store.clone(),
ptr: self.ptr,
}
}
pub fn complete(self, object: T) -> Handle<T> {
let mut blocks = self.store.write();
let ptr = blocks.insert(self.index, object);
Handle {
store: self.store.clone(),
ptr,
}
}
}
pub type StoreInner<T> = Arc<RwLock<Blocks<T>>>;
#[cfg(test)]
mod tests {
use super::Store;
#[test]
fn insert_and_handle() {
let store = Store::new();
let object = 0;
let handle = store.insert(object);
assert_eq!(*handle, object);
}
#[test]
fn insert_and_iter() {
let store = Store::new();
let a = store.insert(0);
let b = store.insert(1);
let objects = store.iter().collect::<Vec<_>>();
assert_eq!(objects, [a, b])
}
#[test]
fn reserve() {
let store = Store::<i32>::new();
let a = store.reserve();
let b = store.reserve();
let id_a = a.handle().id();
let id_b = b.handle().id();
assert_ne!(id_a, id_b);
let a = a.complete(0);
let b = b.complete(1);
assert_eq!(*a, 0);
assert_eq!(*b, 1);
let objects = store.iter().collect::<Vec<_>>();
assert_eq!(objects, [a, b]);
}
}