use qecs_core::{
Component, Id, IdWithIndex, Valid, PrimaryIdManager,
IdActivationError, IdActivationResult, IdGenerationError, IdGenerationResult,
_PrimaryIdManager,
};
use num::{Unsigned, NumCast, ToPrimitive, Bounded};
use std::any::Any;
use std::collections::LinkedList;
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
use std::{cmp, iter, slice, mem};
pub trait SimpleIndex: IdWithIndex + From<usize> {}
impl<T> SimpleIndex for T
where T: IdWithIndex + From<usize>
{}
#[derive(RustcEncodable, RustcDecodable)]
#[derive(Debug, Hash, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub struct Index<U>(U);
impl<U, T> From<T> for Index<U>
where
U: Unsigned + NumCast + Bounded + Debug + Hash + Copy + Ord + Any + Send + Sync,
T: Unsigned + ToPrimitive,
{
fn from(val: T) -> Self {
Index(U::from(val).expect("Maximum id count exceeded.")) }
}
impl<U> Component for Index<U>
where U: Unsigned + NumCast + Bounded + Debug + Hash + Copy + Ord + Any + Send + Sync
{}
impl<U> Id for Index<U>
where U: Unsigned + NumCast + Bounded + Debug + Hash + Copy + Ord + Any + Send + Sync
{}
impl<U> IdWithIndex for Index<U>
where U: Unsigned + NumCast + Bounded + Debug + Hash + Copy + Ord + Any + Send + Sync
{
fn max_index() -> usize { U::max_value().to_usize().unwrap() }
fn index(&self) -> usize { self.0.to_usize().unwrap() }
}
pub type Index8 = Index<u8>;
pub type Index16 = Index<u16>;
pub type Index32 = Index<u32>;
pub struct SimpleIndexManager<MID, Extra = ()> {
data: Vec<Option<Extra>>,
freed_indicies: LinkedList<MID>,
}
impl<MID, Extra> Default for SimpleIndexManager<MID, Extra>
where MID: SimpleIndex, Extra: Copy + Any + Send + Sync
{
fn default() -> Self {
SimpleIndexManager {
data: Vec::new(),
freed_indicies: LinkedList::new(),
}
}
}
impl<MID, Extra> SimpleIndexManager<MID, Extra>
where MID: SimpleIndex, Extra: Copy + Eq + Any + Send + Sync
{
fn _len(&self) -> usize {
self.data.len() - self.freed_indicies.len()
}
fn _maximum_id_count(&self) -> usize {
MID::max_index() + 1
}
fn _validate(&self, m_id: MID) -> Option<&Extra> {
match self.data.get(m_id.index()){
Some(&Some(ref extra)) => Some(extra),
_ => None
}
}
fn _invalidate(&mut self, m_id: MID) -> Option<Extra> {
if self._validate(m_id).is_none() { return None }
self.freed_indicies.push_back(m_id);
mem::replace(&mut self.data[m_id.index()], None)
}
fn _generate(&mut self, extra: Extra) -> IdGenerationResult<MID> {
let min_freed_indicies = cmp::min(1024, self._maximum_id_count());
if self.freed_indicies.len() >= min_freed_indicies
|| (!self.freed_indicies.is_empty() && self._len() == self._maximum_id_count())
{
let prev_id = self.freed_indicies.pop_front().unwrap();
self.data[prev_id.index()] = Some(extra);
Ok(prev_id)
} else {
let idx = self.data.len();
if idx >= self._maximum_id_count() {
return Err(IdGenerationError::MaximumIdCountReached(MID::max_index() + 1));
}
self.data.push(Some(extra));
Ok(MID::from(idx))
}
}
fn _activate(&mut self, id: MID, extra: Extra) -> IdActivationResult<(), (MID, Extra)> {
let idx = id.index();
match self.data.get(id.index()) {
Some(&Some(occ_extra)) => if occ_extra == extra {
return Err(IdActivationError::AlreadyActivated)
} else {
return Err(IdActivationError::SlotOccupied((id, occ_extra)))
},
_ => {}
}
if idx < self.data.len() {
let pos = self.freed_indicies.iter().position(|freed_id| {
freed_id.index() == idx
}).unwrap();
let mut tail = self.freed_indicies.split_off(pos);
tail.pop_front();
self.freed_indicies.append(&mut tail);
self.data[idx] = Some(extra)
} else {
if idx >= self._maximum_id_count() {
return Err(IdActivationError::MaximumIdCountReached(MID::max_index() - 1));
}
for idx in self.data.len()..idx {
self.data.push(None);
self.freed_indicies.push_back(MID::from(idx));
}
self.data.push(Some(extra));
}
Ok(())
}
fn _clear(&mut self){
self.data.clear();
self.freed_indicies.clear();
}
}
#[derive(Clone)]
pub struct Iter<'a, MID>
where MID: SimpleIndex,
{
iter: iter::Enumerate<slice::Iter<'a, Option<()>>>,
_phantom: PhantomData<MID>
}
impl<'a, MID> Iterator for Iter<'a, MID>
where MID: SimpleIndex,
{
type Item = Valid<'a, MID>;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
Some((idx, &Some( _))) => unsafe { Some(Valid::new(MID::from(idx))) },
Some((_, &None)) => self.next(),
None => None
}
}
}
impl<'a, MID> _PrimaryIdManager<'a> for SimpleIndexManager<MID>
where MID: SimpleIndex
{
type _Id = MID;
type Iter = Iter<'a, MID>;
}
impl<MID> PrimaryIdManager for SimpleIndexManager<MID>
where MID: SimpleIndex
{
type Id = MID;
fn len(&self) -> usize { self._len() }
fn maximum_id_count(&self) -> usize { self._maximum_id_count() }
fn validate(&self, id: Self::Id) -> Option<Valid<Self::Id>> {
self._validate(id).map(|_| unsafe { Valid::new(id) })
}
unsafe fn invalidate(&mut self, m_id: Self::Id) -> bool {
self._invalidate(m_id).is_some()
}
fn generate(&mut self) -> IdGenerationResult<Valid<Self::Id>> {
let id = try!{self._generate(())};
Ok(self.validate(id).unwrap())
}
fn activate(&mut self, id: Self::Id) -> IdActivationResult<Valid<Self::Id>, Self::Id> {
match self._activate(id, ()) {
Err(IdActivationError::SlotOccupied(_)) => {
return Err(IdActivationError::SlotOccupied(id))
}
Err(err) => { return Err(IdActivationError::from_err(err)); }
Ok(_) => {}
}
Ok(self.validate(id).unwrap())
}
unsafe fn clear(&mut self){ self._clear(); }
fn iter<'a>(&'a self) -> <Self as _PrimaryIdManager<'a>>::Iter {
Iter{ iter: self.data.iter().enumerate(), _phantom: PhantomData }
}
}
impl<'a, MID> IntoIterator for &'a SimpleIndexManager<MID>
where MID: SimpleIndex
{
type Item = <Self::IntoIter as Iterator>::Item;
type IntoIter = Iter<'a, MID>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
#[test]
fn generate_ids(){
let mut ids = SimpleIndexManager::<Index8>::default();
let zero = Index8::from(0u8);
let one = Index8::from(1u8);
assert_eq!(zero, *ids.generate().unwrap());
assert_eq!(one, *ids.generate().unwrap());
assert_eq!(2, ids.len());
assert!(unsafe { ids.invalidate(zero) });
assert_eq!(1, ids.len());
unsafe { ids.clear(); }
assert_eq!(ids.len(), 0);
let mut gens = Vec::new();
for _ in 0..Index8::max_index() + 1 {
gens.push(*ids.generate().unwrap());
}
assert_eq!(
IdGenerationError::MaximumIdCountReached(Index8::max_index() + 1),
ids.generate().unwrap_err()
);
for id in gens {
assert!(unsafe { ids.invalidate(id) });
}
assert_eq!(0, ids.len());
assert_eq!(zero, *ids.generate().unwrap());
}