From f533229a0ac1e795c7bb4e8fe5fc9bb70d246090 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Tue, 7 Jul 2020 09:35:12 +0200 Subject: [PATCH] Bump to 0.5.0, delete unsafe, use 2018 edition --- Cargo.toml | 11 +- README.md | 4 +- examples/{linked_list.rs => linked-list.rs} | 18 +- examples/{splay_tree.rs => splay-tree.rs} | 15 +- src/lib.rs | 383 +++----------------- tests/arena.rs | 232 ++++++++++++ 6 files changed, 316 insertions(+), 347 deletions(-) rename examples/{linked_list.rs => linked-list.rs} (90%) rename examples/{splay_tree.rs => splay-tree.rs} (95%) create mode 100644 tests/arena.rs diff --git a/Cargo.toml b/Cargo.toml index d2c3666..109db5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,11 @@ [package] name = "vec-arena" -version = "0.4.2" +version = "0.5.0" authors = ["Stjepan Glavina "] +edition = "2018" description = "A simple object arena" repository = "https://github.com/stjepang/vec-arena" documentation = "https://docs.rs/vec-arena" readme = "README.md" -license = "Apache-2.0/MIT" +license = "Apache-2.0 OR MIT" categories = ["memory-management"] - -[badges] -travis-ci = { repository = "stjepang/vec-arena" } - -[dependencies] -unreachable = "0.1" diff --git a/README.md b/README.md index b0ed97d..3a1396b 100644 --- a/README.md +++ b/README.md @@ -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) [![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) [![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? A simple object arena. diff --git a/examples/linked_list.rs b/examples/linked-list.rs similarity index 90% rename from examples/linked_list.rs rename to examples/linked-list.rs index bce6310..431e1b1 100644 --- a/examples/linked_list.rs +++ b/examples/linked-list.rs @@ -1,5 +1,3 @@ -extern crate vec_arena; - use vec_arena::Arena; /// The null index, akin to null pointers. @@ -49,8 +47,12 @@ impl List { /// Links nodes `a` and `b` together, so that `a` comes before `b` in the list. fn link(&mut self, a: usize, b: usize) { - if a != NULL { self.arena[a].next = b; } - if b != NULL { self.arena[b].prev = a; } + if a != NULL { + self.arena[a].next = b; + } + if b != NULL { + self.arena[b].prev = a; + } } /// Appends `value` to the back of the list. @@ -88,8 +90,12 @@ impl List { let node = self.arena.remove(index).unwrap(); self.link(node.prev, node.next); - if self.head == index { self.head = node.next; } - if self.tail == index { self.tail = node.prev; } + if self.head == index { + self.head = node.next; + } + if self.tail == index { + self.tail = node.prev; + } node.value } diff --git a/examples/splay_tree.rs b/examples/splay-tree.rs similarity index 95% rename from examples/splay_tree.rs rename to examples/splay-tree.rs index acc8f71..9f08b44 100644 --- a/examples/splay_tree.rs +++ b/examples/splay-tree.rs @@ -1,5 +1,3 @@ -extern crate vec_arena; - use vec_arena::Arena; /// The null index, akin to null pointers. @@ -39,7 +37,7 @@ struct Splay { root: usize, } -impl Splay where T: Ord { +impl Splay { /// Constructs a new, empty splay tree. fn new() -> Splay { Splay { @@ -139,7 +137,11 @@ impl Splay where T: Ord { let mut p = self.root; loop { // 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]; if c == NULL { @@ -153,7 +155,10 @@ impl Splay where T: Ord { } /// 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 { // Print the left subtree. self.print(self.arena[node].children[0], indent + 3); diff --git a/src/lib.rs b/src/lib.rs index 632fdbf..2612de2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ //! //! `Arena` is basically just a `Vec>`, 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. //! * 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) //! * [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::iter; use std::mem; use std::ops::{Index, IndexMut}; -use std::ptr; use std::slice; use std::vec; -use unreachable::unreachable; - /// 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 @@ -39,6 +37,16 @@ enum Slot { Occupied(T), } +impl Slot { + /// Returns `true` if the slot is vacant. + fn is_occupied(&self) -> bool { + match self { + Slot::Vacant(_) => false, + Slot::Occupied(_) => true, + } + } +} + /// An object arena. /// /// `Arena` holds an array of slots for storing objects. @@ -73,7 +81,7 @@ enum Slot { /// /// # 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. /// /// ``` @@ -90,7 +98,8 @@ enum Slot { /// 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 { /// Slots in which objects are stored. slots: Vec>, @@ -125,8 +134,8 @@ impl Arena { /// Constructs a new, empty arena with the specified capacity (number of slots). /// - /// The arena will be able to hold exactly `capacity` objects without reallocating. - /// If `capacity` is 0, the arena will not allocate. + /// The arena will be able to hold exactly `cap` objects without reallocating. + /// If `cap` is 0, the arena will not allocate. /// /// # Examples /// @@ -210,7 +219,7 @@ impl Arena { 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. /// /// # Examples @@ -228,7 +237,7 @@ impl Arena { /// assert_eq!(c, d); /// ``` #[inline] - pub fn next_vacant(&mut self) -> usize { + pub fn next_vacant(&self) -> usize { if self.head == !0 { self.len } else { @@ -237,6 +246,7 @@ impl Arena { } /// Inserts an object into the arena and returns the slot index it was stored in. + /// /// The arena will reallocate if it's full. /// /// # Examples @@ -263,7 +273,7 @@ impl Arena { Slot::Vacant(next) => { self.head = next; self.slots[index] = Slot::Occupied(object); - }, + } Slot::Occupied(_) => unreachable!(), } index @@ -272,7 +282,7 @@ impl Arena { /// 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 /// @@ -305,8 +315,9 @@ impl Arena { } } - /// Clears the arena, removing and dropping all objects it holds. Keeps the allocated memory - /// for reuse. + /// Clears the arena, removing and dropping all objects it holds. + /// + /// Keeps the allocated memory for reuse. /// /// # Examples /// @@ -331,7 +342,7 @@ impl Arena { /// 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 /// @@ -356,7 +367,7 @@ impl Arena { /// 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 /// @@ -379,56 +390,6 @@ impl Arena { } } - /// 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. /// /// The two indices are `a` and `b`. @@ -452,17 +413,19 @@ impl Arena { /// ``` #[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); - } + assert!(self.slots[a].is_occupied(), "invalid object ID"); + assert!(self.slots[b].is_occupied(), "invalid object ID"); + + if a != b { + 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 - /// reserve more space to avoid frequent reallocations. + /// Reserves capacity for at least `additional` more objects to be inserted. + /// + /// The arena may reserve more space to avoid frequent reallocations. /// /// # Panics /// @@ -530,8 +493,10 @@ impl Arena { /// assert_eq!(iterator.next(), Some((2, &4))); /// ``` #[inline] - pub fn iter(&self) -> Iter { - Iter { slots: self.slots.iter().enumerate() } + pub fn iter(&self) -> Iter<'_, T> { + Iter { + slots: self.slots.iter().enumerate(), + } } /// Returns an iterator that returns mutable references to objects. @@ -556,8 +521,10 @@ impl Arena { /// assert_eq!(iterator.next(), Some((2, &"2 two".to_string()))); /// ``` #[inline] - pub fn iter_mut(&mut self) -> IterMut { - IterMut { slots: self.slots.iter_mut().enumerate() } + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut { + slots: self.slots.iter_mut().enumerate(), + } } /// Shrinks the capacity of the arena as much as possible. @@ -584,7 +551,7 @@ impl Arena { } impl fmt::Debug for Arena { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Arena {{ ... }}") } } @@ -621,7 +588,7 @@ impl Clone for Arena { } } -/// An iterator over the occupied slots in a `Arena`. +/// An iterator over the occupied slots in an [`Arena`]. pub struct IntoIter { slots: iter::Enumerate>>, } @@ -646,12 +613,14 @@ impl IntoIterator for Arena { #[inline] fn into_iter(self) -> Self::IntoIter { - IntoIter { slots: self.slots.into_iter().enumerate() } + IntoIter { + slots: self.slots.into_iter().enumerate(), + } } } impl iter::FromIterator for Arena { - fn from_iter>(iter: U) -> Arena { + fn from_iter>(iter: U) -> Arena { let iter = iter.into_iter(); let mut arena = Arena::with_capacity(iter.size_hint().0); for i in iter { @@ -662,13 +631,13 @@ impl iter::FromIterator for Arena { } impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "IntoIter {{ ... }}") } } -/// An iterator over references to the occupied slots in a `Arena`. -pub struct Iter<'a, T: 'a> { +/// An iterator over references to the occupied slots in an [`Arena`]. +pub struct Iter<'a, T> { slots: iter::Enumerate>>, } @@ -697,13 +666,13 @@ impl<'a, T> IntoIterator for &'a Arena { } 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 {{ ... }}") } } /// 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>>, } @@ -732,243 +701,7 @@ impl<'a, T> IntoIterator for &'a mut Arena { } 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 {{ ... }}") } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn new() { - let arena = Arena::::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); - } -} diff --git a/tests/arena.rs b/tests/arena.rs new file mode 100644 index 0000000..d1732be --- /dev/null +++ b/tests/arena.rs @@ -0,0 +1,232 @@ +use vec_arena::Arena; + +#[test] +fn new() { + let arena = Arena::::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); +}