From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/tinyvec/src/tinyvec.rs | 1740 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1740 insertions(+) create mode 100644 vendor/tinyvec/src/tinyvec.rs (limited to 'vendor/tinyvec/src/tinyvec.rs') diff --git a/vendor/tinyvec/src/tinyvec.rs b/vendor/tinyvec/src/tinyvec.rs new file mode 100644 index 000000000..a5e1c1551 --- /dev/null +++ b/vendor/tinyvec/src/tinyvec.rs @@ -0,0 +1,1740 @@ +#![cfg(feature = "alloc")] + +use super::*; + +use alloc::vec::{self, Vec}; +use core::convert::TryFrom; +use tinyvec_macros::impl_mirrored; + +#[cfg(feature = "rustc_1_57")] +use alloc::collections::TryReserveError; + +#[cfg(feature = "serde")] +use core::marker::PhantomData; +#[cfg(feature = "serde")] +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +#[cfg(feature = "serde")] +use serde::ser::{Serialize, SerializeSeq, Serializer}; + +/// Helper to make a `TinyVec`. +/// +/// You specify the backing array type, and optionally give all the elements you +/// want to initially place into the array. +/// +/// ```rust +/// use tinyvec::*; +/// +/// // The backing array type can be specified in the macro call +/// let empty_tv = tiny_vec!([u8; 16]); +/// let some_ints = tiny_vec!([i32; 4] => 1, 2, 3); +/// let many_ints = tiny_vec!([i32; 4] => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +/// +/// // Or left to inference +/// let empty_tv: TinyVec<[u8; 16]> = tiny_vec!(); +/// let some_ints: TinyVec<[i32; 4]> = tiny_vec!(1, 2, 3); +/// let many_ints: TinyVec<[i32; 4]> = tiny_vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +/// ``` +#[macro_export] +#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))] +macro_rules! tiny_vec { + ($array_type:ty => $($elem:expr),* $(,)?) => { + { + // https://github.com/rust-lang/lang-team/issues/28 + const INVOKED_ELEM_COUNT: usize = 0 $( + { let _ = stringify!($elem); 1 })*; + // If we have more `$elem` than the `CAPACITY` we will simply go directly + // to constructing on the heap. + match $crate::TinyVec::constructor_for_capacity(INVOKED_ELEM_COUNT) { + $crate::TinyVecConstructor::Inline(f) => { + f($crate::array_vec!($array_type => $($elem),*)) + } + $crate::TinyVecConstructor::Heap(f) => { + f(vec!($($elem),*)) + } + } + } + }; + ($array_type:ty) => { + $crate::TinyVec::<$array_type>::default() + }; + ($($elem:expr),*) => { + $crate::tiny_vec!(_ => $($elem),*) + }; + ($elem:expr; $n:expr) => { + $crate::TinyVec::from([$elem; $n]) + }; + () => { + $crate::tiny_vec!(_) + }; +} + +#[doc(hidden)] // Internal implementation details of `tiny_vec!` +pub enum TinyVecConstructor { + Inline(fn(ArrayVec) -> TinyVec), + Heap(fn(Vec) -> TinyVec), +} + +/// A vector that starts inline, but can automatically move to the heap. +/// +/// * Requires the `alloc` feature +/// +/// A `TinyVec` is either an Inline([`ArrayVec`](crate::ArrayVec::)) or +/// Heap([`Vec`](https://doc.rust-lang.org/alloc/vec/struct.Vec.html)). The +/// interface for the type as a whole is a bunch of methods that just match on +/// the enum variant and then call the same method on the inner vec. +/// +/// ## Construction +/// +/// Because it's an enum, you can construct a `TinyVec` simply by making an +/// `ArrayVec` or `Vec` and then putting it into the enum. +/// +/// There is also a macro +/// +/// ```rust +/// # use tinyvec::*; +/// let empty_tv = tiny_vec!([u8; 16]); +/// let some_ints = tiny_vec!([i32; 4] => 1, 2, 3); +/// ``` +#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))] +pub enum TinyVec { + #[allow(missing_docs)] + Inline(ArrayVec), + #[allow(missing_docs)] + Heap(Vec), +} + +impl Clone for TinyVec +where + A: Array + Clone, + A::Item: Clone, +{ + #[inline] + fn clone(&self) -> Self { + match self { + TinyVec::Heap(v) => TinyVec::Heap(v.clone()), + TinyVec::Inline(v) => TinyVec::Inline(v.clone()), + } + } + + #[inline] + fn clone_from(&mut self, o: &Self) { + if o.len() > self.len() { + self.reserve(o.len() - self.len()); + } else { + self.truncate(o.len()); + } + let (start, end) = o.split_at(self.len()); + for (dst, src) in self.iter_mut().zip(start) { + dst.clone_from(src); + } + self.extend_from_slice(end); + } +} + +impl Default for TinyVec { + #[inline] + #[must_use] + fn default() -> Self { + TinyVec::Inline(ArrayVec::default()) + } +} + +impl Deref for TinyVec { + type Target = [A::Item]; + + impl_mirrored! { + type Mirror = TinyVec; + #[inline(always)] + #[must_use] + fn deref(self: &Self) -> &Self::Target; + } +} + +impl DerefMut for TinyVec { + impl_mirrored! { + type Mirror = TinyVec; + #[inline(always)] + #[must_use] + fn deref_mut(self: &mut Self) -> &mut Self::Target; + } +} + +impl> Index for TinyVec { + type Output = >::Output; + #[inline(always)] + #[must_use] + fn index(&self, index: I) -> &Self::Output { + &self.deref()[index] + } +} + +impl> IndexMut for TinyVec { + #[inline(always)] + #[must_use] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + &mut self.deref_mut()[index] + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docs_rs, doc(cfg(feature = "std")))] +impl> std::io::Write for TinyVec { + #[inline(always)] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline(always)] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docs_rs, doc(cfg(feature = "serde")))] +impl Serialize for TinyVec +where + A::Item: Serialize, +{ + #[must_use] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.len()))?; + for element in self.iter() { + seq.serialize_element(element)?; + } + seq.end() + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docs_rs, doc(cfg(feature = "serde")))] +impl<'de, A: Array> Deserialize<'de> for TinyVec +where + A::Item: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_seq(TinyVecVisitor(PhantomData)) + } +} + +#[cfg(feature = "arbitrary")] +#[cfg_attr(docs_rs, doc(cfg(feature = "arbitrary")))] +impl<'a, A> arbitrary::Arbitrary<'a> for TinyVec +where + A: Array, + A::Item: arbitrary::Arbitrary<'a>, +{ + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + let v = Vec::arbitrary(u)?; + let mut tv = TinyVec::Heap(v); + tv.shrink_to_fit(); + Ok(tv) + } +} + +impl TinyVec { + /// Returns whether elements are on heap + #[inline(always)] + #[must_use] + pub fn is_heap(&self) -> bool { + match self { + TinyVec::Heap(_) => true, + TinyVec::Inline(_) => false, + } + } + /// Returns whether elements are on stack + #[inline(always)] + #[must_use] + pub fn is_inline(&self) -> bool { + !self.is_heap() + } + + /// Shrinks the capacity of the vector as much as possible.\ + /// It is inlined if length is less than `A::CAPACITY`. + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 2] => 1, 2, 3); + /// assert!(tv.is_heap()); + /// let _ = tv.pop(); + /// assert!(tv.is_heap()); + /// tv.shrink_to_fit(); + /// assert!(tv.is_inline()); + /// ``` + pub fn shrink_to_fit(&mut self) { + let vec = match self { + TinyVec::Inline(_) => return, + TinyVec::Heap(h) => h, + }; + + if vec.len() > A::CAPACITY { + return vec.shrink_to_fit(); + } + + let moved_vec = core::mem::replace(vec, Vec::new()); + + let mut av = ArrayVec::default(); + let mut rest = av.fill(moved_vec); + debug_assert!(rest.next().is_none()); + *self = TinyVec::Inline(av); + } + + /// Moves the content of the TinyVec to the heap, if it's inline. + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// assert!(tv.is_inline()); + /// tv.move_to_the_heap(); + /// assert!(tv.is_heap()); + /// ``` + #[allow(clippy::missing_inline_in_public_items)] + pub fn move_to_the_heap(&mut self) { + let arr = match self { + TinyVec::Heap(_) => return, + TinyVec::Inline(a) => a, + }; + + let v = arr.drain_to_vec(); + *self = TinyVec::Heap(v); + } + + /// Tries to move the content of the TinyVec to the heap, if it's inline. + /// + /// # Errors + /// + /// If the allocator reports a failure, then an error is returned and the + /// content is kept on the stack. + /// + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// assert!(tv.is_inline()); + /// assert_eq!(Ok(()), tv.try_move_to_the_heap()); + /// assert!(tv.is_heap()); + /// ``` + #[cfg(feature = "rustc_1_57")] + pub fn try_move_to_the_heap(&mut self) -> Result<(), TryReserveError> { + let arr = match self { + TinyVec::Heap(_) => return Ok(()), + TinyVec::Inline(a) => a, + }; + + let v = arr.try_drain_to_vec()?; + *self = TinyVec::Heap(v); + return Ok(()); + } + + /// If TinyVec is inline, moves the content of it to the heap. + /// Also reserves additional space. + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// assert!(tv.is_inline()); + /// tv.move_to_the_heap_and_reserve(32); + /// assert!(tv.is_heap()); + /// assert!(tv.capacity() >= 35); + /// ``` + pub fn move_to_the_heap_and_reserve(&mut self, n: usize) { + let arr = match self { + TinyVec::Heap(h) => return h.reserve(n), + TinyVec::Inline(a) => a, + }; + + let v = arr.drain_to_vec_and_reserve(n); + *self = TinyVec::Heap(v); + } + + /// If TinyVec is inline, try to move the content of it to the heap. + /// Also reserves additional space. + /// + /// # Errors + /// + /// If the allocator reports a failure, then an error is returned. + /// + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// assert!(tv.is_inline()); + /// assert_eq!(Ok(()), tv.try_move_to_the_heap_and_reserve(32)); + /// assert!(tv.is_heap()); + /// assert!(tv.capacity() >= 35); + /// ``` + #[cfg(feature = "rustc_1_57")] + pub fn try_move_to_the_heap_and_reserve( + &mut self, n: usize, + ) -> Result<(), TryReserveError> { + let arr = match self { + TinyVec::Heap(h) => return h.try_reserve(n), + TinyVec::Inline(a) => a, + }; + + let v = arr.try_drain_to_vec_and_reserve(n)?; + *self = TinyVec::Heap(v); + return Ok(()); + } + + /// Reserves additional space. + /// Moves to the heap if array can't hold `n` more items + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3, 4); + /// assert!(tv.is_inline()); + /// tv.reserve(1); + /// assert!(tv.is_heap()); + /// assert!(tv.capacity() >= 5); + /// ``` + pub fn reserve(&mut self, n: usize) { + let arr = match self { + TinyVec::Heap(h) => return h.reserve(n), + TinyVec::Inline(a) => a, + }; + + if n > arr.capacity() - arr.len() { + let v = arr.drain_to_vec_and_reserve(n); + *self = TinyVec::Heap(v); + } + + /* In this place array has enough place, so no work is needed more */ + return; + } + + /// Tries to reserve additional space. + /// Moves to the heap if array can't hold `n` more items. + /// + /// # Errors + /// + /// If the allocator reports a failure, then an error is returned. + /// + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3, 4); + /// assert!(tv.is_inline()); + /// assert_eq!(Ok(()), tv.try_reserve(1)); + /// assert!(tv.is_heap()); + /// assert!(tv.capacity() >= 5); + /// ``` + #[cfg(feature = "rustc_1_57")] + pub fn try_reserve(&mut self, n: usize) -> Result<(), TryReserveError> { + let arr = match self { + TinyVec::Heap(h) => return h.try_reserve(n), + TinyVec::Inline(a) => a, + }; + + if n > arr.capacity() - arr.len() { + let v = arr.try_drain_to_vec_and_reserve(n)?; + *self = TinyVec::Heap(v); + } + + /* In this place array has enough place, so no work is needed more */ + return Ok(()); + } + + /// Reserves additional space. + /// Moves to the heap if array can't hold `n` more items + /// + /// From [Vec::reserve_exact](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve_exact) + /// ```text + /// Note that the allocator may give the collection more space than it requests. + /// Therefore, capacity can not be relied upon to be precisely minimal. + /// Prefer `reserve` if future insertions are expected. + /// ``` + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3, 4); + /// assert!(tv.is_inline()); + /// tv.reserve_exact(1); + /// assert!(tv.is_heap()); + /// assert!(tv.capacity() >= 5); + /// ``` + pub fn reserve_exact(&mut self, n: usize) { + let arr = match self { + TinyVec::Heap(h) => return h.reserve_exact(n), + TinyVec::Inline(a) => a, + }; + + if n > arr.capacity() - arr.len() { + let v = arr.drain_to_vec_and_reserve(n); + *self = TinyVec::Heap(v); + } + + /* In this place array has enough place, so no work is needed more */ + return; + } + + /// Tries to reserve additional space. + /// Moves to the heap if array can't hold `n` more items + /// + /// # Errors + /// + /// If the allocator reports a failure, then an error is returned. + /// + /// From [Vec::try_reserve_exact](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact) + /// ```text + /// Note that the allocator may give the collection more space than it requests. + /// Therefore, capacity can not be relied upon to be precisely minimal. + /// Prefer `reserve` if future insertions are expected. + /// ``` + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3, 4); + /// assert!(tv.is_inline()); + /// assert_eq!(Ok(()), tv.try_reserve_exact(1)); + /// assert!(tv.is_heap()); + /// assert!(tv.capacity() >= 5); + /// ``` + #[cfg(feature = "rustc_1_57")] + pub fn try_reserve_exact(&mut self, n: usize) -> Result<(), TryReserveError> { + let arr = match self { + TinyVec::Heap(h) => return h.try_reserve_exact(n), + TinyVec::Inline(a) => a, + }; + + if n > arr.capacity() - arr.len() { + let v = arr.try_drain_to_vec_and_reserve(n)?; + *self = TinyVec::Heap(v); + } + + /* In this place array has enough place, so no work is needed more */ + return Ok(()); + } + + /// Makes a new TinyVec with _at least_ the given capacity. + /// + /// If the requested capacity is less than or equal to the array capacity you + /// get an inline vec. If it's greater than you get a heap vec. + /// ``` + /// # use tinyvec::*; + /// let t = TinyVec::<[u8; 10]>::with_capacity(5); + /// assert!(t.is_inline()); + /// assert!(t.capacity() >= 5); + /// + /// let t = TinyVec::<[u8; 10]>::with_capacity(20); + /// assert!(t.is_heap()); + /// assert!(t.capacity() >= 20); + /// ``` + #[inline] + #[must_use] + pub fn with_capacity(cap: usize) -> Self { + if cap <= A::CAPACITY { + TinyVec::Inline(ArrayVec::default()) + } else { + TinyVec::Heap(Vec::with_capacity(cap)) + } + } +} + +impl TinyVec { + /// Move all values from `other` into this vec. + #[cfg(feature = "rustc_1_40")] + #[inline] + pub fn append(&mut self, other: &mut Self) { + self.reserve(other.len()); + + /* Doing append should be faster, because it is effectively a memcpy */ + match (self, other) { + (TinyVec::Heap(sh), TinyVec::Heap(oh)) => sh.append(oh), + (TinyVec::Inline(a), TinyVec::Heap(h)) => a.extend(h.drain(..)), + (ref mut this, TinyVec::Inline(arr)) => this.extend(arr.drain(..)), + } + } + + /// Move all values from `other` into this vec. + #[cfg(not(feature = "rustc_1_40"))] + #[inline] + pub fn append(&mut self, other: &mut Self) { + match other { + TinyVec::Inline(a) => self.extend(a.drain(..)), + TinyVec::Heap(h) => self.extend(h.drain(..)), + } + } + + impl_mirrored! { + type Mirror = TinyVec; + + /// Remove an element, swapping the end of the vec into its place. + /// + /// ## Panics + /// * If the index is out of bounds. + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([&str; 4] => "foo", "bar", "quack", "zap"); + /// + /// assert_eq!(tv.swap_remove(1), "bar"); + /// assert_eq!(tv.as_slice(), &["foo", "zap", "quack"][..]); + /// + /// assert_eq!(tv.swap_remove(0), "foo"); + /// assert_eq!(tv.as_slice(), &["quack", "zap"][..]); + /// ``` + #[inline] + pub fn swap_remove(self: &mut Self, index: usize) -> A::Item; + + /// Remove and return the last element of the vec, if there is one. + /// + /// ## Failure + /// * If the vec is empty you get `None`. + #[inline] + pub fn pop(self: &mut Self) -> Option; + + /// Removes the item at `index`, shifting all others down by one index. + /// + /// Returns the removed element. + /// + /// ## Panics + /// + /// If the index is out of bounds. + /// + /// ## Example + /// + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// assert_eq!(tv.remove(1), 2); + /// assert_eq!(tv.as_slice(), &[1, 3][..]); + /// ``` + #[inline] + pub fn remove(self: &mut Self, index: usize) -> A::Item; + + /// The length of the vec (in elements). + #[inline(always)] + #[must_use] + pub fn len(self: &Self) -> usize; + + /// The capacity of the `TinyVec`. + /// + /// When not heap allocated this is fixed based on the array type. + /// Otherwise its the result of the underlying Vec::capacity. + #[inline(always)] + #[must_use] + pub fn capacity(self: &Self) -> usize; + + /// Reduces the vec's length to the given value. + /// + /// If the vec is already shorter than the input, nothing happens. + #[inline] + pub fn truncate(self: &mut Self, new_len: usize); + + /// A mutable pointer to the backing array. + /// + /// ## Safety + /// + /// This pointer has provenance over the _entire_ backing array/buffer. + #[inline(always)] + #[must_use] + pub fn as_mut_ptr(self: &mut Self) -> *mut A::Item; + + /// A const pointer to the backing array. + /// + /// ## Safety + /// + /// This pointer has provenance over the _entire_ backing array/buffer. + #[inline(always)] + #[must_use] + pub fn as_ptr(self: &Self) -> *const A::Item; + } + + /// Walk the vec and keep only the elements that pass the predicate given. + /// + /// ## Example + /// + /// ```rust + /// use tinyvec::*; + /// + /// let mut tv = tiny_vec!([i32; 10] => 1, 2, 3, 4); + /// tv.retain(|&x| x % 2 == 0); + /// assert_eq!(tv.as_slice(), &[2, 4][..]); + /// ``` + #[inline] + pub fn retain bool>(self: &mut Self, acceptable: F) { + match self { + TinyVec::Inline(i) => i.retain(acceptable), + TinyVec::Heap(h) => h.retain(acceptable), + } + } + + /// Helper for getting the mut slice. + #[inline(always)] + #[must_use] + pub fn as_mut_slice(self: &mut Self) -> &mut [A::Item] { + self.deref_mut() + } + + /// Helper for getting the shared slice. + #[inline(always)] + #[must_use] + pub fn as_slice(self: &Self) -> &[A::Item] { + self.deref() + } + + /// Removes all elements from the vec. + #[inline(always)] + pub fn clear(&mut self) { + self.truncate(0) + } + + /// De-duplicates the vec. + #[cfg(feature = "nightly_slice_partition_dedup")] + #[inline(always)] + pub fn dedup(&mut self) + where + A::Item: PartialEq, + { + self.dedup_by(|a, b| a == b) + } + + /// De-duplicates the vec according to the predicate given. + #[cfg(feature = "nightly_slice_partition_dedup")] + #[inline(always)] + pub fn dedup_by(&mut self, same_bucket: F) + where + F: FnMut(&mut A::Item, &mut A::Item) -> bool, + { + let len = { + let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket); + dedup.len() + }; + self.truncate(len); + } + + /// De-duplicates the vec according to the key selector given. + #[cfg(feature = "nightly_slice_partition_dedup")] + #[inline(always)] + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut A::Item) -> K, + K: PartialEq, + { + self.dedup_by(|a, b| key(a) == key(b)) + } + + /// Creates a draining iterator that removes the specified range in the vector + /// and yields the removed items. + /// + /// **Note: This method has significant performance issues compared to + /// matching on the TinyVec and then calling drain on the Inline or Heap value + /// inside. The draining iterator has to branch on every single access. It is + /// provided for simplicity and compatability only.** + /// + /// ## Panics + /// * If the start is greater than the end + /// * If the end is past the edge of the vec. + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// let tv2: TinyVec<[i32; 4]> = tv.drain(1..).collect(); + /// assert_eq!(tv.as_slice(), &[1][..]); + /// assert_eq!(tv2.as_slice(), &[2, 3][..]); + /// + /// tv.drain(..); + /// assert_eq!(tv.as_slice(), &[]); + /// ``` + #[inline] + pub fn drain>( + &mut self, range: R, + ) -> TinyVecDrain<'_, A> { + match self { + TinyVec::Inline(i) => TinyVecDrain::Inline(i.drain(range)), + TinyVec::Heap(h) => TinyVecDrain::Heap(h.drain(range)), + } + } + + /// Clone each element of the slice into this vec. + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2); + /// tv.extend_from_slice(&[3, 4]); + /// assert_eq!(tv.as_slice(), [1, 2, 3, 4]); + /// ``` + #[inline] + pub fn extend_from_slice(&mut self, sli: &[A::Item]) + where + A::Item: Clone, + { + self.reserve(sli.len()); + match self { + TinyVec::Inline(a) => a.extend_from_slice(sli), + TinyVec::Heap(h) => h.extend_from_slice(sli), + } + } + + /// Wraps up an array and uses the given length as the initial length. + /// + /// Note that the `From` impl for arrays assumes the full length is used. + /// + /// ## Panics + /// + /// The length must be less than or equal to the capacity of the array. + #[inline] + #[must_use] + #[allow(clippy::match_wild_err_arm)] + pub fn from_array_len(data: A, len: usize) -> Self { + match Self::try_from_array_len(data, len) { + Ok(out) => out, + Err(_) => { + panic!("TinyVec: length {} exceeds capacity {}!", len, A::CAPACITY) + } + } + } + + /// This is an internal implementation detail of the `tiny_vec!` macro, and + /// using it other than from that macro is not supported by this crate's + /// SemVer guarantee. + #[inline(always)] + #[doc(hidden)] + pub fn constructor_for_capacity(cap: usize) -> TinyVecConstructor { + if cap <= A::CAPACITY { + TinyVecConstructor::Inline(TinyVec::Inline) + } else { + TinyVecConstructor::Heap(TinyVec::Heap) + } + } + + /// Inserts an item at the position given, moving all following elements +1 + /// index. + /// + /// ## Panics + /// * If `index` > `len` + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 10] => 1, 2, 3); + /// tv.insert(1, 4); + /// assert_eq!(tv.as_slice(), &[1, 4, 2, 3]); + /// tv.insert(4, 5); + /// assert_eq!(tv.as_slice(), &[1, 4, 2, 3, 5]); + /// ``` + #[inline] + pub fn insert(&mut self, index: usize, item: A::Item) { + assert!( + index <= self.len(), + "insertion index (is {}) should be <= len (is {})", + index, + self.len() + ); + + let arr = match self { + TinyVec::Heap(v) => return v.insert(index, item), + TinyVec::Inline(a) => a, + }; + + if let Some(x) = arr.try_insert(index, item) { + let mut v = Vec::with_capacity(arr.len() * 2); + let mut it = + arr.iter_mut().map(|r| core::mem::replace(r, Default::default())); + v.extend(it.by_ref().take(index)); + v.push(x); + v.extend(it); + *self = TinyVec::Heap(v); + } + } + + /// If the vec is empty. + #[inline(always)] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Makes a new, empty vec. + #[inline(always)] + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// Place an element onto the end of the vec. + /// ## Panics + /// * If the length of the vec would overflow the capacity. + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 10] => 1, 2, 3); + /// tv.push(4); + /// assert_eq!(tv.as_slice(), &[1, 2, 3, 4]); + /// ``` + #[inline] + pub fn push(&mut self, val: A::Item) { + // The code path for moving the inline contents to the heap produces a lot + // of instructions, but we have a strong guarantee that this is a cold + // path. LLVM doesn't know this, inlines it, and this tends to cause a + // cascade of other bad inlining decisions because the body of push looks + // huge even though nearly every call executes the same few instructions. + // + // Moving the logic out of line with #[cold] causes the hot code to be + // inlined together, and we take the extra cost of a function call only + // in rare cases. + #[cold] + fn drain_to_heap_and_push( + arr: &mut ArrayVec, val: A::Item, + ) -> TinyVec { + /* Make the Vec twice the size to amortize the cost of draining */ + let mut v = arr.drain_to_vec_and_reserve(arr.len()); + v.push(val); + TinyVec::Heap(v) + } + + match self { + TinyVec::Heap(v) => v.push(val), + TinyVec::Inline(arr) => { + if let Some(x) = arr.try_push(val) { + *self = drain_to_heap_and_push(arr, x); + } + } + } + } + + /// Resize the vec to the new length. + /// + /// If it needs to be longer, it's filled with clones of the provided value. + /// If it needs to be shorter, it's truncated. + /// + /// ## Example + /// + /// ```rust + /// use tinyvec::*; + /// + /// let mut tv = tiny_vec!([&str; 10] => "hello"); + /// tv.resize(3, "world"); + /// assert_eq!(tv.as_slice(), &["hello", "world", "world"][..]); + /// + /// let mut tv = tiny_vec!([i32; 10] => 1, 2, 3, 4); + /// tv.resize(2, 0); + /// assert_eq!(tv.as_slice(), &[1, 2][..]); + /// ``` + #[inline] + pub fn resize(&mut self, new_len: usize, new_val: A::Item) + where + A::Item: Clone, + { + self.resize_with(new_len, || new_val.clone()); + } + + /// Resize the vec to the new length. + /// + /// If it needs to be longer, it's filled with repeated calls to the provided + /// function. If it needs to be shorter, it's truncated. + /// + /// ## Example + /// + /// ```rust + /// use tinyvec::*; + /// + /// let mut tv = tiny_vec!([i32; 3] => 1, 2, 3); + /// tv.resize_with(5, Default::default); + /// assert_eq!(tv.as_slice(), &[1, 2, 3, 0, 0][..]); + /// + /// let mut tv = tiny_vec!([i32; 2]); + /// let mut p = 1; + /// tv.resize_with(4, || { + /// p *= 2; + /// p + /// }); + /// assert_eq!(tv.as_slice(), &[2, 4, 8, 16][..]); + /// ``` + #[inline] + pub fn resize_with A::Item>(&mut self, new_len: usize, f: F) { + match new_len.checked_sub(self.len()) { + None => return self.truncate(new_len), + Some(n) => self.reserve(n), + } + + match self { + TinyVec::Inline(a) => a.resize_with(new_len, f), + TinyVec::Heap(v) => v.resize_with(new_len, f), + } + } + + /// Splits the collection at the point given. + /// + /// * `[0, at)` stays in this vec + /// * `[at, len)` ends up in the new vec. + /// + /// ## Panics + /// * if at > len + /// + /// ## Example + /// + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// let tv2 = tv.split_off(1); + /// assert_eq!(tv.as_slice(), &[1][..]); + /// assert_eq!(tv2.as_slice(), &[2, 3][..]); + /// ``` + #[inline] + pub fn split_off(&mut self, at: usize) -> Self { + match self { + TinyVec::Inline(a) => TinyVec::Inline(a.split_off(at)), + TinyVec::Heap(v) => TinyVec::Heap(v.split_off(at)), + } + } + + /// Creates a splicing iterator that removes the specified range in the + /// vector, yields the removed items, and replaces them with elements from + /// the provided iterator. + /// + /// `splice` fuses the provided iterator, so elements after the first `None` + /// are ignored. + /// + /// ## Panics + /// * If the start is greater than the end. + /// * If the end is past the edge of the vec. + /// * If the provided iterator panics. + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// let tv2: TinyVec<[i32; 4]> = tv.splice(1.., 4..=6).collect(); + /// assert_eq!(tv.as_slice(), &[1, 4, 5, 6][..]); + /// assert_eq!(tv2.as_slice(), &[2, 3][..]); + /// + /// tv.splice(.., None); + /// assert_eq!(tv.as_slice(), &[]); + /// ``` + #[inline] + pub fn splice( + &mut self, range: R, replacement: I, + ) -> TinyVecSplice<'_, A, core::iter::Fuse> + where + R: RangeBounds, + I: IntoIterator, + { + use core::ops::Bound; + let start = match range.start_bound() { + Bound::Included(x) => *x, + Bound::Excluded(x) => x.saturating_add(1), + Bound::Unbounded => 0, + }; + let end = match range.end_bound() { + Bound::Included(x) => x.saturating_add(1), + Bound::Excluded(x) => *x, + Bound::Unbounded => self.len(), + }; + assert!( + start <= end, + "TinyVec::splice> Illegal range, {} to {}", + start, + end + ); + assert!( + end <= self.len(), + "TinyVec::splice> Range ends at {} but length is only {}!", + end, + self.len() + ); + + TinyVecSplice { + removal_start: start, + removal_end: end, + parent: self, + replacement: replacement.into_iter().fuse(), + } + } + + /// Wraps an array, using the given length as the starting length. + /// + /// If you want to use the whole length of the array, you can just use the + /// `From` impl. + /// + /// ## Failure + /// + /// If the given length is greater than the capacity of the array this will + /// error, and you'll get the array back in the `Err`. + #[inline] + pub fn try_from_array_len(data: A, len: usize) -> Result { + let arr = ArrayVec::try_from_array_len(data, len)?; + Ok(TinyVec::Inline(arr)) + } +} + +/// Draining iterator for `TinyVecDrain` +/// +/// See [`TinyVecDrain::drain`](TinyVecDrain::::drain) +#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))] +pub enum TinyVecDrain<'p, A: Array> { + #[allow(missing_docs)] + Inline(ArrayVecDrain<'p, A::Item>), + #[allow(missing_docs)] + Heap(vec::Drain<'p, A::Item>), +} + +impl<'p, A: Array> Iterator for TinyVecDrain<'p, A> { + type Item = A::Item; + + impl_mirrored! { + type Mirror = TinyVecDrain; + + #[inline] + fn next(self: &mut Self) -> Option; + #[inline] + fn nth(self: &mut Self, n: usize) -> Option; + #[inline] + fn size_hint(self: &Self) -> (usize, Option); + #[inline] + fn last(self: Self) -> Option; + #[inline] + fn count(self: Self) -> usize; + } + + #[inline] + fn for_each(self, f: F) { + match self { + TinyVecDrain::Inline(i) => i.for_each(f), + TinyVecDrain::Heap(h) => h.for_each(f), + } + } +} + +impl<'p, A: Array> DoubleEndedIterator for TinyVecDrain<'p, A> { + impl_mirrored! { + type Mirror = TinyVecDrain; + + #[inline] + fn next_back(self: &mut Self) -> Option; + + #[cfg(feature = "rustc_1_40")] + #[inline] + fn nth_back(self: &mut Self, n: usize) -> Option; + } +} + +/// Splicing iterator for `TinyVec` +/// See [`TinyVec::splice`](TinyVec::::splice) +#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))] +pub struct TinyVecSplice<'p, A: Array, I: Iterator> { + parent: &'p mut TinyVec, + removal_start: usize, + removal_end: usize, + replacement: I, +} + +impl<'p, A, I> Iterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ + type Item = A::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.removal_start < self.removal_end { + match self.replacement.next() { + Some(replacement) => { + let removed = core::mem::replace( + &mut self.parent[self.removal_start], + replacement, + ); + self.removal_start += 1; + Some(removed) + } + None => { + let removed = self.parent.remove(self.removal_start); + self.removal_end -= 1; + Some(removed) + } + } + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'p, A, I> ExactSizeIterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ + #[inline] + fn len(&self) -> usize { + self.removal_end - self.removal_start + } +} + +impl<'p, A, I> FusedIterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ +} + +impl<'p, A, I> DoubleEndedIterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator + DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + if self.removal_start < self.removal_end { + match self.replacement.next_back() { + Some(replacement) => { + let removed = core::mem::replace( + &mut self.parent[self.removal_end - 1], + replacement, + ); + self.removal_end -= 1; + Some(removed) + } + None => { + let removed = self.parent.remove(self.removal_end - 1); + self.removal_end -= 1; + Some(removed) + } + } + } else { + None + } + } +} + +impl<'p, A: Array, I: Iterator> Drop + for TinyVecSplice<'p, A, I> +{ + fn drop(&mut self) { + for _ in self.by_ref() {} + + let (lower_bound, _) = self.replacement.size_hint(); + self.parent.reserve(lower_bound); + + for replacement in self.replacement.by_ref() { + self.parent.insert(self.removal_end, replacement); + self.removal_end += 1; + } + } +} + +impl AsMut<[A::Item]> for TinyVec { + #[inline(always)] + #[must_use] + fn as_mut(&mut self) -> &mut [A::Item] { + &mut *self + } +} + +impl AsRef<[A::Item]> for TinyVec { + #[inline(always)] + #[must_use] + fn as_ref(&self) -> &[A::Item] { + &*self + } +} + +impl Borrow<[A::Item]> for TinyVec { + #[inline(always)] + #[must_use] + fn borrow(&self) -> &[A::Item] { + &*self + } +} + +impl BorrowMut<[A::Item]> for TinyVec { + #[inline(always)] + #[must_use] + fn borrow_mut(&mut self) -> &mut [A::Item] { + &mut *self + } +} + +impl Extend for TinyVec { + #[inline] + fn extend>(&mut self, iter: T) { + let iter = iter.into_iter(); + let (lower_bound, _) = iter.size_hint(); + self.reserve(lower_bound); + + let a = match self { + TinyVec::Heap(h) => return h.extend(iter), + TinyVec::Inline(a) => a, + }; + + let mut iter = a.fill(iter); + let maybe = iter.next(); + + let surely = match maybe { + Some(x) => x, + None => return, + }; + + let mut v = a.drain_to_vec_and_reserve(a.len()); + v.push(surely); + v.extend(iter); + *self = TinyVec::Heap(v); + } +} + +impl From> for TinyVec { + #[inline(always)] + #[must_use] + fn from(arr: ArrayVec) -> Self { + TinyVec::Inline(arr) + } +} + +impl From for TinyVec { + fn from(array: A) -> Self { + TinyVec::Inline(ArrayVec::from(array)) + } +} + +impl From<&'_ [T]> for TinyVec +where + T: Clone + Default, + A: Array, +{ + #[inline] + #[must_use] + fn from(slice: &[T]) -> Self { + if let Ok(arr) = ArrayVec::try_from(slice) { + TinyVec::Inline(arr) + } else { + TinyVec::Heap(slice.into()) + } + } +} + +impl From<&'_ mut [T]> for TinyVec +where + T: Clone + Default, + A: Array, +{ + #[inline] + #[must_use] + fn from(slice: &mut [T]) -> Self { + Self::from(&*slice) + } +} + +impl FromIterator for TinyVec { + #[inline] + #[must_use] + fn from_iter>(iter: T) -> Self { + let mut av = Self::default(); + av.extend(iter); + av + } +} + +/// Iterator for consuming an `TinyVec` and returning owned elements. +#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))] +pub enum TinyVecIterator { + #[allow(missing_docs)] + Inline(ArrayVecIterator), + #[allow(missing_docs)] + Heap(alloc::vec::IntoIter), +} + +impl TinyVecIterator { + impl_mirrored! { + type Mirror = TinyVecIterator; + /// Returns the remaining items of this iterator as a slice. + #[inline] + #[must_use] + pub fn as_slice(self: &Self) -> &[A::Item]; + } +} + +impl FusedIterator for TinyVecIterator {} + +impl Iterator for TinyVecIterator { + type Item = A::Item; + + impl_mirrored! { + type Mirror = TinyVecIterator; + + #[inline] + fn next(self: &mut Self) -> Option; + + #[inline(always)] + #[must_use] + fn size_hint(self: &Self) -> (usize, Option); + + #[inline(always)] + fn count(self: Self) -> usize; + + #[inline] + fn last(self: Self) -> Option; + + #[inline] + fn nth(self: &mut Self, n: usize) -> Option; + } +} + +impl DoubleEndedIterator for TinyVecIterator { + impl_mirrored! { + type Mirror = TinyVecIterator; + + #[inline] + fn next_back(self: &mut Self) -> Option; + + #[cfg(feature = "rustc_1_40")] + #[inline] + fn nth_back(self: &mut Self, n: usize) -> Option; + } +} + +impl Debug for TinyVecIterator +where + A::Item: Debug, +{ + #[allow(clippy::missing_inline_in_public_items)] + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("TinyVecIterator").field(&self.as_slice()).finish() + } +} + +impl IntoIterator for TinyVec { + type Item = A::Item; + type IntoIter = TinyVecIterator; + #[inline(always)] + #[must_use] + fn into_iter(self) -> Self::IntoIter { + match self { + TinyVec::Inline(a) => TinyVecIterator::Inline(a.into_iter()), + TinyVec::Heap(v) => TinyVecIterator::Heap(v.into_iter()), + } + } +} + +impl<'a, A: Array> IntoIterator for &'a mut TinyVec { + type Item = &'a mut A::Item; + type IntoIter = core::slice::IterMut<'a, A::Item>; + #[inline(always)] + #[must_use] + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +impl<'a, A: Array> IntoIterator for &'a TinyVec { + type Item = &'a A::Item; + type IntoIter = core::slice::Iter<'a, A::Item>; + #[inline(always)] + #[must_use] + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl PartialEq for TinyVec +where + A::Item: PartialEq, +{ + #[inline] + #[must_use] + fn eq(&self, other: &Self) -> bool { + self.as_slice().eq(other.as_slice()) + } +} +impl Eq for TinyVec where A::Item: Eq {} + +impl PartialOrd for TinyVec +where + A::Item: PartialOrd, +{ + #[inline] + #[must_use] + fn partial_cmp(&self, other: &Self) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} +impl Ord for TinyVec +where + A::Item: Ord, +{ + #[inline] + #[must_use] + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.as_slice().cmp(other.as_slice()) + } +} + +impl PartialEq<&A> for TinyVec +where + A::Item: PartialEq, +{ + #[inline] + #[must_use] + fn eq(&self, other: &&A) -> bool { + self.as_slice().eq(other.as_slice()) + } +} + +impl PartialEq<&[A::Item]> for TinyVec +where + A::Item: PartialEq, +{ + #[inline] + #[must_use] + fn eq(&self, other: &&[A::Item]) -> bool { + self.as_slice().eq(*other) + } +} + +impl Hash for TinyVec +where + A::Item: Hash, +{ + #[inline] + fn hash(&self, state: &mut H) { + self.as_slice().hash(state) + } +} + +// // // // // // // // +// Formatting impls +// // // // // // // // + +impl Binary for TinyVec +where + A::Item: Binary, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + Binary::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl Debug for TinyVec +where + A::Item: Debug, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + Debug::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl Display for TinyVec +where + A::Item: Display, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + Display::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl LowerExp for TinyVec +where + A::Item: LowerExp, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + LowerExp::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl LowerHex for TinyVec +where + A::Item: LowerHex, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + LowerHex::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl Octal for TinyVec +where + A::Item: Octal, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + Octal::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl Pointer for TinyVec +where + A::Item: Pointer, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + Pointer::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl UpperExp for TinyVec +where + A::Item: UpperExp, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + UpperExp::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +impl UpperHex for TinyVec +where + A::Item: UpperHex, +{ + #[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, ",{}", if f.alternate() { "\n " } else { " " })?; + } + UpperHex::fmt(elem, f)?; + } + if f.alternate() { + write!(f, ",\n")?; + } + write!(f, "]") + } +} + +#[cfg(feature = "serde")] +#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))] +struct TinyVecVisitor(PhantomData); + +#[cfg(feature = "serde")] +impl<'de, A: Array> Visitor<'de> for TinyVecVisitor +where + A::Item: Deserialize<'de>, +{ + type Value = TinyVec; + + fn expecting( + &self, formatter: &mut core::fmt::Formatter, + ) -> core::fmt::Result { + formatter.write_str("a sequence") + } + + fn visit_seq(self, mut seq: S) -> Result + where + S: SeqAccess<'de>, + { + let mut new_tinyvec = match seq.size_hint() { + Some(expected_size) => TinyVec::with_capacity(expected_size), + None => Default::default(), + }; + + while let Some(value) = seq.next_element()? { + new_tinyvec.push(value); + } + + Ok(new_tinyvec) + } +} -- cgit v1.2.3