From adc6484e14acb4fd9014d7e888586379385a22cb Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 26 Apr 2016 17:03:00 +0200 Subject: [PATCH] Add `ArrayVecCopy`, which is a copyable `ArrayVec` Fixes #32. --- src/copy.rs | 377 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 +- src/raw.rs | 4 +- src/vec.rs | 11 +- 4 files changed, 391 insertions(+), 7 deletions(-) create mode 100644 src/copy.rs diff --git a/src/copy.rs b/src/copy.rs new file mode 100644 index 00000000..8d31f04c --- /dev/null +++ b/src/copy.rs @@ -0,0 +1,377 @@ +use std::cmp; +use std::iter; +use std::ptr; +use std::ops; +use std::slice; + +// extra traits +use std::borrow::{Borrow, BorrowMut}; +use std::hash::{Hash, Hasher}; +use std::fmt; + +#[cfg(feature="std")] +use std::io; + +use Array; +use CapacityError; +use RangeArgument; +use array::Index; +use raw::Drain; +use raw::RawArrayVec; + +/// A vector with a fixed capacity that implements `Copy`. +pub struct ArrayVecCopy { + inner: RawArrayVec, +} + +impl ArrayVecCopy { + /// Create a new empty `ArrayVecCopy`. + /// + /// Capacity is inferred from the type parameter. + #[inline] + pub fn new() -> ArrayVecCopy { + ArrayVecCopy { + inner: RawArrayVec::new(), + } + } + + /// Return the number of elements in the `ArrayVecCopy`. + #[inline] + pub fn len(&self) -> usize { self.inner.len() } + + /// Return the capacity of the `ArrayVecCopy`. + #[inline] + pub fn capacity(&self) -> usize { self.inner.capacity() } + + /// Push `element` to the end of the vector. + /// + /// Returns `Ok` if the push succeeds. + /// + /// **Errors** if the backing array is not large enough to fit the + /// additional element. + #[inline] + pub fn push(&mut self, element: A::Item) -> Result<(), CapacityError> { + self.inner.push(element) + } + + /// Insert `element` in position `index`. + /// + /// Shift up all elements after `index`. If any is pushed out, `Err` is + /// returned. + /// + /// Return `Ok` if no element is shifted out. + #[inline] + pub fn insert(&mut self, index: usize, element: A::Item) + -> Result<(), CapacityError> + { + self.inner.insert(index, element) + } + + /// Remove the last element in the vector. + /// + /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. + #[inline] + pub fn pop(&mut self) -> Option { + self.inner.pop() + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This operation is O(1). + /// + /// Return `Some(` *element* `)` if the index is in bounds, else `None`. + #[inline] + pub fn swap_remove(&mut self, index: usize) -> Option { + self.inner.swap_remove(index) + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// Return `Some(` *element* `)` if the index is in bounds, else `None`. + #[inline] + pub fn remove(&mut self, index: usize) -> Option { + self.inner.remove(index) + } + + /// Remove all elements in the vector. + /// + /// This is a constant-time operation. + #[inline] + pub fn clear(&mut self) { + unsafe { + self.set_len(0); + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns false. + /// This method operates in place and preserves the order of the retained + /// elements. + #[inline] + pub fn retain(&mut self, f: F) + where F: FnMut(&mut A::Item) -> bool + { + self.inner.retain(f) + } + + /// Set the vector's length without dropping or moving out elements + /// + /// May panic if `length` is greater than the capacity. + /// + /// This function is `unsafe` because it changes the notion of the + /// number of “valid” elements in the vector. Use with care. + #[inline] + pub unsafe fn set_len(&mut self, length: usize) { + self.inner.set_len(length) + } + + + /// Create a draining iterator that removes the specified range in the vector + /// and yields the removed items from start to end. The element range is + /// removed even if the iterator is not consumed until the end. + /// + /// Note: It is unspecified how many elements are removed from the vector, + /// if the `Drain` value is leaked. + /// + /// **Panics** if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + pub fn drain(&mut self, range: R) -> Drain { + self.inner.drain(range) + } + + /// Return the inner fixed size array, if it is full to its capacity. + /// + /// Return an `Ok` value with the array if length equals capacity, + /// return an `Err` with self otherwise. + /// + /// `Note:` This function may incur unproportionally large overhead + /// to move the array out, its performance is not optimal. + pub fn into_inner(self) -> Result { + self.inner.into_inner().map_err(|e| ArrayVecCopy { inner: e }) + } + + /// Dispose of `self` without the overwriting that is needed in Drop. + pub fn dispose(self) { } + + /// Return a slice containing all elements of the vector. + pub fn as_slice(&self) -> &[A::Item] { + self.inner.as_slice() + } + + /// Return a mutable slice containing all elements of the vector. + pub fn as_mut_slice(&mut self) -> &mut [A::Item] { + self.inner.as_mut_slice() + } +} + +impl ops::Deref for ArrayVecCopy { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + self.inner.deref() + } +} + +impl ops::DerefMut for ArrayVecCopy { + #[inline] + fn deref_mut(&mut self) -> &mut [A::Item] { + self.inner.deref_mut() + } +} + +/// Create an `ArrayVecCopy` from an array. +impl From for ArrayVecCopy { + fn from(array: A) -> Self { + ArrayVecCopy { inner: RawArrayVec::from(array) } + } +} + + +/// Iterate the `ArrayVecCopy` with references to each element. +impl<'a, A: Array + Copy> IntoIterator for &'a ArrayVecCopy { + type Item = &'a A::Item; + type IntoIter = slice::Iter<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.inner.iter() } +} + +/// Iterate the `ArrayVecCopy` with mutable references to each element. +impl<'a, A: Array + Copy> IntoIterator for &'a mut ArrayVecCopy { + type Item = &'a mut A::Item; + type IntoIter = slice::IterMut<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.inner.iter_mut() } +} + +/// Iterate the `ArrayVecCopy` with each element by value. +/// +/// The vector is consumed by this operation. +impl IntoIterator for ArrayVecCopy { + type Item = A::Item; + type IntoIter = IntoIter; + fn into_iter(self) -> IntoIter { + IntoIter { index: Index::from(0), v: self } + } +} + + +/// By-value iterator for `ArrayVecCopy`. +pub struct IntoIter { + index: A::Index, + v: ArrayVecCopy, +} + +impl Iterator for IntoIter { + type Item = A::Item; + + #[inline] + fn next(&mut self) -> Option { + let index = self.index.to_usize(); + if index == self.v.len() { + None + } else { + unsafe { + self.index = Index::from(index + 1); + Some(ptr::read(self.v.get_unchecked_mut(index))) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.v.len() - self.index.to_usize(); + (len, Some(len)) + } +} + +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if self.index.to_usize() == self.v.len() { + None + } else { + unsafe { + let new_len = self.v.len() - 1; + self.v.set_len(new_len); + Some(ptr::read(self.v.get_unchecked_mut(new_len))) + } + } + } +} + +impl ExactSizeIterator for IntoIter { } + +/// Extend the `ArrayVecCopy` with an iterator. +/// +/// Does not extract more items than there is space for. No error +/// occurs if there are more iterator elements. +impl Extend for ArrayVecCopy { + fn extend>(&mut self, iter: T) { + self.inner.extend(iter) + } +} + +/// Create an `ArrayVecCopy` from an iterator. +/// +/// Does not extract more items than there is space for. No error +/// occurs if there are more iterator elements. +impl iter::FromIterator for ArrayVecCopy { + fn from_iter>(iter: T) -> Self { + ArrayVecCopy { inner: RawArrayVec::from_iter(iter) } + } +} + +impl Clone for ArrayVecCopy + where A::Item: Clone +{ + #[inline] + fn clone(&self) -> Self { + ArrayVecCopy { inner: self.inner.clone() } + } + + #[inline] + fn clone_from(&mut self, rhs: &Self) { + self.inner.clone_from(&rhs.inner) + } +} + +impl Hash for ArrayVecCopy + where A::Item: Hash +{ + fn hash(&self, state: &mut H) { + self.inner.hash(state) + } +} + +impl PartialEq for ArrayVecCopy + where A::Item: PartialEq +{ + fn eq(&self, other: &Self) -> bool { + use std::ops::Deref; + self.inner.eq(other.inner.deref()) + } +} + +impl PartialEq<[A::Item]> for ArrayVecCopy + where A::Item: PartialEq +{ + fn eq(&self, other: &[A::Item]) -> bool { + self.inner.eq(other) + } +} + +impl Eq for ArrayVecCopy where A::Item: Eq { } + +impl Borrow<[A::Item]> for ArrayVecCopy { + fn borrow(&self) -> &[A::Item] { self.inner.borrow() } +} + +impl BorrowMut<[A::Item]> for ArrayVecCopy { + fn borrow_mut(&mut self) -> &mut [A::Item] { self.inner.borrow_mut() } +} + +impl AsRef<[A::Item]> for ArrayVecCopy { + fn as_ref(&self) -> &[A::Item] { self.inner.as_ref() } +} + +impl AsMut<[A::Item]> for ArrayVecCopy { + fn as_mut(&mut self) -> &mut [A::Item] { self.inner.as_mut() } +} + +impl fmt::Debug for ArrayVecCopy where A::Item: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.fmt(f) } +} + +impl Default for ArrayVecCopy { + fn default() -> ArrayVecCopy { + ArrayVecCopy::new() + } +} + +impl PartialOrd for ArrayVecCopy where A::Item: PartialOrd { + #[inline] + fn partial_cmp(&self, other: &ArrayVecCopy) -> Option { + self.inner.partial_cmp(&other.inner) + } + + #[inline] fn lt(&self, other: &Self) -> bool { self.inner.lt(&other.inner) } + #[inline] fn le(&self, other: &Self) -> bool { self.inner.le(&other.inner) } + #[inline] fn ge(&self, other: &Self) -> bool { self.inner.ge(&other.inner) } + #[inline] fn gt(&self, other: &Self) -> bool { self.inner.gt(&other.inner) } +} + +impl Ord for ArrayVecCopy where A::Item: Ord { + fn cmp(&self, other: &ArrayVecCopy) -> cmp::Ordering { + self.inner.cmp(&other.inner) + } +} + +#[cfg(feature="std")] +/// `Write` appends written data to the end of the vector. +/// +/// Requires `features="std"`. +impl + Copy> io::Write for ArrayVecCopy { + fn write(&mut self, data: &[u8]) -> io::Result { + self.inner.write(data) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} diff --git a/src/lib.rs b/src/lib.rs index 09dcbf5e..17b01027 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -//! **arrayvec** provides the types `ArrayVec` and `ArrayString`: +//! **arrayvec** provides the types `ArrayVec` and `ArrayString`: //! array-backed vector and string types, which store their contents inline. //! //! The **arrayvec** crate has the following cargo feature flags: @@ -16,11 +16,15 @@ extern crate nodrop; extern crate core as std; pub use array::Array; +pub use copy::ArrayVecCopy; pub use odds::IndexRange as RangeArgument; +pub use raw::Drain; pub use string::ArrayString; pub use vec::ArrayVec; +pub use vec::IntoIter; mod array; +mod copy; mod raw; mod string; mod vec; diff --git a/src/raw.rs b/src/raw.rs index 6e9aae5c..6bf3d915 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -232,7 +232,7 @@ impl<'a, A: Array> IntoIterator for &'a mut RawArrayVec { } /// A draining iterator for `RawArrayVec`. -pub struct Drain<'a, A> +pub struct Drain<'a, A> where A: Array, A::Item: 'a, { @@ -283,7 +283,7 @@ impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} -impl<'a, A: Array> Drop for Drain<'a, A> +impl<'a, A: Array> Drop for Drain<'a, A> where A::Item: 'a { fn drop(&mut self) { diff --git a/src/vec.rs b/src/vec.rs index 1d49f555..8854d999 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -272,8 +272,9 @@ impl ArrayVec { } /// Dispose of `self` without the overwriting that is needed in Drop. - pub fn dispose(mut self) { - self.inner.clear() + pub fn dispose(&mut self) { + self.clear(); + mem::forget(self); } /// Return a slice containing all elements of the vector. @@ -435,7 +436,7 @@ impl Drop for IntoIter { } /// Extend the `ArrayVec` with an iterator. -/// +/// /// Does not extract more items than there is space for. No error /// occurs if there are more iterator elements. impl Extend for ArrayVec { @@ -445,11 +446,13 @@ impl Extend for ArrayVec { } /// Create an `ArrayVec` from an iterator. -/// +/// /// Does not extract more items than there is space for. No error /// occurs if there are more iterator elements. impl iter::FromIterator for ArrayVec { fn from_iter>(iter: T) -> Self { + // Cannot use `RawArrayVec::from_iter` because it's not wrapped in + // `ArrayVec` immediately which makes it panic-unsafe. let mut array = ArrayVec::new(); array.extend(iter); array