| 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) | ||
| } | ||
| } | ||
+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) } | ||
| } | ||
| #![cfg(feature = "serde-1")] | ||
| extern crate arrayvec; | ||
| extern crate serde_test; | ||
| mod array_vec { | ||
| use arrayvec::ArrayVec; | ||
| use serde_test::{Token, assert_tokens, assert_de_tokens_error}; | ||
| #[test] | ||
| fn test_ser_de_empty() { | ||
| let vec = ArrayVec::<[u32; 0]>::new(); | ||
| assert_tokens(&vec, &[ | ||
| Token::Seq { len: Some(0) }, | ||
| Token::SeqEnd, | ||
| ]); | ||
| } | ||
| #[test] | ||
| fn test_ser_de() { | ||
| let mut vec = ArrayVec::<[u32; 3]>::new(); | ||
| vec.push(20); | ||
| vec.push(55); | ||
| vec.push(123); | ||
| assert_tokens(&vec, &[ | ||
| Token::Seq { len: Some(3) }, | ||
| Token::U32(20), | ||
| Token::U32(55), | ||
| Token::U32(123), | ||
| Token::SeqEnd, | ||
| ]); | ||
| } | ||
| #[test] | ||
| fn test_de_too_large() { | ||
| assert_de_tokens_error::<ArrayVec<[u32; 2]>>(&[ | ||
| Token::Seq { len: Some(3) }, | ||
| Token::U32(13), | ||
| Token::U32(42), | ||
| Token::U32(68), | ||
| ], "invalid length 3, expected an array with no more than 2 items"); | ||
| } | ||
| } | ||
| mod array_string { | ||
| use arrayvec::ArrayString; | ||
| use serde_test::{Token, assert_tokens, assert_de_tokens_error}; | ||
| #[test] | ||
| fn test_ser_de_empty() { | ||
| let string = ArrayString::<[u8; 0]>::new(); | ||
| assert_tokens(&string, &[ | ||
| Token::Str(""), | ||
| ]); | ||
| } | ||
| #[test] | ||
| fn test_ser_de() { | ||
| let string = ArrayString::<[u8; 9]>::from("1234 abcd") | ||
| .expect("expected exact specified capacity to be enough"); | ||
| assert_tokens(&string, &[ | ||
| Token::Str("1234 abcd"), | ||
| ]); | ||
| } | ||
| #[test] | ||
| fn test_de_too_large() { | ||
| assert_de_tokens_error::<ArrayString<[u8; 2]>>(&[ | ||
| Token::Str("afd") | ||
| ], "invalid length 3, expected a string no more than 2 bytes long"); | ||
| } | ||
| } |
+1
-0
@@ -11,2 +11,3 @@ # Compiled files | ||
| # Generated by Cargo | ||
| /Cargo.lock | ||
| /target/ |
+4
-3
| language: rust | ||
| sudo: false | ||
| env: | ||
| - FEATURES='serde-1' | ||
| matrix: | ||
| include: | ||
| - rust: 1.2.0 | ||
| - rust: 1.14.0 | ||
| - rust: stable | ||
| env: | ||
| - FEATURES="use_generic_array" | ||
| - NODEFAULT=1 | ||
@@ -19,3 +20,3 @@ - rust: beta | ||
| env: | ||
| - FEATURES='use_union use_generic_array' | ||
| - FEATURES='serde use_union' | ||
| - NODROP_FEATURES='use_union' | ||
@@ -22,0 +23,0 @@ branches: |
+20
-10
@@ -15,17 +15,18 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "arrayvec" | ||
| version = "0.3.25" | ||
| version = "0.4.0" | ||
| authors = ["bluss"] | ||
| description = "A vector with a fixed capacity, it can be stored on the stack too. Implements fixed capacity ArrayVec and ArrayString." | ||
| description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." | ||
| documentation = "https://docs.rs/arrayvec/" | ||
| keywords = ["stack", "vector", "array", "data-structure", "no_std"] | ||
| categories = ["data-structures", "no-std"] | ||
| license = "MIT/Apache-2.0" | ||
| repository = "https://github.com/bluss/arrayvec" | ||
| [package.metadata.docs.rs] | ||
| features = ["serde-1"] | ||
| [package.metadata.release] | ||
| no-dev-version = true | ||
| [dependencies.generic-array] | ||
| version = "0.5.1" | ||
| [dependencies.serde] | ||
| version = "1.0" | ||
| optional = true | ||
| [dependencies.nodrop] | ||
| version = "0.1.8" | ||
| default-features = false | ||
@@ -37,6 +38,15 @@ | ||
| [dependencies.nodrop] | ||
| version = "0.1.8" | ||
| default-features = false | ||
| [dev-dependencies.serde_test] | ||
| version = "1.0" | ||
| [dev-dependencies.matches] | ||
| version = "0.1" | ||
| [features] | ||
| use_union = ["nodrop/use_union"] | ||
| std = ["odds/std", "nodrop/std"] | ||
| default = ["std"] | ||
| std = ["odds/std", "nodrop/std"] | ||
| use_generic_array = ["generic-array"] | ||
| use_union = ["nodrop/use_union"] | ||
| serde-1 = ["serde"] |
+14
-7
@@ -5,3 +5,3 @@ | ||
| A vector with fixed capacity. Requires Rust 1.2+. | ||
| A vector with fixed capacity. | ||
@@ -26,11 +26,18 @@ Please read the `API documentation here`__ | ||
| - 0.3.25 | ||
| - 0.4.0 | ||
| - Fix future compat warning about raw pointer casts | ||
| - Reformed signatures and error handling by @bluss and @tbu-: | ||
| - 0.3.24 | ||
| - ``ArrayVec``'s ``push, insert, remove, swap_remove`` now match ``Vec``'s | ||
| corresponding signature and panic on capacity errors where applicable. | ||
| - Add fallible methods ``try_push, insert`` and checked methods | ||
| ``pop_at, swap_pop``. | ||
| - Similar changes to ``ArrayString``'s push methods. | ||
| - Fix compilation on 16-bit targets. This means, the 65536 array size is not | ||
| included on these targets. | ||
| - Fix license files so that they are both included (was fixed in 0.4 before) | ||
| - Use a local version of the ``RangeArgument`` trait | ||
| - Add array sizes 50, 150, 200 by @daboross | ||
| - Support serde 1.0 by @daboross | ||
| - New method ``.push_unchecked()`` by @niklasf | ||
| - ``ArrayString`` implements ``PartialOrd, Ord`` by @tbu- | ||
| - Require Rust 1.14 | ||
@@ -37,0 +44,0 @@ - 0.3.23 |
+104
-14
@@ -15,4 +15,8 @@ use std::borrow::Borrow; | ||
| use CapacityError; | ||
| use errors::PubCrateNew; | ||
| use odds::char::encode_utf8; | ||
| #[cfg(feature="serde-1")] | ||
| use serde::{Serialize, Deserialize, Serializer, Deserializer}; | ||
| /// A string with a fixed capacity. | ||
@@ -69,3 +73,3 @@ /// | ||
| let mut arraystr = Self::new(); | ||
| try!(arraystr.push_str(s)); | ||
| arraystr.try_push_str(s)?; | ||
| Ok(arraystr) | ||
@@ -86,3 +90,3 @@ } | ||
| 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()); | ||
@@ -119,2 +123,22 @@ Ok(arraystr) | ||
| /// | ||
| /// ***Panics*** if the backing array is not large enough to fit the additional char. | ||
| /// | ||
| /// ``` | ||
| /// use arrayvec::ArrayString; | ||
| /// | ||
| /// let mut string = ArrayString::<[_; 2]>::new(); | ||
| /// | ||
| /// 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. | ||
@@ -127,5 +151,5 @@ /// | ||
| /// | ||
| /// string.push('a').unwrap(); | ||
| /// string.push('b').unwrap(); | ||
| /// let overflow = string.push('c'); | ||
| /// string.try_push('a').unwrap(); | ||
| /// string.try_push('b').unwrap(); | ||
| /// let overflow = string.try_push('c'); | ||
| /// | ||
@@ -135,3 +159,3 @@ /// assert_eq!(&string[..], "ab"); | ||
| /// ``` | ||
| 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(); | ||
@@ -153,2 +177,22 @@ unsafe { | ||
| /// | ||
| /// ***Panics*** if the backing array is not large enough to fit the string. | ||
| /// | ||
| /// ``` | ||
| /// use arrayvec::ArrayString; | ||
| /// | ||
| /// let mut string = ArrayString::<[_; 2]>::new(); | ||
| /// | ||
| /// 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. | ||
@@ -161,6 +205,6 @@ /// | ||
| /// | ||
| /// string.push_str("a").unwrap(); | ||
| /// let overflow1 = string.push_str("bc"); | ||
| /// string.push_str("d").unwrap(); | ||
| /// let overflow2 = string.push_str("ef"); | ||
| /// 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"); | ||
| /// | ||
@@ -171,3 +215,3 @@ /// assert_eq!(&string[..], "ad"); | ||
| /// ``` | ||
| 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() { | ||
@@ -283,6 +327,7 @@ return Err(CapacityError::new(s)); | ||
| 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) | ||
| } | ||
@@ -298,3 +343,3 @@ } | ||
| self.clear(); | ||
| self.push_str(rhs).ok(); | ||
| self.try_push_str(rhs).ok(); | ||
| } | ||
@@ -338,1 +383,46 @@ } | ||
| } | ||
| #[cfg(feature="serde-1")] | ||
| impl<A: Array<Item=u8>> Serialize for ArrayString<A> { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
| where S: Serializer | ||
| { | ||
| serializer.serialize_str(&*self) | ||
| } | ||
| } | ||
| #[cfg(feature="serde-1")] | ||
| impl<'de, A: Array<Item=u8>> Deserialize<'de> for ArrayString<A> { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
| where D: Deserializer<'de> | ||
| { | ||
| use serde::de::{self, Visitor}; | ||
| use std::marker::PhantomData; | ||
| struct ArrayStringVisitor<A: Array<Item=u8>>(PhantomData<A>); | ||
| impl<'de, A: Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> { | ||
| type Value = ArrayString<A>; | ||
| fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | ||
| write!(formatter, "a string no more than {} bytes long", A::capacity()) | ||
| } | ||
| fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> | ||
| where E: de::Error, | ||
| { | ||
| ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self)) | ||
| } | ||
| fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> | ||
| where E: de::Error, | ||
| { | ||
| let s = try!(str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))); | ||
| ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self)) | ||
| } | ||
| } | ||
| deserializer.deserialize_str(ArrayStringVisitor::<A>(PhantomData)) | ||
| } | ||
| } |
+1
-21
@@ -35,20 +35,2 @@ | ||
| #[cfg(feature = "use_generic_array")] | ||
| unsafe impl<T, U> Array for ::generic_array::GenericArray<T, U> | ||
| where U: ::generic_array::ArrayLength<T> | ||
| { | ||
| type Item = T; | ||
| type Index = usize; | ||
| fn as_ptr(&self) -> *const Self::Item { | ||
| (**self).as_ptr() | ||
| } | ||
| fn as_mut_ptr(&mut self) -> *mut Self::Item { | ||
| (**self).as_mut_ptr() | ||
| } | ||
| fn capacity() -> usize { | ||
| U::to_usize() | ||
| } | ||
| } | ||
| impl Index for u8 { | ||
@@ -107,7 +89,5 @@ #[inline(always)] | ||
| 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,); | ||
| 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, 160, 192, 200, 224,); | ||
| fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,); | ||
| // This array size doesn't exist on 16-bit | ||
| #[cfg(any(target_pointer_width="32", target_pointer_width="64"))] | ||
| fix_array_impl_recursive!(u32, 1 << 16,); | ||
+227
-93
| //! **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: | ||
| //! The arrayvec package has the following cargo features: | ||
| //! | ||
| //! - `std` | ||
| //! - Optional, enabled by default | ||
| //! - Requires Rust 1.6 *to disable* | ||
| //! - Use libstd | ||
| //! - Use libstd; disable to use `no_std` instead. | ||
| //! | ||
@@ -14,18 +13,19 @@ //! - `use_union` | ||
| //! - Requires Rust nightly channel | ||
| //! - Experimental: This flag uses nightly so it *may break* unexpectedly | ||
| //! at some point; since it doesn't change API this flag may also change | ||
| //! to do nothing in the future. | ||
| //! - Use the unstable feature untagged unions for the internal implementation, | ||
| //! which has reduced space overhead | ||
| //! which may have reduced space overhead | ||
| //! | ||
| //! - `use_generic_array` | ||
| //! - Optional | ||
| //! - Requires Rust stable channel | ||
| //! - Depend on generic-array and allow using it just like a fixed | ||
| //! size array for ArrayVec storage. | ||
| #![doc(html_root_url="https://docs.rs/arrayvec/0.3/")] | ||
| //! ## Rust Version | ||
| //! | ||
| //! This version of arrayvec requires Rust 1.14 or later. | ||
| //! | ||
| #![doc(html_root_url="https://docs.rs/arrayvec/0.4/")] | ||
| #![cfg_attr(not(feature="std"), no_std)] | ||
| extern crate odds; | ||
| extern crate nodrop; | ||
| #[cfg(feature="serde-1")] | ||
| extern crate serde; | ||
| #[cfg(feature = "use_generic_array")] | ||
| extern crate generic_array; | ||
| #[cfg(not(feature="std"))] | ||
@@ -51,16 +51,19 @@ extern crate core as std; | ||
| use std::io; | ||
| #[cfg(feature="std")] | ||
| use std::error::Error; | ||
| #[cfg(feature="std")] | ||
| use std::any::Any; // core but unused | ||
| use nodrop::NoDrop; | ||
| #[cfg(feature="serde-1")] | ||
| 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; | ||
@@ -103,2 +106,9 @@ | ||
| 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> { | ||
@@ -161,4 +171,3 @@ /// Create a new empty `ArrayVec`. | ||
| /// | ||
| /// Return `None` if the push succeeds, or and return `Some(` *element* `)` | ||
| /// if the vector is full. | ||
| /// ***Panics*** if the vector is already full. | ||
| /// | ||
@@ -172,31 +181,82 @@ /// ``` | ||
| /// 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() { | ||
| let len = self.len(); | ||
| unsafe { | ||
| ptr::write(self.get_unchecked_mut(len), element); | ||
| self.set_len(len + 1); | ||
| self.push_unchecked(element); | ||
| } | ||
| None | ||
| Ok(()) | ||
| } else { | ||
| Some(element) | ||
| Err(CapacityError::new(element)) | ||
| } | ||
| } | ||
| /// Insert `element` in position `index`. | ||
| /// Push `element` to the end of the vector without checking the capacity. | ||
| /// | ||
| /// Shift up all elements after `index`. If any is pushed out, it is returned. | ||
| /// It is up to the caller to ensure the capacity of the vector is | ||
| /// sufficiently large. | ||
| /// | ||
| /// Return `None` if no element is shifted out. | ||
| /// This method *may* use debug assertions to check that the arrayvec is not 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. | ||
| /// ``` | ||
| /// use arrayvec::ArrayVec; | ||
| /// | ||
| /// let mut array = ArrayVec::<[_; 2]>::new(); | ||
| /// | ||
| /// if array.len() + 2 <= array.capacity() { | ||
| /// unsafe { | ||
| /// array.push_unchecked(1); | ||
| /// array.push_unchecked(2); | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// assert_eq!(&array[..], &[1, 2]); | ||
| /// ``` | ||
| #[inline] | ||
| pub unsafe fn push_unchecked(&mut self, element: A::Item) { | ||
| let len = self.len(); | ||
| debug_assert!(len < A::capacity()); | ||
| ptr::write(self.get_unchecked_mut(len), element); | ||
| self.set_len(len + 1); | ||
| } | ||
| /// Insert `element` at position `index`. | ||
| /// | ||
| /// Shift up all elements after `index`. | ||
| /// | ||
| /// It is an error if the index is greater than the length or if the | ||
| /// arrayvec is full. | ||
| /// | ||
| /// ***Panics*** on errors. See `try_result` for fallible version. | ||
| /// | ||
| /// ``` | ||
| /// use arrayvec::ArrayVec; | ||
@@ -206,16 +266,37 @@ /// | ||
| /// | ||
| /// 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)); | ||
| } | ||
@@ -228,3 +309,3 @@ let len = self.len(); | ||
| { | ||
| let p: *mut _ = self.get_unchecked_mut(index); | ||
| let p = self.get_unchecked_mut(index) as *mut _; | ||
| // Shift everything over to make space. (Duplicating the | ||
@@ -239,6 +320,6 @@ // `index`th element into two consecutive places.) | ||
| } | ||
| ret | ||
| Ok(()) | ||
| } | ||
| /// Remove the last element in the vector. | ||
| /// Remove the last element in the vector and return it. | ||
| /// | ||
@@ -272,2 +353,29 @@ /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. | ||
| /// | ||
| /// 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`. | ||
@@ -280,11 +388,11 @@ /// | ||
| /// | ||
| /// 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; | ||
| } | ||
@@ -297,4 +405,6 @@ self.swap(index, len - 1); | ||
| /// | ||
| /// 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. | ||
| /// | ||
| /// ``` | ||
@@ -305,8 +415,30 @@ /// use arrayvec::ArrayVec; | ||
| /// | ||
| /// 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. | ||
| /// | ||
| /// assert_eq!(array.remove(10), None); | ||
| /// This is a checked version of `.remove(index)`. Returns `None` if there | ||
| /// is no element at `index`. Otherwise, return the element inside `Some`. | ||
| /// | ||
| /// ``` | ||
| pub fn remove(&mut self, index: usize) -> Option<A::Item> { | ||
| /// use arrayvec::ArrayVec; | ||
| /// | ||
| /// let mut array = ArrayVec::from([1, 2, 3]); | ||
| /// | ||
| /// assert!(array.pop_at(0).is_some()); | ||
| /// assert_eq!(&array[..], &[2, 3]); | ||
| /// | ||
| /// assert!(array.pop_at(2).is_none()); | ||
| /// assert!(array.pop_at(10).is_none()); | ||
| /// ``` | ||
| pub fn pop_at(&mut self, index: usize) -> Option<A::Item> { | ||
| if index >= self.len() { | ||
@@ -360,3 +492,4 @@ None | ||
| /// | ||
| /// May panic if `length` is greater than the capacity. | ||
| /// May use debug assertions to check that `length` is not greater than the | ||
| /// capacity. | ||
| /// | ||
@@ -386,3 +519,3 @@ /// This function is `unsafe` because it changes the notion of the | ||
| /// 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]); | ||
@@ -694,3 +827,5 @@ /// assert_eq!(&u[..], &[1, 2]); | ||
| for elt in iter.into_iter().take(take) { | ||
| self.push(elt); | ||
| unsafe { | ||
| self.push_unchecked(elt); | ||
| } | ||
| } | ||
@@ -847,46 +982,45 @@ } | ||
| /// Error value indicating insufficient capacity | ||
| #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] | ||
| pub struct CapacityError<T = ()> { | ||
| element: T, | ||
| #[cfg(feature="serde-1")] | ||
| impl<T: Serialize, A: Array<Item=T>> Serialize for ArrayVec<A> { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
| where S: Serializer | ||
| { | ||
| serializer.collect_seq(self) | ||
| } | ||
| } | ||
| impl<T> CapacityError<T> { | ||
| fn new(element: T) -> CapacityError<T> { | ||
| CapacityError { | ||
| element: element, | ||
| } | ||
| } | ||
| #[cfg(feature="serde-1")] | ||
| impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A> { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
| where D: Deserializer<'de> | ||
| { | ||
| use serde::de::{Visitor, SeqAccess, Error}; | ||
| use std::marker::PhantomData; | ||
| /// Extract the overflowing element | ||
| pub fn element(self) -> T { | ||
| self.element | ||
| } | ||
| struct ArrayVecVisitor<'de, T: Deserialize<'de>, A: Array<Item=T>>(PhantomData<(&'de (), T, A)>); | ||
| /// Convert into a `CapacityError` that does not carry an element. | ||
| pub fn simplify(self) -> CapacityError { | ||
| CapacityError { element: () } | ||
| } | ||
| } | ||
| impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Visitor<'de> for ArrayVecVisitor<'de, T, A> { | ||
| type Value = ArrayVec<A>; | ||
| const CAPERROR: &'static str = "insufficient capacity"; | ||
| fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | ||
| write!(formatter, "an array with no more than {} items", A::capacity()) | ||
| } | ||
| #[cfg(feature="std")] | ||
| /// Requires `features="std"`. | ||
| impl<T: Any> Error for CapacityError<T> { | ||
| fn description(&self) -> &str { | ||
| CAPERROR | ||
| } | ||
| } | ||
| fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error> | ||
| where SA: SeqAccess<'de>, | ||
| { | ||
| let mut values = ArrayVec::<A>::new(); | ||
| impl<T> fmt::Display for CapacityError<T> { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write!(f, "{}", CAPERROR) | ||
| } | ||
| } | ||
| while let Some(value) = try!(seq.next_element()) { | ||
| if let Err(_) = values.try_push(value) { | ||
| return Err(SA::Error::invalid_length(A::capacity() + 1, &self)); | ||
| } | ||
| } | ||
| impl<T> fmt::Debug for CapacityError<T> { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| write!(f, "{}: {}", "CapacityError", CAPERROR) | ||
| Ok(values) | ||
| } | ||
| } | ||
| deserializer.deserialize_seq(ArrayVecVisitor::<T, A>(PhantomData)) | ||
| } | ||
| } |
+57
-31
| extern crate arrayvec; | ||
| #[macro_use] extern crate matches; | ||
@@ -6,2 +7,3 @@ use arrayvec::ArrayVec; | ||
| use std::mem; | ||
| use arrayvec::CapacityError; | ||
@@ -34,5 +36,5 @@ use std::collections::HashMap; | ||
| 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); | ||
@@ -82,3 +84,5 @@ } | ||
| 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); | ||
@@ -223,4 +227,3 @@ drop(array.pop()); | ||
| 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(_)); | ||
@@ -230,11 +233,16 @@ let mut v = ArrayVec::<[_; 3]>::new(); | ||
| 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 { .. })); | ||
| } | ||
@@ -307,3 +315,3 @@ | ||
| let mut s = ArrayString::<[_; 16]>::new(); | ||
| s.push_str(text).unwrap(); | ||
| s.try_push_str(text).unwrap(); | ||
| assert_eq!(&s, text); | ||
@@ -318,6 +326,6 @@ assert_eq!(text, &s); | ||
| 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 | ||
@@ -330,3 +338,3 @@ let tmut: &mut str = &mut t; | ||
| let mut t = ArrayString::<[_; 2]>::new(); | ||
| try!(t.push_str(text)); | ||
| try!(t.try_push_str(text)); | ||
| Ok(()) | ||
@@ -358,3 +366,3 @@ }(); | ||
| let mut s = ArrayString::<[_; 4]>::new(); | ||
| s.push_str("abcd").unwrap(); | ||
| s.push_str("abcd"); | ||
| let t = ArrayString::<[_; 4]>::from(text).unwrap(); | ||
@@ -370,3 +378,3 @@ s.clone_from(&t); | ||
| for c in text.chars() { | ||
| if let Err(_) = s.push(c) { | ||
| if let Err(_) = s.try_push(c) { | ||
| break; | ||
@@ -376,5 +384,5 @@ } | ||
| 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()); | ||
| } | ||
@@ -386,23 +394,25 @@ | ||
| 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 _ = v.try_insert(1, "test"); | ||
| } | ||
| /* | ||
| * insert that pushes out the last | ||
| let mut u = ArrayVec::from([1, 2, 3, 4]); | ||
| let ret = u.insert(3, 99); | ||
| let ret = u.try_insert(3, 99); | ||
| assert_eq!(&u[..], &[1, 2, 3, 99]); | ||
| assert_eq!(ret, Some(4)); | ||
| let ret = u.insert(4, 77); | ||
| assert_matches!(ret, Err(_)); | ||
| let ret = u.try_insert(4, 77); | ||
| assert_eq!(&u[..], &[1, 2, 3, 99]); | ||
| assert_eq!(ret, Some(77)); | ||
| } | ||
| assert_matches!(ret, Err(_)); | ||
| */ | ||
@@ -431,5 +441,5 @@ #[test] | ||
| 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); | ||
@@ -442,2 +452,18 @@ assert_eq!(flag.get(), 1); | ||
| #[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"]); | ||
| } | ||
| #[test] | ||
| fn test_sizes() { | ||
@@ -444,0 +470,0 @@ let v = ArrayVec::from([0u8; 1 << 16]); |
| #![cfg(feature = "use_generic_array")] | ||
| extern crate arrayvec; | ||
| #[macro_use] | ||
| extern crate generic_array; | ||
| use arrayvec::ArrayVec; | ||
| use generic_array::GenericArray; | ||
| use generic_array::typenum::U41; | ||
| #[test] | ||
| fn test_simple() { | ||
| let mut vec: ArrayVec<GenericArray<i32, U41>> = ArrayVec::new(); | ||
| assert_eq!(vec.len(), 0); | ||
| assert_eq!(vec.capacity(), 41); | ||
| vec.extend(0..20); | ||
| assert_eq!(vec.len(), 20); | ||
| assert_eq!(&vec[..5], &[0, 1, 2, 3, 4]); | ||
| } | ||
Sorry, the diff of this file is not supported yet