use std::{marker::PhantomData, sync::Arc};
use parking_lot::RwLock;
use super::{
blocks::{Blocks, Index},
Handle,
};
#[derive(Debug)]
pub struct Store<T> {
inner: StoreInner<T>,
}
impl<T> Store<T> {
pub fn new() -> Self {
Self::with_block_size(16384)
}
pub fn with_block_size(block_size: usize) -> Self {
let inner = Arc::new(RwLock::new(StoreInnerInner {
blocks: Blocks::new(block_size),
}));
Self { inner }
}
pub fn reserve(&self) -> Handle<T> {
let mut inner = self.inner.write();
let (index, ptr) = inner.blocks.reserve();
Handle {
store: self.inner.clone(),
index,
ptr,
}
}
pub fn insert(&mut self, handle: Handle<T>, object: T) {
let mut inner = self.inner.write();
inner.blocks.insert(handle.index, object);
}
pub fn iter(&self) -> Iter<T> {
Iter {
store: self.inner.clone(),
next_index: Index::zero(),
_a: PhantomData,
}
}
}
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_index: Index,
_a: PhantomData<&'a ()>,
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = Handle<T>;
fn next(&mut self) -> Option<Self::Item> {
let inner = self.store.read();
loop {
let index = self.next_index;
let ptr = inner.blocks.get_and_inc(&mut self.next_index)?;
if ptr.is_none() {
continue;
}
return Some(Handle {
store: self.store.clone(),
index,
ptr,
});
}
}
}
pub type StoreInner<T> = Arc<RwLock<StoreInnerInner<T>>>;
#[derive(Debug)]
pub struct StoreInnerInner<T> {
blocks: Blocks<T>,
}
#[cfg(test)]
mod tests {
use crate::storage::Handle;
use super::Store;
#[test]
fn insert_and_handle() {
let mut store = Store::with_block_size(1);
let handle: Handle<i32> = store.reserve();
let object = 0;
store.insert(handle.clone(), object);
assert_eq!(*handle, object);
}
#[test]
fn insert_and_iter() {
let mut store = Store::with_block_size(1);
let a: Handle<i32> = store.reserve();
let b = store.reserve();
store.insert(a.clone(), 0);
store.insert(b.clone(), 1);
let objects = store.iter().collect::<Vec<_>>();
assert_eq!(objects, [a, b]);
}
}