aboutsummaryrefslogtreecommitdiff
path: root/src/arrayvec.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/arrayvec.rs')
-rw-r--r--src/arrayvec.rs145
1 files changed, 134 insertions, 11 deletions
diff --git a/src/arrayvec.rs b/src/arrayvec.rs
index 55e67db..ba351c1 100644
--- a/src/arrayvec.rs
+++ b/src/arrayvec.rs
@@ -1,5 +1,5 @@
use super::*;
-use core::convert::TryInto;
+use core::convert::{TryFrom, TryInto};
#[cfg(feature = "serde")]
use core::marker::PhantomData;
@@ -96,10 +96,13 @@ macro_rules! array_vec {
///
/// let more_ints = ArrayVec::from_array_len([5, 6, 7, 8], 2);
/// assert_eq!(more_ints.len(), 2);
+///
+/// let no_ints: ArrayVec<[u8; 5]> = ArrayVec::from_array_empty([1, 2, 3, 4, 5]);
+/// assert_eq!(no_ints.len(), 0);
/// ```
#[repr(C)]
#[derive(Clone, Copy)]
-pub struct ArrayVec<A: Array> {
+pub struct ArrayVec<A> {
len: u16,
pub(crate) data: A,
}
@@ -954,6 +957,37 @@ impl<A: Array> ArrayVec<A> {
}
}
+impl<A> ArrayVec<A> {
+ /// Wraps up an array as a new empty `ArrayVec`.
+ ///
+ /// If you want to simply use the full array, use `from` instead.
+ ///
+ /// ## Examples
+ ///
+ /// This method in particular allows to create values for statics:
+ ///
+ /// ```rust
+ /// # use tinyvec::ArrayVec;
+ /// static DATA: ArrayVec<[u8; 5]> = ArrayVec::from_array_empty([0; 5]);
+ /// assert_eq!(DATA.len(), 0);
+ /// ```
+ ///
+ /// But of course it is just an normal empty `ArrayVec`:
+ ///
+ /// ```rust
+ /// # use tinyvec::ArrayVec;
+ /// let mut data = ArrayVec::from_array_empty([1, 2, 3, 4]);
+ /// assert_eq!(&data[..], &[]);
+ /// data.push(42);
+ /// assert_eq!(&data[..], &[42]);
+ /// ```
+ #[inline]
+ #[must_use]
+ pub const fn from_array_empty(data: A) -> Self {
+ Self { data, len: 0 }
+ }
+}
+
#[cfg(feature = "grab_spare_slice")]
impl<A: Array> ArrayVec<A> {
/// Obtain the shared slice of the array _after_ the active memory.
@@ -1190,6 +1224,41 @@ impl<A: Array> From<A> for ArrayVec<A> {
}
}
+/// The error type returned when a conversion from a slice to an [`ArrayVec`]
+/// fails.
+#[derive(Debug, Copy, Clone)]
+pub struct TryFromSliceError(());
+
+impl<T, A> TryFrom<&'_ [T]> for ArrayVec<A>
+where
+ T: Clone + Default,
+ A: Array<Item = T>,
+{
+ type Error = TryFromSliceError;
+
+ #[inline]
+ #[must_use]
+ /// The output has a length equal to that of the slice, with the same capacity
+ /// as `A`.
+ fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
+ if slice.len() > A::CAPACITY {
+ Err(TryFromSliceError(()))
+ } else {
+ let mut arr = ArrayVec::new();
+ // We do not use ArrayVec::extend_from_slice, because it looks like LLVM
+ // fails to deduplicate all the length-checking logic between the
+ // above if and the contents of that method, thus producing much
+ // slower code. Unlike many of the other optimizations in this
+ // crate, this one is worth keeping an eye on. I see no reason, for
+ // any element type, that these should produce different code. But
+ // they do. (rustc 1.51.0)
+ arr.set_len(slice.len());
+ arr.as_mut_slice().clone_from_slice(slice);
+ Ok(arr)
+ }
+ }
+}
+
impl<A: Array> FromIterator<A::Item> for ArrayVec<A> {
#[inline]
#[must_use]
@@ -1420,12 +1489,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
Binary::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1437,12 +1512,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
Debug::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1454,12 +1535,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
Display::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1471,12 +1558,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
LowerExp::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1488,12 +1581,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
LowerHex::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1505,12 +1604,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
Octal::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1522,12 +1627,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
Pointer::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1539,12 +1650,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
UpperExp::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}
@@ -1556,12 +1673,18 @@ where
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "[")?;
+ if f.alternate() {
+ write!(f, "\n ")?;
+ }
for (i, elem) in self.iter().enumerate() {
if i > 0 {
- write!(f, ", ")?;
+ write!(f, ",{}", if f.alternate() { "\n " } else { " " })?;
}
UpperHex::fmt(elem, f)?;
}
+ if f.alternate() {
+ write!(f, ",\n")?;
+ }
write!(f, "]")
}
}