Merge pull request #61 from bluss/vec-like-api
Prepare 0.4, more vec-like api and error reform
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ env:
|
||||
- FEATURES='serde-1'
|
||||
matrix:
|
||||
include:
|
||||
- rust: 1.12.0
|
||||
- rust: 1.15.0
|
||||
- rust: stable
|
||||
env:
|
||||
- NODEFAULT=1
|
||||
|
||||
@@ -27,8 +27,14 @@ default-features = false
|
||||
[dev-dependencies.serde_test]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
matches = { version = "0.1" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["odds/std", "nodrop/std"]
|
||||
use_union = ["nodrop/use_union"]
|
||||
serde-1 = ["serde"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["serde-1"]
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
arrayvec
|
||||
========
|
||||
|
||||
A vector with fixed capacity. Requires Rust 1.12.0 or later.
|
||||
A vector with fixed capacity.
|
||||
|
||||
Please read the `API documentation here`__
|
||||
|
||||
|
||||
+56
-14
@@ -12,6 +12,7 @@ use std::slice;
|
||||
use array::{Array, ArrayExt};
|
||||
use array::Index;
|
||||
use CapacityError;
|
||||
use errors::PubCrateNew;
|
||||
use odds::char::encode_utf8;
|
||||
|
||||
#[cfg(feature="serde-1")]
|
||||
@@ -68,7 +69,7 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
/// ```
|
||||
pub fn from(s: &str) -> Result<Self, CapacityError<&str>> {
|
||||
let mut arraystr = Self::new();
|
||||
try!(arraystr.push_str(s));
|
||||
arraystr.try_push_str(s)?;
|
||||
Ok(arraystr)
|
||||
}
|
||||
|
||||
@@ -84,7 +85,7 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> {
|
||||
let mut arraystr = Self::new();
|
||||
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());
|
||||
Ok(arraystr)
|
||||
}
|
||||
@@ -123,14 +124,34 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
///
|
||||
/// let mut string = ArrayString::<[_; 2]>::new();
|
||||
///
|
||||
/// string.push('a').unwrap();
|
||||
/// string.push('b').unwrap();
|
||||
/// let overflow = string.push('c');
|
||||
/// string.push('a');
|
||||
/// string.push('b');
|
||||
///
|
||||
/// 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!(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();
|
||||
unsafe {
|
||||
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();
|
||||
///
|
||||
/// string.push_str("a").unwrap();
|
||||
/// let overflow1 = string.push_str("bc");
|
||||
/// string.push_str("d").unwrap();
|
||||
/// let overflow2 = string.push_str("ef");
|
||||
/// string.push_str("a");
|
||||
/// string.push_str("d");
|
||||
///
|
||||
/// 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!(overflow1.unwrap_err().element(), "bc");
|
||||
/// 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() {
|
||||
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.
|
||||
impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> {
|
||||
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 {
|
||||
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) {
|
||||
// guaranteed to fit due to types matching.
|
||||
self.clear();
|
||||
self.push_str(rhs).ok();
|
||||
self.try_push_str(rhs).ok();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -5,7 +5,6 @@
|
||||
//!
|
||||
//! - `std`
|
||||
//! - Optional, enabled by default
|
||||
//! - Requires Rust 1.6 *to disable*
|
||||
//! - Use libstd
|
||||
//!
|
||||
//! - `use_union`
|
||||
@@ -14,6 +13,10 @@
|
||||
//! - Use the unstable feature untagged unions for the internal implementation,
|
||||
//! 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/")]
|
||||
#![cfg_attr(not(feature="std"), no_std)]
|
||||
extern crate odds;
|
||||
@@ -41,10 +44,6 @@ 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;
|
||||
|
||||
@@ -53,11 +52,15 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||
|
||||
mod array;
|
||||
mod array_string;
|
||||
mod range;
|
||||
mod errors;
|
||||
|
||||
pub use array::Array;
|
||||
pub use odds::IndexRange as RangeArgument;
|
||||
pub use range::RangeArgument;
|
||||
use array::Index;
|
||||
pub use array_string::ArrayString;
|
||||
use errors::PubCrateNew;
|
||||
pub use errors::CapacityError;
|
||||
|
||||
|
||||
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> {
|
||||
/// Create a new empty `ArrayVec`.
|
||||
///
|
||||
@@ -152,8 +162,7 @@ impl<A: Array> ArrayVec<A> {
|
||||
|
||||
/// Push `element` to the end of the vector.
|
||||
///
|
||||
/// Return `None` if the push succeeds, or and return `Some(` *element* `)`
|
||||
/// if the vector is full.
|
||||
/// ***Panics*** if the vector is already full.
|
||||
///
|
||||
/// ```
|
||||
/// use arrayvec::ArrayVec;
|
||||
@@ -162,28 +171,53 @@ impl<A: Array> ArrayVec<A> {
|
||||
///
|
||||
/// 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<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() {
|
||||
unsafe {
|
||||
self.push_unchecked(element);
|
||||
}
|
||||
None
|
||||
Ok(())
|
||||
} else {
|
||||
Some(element)
|
||||
Err(CapacityError::new(element))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 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
|
||||
/// sufficiently large.
|
||||
///
|
||||
/// # Examples
|
||||
/// This method *may* use debug assertions to check that the arrayvec is not full.
|
||||
///
|
||||
/// ```
|
||||
/// use arrayvec::ArrayVec;
|
||||
@@ -207,35 +241,55 @@ impl<A: Array> ArrayVec<A> {
|
||||
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
|
||||
/// out of bounds index insert results in the element being "shifted out"
|
||||
/// and returned directly.
|
||||
/// ***Panics*** on errors. See `try_result` for fallible version.
|
||||
///
|
||||
/// ```
|
||||
/// 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"]);
|
||||
/// array.insert(0, "x");
|
||||
/// array.insert(0, "y");
|
||||
/// assert_eq!(&array[..], &["y", "x"]);
|
||||
///
|
||||
/// ```
|
||||
pub fn insert(&mut self, index: usize, element: A::Item) -> Option<A::Item> {
|
||||
if index > self.len() || index == self.capacity() {
|
||||
return Some(element);
|
||||
pub fn insert(&mut self, index: usize, element: A::Item) {
|
||||
self.try_insert(index, element).unwrap()
|
||||
}
|
||||
|
||||
/// 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() {
|
||||
ret = self.pop();
|
||||
return Err(CapacityError::new(element));
|
||||
}
|
||||
let len = self.len();
|
||||
|
||||
@@ -253,10 +307,10 @@ impl<A: Array> ArrayVec<A> {
|
||||
}
|
||||
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`.
|
||||
///
|
||||
@@ -285,6 +339,33 @@ impl<A: Array> ArrayVec<A> {
|
||||
///
|
||||
/// 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`.
|
||||
///
|
||||
/// ```
|
||||
@@ -292,15 +373,15 @@ impl<A: Array> ArrayVec<A> {
|
||||
///
|
||||
/// 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.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();
|
||||
if index >= len {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
self.swap(index, len - 1);
|
||||
self.pop()
|
||||
@@ -308,19 +389,43 @@ impl<A: Array> ArrayVec<A> {
|
||||
|
||||
/// 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;
|
||||
///
|
||||
/// 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.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() {
|
||||
None
|
||||
} else {
|
||||
@@ -369,7 +474,8 @@ impl<A: Array> ArrayVec<A> {
|
||||
|
||||
/// 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
|
||||
/// number of “valid” elements in the vector. Use with care.
|
||||
@@ -394,7 +500,7 @@ impl<A: Array> ArrayVec<A> {
|
||||
/// use arrayvec::ArrayVec;
|
||||
///
|
||||
/// 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!(&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();
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -1,8 +1,10 @@
|
||||
extern crate arrayvec;
|
||||
#[macro_use] extern crate matches;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use arrayvec::ArrayString;
|
||||
use std::mem;
|
||||
use arrayvec::CapacityError;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -30,9 +32,9 @@ fn test_u16_index() {
|
||||
const N: usize = 4096;
|
||||
let mut vec: ArrayVec<[_; N]> = ArrayVec::new();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -77,7 +79,9 @@ fn test_drop() {
|
||||
array.push(vec![Bump(flag)]);
|
||||
array.push(vec![Bump(flag), Bump(flag)]);
|
||||
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);
|
||||
drop(array.pop());
|
||||
assert_eq!(flag.get(), 1);
|
||||
@@ -217,21 +221,25 @@ fn test_drop_panic_into_iter() {
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let mut v = ArrayVec::from([]);
|
||||
assert_eq!(v.push(1), Some(1));
|
||||
assert_eq!(v.insert(0, 1), Some(1));
|
||||
assert_matches!(v.try_push(1), Err(_));
|
||||
|
||||
let mut v = ArrayVec::<[_; 3]>::new();
|
||||
v.insert(0, 0);
|
||||
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(3, 3);
|
||||
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]);
|
||||
assert_eq!(v.insert(1, 1), Some(1));
|
||||
assert_eq!(v.insert(2, 1), Some(1));
|
||||
assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. }));
|
||||
assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. }));
|
||||
//assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -299,7 +307,7 @@ fn test_string() {
|
||||
|
||||
let text = "hello world";
|
||||
let mut s = ArrayString::<[_; 16]>::new();
|
||||
s.push_str(text).unwrap();
|
||||
s.try_push_str(text).unwrap();
|
||||
assert_eq!(&s, text);
|
||||
assert_eq!(text, &s);
|
||||
|
||||
@@ -309,10 +317,10 @@ fn test_string() {
|
||||
assert_eq!(map[text], 1);
|
||||
|
||||
let mut t = ArrayString::<[_; 2]>::new();
|
||||
assert!(t.push_str(text).is_err());
|
||||
assert!(t.try_push_str(text).is_err());
|
||||
assert_eq!(&t, "");
|
||||
|
||||
t.push_str("ab").unwrap();
|
||||
t.push_str("ab");
|
||||
// DerefMut
|
||||
let tmut: &mut str = &mut t;
|
||||
assert_eq!(tmut, "ab");
|
||||
@@ -320,7 +328,7 @@ fn test_string() {
|
||||
// Test Error trait / try
|
||||
let t = || -> Result<(), Box<Error>> {
|
||||
let mut t = ArrayString::<[_; 2]>::new();
|
||||
try!(t.push_str(text));
|
||||
try!(t.try_push_str(text));
|
||||
Ok(())
|
||||
}();
|
||||
assert!(t.is_err());
|
||||
@@ -347,7 +355,7 @@ fn test_string_from_bytes() {
|
||||
fn test_string_clone() {
|
||||
let text = "hi";
|
||||
let mut s = ArrayString::<[_; 4]>::new();
|
||||
s.push_str("abcd").unwrap();
|
||||
s.push_str("abcd");
|
||||
let t = ArrayString::<[_; 4]>::from(text).unwrap();
|
||||
s.clone_from(&t);
|
||||
assert_eq!(&t, &s);
|
||||
@@ -358,42 +366,44 @@ fn test_string_push() {
|
||||
let text = "abcαβγ";
|
||||
let mut s = ArrayString::<[_; 8]>::new();
|
||||
for c in text.chars() {
|
||||
if let Err(_) = s.push(c) {
|
||||
if let Err(_) = s.try_push(c) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert_eq!("abcαβ", &s[..]);
|
||||
s.push('x').ok();
|
||||
s.push('x');
|
||||
assert_eq!("abcαβx", &s[..]);
|
||||
assert!(s.push('x').is_err());
|
||||
assert!(s.try_push('x').is_err());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_insert_at_length() {
|
||||
let mut v = ArrayVec::<[_; 8]>::new();
|
||||
let result1 = v.insert(0, "a");
|
||||
let result2 = v.insert(1, "b");
|
||||
assert!(result1.is_none() && result2.is_none());
|
||||
let result1 = v.try_insert(0, "a");
|
||||
let result2 = v.try_insert(1, "b");
|
||||
assert!(result1.is_ok() && result2.is_ok());
|
||||
assert_eq!(&v[..], &["a", "b"]);
|
||||
}
|
||||
|
||||
#[should_panic]
|
||||
#[test]
|
||||
fn test_insert_out_of_bounds() {
|
||||
let mut v = ArrayVec::<[_; 8]>::new();
|
||||
let result = v.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));
|
||||
let _ = v.try_insert(1, "test");
|
||||
}
|
||||
|
||||
/*
|
||||
* 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]
|
||||
fn test_drop_in_insert() {
|
||||
use std::cell::Cell;
|
||||
@@ -416,11 +426,27 @@ fn test_drop_in_insert() {
|
||||
array.push(Bump(flag));
|
||||
array.insert(0, Bump(flag));
|
||||
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!(ret.is_some());
|
||||
assert_matches!(ret, Err(_));
|
||||
drop(ret);
|
||||
assert_eq!(flag.get(), 1);
|
||||
}
|
||||
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"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user