Merge pull request #61 from bluss/vec-like-api

Prepare 0.4, more vec-like api and error reform
This commit is contained in:
bluss
2017-08-06 00:48:10 +02:00
committed by GitHub
8 changed files with 373 additions and 139 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ env:
- FEATURES='serde-1' - FEATURES='serde-1'
matrix: matrix:
include: include:
- rust: 1.12.0 - rust: 1.15.0
- rust: stable - rust: stable
env: env:
- NODEFAULT=1 - NODEFAULT=1
+6
View File
@@ -27,8 +27,14 @@ default-features = false
[dev-dependencies.serde_test] [dev-dependencies.serde_test]
version = "1.0" version = "1.0"
[dev-dependencies]
matches = { version = "0.1" }
[features] [features]
default = ["std"] default = ["std"]
std = ["odds/std", "nodrop/std"] std = ["odds/std", "nodrop/std"]
use_union = ["nodrop/use_union"] use_union = ["nodrop/use_union"]
serde-1 = ["serde"] serde-1 = ["serde"]
[package.metadata.docs.rs]
features = ["serde-1"]
+1 -1
View File
@@ -2,7 +2,7 @@
arrayvec arrayvec
======== ========
A vector with fixed capacity. Requires Rust 1.12.0 or later. A vector with fixed capacity.
Please read the `API documentation here`__ Please read the `API documentation here`__
+56 -14
View File
@@ -12,6 +12,7 @@ use std::slice;
use array::{Array, ArrayExt}; use array::{Array, ArrayExt};
use array::Index; use array::Index;
use CapacityError; use CapacityError;
use errors::PubCrateNew;
use odds::char::encode_utf8; use odds::char::encode_utf8;
#[cfg(feature="serde-1")] #[cfg(feature="serde-1")]
@@ -68,7 +69,7 @@ impl<A: Array<Item=u8>> ArrayString<A> {
/// ``` /// ```
pub fn from(s: &str) -> Result<Self, CapacityError<&str>> { pub fn from(s: &str) -> Result<Self, CapacityError<&str>> {
let mut arraystr = Self::new(); let mut arraystr = Self::new();
try!(arraystr.push_str(s)); arraystr.try_push_str(s)?;
Ok(arraystr) Ok(arraystr)
} }
@@ -84,7 +85,7 @@ impl<A: Array<Item=u8>> ArrayString<A> {
pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> { pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> {
let mut arraystr = Self::new(); let mut arraystr = Self::new();
let s = try!(str::from_utf8(b.as_slice())); let s = try!(str::from_utf8(b.as_slice()));
let _result = arraystr.push_str(s); let _result = arraystr.try_push_str(s);
debug_assert!(_result.is_ok()); debug_assert!(_result.is_ok());
Ok(arraystr) Ok(arraystr)
} }
@@ -123,14 +124,34 @@ impl<A: Array<Item=u8>> ArrayString<A> {
/// ///
/// let mut string = ArrayString::<[_; 2]>::new(); /// let mut string = ArrayString::<[_; 2]>::new();
/// ///
/// string.push('a').unwrap(); /// string.push('a');
/// string.push('b').unwrap(); /// string.push('b');
/// let overflow = string.push('c'); ///
/// assert_eq!(&string[..], "ab");
/// ```
pub fn push(&mut self, c: char) {
self.try_push(c).unwrap();
}
/// Adds the given char to the end of the string.
///
/// Returns `Ok` if the push succeeds.
///
/// **Errors** if the backing array is not large enough to fit the additional char.
///
/// ```
/// use arrayvec::ArrayString;
///
/// let mut string = ArrayString::<[_; 2]>::new();
///
/// string.try_push('a').unwrap();
/// string.try_push('b').unwrap();
/// let overflow = string.try_push('c');
/// ///
/// assert_eq!(&string[..], "ab"); /// assert_eq!(&string[..], "ab");
/// assert_eq!(overflow.unwrap_err().element(), 'c'); /// assert_eq!(overflow.unwrap_err().element(), 'c');
/// ``` /// ```
pub fn push(&mut self, c: char) -> Result<(), CapacityError<char>> { pub fn try_push(&mut self, c: char) -> Result<(), CapacityError<char>> {
let len = self.len(); let len = self.len();
unsafe { unsafe {
match encode_utf8(c, &mut self.raw_mut_bytes()[len..]) { match encode_utf8(c, &mut self.raw_mut_bytes()[len..]) {
@@ -154,16 +175,36 @@ impl<A: Array<Item=u8>> ArrayString<A> {
/// ///
/// let mut string = ArrayString::<[_; 2]>::new(); /// let mut string = ArrayString::<[_; 2]>::new();
/// ///
/// string.push_str("a").unwrap(); /// string.push_str("a");
/// let overflow1 = string.push_str("bc"); /// string.push_str("d");
/// string.push_str("d").unwrap(); ///
/// let overflow2 = string.push_str("ef"); /// assert_eq!(&string[..], "ad");
/// ```
pub fn push_str(&mut self, s: &str) {
self.try_push_str(s).unwrap()
}
/// Adds the given string slice to the end of the string.
///
/// Returns `Ok` if the push succeeds.
///
/// **Errors** if the backing array is not large enough to fit the string.
///
/// ```
/// use arrayvec::ArrayString;
///
/// let mut string = ArrayString::<[_; 2]>::new();
///
/// string.try_push_str("a").unwrap();
/// let overflow1 = string.try_push_str("bc");
/// string.try_push_str("d").unwrap();
/// let overflow2 = string.try_push_str("ef");
/// ///
/// assert_eq!(&string[..], "ad"); /// assert_eq!(&string[..], "ad");
/// assert_eq!(overflow1.unwrap_err().element(), "bc"); /// assert_eq!(overflow1.unwrap_err().element(), "bc");
/// assert_eq!(overflow2.unwrap_err().element(), "ef"); /// assert_eq!(overflow2.unwrap_err().element(), "ef");
/// ``` /// ```
pub fn push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> {
if s.len() > self.capacity() - self.len() { if s.len() > self.capacity() - self.len() {
return Err(CapacityError::new(s)); return Err(CapacityError::new(s));
} }
@@ -274,10 +315,11 @@ impl<A: Array<Item=u8>> fmt::Display for ArrayString<A> {
/// `Write` appends written data to the end of the string. /// `Write` appends written data to the end of the string.
impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> { impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> {
fn write_char(&mut self, c: char) -> fmt::Result { fn write_char(&mut self, c: char) -> fmt::Result {
self.push(c).map_err(|_| fmt::Error) self.try_push(c).map_err(|_| fmt::Error)
} }
fn write_str(&mut self, s: &str) -> fmt::Result { fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_str(s).map_err(|_| fmt::Error) self.try_push_str(s).map_err(|_| fmt::Error)
} }
} }
@@ -288,7 +330,7 @@ impl<A: Array<Item=u8> + Copy> Clone for ArrayString<A> {
fn clone_from(&mut self, rhs: &Self) { fn clone_from(&mut self, rhs: &Self) {
// guaranteed to fit due to types matching. // guaranteed to fit due to types matching.
self.clear(); self.clear();
self.push_str(rhs).ok(); self.try_push_str(rhs).ok();
} }
} }
+58
View File
@@ -0,0 +1,58 @@
use std::fmt;
#[cfg(feature="std")]
use std::any::Any;
#[cfg(feature="std")]
use std::error::Error;
/// Error value indicating insufficient capacity
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
pub struct CapacityError<T = ()> {
element: T,
}
pub trait PubCrateNew<T> {
fn new(elt: T) -> Self;
}
impl<T> PubCrateNew<T> for CapacityError<T> {
fn new(element: T) -> CapacityError<T> {
CapacityError {
element: element,
}
}
}
impl<T> CapacityError<T> {
/// Extract the overflowing element
pub fn element(self) -> T {
self.element
}
/// Convert into a `CapacityError` that does not carry an element.
pub fn simplify(self) -> CapacityError {
CapacityError { element: () }
}
}
const CAPERROR: &'static str = "insufficient capacity";
#[cfg(feature="std")]
/// Requires `features="std"`.
impl<T: Any> Error for CapacityError<T> {
fn description(&self) -> &str {
CAPERROR
}
}
impl<T> fmt::Display for CapacityError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", CAPERROR)
}
}
impl<T> fmt::Debug for CapacityError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", "CapacityError", CAPERROR)
}
}
+149 -89
View File
@@ -5,7 +5,6 @@
//! //!
//! - `std` //! - `std`
//! - Optional, enabled by default //! - Optional, enabled by default
//! - Requires Rust 1.6 *to disable*
//! - Use libstd //! - Use libstd
//! //!
//! - `use_union` //! - `use_union`
@@ -14,6 +13,10 @@
//! - Use the unstable feature untagged unions for the internal implementation, //! - Use the unstable feature untagged unions for the internal implementation,
//! which has reduced space overhead //! which has reduced space overhead
//! //!
//! ## Rust Version
//!
//! This version of arrayvec requires Rust 1.15 or later.
//!
#![doc(html_root_url="https://docs.rs/arrayvec/0.3/")] #![doc(html_root_url="https://docs.rs/arrayvec/0.3/")]
#![cfg_attr(not(feature="std"), no_std)] #![cfg_attr(not(feature="std"), no_std)]
extern crate odds; extern crate odds;
@@ -41,10 +44,6 @@ use std::fmt;
#[cfg(feature="std")] #[cfg(feature="std")]
use std::io; use std::io;
#[cfg(feature="std")]
use std::error::Error;
#[cfg(feature="std")]
use std::any::Any; // core but unused
use nodrop::NoDrop; use nodrop::NoDrop;
@@ -53,11 +52,15 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
mod array; mod array;
mod array_string; mod array_string;
mod range;
mod errors;
pub use array::Array; pub use array::Array;
pub use odds::IndexRange as RangeArgument; pub use range::RangeArgument;
use array::Index; use array::Index;
pub use array_string::ArrayString; pub use array_string::ArrayString;
use errors::PubCrateNew;
pub use errors::CapacityError;
unsafe fn new_array<A: Array>() -> A { unsafe fn new_array<A: Array>() -> A {
@@ -95,6 +98,13 @@ impl<A: Array> Drop for ArrayVec<A> {
} }
} }
macro_rules! panic_oob {
($method_name:expr, $index:expr, $len:expr) => {
panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"),
$index, $len)
}
}
impl<A: Array> ArrayVec<A> { impl<A: Array> ArrayVec<A> {
/// Create a new empty `ArrayVec`. /// Create a new empty `ArrayVec`.
/// ///
@@ -152,8 +162,7 @@ impl<A: Array> ArrayVec<A> {
/// Push `element` to the end of the vector. /// Push `element` to the end of the vector.
/// ///
/// Return `None` if the push succeeds, or and return `Some(` *element* `)` /// ***Panics*** if the vector is already full.
/// if the vector is full.
/// ///
/// ``` /// ```
/// use arrayvec::ArrayVec; /// use arrayvec::ArrayVec;
@@ -162,28 +171,53 @@ impl<A: Array> ArrayVec<A> {
/// ///
/// array.push(1); /// array.push(1);
/// array.push(2); /// array.push(2);
/// let overflow = array.push(3);
/// ///
/// assert_eq!(&array[..], &[1, 2]); /// assert_eq!(&array[..], &[1, 2]);
/// assert_eq!(overflow, Some(3));
/// ``` /// ```
pub fn push(&mut self, element: A::Item) -> Option<A::Item> { pub fn push(&mut self, element: A::Item) {
self.try_push(element).unwrap()
}
/// Push `element` to the end of the vector.
///
/// Return `Ok` if the push succeeds, or return an error if the vector
/// is already full.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::<[_; 2]>::new();
///
/// let push1 = array.try_push(1);
/// let push2 = array.try_push(2);
///
/// assert!(push1.is_ok());
/// assert!(push2.is_ok());
///
/// assert_eq!(&array[..], &[1, 2]);
///
/// let overflow = array.try_push(3);
///
/// assert!(overflow.is_err());
/// ```
pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError<A::Item>> {
if self.len() < A::capacity() { if self.len() < A::capacity() {
unsafe { unsafe {
self.push_unchecked(element); self.push_unchecked(element);
} }
None Ok(())
} else { } else {
Some(element) Err(CapacityError::new(element))
} }
} }
/// Push `element` to the end of the vector without checking the capacity. /// Push `element` to the end of the vector without checking the capacity.
/// ///
/// It is up to the caller to ensure the capacity of the vector is /// It is up to the caller to ensure the capacity of the vector is
/// sufficiently large. /// sufficiently large.
/// ///
/// # Examples /// This method *may* use debug assertions to check that the arrayvec is not full.
/// ///
/// ``` /// ```
/// use arrayvec::ArrayVec; /// use arrayvec::ArrayVec;
@@ -207,35 +241,55 @@ impl<A: Array> ArrayVec<A> {
self.set_len(len + 1); self.set_len(len + 1);
} }
/// Insert `element` in position `index`. /// Insert `element` at position `index`.
/// ///
/// Shift up all elements after `index`. If any is pushed out, it is returned. /// Shift up all elements after `index`.
/// ///
/// Return `None` if no element is shifted out. /// It is an error if the index is greater than the length or if the
/// arrayvec is full.
/// ///
/// `index` must be <= `self.len()` and < `self.capacity()`. Note that any /// ***Panics*** on errors. See `try_result` for fallible version.
/// out of bounds index insert results in the element being "shifted out"
/// and returned directly.
/// ///
/// ``` /// ```
/// use arrayvec::ArrayVec; /// use arrayvec::ArrayVec;
/// ///
/// let mut array = ArrayVec::<[_; 2]>::new(); /// let mut array = ArrayVec::<[_; 2]>::new();
/// ///
/// assert_eq!(array.insert(0, "x"), None); /// array.insert(0, "x");
/// assert_eq!(array.insert(0, "y"), None); /// array.insert(0, "y");
/// assert_eq!(array.insert(0, "z"), Some("x")); /// assert_eq!(&array[..], &["y", "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<A::Item> { pub fn insert(&mut self, index: usize, element: A::Item) {
if index > self.len() || index == self.capacity() { self.try_insert(index, element).unwrap()
return Some(element); }
/// Insert `element` at position `index`.
///
/// Shift up all elements after `index`; the `index` must be less than
/// or equal to the length.
///
/// Returns an error if vector is already at full capacity.
///
/// ***Panics*** `index` is out of bounds.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::<[_; 2]>::new();
///
/// assert!(array.try_insert(0, "x").is_ok());
/// assert!(array.try_insert(0, "y").is_ok());
/// assert!(array.try_insert(0, "z").is_err());
/// assert_eq!(&array[..], &["y", "x"]);
///
/// ```
pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityError<A::Item>> {
if index > self.len() {
panic_oob!("try_insert", index, self.len())
} }
let mut ret = None;
if self.len() == self.capacity() { if self.len() == self.capacity() {
ret = self.pop(); return Err(CapacityError::new(element));
} }
let len = self.len(); let len = self.len();
@@ -253,10 +307,10 @@ impl<A: Array> ArrayVec<A> {
} }
self.set_len(len + 1); self.set_len(len + 1);
} }
ret Ok(())
} }
/// Remove the last element in the vector. /// Remove the last element in the vector and return it.
/// ///
/// Return `Some(` *element* `)` if the vector is non-empty, else `None`. /// Return `Some(` *element* `)` if the vector is non-empty, else `None`.
/// ///
@@ -285,6 +339,33 @@ impl<A: Array> ArrayVec<A> {
/// ///
/// This operation is O(1). /// This operation is O(1).
/// ///
/// Return the *element* if the index is in bounds, else panic.
///
/// ***Panics*** if the `index` is out of bounds.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
///
/// assert_eq!(array.swap_remove(0), 1);
/// assert_eq!(&array[..], &[3, 2]);
///
/// assert_eq!(array.swap_remove(1), 2);
/// assert_eq!(&array[..], &[3]);
/// ```
pub fn swap_remove(&mut self, index: usize) -> A::Item {
self.swap_pop(index)
.unwrap_or_else(|| {
panic_oob!("swap_remove", index, self.len())
})
}
/// Remove the element at `index` and swap the last element into its place.
///
/// This is a checked version of `.swap_remove`.
/// This operation is O(1).
///
/// Return `Some(` *element* `)` if the index is in bounds, else `None`. /// Return `Some(` *element* `)` if the index is in bounds, else `None`.
/// ///
/// ``` /// ```
@@ -292,15 +373,15 @@ impl<A: Array> ArrayVec<A> {
/// ///
/// let mut array = ArrayVec::from([1, 2, 3]); /// let mut array = ArrayVec::from([1, 2, 3]);
/// ///
/// assert_eq!(array.swap_remove(0), Some(1)); /// assert_eq!(array.swap_pop(0), Some(1));
/// assert_eq!(&array[..], &[3, 2]); /// assert_eq!(&array[..], &[3, 2]);
/// ///
/// assert_eq!(array.swap_remove(10), None); /// assert_eq!(array.swap_pop(10), None);
/// ``` /// ```
pub fn swap_remove(&mut self, index: usize) -> Option<A::Item> { pub fn swap_pop(&mut self, index: usize) -> Option<A::Item> {
let len = self.len(); let len = self.len();
if index >= len { if index >= len {
return None return None;
} }
self.swap(index, len - 1); self.swap(index, len - 1);
self.pop() self.pop()
@@ -308,19 +389,43 @@ impl<A: Array> ArrayVec<A> {
/// Remove the element at `index` and shift down the following elements. /// Remove the element at `index` and shift down the following elements.
/// ///
/// Return `Some(` *element* `)` if the index is in bounds, else `None`. /// The `index` must be strictly less than the length of the vector.
///
/// ***Panics*** if the `index` is out of bounds.
/// ///
/// ``` /// ```
/// use arrayvec::ArrayVec; /// use arrayvec::ArrayVec;
/// ///
/// let mut array = ArrayVec::from([1, 2, 3]); /// let mut array = ArrayVec::from([1, 2, 3]);
/// ///
/// assert_eq!(array.remove(0), Some(1)); /// let removed_elt = array.remove(0);
/// assert_eq!(removed_elt, 1);
/// assert_eq!(&array[..], &[2, 3]);
/// ```
pub fn remove(&mut self, index: usize) -> A::Item {
self.pop_at(index)
.unwrap_or_else(|| {
panic_oob!("remove", index, self.len())
})
}
/// Remove the element at `index` and shift down the following elements.
///
/// This is a checked version of `.remove(index)`. Returns `None` if there
/// is no element at `index`. Otherwise, return the element inside `Some`.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
///
/// assert!(array.pop_at(0).is_some());
/// assert_eq!(&array[..], &[2, 3]); /// assert_eq!(&array[..], &[2, 3]);
/// ///
/// assert_eq!(array.remove(10), None); /// assert!(array.pop_at(2).is_none());
/// assert!(array.pop_at(10).is_none());
/// ``` /// ```
pub fn remove(&mut self, index: usize) -> Option<A::Item> { pub fn pop_at(&mut self, index: usize) -> Option<A::Item> {
if index >= self.len() { if index >= self.len() {
None None
} else { } else {
@@ -369,7 +474,8 @@ impl<A: Array> ArrayVec<A> {
/// Set the vector's length without dropping or moving out elements /// Set the vector's length without dropping or moving out elements
/// ///
/// May panic if `length` is greater than the capacity. /// May use debug assertions to check that `length` is not greater than the
/// capacity.
/// ///
/// This function is `unsafe` because it changes the notion of the /// This function is `unsafe` because it changes the notion of the
/// number of “valid” elements in the vector. Use with care. /// number of “valid” elements in the vector. Use with care.
@@ -394,7 +500,7 @@ impl<A: Array> ArrayVec<A> {
/// use arrayvec::ArrayVec; /// use arrayvec::ArrayVec;
/// ///
/// let mut v = ArrayVec::from([1, 2, 3]); /// let mut v = ArrayVec::from([1, 2, 3]);
/// let u: Vec<_> = v.drain(0..2).collect(); /// let u: ArrayVec<[_; 3]> = v.drain(0..2).collect();
/// assert_eq!(&v[..], &[3]); /// assert_eq!(&v[..], &[3]);
/// assert_eq!(&u[..], &[1, 2]); /// assert_eq!(&u[..], &[1, 2]);
/// ``` /// ```
@@ -887,7 +993,7 @@ impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A
let mut values = ArrayVec::<A>::new(); let mut values = ArrayVec::<A>::new();
while let Some(value) = try!(seq.next_element()) { while let Some(value) = try!(seq.next_element()) {
if let Some(_) = values.push(value) { if let Err(_) = values.try_push(value) {
return Err(SA::Error::invalid_length(A::capacity() + 1, &self)); return Err(SA::Error::invalid_length(A::capacity() + 1, &self));
} }
} }
@@ -899,49 +1005,3 @@ impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A
deserializer.deserialize_seq(ArrayVecVisitor::<T, A>(PhantomData)) deserializer.deserialize_seq(ArrayVecVisitor::<T, A>(PhantomData))
} }
} }
/// Error value indicating insufficient capacity
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
pub struct CapacityError<T = ()> {
element: T,
}
impl<T> CapacityError<T> {
fn new(element: T) -> CapacityError<T> {
CapacityError {
element: element,
}
}
/// Extract the overflowing element
pub fn element(self) -> T {
self.element
}
/// Convert into a `CapacityError` that does not carry an element.
pub fn simplify(self) -> CapacityError {
CapacityError { element: () }
}
}
const CAPERROR: &'static str = "insufficient capacity";
#[cfg(feature="std")]
/// Requires `features="std"`.
impl<T: Any> Error for CapacityError<T> {
fn description(&self) -> &str {
CAPERROR
}
}
impl<T> fmt::Display for CapacityError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", CAPERROR)
}
}
impl<T> fmt::Debug for CapacityError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", "CapacityError", CAPERROR)
}
}
+42
View File
@@ -0,0 +1,42 @@
use std::ops::{
RangeFull,
RangeFrom,
RangeTo,
Range,
};
/// `RangeArgument` is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
///
/// Note: This is arrayvec's provisional trait, waiting for stable Rust to
/// provide an equivalent.
pub trait RangeArgument {
#[inline]
/// Start index (inclusive)
fn start(&self) -> Option<usize> { None }
#[inline]
/// End index (exclusive)
fn end(&self) -> Option<usize> { None }
}
impl RangeArgument for RangeFull {}
impl RangeArgument for RangeFrom<usize> {
#[inline]
fn start(&self) -> Option<usize> { Some(self.start) }
}
impl RangeArgument for RangeTo<usize> {
#[inline]
fn end(&self) -> Option<usize> { Some(self.end) }
}
impl RangeArgument for Range<usize> {
#[inline]
fn start(&self) -> Option<usize> { Some(self.start) }
#[inline]
fn end(&self) -> Option<usize> { Some(self.end) }
}
+60 -34
View File
@@ -1,8 +1,10 @@
extern crate arrayvec; extern crate arrayvec;
#[macro_use] extern crate matches;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use arrayvec::ArrayString; use arrayvec::ArrayString;
use std::mem; use std::mem;
use arrayvec::CapacityError;
use std::collections::HashMap; use std::collections::HashMap;
@@ -30,9 +32,9 @@ fn test_u16_index() {
const N: usize = 4096; const N: usize = 4096;
let mut vec: ArrayVec<[_; N]> = ArrayVec::new(); let mut vec: ArrayVec<[_; N]> = ArrayVec::new();
for _ in 0..N { for _ in 0..N {
assert!(vec.push(1u8).is_none()); assert!(vec.try_push(1u8).is_ok());
} }
assert!(vec.push(0).is_some()); assert!(vec.try_push(0).is_err());
assert_eq!(vec.len(), N); assert_eq!(vec.len(), N);
} }
@@ -77,7 +79,9 @@ fn test_drop() {
array.push(vec![Bump(flag)]); array.push(vec![Bump(flag)]);
array.push(vec![Bump(flag), Bump(flag)]); array.push(vec![Bump(flag), Bump(flag)]);
array.push(vec![]); array.push(vec![]);
array.push(vec![Bump(flag)]); let push4 = array.try_push(vec![Bump(flag)]);
assert_eq!(flag.get(), 0);
drop(push4);
assert_eq!(flag.get(), 1); assert_eq!(flag.get(), 1);
drop(array.pop()); drop(array.pop());
assert_eq!(flag.get(), 1); assert_eq!(flag.get(), 1);
@@ -217,21 +221,25 @@ fn test_drop_panic_into_iter() {
#[test] #[test]
fn test_insert() { fn test_insert() {
let mut v = ArrayVec::from([]); let mut v = ArrayVec::from([]);
assert_eq!(v.push(1), Some(1)); assert_matches!(v.try_push(1), Err(_));
assert_eq!(v.insert(0, 1), Some(1));
let mut v = ArrayVec::<[_; 3]>::new(); let mut v = ArrayVec::<[_; 3]>::new();
v.insert(0, 0); v.insert(0, 0);
v.insert(1, 1); v.insert(1, 1);
//let ret1 = v.try_insert(3, 3);
//assert_matches!(ret1, Err(InsertError::OutOfBounds(_)));
assert_eq!(&v[..], &[0, 1]);
v.insert(2, 2); v.insert(2, 2);
v.insert(3, 3);
assert_eq!(&v[..], &[0, 1, 2]); assert_eq!(&v[..], &[0, 1, 2]);
v.insert(1, 9);
assert_eq!(&v[..], &[0, 9, 1]); let ret2 = v.try_insert(1, 9);
assert_eq!(&v[..], &[0, 1, 2]);
assert_matches!(ret2, Err(_));
let mut v = ArrayVec::from([2]); let mut v = ArrayVec::from([2]);
assert_eq!(v.insert(1, 1), Some(1)); assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. }));
assert_eq!(v.insert(2, 1), Some(1)); assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. }));
//assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. }));
} }
#[test] #[test]
@@ -299,7 +307,7 @@ fn test_string() {
let text = "hello world"; let text = "hello world";
let mut s = ArrayString::<[_; 16]>::new(); let mut s = ArrayString::<[_; 16]>::new();
s.push_str(text).unwrap(); s.try_push_str(text).unwrap();
assert_eq!(&s, text); assert_eq!(&s, text);
assert_eq!(text, &s); assert_eq!(text, &s);
@@ -309,10 +317,10 @@ fn test_string() {
assert_eq!(map[text], 1); assert_eq!(map[text], 1);
let mut t = ArrayString::<[_; 2]>::new(); let mut t = ArrayString::<[_; 2]>::new();
assert!(t.push_str(text).is_err()); assert!(t.try_push_str(text).is_err());
assert_eq!(&t, ""); assert_eq!(&t, "");
t.push_str("ab").unwrap(); t.push_str("ab");
// DerefMut // DerefMut
let tmut: &mut str = &mut t; let tmut: &mut str = &mut t;
assert_eq!(tmut, "ab"); assert_eq!(tmut, "ab");
@@ -320,7 +328,7 @@ fn test_string() {
// Test Error trait / try // Test Error trait / try
let t = || -> Result<(), Box<Error>> { let t = || -> Result<(), Box<Error>> {
let mut t = ArrayString::<[_; 2]>::new(); let mut t = ArrayString::<[_; 2]>::new();
try!(t.push_str(text)); try!(t.try_push_str(text));
Ok(()) Ok(())
}(); }();
assert!(t.is_err()); assert!(t.is_err());
@@ -347,7 +355,7 @@ fn test_string_from_bytes() {
fn test_string_clone() { fn test_string_clone() {
let text = "hi"; let text = "hi";
let mut s = ArrayString::<[_; 4]>::new(); let mut s = ArrayString::<[_; 4]>::new();
s.push_str("abcd").unwrap(); s.push_str("abcd");
let t = ArrayString::<[_; 4]>::from(text).unwrap(); let t = ArrayString::<[_; 4]>::from(text).unwrap();
s.clone_from(&t); s.clone_from(&t);
assert_eq!(&t, &s); assert_eq!(&t, &s);
@@ -358,42 +366,44 @@ fn test_string_push() {
let text = "abcαβγ"; let text = "abcαβγ";
let mut s = ArrayString::<[_; 8]>::new(); let mut s = ArrayString::<[_; 8]>::new();
for c in text.chars() { for c in text.chars() {
if let Err(_) = s.push(c) { if let Err(_) = s.try_push(c) {
break; break;
} }
} }
assert_eq!("abcαβ", &s[..]); assert_eq!("abcαβ", &s[..]);
s.push('x').ok(); s.push('x');
assert_eq!("abcαβx", &s[..]); assert_eq!("abcαβx", &s[..]);
assert!(s.push('x').is_err()); assert!(s.try_push('x').is_err());
} }
#[test] #[test]
fn test_insert_at_length() { fn test_insert_at_length() {
let mut v = ArrayVec::<[_; 8]>::new(); let mut v = ArrayVec::<[_; 8]>::new();
let result1 = v.insert(0, "a"); let result1 = v.try_insert(0, "a");
let result2 = v.insert(1, "b"); let result2 = v.try_insert(1, "b");
assert!(result1.is_none() && result2.is_none()); assert!(result1.is_ok() && result2.is_ok());
assert_eq!(&v[..], &["a", "b"]); assert_eq!(&v[..], &["a", "b"]);
} }
#[should_panic]
#[test] #[test]
fn test_insert_out_of_bounds() { fn test_insert_out_of_bounds() {
let mut v = ArrayVec::<[_; 8]>::new(); let mut v = ArrayVec::<[_; 8]>::new();
let result = v.insert(1, "test"); let _ = v.try_insert(1, "test");
assert_eq!(result, Some("test"));
assert_eq!(v.len(), 0);
let mut u = ArrayVec::from([1, 2, 3, 4]);
let ret = u.insert(3, 99);
assert_eq!(&u[..], &[1, 2, 3, 99]);
assert_eq!(ret, Some(4));
let ret = u.insert(4, 77);
assert_eq!(&u[..], &[1, 2, 3, 99]);
assert_eq!(ret, Some(77));
} }
/*
* insert that pushes out the last
let mut u = ArrayVec::from([1, 2, 3, 4]);
let ret = u.try_insert(3, 99);
assert_eq!(&u[..], &[1, 2, 3, 99]);
assert_matches!(ret, Err(_));
let ret = u.try_insert(4, 77);
assert_eq!(&u[..], &[1, 2, 3, 99]);
assert_matches!(ret, Err(_));
*/
#[test] #[test]
fn test_drop_in_insert() { fn test_drop_in_insert() {
use std::cell::Cell; use std::cell::Cell;
@@ -416,11 +426,27 @@ fn test_drop_in_insert() {
array.push(Bump(flag)); array.push(Bump(flag));
array.insert(0, Bump(flag)); array.insert(0, Bump(flag));
assert_eq!(flag.get(), 0); assert_eq!(flag.get(), 0);
let ret = array.insert(1, Bump(flag)); let ret = array.try_insert(1, Bump(flag));
assert_eq!(flag.get(), 0); assert_eq!(flag.get(), 0);
assert!(ret.is_some()); assert_matches!(ret, Err(_));
drop(ret); drop(ret);
assert_eq!(flag.get(), 1); assert_eq!(flag.get(), 1);
} }
assert_eq!(flag.get(), 3); assert_eq!(flag.get(), 3);
} }
#[test]
fn test_pop_at() {
let mut v = ArrayVec::<[String; 4]>::new();
let s = String::from;
v.push(s("a"));
v.push(s("b"));
v.push(s("c"));
v.push(s("d"));
assert_eq!(v.pop_at(4), None);
assert_eq!(v.pop_at(1), Some(s("b")));
assert_eq!(v.pop_at(1), Some(s("c")));
assert_eq!(v.pop_at(2), None);
assert_eq!(&v[..], &["a", "d"]);
}