use std::collections::binary_heap::BinaryHeap;
use std::ops::{Index, IndexMut};
#[derive(PartialEq, Eq, Copy, Clone, Hash)]
pub struct Handle { pub val : usize }
impl ::std::cmp::Ord for Handle {
fn cmp(&self, other : &Handle) -> ::std::cmp::Ordering {
if self.val > other.val { ::std::cmp::Ordering::Less }
else if self.val < other.val { ::std::cmp::Ordering::Greater }
else { ::std::cmp::Ordering::Equal }
}
}
impl ::std::cmp::PartialOrd for Handle {
fn partial_cmp(&self, other : &Handle) -> Option<::std::cmp::Ordering> {
Some(self.cmp(other))
}
}
pub struct HandleTable<T> {
slots: Vec<Option<T>>,
num_active: usize,
free_ids : BinaryHeap<Handle>,
}
impl <T> HandleTable<T> {
pub fn new() -> HandleTable<T> {
HandleTable { slots : Vec::new(),
num_active: 0,
free_ids : BinaryHeap::new() }
}
pub fn remove(&mut self, handle: Handle) -> Option<T> {
let result = ::std::mem::replace(&mut self.slots[handle.val], None);
if !result.is_none() {
self.free_ids.push(handle);
}
self.num_active -= 1;
return result;
}
pub fn push(&mut self, val: T) -> Handle {
self.num_active += 1;
match self.free_ids.pop() {
Some(Handle { val: id }) => {
assert!(self.slots[id as usize].is_none());
self.slots[id as usize] = Some(val);
Handle { val: id }
}
None => {
self.slots.push(Some(val));
Handle { val: self.slots.len() - 1 }
}
}
}
pub fn len(&self) -> usize {
self.num_active
}
}
impl<T> Index<Handle> for HandleTable<T> {
type Output = T;
fn index<'a>(&'a self, idx: Handle) -> &'a T {
match &self.slots[idx.val] {
&Some(ref v) => return v,
&None => panic!("invalid handle idx: {}", idx.val),
}
}
}
impl<T> IndexMut<Handle> for HandleTable<T> {
fn index_mut<'a>(&'a mut self, idx: Handle) -> &'a mut T {
match &mut self.slots[idx.val] {
&mut Some(ref mut v) => return v,
&mut None => panic!("invalid handle idx: {}", idx.val),
}
}
}