| { | ||
| "git": { | ||
| "sha1": "f88c62e59fc130edf1185b6c33720eb4874c814a" | ||
| "sha1": "ea591bc2de5202790c600638c96efa392413001c" | ||
| } | ||
| } |
+16
-25
| language: rust | ||
| sudo: false | ||
| env: | ||
| - FEATURES='serde-1' | ||
| - FEATURES='serde' | ||
| matrix: | ||
| include: | ||
| - rust: 1.13.0 | ||
| - rust: stable | ||
| - rust: 1.36.0 | ||
| env: | ||
| - NODEFAULT=1 | ||
| - NODROP_FEATURES='use_needs_drop' | ||
| - rust: 1.22.1 | ||
| env: | ||
| - FEATURES='array-sizes-33-128 array-sizes-129-255' | ||
| - rust: stable | ||
| - rust: stable | ||
| env: | ||
| - FEATURES='serde' | ||
| - rust: stable | ||
| env: | ||
| - FEATURES='array-sizes-33-128 array-sizes-129-255' | ||
| - ARRAYVECTEST_ENSURE_MAYBEUNINIT=1 | ||
| - rust: beta | ||
| - rust: nightly | ||
| env: | ||
| - NODEFAULT=1 | ||
| - ARRAYVECTEST_ENSURE_UNION=1 | ||
| - rust: nightly | ||
| env: | ||
| - NODROP_FEATURES='use_needs_drop' | ||
| - ARRAYVECTEST_ENSURE_MAYBEUNINIT=1 | ||
| - FEATURES='serde' | ||
| - rust: nightly | ||
| env: | ||
| - FEATURES='serde use_union' | ||
| - NODROP_FEATURES='use_union' | ||
| - ARRAYVECTEST_ENSURE_MAYBEUNINIT=1 | ||
| - FEATURES='array-sizes-33-128 array-sizes-129-255' | ||
| branches: | ||
@@ -39,10 +31,9 @@ only: | ||
| - | | ||
| ([ ! -z "$NODROP_FEATURES" ] || cargo build --verbose --features "$FEATURES") && | ||
| ([ "$NODEFAULT" != 1 ] || cargo build --verbose --no-default-features) && | ||
| ([ ! -z "$NODROP_FEATURES" ] || cargo test --verbose --features "$FEATURES") && | ||
| ([ ! -z "$NODROP_FEATURES" ] || cargo test --release --verbose --features "$FEATURES") && | ||
| ([ ! -z "$NODROP_FEATURES" ] || cargo bench --verbose --features "$FEATURES" -- --test) && | ||
| ([ ! -z "$NODROP_FEATURES" ] || cargo doc --verbose --features "$FEATURES") && | ||
| ([ "$NODEFAULT" != 1 ] || cargo build --verbose --manifest-path=nodrop/Cargo.toml --no-default-features) && | ||
| cargo test --verbose --manifest-path=nodrop/Cargo.toml --features "$NODROP_FEATURES" && | ||
| cargo bench --verbose --manifest-path=nodrop/Cargo.toml --features "$NODROP_FEATURES" -- --test | ||
| cargo build -v --no-default-features && | ||
| cargo build -v --features "$FEATURES" && | ||
| cargo test -v --features "$FEATURES" && | ||
| cargo test -v --release --features "$FEATURES" && | ||
| cargo bench -v --features "$FEATURES" --no-run && | ||
| cargo doc -v --features "$FEATURES" && | ||
| cargo build -v --manifest-path=nodrop/Cargo.toml && | ||
| cargo test -v --manifest-path=nodrop/Cargo.toml |
+42
-7
@@ -5,5 +5,8 @@ | ||
| use std::io::Write; | ||
| use arrayvec::ArrayVec; | ||
| use bencher::Bencher; | ||
| use bencher::black_box; | ||
@@ -15,4 +18,5 @@ fn extend_with_constant(b: &mut Bencher) { | ||
| v.clear(); | ||
| v.extend((0..cap).map(|_| 1)); | ||
| v[0] | ||
| let constant = black_box(1); | ||
| v.extend((0..cap).map(move |_| constant)); | ||
| v[511] | ||
| }); | ||
@@ -27,4 +31,5 @@ b.bytes = v.capacity() as u64; | ||
| v.clear(); | ||
| v.extend((0..cap).map(|x| x as _)); | ||
| v[0] | ||
| let range = 0..cap; | ||
| v.extend(range.map(|x| black_box(x as _))); | ||
| v[511] | ||
| }); | ||
@@ -39,4 +44,5 @@ b.bytes = v.capacity() as u64; | ||
| v.clear(); | ||
| v.extend(data.iter().cloned()); | ||
| v[0] | ||
| let iter = data.iter().map(|&x| x); | ||
| v.extend(iter); | ||
| v[511] | ||
| }); | ||
@@ -46,3 +52,32 @@ b.bytes = v.capacity() as u64; | ||
| benchmark_group!(benches, extend_with_constant, extend_with_range, extend_with_slice); | ||
| fn extend_with_write(b: &mut Bencher) { | ||
| let mut v = ArrayVec::<[u8; 512]>::new(); | ||
| let data = [1; 512]; | ||
| b.iter(|| { | ||
| v.clear(); | ||
| v.write(&data[..]).ok(); | ||
| v[511] | ||
| }); | ||
| b.bytes = v.capacity() as u64; | ||
| } | ||
| fn extend_from_slice(b: &mut Bencher) { | ||
| let mut v = ArrayVec::<[u8; 512]>::new(); | ||
| let data = [1; 512]; | ||
| b.iter(|| { | ||
| v.clear(); | ||
| v.try_extend_from_slice(&data).ok(); | ||
| v[511] | ||
| }); | ||
| b.bytes = v.capacity() as u64; | ||
| } | ||
| benchmark_group!(benches, | ||
| extend_with_constant, | ||
| extend_with_range, | ||
| extend_with_slice, | ||
| extend_with_write, | ||
| extend_from_slice | ||
| ); | ||
| benchmark_main!(benches); |
+3
-8
@@ -14,4 +14,5 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| [package] | ||
| edition = "2018" | ||
| name = "arrayvec" | ||
| version = "0.4.12" | ||
| version = "0.5.0" | ||
| authors = ["bluss"] | ||
@@ -25,3 +26,3 @@ description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." | ||
| [package.metadata.docs.rs] | ||
| features = ["serde-1"] | ||
| features = ["serde"] | ||
@@ -39,6 +40,2 @@ [package.metadata.release] | ||
| harness = false | ||
| [dependencies.nodrop] | ||
| version = "0.1.12" | ||
| default-features = false | ||
| [dependencies.serde] | ||
@@ -63,4 +60,2 @@ version = "1.0" | ||
| default = ["std"] | ||
| serde-1 = ["serde"] | ||
| std = [] | ||
| use_union = [] |
+20
-3
@@ -25,6 +25,23 @@ | ||
| - 0.4.12 | ||
| - 0.5.0 (not released yet) | ||
| - Use raw pointers instead of ``get_unchecked_mut`` where the target may be | ||
| uninitialized a everywhere relevant in the ArrayVec implementation. | ||
| - Use ``MaybeUninit`` (now unconditionally) in the implementation of | ||
| ``ArrayVec`` | ||
| - Use ``MaybeUninit`` (now unconditionally) in the implementation of | ||
| ``ArrayString`` | ||
| - The crate feature for serde serialization is now named ``serde``. | ||
| - Updated the ``Array`` trait interface, and it is now easier to use for | ||
| users outside the crate. | ||
| - Add ``FromStr`` impl for ``ArrayString`` by @despawnerer | ||
| - Add method ``try_extend_from_slice`` to ``ArrayVec``, which is always | ||
| effecient by @Thomasdezeeuw. | ||
| - Add method ``remaining_capacity`` by @Thomasdezeeuw | ||
| - Improve performance of the ``extend`` method. | ||
| - The index type of zero capacity vectors is now itself zero size, by | ||
| @clarfon | ||
| - Use ``drop_in_place`` for truncate and clear methods. This affects drop order | ||
| and resume from panic during drop. | ||
| - Use Rust 2018 edition for the implementation | ||
| - Require Rust 1.36 or later, for the unconditional ``MaybeUninit`` | ||
| improvements. | ||
@@ -31,0 +48,0 @@ - 0.4.11 |
+107
-53
@@ -5,17 +5,19 @@ use std::borrow::Borrow; | ||
| use std::hash::{Hash, Hasher}; | ||
| use std::mem; | ||
| use std::ptr; | ||
| use std::ops::{Deref, DerefMut}; | ||
| use std::str; | ||
| use std::str::FromStr; | ||
| use std::str::Utf8Error; | ||
| use std::slice; | ||
| use array::{Array, ArrayExt}; | ||
| use array::Index; | ||
| use CapacityError; | ||
| use char::encode_utf8; | ||
| use crate::array::Array; | ||
| use crate::array::Index; | ||
| use crate::CapacityError; | ||
| use crate::char::encode_utf8; | ||
| #[cfg(feature="serde-1")] | ||
| #[cfg(feature="serde")] | ||
| use serde::{Serialize, Deserialize, Serializer, Deserializer}; | ||
| use super::MaybeUninit as MaybeUninitCopy; | ||
| /// A string with a fixed capacity. | ||
@@ -29,9 +31,12 @@ /// | ||
| #[derive(Copy)] | ||
| pub struct ArrayString<A: Array<Item=u8>> { | ||
| // FIXME: Use Copyable union for xs when we can | ||
| xs: A, | ||
| pub struct ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| xs: MaybeUninitCopy<A>, | ||
| len: A::Index, | ||
| } | ||
| impl<A: Array<Item=u8>> Default for ArrayString<A> { | ||
| impl<A> Default for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| /// Return an empty `ArrayString` | ||
@@ -43,3 +48,5 @@ fn default() -> ArrayString<A> { | ||
| impl<A: Array<Item=u8>> ArrayString<A> { | ||
| impl<A> ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| /// Create a new empty `ArrayString`. | ||
@@ -60,4 +67,3 @@ /// | ||
| ArrayString { | ||
| // FIXME: Use Copyable union for xs when we can | ||
| xs: mem::zeroed(), | ||
| xs: MaybeUninitCopy::uninitialized(), | ||
| len: Index::from(0), | ||
@@ -98,7 +104,8 @@ } | ||
| 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.try_push_str(s); | ||
| debug_assert!(_result.is_ok()); | ||
| Ok(arraystr) | ||
| let len = str::from_utf8(b.as_slice())?.len(); | ||
| debug_assert_eq!(len, A::CAPACITY); | ||
| Ok(ArrayString { | ||
| xs: MaybeUninitCopy::from(*b), | ||
| len: Index::from(A::CAPACITY), | ||
| }) | ||
| } | ||
@@ -115,3 +122,3 @@ | ||
| #[inline] | ||
| pub fn capacity(&self) -> usize { A::capacity() } | ||
| pub fn capacity(&self) -> usize { A::CAPACITY } | ||
@@ -222,3 +229,3 @@ /// Return if the `ArrayString` is completely filled. | ||
| unsafe { | ||
| let dst = self.xs.as_mut_ptr().offset(self.len() as isize); | ||
| let dst = self.xs.ptr_mut().offset(self.len() as isize); | ||
| let src = s.as_ptr(); | ||
@@ -317,4 +324,4 @@ ptr::copy_nonoverlapping(src, dst, s.len()); | ||
| unsafe { | ||
| ptr::copy(self.xs.as_ptr().offset(next as isize), | ||
| self.xs.as_mut_ptr().offset(idx as isize), | ||
| ptr::copy(self.xs.ptr().offset(next as isize), | ||
| self.xs.ptr_mut().offset(idx as isize), | ||
| len - next); | ||
@@ -353,7 +360,9 @@ self.set_len(len - (next - idx)); | ||
| unsafe fn raw_mut_bytes(&mut self) -> &mut [u8] { | ||
| slice::from_raw_parts_mut(self.xs.as_mut_ptr(), self.capacity()) | ||
| slice::from_raw_parts_mut(self.xs.ptr_mut(), self.capacity()) | ||
| } | ||
| } | ||
| impl<A: Array<Item=u8>> Deref for ArrayString<A> { | ||
| impl<A> Deref for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| type Target = str; | ||
@@ -363,3 +372,3 @@ #[inline] | ||
| unsafe { | ||
| let sl = slice::from_raw_parts(self.xs.as_ptr(), self.len.to_usize()); | ||
| let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize()); | ||
| str::from_utf8_unchecked(sl) | ||
@@ -370,9 +379,10 @@ } | ||
| impl<A: Array<Item=u8>> DerefMut for ArrayString<A> { | ||
| impl<A> DerefMut for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| #[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 sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize()); | ||
| str::from_utf8_unchecked_mut(sl) | ||
| } | ||
@@ -382,3 +392,5 @@ } | ||
| impl<A: Array<Item=u8>> PartialEq for ArrayString<A> { | ||
| impl<A> PartialEq for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn eq(&self, rhs: &Self) -> bool { | ||
@@ -389,3 +401,5 @@ **self == **rhs | ||
| impl<A: Array<Item=u8>> PartialEq<str> for ArrayString<A> { | ||
| impl<A> PartialEq<str> for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn eq(&self, rhs: &str) -> bool { | ||
@@ -396,3 +410,5 @@ &**self == rhs | ||
| impl<A: Array<Item=u8>> PartialEq<ArrayString<A>> for str { | ||
| impl<A> PartialEq<ArrayString<A>> for str | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn eq(&self, rhs: &ArrayString<A>) -> bool { | ||
@@ -403,5 +419,9 @@ self == &**rhs | ||
| impl<A: Array<Item=u8>> Eq for ArrayString<A> { } | ||
| impl<A> Eq for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { } | ||
| impl<A: Array<Item=u8>> Hash for ArrayString<A> { | ||
| impl<A> Hash for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn hash<H: Hasher>(&self, h: &mut H) { | ||
@@ -412,15 +432,23 @@ (**self).hash(h) | ||
| impl<A: Array<Item=u8>> Borrow<str> for ArrayString<A> { | ||
| impl<A> Borrow<str> for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn borrow(&self) -> &str { self } | ||
| } | ||
| impl<A: Array<Item=u8>> AsRef<str> for ArrayString<A> { | ||
| impl<A> AsRef<str> for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn as_ref(&self) -> &str { self } | ||
| } | ||
| impl<A: Array<Item=u8>> fmt::Debug for ArrayString<A> { | ||
| impl<A> fmt::Debug for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } | ||
| } | ||
| impl<A: Array<Item=u8>> fmt::Display for ArrayString<A> { | ||
| impl<A> fmt::Display for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } | ||
@@ -430,3 +458,5 @@ } | ||
| /// `Write` appends written data to the end of the string. | ||
| impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> { | ||
| impl<A> fmt::Write for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn write_char(&mut self, c: char) -> fmt::Result { | ||
@@ -441,3 +471,5 @@ self.try_push(c).map_err(|_| fmt::Error) | ||
| impl<A: Array<Item=u8> + Copy> Clone for ArrayString<A> { | ||
| impl<A> Clone for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn clone(&self) -> ArrayString<A> { | ||
@@ -453,3 +485,5 @@ *self | ||
| impl<A: Array<Item=u8>> PartialOrd for ArrayString<A> { | ||
| impl<A> PartialOrd for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> { | ||
@@ -464,3 +498,5 @@ (**self).partial_cmp(&**rhs) | ||
| impl<A: Array<Item=u8>> PartialOrd<str> for ArrayString<A> { | ||
| impl<A> PartialOrd<str> for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> { | ||
@@ -475,3 +511,5 @@ (**self).partial_cmp(rhs) | ||
| impl<A: Array<Item=u8>> PartialOrd<ArrayString<A>> for str { | ||
| impl<A> PartialOrd<ArrayString<A>> for str | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn partial_cmp(&self, rhs: &ArrayString<A>) -> Option<cmp::Ordering> { | ||
@@ -486,3 +524,5 @@ self.partial_cmp(&**rhs) | ||
| impl<A: Array<Item=u8>> Ord for ArrayString<A> { | ||
| impl<A> Ord for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn cmp(&self, rhs: &Self) -> cmp::Ordering { | ||
@@ -493,5 +533,17 @@ (**self).cmp(&**rhs) | ||
| #[cfg(feature="serde-1")] | ||
| /// Requires crate feature `"serde-1"` | ||
| impl<A: Array<Item=u8>> Serialize for ArrayString<A> { | ||
| impl<A> FromStr for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| type Err = CapacityError; | ||
| fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
| Self::from(s).map_err(CapacityError::simplify) | ||
| } | ||
| } | ||
| #[cfg(feature="serde")] | ||
| /// Requires crate feature `"serde"` | ||
| impl<A> Serialize for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
@@ -504,5 +556,7 @@ where S: Serializer | ||
| #[cfg(feature="serde-1")] | ||
| /// Requires crate feature `"serde-1"` | ||
| impl<'de, A: Array<Item=u8>> Deserialize<'de> for ArrayString<A> { | ||
| #[cfg(feature="serde")] | ||
| /// Requires crate feature `"serde"` | ||
| impl<'de, A> Deserialize<'de> for ArrayString<A> | ||
| where A: Array<Item=u8> + Copy | ||
| { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
@@ -516,7 +570,7 @@ where D: Deserializer<'de> | ||
| impl<'de, A: Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> { | ||
| impl<'de, A: Copy + 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()) | ||
| write!(formatter, "a string no more than {} bytes long", A::CAPACITY) | ||
| } | ||
@@ -533,3 +587,3 @@ | ||
| { | ||
| let s = try!(str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))); | ||
| let s = str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))?; | ||
@@ -536,0 +590,0 @@ ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self)) |
+34
-25
@@ -15,14 +15,21 @@ | ||
| /// (a few in this range are included by default). | ||
| /// | ||
| /// ## Safety | ||
| /// | ||
| /// This trait can *only* be implemented by fixed-size arrays or types with | ||
| /// *exactly* the representation of a fixed size array (of the right element | ||
| /// type and capacity). | ||
| /// | ||
| /// Normally this trait is an implementation detail of arrayvec and doesn’t | ||
| /// need implementing. | ||
| pub unsafe trait Array { | ||
| /// The array’s element type | ||
| type Item; | ||
| /// The smallest type that can index and tell the length of the array. | ||
| #[doc(hidden)] | ||
| /// The smallest index type that indexes the array. | ||
| type Index: Index; | ||
| #[doc(hidden)] | ||
| fn as_ptr(&self) -> *const Self::Item; | ||
| #[doc(hidden)] | ||
| fn as_mut_ptr(&mut self) -> *mut Self::Item; | ||
| #[doc(hidden)] | ||
| fn capacity() -> usize; | ||
| /// The array's element capacity | ||
| const CAPACITY: usize; | ||
| fn as_slice(&self) -> &[Self::Item]; | ||
| fn as_mut_slice(&mut self) -> &mut [Self::Item]; | ||
| } | ||
@@ -32,18 +39,19 @@ | ||
| fn to_usize(self) -> usize; | ||
| fn from(usize) -> Self; | ||
| fn from(_: usize) -> Self; | ||
| } | ||
| use std::slice::{from_raw_parts}; | ||
| impl Index for () { | ||
| #[inline(always)] | ||
| fn to_usize(self) -> usize { 0 } | ||
| #[inline(always)] | ||
| fn from(_ix: usize) -> Self { () } | ||
| } | ||
| pub trait ArrayExt : Array { | ||
| impl Index for bool { | ||
| #[inline(always)] | ||
| fn as_slice(&self) -> &[Self::Item] { | ||
| unsafe { | ||
| from_raw_parts(self.as_ptr(), Self::capacity()) | ||
| } | ||
| } | ||
| fn to_usize(self) -> usize { self as usize } | ||
| #[inline(always)] | ||
| fn from(ix: usize) -> Self { ix != 0 } | ||
| } | ||
| impl<A> ArrayExt for A where A: Array { } | ||
| impl Index for u8 { | ||
@@ -82,11 +90,9 @@ #[inline(always)] | ||
| type Index = $index_type; | ||
| const CAPACITY: usize = $len; | ||
| #[doc(hidden)] | ||
| #[inline(always)] | ||
| fn as_ptr(&self) -> *const T { self as *const _ as *const _ } | ||
| #[inline] | ||
| fn as_slice(&self) -> &[Self::Item] { self } | ||
| #[doc(hidden)] | ||
| #[inline(always)] | ||
| fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _} | ||
| #[doc(hidden)] | ||
| #[inline(always)] | ||
| fn capacity() -> usize { $len } | ||
| #[inline] | ||
| fn as_mut_slice(&mut self) -> &mut [Self::Item] { self } | ||
| } | ||
@@ -103,3 +109,6 @@ ) | ||
| fix_array_impl_recursive!(u8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | ||
| fix_array_impl_recursive!((), 0,); | ||
| fix_array_impl_recursive!(bool, 1,); | ||
| fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | ||
| 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, | ||
@@ -106,0 +115,0 @@ 28, 29, 30, 31, ); |
+145
-77
@@ -10,5 +10,5 @@ //! **arrayvec** provides the types `ArrayVec` and `ArrayString`: | ||
| //! | ||
| //! - `serde-1` | ||
| //! - `serde` | ||
| //! - Optional | ||
| //! - Enable serialization for ArrayVec and ArrayString using serde 1.0 | ||
| //! - Enable serialization for ArrayVec and ArrayString using serde 1.x | ||
| //! - `array-sizes-33-128`, `array-sizes-129-255` | ||
@@ -20,9 +20,8 @@ //! - Optional | ||
| //! | ||
| //! This version of arrayvec requires Rust 1.13 or later. | ||
| //! This version of arrayvec requires Rust 1.36 or later. | ||
| //! | ||
| #![doc(html_root_url="https://docs.rs/arrayvec/0.4/")] | ||
| #![cfg_attr(not(feature="std"), no_std)] | ||
| #![cfg_attr(has_union_feature, feature(untagged_unions))] | ||
| #[cfg(feature="serde-1")] | ||
| #[cfg(feature="serde")] | ||
| extern crate serde; | ||
@@ -33,13 +32,7 @@ | ||
| #[cfg(not(has_manually_drop_in_union))] | ||
| extern crate nodrop; | ||
| use std::cmp; | ||
| use std::iter; | ||
| use std::mem; | ||
| use std::ops::{Bound, Deref, DerefMut, RangeBounds}; | ||
| use std::ptr; | ||
| use std::ops::{ | ||
| Deref, | ||
| DerefMut, | ||
| }; | ||
| use std::slice; | ||
@@ -56,14 +49,6 @@ | ||
| #[cfg(has_stable_maybe_uninit)] | ||
| #[path="maybe_uninit_stable.rs"] | ||
| mod maybe_uninit; | ||
| #[cfg(all(not(has_stable_maybe_uninit), has_manually_drop_in_union))] | ||
| mod maybe_uninit; | ||
| #[cfg(all(not(has_stable_maybe_uninit), not(has_manually_drop_in_union)))] | ||
| #[path="maybe_uninit_nodrop.rs"] | ||
| mod maybe_uninit; | ||
| use crate::maybe_uninit::MaybeUninit; | ||
| use maybe_uninit::MaybeUninit; | ||
| #[cfg(feature="serde-1")] | ||
| #[cfg(feature="serde")] | ||
| use serde::{Serialize, Deserialize, Serializer, Deserializer}; | ||
@@ -74,10 +59,8 @@ | ||
| mod char; | ||
| mod range; | ||
| mod errors; | ||
| pub use array::Array; | ||
| pub use range::RangeArgument; | ||
| use array::Index; | ||
| pub use array_string::ArrayString; | ||
| pub use errors::CapacityError; | ||
| pub use crate::array::Array; | ||
| use crate::array::Index; | ||
| pub use crate::array_string::ArrayString; | ||
| pub use crate::errors::CapacityError; | ||
@@ -160,3 +143,3 @@ | ||
| #[inline] | ||
| pub fn capacity(&self) -> usize { A::capacity() } | ||
| pub fn capacity(&self) -> usize { A::CAPACITY } | ||
@@ -175,2 +158,15 @@ /// Return if the `ArrayVec` is completely filled. | ||
| /// Returns the capacity left in the `ArrayVec`. | ||
| /// | ||
| /// ``` | ||
| /// use arrayvec::ArrayVec; | ||
| /// | ||
| /// let mut array = ArrayVec::from([1, 2, 3]); | ||
| /// array.pop(); | ||
| /// assert_eq!(array.remaining_capacity(), 1); | ||
| /// ``` | ||
| pub fn remaining_capacity(&self) -> usize { | ||
| self.capacity() - self.len() | ||
| } | ||
| /// Push `element` to the end of the vector. | ||
@@ -217,3 +213,3 @@ /// | ||
| pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError<A::Item>> { | ||
| if self.len() < A::capacity() { | ||
| if self.len() < A::CAPACITY { | ||
| unsafe { | ||
@@ -253,12 +249,7 @@ self.push_unchecked(element); | ||
| let len = self.len(); | ||
| debug_assert!(len < A::capacity()); | ||
| ptr::write(self.get_unchecked_ptr(len), element); | ||
| debug_assert!(len < A::CAPACITY); | ||
| ptr::write(self.get_unchecked_mut(len), element); | ||
| self.set_len(len + 1); | ||
| } | ||
| /// Get pointer to where element at `index` would be | ||
| unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut A::Item { | ||
| self.xs.ptr_mut().offset(index as isize) | ||
| } | ||
| /// Insert `element` at position `index`. | ||
@@ -321,3 +312,3 @@ /// | ||
| { | ||
| let p: *mut _ = self.get_unchecked_ptr(index); | ||
| let p: *mut _ = self.get_unchecked_mut(index); | ||
| // Shift everything over to make space. (Duplicating the | ||
@@ -351,3 +342,3 @@ // `index`th element into two consecutive places.) | ||
| if self.len() == 0 { | ||
| return None | ||
| return None; | ||
| } | ||
@@ -357,3 +348,3 @@ unsafe { | ||
| self.set_len(new_len); | ||
| Some(ptr::read(self.get_unchecked_ptr(new_len))) | ||
| Some(ptr::read(self.get_unchecked_mut(new_len))) | ||
| } | ||
@@ -475,4 +466,10 @@ } | ||
| /// ``` | ||
| pub fn truncate(&mut self, len: usize) { | ||
| while self.len() > len { self.pop(); } | ||
| pub fn truncate(&mut self, new_len: usize) { | ||
| unsafe { | ||
| if new_len < self.len() { | ||
| let tail: *mut [_] = &mut self[new_len..]; | ||
| self.len = Index::from(new_len); | ||
| ptr::drop_in_place(tail); | ||
| } | ||
| } | ||
| } | ||
@@ -482,3 +479,3 @@ | ||
| pub fn clear(&mut self) { | ||
| while let Some(_) = self.pop() { } | ||
| self.truncate(0) | ||
| } | ||
@@ -525,3 +522,3 @@ | ||
| /// | ||
| /// This method uses *debug assertions* to check that check that `length` is | ||
| /// This method uses *debug assertions* to check that `length` is | ||
| /// not greater than the capacity. | ||
@@ -534,2 +531,38 @@ #[inline] | ||
| /// Copy and appends all elements in a slice to the `ArrayVec`. | ||
| /// | ||
| /// ``` | ||
| /// use arrayvec::ArrayVec; | ||
| /// | ||
| /// let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); | ||
| /// vec.push(1); | ||
| /// vec.try_extend_from_slice(&[2, 3]).unwrap(); | ||
| /// assert_eq!(&vec[..], &[1, 2, 3]); | ||
| /// ``` | ||
| /// | ||
| /// # Errors | ||
| /// | ||
| /// This method will return an error if the capacity left (see | ||
| /// [`remaining_capacity`]) is smaller then the length of the provided | ||
| /// slice. | ||
| /// | ||
| /// [`remaining_capacity`]: #method.remaining_capacity | ||
| pub fn try_extend_from_slice(&mut self, other: &[A::Item]) -> Result<(), CapacityError> | ||
| where A::Item: Copy, | ||
| { | ||
| if self.remaining_capacity() < other.len() { | ||
| return Err(CapacityError::new(())); | ||
| } | ||
| let self_len = self.len(); | ||
| let other_len = other.len(); | ||
| unsafe { | ||
| let dst = self.xs.ptr_mut().offset(self_len as isize); | ||
| ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); | ||
| self.set_len(self_len + other_len); | ||
| } | ||
| Ok(()) | ||
| } | ||
| /// Create a draining iterator that removes the specified range in the vector | ||
@@ -553,7 +586,9 @@ /// and yields the removed items from start to end. The element range is | ||
| /// ``` | ||
| pub fn drain<R: RangeArgument>(&mut self, range: R) -> Drain<A> { | ||
| pub fn drain<R>(&mut self, range: R) -> Drain<A> | ||
| where R: RangeBounds<usize> | ||
| { | ||
| // 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 | ||
| // the source vector to make sure no uninitialized or moved-from elements | ||
| // are accessible at all if the Drain's destructor never gets to run. | ||
@@ -566,4 +601,18 @@ // | ||
| let len = self.len(); | ||
| let start = range.start().unwrap_or(0); | ||
| let end = range.end().unwrap_or(len); | ||
| let start = match range.start_bound() { | ||
| Bound::Unbounded => 0, | ||
| Bound::Included(&i) => i, | ||
| Bound::Excluded(&i) => i.saturating_add(1), | ||
| }; | ||
| let end = match range.end_bound() { | ||
| Bound::Excluded(&j) => j, | ||
| Bound::Included(&j) => j.saturating_add(1), | ||
| Bound::Unbounded => len, | ||
| }; | ||
| self.drain_range(start, end) | ||
| } | ||
| fn drain_range(&mut self, start: usize, end: usize) -> Drain<A> | ||
| { | ||
| let len = self.len(); | ||
| // bounds check happens here | ||
@@ -588,5 +637,2 @@ let range_slice: *const _ = &self[start..end]; | ||
| /// 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<A, Self> { | ||
@@ -652,3 +698,3 @@ if self.len() < self.capacity() { | ||
| fn from(array: A) -> Self { | ||
| ArrayVec { xs: MaybeUninit::from(array), len: Index::from(A::capacity()) } | ||
| ArrayVec { xs: MaybeUninit::from(array), len: Index::from(A::CAPACITY) } | ||
| } | ||
@@ -729,3 +775,3 @@ } | ||
| self.index = Index::from(index + 1); | ||
| Some(ptr::read(self.v.get_unchecked_ptr(index))) | ||
| Some(ptr::read(self.v.get_unchecked_mut(index))) | ||
| } | ||
@@ -750,3 +796,3 @@ } | ||
| self.v.set_len(new_len); | ||
| Some(ptr::read(self.v.get_unchecked_ptr(new_len))) | ||
| Some(ptr::read(self.v.get_unchecked_mut(new_len))) | ||
| } | ||
@@ -767,3 +813,3 @@ } | ||
| let elements = slice::from_raw_parts_mut( | ||
| self.v.get_unchecked_ptr(index), | ||
| self.v.get_unchecked_mut(index), | ||
| len - index); | ||
@@ -902,3 +948,4 @@ ptr::drop_in_place(elements); | ||
| let len = self.len(); | ||
| let mut ptr = self.as_mut_ptr().offset(len as isize); | ||
| let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); | ||
| let end_ptr = raw_ptr_add(ptr, take); | ||
| // Keep the length in a separate variable, write it back on scope | ||
@@ -909,12 +956,18 @@ // exit. To help the compiler with alias analysis and stuff. | ||
| let mut guard = ScopeExitGuard { | ||
| value: self, | ||
| value: &mut self.len, | ||
| data: len, | ||
| f: |&len, self_| { | ||
| self_.set_len(len) | ||
| f: move |&len, self_len| { | ||
| **self_len = Index::from(len); | ||
| } | ||
| }; | ||
| for elt in iter.into_iter().take(take) { | ||
| ptr::write(ptr, elt); | ||
| ptr = ptr.offset(1); | ||
| guard.data += 1; | ||
| let mut iter = iter.into_iter(); | ||
| loop { | ||
| if ptr == end_ptr { break; } | ||
| if let Some(elt) = iter.next() { | ||
| raw_ptr_write(ptr, elt); | ||
| ptr = raw_ptr_add(ptr, 1); | ||
| guard.data += 1; | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
@@ -925,2 +978,20 @@ } | ||
| /// Rawptr add but uses arithmetic distance for ZST | ||
| unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T { | ||
| if mem::size_of::<T>() == 0 { | ||
| // Special case for ZST | ||
| (ptr as usize).wrapping_add(offset) as _ | ||
| } else { | ||
| ptr.offset(offset as isize) | ||
| } | ||
| } | ||
| unsafe fn raw_ptr_write<T>(ptr: *mut T, value: T) { | ||
| if mem::size_of::<T>() == 0 { | ||
| /* nothing */ | ||
| } else { | ||
| ptr::write(ptr, value) | ||
| } | ||
| } | ||
| /// Create an `ArrayVec` from an iterator. | ||
@@ -1054,9 +1125,6 @@ /// | ||
| fn write(&mut self, data: &[u8]) -> io::Result<usize> { | ||
| unsafe { | ||
| let len = self.len(); | ||
| let write_len = cmp::min(A::capacity() - len, data.len()); | ||
| ptr::copy_nonoverlapping(data.as_ptr(), self.get_unchecked_ptr(len), write_len); | ||
| self.set_len(len + write_len); | ||
| Ok(write_len) | ||
| } | ||
| let len = cmp::min(self.remaining_capacity(), data.len()); | ||
| let _result = self.try_extend_from_slice(&data[..len]); | ||
| debug_assert!(_result.is_ok()); | ||
| Ok(len) | ||
| } | ||
@@ -1066,4 +1134,4 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) } | ||
| #[cfg(feature="serde-1")] | ||
| /// Requires crate feature `"serde-1"` | ||
| #[cfg(feature="serde")] | ||
| /// Requires crate feature `"serde"` | ||
| impl<T: Serialize, A: Array<Item=T>> Serialize for ArrayVec<A> { | ||
@@ -1077,4 +1145,4 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
| #[cfg(feature="serde-1")] | ||
| /// Requires crate feature `"serde-1"` | ||
| #[cfg(feature="serde")] | ||
| /// Requires crate feature `"serde"` | ||
| impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A> { | ||
@@ -1093,3 +1161,3 @@ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
| fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | ||
| write!(formatter, "an array with no more than {} items", A::capacity()) | ||
| write!(formatter, "an array with no more than {} items", A::CAPACITY) | ||
| } | ||
@@ -1102,5 +1170,5 @@ | ||
| while let Some(value) = try!(seq.next_element()) { | ||
| while let Some(value) = seq.next_element()? { | ||
| 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)); | ||
| } | ||
@@ -1107,0 +1175,0 @@ } |
+15
-17
| use array::Array; | ||
| use std::mem::ManuallyDrop; | ||
| use crate::array::Array; | ||
| use std::mem::MaybeUninit as StdMaybeUninit; | ||
| /// A combination of ManuallyDrop and “maybe uninitialized”; | ||
| /// this wraps a value that can be wholly or partially uninitialized; | ||
| /// it also has no drop regardless of the type of T. | ||
| #[repr(C)] // for cast from self ptr to value | ||
| pub union MaybeUninit<T> { | ||
| empty: (), | ||
| value: ManuallyDrop<T>, | ||
| #[derive(Copy)] | ||
| pub struct MaybeUninit<T> { | ||
| inner: StdMaybeUninit<T>, | ||
| } | ||
| // Why we don't use std's MaybeUninit on nightly? See the ptr method | ||
| impl<T> Clone for MaybeUninit<T> | ||
| where T: Copy | ||
| { | ||
| fn clone(&self) -> Self { *self } | ||
| } | ||
| impl<T> MaybeUninit<T> { | ||
| /// Create a new MaybeUninit with uninitialized interior | ||
| pub unsafe fn uninitialized() -> Self { | ||
| MaybeUninit { empty: () } | ||
| MaybeUninit { inner: StdMaybeUninit::uninit() } | ||
| } | ||
@@ -24,3 +25,3 @@ | ||
| pub fn from(v: T) -> Self { | ||
| MaybeUninit { value: ManuallyDrop::new(v) } | ||
| MaybeUninit { inner: StdMaybeUninit::new(v) } | ||
| } | ||
@@ -35,6 +36,3 @@ | ||
| { | ||
| // std MaybeUninit creates a &self.value reference here which is | ||
| // not guaranteed to be sound in our case - we will partially | ||
| // initialize the value, not always wholly. | ||
| self as *const _ as *const T::Item | ||
| self.inner.as_ptr() as *const T::Item | ||
| } | ||
@@ -46,4 +44,4 @@ | ||
| { | ||
| self as *mut _ as *mut T::Item | ||
| self.inner.as_mut_ptr() as *mut T::Item | ||
| } | ||
| } |
+1
-1
@@ -1,2 +0,2 @@ | ||
| #![cfg(feature = "serde-1")] | ||
| #![cfg(feature = "serde")] | ||
| extern crate arrayvec; | ||
@@ -3,0 +3,0 @@ extern crate serde_test; |
+171
-9
@@ -31,2 +31,40 @@ extern crate arrayvec; | ||
| #[test] | ||
| fn test_capacity_left() { | ||
| let mut vec: ArrayVec<[usize; 4]> = ArrayVec::new(); | ||
| assert_eq!(vec.remaining_capacity(), 4); | ||
| vec.push(1); | ||
| assert_eq!(vec.remaining_capacity(), 3); | ||
| vec.push(2); | ||
| assert_eq!(vec.remaining_capacity(), 2); | ||
| vec.push(3); | ||
| assert_eq!(vec.remaining_capacity(), 1); | ||
| vec.push(4); | ||
| assert_eq!(vec.remaining_capacity(), 0); | ||
| } | ||
| #[test] | ||
| fn test_extend_from_slice() { | ||
| let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); | ||
| vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); | ||
| assert_eq!(vec.len(), 3); | ||
| assert_eq!(&vec[..], &[1, 2, 3]); | ||
| assert_eq!(vec.pop(), Some(3)); | ||
| assert_eq!(&vec[..], &[1, 2]); | ||
| } | ||
| #[test] | ||
| fn test_extend_from_slice_error() { | ||
| let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); | ||
| vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); | ||
| let res = vec.try_extend_from_slice(&[0; 8]); | ||
| assert_matches!(res, Err(_)); | ||
| let mut vec: ArrayVec<[usize; 0]> = ArrayVec::new(); | ||
| let res = vec.try_extend_from_slice(&[0; 1]); | ||
| assert_matches!(res, Err(_)); | ||
| } | ||
| #[test] | ||
| fn test_u16_index() { | ||
@@ -131,2 +169,76 @@ const N: usize = 4096; | ||
| #[test] | ||
| fn test_drop_panics() { | ||
| use std::cell::Cell; | ||
| use std::panic::catch_unwind; | ||
| use std::panic::AssertUnwindSafe; | ||
| let flag = &Cell::new(0); | ||
| struct Bump<'a>(&'a Cell<i32>); | ||
| // Panic in the first drop | ||
| impl<'a> Drop for Bump<'a> { | ||
| fn drop(&mut self) { | ||
| let n = self.0.get(); | ||
| self.0.set(n + 1); | ||
| if n == 0 { | ||
| panic!("Panic in Bump's drop"); | ||
| } | ||
| } | ||
| } | ||
| // check if rust is new enough | ||
| flag.set(0); | ||
| { | ||
| let array = vec![Bump(flag), Bump(flag)]; | ||
| let res = catch_unwind(AssertUnwindSafe(|| { | ||
| drop(array); | ||
| })); | ||
| assert!(res.is_err()); | ||
| } | ||
| if flag.get() != 2 { | ||
| println!("test_drop_panics: skip, this version of Rust doesn't continue in drop_in_place"); | ||
| return; | ||
| } | ||
| flag.set(0); | ||
| { | ||
| let mut array = ArrayVec::<[Bump; 128]>::new(); | ||
| array.push(Bump(flag)); | ||
| array.push(Bump(flag)); | ||
| array.push(Bump(flag)); | ||
| let res = catch_unwind(AssertUnwindSafe(|| { | ||
| drop(array); | ||
| })); | ||
| assert!(res.is_err()); | ||
| } | ||
| // Check that all the elements drop, even if the first drop panics. | ||
| assert_eq!(flag.get(), 3); | ||
| flag.set(0); | ||
| { | ||
| let mut array = ArrayVec::<[Bump; 16]>::new(); | ||
| array.push(Bump(flag)); | ||
| array.push(Bump(flag)); | ||
| array.push(Bump(flag)); | ||
| array.push(Bump(flag)); | ||
| array.push(Bump(flag)); | ||
| let i = 2; | ||
| let tail_len = array.len() - i; | ||
| let res = catch_unwind(AssertUnwindSafe(|| { | ||
| array.truncate(i); | ||
| })); | ||
| assert!(res.is_err()); | ||
| // Check that all the tail elements drop, even if the first drop panics. | ||
| assert_eq!(flag.get(), tail_len as i32); | ||
| } | ||
| } | ||
| #[test] | ||
| fn test_extend() { | ||
@@ -151,4 +263,4 @@ let mut range = 0..10; | ||
| let data = ArrayVec::<[Vec<i32>; 5]>::new(); | ||
| &data as &Send; | ||
| &data as &Sync; | ||
| &data as &dyn Send; | ||
| &data as &dyn Sync; | ||
| } | ||
@@ -164,2 +276,7 @@ | ||
| // 1 enum tag + 1 drop flag | ||
| type EmptyArray = ArrayVec<[u8; 0]>; | ||
| println!("{}", mem::size_of::<EmptyArray>()); | ||
| assert!(mem::size_of::<EmptyArray>() <= 2); | ||
| // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding | ||
@@ -197,2 +314,25 @@ type QuadArray = ArrayVec<[u32; 3]>; | ||
| #[test] | ||
| fn test_drain_range_inclusive() { | ||
| let mut v = ArrayVec::from([0; 8]); | ||
| v.drain(0..=7); | ||
| assert_eq!(&v[..], &[]); | ||
| v.extend(0..); | ||
| v.drain(1..=4); | ||
| assert_eq!(&v[..], &[0, 5, 6, 7]); | ||
| let u: ArrayVec<[_; 3]> = v.drain(1..=2).rev().collect(); | ||
| assert_eq!(&u[..], &[6, 5]); | ||
| assert_eq!(&v[..], &[0, 7]); | ||
| v.drain(..); | ||
| assert_eq!(&v[..], &[]); | ||
| } | ||
| #[test] | ||
| #[should_panic] | ||
| fn test_drain_range_inclusive_oob() { | ||
| let mut v = ArrayVec::from([0; 0]); | ||
| v.drain(0..=0); | ||
| } | ||
| #[test] | ||
| fn test_retain() { | ||
@@ -302,2 +442,3 @@ let mut v = ArrayVec::from([0; 8]); | ||
| #[cfg(feature="std")] | ||
| #[test] | ||
@@ -337,2 +478,3 @@ fn test_write() { | ||
| #[cfg(feature="std")] | ||
| #[test] | ||
@@ -363,5 +505,5 @@ fn test_string() { | ||
| // Test Error trait / try | ||
| let t = || -> Result<(), Box<Error>> { | ||
| let t = || -> Result<(), Box<dyn Error>> { | ||
| let mut t = ArrayString::<[_; 2]>::new(); | ||
| try!(t.try_push_str(text)); | ||
| t.try_push_str(text)?; | ||
| Ok(()) | ||
@@ -382,2 +524,10 @@ }(); | ||
| #[test] | ||
| fn test_string_parse_from_str() { | ||
| let text = "hello world"; | ||
| let u: ArrayString<[_; 11]> = text.parse().unwrap(); | ||
| assert_eq!(&u, text); | ||
| assert_eq!(u.len(), text.len()); | ||
| } | ||
| #[test] | ||
| fn test_string_from_bytes() { | ||
@@ -520,8 +670,20 @@ let text = "hello world"; | ||
| #[test] | ||
| fn test_extend_zst() { | ||
| let mut range = 0..10; | ||
| #[derive(Copy, Clone, PartialEq, Debug)] | ||
| struct Z; // Zero sized type | ||
| #[test] | ||
| fn test_newish_stable_uses_maybe_uninit() { | ||
| if option_env!("ARRAYVECTEST_ENSURE_MAYBEUNINIT").map(|s| !s.is_empty()).unwrap_or(false) { | ||
| assert!(cfg!(has_stable_maybe_uninit)); | ||
| } | ||
| let mut array: ArrayVec<[_; 5]> = range.by_ref().map(|_| Z).collect(); | ||
| assert_eq!(&array[..], &[Z; 5]); | ||
| assert_eq!(range.next(), Some(5)); | ||
| array.extend(range.by_ref().map(|_| Z)); | ||
| assert_eq!(range.next(), Some(6)); | ||
| let mut array: ArrayVec<[_; 10]> = (0..3).map(|_| Z).collect(); | ||
| assert_eq!(&array[..], &[Z; 3]); | ||
| array.extend((3..5).map(|_| Z)); | ||
| assert_eq!(&array[..], &[Z; 5]); | ||
| assert_eq!(array.len(), 5); | ||
| } |
-90
| use std::env; | ||
| use std::io::Write; | ||
| use std::process::{Command, Stdio}; | ||
| fn main() { | ||
| // we need to output *some* file to opt out of the default | ||
| println!("cargo:rerun-if-changed=build.rs"); | ||
| detect_maybe_uninit(); | ||
| } | ||
| fn detect_maybe_uninit() { | ||
| let has_stable_maybe_uninit = probe(&stable_maybe_uninit()); | ||
| if has_stable_maybe_uninit { | ||
| println!("cargo:rustc-cfg=has_stable_maybe_uninit"); | ||
| return; | ||
| } | ||
| let has_unstable_union_with_md = probe(&maybe_uninit_code(true)); | ||
| if has_unstable_union_with_md { | ||
| println!("cargo:rustc-cfg=has_manually_drop_in_union"); | ||
| println!("cargo:rustc-cfg=has_union_feature"); | ||
| } | ||
| } | ||
| // To guard against changes in this currently unstable feature, use | ||
| // a detection tests instead of a Rustc version and/or date test. | ||
| fn stable_maybe_uninit() -> String { | ||
| let code = " | ||
| #![allow(warnings)] | ||
| use std::mem::MaybeUninit; | ||
| fn main() { } | ||
| "; | ||
| code.to_string() | ||
| } | ||
| // To guard against changes in this currently unstable feature, use | ||
| // a detection tests instead of a Rustc version and/or date test. | ||
| fn maybe_uninit_code(use_feature: bool) -> String { | ||
| let feature = if use_feature { "#![feature(untagged_unions)]" } else { "" }; | ||
| let code = " | ||
| #![allow(warnings)] | ||
| use std::mem::ManuallyDrop; | ||
| #[derive(Copy)] | ||
| pub union MaybeUninit<T> { | ||
| empty: (), | ||
| value: ManuallyDrop<T>, | ||
| } | ||
| impl<T> Clone for MaybeUninit<T> where T: Copy | ||
| { | ||
| fn clone(&self) -> Self { *self } | ||
| } | ||
| fn main() { | ||
| let value1 = MaybeUninit::<[i32; 3]> { empty: () }; | ||
| let value2 = MaybeUninit { value: ManuallyDrop::new([1, 2, 3]) }; | ||
| } | ||
| "; | ||
| [feature, code].concat() | ||
| } | ||
| /// Test if a code snippet can be compiled | ||
| fn probe(code: &str) -> bool { | ||
| let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); | ||
| let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR"); | ||
| let mut child = Command::new(rustc) | ||
| .arg("--out-dir") | ||
| .arg(out_dir) | ||
| .arg("--emit=obj") | ||
| .arg("-") | ||
| .stdin(Stdio::piped()) | ||
| .spawn() | ||
| .expect("rustc probe"); | ||
| child | ||
| .stdin | ||
| .as_mut() | ||
| .expect("rustc stdin") | ||
| .write_all(code.as_bytes()) | ||
| .expect("write rustc stdin"); | ||
| child.wait().expect("rustc probe").success() | ||
| } |
| use array::Array; | ||
| use nodrop::NoDrop; | ||
| use std::mem::uninitialized; | ||
| /// A combination of NoDrop and “maybe uninitialized”; | ||
| /// this wraps a value that can be wholly or partially uninitialized. | ||
| /// | ||
| /// NOTE: This is known to not be a good solution, but it's the one we have kept | ||
| /// working on stable Rust. Stable improvements are encouraged, in any form, | ||
| /// but of course we are waiting for a real, stable, MaybeUninit. | ||
| pub struct MaybeUninit<T>(NoDrop<T>); | ||
| // why don't we use ManuallyDrop here: It doesn't inhibit | ||
| // enum layout optimizations that depend on T, and we support older Rust. | ||
| impl<T> MaybeUninit<T> { | ||
| /// Create a new MaybeUninit with uninitialized interior | ||
| pub unsafe fn uninitialized() -> Self { | ||
| Self::from(uninitialized()) | ||
| } | ||
| /// Create a new MaybeUninit from the value `v`. | ||
| pub fn from(v: T) -> Self { | ||
| MaybeUninit(NoDrop::new(v)) | ||
| } | ||
| /// Return a raw pointer to the start of the interior array | ||
| pub fn ptr(&self) -> *const T::Item | ||
| where T: Array | ||
| { | ||
| &*self.0 as *const T as *const _ | ||
| } | ||
| /// Return a mut raw pointer to the start of the interior array | ||
| pub fn ptr_mut(&mut self) -> *mut T::Item | ||
| where T: Array | ||
| { | ||
| &mut *self.0 as *mut T as *mut _ | ||
| } | ||
| } | ||
| use array::Array; | ||
| use std::mem::MaybeUninit as StdMaybeUninit; | ||
| pub struct MaybeUninit<T> { | ||
| inner: StdMaybeUninit<T>, | ||
| } | ||
| impl<T> MaybeUninit<T> { | ||
| /// Create a new MaybeUninit with uninitialized interior | ||
| pub unsafe fn uninitialized() -> Self { | ||
| MaybeUninit { inner: StdMaybeUninit::uninit() } | ||
| } | ||
| /// Create a new MaybeUninit from the value `v`. | ||
| pub fn from(v: T) -> Self { | ||
| MaybeUninit { inner: StdMaybeUninit::new(v) } | ||
| } | ||
| // Raw pointer casts written so that we don't reference or access the | ||
| // uninitialized interior value | ||
| /// Return a raw pointer to the start of the interior array | ||
| pub fn ptr(&self) -> *const T::Item | ||
| where T: Array | ||
| { | ||
| // std MaybeUninit creates a &self.value reference here which is | ||
| // not guaranteed to be sound in our case - we will partially | ||
| // initialize the value, not always wholly. | ||
| self.inner.as_ptr() as *const T::Item | ||
| } | ||
| /// Return a mut raw pointer to the start of the interior array | ||
| pub fn ptr_mut(&mut self) -> *mut T::Item | ||
| where T: Array | ||
| { | ||
| self.inner.as_mut_ptr() as *mut T::Item | ||
| } | ||
| } |
-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) } | ||
| } | ||
Sorry, the diff of this file is not supported yet