diff options
Diffstat (limited to 'vendor/im-rc/src/vector/mod.rs')
-rw-r--r-- | vendor/im-rc/src/vector/mod.rs | 2745 |
1 files changed, 2745 insertions, 0 deletions
diff --git a/vendor/im-rc/src/vector/mod.rs b/vendor/im-rc/src/vector/mod.rs new file mode 100644 index 000000000..a2ce0adf7 --- /dev/null +++ b/vendor/im-rc/src/vector/mod.rs @@ -0,0 +1,2745 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//! A persistent vector. +//! +//! This is a sequence of elements in insertion order - if you need a +//! list of things, any kind of list of things, this is what you're +//! looking for. +//! +//! It's implemented as an [RRB vector][rrbpaper] with [smart +//! head/tail chunking][chunkedseq]. In performance terms, this means +//! that practically every operation is O(log n), except push/pop on +//! both sides, which will be O(1) amortised, and O(log n) in the +//! worst case. In practice, the push/pop operations will be +//! blindingly fast, nearly on par with the native +//! [`VecDeque`][VecDeque], and other operations will have decent, if +//! not high, performance, but they all have more or less the same +//! O(log n) complexity, so you don't need to keep their performance +//! characteristics in mind - everything, even splitting and merging, +//! is safe to use and never too slow. +//! +//! ## Performance Notes +//! +//! Because of the head/tail chunking technique, until you push a +//! number of items above double the tree's branching factor (that's +//! `self.len()` = 2 × *k* (where *k* = 64) = 128) on either side, the +//! data structure is still just a handful of arrays, not yet an RRB +//! tree, so you'll see performance and memory characteristics fairly +//! close to [`Vec`][Vec] or [`VecDeque`][VecDeque]. +//! +//! This means that the structure always preallocates four chunks of +//! size *k* (*k* being the tree's branching factor), equivalent to a +//! [`Vec`][Vec] with an initial capacity of 256. Beyond that, it will +//! allocate tree nodes of capacity *k* as needed. +//! +//! In addition, vectors start out as single chunks, and only expand into the +//! full data structure once you go past the chunk size. This makes them +//! perform identically to [`Vec`][Vec] at small sizes. +//! +//! [rrbpaper]: https://infoscience.epfl.ch/record/213452/files/rrbvector.pdf +//! [chunkedseq]: http://deepsea.inria.fr/pasl/chunkedseq.pdf +//! [Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html +//! [VecDeque]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html + +use std::borrow::Borrow; +use std::cmp::Ordering; +use std::fmt::{Debug, Error, Formatter}; +use std::hash::{Hash, Hasher}; +use std::iter::Sum; +use std::iter::{FromIterator, FusedIterator}; +use std::mem::{replace, swap}; +use std::ops::{Add, Index, IndexMut, RangeBounds}; + +use sized_chunks::InlineArray; + +use crate::nodes::chunk::{Chunk, CHUNK_SIZE}; +use crate::nodes::rrb::{Node, PopResult, PushResult, SplitResult}; +use crate::sort; +use crate::util::{clone_ref, swap_indices, to_range, Pool, PoolDefault, PoolRef, Ref, Side}; + +use self::VectorInner::{Full, Inline, Single}; + +mod focus; + +pub use self::focus::{Focus, FocusMut}; + +mod pool; +pub use self::pool::RRBPool; + +#[cfg(all(threadsafe, any(test, feature = "rayon")))] +pub mod rayon; + +/// Construct a vector from a sequence of elements. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate im_rc as im; +/// # use im::vector::Vector; +/// # fn main() { +/// assert_eq!( +/// vector![1, 2, 3], +/// Vector::from(vec![1, 2, 3]) +/// ); +/// # } +/// ``` +#[macro_export] +macro_rules! vector { + () => { $crate::vector::Vector::new() }; + + ( $($x:expr),* ) => {{ + let mut l = $crate::vector::Vector::new(); + $( + l.push_back($x); + )* + l + }}; + + ( $($x:expr ,)* ) => {{ + let mut l = $crate::vector::Vector::new(); + $( + l.push_back($x); + )* + l + }}; +} + +/// A persistent vector. +/// +/// This is a sequence of elements in insertion order - if you need a list of +/// things, any kind of list of things, this is what you're looking for. +/// +/// It's implemented as an [RRB vector][rrbpaper] with [smart head/tail +/// chunking][chunkedseq]. In performance terms, this means that practically +/// every operation is O(log n), except push/pop on both sides, which will be +/// O(1) amortised, and O(log n) in the worst case. In practice, the push/pop +/// operations will be blindingly fast, nearly on par with the native +/// [`VecDeque`][VecDeque], and other operations will have decent, if not high, +/// performance, but they all have more or less the same O(log n) complexity, so +/// you don't need to keep their performance characteristics in mind - +/// everything, even splitting and merging, is safe to use and never too slow. +/// +/// ## Performance Notes +/// +/// Because of the head/tail chunking technique, until you push a number of +/// items above double the tree's branching factor (that's `self.len()` = 2 × +/// *k* (where *k* = 64) = 128) on either side, the data structure is still just +/// a handful of arrays, not yet an RRB tree, so you'll see performance and +/// memory characteristics similar to [`Vec`][Vec] or [`VecDeque`][VecDeque]. +/// +/// This means that the structure always preallocates four chunks of size *k* +/// (*k* being the tree's branching factor), equivalent to a [`Vec`][Vec] with +/// an initial capacity of 256. Beyond that, it will allocate tree nodes of +/// capacity *k* as needed. +/// +/// In addition, vectors start out as single chunks, and only expand into the +/// full data structure once you go past the chunk size. This makes them +/// perform identically to [`Vec`][Vec] at small sizes. +/// +/// [rrbpaper]: https://infoscience.epfl.ch/record/213452/files/rrbvector.pdf +/// [chunkedseq]: http://deepsea.inria.fr/pasl/chunkedseq.pdf +/// [Vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html +/// [VecDeque]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html +pub struct Vector<A> { + vector: VectorInner<A>, +} + +enum VectorInner<A> { + Inline(RRBPool<A>, InlineArray<A, Rrb<A>>), + Single(RRBPool<A>, PoolRef<Chunk<A>>), + Full(RRBPool<A>, Rrb<A>), +} + +#[doc(hidden)] +pub struct Rrb<A> { + length: usize, + middle_level: usize, + outer_f: PoolRef<Chunk<A>>, + inner_f: PoolRef<Chunk<A>>, + middle: Ref<Node<A>>, + inner_b: PoolRef<Chunk<A>>, + outer_b: PoolRef<Chunk<A>>, +} + +impl<A> Clone for Rrb<A> { + fn clone(&self) -> Self { + Rrb { + length: self.length, + middle_level: self.middle_level, + outer_f: self.outer_f.clone(), + inner_f: self.inner_f.clone(), + middle: self.middle.clone(), + inner_b: self.inner_b.clone(), + outer_b: self.outer_b.clone(), + } + } +} + +impl<A: Clone> Vector<A> { + /// Get a reference to the memory pool this `Vector` is using. + /// + /// Note that if you didn't specifically construct it with a pool, you'll + /// get back a reference to a pool of size 0. + #[cfg_attr(not(feature = "pool"), doc(hidden))] + pub fn pool(&self) -> &RRBPool<A> { + match self.vector { + Inline(ref pool, _) => pool, + Single(ref pool, _) => pool, + Full(ref pool, _) => pool, + } + } + + /// True if a vector is a full inline or single chunk, ie. must be promoted + /// to grow further. + fn needs_promotion(&self) -> bool { + match &self.vector { + Inline(_, chunk) if chunk.is_full() => true, + Single(_, chunk) if chunk.is_full() => true, + _ => false, + } + } + + /// Promote an inline to a single. + fn promote_inline(&mut self) { + if let Inline(pool, chunk) = &mut self.vector { + self.vector = Single(pool.clone(), PoolRef::new(&pool.value_pool, chunk.into())); + } + } + + /// Promote a single to a full, with the single chunk becoming inner_f, or + /// promote an inline to a single. + fn promote_front(&mut self) { + self.vector = match &mut self.vector { + Inline(pool, chunk) => { + Single(pool.clone(), PoolRef::new(&pool.value_pool, chunk.into())) + } + Single(pool, chunk) => { + let chunk = chunk.clone(); + Full( + pool.clone(), + Rrb { + length: chunk.len(), + middle_level: 0, + outer_f: PoolRef::default(&pool.value_pool), + inner_f: chunk, + middle: Ref::new(Node::new()), + inner_b: PoolRef::default(&pool.value_pool), + outer_b: PoolRef::default(&pool.value_pool), + }, + ) + } + Full(_, _) => return, + } + } + + /// Promote a single to a full, with the single chunk becoming inner_b, or + /// promote an inline to a single. + fn promote_back(&mut self) { + self.vector = match &mut self.vector { + Inline(pool, chunk) => { + Single(pool.clone(), PoolRef::new(&pool.value_pool, chunk.into())) + } + Single(pool, chunk) => { + let chunk = chunk.clone(); + Full( + pool.clone(), + Rrb { + length: chunk.len(), + middle_level: 0, + outer_f: PoolRef::default(&pool.value_pool), + inner_f: PoolRef::default(&pool.value_pool), + middle: Ref::new(Node::new()), + inner_b: chunk, + outer_b: PoolRef::default(&pool.value_pool), + }, + ) + } + Full(_, _) => return, + } + } + + /// Construct an empty vector. + #[must_use] + pub fn new() -> Self { + Self { + vector: Inline(RRBPool::default(), InlineArray::new()), + } + } + + /// Construct an empty vector using a specific memory pool. + #[cfg(feature = "pool")] + #[must_use] + pub fn with_pool(pool: &RRBPool<A>) -> Self { + Self { + vector: Inline(pool.clone(), InlineArray::new()), + } + } + + /// Get the length of a vector. + /// + /// Time: O(1) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// assert_eq!(5, vector![1, 2, 3, 4, 5].len()); + /// ``` + #[inline] + #[must_use] + pub fn len(&self) -> usize { + match &self.vector { + Inline(_, chunk) => chunk.len(), + Single(_, chunk) => chunk.len(), + Full(_, tree) => tree.length, + } + } + + /// Test whether a vector is empty. + /// + /// Time: O(1) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let vec = vector!["Joe", "Mike", "Robert"]; + /// assert_eq!(false, vec.is_empty()); + /// assert_eq!(true, Vector::<i32>::new().is_empty()); + /// ``` + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Test whether a vector is currently inlined. + /// + /// Vectors small enough that their contents could be stored entirely inside + /// the space of `std::mem::size_of::<Vector<A>>()` bytes are stored inline on + /// the stack instead of allocating any chunks. This method returns `true` if + /// this vector is currently inlined, or `false` if it currently has chunks allocated + /// on the heap. + /// + /// This may be useful in conjunction with [`ptr_eq()`][ptr_eq], which checks if + /// two vectors' heap allocations are the same, and thus will never return `true` + /// for inlined vectors. + /// + /// Time: O(1) + /// + /// [ptr_eq]: #method.ptr_eq + #[inline] + #[must_use] + pub fn is_inline(&self) -> bool { + matches!(&self.vector, Inline(_, _)) + } + + /// Test whether two vectors refer to the same content in memory. + /// + /// This uses the following rules to determine equality: + /// * If the two sides are references to the same vector, return true. + /// * If the two sides are single chunk vectors pointing to the same chunk, return true. + /// * If the two sides are full trees pointing to the same chunks, return true. + /// + /// This would return true if you're comparing a vector to itself, or + /// if you're comparing a vector to a fresh clone of itself. The exception to this is + /// if you've cloned an inline array (ie. an array with so few elements they can fit + /// inside the space a `Vector` allocates for its pointers, so there are no heap allocations + /// to compare). + /// + /// Time: O(1) + #[must_use] + pub fn ptr_eq(&self, other: &Self) -> bool { + fn cmp_chunk<A>(left: &PoolRef<Chunk<A>>, right: &PoolRef<Chunk<A>>) -> bool { + (left.is_empty() && right.is_empty()) || PoolRef::ptr_eq(left, right) + } + + if std::ptr::eq(self, other) { + return true; + } + + match (&self.vector, &other.vector) { + (Single(_, left), Single(_, right)) => cmp_chunk(left, right), + (Full(_, left), Full(_, right)) => { + cmp_chunk(&left.outer_f, &right.outer_f) + && cmp_chunk(&left.inner_f, &right.inner_f) + && cmp_chunk(&left.inner_b, &right.inner_b) + && cmp_chunk(&left.outer_b, &right.outer_b) + && ((left.middle.is_empty() && right.middle.is_empty()) + || Ref::ptr_eq(&left.middle, &right.middle)) + } + _ => false, + } + } + + /// Get an iterator over a vector. + /// + /// Time: O(1) + #[inline] + #[must_use] + pub fn iter(&self) -> Iter<'_, A> { + Iter::new(self) + } + + /// Get a mutable iterator over a vector. + /// + /// Time: O(1) + #[inline] + #[must_use] + pub fn iter_mut(&mut self) -> IterMut<'_, A> { + IterMut::new(self) + } + + /// Get an iterator over the leaf nodes of a vector. + /// + /// This returns an iterator over the [`Chunk`s][Chunk] at the leaves of the + /// RRB tree. These are useful for efficient parallelisation of work on + /// the vector, but should not be used for basic iteration. + /// + /// Time: O(1) + /// + /// [Chunk]: ../chunk/struct.Chunk.html + #[inline] + #[must_use] + pub fn leaves(&self) -> Chunks<'_, A> { + Chunks::new(self) + } + + /// Get a mutable iterator over the leaf nodes of a vector. + // + /// This returns an iterator over the [`Chunk`s][Chunk] at the leaves of the + /// RRB tree. These are useful for efficient parallelisation of work on + /// the vector, but should not be used for basic iteration. + /// + /// Time: O(1) + /// + /// [Chunk]: ../chunk/struct.Chunk.html + #[inline] + #[must_use] + pub fn leaves_mut(&mut self) -> ChunksMut<'_, A> { + ChunksMut::new(self) + } + + /// Construct a [`Focus`][Focus] for a vector. + /// + /// Time: O(1) + /// + /// [Focus]: enum.Focus.html + #[inline] + #[must_use] + pub fn focus(&self) -> Focus<'_, A> { + Focus::new(self) + } + + /// Construct a [`FocusMut`][FocusMut] for a vector. + /// + /// Time: O(1) + /// + /// [FocusMut]: enum.FocusMut.html + #[inline] + #[must_use] + pub fn focus_mut(&mut self) -> FocusMut<'_, A> { + FocusMut::new(self) + } + + /// Get a reference to the value at index `index` in a vector. + /// + /// Returns `None` if the index is out of bounds. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let vec = vector!["Joe", "Mike", "Robert"]; + /// assert_eq!(Some(&"Robert"), vec.get(2)); + /// assert_eq!(None, vec.get(5)); + /// ``` + #[must_use] + pub fn get(&self, index: usize) -> Option<&A> { + if index >= self.len() { + return None; + } + + match &self.vector { + Inline(_, chunk) => chunk.get(index), + Single(_, chunk) => chunk.get(index), + Full(_, tree) => { + let mut local_index = index; + + if local_index < tree.outer_f.len() { + return Some(&tree.outer_f[local_index]); + } + local_index -= tree.outer_f.len(); + + if local_index < tree.inner_f.len() { + return Some(&tree.inner_f[local_index]); + } + local_index -= tree.inner_f.len(); + + if local_index < tree.middle.len() { + return Some(tree.middle.index(tree.middle_level, local_index)); + } + local_index -= tree.middle.len(); + + if local_index < tree.inner_b.len() { + return Some(&tree.inner_b[local_index]); + } + local_index -= tree.inner_b.len(); + + Some(&tree.outer_b[local_index]) + } + } + } + + /// Get a mutable reference to the value at index `index` in a + /// vector. + /// + /// Returns `None` if the index is out of bounds. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector!["Joe", "Mike", "Robert"]; + /// { + /// let robert = vec.get_mut(2).unwrap(); + /// assert_eq!(&mut "Robert", robert); + /// *robert = "Bjarne"; + /// } + /// assert_eq!(vector!["Joe", "Mike", "Bjarne"], vec); + /// ``` + #[must_use] + pub fn get_mut(&mut self, index: usize) -> Option<&mut A> { + if index >= self.len() { + return None; + } + + match &mut self.vector { + Inline(_, chunk) => chunk.get_mut(index), + Single(pool, chunk) => PoolRef::make_mut(&pool.value_pool, chunk).get_mut(index), + Full(pool, tree) => { + let mut local_index = index; + + if local_index < tree.outer_f.len() { + let outer_f = PoolRef::make_mut(&pool.value_pool, &mut tree.outer_f); + return Some(&mut outer_f[local_index]); + } + local_index -= tree.outer_f.len(); + + if local_index < tree.inner_f.len() { + let inner_f = PoolRef::make_mut(&pool.value_pool, &mut tree.inner_f); + return Some(&mut inner_f[local_index]); + } + local_index -= tree.inner_f.len(); + + if local_index < tree.middle.len() { + let middle = Ref::make_mut(&mut tree.middle); + return Some(middle.index_mut(pool, tree.middle_level, local_index)); + } + local_index -= tree.middle.len(); + + if local_index < tree.inner_b.len() { + let inner_b = PoolRef::make_mut(&pool.value_pool, &mut tree.inner_b); + return Some(&mut inner_b[local_index]); + } + local_index -= tree.inner_b.len(); + + let outer_b = PoolRef::make_mut(&pool.value_pool, &mut tree.outer_b); + Some(&mut outer_b[local_index]) + } + } + } + + /// Get the first element of a vector. + /// + /// If the vector is empty, `None` is returned. + /// + /// Time: O(log n) + #[inline] + #[must_use] + pub fn front(&self) -> Option<&A> { + self.get(0) + } + + /// Get a mutable reference to the first element of a vector. + /// + /// If the vector is empty, `None` is returned. + /// + /// Time: O(log n) + #[inline] + #[must_use] + pub fn front_mut(&mut self) -> Option<&mut A> { + self.get_mut(0) + } + + /// Get the first element of a vector. + /// + /// If the vector is empty, `None` is returned. + /// + /// This is an alias for the [`front`][front] method. + /// + /// Time: O(log n) + /// + /// [front]: #method.front + #[inline] + #[must_use] + pub fn head(&self) -> Option<&A> { + self.get(0) + } + + /// Get the last element of a vector. + /// + /// If the vector is empty, `None` is returned. + /// + /// Time: O(log n) + #[must_use] + pub fn back(&self) -> Option<&A> { + if self.is_empty() { + None + } else { + self.get(self.len() - 1) + } + } + + /// Get a mutable reference to the last element of a vector. + /// + /// If the vector is empty, `None` is returned. + /// + /// Time: O(log n) + #[must_use] + pub fn back_mut(&mut self) -> Option<&mut A> { + if self.is_empty() { + None + } else { + let len = self.len(); + self.get_mut(len - 1) + } + } + + /// Get the last element of a vector. + /// + /// If the vector is empty, `None` is returned. + /// + /// This is an alias for the [`back`][back] method. + /// + /// Time: O(log n) + /// + /// [back]: #method.back + #[inline] + #[must_use] + pub fn last(&self) -> Option<&A> { + self.back() + } + + /// Get the index of a given element in the vector. + /// + /// Searches the vector for the first occurrence of a given value, + /// and returns the index of the value if it's there. Otherwise, + /// it returns `None`. + /// + /// Time: O(n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![1, 2, 3, 4, 5]; + /// assert_eq!(Some(2), vec.index_of(&3)); + /// assert_eq!(None, vec.index_of(&31337)); + /// ``` + #[must_use] + pub fn index_of(&self, value: &A) -> Option<usize> + where + A: PartialEq, + { + for (index, item) in self.iter().enumerate() { + if value == item { + return Some(index); + } + } + None + } + + /// Test if a given element is in the vector. + /// + /// Searches the vector for the first occurrence of a given value, + /// and returns `true` if it's there. If it's nowhere to be found + /// in the vector, it returns `false`. + /// + /// Time: O(n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![1, 2, 3, 4, 5]; + /// assert_eq!(true, vec.contains(&3)); + /// assert_eq!(false, vec.contains(&31337)); + /// ``` + #[inline] + #[must_use] + pub fn contains(&self, value: &A) -> bool + where + A: PartialEq, + { + self.index_of(value).is_some() + } + + /// Discard all elements from the vector. + /// + /// This leaves you with an empty vector, and all elements that + /// were previously inside it are dropped. + /// + /// Time: O(n) + pub fn clear(&mut self) { + if !self.is_empty() { + self.vector = Inline(self.pool().clone(), InlineArray::new()); + } + } + + /// Binary search a sorted vector for a given element using a comparator + /// function. + /// + /// Assumes the vector has already been sorted using the same comparator + /// function, eg. by using [`sort_by`][sort_by]. + /// + /// If the value is found, it returns `Ok(index)` where `index` is the index + /// of the element. If the value isn't found, it returns `Err(index)` where + /// `index` is the index at which the element would need to be inserted to + /// maintain sorted order. + /// + /// Time: O(log n) + /// + /// [sort_by]: #method.sort_by + pub fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize> + where + F: FnMut(&A) -> Ordering, + { + let mut size = self.len(); + if size == 0 { + return Err(0); + } + let mut base = 0; + while size > 1 { + let half = size / 2; + let mid = base + half; + base = match f(&self[mid]) { + Ordering::Greater => base, + _ => mid, + }; + size -= half; + } + match f(&self[base]) { + Ordering::Equal => Ok(base), + Ordering::Greater => Err(base), + Ordering::Less => Err(base + 1), + } + } + + /// Binary search a sorted vector for a given element. + /// + /// If the value is found, it returns `Ok(index)` where `index` is the index + /// of the element. If the value isn't found, it returns `Err(index)` where + /// `index` is the index at which the element would need to be inserted to + /// maintain sorted order. + /// + /// Time: O(log n) + pub fn binary_search(&self, value: &A) -> Result<usize, usize> + where + A: Ord, + { + self.binary_search_by(|e| e.cmp(value)) + } + + /// Binary search a sorted vector for a given element with a key extract + /// function. + /// + /// Assumes the vector has already been sorted using the same key extract + /// function, eg. by using [`sort_by_key`][sort_by_key]. + /// + /// If the value is found, it returns `Ok(index)` where `index` is the index + /// of the element. If the value isn't found, it returns `Err(index)` where + /// `index` is the index at which the element would need to be inserted to + /// maintain sorted order. + /// + /// Time: O(log n) + /// + /// [sort_by_key]: #method.sort_by_key + pub fn binary_search_by_key<B, F>(&self, b: &B, mut f: F) -> Result<usize, usize> + where + F: FnMut(&A) -> B, + B: Ord, + { + self.binary_search_by(|k| f(k).cmp(b)) + } +} + +impl<A: Clone> Vector<A> { + /// Construct a vector with a single value. + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let vec = Vector::unit(1337); + /// assert_eq!(1, vec.len()); + /// assert_eq!( + /// vec.get(0), + /// Some(&1337) + /// ); + /// ``` + #[inline] + #[must_use] + pub fn unit(a: A) -> Self { + let pool = RRBPool::default(); + if InlineArray::<A, Rrb<A>>::CAPACITY > 0 { + let mut array = InlineArray::new(); + array.push(a); + Self { + vector: Inline(pool, array), + } + } else { + let chunk = PoolRef::new(&pool.value_pool, Chunk::unit(a)); + Self { + vector: Single(pool, chunk), + } + } + } + + /// Create a new vector with the value at index `index` updated. + /// + /// Panics if the index is out of bounds. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![1, 2, 3]; + /// assert_eq!(vector![1, 5, 3], vec.update(1, 5)); + /// ``` + #[must_use] + pub fn update(&self, index: usize, value: A) -> Self { + let mut out = self.clone(); + out[index] = value; + out + } + + /// Update the value at index `index` in a vector. + /// + /// Returns the previous value at the index. + /// + /// Panics if the index is out of bounds. + /// + /// Time: O(log n) + #[inline] + pub fn set(&mut self, index: usize, value: A) -> A { + replace(&mut self[index], value) + } + + /// Swap the elements at indices `i` and `j`. + /// + /// Time: O(log n) + pub fn swap(&mut self, i: usize, j: usize) { + swap_indices(self, i, j) + } + + /// Push a value to the front of a vector. + /// + /// Time: O(1)* + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![5, 6, 7]; + /// vec.push_front(4); + /// assert_eq!(vector![4, 5, 6, 7], vec); + /// ``` + pub fn push_front(&mut self, value: A) { + if self.needs_promotion() { + self.promote_back(); + } + match &mut self.vector { + Inline(_, chunk) => { + chunk.insert(0, value); + } + Single(pool, chunk) => PoolRef::make_mut(&pool.value_pool, chunk).push_front(value), + Full(pool, tree) => tree.push_front(pool, value), + } + } + + /// Push a value to the back of a vector. + /// + /// Time: O(1)* + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![1, 2, 3]; + /// vec.push_back(4); + /// assert_eq!(vector![1, 2, 3, 4], vec); + /// ``` + pub fn push_back(&mut self, value: A) { + if self.needs_promotion() { + self.promote_front(); + } + match &mut self.vector { + Inline(_, chunk) => { + chunk.push(value); + } + Single(pool, chunk) => PoolRef::make_mut(&pool.value_pool, chunk).push_back(value), + Full(pool, tree) => tree.push_back(pool, value), + } + } + + /// Remove the first element from a vector and return it. + /// + /// Time: O(1)* + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![1, 2, 3]; + /// assert_eq!(Some(1), vec.pop_front()); + /// assert_eq!(vector![2, 3], vec); + /// ``` + pub fn pop_front(&mut self) -> Option<A> { + if self.is_empty() { + None + } else { + match &mut self.vector { + Inline(_, chunk) => chunk.remove(0), + Single(pool, chunk) => Some(PoolRef::make_mut(&pool.value_pool, chunk).pop_front()), + Full(pool, tree) => tree.pop_front(pool), + } + } + } + + /// Remove the last element from a vector and return it. + /// + /// Time: O(1)* + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::Vector; + /// let mut vec = vector![1, 2, 3]; + /// assert_eq!(Some(3), vec.pop_back()); + /// assert_eq!(vector![1, 2], vec); + /// ``` + pub fn pop_back(&mut self) -> Option<A> { + if self.is_empty() { + None + } else { + match &mut self.vector { + Inline(_, chunk) => chunk.pop(), + Single(pool, chunk) => Some(PoolRef::make_mut(&pool.value_pool, chunk).pop_back()), + Full(pool, tree) => tree.pop_back(pool), + } + } + } + + /// Append the vector `other` to the end of the current vector. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let mut vec = vector![1, 2, 3]; + /// vec.append(vector![7, 8, 9]); + /// assert_eq!(vector![1, 2, 3, 7, 8, 9], vec); + /// ``` + pub fn append(&mut self, mut other: Self) { + if other.is_empty() { + return; + } + + if self.is_empty() { + *self = other; + return; + } + + self.promote_inline(); + other.promote_inline(); + + let total_length = self + .len() + .checked_add(other.len()) + .expect("Vector length overflow"); + + match &mut self.vector { + Inline(_, _) => unreachable!("inline vecs should have been promoted"), + Single(pool, left) => { + match &mut other.vector { + Inline(_, _) => unreachable!("inline vecs should have been promoted"), + // If both are single chunks and left has room for right: directly + // memcpy right into left + Single(_, ref mut right) if total_length <= CHUNK_SIZE => { + PoolRef::make_mut(&pool.value_pool, left) + .append(PoolRef::make_mut(&pool.value_pool, right)); + return; + } + // If only left is a single chunk and has room for right: push + // right's elements into left + _ if total_length <= CHUNK_SIZE => { + while let Some(value) = other.pop_front() { + PoolRef::make_mut(&pool.value_pool, left).push_back(value); + } + return; + } + _ => {} + } + } + Full(pool, left) => { + if let Full(_, mut right) = other.vector { + // If left and right are trees with empty middles, left has no back + // buffers, and right has no front buffers: copy right's back + // buffers over to left + if left.middle.is_empty() + && right.middle.is_empty() + && left.outer_b.is_empty() + && left.inner_b.is_empty() + && right.outer_f.is_empty() + && right.inner_f.is_empty() + { + left.inner_b = right.inner_b; + left.outer_b = right.outer_b; + left.length = total_length; + return; + } + // If left and right are trees with empty middles and left's buffers + // can fit right's buffers: push right's elements onto left + if left.middle.is_empty() + && right.middle.is_empty() + && total_length <= CHUNK_SIZE * 4 + { + while let Some(value) = right.pop_front(pool) { + left.push_back(pool, value); + } + return; + } + // Both are full and big: do the full RRB join + let inner_b1 = left.inner_b.clone(); + left.push_middle(pool, Side::Right, inner_b1); + let outer_b1 = left.outer_b.clone(); + left.push_middle(pool, Side::Right, outer_b1); + let inner_f2 = right.inner_f.clone(); + right.push_middle(pool, Side::Left, inner_f2); + let outer_f2 = right.outer_f.clone(); + right.push_middle(pool, Side::Left, outer_f2); + + let mut middle1 = clone_ref(replace(&mut left.middle, Ref::from(Node::new()))); + let mut middle2 = clone_ref(right.middle); + let normalised_middle = match left.middle_level.cmp(&right.middle_level) { + Ordering::Greater => { + middle2 = middle2.elevate(pool, left.middle_level - right.middle_level); + left.middle_level + } + Ordering::Less => { + middle1 = middle1.elevate(pool, right.middle_level - left.middle_level); + right.middle_level + } + Ordering::Equal => left.middle_level, + }; + left.middle = Ref::new(Node::merge(pool, middle1, middle2, normalised_middle)); + left.middle_level = normalised_middle + 1; + + left.inner_b = right.inner_b; + left.outer_b = right.outer_b; + left.length = total_length; + left.prune(); + return; + } + } + } + // No optimisations available, and either left, right or both are + // single: promote both to full and retry + self.promote_front(); + other.promote_back(); + self.append(other) + } + + /// Retain only the elements specified by the predicate. + /// + /// Remove all elements for which the provided function `f` + /// returns false from the vector. + /// + /// Time: O(n) + pub fn retain<F>(&mut self, mut f: F) + where + F: FnMut(&A) -> bool, + { + let len = self.len(); + let mut del = 0; + { + let mut focus = self.focus_mut(); + for i in 0..len { + if !f(focus.index(i)) { + del += 1; + } else if del > 0 { + focus.swap(i - del, i); + } + } + } + if del > 0 { + self.split_off(len - del); + } + } + + /// Split a vector at a given index. + /// + /// Split a vector at a given index, consuming the vector and + /// returning a pair of the left hand side and the right hand side + /// of the split. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let mut vec = vector![1, 2, 3, 7, 8, 9]; + /// let (left, right) = vec.split_at(3); + /// assert_eq!(vector![1, 2, 3], left); + /// assert_eq!(vector![7, 8, 9], right); + /// ``` + pub fn split_at(mut self, index: usize) -> (Self, Self) { + let right = self.split_off(index); + (self, right) + } + + /// Split a vector at a given index. + /// + /// Split a vector at a given index, leaving the left hand side in + /// the current vector and returning a new vector containing the + /// right hand side. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let mut left = vector![1, 2, 3, 7, 8, 9]; + /// let right = left.split_off(3); + /// assert_eq!(vector![1, 2, 3], left); + /// assert_eq!(vector![7, 8, 9], right); + /// ``` + pub fn split_off(&mut self, index: usize) -> Self { + assert!(index <= self.len()); + + match &mut self.vector { + Inline(pool, chunk) => Self { + vector: Inline(pool.clone(), chunk.split_off(index)), + }, + Single(pool, chunk) => Self { + vector: Single( + pool.clone(), + PoolRef::new( + &pool.value_pool, + PoolRef::make_mut(&pool.value_pool, chunk).split_off(index), + ), + ), + }, + Full(pool, tree) => { + let mut local_index = index; + + if local_index < tree.outer_f.len() { + let of2 = PoolRef::make_mut(&pool.value_pool, &mut tree.outer_f) + .split_off(local_index); + let right = Rrb { + length: tree.length - index, + middle_level: tree.middle_level, + outer_f: PoolRef::new(&pool.value_pool, of2), + inner_f: replace_pool_def(&pool.value_pool, &mut tree.inner_f), + middle: std::mem::take(&mut tree.middle), + inner_b: replace_pool_def(&pool.value_pool, &mut tree.inner_b), + outer_b: replace_pool_def(&pool.value_pool, &mut tree.outer_b), + }; + tree.length = index; + tree.middle_level = 0; + return Self { + vector: Full(pool.clone(), right), + }; + } + + local_index -= tree.outer_f.len(); + + if local_index < tree.inner_f.len() { + let if2 = PoolRef::make_mut(&pool.value_pool, &mut tree.inner_f) + .split_off(local_index); + let right = Rrb { + length: tree.length - index, + middle_level: tree.middle_level, + outer_f: PoolRef::new(&pool.value_pool, if2), + inner_f: PoolRef::<Chunk<A>>::default(&pool.value_pool), + middle: std::mem::take(&mut tree.middle), + inner_b: replace_pool_def(&pool.value_pool, &mut tree.inner_b), + outer_b: replace_pool_def(&pool.value_pool, &mut tree.outer_b), + }; + tree.length = index; + tree.middle_level = 0; + swap(&mut tree.outer_b, &mut tree.inner_f); + return Self { + vector: Full(pool.clone(), right), + }; + } + + local_index -= tree.inner_f.len(); + + if local_index < tree.middle.len() { + let mut right_middle = tree.middle.clone(); + let (c1, c2) = { + let m1 = Ref::make_mut(&mut tree.middle); + let m2 = Ref::make_mut(&mut right_middle); + match m1.split(pool, tree.middle_level, Side::Right, local_index) { + SplitResult::Dropped(_) => (), + SplitResult::OutOfBounds => unreachable!(), + }; + match m2.split(pool, tree.middle_level, Side::Left, local_index) { + SplitResult::Dropped(_) => (), + SplitResult::OutOfBounds => unreachable!(), + }; + let c1 = match m1.pop_chunk(pool, tree.middle_level, Side::Right) { + PopResult::Empty => PoolRef::default(&pool.value_pool), + PopResult::Done(chunk) => chunk, + PopResult::Drained(chunk) => { + m1.clear_node(); + chunk + } + }; + let c2 = match m2.pop_chunk(pool, tree.middle_level, Side::Left) { + PopResult::Empty => PoolRef::default(&pool.value_pool), + PopResult::Done(chunk) => chunk, + PopResult::Drained(chunk) => { + m2.clear_node(); + chunk + } + }; + (c1, c2) + }; + let mut right = Rrb { + length: tree.length - index, + middle_level: tree.middle_level, + outer_f: c2, + inner_f: PoolRef::<Chunk<A>>::default(&pool.value_pool), + middle: right_middle, + inner_b: replace_pool_def(&pool.value_pool, &mut tree.inner_b), + outer_b: replace(&mut tree.outer_b, c1), + }; + tree.length = index; + tree.prune(); + right.prune(); + return Self { + vector: Full(pool.clone(), right), + }; + } + + local_index -= tree.middle.len(); + + if local_index < tree.inner_b.len() { + let ib2 = PoolRef::make_mut(&pool.value_pool, &mut tree.inner_b) + .split_off(local_index); + let right = Rrb { + length: tree.length - index, + outer_b: replace_pool_def(&pool.value_pool, &mut tree.outer_b), + outer_f: PoolRef::new(&pool.value_pool, ib2), + ..Rrb::new(pool) + }; + tree.length = index; + swap(&mut tree.outer_b, &mut tree.inner_b); + return Self { + vector: Full(pool.clone(), right), + }; + } + + local_index -= tree.inner_b.len(); + + let ob2 = + PoolRef::make_mut(&pool.value_pool, &mut tree.outer_b).split_off(local_index); + tree.length = index; + Self { + vector: Single(pool.clone(), PoolRef::new(&pool.value_pool, ob2)), + } + } + } + } + + /// Construct a vector with `count` elements removed from the + /// start of the current vector. + /// + /// Time: O(log n) + #[must_use] + pub fn skip(&self, count: usize) -> Self { + // FIXME can be made more efficient by dropping the unwanted side without constructing it + self.clone().split_off(count) + } + + /// Construct a vector of the first `count` elements from the + /// current vector. + /// + /// Time: O(log n) + #[must_use] + pub fn take(&self, count: usize) -> Self { + // FIXME can be made more efficient by dropping the unwanted side without constructing it + let mut left = self.clone(); + left.split_off(count); + left + } + + /// Truncate a vector to the given size. + /// + /// Discards all elements in the vector beyond the given length. + /// + /// Panics if the new length is greater than the current length. + /// + /// Time: O(log n) + pub fn truncate(&mut self, len: usize) { + // FIXME can be made more efficient by dropping the unwanted side without constructing it + self.split_off(len); + } + + /// Extract a slice from a vector. + /// + /// Remove the elements from `start_index` until `end_index` in + /// the current vector and return the removed slice as a new + /// vector. + /// + /// Time: O(log n) + pub fn slice<R>(&mut self, range: R) -> Self + where + R: RangeBounds<usize>, + { + let r = to_range(&range, self.len()); + if r.start >= r.end || r.start >= self.len() { + return Vector::new(); + } + let mut middle = self.split_off(r.start); + let right = middle.split_off(r.end - r.start); + self.append(right); + middle + } + + /// Insert an element into a vector. + /// + /// Insert an element at position `index`, shifting all elements + /// after it to the right. + /// + /// ## Performance Note + /// + /// While `push_front` and `push_back` are heavily optimised + /// operations, `insert` in the middle of a vector requires a + /// split, a push, and an append. Thus, if you want to insert + /// many elements at the same location, instead of `insert`ing + /// them one by one, you should rather create a new vector + /// containing the elements to insert, split the vector at the + /// insertion point, and append the left hand, the new vector and + /// the right hand in order. + /// + /// Time: O(log n) + pub fn insert(&mut self, index: usize, value: A) { + if index == 0 { + return self.push_front(value); + } + if index == self.len() { + return self.push_back(value); + } + assert!(index < self.len()); + if if let Inline(_, chunk) = &self.vector { + chunk.is_full() + } else { + false + } { + self.promote_inline(); + } + match &mut self.vector { + Inline(_, chunk) => { + chunk.insert(index, value); + } + Single(pool, chunk) if chunk.len() < CHUNK_SIZE => { + PoolRef::make_mut(&pool.value_pool, chunk).insert(index, value) + } + // TODO a lot of optimisations still possible here + _ => { + let right = self.split_off(index); + self.push_back(value); + self.append(right); + } + } + } + + /// Remove an element from a vector. + /// + /// Remove the element from position 'index', shifting all + /// elements after it to the left, and return the removed element. + /// + /// ## Performance Note + /// + /// While `pop_front` and `pop_back` are heavily optimised + /// operations, `remove` in the middle of a vector requires a + /// split, a pop, and an append. Thus, if you want to remove many + /// elements from the same location, instead of `remove`ing them + /// one by one, it is much better to use [`slice`][slice]. + /// + /// Time: O(log n) + /// + /// [slice]: #method.slice + pub fn remove(&mut self, index: usize) -> A { + assert!(index < self.len()); + match &mut self.vector { + Inline(_, chunk) => chunk.remove(index).unwrap(), + Single(pool, chunk) => PoolRef::make_mut(&pool.value_pool, chunk).remove(index), + _ => { + if index == 0 { + return self.pop_front().unwrap(); + } + if index == self.len() - 1 { + return self.pop_back().unwrap(); + } + // TODO a lot of optimisations still possible here + let mut right = self.split_off(index); + let value = right.pop_front().unwrap(); + self.append(right); + value + } + } + } + + /// Insert an element into a sorted vector. + /// + /// Insert an element into a vector in sorted order, assuming the vector is + /// already in sorted order. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let mut vec = vector![1, 2, 3, 7, 8, 9]; + /// vec.insert_ord(5); + /// assert_eq!(vector![1, 2, 3, 5, 7, 8, 9], vec); + /// ``` + pub fn insert_ord(&mut self, item: A) + where + A: Ord, + { + match self.binary_search(&item) { + Ok(index) => self.insert(index, item), + Err(index) => self.insert(index, item), + } + } + + /// Sort a vector. + /// + /// Time: O(n log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let mut vec = vector![3, 2, 5, 4, 1]; + /// vec.sort(); + /// assert_eq!(vector![1, 2, 3, 4, 5], vec); + /// ``` + pub fn sort(&mut self) + where + A: Ord, + { + self.sort_by(Ord::cmp) + } + + /// Sort a vector using a comparator function. + /// + /// Time: O(n log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::vector::Vector; + /// let mut vec = vector![3, 2, 5, 4, 1]; + /// vec.sort_by(|left, right| left.cmp(right)); + /// assert_eq!(vector![1, 2, 3, 4, 5], vec); + /// ``` + pub fn sort_by<F>(&mut self, cmp: F) + where + F: Fn(&A, &A) -> Ordering, + { + let len = self.len(); + if len > 1 { + sort::quicksort(self.focus_mut(), &cmp); + } + } + + /// Verify the internal consistency of a vector. + /// + /// This method walks the RRB tree making up the current `Vector` + /// (if it has one) and verifies that all the invariants hold. + /// If something is wrong, it will panic. + /// + /// This method requires the `debug` feature flag. + #[cfg(any(test, feature = "debug"))] + pub fn assert_invariants(&self) { + if let Full(_, ref tree) = self.vector { + tree.assert_invariants(); + } + } +} + +// Implementation details + +impl<A: Clone> Rrb<A> { + fn new(pool: &RRBPool<A>) -> Self { + Rrb { + length: 0, + middle_level: 0, + outer_f: PoolRef::default(&pool.value_pool), + inner_f: PoolRef::default(&pool.value_pool), + middle: Ref::new(Node::new()), + inner_b: PoolRef::default(&pool.value_pool), + outer_b: PoolRef::default(&pool.value_pool), + } + } + + #[cfg(any(test, feature = "debug"))] + fn assert_invariants(&self) { + let ml = self.middle.assert_invariants(self.middle_level); + assert_eq!( + self.length, + self.outer_f.len() + self.inner_f.len() + ml + self.inner_b.len() + self.outer_b.len() + ); + } + + fn prune(&mut self) { + if self.middle.is_empty() { + self.middle = Ref::new(Node::new()); + self.middle_level = 0; + } else { + while self.middle_level > 0 && self.middle.is_single() { + // FIXME could be optimised, cloning the node is expensive + self.middle = Ref::new(self.middle.first_child().clone()); + self.middle_level -= 1; + } + } + } + + fn pop_front(&mut self, pool: &RRBPool<A>) -> Option<A> { + if self.length == 0 { + return None; + } + if self.outer_f.is_empty() { + if self.inner_f.is_empty() { + if self.middle.is_empty() { + if self.inner_b.is_empty() { + swap(&mut self.outer_f, &mut self.outer_b); + } else { + swap(&mut self.outer_f, &mut self.inner_b); + } + } else { + self.outer_f = self.pop_middle(pool, Side::Left).unwrap(); + } + } else { + swap(&mut self.outer_f, &mut self.inner_f); + } + } + self.length -= 1; + let outer_f = PoolRef::make_mut(&pool.value_pool, &mut self.outer_f); + Some(outer_f.pop_front()) + } + + fn pop_back(&mut self, pool: &RRBPool<A>) -> Option<A> { + if self.length == 0 { + return None; + } + if self.outer_b.is_empty() { + if self.inner_b.is_empty() { + if self.middle.is_empty() { + if self.inner_f.is_empty() { + swap(&mut self.outer_b, &mut self.outer_f); + } else { + swap(&mut self.outer_b, &mut self.inner_f); + } + } else { + self.outer_b = self.pop_middle(pool, Side::Right).unwrap(); + } + } else { + swap(&mut self.outer_b, &mut self.inner_b); + } + } + self.length -= 1; + let outer_b = PoolRef::make_mut(&pool.value_pool, &mut self.outer_b); + Some(outer_b.pop_back()) + } + + fn push_front(&mut self, pool: &RRBPool<A>, value: A) { + if self.outer_f.is_full() { + swap(&mut self.outer_f, &mut self.inner_f); + if !self.outer_f.is_empty() { + let mut chunk = PoolRef::new(&pool.value_pool, Chunk::new()); + swap(&mut chunk, &mut self.outer_f); + self.push_middle(pool, Side::Left, chunk); + } + } + self.length = self.length.checked_add(1).expect("Vector length overflow"); + let outer_f = PoolRef::make_mut(&pool.value_pool, &mut self.outer_f); + outer_f.push_front(value) + } + + fn push_back(&mut self, pool: &RRBPool<A>, value: A) { + if self.outer_b.is_full() { + swap(&mut self.outer_b, &mut self.inner_b); + if !self.outer_b.is_empty() { + let mut chunk = PoolRef::new(&pool.value_pool, Chunk::new()); + swap(&mut chunk, &mut self.outer_b); + self.push_middle(pool, Side::Right, chunk); + } + } + self.length = self.length.checked_add(1).expect("Vector length overflow"); + let outer_b = PoolRef::make_mut(&pool.value_pool, &mut self.outer_b); + outer_b.push_back(value) + } + + fn push_middle(&mut self, pool: &RRBPool<A>, side: Side, chunk: PoolRef<Chunk<A>>) { + if chunk.is_empty() { + return; + } + let new_middle = { + let middle = Ref::make_mut(&mut self.middle); + match middle.push_chunk(pool, self.middle_level, side, chunk) { + PushResult::Done => return, + PushResult::Full(chunk, _num_drained) => Ref::from({ + match side { + Side::Left => Node::from_chunk(pool, self.middle_level, chunk) + .join_branches(pool, middle.clone(), self.middle_level), + Side::Right => middle.clone().join_branches( + pool, + Node::from_chunk(pool, self.middle_level, chunk), + self.middle_level, + ), + } + }), + } + }; + self.middle_level += 1; + self.middle = new_middle; + } + + fn pop_middle(&mut self, pool: &RRBPool<A>, side: Side) -> Option<PoolRef<Chunk<A>>> { + let chunk = { + let middle = Ref::make_mut(&mut self.middle); + match middle.pop_chunk(pool, self.middle_level, side) { + PopResult::Empty => return None, + PopResult::Done(chunk) => chunk, + PopResult::Drained(chunk) => { + middle.clear_node(); + self.middle_level = 0; + chunk + } + } + }; + Some(chunk) + } +} + +#[inline] +fn replace_pool_def<A: PoolDefault>(pool: &Pool<A>, dest: &mut PoolRef<A>) -> PoolRef<A> { + replace(dest, PoolRef::default(pool)) +} + +// Core traits + +impl<A: Clone> Default for Vector<A> { + fn default() -> Self { + Self::new() + } +} + +impl<A: Clone> Clone for Vector<A> { + /// Clone a vector. + /// + /// Time: O(1), or O(n) with a very small, bounded *n* for an inline vector. + fn clone(&self) -> Self { + Self { + vector: match &self.vector { + Inline(pool, chunk) => Inline(pool.clone(), chunk.clone()), + Single(pool, chunk) => Single(pool.clone(), chunk.clone()), + Full(pool, tree) => Full(pool.clone(), tree.clone()), + }, + } + } +} + +impl<A: Clone + Debug> Debug for Vector<A> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + f.debug_list().entries(self.iter()).finish() + // match self { + // Full(rrb) => { + // writeln!(f, "Head: {:?} {:?}", rrb.outer_f, rrb.inner_f)?; + // rrb.middle.print(f, 0, rrb.middle_level)?; + // writeln!(f, "Tail: {:?} {:?}", rrb.inner_b, rrb.outer_b) + // } + // Single(_) => write!(f, "nowt"), + // } + } +} + +#[cfg(not(has_specialisation))] +impl<A: Clone + PartialEq> PartialEq for Vector<A> { + fn eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().eq(other.iter()) + } +} + +#[cfg(has_specialisation)] +impl<A: Clone + PartialEq> PartialEq for Vector<A> { + default fn eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().eq(other.iter()) + } +} + +#[cfg(has_specialisation)] +impl<A: Clone + Eq> PartialEq for Vector<A> { + fn eq(&self, other: &Self) -> bool { + fn cmp_chunk<A>(left: &PoolRef<Chunk<A>>, right: &PoolRef<Chunk<A>>) -> bool { + (left.is_empty() && right.is_empty()) || PoolRef::ptr_eq(left, right) + } + + if std::ptr::eq(self, other) { + return true; + } + + match (&self.vector, &other.vector) { + (Single(_, left), Single(_, right)) => { + if cmp_chunk(left, right) { + return true; + } + self.iter().eq(other.iter()) + } + (Full(_, left), Full(_, right)) => { + if left.length != right.length { + return false; + } + + if cmp_chunk(&left.outer_f, &right.outer_f) + && cmp_chunk(&left.inner_f, &right.inner_f) + && cmp_chunk(&left.inner_b, &right.inner_b) + && cmp_chunk(&left.outer_b, &right.outer_b) + && ((left.middle.is_empty() && right.middle.is_empty()) + || Ref::ptr_eq(&left.middle, &right.middle)) + { + return true; + } + self.iter().eq(other.iter()) + } + _ => self.len() == other.len() && self.iter().eq(other.iter()), + } + } +} + +impl<A: Clone + Eq> Eq for Vector<A> {} + +impl<A: Clone + PartialOrd> PartialOrd for Vector<A> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.iter().partial_cmp(other.iter()) + } +} + +impl<A: Clone + Ord> Ord for Vector<A> { + fn cmp(&self, other: &Self) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +impl<A: Clone + Hash> Hash for Vector<A> { + fn hash<H: Hasher>(&self, state: &mut H) { + for i in self { + i.hash(state) + } + } +} + +impl<A: Clone> Sum for Vector<A> { + fn sum<I>(it: I) -> Self + where + I: Iterator<Item = Self>, + { + it.fold(Self::new(), |a, b| a + b) + } +} + +impl<A: Clone> Add for Vector<A> { + type Output = Vector<A>; + + /// Concatenate two vectors. + /// + /// Time: O(log n) + fn add(mut self, other: Self) -> Self::Output { + self.append(other); + self + } +} + +impl<'a, A: Clone> Add for &'a Vector<A> { + type Output = Vector<A>; + + /// Concatenate two vectors. + /// + /// Time: O(log n) + fn add(self, other: Self) -> Self::Output { + let mut out = self.clone(); + out.append(other.clone()); + out + } +} + +impl<A: Clone> Extend<A> for Vector<A> { + /// Add values to the end of a vector by consuming an iterator. + /// + /// Time: O(n) + fn extend<I>(&mut self, iter: I) + where + I: IntoIterator<Item = A>, + { + for item in iter { + self.push_back(item) + } + } +} + +impl<A: Clone> Index<usize> for Vector<A> { + type Output = A; + /// Get a reference to the value at index `index` in the vector. + /// + /// Time: O(log n) + fn index(&self, index: usize) -> &Self::Output { + match self.get(index) { + Some(value) => value, + None => panic!( + "Vector::index: index out of bounds: {} < {}", + index, + self.len() + ), + } + } +} + +impl<A: Clone> IndexMut<usize> for Vector<A> { + /// Get a mutable reference to the value at index `index` in the + /// vector. + /// + /// Time: O(log n) + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + match self.get_mut(index) { + Some(value) => value, + None => panic!("Vector::index_mut: index out of bounds"), + } + } +} + +// Conversions + +impl<'a, A: Clone> IntoIterator for &'a Vector<A> { + type Item = &'a A; + type IntoIter = Iter<'a, A>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<A: Clone> IntoIterator for Vector<A> { + type Item = A; + type IntoIter = ConsumingIter<A>; + fn into_iter(self) -> Self::IntoIter { + ConsumingIter::new(self) + } +} + +impl<A: Clone> FromIterator<A> for Vector<A> { + /// Create a vector from an iterator. + /// + /// Time: O(n) + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = A>, + { + let mut seq = Self::new(); + for item in iter { + seq.push_back(item) + } + seq + } +} + +impl<'s, 'a, A, OA> From<&'s Vector<&'a A>> for Vector<OA> +where + A: ToOwned<Owned = OA>, + OA: Borrow<A> + Clone, +{ + fn from(vec: &Vector<&A>) -> Self { + vec.iter().map(|a| (*a).to_owned()).collect() + } +} + +impl<'a, A: Clone> From<&'a [A]> for Vector<A> { + fn from(slice: &[A]) -> Self { + slice.iter().cloned().collect() + } +} + +impl<A: Clone> From<Vec<A>> for Vector<A> { + /// Create a vector from a [`std::vec::Vec`][vec]. + /// + /// Time: O(n) + /// + /// [vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html + fn from(vec: Vec<A>) -> Self { + vec.into_iter().collect() + } +} + +impl<'a, A: Clone> From<&'a Vec<A>> for Vector<A> { + /// Create a vector from a [`std::vec::Vec`][vec]. + /// + /// Time: O(n) + /// + /// [vec]: https://doc.rust-lang.org/std/vec/struct.Vec.html + fn from(vec: &Vec<A>) -> Self { + vec.iter().cloned().collect() + } +} + +// Iterators + +/// An iterator over vectors with values of type `A`. +/// +/// To obtain one, use [`Vector::iter()`][iter]. +/// +/// [iter]: enum.Vector.html#method.iter +pub struct Iter<'a, A> { + focus: Focus<'a, A>, + front_index: usize, + back_index: usize, +} + +impl<'a, A: Clone> Iter<'a, A> { + fn new(seq: &'a Vector<A>) -> Self { + Iter { + focus: seq.focus(), + front_index: 0, + back_index: seq.len(), + } + } + + fn from_focus(focus: Focus<'a, A>) -> Self { + Iter { + front_index: 0, + back_index: focus.len(), + focus, + } + } +} + +impl<'a, A: Clone> Iterator for Iter<'a, A> { + type Item = &'a A; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + #[allow(unsafe_code)] + let focus: &'a mut Focus<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + let value = focus.get(self.front_index); + self.front_index += 1; + value + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let remaining = self.back_index - self.front_index; + (remaining, Some(remaining)) + } +} + +impl<'a, A: Clone> DoubleEndedIterator for Iter<'a, A> { + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next_back(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + self.back_index -= 1; + #[allow(unsafe_code)] + let focus: &'a mut Focus<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + focus.get(self.back_index) + } +} + +impl<'a, A: Clone> ExactSizeIterator for Iter<'a, A> {} + +impl<'a, A: Clone> FusedIterator for Iter<'a, A> {} + +/// A mutable iterator over vectors with values of type `A`. +/// +/// To obtain one, use [`Vector::iter_mut()`][iter_mut]. +/// +/// [iter_mut]: enum.Vector.html#method.iter_mut +pub struct IterMut<'a, A> { + focus: FocusMut<'a, A>, + front_index: usize, + back_index: usize, +} + +impl<'a, A> IterMut<'a, A> +where + A: Clone, +{ + fn new(seq: &'a mut Vector<A>) -> Self { + let focus = seq.focus_mut(); + let len = focus.len(); + IterMut { + focus, + front_index: 0, + back_index: len, + } + } + + fn from_focus(focus: FocusMut<'a, A>) -> Self { + IterMut { + front_index: 0, + back_index: focus.len(), + focus, + } + } +} + +impl<'a, A> Iterator for IterMut<'a, A> +where + A: 'a + Clone, +{ + type Item = &'a mut A; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + #[allow(unsafe_code)] + let focus: &'a mut FocusMut<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + let value = focus.get_mut(self.front_index); + self.front_index += 1; + value + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let remaining = self.back_index - self.front_index; + (remaining, Some(remaining)) + } +} + +impl<'a, A> DoubleEndedIterator for IterMut<'a, A> +where + A: 'a + Clone, +{ + /// Remove and return an element from the back of the iterator. + /// + /// Time: O(1)* + fn next_back(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + self.back_index -= 1; + #[allow(unsafe_code)] + let focus: &'a mut FocusMut<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + focus.get_mut(self.back_index) + } +} + +impl<'a, A: Clone> ExactSizeIterator for IterMut<'a, A> {} + +impl<'a, A: Clone> FusedIterator for IterMut<'a, A> {} + +/// A consuming iterator over vectors with values of type `A`. +pub struct ConsumingIter<A> { + vector: Vector<A>, +} + +impl<A: Clone> ConsumingIter<A> { + fn new(vector: Vector<A>) -> Self { + Self { vector } + } +} + +impl<A: Clone> Iterator for ConsumingIter<A> { + type Item = A; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + self.vector.pop_front() + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.vector.len(); + (len, Some(len)) + } +} + +impl<A: Clone> DoubleEndedIterator for ConsumingIter<A> { + /// Remove and return an element from the back of the iterator. + /// + /// Time: O(1)* + fn next_back(&mut self) -> Option<Self::Item> { + self.vector.pop_back() + } +} + +impl<A: Clone> ExactSizeIterator for ConsumingIter<A> {} + +impl<A: Clone> FusedIterator for ConsumingIter<A> {} + +/// An iterator over the leaf nodes of a vector. +/// +/// To obtain one, use [`Vector::chunks()`][chunks]. +/// +/// [chunks]: enum.Vector.html#method.chunks +pub struct Chunks<'a, A> { + focus: Focus<'a, A>, + front_index: usize, + back_index: usize, +} + +impl<'a, A: Clone> Chunks<'a, A> { + fn new(seq: &'a Vector<A>) -> Self { + Chunks { + focus: seq.focus(), + front_index: 0, + back_index: seq.len(), + } + } +} + +impl<'a, A: Clone> Iterator for Chunks<'a, A> { + type Item = &'a [A]; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + #[allow(unsafe_code)] + let focus: &'a mut Focus<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + let (range, value) = focus.chunk_at(self.front_index); + self.front_index = range.end; + Some(value) + } +} + +impl<'a, A: Clone> DoubleEndedIterator for Chunks<'a, A> { + /// Remove and return an element from the back of the iterator. + /// + /// Time: O(1)* + fn next_back(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + self.back_index -= 1; + #[allow(unsafe_code)] + let focus: &'a mut Focus<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + let (range, value) = focus.chunk_at(self.back_index); + self.back_index = range.start; + Some(value) + } +} + +impl<'a, A: Clone> FusedIterator for Chunks<'a, A> {} + +/// A mutable iterator over the leaf nodes of a vector. +/// +/// To obtain one, use [`Vector::chunks_mut()`][chunks_mut]. +/// +/// [chunks_mut]: enum.Vector.html#method.chunks_mut +pub struct ChunksMut<'a, A> { + focus: FocusMut<'a, A>, + front_index: usize, + back_index: usize, +} + +impl<'a, A: Clone> ChunksMut<'a, A> { + fn new(seq: &'a mut Vector<A>) -> Self { + let len = seq.len(); + ChunksMut { + focus: seq.focus_mut(), + front_index: 0, + back_index: len, + } + } +} + +impl<'a, A: Clone> Iterator for ChunksMut<'a, A> { + type Item = &'a mut [A]; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + #[allow(unsafe_code)] + let focus: &'a mut FocusMut<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + let (range, value) = focus.chunk_at(self.front_index); + self.front_index = range.end; + Some(value) + } +} + +impl<'a, A: Clone> DoubleEndedIterator for ChunksMut<'a, A> { + /// Remove and return an element from the back of the iterator. + /// + /// Time: O(1)* + fn next_back(&mut self) -> Option<Self::Item> { + if self.front_index >= self.back_index { + return None; + } + self.back_index -= 1; + #[allow(unsafe_code)] + let focus: &'a mut FocusMut<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; + let (range, value) = focus.chunk_at(self.back_index); + self.back_index = range.start; + Some(value) + } +} + +impl<'a, A: Clone> FusedIterator for ChunksMut<'a, A> {} + +// Proptest +#[cfg(any(test, feature = "proptest"))] +#[doc(hidden)] +pub mod proptest { + #[deprecated( + since = "14.3.0", + note = "proptest strategies have moved to im::proptest" + )] + pub use crate::proptest::vector; +} + +// Tests + +#[cfg(test)] +mod test { + use super::*; + use crate::proptest::vector; + use ::proptest::collection::vec; + use ::proptest::num::{i32, usize}; + use ::proptest::proptest; + + #[test] + fn macro_allows_trailing_comma() { + let vec1 = vector![1, 2, 3]; + let vec2 = vector![1, 2, 3,]; + assert_eq!(vec1, vec2); + } + + #[test] + fn indexing() { + let mut vec = vector![0, 1, 2, 3, 4, 5]; + vec.push_front(0); + assert_eq!(0, *vec.get(0).unwrap()); + assert_eq!(0, vec[0]); + } + + #[test] + fn large_vector_focus() { + let input = (0..100_000).collect::<Vector<_>>(); + let vec = input.clone(); + let mut sum: i64 = 0; + let mut focus = vec.focus(); + for i in 0..input.len() { + sum += *focus.index(i); + } + let expected: i64 = (0..100_000).sum(); + assert_eq!(expected, sum); + } + + #[test] + fn large_vector_focus_mut() { + let input = (0..100_000).collect::<Vector<_>>(); + let mut vec = input.clone(); + { + let mut focus = vec.focus_mut(); + for i in 0..input.len() { + let p = focus.index_mut(i); + *p += 1; + } + } + let expected: Vector<i32> = input.into_iter().map(|i| i + 1).collect(); + assert_eq!(expected, vec); + } + + #[test] + fn issue_55_fwd() { + let mut l = Vector::new(); + for i in 0..4098 { + l.append(Vector::unit(i)); + } + l.append(Vector::unit(4098)); + assert_eq!(Some(&4097), l.get(4097)); + assert_eq!(Some(&4096), l.get(4096)); + } + + #[test] + fn issue_55_back() { + let mut l = Vector::unit(0); + for i in 0..4099 { + let mut tmp = Vector::unit(i + 1); + tmp.append(l); + l = tmp; + } + assert_eq!(Some(&4098), l.get(1)); + assert_eq!(Some(&4097), l.get(2)); + let len = l.len(); + l.slice(2..len); + } + + #[test] + fn issue_55_append() { + let mut vec1 = (0..92).collect::<Vector<_>>(); + let vec2 = (0..165).collect::<Vector<_>>(); + vec1.append(vec2); + } + + #[test] + fn issue_70() { + let mut x = Vector::new(); + for _ in 0..262 { + x.push_back(0); + } + for _ in 0..97 { + x.pop_front(); + } + for &offset in &[160, 163, 160] { + x.remove(offset); + } + for _ in 0..64 { + x.push_back(0); + } + // At this point middle contains three chunks of size 64, 64 and 1 + // respectively. Previously the next `push_back()` would append another + // zero-sized chunk to middle even though there is enough space left. + match x.vector { + VectorInner::Full(_, ref tree) => { + assert_eq!(129, tree.middle.len()); + assert_eq!(3, tree.middle.number_of_children()); + } + _ => unreachable!(), + } + x.push_back(0); + match x.vector { + VectorInner::Full(_, ref tree) => { + assert_eq!(131, tree.middle.len()); + assert_eq!(3, tree.middle.number_of_children()) + } + _ => unreachable!(), + } + for _ in 0..64 { + x.push_back(0); + } + for _ in x.iter() {} + } + + #[test] + fn issue_67() { + let mut l = Vector::unit(4100); + for i in (0..4099).rev() { + let mut tmp = Vector::unit(i); + tmp.append(l); + l = tmp; + } + assert_eq!(4100, l.len()); + let len = l.len(); + let tail = l.slice(1..len); + assert_eq!(1, l.len()); + assert_eq!(4099, tail.len()); + assert_eq!(Some(&0), l.get(0)); + assert_eq!(Some(&1), tail.get(0)); + } + + #[test] + fn issue_74_simple_size() { + use crate::nodes::rrb::NODE_SIZE; + let mut x = Vector::new(); + for _ in 0..(CHUNK_SIZE + * ( + 1 // inner_f + + (2 * NODE_SIZE) // middle: two full Entry::Nodes (4096 elements each) + + 1 // inner_b + + 1 + // outer_b + )) + { + x.push_back(0u32); + } + let middle_first_node_start = CHUNK_SIZE; + let middle_second_node_start = middle_first_node_start + NODE_SIZE * CHUNK_SIZE; + // This reduces the size of the second node to 4095. + x.remove(middle_second_node_start); + // As outer_b is full, this will cause inner_b (length 64) to be pushed + // to middle. The first element will be merged into the second node, the + // remaining 63 elements will end up in a new node. + x.push_back(0u32); + match x.vector { + VectorInner::Full(_, tree) => { + assert_eq!(3, tree.middle.number_of_children()); + assert_eq!( + 2 * NODE_SIZE * CHUNK_SIZE + CHUNK_SIZE - 1, + tree.middle.len() + ); + } + _ => unreachable!(), + } + } + + #[test] + fn issue_77() { + let mut x = Vector::new(); + for _ in 0..44 { + x.push_back(0); + } + for _ in 0..20 { + x.insert(0, 0); + } + x.insert(1, 0); + for _ in 0..441 { + x.push_back(0); + } + for _ in 0..58 { + x.insert(0, 0); + } + x.insert(514, 0); + for _ in 0..73 { + x.push_back(0); + } + for _ in 0..10 { + x.insert(0, 0); + } + x.insert(514, 0); + } + + #[test] + fn issue_105() { + let mut v = Vector::new(); + + for i in 0..270_000 { + v.push_front(i); + } + + while !v.is_empty() { + v = v.take(v.len() - 1); + } + } + + #[test] + fn issue_107_split_off_causes_overflow() { + let mut vec = (0..4289).collect::<Vector<_>>(); + let mut control = (0..4289).collect::<Vec<_>>(); + let chunk = 64; + + while vec.len() >= chunk { + vec = vec.split_off(chunk); + control = control.split_off(chunk); + assert_eq!(vec.len(), control.len()); + assert_eq!(control, vec.iter().cloned().collect::<Vec<_>>()); + } + } + + #[test] + fn collect_crash() { + let _vector: Vector<i32> = (0..5953).collect(); + // let _vector: Vector<i32> = (0..16384).collect(); + } + + #[test] + fn issue_116() { + let vec = (0..300).collect::<Vector<_>>(); + let rev_vec: Vector<u32> = vec.clone().into_iter().rev().collect(); + assert_eq!(vec.len(), rev_vec.len()); + } + + #[test] + fn issue_131() { + let smol = std::iter::repeat(42).take(64).collect::<Vector<_>>(); + let mut smol2 = smol.clone(); + assert!(smol.ptr_eq(&smol2)); + smol2.set(63, 420); + assert!(!smol.ptr_eq(&smol2)); + + let huge = std::iter::repeat(42).take(65).collect::<Vector<_>>(); + let mut huge2 = huge.clone(); + assert!(huge.ptr_eq(&huge2)); + huge2.set(63, 420); + assert!(!huge.ptr_eq(&huge2)); + } + + #[test] + fn ptr_eq() { + for len in 32..256 { + let input = std::iter::repeat(42).take(len).collect::<Vector<_>>(); + let mut inp2 = input.clone(); + assert!(input.ptr_eq(&inp2)); + inp2.set(len - 1, 98); + assert_ne!(inp2.get(len - 1), input.get(len - 1)); + assert!(!input.ptr_eq(&inp2)); + } + } + + proptest! { + #[test] + fn iter(ref vec in vec(i32::ANY, 0..1000)) { + let seq: Vector<i32> = vec.iter().cloned().collect::<Vector<_>>(); + for (index, item) in seq.iter().enumerate() { + assert_eq!(&vec[index], item); + } + assert_eq!(vec.len(), seq.len()); + } + + #[test] + fn push_front_mut(ref input in vec(i32::ANY, 0..1000)) { + let mut vector = Vector::new(); + for (count, value) in input.iter().cloned().enumerate() { + assert_eq!(count, vector.len()); + vector.push_front(value); + assert_eq!(count + 1, vector.len()); + } + let input2 = input.iter().rev().cloned().collect::<Vec<_>>(); + assert_eq!(input2, vector.iter().cloned().collect::<Vec<_>>()); + } + + #[test] + fn push_back_mut(ref input in vec(i32::ANY, 0..1000)) { + let mut vector = Vector::new(); + for (count, value) in input.iter().cloned().enumerate() { + assert_eq!(count, vector.len()); + vector.push_back(value); + assert_eq!(count + 1, vector.len()); + } + assert_eq!(input, &vector.iter().cloned().collect::<Vec<_>>()); + } + + #[test] + fn pop_back_mut(ref input in vec(i32::ANY, 0..1000)) { + let mut vector = input.iter().cloned().collect::<Vector<_>>(); + assert_eq!(input.len(), vector.len()); + for (index, value) in input.iter().cloned().enumerate().rev() { + match vector.pop_back() { + None => panic!("vector emptied unexpectedly"), + Some(item) => { + assert_eq!(index, vector.len()); + assert_eq!(value, item); + } + } + } + assert_eq!(0, vector.len()); + } + + #[test] + fn pop_front_mut(ref input in vec(i32::ANY, 0..1000)) { + let mut vector = input.iter().cloned().collect::<Vector<_>>(); + assert_eq!(input.len(), vector.len()); + for (index, value) in input.iter().cloned().rev().enumerate().rev() { + match vector.pop_front() { + None => panic!("vector emptied unexpectedly"), + Some(item) => { + assert_eq!(index, vector.len()); + assert_eq!(value, item); + } + } + } + assert_eq!(0, vector.len()); + } + + // #[test] + // fn push_and_pop(ref input in vec(i32::ANY, 0..1000)) { + // let mut vector = Vector::new(); + // for (count, value) in input.iter().cloned().enumerate() { + // assert_eq!(count, vector.len()); + // vector.push_back(value); + // assert_eq!(count + 1, vector.len()); + // } + // for (index, value) in input.iter().cloned().rev().enumerate().rev() { + // match vector.pop_front() { + // None => panic!("vector emptied unexpectedly"), + // Some(item) => { + // assert_eq!(index, vector.len()); + // assert_eq!(value, item); + // } + // } + // } + // assert_eq!(true, vector.is_empty()); + // } + + #[test] + fn split(ref vec in vec(i32::ANY, 1..2000), split_pos in usize::ANY) { + let split_index = split_pos % (vec.len() + 1); + let mut left = vec.iter().cloned().collect::<Vector<_>>(); + let right = left.split_off(split_index); + assert_eq!(left.len(), split_index); + assert_eq!(right.len(), vec.len() - split_index); + for (index, item) in left.iter().enumerate() { + assert_eq!(& vec[index], item); + } + for (index, item) in right.iter().enumerate() { + assert_eq!(&vec[split_index + index], item); + } + } + + #[test] + fn append(ref vec1 in vec(i32::ANY, 0..1000), ref vec2 in vec(i32::ANY, 0..1000)) { + let mut seq1 = vec1.iter().cloned().collect::<Vector<_>>(); + let seq2 = vec2.iter().cloned().collect::<Vector<_>>(); + assert_eq!(seq1.len(), vec1.len()); + assert_eq!(seq2.len(), vec2.len()); + seq1.append(seq2); + let mut vec = vec1.clone(); + vec.extend(vec2); + assert_eq!(seq1.len(), vec.len()); + for (index, item) in seq1.into_iter().enumerate() { + assert_eq!(vec[index], item); + } + } + + #[test] + fn iter_mut(ref input in vector(i32::ANY, 0..10000)) { + let mut vec = input.clone(); + { + for p in vec.iter_mut() { + *p = p.overflowing_add(1).0; + } + } + let expected: Vector<i32> = input.clone().into_iter().map(|i| i.overflowing_add(1).0).collect(); + assert_eq!(expected, vec); + } + + #[test] + fn focus(ref input in vector(i32::ANY, 0..10000)) { + let mut vec = input.clone(); + { + let mut focus = vec.focus_mut(); + for i in 0..input.len() { + let p = focus.index_mut(i); + *p = p.overflowing_add(1).0; + } + } + let expected: Vector<i32> = input.clone().into_iter().map(|i| i.overflowing_add(1).0).collect(); + assert_eq!(expected, vec); + } + + #[test] + fn focus_mut_split(ref input in vector(i32::ANY, 0..10000)) { + let mut vec = input.clone(); + + fn split_down(focus: FocusMut<'_, i32>) { + let len = focus.len(); + if len < 8 { + for p in focus { + *p = p.overflowing_add(1).0; + } + } else { + let (left, right) = focus.split_at(len / 2); + split_down(left); + split_down(right); + } + } + + split_down(vec.focus_mut()); + + let expected: Vector<i32> = input.clone().into_iter().map(|i| i.overflowing_add(1).0).collect(); + assert_eq!(expected, vec); + } + + #[test] + fn chunks(ref input in vector(i32::ANY, 0..10000)) { + let output: Vector<_> = input.leaves().flatten().cloned().collect(); + assert_eq!(input, &output); + let rev_in: Vector<_> = input.iter().rev().cloned().collect(); + let rev_out: Vector<_> = input.leaves().rev().map(|c| c.iter().rev()).flatten().cloned().collect(); + assert_eq!(rev_in, rev_out); + } + + #[test] + fn chunks_mut(ref mut input_src in vector(i32::ANY, 0..10000)) { + let mut input = input_src.clone(); + #[allow(clippy::map_clone)] + let output: Vector<_> = input.leaves_mut().flatten().map(|v| *v).collect(); + assert_eq!(input, output); + let rev_in: Vector<_> = input.iter().rev().cloned().collect(); + let rev_out: Vector<_> = input.leaves_mut().rev().map(|c| c.iter().rev()).flatten().cloned().collect(); + assert_eq!(rev_in, rev_out); + } + + // The following two tests are very slow and there are unit tests above + // which test for regression of issue #55. It would still be good to + // run them occasionally. + + // #[test] + // fn issue55_back(count in 0..10000, slice_at in usize::ANY) { + // let count = count as usize; + // let slice_at = slice_at % count; + // let mut l = Vector::unit(0); + // for _ in 0..count { + // let mut tmp = Vector::unit(0); + // tmp.append(l); + // l = tmp; + // } + // let len = l.len(); + // l.slice(slice_at..len); + // } + + // #[test] + // fn issue55_fwd(count in 0..10000, slice_at in usize::ANY) { + // let count = count as usize; + // let slice_at = slice_at % count; + // let mut l = Vector::new(); + // for i in 0..count { + // l.append(Vector::unit(i)); + // } + // assert_eq!(Some(&slice_at), l.get(slice_at)); + // } + } +} |