use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::slice::{Iter, IterMut};
use slog;
#[derive(Debug, Serialize, Deserialize)]
pub struct ObjPoolIndex<T> {
i: usize,
type_marker: PhantomData<T>
}
impl<T> Copy for ObjPoolIndex<T> { }
impl<T> Clone for ObjPoolIndex<T> {
fn clone(&self) -> ObjPoolIndex<T> {
*self
}
}
impl<T> PartialEq for ObjPoolIndex<T> {
fn eq(&self, other: &ObjPoolIndex<T>) -> bool {
self.i == other.i
}
}
impl<T> Eq for ObjPoolIndex<T> { }
impl<T> Hash for ObjPoolIndex<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.i.hash(state);
}
}
impl<T> ObjPoolIndex<T> {
pub fn get_raw_i(&self) -> usize {
self.i
}
}
impl<T> slog::Value for ObjPoolIndex<T> {
fn serialize(&self, _record: &slog::Record, key: slog::Key, serializer: &mut dyn slog::Serializer) -> slog::Result {
serializer.emit_usize(key, self.i)
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct ObjPool<T> {
storage: Vec<T>
}
impl<T> ObjPool<T> {
pub fn new() -> ObjPool<T> {
ObjPool {storage: Vec::new()}
}
pub fn insert(&mut self, item: T) -> ObjPoolIndex<T> {
let i = self.storage.len();
self.storage.push(item);
ObjPoolIndex::<T> {i: i, type_marker: PhantomData}
}
pub fn get(&self, i: ObjPoolIndex<T>) -> &T {
&self.storage[i.i]
}
pub fn get_mut(&mut self, i: ObjPoolIndex<T>) -> &mut T {
&mut self.storage[i.i]
}
pub fn iter_idx(&self) -> ObjPoolIdxIterator<T> {
ObjPoolIdxIterator {
pool: self,
current_idx: 0,
}
}
pub fn iter(&self) -> Iter<T> {
self.storage.iter()
}
pub fn iter_mut(&mut self) -> IterMut<T> {
self.storage.iter_mut()
}
pub fn iter_mut_idx(&mut self) -> ObjPoolMutIdxIterator<T> {
ObjPoolMutIdxIterator {
inner_iter: self.storage.iter_mut(),
current_idx: 0,
}
}
pub fn len(&self) -> usize {
self.storage.len()
}
}
impl<T: Default> ObjPool<T> {
pub fn alloc(&mut self) -> ObjPoolIndex<T> {
let i = self.storage.len();
let o = T::default();
self.storage.push(o);
ObjPoolIndex::<T> {i: i, type_marker: PhantomData}
}
}
pub struct ObjPoolIdxIterator<'a, T: 'a> {
pool: &'a ObjPool<T>,
current_idx: usize,
}
impl<'a, T> Iterator for ObjPoolIdxIterator<'a, T> {
type Item = ObjPoolIndex<T>;
fn next(&mut self) -> Option<ObjPoolIndex<T>> {
if self.current_idx == self.pool.storage.len() {
None
} else {
let ret = ObjPoolIndex::<T> {i: self.current_idx, type_marker: PhantomData};
self.current_idx += 1;
Some(ret)
}
}
}
pub struct ObjPoolMutIdxIterator<'a, T: 'a> {
inner_iter: IterMut<'a, T>,
current_idx: usize,
}
impl<'a, T> Iterator for ObjPoolMutIdxIterator<'a, T> {
type Item = (ObjPoolIndex<T>, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
let next = self.inner_iter.next();
match next {
None => None,
Some(x) => {
let ret = ObjPoolIndex::<T> {i: self.current_idx, type_marker: PhantomData};
self.current_idx += 1;
Some((ret, x))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Default)]
struct ObjPoolTestObject {
foo: u32
}
#[test]
fn objpool_basic_works() {
let mut pool = ObjPool::<ObjPoolTestObject>::new();
let x = pool.alloc();
let y = pool.alloc();
{
let o = pool.get_mut(x);
o.foo = 123;
}
{
let o = pool.get_mut(y);
o.foo = 456;
}
let ox = pool.get(x);
let oy = pool.get(y);
assert_eq!(ox.foo, 123);
assert_eq!(oy.foo, 456);
}
}