extern crate unreachable;
use std::fmt;
use std::iter;
use std::mem;
use std::ops::{Index, IndexMut};
use std::ptr;
use std::slice;
use std::vec;
use unreachable::unreachable;
#[derive(Clone)]
enum Slot<T> {
Vacant(usize),
Occupied(T),
}
pub struct Arena<T> {
slots: Vec<Slot<T>>,
len: usize,
head: usize,
}
impl<T> Arena<T> {
#[inline]
pub fn new() -> Self {
Arena {
slots: Vec::new(),
len: 0,
head: !0,
}
}
#[inline]
pub fn with_capacity(cap: usize) -> Self {
Arena {
slots: Vec::with_capacity(cap),
len: 0,
head: !0,
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.slots.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn next_vacant(&mut self) -> usize {
if self.head == !0 {
self.len
} else {
self.head
}
}
#[inline]
pub fn insert(&mut self, object: T) -> usize {
self.len += 1;
if self.head == !0 {
self.slots.push(Slot::Occupied(object));
self.len - 1
} else {
let index = self.head;
match self.slots[index] {
Slot::Vacant(next) => {
self.head = next;
self.slots[index] = Slot::Occupied(object);
},
Slot::Occupied(_) => unreachable!(),
}
index
}
}
#[inline]
pub fn remove(&mut self, index: usize) -> Option<T> {
match self.slots.get_mut(index) {
None => None,
Some(&mut Slot::Vacant(_)) => None,
Some(slot @ &mut Slot::Occupied(_)) => {
if let Slot::Occupied(object) = mem::replace(slot, Slot::Vacant(self.head)) {
self.head = index;
self.len -= 1;
Some(object)
} else {
unreachable!();
}
}
}
}
#[inline]
pub fn clear(&mut self) {
self.slots.clear();
self.len = 0;
self.head = !0;
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
match self.slots.get(index) {
None => None,
Some(&Slot::Vacant(_)) => None,
Some(&Slot::Occupied(ref object)) => Some(object),
}
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
match self.slots.get_mut(index) {
None => None,
Some(&mut Slot::Vacant(_)) => None,
Some(&mut Slot::Occupied(ref mut object)) => Some(object),
}
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
match self.slots.get(index) {
None => unreachable(),
Some(&Slot::Vacant(_)) => unreachable(),
Some(&Slot::Occupied(ref object)) => object,
}
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
match self.slots.get_mut(index) {
None => unreachable(),
Some(&mut Slot::Vacant(_)) => unreachable(),
Some(&mut Slot::Occupied(ref mut object)) => object,
}
}
#[inline]
pub fn swap(&mut self, a: usize, b: usize) {
unsafe {
let fst = self.get_mut(a).unwrap() as *mut _;
let snd = self.get_mut(b).unwrap() as *mut _;
if a != b {
ptr::swap(fst, snd);
}
}
}
pub fn reserve(&mut self, additional: usize) {
let vacant = self.slots.len() - self.len;
if additional > vacant {
self.slots.reserve(additional - vacant);
}
}
pub fn reserve_exact(&mut self, additional: usize) {
let vacant = self.slots.len() - self.len;
if additional > vacant {
self.slots.reserve_exact(additional - vacant);
}
}
#[inline]
pub fn iter(&self) -> Iter<T> {
Iter { slots: self.slots.iter().enumerate() }
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut { slots: self.slots.iter_mut().enumerate() }
}
}
impl<T> fmt::Debug for Arena<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Arena {{ ... }}")
}
}
impl<T> Index<usize> for Arena<T> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &T {
self.get(index).expect("vacant slot at `index`")
}
}
impl<T> IndexMut<usize> for Arena<T> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut T {
self.get_mut(index).expect("vacant slot at `index`")
}
}
impl<T> Default for Arena<T> {
fn default() -> Self {
Arena::new()
}
}
impl<T: Clone> Clone for Arena<T> {
fn clone(&self) -> Self {
Arena {
slots: self.slots.clone(),
len: self.len,
head: self.head,
}
}
}
pub struct IntoIter<T> {
slots: iter::Enumerate<vec::IntoIter<Slot<T>>>,
}
impl<T> Iterator for IntoIter<T> {
type Item = (usize, T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while let Some((index, slot)) = self.slots.next() {
if let Slot::Occupied(object) = slot {
return Some((index, object));
}
}
None
}
}
impl<T> IntoIterator for Arena<T> {
type Item = (usize, T);
type IntoIter = IntoIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter { slots: self.slots.into_iter().enumerate() }
}
}
impl<T> fmt::Debug for IntoIter<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "IntoIter {{ ... }}")
}
}
pub struct Iter<'a, T: 'a> {
slots: iter::Enumerate<slice::Iter<'a, Slot<T>>>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = (usize, &'a T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while let Some((index, slot)) = self.slots.next() {
if let Slot::Occupied(ref object) = *slot {
return Some((index, object));
}
}
None
}
}
impl<'a, T> fmt::Debug for Iter<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Iter {{ ... }}")
}
}
pub struct IterMut<'a, T: 'a> {
slots: iter::Enumerate<slice::IterMut<'a, Slot<T>>>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = (usize, &'a mut T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while let Some((index, slot)) = self.slots.next() {
if let Slot::Occupied(ref mut object) = *slot {
return Some((index, object));
}
}
None
}
}
impl<'a, T> fmt::Debug for IterMut<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "IterMut {{ ... }}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new() {
let arena = Arena::<i32>::new();
assert!(arena.is_empty());
assert_eq!(arena.len(), 0);
assert_eq!(arena.capacity(), 0);
}
#[test]
fn insert() {
let mut arena = Arena::new();
for i in 0..10 {
assert_eq!(arena.insert(i * 10), i);
assert_eq!(arena[i], i * 10);
}
assert!(!arena.is_empty());
assert_eq!(arena.len(), 10);
}
#[test]
fn with_capacity() {
let mut arena = Arena::with_capacity(10);
assert_eq!(arena.capacity(), 10);
for _ in 0..10 {
arena.insert(());
}
assert_eq!(arena.len(), 10);
assert_eq!(arena.capacity(), 10);
arena.insert(());
assert_eq!(arena.len(), 11);
assert!(arena.capacity() > 10);
}
#[test]
fn remove() {
let mut arena = Arena::new();
assert_eq!(arena.insert(0), 0);
assert_eq!(arena.insert(10), 1);
assert_eq!(arena.insert(20), 2);
assert_eq!(arena.insert(30), 3);
assert_eq!(arena.len(), 4);
assert_eq!(arena.remove(1), Some(10));
assert_eq!(arena.remove(2), Some(20));
assert_eq!(arena.len(), 2);
assert!(arena.insert(-1) < 4);
assert!(arena.insert(-1) < 4);
assert_eq!(arena.len(), 4);
assert_eq!(arena.remove(0), Some(0));
assert!(arena.insert(-1) < 4);
assert_eq!(arena.len(), 4);
assert_eq!(arena.insert(400), 4);
assert_eq!(arena.len(), 5);
}
#[test]
fn invalid_remove() {
let mut arena = Arena::new();
for i in 0..10 {
arena.insert(i.to_string());
}
assert_eq!(arena.remove(7), Some("7".to_string()));
assert_eq!(arena.remove(5), Some("5".to_string()));
assert_eq!(arena.remove(!0), None);
assert_eq!(arena.remove(10), None);
assert_eq!(arena.remove(11), None);
assert_eq!(arena.remove(5), None);
assert_eq!(arena.remove(7), None);
}
#[test]
fn clear() {
let mut arena = Arena::new();
arena.insert(10);
arena.insert(20);
assert!(!arena.is_empty());
assert_eq!(arena.len(), 2);
let cap = arena.capacity();
arena.clear();
assert!(arena.is_empty());
assert_eq!(arena.len(), 0);
assert_eq!(arena.capacity(), cap);
}
#[test]
fn indexing() {
let mut arena = Arena::new();
let a = arena.insert(10);
let b = arena.insert(20);
let c = arena.insert(30);
arena[b] += arena[c];
assert_eq!(arena[a], 10);
assert_eq!(arena[b], 50);
assert_eq!(arena[c], 30);
}
#[test]
#[should_panic]
fn indexing_vacant() {
let mut arena = Arena::new();
let _ = arena.insert(10);
let b = arena.insert(20);
let _ = arena.insert(30);
arena.remove(b);
arena[b];
}
#[test]
#[should_panic]
fn invalid_indexing() {
let mut arena = Arena::new();
arena.insert(10);
arena.insert(20);
arena.insert(30);
arena[100];
}
#[test]
fn get() {
let mut arena = Arena::new();
let a = arena.insert(10);
let b = arena.insert(20);
let c = arena.insert(30);
*arena.get_mut(b).unwrap() += *arena.get(c).unwrap();
assert_eq!(arena.get(a), Some(&10));
assert_eq!(arena.get(b), Some(&50));
assert_eq!(arena.get(c), Some(&30));
arena.remove(b);
assert_eq!(arena.get(b), None);
assert_eq!(arena.get_mut(b), None);
}
#[test]
fn reserve() {
let mut arena = Arena::new();
arena.insert(1);
arena.insert(2);
arena.reserve(10);
assert!(arena.capacity() >= 11);
}
#[test]
fn reserve_exact() {
let mut arena = Arena::new();
arena.insert(1);
arena.insert(2);
arena.reserve(10);
assert!(arena.capacity() >= 11);
}
#[test]
fn iter() {
let mut arena = Arena::new();
let a = arena.insert(10);
let b = arena.insert(20);
let c = arena.insert(30);
let d = arena.insert(40);
arena.remove(b);
let mut it = arena.iter();
assert_eq!(it.next(), Some((a, &10)));
assert_eq!(it.next(), Some((c, &30)));
assert_eq!(it.next(), Some((d, &40)));
assert_eq!(it.next(), None);
}
#[test]
fn iter_mut() {
let mut arena = Arena::new();
let a = arena.insert(10);
let b = arena.insert(20);
let c = arena.insert(30);
let d = arena.insert(40);
arena.remove(b);
{
let mut it = arena.iter_mut();
assert_eq!(it.next(), Some((a, &mut 10)));
assert_eq!(it.next(), Some((c, &mut 30)));
assert_eq!(it.next(), Some((d, &mut 40)));
assert_eq!(it.next(), None);
}
for (index, value) in arena.iter_mut() {
*value += index;
}
let mut it = arena.iter_mut();
assert_eq!(*it.next().unwrap().1, 10 + a);
assert_eq!(*it.next().unwrap().1, 30 + c);
assert_eq!(*it.next().unwrap().1, 40 + d);
assert_eq!(it.next(), None);
}
}