use std::mem::replace;
use std::ops::{Index, IndexMut};
#[derive(Clone, Debug)]
enum Node<T> {
Vacant(Option<usize>),
Occupied(T),
}
impl<T> Node<T> {
fn expect_vacant(&self) -> Option<usize> {
match *self {
Node::Vacant(next) => next,
Node::Occupied(_) => panic!("Node is occupied"),
}
}
fn expect_occupied(self) -> T {
match self {
Node::Vacant(_) => panic!("Node is vacant"),
Node::Occupied(value) => value,
}
}
fn free(&mut self, next: Option<usize>) -> Option<T> {
match *self {
Node::Vacant(_) => return None,
_ => {}
};
Some(replace(self, Node::Vacant(next)).expect_occupied())
}
}
#[derive(Clone, Debug)]
pub struct VecList<T> {
free: Option<usize>,
data: Vec<Node<T>>,
}
impl<T> Default for VecList<T> {
fn default() -> Self {
VecList::new()
}
}
impl<T> VecList<T> {
pub fn new() -> Self {
VecList {
free: None,
data: Vec::new(),
}
}
pub fn with_capacity(cap: usize) -> Self {
VecList {
free: None,
data: Vec::with_capacity(cap),
}
}
pub fn push(&mut self, value: T) -> usize {
if let Some(free) = self.free {
debug_assert!(free < self.data.len());
let old = replace(&mut self.data[free], Node::Occupied(value));
replace(&mut self.free, old.expect_vacant()).unwrap()
} else {
self.data.push(Node::Occupied(value));
self.data.len() - 1
}
}
pub fn pop(&mut self, index: usize) -> Option<T> {
if index > self.data.len() {
None
} else {
self.data[index].free(self.free).map(|value| {
self.free = Some(index);
value
})
}
}
pub fn get(&self, index: usize) -> Option<&T> {
self.data.get(index).and_then(|node| match *node {
Node::Vacant(_) => None,
Node::Occupied(ref value) => Some(value),
})
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.data.get_mut(index).and_then(|node| match *node {
Node::Vacant(_) => None,
Node::Occupied(ref mut value) => Some(value),
})
}
pub fn upper_bound(&self) -> usize {
self.data.len()
}
}
impl<T> Index<usize> for VecList<T> {
type Output = T;
fn index(&self, index: usize) -> &T {
self.get(index).expect("Expect occupied")
}
}
impl<T> IndexMut<usize> for VecList<T> {
fn index_mut(&mut self, index: usize) -> &mut T {
self.get_mut(index).expect("Expect occupied")
}
}
#[cfg(test)]
mod tests {
use VecList;
#[test]
fn test_push() {
let mut veclist = VecList::new();
for i in 0..10 {
veclist.push(i);
}
for i in 0..10 {
assert_eq!(veclist.get(i), Some(&i));
}
}
#[test]
fn test_pop() {
let mut veclist = VecList::new();
for i in 0..10 {
veclist.push(i);
}
for i in 0..5 {
assert_eq!(veclist.pop(i), Some(i));
}
for i in 0..5 {
assert_eq!(veclist.get(i), None);
}
for i in 6..10 {
assert_eq!(veclist[i], i);
}
}
#[test]
fn test_reuse() {
let mut veclist = VecList::new();
for i in 0..10 {
veclist.push(i);
}
for i in 0..5 {
assert_eq!(veclist.pop(i), Some(i));
}
for i in 0..5 {
veclist.push(i + 10);
}
for i in 0..5 {
assert_eq!(veclist[i], 14 - i);
}
}
}