From ae48f8e4ae0fc0efc2409094e18f5f97e22f3b99 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 26 Apr 2016 16:41:04 +0200 Subject: [PATCH 1/2] Add `RawArrayVec` backing both `ArrayString` and `ArrayVec` `RawArrayVec` does not concern itself with the dropping or non-dropping of elements when it goes out of scope. --- src/lib.rs | 795 +---------------------------- src/raw.rs | 439 ++++++++++++++++ src/{array_string.rs => string.rs} | 36 +- src/vec.rs | 582 +++++++++++++++++++++ tests/tests.rs | 6 +- 5 files changed, 1045 insertions(+), 813 deletions(-) create mode 100644 src/raw.rs rename src/{array_string.rs => string.rs} (88%) create mode 100644 src/vec.rs diff --git a/src/lib.rs b/src/lib.rs index 1bb33ae9..9def947d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,810 +14,29 @@ //! - Use the unstable feature untagged unions for the internal implementation, //! which has reduced space overhead #![cfg_attr(not(feature="std"), no_std)] + extern crate odds; extern crate nodrop; #[cfg(not(feature="std"))] extern crate core as std; -use std::cmp; -use std::iter; -use std::mem; -use std::ptr; -use std::ops::{ - Deref, - DerefMut, -}; -use std::slice; - -// extra traits -use std::borrow::{Borrow, BorrowMut}; -use std::hash::{Hash, Hasher}; use std::fmt; - -#[cfg(feature="std")] -use std::io; #[cfg(feature="std")] use std::error::Error; #[cfg(feature="std")] use std::any::Any; // core but unused -use nodrop::NoDrop; - mod array; -mod array_string; +mod string; +mod vec; +mod raw; pub use array::Array; pub use odds::IndexRange as RangeArgument; -use array::Index; -pub use array_string::ArrayString; - - -unsafe fn new_array() -> A { - // Note: Returning an uninitialized value here only works - // if we can be sure the data is never used. The nullable pointer - // inside enum optimization conflicts with this this for example, - // so we need to be extra careful. See `NoDrop` enum. - mem::uninitialized() -} - -/// A vector with a fixed capacity. -/// -/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of -/// the number of initialized elements. -/// -/// The vector is a contiguous value that you can store directly on the stack -/// if needed. -/// -/// It offers a simple API but also dereferences to a slice, so -/// that the full slice API is available. -/// -/// ArrayVec can be converted into a by value iterator. -pub struct ArrayVec { - xs: NoDrop, - len: A::Index, -} - -impl Drop for ArrayVec { - fn drop(&mut self) { - self.clear(); - - // NoDrop inhibits array's drop - // panic safety: NoDrop::drop will trigger on panic, so the inner - // array will not drop even after panic. - } -} - -impl ArrayVec { - /// Create a new empty `ArrayVec`. - /// - /// Capacity is inferred from the type parameter. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 16]>::new(); - /// array.push(1); - /// array.push(2); - /// assert_eq!(&array[..], &[1, 2]); - /// assert_eq!(array.capacity(), 16); - /// ``` - pub fn new() -> ArrayVec { - unsafe { - ArrayVec { xs: NoDrop::new(new_array()), len: Index::from(0) } - } - } - - /// Return the number of elements in the `ArrayVec`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// array.pop(); - /// assert_eq!(array.len(), 2); - /// ``` - #[inline] - pub fn len(&self) -> usize { self.len.to_usize() } - - /// Return the capacity of the `ArrayVec`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let array = ArrayVec::from([1, 2, 3]); - /// assert_eq!(array.capacity(), 3); - /// ``` - #[inline] - pub fn capacity(&self) -> usize { A::capacity() } - - /// Return if the `ArrayVec` is completely filled. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 1]>::new(); - /// assert!(!array.is_full()); - /// array.push(1); - /// assert!(array.is_full()); - /// ``` - pub fn is_full(&self) -> bool { self.len() == self.capacity() } - - /// Push `element` to the end of the vector. - /// - /// Return `None` if the push succeeds, or and return `Some(` *element* `)` - /// if the vector is full. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// array.push(1); - /// array.push(2); - /// let overflow = array.push(3); - /// - /// assert_eq!(&array[..], &[1, 2]); - /// assert_eq!(overflow, Some(3)); - /// ``` - pub fn push(&mut self, element: A::Item) -> Option { - if self.len() < A::capacity() { - let len = self.len(); - unsafe { - ptr::write(self.get_unchecked_mut(len), element); - self.set_len(len + 1); - } - None - } else { - Some(element) - } - } - - /// Insert `element` in position `index`. - /// - /// Shift up all elements after `index`. If any is pushed out, it is returned. - /// - /// Return `None` if no element is shifted out. - /// - /// `index` must be <= `self.len()` and < `self.capacity()`. Note that any - /// out of bounds index insert results in the element being "shifted out" - /// and returned directly. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// assert_eq!(array.insert(0, "x"), None); - /// assert_eq!(array.insert(0, "y"), None); - /// assert_eq!(array.insert(0, "z"), Some("x")); - /// assert_eq!(array.insert(1, "w"), Some("y")); - /// assert_eq!(&array[..], &["z", "w"]); - /// - /// ``` - pub fn insert(&mut self, index: usize, element: A::Item) -> Option { - if index > self.len() || index == self.capacity() { - return Some(element); - } - let mut ret = None; - if self.len() == self.capacity() { - ret = self.pop(); - } - let len = self.len(); - - // follows is just like Vec - unsafe { // infallible - // The spot to put the new value - { - let p = self.get_unchecked_mut(index) as *mut _; - // Shift everything over to make space. (Duplicating the - // `index`th element into two consecutive places.) - ptr::copy(p, p.offset(1), len - index); - // Write it in, overwriting the first copy of the `index`th - // element. - ptr::write(p, element); - } - self.set_len(len + 1); - } - ret - } - - /// Remove the last element in the vector. - /// - /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// array.push(1); - /// - /// assert_eq!(array.pop(), Some(1)); - /// assert_eq!(array.pop(), None); - /// ``` - pub fn pop(&mut self) -> Option { - if self.len() == 0 { - return None - } - unsafe { - let new_len = self.len() - 1; - self.set_len(new_len); - Some(ptr::read(self.get_unchecked_mut(new_len))) - } - } - - /// 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`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// - /// assert_eq!(array.swap_remove(0), Some(1)); - /// assert_eq!(&array[..], &[3, 2]); - /// - /// assert_eq!(array.swap_remove(10), None); - /// ``` - pub fn swap_remove(&mut self, index: usize) -> Option { - let len = self.len(); - if index >= len { - return None - } - self.swap(index, len - 1); - self.pop() - } - - /// Remove the element at `index` and shift down the following elements. - /// - /// Return `Some(` *element* `)` if the index is in bounds, else `None`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// - /// assert_eq!(array.remove(0), Some(1)); - /// assert_eq!(&array[..], &[2, 3]); - /// - /// assert_eq!(array.remove(10), None); - /// ``` - pub fn remove(&mut self, index: usize) -> Option { - if index >= self.len() { - None - } else { - self.drain(index..index + 1).next() - } - } - - /// Remove all elements in the vector. - pub fn clear(&mut self) { - while let Some(_) = self.pop() { } - } - - /// 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. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3, 4]); - /// array.retain(|x| *x & 1 != 0 ); - /// assert_eq!(&array[..], &[1, 3]); - /// ``` - pub fn retain(&mut self, mut f: F) - where F: FnMut(&mut A::Item) -> bool - { - let len = self.len(); - let mut del = 0; - { - let v = &mut **self; - - for i in 0..len { - if !f(&mut v[i]) { - del += 1; - } else if del > 0 { - v.swap(i - del, i); - } - } - } - if del > 0 { - self.drain(len - del..); - } - } - - /// 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) { - debug_assert!(length <= self.capacity()); - self.len = Index::from(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. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut v = ArrayVec::from([1, 2, 3]); - /// let u: Vec<_> = v.drain(0..2).collect(); - /// assert_eq!(&v[..], &[3]); - /// assert_eq!(&u[..], &[1, 2]); - /// ``` - pub fn drain(&mut self, range: R) -> Drain { - // Memory safety - // - // When the Drain is first created, it shortens the length of - // the source vector to make sure no uninitalized or moved-from elements - // are accessible at all if the Drain's destructor never gets to run. - // - // Drain will ptr::read out the values to remove. - // When finished, remaining tail of the vec is copied back to cover - // the hole, and the vector length is restored to the new length. - // - let len = self.len(); - let start = range.start().unwrap_or(0); - let end = range.end().unwrap_or(len); - // bounds check happens here - let range_slice: *const _ = &self[start..end]; - - unsafe { - // set self.vec length's to start, to be safe in case Drain is leaked - self.set_len(start); - Drain { - tail_start: end, - tail_len: len - end, - iter: (*range_slice).iter(), - vec: self as *mut _, - } - } - } - - /// 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 { - if self.len() < self.capacity() { - Err(self) - } else { - unsafe { - let array = ptr::read(&*self.xs); - mem::forget(self); - Ok(array) - } - } - } - - /// Dispose of `self` without the overwriting that is needed in Drop. - pub fn dispose(mut self) { - self.clear(); - mem::forget(self); - } - - /// Return a slice containing all elements of the vector. - pub fn as_slice(&self) -> &[A::Item] { - self - } - - /// Return a mutable slice containing all elements of the vector. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { - self - } -} - -impl Deref for ArrayVec { - type Target = [A::Item]; - #[inline] - fn deref(&self) -> &[A::Item] { - unsafe { - slice::from_raw_parts(self.xs.as_ptr(), self.len()) - } - } -} - -impl DerefMut for ArrayVec { - #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { - let len = self.len(); - unsafe { - slice::from_raw_parts_mut(self.xs.as_mut_ptr(), len) - } - } -} - -/// Create an `ArrayVec` from an array. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// let mut array = ArrayVec::from([1, 2, 3]); -/// assert_eq!(array.len(), 3); -/// assert_eq!(array.capacity(), 3); -/// ``` -impl From for ArrayVec { - fn from(array: A) -> Self { - ArrayVec { xs: NoDrop::new(array), len: Index::from(A::capacity()) } - } -} - - -/// Iterate the `ArrayVec` with references to each element. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// let array = ArrayVec::from([1, 2, 3]); -/// -/// for elt in &array { -/// // ... -/// } -/// ``` -impl<'a, A: Array> IntoIterator for &'a ArrayVec { - type Item = &'a A::Item; - type IntoIter = slice::Iter<'a, A::Item>; - fn into_iter(self) -> Self::IntoIter { self.iter() } -} - -/// Iterate the `ArrayVec` with mutable references to each element. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// let mut array = ArrayVec::from([1, 2, 3]); -/// -/// for elt in &mut array { -/// // ... -/// } -/// ``` -impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { - type Item = &'a mut A::Item; - type IntoIter = slice::IterMut<'a, A::Item>; - fn into_iter(self) -> Self::IntoIter { self.iter_mut() } -} - -/// Iterate the `ArrayVec` with each element by value. -/// -/// The vector is consumed by this operation. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// for elt in ArrayVec::from([1, 2, 3]) { -/// // ... -/// } -/// ``` -impl IntoIterator for ArrayVec { - type Item = A::Item; - type IntoIter = IntoIter; - fn into_iter(self) -> IntoIter { - IntoIter { index: Index::from(0), v: self, } - } -} - - -/// By-value iterator for `ArrayVec`. -pub struct IntoIter { - index: A::Index, - v: ArrayVec, -} - -impl Iterator for IntoIter { - type Item = A::Item; - - #[inline] - fn next(&mut self) -> Option { - if self.index == self.v.len { - None - } else { - unsafe { - let index = self.index.to_usize(); - self.index = Index::from(index + 1); - Some(ptr::read(self.v.get_unchecked_mut(index))) - } - } - } - - 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 == 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 { } - -impl Drop for IntoIter { - fn drop(&mut self) { - // panic safety: Set length to 0 before dropping elements. - let index = self.index.to_usize(); - let len = self.v.len(); - unsafe { - self.v.set_len(0); - let elements = slice::from_raw_parts(self.v.get_unchecked_mut(index), - len - index); - for elt in elements { - ptr::read(elt); - } - } - } -} - -/// A draining iterator for `ArrayVec`. -pub struct Drain<'a, A> - where A: Array, - A::Item: 'a, -{ - /// Index of tail to preserve - tail_start: usize, - /// Length of tail - tail_len: usize, - /// Current remaining range to remove - iter: slice::Iter<'a, A::Item>, - vec: *mut ArrayVec, -} - -unsafe impl<'a, A: Array + Sync> Sync for Drain<'a, A> {} -unsafe impl<'a, A: Array + Send> Send for Drain<'a, A> {} - -impl<'a, A: Array> Iterator for Drain<'a, A> - where A::Item: 'a, -{ - type Item = A::Item; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| - unsafe { - ptr::read(elt as *const _) - } - ) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> - where A::Item: 'a, -{ - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|elt| - unsafe { - ptr::read(elt as *const _) - } - ) - } -} - -impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} - -impl<'a, A: Array> Drop for Drain<'a, A> - where A::Item: 'a -{ - fn drop(&mut self) { - // len is currently 0 so panicking while dropping will not cause a double drop. - - // exhaust self first - while let Some(_) = self.next() { } - - if self.tail_len > 0 { - unsafe { - let source_vec = &mut *self.vec; - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.tail_start; - let src = source_vec.as_ptr().offset(tail as isize); - let dst = source_vec.as_mut_ptr().offset(start as isize); - ptr::copy(src, dst, self.tail_len); - source_vec.set_len(start + self.tail_len); - } - } - } -} - - - - -/// 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 { - fn extend>(&mut self, iter: T) { - let take = self.capacity() - self.len(); - for elt in iter.into_iter().take(take) { - self.push(elt); - } - } -} - -/// 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 { - let mut array = ArrayVec::new(); - array.extend(iter); - array - } -} - -impl Clone for ArrayVec - where A::Item: Clone -{ - fn clone(&self) -> Self { - self.iter().cloned().collect() - } - - fn clone_from(&mut self, rhs: &Self) { - // recursive case for the common prefix - let prefix = cmp::min(self.len(), rhs.len()); - { - let a = &mut self[..prefix]; - let b = &rhs[..prefix]; - for i in 0..prefix { - a[i].clone_from(&b[i]); - } - } - if prefix < self.len() { - // rhs was shorter - for _ in 0..self.len() - prefix { - self.pop(); - } - } else { - for elt in &rhs[self.len()..] { - self.push(elt.clone()); - } - } - } -} - -impl Hash for ArrayVec - where A::Item: Hash -{ - fn hash(&self, state: &mut H) { - Hash::hash(&**self, state) - } -} - -impl PartialEq for ArrayVec - where A::Item: PartialEq -{ - fn eq(&self, other: &Self) -> bool { - **self == **other - } -} - -impl PartialEq<[A::Item]> for ArrayVec - where A::Item: PartialEq -{ - fn eq(&self, other: &[A::Item]) -> bool { - **self == *other - } -} - -impl Eq for ArrayVec where A::Item: Eq { } - -impl Borrow<[A::Item]> for ArrayVec { - fn borrow(&self) -> &[A::Item] { self } -} - -impl BorrowMut<[A::Item]> for ArrayVec { - fn borrow_mut(&mut self) -> &mut [A::Item] { self } -} - -impl AsRef<[A::Item]> for ArrayVec { - fn as_ref(&self) -> &[A::Item] { self } -} - -impl AsMut<[A::Item]> for ArrayVec { - fn as_mut(&mut self) -> &mut [A::Item] { self } -} - -impl fmt::Debug for ArrayVec where A::Item: fmt::Debug { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } -} - -impl Default for ArrayVec { - fn default() -> ArrayVec { - ArrayVec::new() - } -} - -impl PartialOrd for ArrayVec where A::Item: PartialOrd { - #[inline] - fn partial_cmp(&self, other: &ArrayVec) -> Option { - (**self).partial_cmp(other) - } - - #[inline] - fn lt(&self, other: &Self) -> bool { - (**self).lt(other) - } - - #[inline] - fn le(&self, other: &Self) -> bool { - (**self).le(other) - } - - #[inline] - fn ge(&self, other: &Self) -> bool { - (**self).ge(other) - } - - #[inline] - fn gt(&self, other: &Self) -> bool { - (**self).gt(other) - } -} - -impl Ord for ArrayVec where A::Item: Ord { - fn cmp(&self, other: &ArrayVec) -> cmp::Ordering { - (**self).cmp(other) - } -} - -#[cfg(feature="std")] -/// `Write` appends written data to the end of the vector. -/// -/// Requires `features="std"`. -impl> io::Write for ArrayVec { - fn write(&mut self, data: &[u8]) -> io::Result { - unsafe { - let len = self.len(); - let mut tail = slice::from_raw_parts_mut(self.get_unchecked_mut(len), - A::capacity() - len); - let result = tail.write(data); - if let Ok(written) = result { - self.set_len(len + written); - } - result - } - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } -} +pub use raw::Drain; +pub use string::ArrayString; +pub use vec::ArrayVec; /// Error value indicating insufficient capacity #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] diff --git a/src/raw.rs b/src/raw.rs new file mode 100644 index 00000000..72055d37 --- /dev/null +++ b/src/raw.rs @@ -0,0 +1,439 @@ +use CapacityError; +use RangeArgument; +use array::Array; +use std::borrow::{Borrow, BorrowMut}; +use std::cmp; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::iter; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::ptr; +use std::slice; + +#[cfg(feature="std")] +use std::io; + +use array::Index; + +pub struct RawArrayVec { + xs: A, + len: A::Index, +} + +impl RawArrayVec { + #[inline] + pub fn new() -> RawArrayVec { + unsafe { + RawArrayVec { + xs: mem::uninitialized(), + len: Index::from(0), + } + } + } + + #[inline] pub fn len(&self) -> usize { self.len.to_usize() } + #[inline] pub fn capacity(&self) -> usize { A::capacity() } + #[inline] pub fn is_full(&self) -> bool { self.len() == self.capacity() } + + pub fn push(&mut self, element: A::Item) -> Result<(), CapacityError> { + if self.len() < A::capacity() { + let len = self.len(); + unsafe { + ptr::write(self.get_unchecked_mut(len), element); + self.set_len(len + 1); + } + Ok(()) + } else { + Err(CapacityError::new(element)) + } + } + + pub fn insert(&mut self, index: usize, element: A::Item) + -> Result<(), CapacityError> + { + assert!(index <= self.len()); + if index == self.capacity() { + return Err(CapacityError::new(element)); + } + let ret = if self.len() == self.capacity() { + Err(CapacityError::new(self.pop().unwrap())) + } else { + Ok(()) + }; + let len = self.len(); + + // follows is just like Vec + unsafe { // infallible + // The spot to put the new value + { + let p = self.get_unchecked_mut(index) as *mut _; + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + ret + } + + pub fn pop(&mut self) -> Option { + if self.len() == 0 { + return None + } + unsafe { + let new_len = self.len() - 1; + self.set_len(new_len); + Some(ptr::read(self.get_unchecked_mut(new_len))) + } + } + + pub fn swap_remove(&mut self, index: usize) -> Option { + let len = self.len(); + if index >= len { + return None + } + self.swap(index, len - 1); + self.pop() + } + + pub fn remove(&mut self, index: usize) -> Option { + if index >= self.len() { + None + } else { + self.drain(index..index + 1).next() + } + } + + pub fn clear(&mut self) { + while let Some(_) = self.pop() { } + } + + pub fn retain(&mut self, mut f: F) + where F: FnMut(&mut A::Item) -> bool + { + let len = self.len(); + let mut del = 0; + { + let v = &mut **self; + + for i in 0..len { + if !f(&mut v[i]) { + del += 1; + } else if del > 0 { + v.swap(i - del, i); + } + } + } + if del > 0 { + self.drain(len - del..); + } + } + + pub unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= self.capacity()); + self.len = Index::from(length); + } + + pub fn drain(&mut self, range: R) -> Drain { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitalized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let start = range.start().unwrap_or(0); + let end = range.end().unwrap_or(len); + // bounds check happens here + let range_slice: *const _ = &self[start..end]; + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + self.set_len(start); + Drain { + tail_start: end, + tail_len: len - end, + iter: (*range_slice).iter(), + vec: self as *mut _, + } + } + } + + pub fn into_inner(self) -> Result { + if self.len() < self.capacity() { + Err(self) + } else { + unsafe { + let array = ptr::read(&self.xs); + mem::forget(self); + Ok(array) + } + } + } + + #[inline] pub fn dispose(self) { } + #[inline] pub fn as_slice(&self) -> &[A::Item] { self } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [A::Item] { self } +} + +impl Deref for RawArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + unsafe { + slice::from_raw_parts(self.xs.as_ptr(), self.len()) + } + } +} + +impl DerefMut for RawArrayVec { + #[inline] + fn deref_mut(&mut self) -> &mut [A::Item] { + let len = self.len(); + unsafe { + slice::from_raw_parts_mut(self.xs.as_mut_ptr(), len) + } + } +} + +impl From for RawArrayVec { + fn from(array: A) -> Self { + RawArrayVec { + xs: array, + len: Index::from(A::capacity()), + } + } +} + +impl<'a, A: Array> IntoIterator for &'a RawArrayVec { + type Item = &'a A::Item; + type IntoIter = slice::Iter<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.iter() } +} + +impl<'a, A: Array> IntoIterator for &'a mut RawArrayVec { + type Item = &'a mut A::Item; + type IntoIter = slice::IterMut<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } +} + +/// A draining iterator for `ArrayVec`. +pub struct Drain<'a, A> + where A: Array, + A::Item: 'a, +{ + /// Index of tail to preserve + tail_start: usize, + /// Length of tail + tail_len: usize, + /// Current remaining range to remove + iter: slice::Iter<'a, A::Item>, + vec: *mut RawArrayVec, +} + +unsafe impl<'a, A: Array + Sync> Sync for Drain<'a, A> {} +unsafe impl<'a, A: Array + Send> Send for Drain<'a, A> {} + +impl<'a, A: Array> Iterator for Drain<'a, A> + where A::Item: 'a, +{ + type Item = A::Item; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> + where A::Item: 'a, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } +} + +impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} + +impl<'a, A: Array> Drop for Drain<'a, A> + where A::Item: 'a +{ + fn drop(&mut self) { + // len is currently 0 so panicking while dropping will not cause a double drop. + + // exhaust self first + while let Some(_) = self.next() { } + + if self.tail_len > 0 { + unsafe { + let source_vec = &mut *self.vec; + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.tail_start; + let src = source_vec.as_ptr().offset(tail as isize); + let dst = source_vec.as_mut_ptr().offset(start as isize); + ptr::copy(src, dst, self.tail_len); + source_vec.set_len(start + self.tail_len); + } + } + } +} + +impl Extend for RawArrayVec { + fn extend>(&mut self, iter: T) { + let take = self.capacity() - self.len(); + for elt in iter.into_iter().take(take) { + let _ = self.push(elt); + } + } +} + +impl iter::FromIterator for RawArrayVec { + fn from_iter>(iter: T) -> Self { + let mut array = RawArrayVec::new(); + array.extend(iter); + array + } +} + +impl Copy for RawArrayVec where A::Item: Clone { } + +impl Clone for RawArrayVec + where A::Item: Clone +{ + fn clone(&self) -> Self { + self.iter().cloned().collect() + } + + fn clone_from(&mut self, rhs: &Self) { + // recursive case for the common prefix + let prefix = cmp::min(self.len(), rhs.len()); + { + let a = &mut self[..prefix]; + let b = &rhs[..prefix]; + for i in 0..prefix { + a[i].clone_from(&b[i]); + } + } + if prefix < self.len() { + // rhs was shorter + for _ in 0..self.len() - prefix { + self.pop(); + } + } else { + for elt in &rhs[self.len()..] { + let _ = self.push(elt.clone()); + } + } + } +} + +impl Hash for RawArrayVec + where A::Item: Hash +{ + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +impl PartialEq for RawArrayVec + where A::Item: PartialEq +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} + +impl PartialEq<[A::Item]> for RawArrayVec + where A::Item: PartialEq +{ + fn eq(&self, other: &[A::Item]) -> bool { + **self == *other + } +} + +impl Eq for RawArrayVec where A::Item: Eq { } + +impl Borrow<[A::Item]> for RawArrayVec { + fn borrow(&self) -> &[A::Item] { self } +} + +impl BorrowMut<[A::Item]> for RawArrayVec { + fn borrow_mut(&mut self) -> &mut [A::Item] { self } +} + +impl AsRef<[A::Item]> for RawArrayVec { + fn as_ref(&self) -> &[A::Item] { self } +} + +impl AsMut<[A::Item]> for RawArrayVec { + fn as_mut(&mut self) -> &mut [A::Item] { self } +} + +impl fmt::Debug for RawArrayVec where A::Item: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +impl Default for RawArrayVec { + fn default() -> RawArrayVec { + RawArrayVec::new() + } +} + +impl PartialOrd for RawArrayVec where A::Item: PartialOrd { + #[inline] + fn partial_cmp(&self, other: &RawArrayVec) -> Option { + (**self).partial_cmp(other) + } + + #[inline] fn lt(&self, other: &Self) -> bool { (**self).lt(other) } + #[inline] fn le(&self, other: &Self) -> bool { (**self).le(other) } + #[inline] fn ge(&self, other: &Self) -> bool { (**self).ge(other) } + #[inline] fn gt(&self, other: &Self) -> bool { (**self).gt(other) } +} + +impl Ord for RawArrayVec where A::Item: Ord { + fn cmp(&self, other: &RawArrayVec) -> cmp::Ordering { + (**self).cmp(other) + } +} + +#[cfg(feature="std")] +impl> io::Write for RawArrayVec { + fn write(&mut self, data: &[u8]) -> io::Result { + unsafe { + let len = self.len(); + let mut tail = slice::from_raw_parts_mut(self.get_unchecked_mut(len), + A::capacity() - len); + let result = tail.write(data); + if let Ok(written) = result { + self.set_len(len + written); + } + result + } + } + #[inline] + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} diff --git a/src/array_string.rs b/src/string.rs similarity index 88% rename from src/array_string.rs rename to src/string.rs index ee1b0aa0..a3d7bcaa 100644 --- a/src/array_string.rs +++ b/src/string.rs @@ -5,11 +5,10 @@ use std::mem; use std::ptr; use std::ops::{Deref, DerefMut}; use std::str; -use std::slice; -use array::Array; -use array::Index; +use Array; use CapacityError; +use raw::RawArrayVec; /// A string with a fixed capacity. /// @@ -18,12 +17,12 @@ use CapacityError; /// /// The string is a contiguous value that you can store directly on the stack /// if needed. -#[derive(Copy)] pub struct ArrayString> { - xs: A, - len: A::Index, + inner: RawArrayVec, } +impl + Copy> Copy for ArrayString where A::Item: Clone { } + impl> ArrayString { /// Create a new empty `ArrayString`. /// @@ -38,11 +37,8 @@ impl> ArrayString { /// assert_eq!(string.capacity(), 16); /// ``` pub fn new() -> ArrayString { - unsafe { - ArrayString { - xs: ::new_array(), - len: Index::from(0), - } + ArrayString { + inner: RawArrayVec::new(), } } @@ -75,7 +71,7 @@ impl> ArrayString { /// assert_eq!(string.capacity(), 3); /// ``` #[inline] - pub fn capacity(&self) -> usize { A::capacity() } + pub fn capacity(&self) -> usize { self.inner.capacity() } /// Return if the `ArrayString` is completely filled. /// @@ -137,7 +133,7 @@ impl> ArrayString { return Err(CapacityError::new(s)); } unsafe { - let dst = self.xs.as_mut_ptr().offset(self.len() as isize); + let dst = self.inner.as_mut_ptr().offset(self.len() as isize); let src = s.as_ptr(); ptr::copy_nonoverlapping(src, dst, s.len()); let newl = self.len() + s.len(); @@ -161,8 +157,7 @@ impl> ArrayString { /// number of “valid” bytes in the string. Use with care. #[inline] pub unsafe fn set_len(&mut self, length: usize) { - debug_assert!(length <= self.capacity()); - self.len = Index::from(length); + self.inner.set_len(length) } /// Return a string slice of the whole `ArrayString`. @@ -176,8 +171,7 @@ impl> Deref for ArrayString { #[inline] fn deref(&self) -> &str { unsafe { - let sl = slice::from_raw_parts(self.xs.as_ptr(), self.len.to_usize()); - str::from_utf8_unchecked(sl) + str::from_utf8_unchecked(&self.inner) } } } @@ -186,9 +180,8 @@ impl> DerefMut for ArrayString { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { - let sl = slice::from_raw_parts_mut(self.xs.as_mut_ptr(), self.len.to_usize()); - // FIXME: Nothing but transmute to do this right now - mem::transmute(sl) + let bytes: &mut [u8] = &mut self.inner; + mem::transmute(bytes) } } } @@ -246,10 +239,9 @@ impl + Copy> Clone for ArrayString { fn clone(&self) -> ArrayString { *self } - fn clone_from(&mut self, rhs: &Self) { // guaranteed to fit due to types matching. self.clear(); - self.push_str(rhs).ok(); + let _ = self.push_str(rhs); } } diff --git a/src/vec.rs b/src/vec.rs new file mode 100644 index 00000000..29c9db31 --- /dev/null +++ b/src/vec.rs @@ -0,0 +1,582 @@ +use RangeArgument; +use array::Array; +use raw::RawArrayVec; +use raw::Drain; +use std::borrow::{Borrow, BorrowMut}; +use std::cmp; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::iter; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::ptr; +use std::slice; + +#[cfg(feature="std")] +use std::io; + +use nodrop::NoDrop; + +use array::Index; + +/// A vector with a fixed capacity. +/// +/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of +/// the number of initialized elements. +/// +/// The vector is a contiguous value that you can store directly on the stack +/// if needed. +/// +/// It offers a simple API but also dereferences to a slice, so +/// that the full slice API is available. +/// +/// ArrayVec can be converted into a by value iterator. +pub struct ArrayVec { + inner: NoDrop>, +} + +impl Drop for ArrayVec { + fn drop(&mut self) { + self.clear(); + + // NoDrop inhibits array's drop + // panic safety: NoDrop::drop will trigger on panic, so the inner + // array will not drop even after panic. + } +} + +impl ArrayVec { + /// Create a new empty `ArrayVec`. + /// + /// Capacity is inferred from the type parameter. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 16]>::new(); + /// array.push(1); + /// array.push(2); + /// assert_eq!(&array[..], &[1, 2]); + /// assert_eq!(array.capacity(), 16); + /// ``` + pub fn new() -> ArrayVec { + ArrayVec { + inner: NoDrop::new(RawArrayVec::new()) + } + } + + /// Return the number of elements in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.len(), 2); + /// ``` + #[inline] + pub fn len(&self) -> usize { self.inner.len() } + + /// Return the capacity of the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let array = ArrayVec::from([1, 2, 3]); + /// assert_eq!(array.capacity(), 3); + /// ``` + #[inline] + pub fn capacity(&self) -> usize { self.inner.capacity() } + + /// Return if the `ArrayVec` is completely filled. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 1]>::new(); + /// assert!(!array.is_full()); + /// array.push(1); + /// assert!(array.is_full()); + /// ``` + #[inline] + pub fn is_full(&self) -> bool { self.inner.is_full() } + + /// Push `element` to the end of the vector. + /// + /// Return `None` if the push succeeds, or and return `Some(` *element* `)` + /// if the vector is full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// array.push(1); + /// array.push(2); + /// let overflow = array.push(3); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// assert_eq!(overflow, Some(3)); + /// ``` + #[inline] + pub fn push(&mut self, element: A::Item) -> Option { + self.inner.push(element).err().map(|e| e.element()) + } + + /// Insert `element` in position `index`. + /// + /// Shift up all elements after `index`. If any is pushed out, it is returned. + /// + /// Return `None` if no element is shifted out. + /// + /// `index` must be <= `self.len()` and < `self.capacity()`. Note that any + /// out of bounds index insert results in the element being "shifted out" + /// and returned directly. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// assert_eq!(array.insert(0, "x"), None); + /// assert_eq!(array.insert(0, "y"), None); + /// assert_eq!(array.insert(0, "z"), Some("x")); + /// assert_eq!(array.insert(1, "w"), Some("y")); + /// assert_eq!(&array[..], &["z", "w"]); + /// + /// ``` + #[inline] + pub fn insert(&mut self, index: usize, element: A::Item) -> Option { + if index > self.len() { + return Some(element); + } + self.inner.insert(index, element).err().map(|e| e.element()) + } + + /// Remove the last element in the vector. + /// + /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// array.push(1); + /// + /// assert_eq!(array.pop(), Some(1)); + /// assert_eq!(array.pop(), 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`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_remove(0), Some(1)); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_remove(10), 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`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.remove(0), Some(1)); + /// assert_eq!(&array[..], &[2, 3]); + /// + /// assert_eq!(array.remove(10), None); + /// ``` + #[inline] + pub fn remove(&mut self, index: usize) -> Option { + self.inner.remove(index) + } + + /// Remove all elements in the vector. + #[inline] + pub fn clear(&mut self) { + self.inner.clear() + } + + /// 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. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4]); + /// array.retain(|x| *x & 1 != 0 ); + /// assert_eq!(&array[..], &[1, 3]); + /// ``` + #[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. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut v = ArrayVec::from([1, 2, 3]); + /// let u: Vec<_> = v.drain(0..2).collect(); + /// assert_eq!(&v[..], &[3]); + /// assert_eq!(&u[..], &[1, 2]); + /// ``` + #[inline] + 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. + #[inline] + pub fn into_inner(self) -> Result { + let inner; + unsafe { + inner = ptr::read(&self.inner); + mem::forget(self); + } + inner.into_inner().into_inner().map_err(|e| ArrayVec { inner: NoDrop::new(e) }) + } + + /// Dispose of `self` without the overwriting that is needed in Drop. + #[inline] + pub fn dispose(mut self) { + self.clear(); + mem::forget(self); + } + + /// Return a slice containing all elements of the vector. + #[inline] + pub fn as_slice(&self) -> &[A::Item] { + self.inner.as_slice() + } + + /// Return a mutable slice containing all elements of the vector. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [A::Item] { + self.inner.as_mut_slice() + } +} + +impl Deref for ArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + self.inner.deref() + } +} + +impl DerefMut for ArrayVec { + #[inline] + fn deref_mut(&mut self) -> &mut [A::Item] { + self.inner.deref_mut() + } +} + +/// Create an `ArrayVec` from an array. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 3); +/// ``` +impl From for ArrayVec { + fn from(array: A) -> Self { + ArrayVec { inner: NoDrop::new(RawArrayVec::from(array)) } + } +} + + +/// Iterate the `ArrayVec` with references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &array { +/// // ... +/// } +/// ``` +impl<'a, A: Array> IntoIterator for &'a ArrayVec { + type Item = &'a A::Item; + type IntoIter = slice::Iter<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.inner.iter() } +} + +/// Iterate the `ArrayVec` with mutable references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &mut array { +/// // ... +/// } +/// ``` +impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { + 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 `ArrayVec` with each element by value. +/// +/// The vector is consumed by this operation. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// for elt in ArrayVec::from([1, 2, 3]) { +/// // ... +/// } +/// ``` +impl IntoIterator for ArrayVec { + type Item = A::Item; + type IntoIter = IntoIter; + fn into_iter(self) -> IntoIter { + IntoIter { index: Index::from(0), v: self } + } +} + + +/// By-value iterator for `ArrayVec`. +pub struct IntoIter { + index: A::Index, + v: ArrayVec, +} + +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 { } + +impl Drop for IntoIter { + fn drop(&mut self) { + // panic safety: Set length to 0 before dropping elements. + let index = self.index.to_usize(); + let len = self.v.len(); + unsafe { + self.v.set_len(0); + let elements = slice::from_raw_parts(self.v.get_unchecked_mut(index), + len - index); + for elt in elements { + ptr::read(elt); + } + } + } +} + +/// 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 { + fn extend>(&mut self, iter: T) { + self.inner.extend(iter) + } +} + +/// 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 + } +} + +impl Clone for ArrayVec + where A::Item: Clone +{ + #[inline] + fn clone(&self) -> Self { + // Can't use `RawArrayVec::clone` here because it's not wrapped in + // `ArrayVec`, see above. + self.iter().cloned().collect() + } + + fn clone_from(&mut self, rhs: &Self) { + self.inner.clone_from(&rhs.inner) + } +} + +impl Hash for ArrayVec + where A::Item: Hash +{ + fn hash(&self, state: &mut H) { + self.inner.hash(state) + } +} + +impl PartialEq for ArrayVec + 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 ArrayVec + where A::Item: PartialEq +{ + fn eq(&self, other: &[A::Item]) -> bool { + self.inner.eq(other) + } +} + +impl Eq for ArrayVec where A::Item: Eq { } + +impl Borrow<[A::Item]> for ArrayVec { + fn borrow(&self) -> &[A::Item] { self.inner.borrow() } +} + +impl BorrowMut<[A::Item]> for ArrayVec { + fn borrow_mut(&mut self) -> &mut [A::Item] { self.inner.borrow_mut() } +} + +impl AsRef<[A::Item]> for ArrayVec { + fn as_ref(&self) -> &[A::Item] { self.inner.as_ref() } +} + +impl AsMut<[A::Item]> for ArrayVec { + fn as_mut(&mut self) -> &mut [A::Item] { self.inner.as_mut() } +} + +impl fmt::Debug for ArrayVec where A::Item: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.fmt(f) } +} + +impl Default for ArrayVec { + fn default() -> ArrayVec { + ArrayVec { inner: NoDrop::new(Default::default()) } + } +} + +impl PartialOrd for ArrayVec where A::Item: PartialOrd { + #[inline] + fn partial_cmp(&self, other: &ArrayVec) -> 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 ArrayVec where A::Item: Ord { + #[inline] + fn cmp(&self, other: &ArrayVec) -> cmp::Ordering { + self.inner.cmp(&other.inner) + } +} + +#[cfg(feature="std")] +/// `Write` appends written data to the end of the vector. +/// +/// Requires `features="std"`. +impl> io::Write for ArrayVec { + #[inline] + fn write(&mut self, data: &[u8]) -> io::Result { + self.inner.write(data) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} diff --git a/tests/tests.rs b/tests/tests.rs index 3dc204c2..d373787f 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -130,15 +130,15 @@ fn test_is_send_sync() { #[test] fn test_compact_size() { // Future rust will kill these drop flags! - // 4 elements size + 1 len + 1 enum tag + [1 drop flag] + // 4 elements size + 1 len + 1 enum tag type ByteArray = ArrayVec<[u8; 4]>; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 8); - // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding + // 12 element size + 1 enum tag + 3 padding + 1 len + 3 padding type QuadArray = ArrayVec<[u32; 3]>; println!("{}", mem::size_of::()); - assert!(mem::size_of::() <= 24); + assert!(mem::size_of::() <= 20); } #[test] From 576324ffaea4b0315db238dbcbe0b50cfedce93e Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 26 Apr 2016 17:03:00 +0200 Subject: [PATCH 2/2] Add `ArrayVecCopy`, which is a copyable `ArrayVec` Fixes #32. --- src/copy.rs | 379 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +- src/raw.rs | 2 +- src/vec.rs | 4 +- 4 files changed, 386 insertions(+), 4 deletions(-) create mode 100644 src/copy.rs diff --git a/src/copy.rs b/src/copy.rs new file mode 100644 index 00000000..a7ab5b2e --- /dev/null +++ b/src/copy.rs @@ -0,0 +1,379 @@ +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. + /// + /// **Panics** if the specified index is greater than the current length. + #[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 9def947d..dddca70b 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: @@ -28,15 +28,18 @@ use std::error::Error; use std::any::Any; // core but unused mod array; +mod copy; mod string; mod vec; mod raw; 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; /// Error value indicating insufficient capacity #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] diff --git a/src/raw.rs b/src/raw.rs index 72055d37..4e56e0bd 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -277,7 +277,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 29c9db31..92461bbc 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -458,7 +458,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 { @@ -468,7 +468,7 @@ 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 {