Bump to 0.5.0, delete unsafe, use 2018 edition

This commit is contained in:
Stjepan Glavina 2020-07-07 09:35:12 +02:00
parent 095b9b5a6c
commit f533229a0a
6 changed files with 316 additions and 347 deletions

View File

@ -1,16 +1,11 @@
[package] [package]
name = "vec-arena" name = "vec-arena"
version = "0.4.2" version = "0.5.0"
authors = ["Stjepan Glavina <stjepang@gmail.com>"] authors = ["Stjepan Glavina <stjepang@gmail.com>"]
edition = "2018"
description = "A simple object arena" description = "A simple object arena"
repository = "https://github.com/stjepang/vec-arena" repository = "https://github.com/stjepang/vec-arena"
documentation = "https://docs.rs/vec-arena" documentation = "https://docs.rs/vec-arena"
readme = "README.md" readme = "README.md"
license = "Apache-2.0/MIT" license = "Apache-2.0 OR MIT"
categories = ["memory-management"] categories = ["memory-management"]
[badges]
travis-ci = { repository = "stjepang/vec-arena" }
[dependencies]
unreachable = "0.1"

View File

@ -1,12 +1,10 @@
# vec-arena (deprecated) # vec-arena
[![Build Status](https://travis-ci.org/stjepang/vec-arena.svg?branch=master)](https://travis-ci.org/stjepang/vec-arena) [![Build Status](https://travis-ci.org/stjepang/vec-arena.svg?branch=master)](https://travis-ci.org/stjepang/vec-arena)
[![License](https://img.shields.io/badge/license-Apache--2.0%2FMIT-blue.svg)](https://github.com/stjepang/vec-arena) [![License](https://img.shields.io/badge/license-Apache--2.0%2FMIT-blue.svg)](https://github.com/stjepang/vec-arena)
[![Cargo](https://img.shields.io/crates/v/vec-arena.svg)](https://crates.io/crates/vec-arena) [![Cargo](https://img.shields.io/crates/v/vec-arena.svg)](https://crates.io/crates/vec-arena)
[![Documentation](https://docs.rs/vec-arena/badge.svg)](https://docs.rs/vec-arena) [![Documentation](https://docs.rs/vec-arena/badge.svg)](https://docs.rs/vec-arena)
**This crate is now deprecated in favor of [slab](https://github.com/carllerche/slab).**
#### What is this? #### What is this?
A simple object arena. A simple object arena.

View File

@ -1,5 +1,3 @@
extern crate vec_arena;
use vec_arena::Arena; use vec_arena::Arena;
/// The null index, akin to null pointers. /// The null index, akin to null pointers.
@ -49,8 +47,12 @@ impl<T> List<T> {
/// Links nodes `a` and `b` together, so that `a` comes before `b` in the list. /// Links nodes `a` and `b` together, so that `a` comes before `b` in the list.
fn link(&mut self, a: usize, b: usize) { fn link(&mut self, a: usize, b: usize) {
if a != NULL { self.arena[a].next = b; } if a != NULL {
if b != NULL { self.arena[b].prev = a; } self.arena[a].next = b;
}
if b != NULL {
self.arena[b].prev = a;
}
} }
/// Appends `value` to the back of the list. /// Appends `value` to the back of the list.
@ -88,8 +90,12 @@ impl<T> List<T> {
let node = self.arena.remove(index).unwrap(); let node = self.arena.remove(index).unwrap();
self.link(node.prev, node.next); self.link(node.prev, node.next);
if self.head == index { self.head = node.next; } if self.head == index {
if self.tail == index { self.tail = node.prev; } self.head = node.next;
}
if self.tail == index {
self.tail = node.prev;
}
node.value node.value
} }

View File

@ -1,5 +1,3 @@
extern crate vec_arena;
use vec_arena::Arena; use vec_arena::Arena;
/// The null index, akin to null pointers. /// The null index, akin to null pointers.
@ -39,7 +37,7 @@ struct Splay<T> {
root: usize, root: usize,
} }
impl<T> Splay<T> where T: Ord { impl<T: Ord> Splay<T> {
/// Constructs a new, empty splay tree. /// Constructs a new, empty splay tree.
fn new() -> Splay<T> { fn new() -> Splay<T> {
Splay { Splay {
@ -139,7 +137,11 @@ impl<T> Splay<T> where T: Ord {
let mut p = self.root; let mut p = self.root;
loop { loop {
// Decide whether to go left or right. // Decide whether to go left or right.
let dir = if self.arena[n].value < self.arena[p].value { 0 } else { 1 }; let dir = if self.arena[n].value < self.arena[p].value {
0
} else {
1
};
let c = self.arena[p].children[dir]; let c = self.arena[p].children[dir];
if c == NULL { if c == NULL {
@ -153,7 +155,10 @@ impl<T> Splay<T> where T: Ord {
} }
/// Pretty-prints the subtree rooted at `node`, indented by `indent` spaces. /// Pretty-prints the subtree rooted at `node`, indented by `indent` spaces.
fn print(&self, node: usize, indent: usize) where T: std::fmt::Display { fn print(&self, node: usize, indent: usize)
where
T: std::fmt::Display,
{
if node != NULL { if node != NULL {
// Print the left subtree. // Print the left subtree.
self.print(self.arena[node].children[0], indent + 3); self.print(self.arena[node].children[0], indent + 3);

View File

@ -2,7 +2,7 @@
//! //!
//! `Arena<T>` is basically just a `Vec<Option<T>>`, which allows you to: //! `Arena<T>` is basically just a `Vec<Option<T>>`, which allows you to:
//! //!
//! * Insert an object (reuse an existing `None` element, or append to the end). //! * Insert an object (reuse an existing [`None`] element, or append to the end).
//! * Remove object at a specified index. //! * Remove object at a specified index.
//! * Access object at a specified index. //! * Access object at a specified index.
//! //!
@ -13,18 +13,16 @@
//! * [Doubly linked list](https://github.com/stjepang/vec-arena/blob/master/examples/linked_list.rs) //! * [Doubly linked list](https://github.com/stjepang/vec-arena/blob/master/examples/linked_list.rs)
//! * [Splay tree](https://github.com/stjepang/vec-arena/blob/master/examples/splay_tree.rs) //! * [Splay tree](https://github.com/stjepang/vec-arena/blob/master/examples/splay_tree.rs)
extern crate unreachable; #![forbid(unsafe_code)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
use std::fmt; use std::fmt;
use std::iter; use std::iter;
use std::mem; use std::mem;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::ptr;
use std::slice; use std::slice;
use std::vec; use std::vec;
use unreachable::unreachable;
/// A slot, which is either vacant or occupied. /// A slot, which is either vacant or occupied.
/// ///
/// Vacant slots in arena are linked together into a singly linked list. This allows the arena to /// Vacant slots in arena are linked together into a singly linked list. This allows the arena to
@ -39,6 +37,16 @@ enum Slot<T> {
Occupied(T), Occupied(T),
} }
impl<T> Slot<T> {
/// Returns `true` if the slot is vacant.
fn is_occupied(&self) -> bool {
match self {
Slot::Vacant(_) => false,
Slot::Occupied(_) => true,
}
}
}
/// An object arena. /// An object arena.
/// ///
/// `Arena<T>` holds an array of slots for storing objects. /// `Arena<T>` holds an array of slots for storing objects.
@ -73,7 +81,7 @@ enum Slot<T> {
/// ///
/// # Indexing /// # Indexing
/// ///
/// You can also access objects in an arena by index, just like you would in a `Vec`. /// You can also access objects in an arena by index, just like you would in a [`Vec`].
/// However, accessing a vacant slot by index or using an out-of-bounds index will result in panic. /// However, accessing a vacant slot by index or using an out-of-bounds index will result in panic.
/// ///
/// ``` /// ```
@ -90,7 +98,8 @@ enum Slot<T> {
/// assert_eq!(arena[a], 30); /// assert_eq!(arena[a], 30);
/// ``` /// ```
/// ///
/// To access slots without fear of panicking, use `get` and `get_mut`, which return `Option`s. /// To access slots without fear of panicking, use [`get()`][`Arena::get()`] and
/// [`get_mut()`][`Arena::get_mut()`], which return [`Option`]s.
pub struct Arena<T> { pub struct Arena<T> {
/// Slots in which objects are stored. /// Slots in which objects are stored.
slots: Vec<Slot<T>>, slots: Vec<Slot<T>>,
@ -125,8 +134,8 @@ impl<T> Arena<T> {
/// Constructs a new, empty arena with the specified capacity (number of slots). /// Constructs a new, empty arena with the specified capacity (number of slots).
/// ///
/// The arena will be able to hold exactly `capacity` objects without reallocating. /// The arena will be able to hold exactly `cap` objects without reallocating.
/// If `capacity` is 0, the arena will not allocate. /// If `cap` is 0, the arena will not allocate.
/// ///
/// # Examples /// # Examples
/// ///
@ -210,7 +219,7 @@ impl<T> Arena<T> {
self.len == 0 self.len == 0
} }
/// Returns the index of the slot that next `insert` will use if no other /// Returns the index of the slot that next [`insert`][`Arena::insert()`] will use if no
/// mutating calls take place in between. /// mutating calls take place in between.
/// ///
/// # Examples /// # Examples
@ -228,7 +237,7 @@ impl<T> Arena<T> {
/// assert_eq!(c, d); /// assert_eq!(c, d);
/// ``` /// ```
#[inline] #[inline]
pub fn next_vacant(&mut self) -> usize { pub fn next_vacant(&self) -> usize {
if self.head == !0 { if self.head == !0 {
self.len self.len
} else { } else {
@ -237,6 +246,7 @@ impl<T> Arena<T> {
} }
/// Inserts an object into the arena and returns the slot index it was stored in. /// Inserts an object into the arena and returns the slot index it was stored in.
///
/// The arena will reallocate if it's full. /// The arena will reallocate if it's full.
/// ///
/// # Examples /// # Examples
@ -263,7 +273,7 @@ impl<T> Arena<T> {
Slot::Vacant(next) => { Slot::Vacant(next) => {
self.head = next; self.head = next;
self.slots[index] = Slot::Occupied(object); self.slots[index] = Slot::Occupied(object);
}, }
Slot::Occupied(_) => unreachable!(), Slot::Occupied(_) => unreachable!(),
} }
index index
@ -272,7 +282,7 @@ impl<T> Arena<T> {
/// Removes the object stored at `index` from the arena and returns it. /// Removes the object stored at `index` from the arena and returns it.
/// ///
/// `None` is returned in case the slot is vacant, or `index` is out of bounds. /// If the slot is vacant or `index` is out of bounds, [`None`] will be returned.
/// ///
/// # Examples /// # Examples
/// ///
@ -305,8 +315,9 @@ impl<T> Arena<T> {
} }
} }
/// Clears the arena, removing and dropping all objects it holds. Keeps the allocated memory /// Clears the arena, removing and dropping all objects it holds.
/// for reuse. ///
/// Keeps the allocated memory for reuse.
/// ///
/// # Examples /// # Examples
/// ///
@ -331,7 +342,7 @@ impl<T> Arena<T> {
/// Returns a reference to the object stored at `index`. /// Returns a reference to the object stored at `index`.
/// ///
/// If `index` is out of bounds or the slot is vacant, `None` is returned. /// If the slot is vacant or `index` is out of bounds, [`None`] will be returned.
/// ///
/// # Examples /// # Examples
/// ///
@ -356,7 +367,7 @@ impl<T> Arena<T> {
/// Returns a mutable reference to the object stored at `index`. /// Returns a mutable reference to the object stored at `index`.
/// ///
/// If `index` is out of bounds or the slot is vacant, `None` is returned. /// If the slot is vacant or `index` is out of bounds, [`None`] will be returned.
/// ///
/// # Examples /// # Examples
/// ///
@ -379,56 +390,6 @@ impl<T> Arena<T> {
} }
} }
/// Returns a reference to the object stored at `index`.
///
/// # Safety
///
/// Behavior is undefined if `index` is out of bounds or the slot is vacant.
///
/// # Examples
///
/// ```
/// use vec_arena::Arena;
///
/// let mut arena = Arena::new();
/// let index = arena.insert("hello");
///
/// unsafe { assert_eq!(&*arena.get_unchecked(index), &"hello") }
/// ```
#[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,
}
}
/// Returns a mutable reference to the object stored at `index`.
///
/// # Safety
///
/// Behavior is undefined if `index` is out of bounds or the slot is vacant.
///
/// # Examples
///
/// ```
/// use vec_arena::Arena;
///
/// let mut arena = Arena::new();
/// let index = arena.insert("hello");
///
/// unsafe { assert_eq!(&*arena.get_unchecked_mut(index), &"hello") }
/// ```
#[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,
}
}
/// Swaps two objects in the arena. /// Swaps two objects in the arena.
/// ///
/// The two indices are `a` and `b`. /// The two indices are `a` and `b`.
@ -452,17 +413,19 @@ impl<T> Arena<T> {
/// ``` /// ```
#[inline] #[inline]
pub fn swap(&mut self, a: usize, b: usize) { pub fn swap(&mut self, a: usize, b: usize) {
unsafe { assert!(self.slots[a].is_occupied(), "invalid object ID");
let fst = self.get_mut(a).unwrap() as *mut _; assert!(self.slots[b].is_occupied(), "invalid object ID");
let snd = self.get_mut(b).unwrap() as *mut _;
if a != b { if a != b {
ptr::swap(fst, snd); let (a, b) = (a.min(b), a.max(b));
} let (l, r) = self.slots.split_at_mut(b);
mem::swap(&mut l[a], &mut r[0]);
} }
} }
/// Reserves capacity for at least `additional` more objects to be inserted. The arena may /// Reserves capacity for at least `additional` more objects to be inserted.
/// reserve more space to avoid frequent reallocations. ///
/// The arena may reserve more space to avoid frequent reallocations.
/// ///
/// # Panics /// # Panics
/// ///
@ -530,8 +493,10 @@ impl<T> Arena<T> {
/// assert_eq!(iterator.next(), Some((2, &4))); /// assert_eq!(iterator.next(), Some((2, &4)));
/// ``` /// ```
#[inline] #[inline]
pub fn iter(&self) -> Iter<T> { pub fn iter(&self) -> Iter<'_, T> {
Iter { slots: self.slots.iter().enumerate() } Iter {
slots: self.slots.iter().enumerate(),
}
} }
/// Returns an iterator that returns mutable references to objects. /// Returns an iterator that returns mutable references to objects.
@ -556,8 +521,10 @@ impl<T> Arena<T> {
/// assert_eq!(iterator.next(), Some((2, &"2 two".to_string()))); /// assert_eq!(iterator.next(), Some((2, &"2 two".to_string())));
/// ``` /// ```
#[inline] #[inline]
pub fn iter_mut(&mut self) -> IterMut<T> { pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut { slots: self.slots.iter_mut().enumerate() } IterMut {
slots: self.slots.iter_mut().enumerate(),
}
} }
/// Shrinks the capacity of the arena as much as possible. /// Shrinks the capacity of the arena as much as possible.
@ -584,7 +551,7 @@ impl<T> Arena<T> {
} }
impl<T> fmt::Debug for Arena<T> { impl<T> fmt::Debug for Arena<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Arena {{ ... }}") write!(f, "Arena {{ ... }}")
} }
} }
@ -621,7 +588,7 @@ impl<T: Clone> Clone for Arena<T> {
} }
} }
/// An iterator over the occupied slots in a `Arena`. /// An iterator over the occupied slots in an [`Arena`].
pub struct IntoIter<T> { pub struct IntoIter<T> {
slots: iter::Enumerate<vec::IntoIter<Slot<T>>>, slots: iter::Enumerate<vec::IntoIter<Slot<T>>>,
} }
@ -646,12 +613,14 @@ impl<T> IntoIterator for Arena<T> {
#[inline] #[inline]
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
IntoIter { slots: self.slots.into_iter().enumerate() } IntoIter {
slots: self.slots.into_iter().enumerate(),
}
} }
} }
impl<T> iter::FromIterator<T> for Arena<T> { impl<T> iter::FromIterator<T> for Arena<T> {
fn from_iter<U: IntoIterator<Item=T>>(iter: U) -> Arena<T> { fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Arena<T> {
let iter = iter.into_iter(); let iter = iter.into_iter();
let mut arena = Arena::with_capacity(iter.size_hint().0); let mut arena = Arena::with_capacity(iter.size_hint().0);
for i in iter { for i in iter {
@ -662,13 +631,13 @@ impl<T> iter::FromIterator<T> for Arena<T> {
} }
impl<T> fmt::Debug for IntoIter<T> { impl<T> fmt::Debug for IntoIter<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "IntoIter {{ ... }}") write!(f, "IntoIter {{ ... }}")
} }
} }
/// An iterator over references to the occupied slots in a `Arena`. /// An iterator over references to the occupied slots in an [`Arena`].
pub struct Iter<'a, T: 'a> { pub struct Iter<'a, T> {
slots: iter::Enumerate<slice::Iter<'a, Slot<T>>>, slots: iter::Enumerate<slice::Iter<'a, Slot<T>>>,
} }
@ -697,13 +666,13 @@ impl<'a, T> IntoIterator for &'a Arena<T> {
} }
impl<'a, T> fmt::Debug for Iter<'a, T> { impl<'a, T> fmt::Debug for Iter<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Iter {{ ... }}") write!(f, "Iter {{ ... }}")
} }
} }
/// An iterator over mutable references to the occupied slots in a `Arena`. /// An iterator over mutable references to the occupied slots in a `Arena`.
pub struct IterMut<'a, T: 'a> { pub struct IterMut<'a, T> {
slots: iter::Enumerate<slice::IterMut<'a, Slot<T>>>, slots: iter::Enumerate<slice::IterMut<'a, Slot<T>>>,
} }
@ -732,243 +701,7 @@ impl<'a, T> IntoIterator for &'a mut Arena<T> {
} }
impl<'a, T> fmt::Debug for IterMut<'a, T> { impl<'a, T> fmt::Debug for IterMut<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "IterMut {{ ... }}") 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 &mut arena {
*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);
}
#[test]
fn from_iter() {
let arena: Arena<_> = [10, 20, 30, 40].iter().cloned().collect();
let mut it = arena.iter();
assert_eq!(it.next(), Some((0, &10)));
assert_eq!(it.next(), Some((1, &20)));
assert_eq!(it.next(), Some((2, &30)));
assert_eq!(it.next(), Some((3, &40)));
assert_eq!(it.next(), None);
}
}

232
tests/arena.rs Normal file
View File

@ -0,0 +1,232 @@
use vec_arena::Arena;
#[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 &mut arena {
*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);
}
#[test]
fn from_iter() {
let arena: Arena<_> = [10, 20, 30, 40].iter().cloned().collect();
let mut it = arena.iter();
assert_eq!(it.next(), Some((0, &10)));
assert_eq!(it.next(), Some((1, &20)));
assert_eq!(it.next(), Some((2, &30)));
assert_eq!(it.next(), Some((3, &40)));
assert_eq!(it.next(), None);
}