#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(feature = "specialization", allow(incomplete_features))]
#![cfg_attr(feature = "specialization", feature(specialization))]
#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))]
#![cfg_attr(
feature = "debugger_visualizer",
feature(debugger_visualizer),
debugger_visualizer(natvis_file = "../debug_metadata/smallvec.natvis")
)]
#![deny(missing_docs)]
#[doc(hidden)]
pub extern crate alloc;
#[cfg(any(test, feature = "write"))]
extern crate std;
#[cfg(test)]
mod tests;
#[allow(deprecated)]
use alloc::alloc::{Layout, LayoutErr};
use alloc::boxed::Box;
use alloc::{vec, vec::Vec};
use core::borrow::{Borrow, BorrowMut};
use core::cmp;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::hint::unreachable_unchecked;
use core::iter::{repeat, FromIterator, FusedIterator, IntoIterator};
use core::mem;
use core::mem::MaybeUninit;
use core::ops::{self, Range, RangeBounds};
use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};
#[cfg(feature = "malloc_size_of")]
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
#[cfg(feature = "serde")]
use serde::{
de::{Deserialize, Deserializer, SeqAccess, Visitor},
ser::{Serialize, SerializeSeq, Serializer},
};
#[cfg(feature = "serde")]
use core::marker::PhantomData;
#[cfg(feature = "write")]
use std::io;
#[cfg(feature = "drain_keep_rest")]
use core::mem::ManuallyDrop;
#[macro_export]
macro_rules! smallvec {
(@one $x:expr) => (1usize);
() => (
$crate::SmallVec::new()
);
($elem:expr; $n:expr) => ({
$crate::SmallVec::from_elem($elem, $n)
});
($($x:expr),+$(,)?) => ({
let count = 0usize $(+ $crate::smallvec!(@one $x))+;
let mut vec = $crate::SmallVec::new();
if count <= vec.inline_size() {
$(vec.push($x);)*
vec
} else {
$crate::SmallVec::from_vec($crate::alloc::vec![$($x,)+])
}
});
}
#[cfg(feature = "const_new")]
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
#[macro_export]
macro_rules! smallvec_inline {
(@one $x:expr) => (1usize);
($elem:expr; $n:expr) => ({
$crate::SmallVec::<[_; $n]>::from_const([$elem; $n])
});
($($x:expr),+ $(,)?) => ({
const N: usize = 0usize $(+ $crate::smallvec_inline!(@one $x))*;
$crate::SmallVec::<[_; N]>::from_const([$($x,)*])
});
}
#[cfg(not(feature = "union"))]
macro_rules! debug_unreachable {
() => {
debug_unreachable!("entered unreachable code")
};
($e:expr) => {
if cfg!(debug_assertions) {
panic!($e);
} else {
unreachable_unchecked();
}
};
}
#[doc(hidden)]
#[deprecated]
pub trait ExtendFromSlice<T> {
fn extend_from_slice(&mut self, other: &[T]);
}
#[allow(deprecated)]
impl<T: Clone> ExtendFromSlice<T> for Vec<T> {
fn extend_from_slice(&mut self, other: &[T]) {
Vec::extend_from_slice(self, other)
}
}
#[derive(Debug)]
pub enum CollectionAllocErr {
CapacityOverflow,
AllocErr {
layout: Layout,
},
}
impl fmt::Display for CollectionAllocErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Allocation error: {:?}", self)
}
}
#[allow(deprecated)]
impl From<LayoutErr> for CollectionAllocErr {
fn from(_: LayoutErr) -> Self {
CollectionAllocErr::CapacityOverflow
}
}
fn infallible<T>(result: Result<T, CollectionAllocErr>) -> T {
match result {
Ok(x) => x,
Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
Err(CollectionAllocErr::AllocErr { layout }) => alloc::alloc::handle_alloc_error(layout),
}
}
fn layout_array<T>(n: usize) -> Result<Layout, CollectionAllocErr> {
let size = mem::size_of::<T>()
.checked_mul(n)
.ok_or(CollectionAllocErr::CapacityOverflow)?;
let align = mem::align_of::<T>();
Layout::from_size_align(size, align).map_err(|_| CollectionAllocErr::CapacityOverflow)
}
unsafe fn deallocate<T>(ptr: NonNull<T>, capacity: usize) {
let layout = layout_array::<T>(capacity).unwrap();
alloc::alloc::dealloc(ptr.as_ptr() as *mut u8, layout)
}
pub struct Drain<'a, T: 'a + Array> {
tail_start: usize,
tail_len: usize,
iter: slice::Iter<'a, T::Item>,
vec: NonNull<SmallVec<T>>,
}
impl<'a, T: 'a + Array> fmt::Debug for Drain<'a, T>
where
T::Item: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
}
}
unsafe impl<'a, T: Sync + Array> Sync for Drain<'a, T> {}
unsafe impl<'a, T: Send + Array> Send for Drain<'a, T> {}
impl<'a, T: 'a + Array> Iterator for Drain<'a, T> {
type Item = T::Item;
#[inline]
fn next(&mut self) -> Option<T::Item> {
self.iter
.next()
.map(|reference| unsafe { ptr::read(reference) })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, T: 'a + Array> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T::Item> {
self.iter
.next_back()
.map(|reference| unsafe { ptr::read(reference) })
}
}
impl<'a, T: Array> ExactSizeIterator for Drain<'a, T> {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<'a, T: Array> FusedIterator for Drain<'a, T> {}
impl<'a, T: 'a + Array> Drop for Drain<'a, T> {
fn drop(&mut self) {
self.for_each(drop);
if self.tail_len > 0 {
unsafe {
let source_vec = self.vec.as_mut();
let start = source_vec.len();
let tail = self.tail_start;
if tail != start {
let ptr = source_vec.as_mut_ptr();
let src = ptr.add(tail);
let dst = ptr.add(start);
ptr::copy(src, dst, self.tail_len);
}
source_vec.set_len(start + self.tail_len);
}
}
}
}
#[cfg(feature = "drain_filter")]
pub struct DrainFilter<'a, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array,
{
vec: &'a mut SmallVec<T>,
idx: usize,
del: usize,
old_len: usize,
pred: F,
panic_flag: bool,
}
#[cfg(feature = "drain_filter")]
impl <T, F> fmt::Debug for DrainFilter<'_, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array,
T::Item: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.vec.as_slice()).finish()
}
}
#[cfg(feature = "drain_filter")]
impl <T, F> Iterator for DrainFilter<'_, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array,
{
type Item = T::Item;
fn next(&mut self) -> Option<T::Item>
{
unsafe {
while self.idx < self.old_len {
let i = self.idx;
let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len);
self.panic_flag = true;
let drained = (self.pred)(&mut v[i]);
self.panic_flag = false;
self.idx += 1;
if drained {
self.del += 1;
return Some(ptr::read(&v[i]));
} else if self.del > 0 {
let del = self.del;
let src: *const Self::Item = &v[i];
let dst: *mut Self::Item = &mut v[i - del];
ptr::copy_nonoverlapping(src, dst, 1);
}
}
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.old_len - self.idx))
}
}
#[cfg(feature = "drain_filter")]
impl <T, F> Drop for DrainFilter<'_, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array,
{
fn drop(&mut self) {
struct BackshiftOnDrop<'a, 'b, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array
{
drain: &'b mut DrainFilter<'a, T, F>,
}
impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array
{
fn drop(&mut self) {
unsafe {
if self.drain.idx < self.drain.old_len && self.drain.del > 0 {
let ptr = self.drain.vec.as_mut_ptr();
let src = ptr.add(self.drain.idx);
let dst = src.sub(self.drain.del);
let tail_len = self.drain.old_len - self.drain.idx;
src.copy_to(dst, tail_len);
}
self.drain.vec.set_len(self.drain.old_len - self.drain.del);
}
}
}
let backshift = BackshiftOnDrop { drain: self };
if !backshift.drain.panic_flag {
backshift.drain.for_each(drop);
}
}
}
#[cfg(feature = "drain_keep_rest")]
impl <T, F> DrainFilter<'_, T, F>
where
F: FnMut(&mut T::Item) -> bool,
T: Array
{
pub fn keep_rest(self)
{
let mut this = ManuallyDrop::new(self);
unsafe {
let needs_move = mem::size_of::<T>() != 0;
if needs_move && this.idx < this.old_len && this.del > 0 {
let ptr = this.vec.as_mut_ptr();
let src = ptr.add(this.idx);
let dst = src.sub(this.del);
let tail_len = this.old_len - this.idx;
src.copy_to(dst, tail_len);
}
let new_len = this.old_len - this.del;
this.vec.set_len(new_len);
}
}
}
#[cfg(feature = "union")]
union SmallVecData<A: Array> {
inline: core::mem::ManuallyDrop<MaybeUninit<A>>,
heap: (NonNull<A::Item>, usize),
}
#[cfg(all(feature = "union", feature = "const_new"))]
impl<T, const N: usize> SmallVecData<[T; N]> {
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
#[inline]
const fn from_const(inline: MaybeUninit<[T; N]>) -> Self {
SmallVecData {
inline: core::mem::ManuallyDrop::new(inline),
}
}
}
#[cfg(feature = "union")]
impl<A: Array> SmallVecData<A> {
#[inline]
unsafe fn inline(&self) -> ConstNonNull<A::Item> {
ConstNonNull::new(self.inline.as_ptr() as *const A::Item).unwrap()
}
#[inline]
unsafe fn inline_mut(&mut self) -> NonNull<A::Item> {
NonNull::new(self.inline.as_mut_ptr() as *mut A::Item).unwrap()
}
#[inline]
fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
SmallVecData {
inline: core::mem::ManuallyDrop::new(inline),
}
}
#[inline]
unsafe fn into_inline(self) -> MaybeUninit<A> {
core::mem::ManuallyDrop::into_inner(self.inline)
}
#[inline]
unsafe fn heap(&self) -> (ConstNonNull<A::Item>, usize) {
(ConstNonNull(self.heap.0), self.heap.1)
}
#[inline]
unsafe fn heap_mut(&mut self) -> (NonNull<A::Item>, &mut usize) {
let h = &mut self.heap;
(h.0, &mut h.1)
}
#[inline]
fn from_heap(ptr: NonNull<A::Item>, len: usize) -> SmallVecData<A> {
SmallVecData { heap: (ptr, len) }
}
}
#[cfg(not(feature = "union"))]
enum SmallVecData<A: Array> {
Inline(MaybeUninit<A>),
Heap {
ptr: NonNull<A::Item>,
len: usize,
},
}
#[cfg(all(not(feature = "union"), feature = "const_new"))]
impl<T, const N: usize> SmallVecData<[T; N]> {
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
#[inline]
const fn from_const(inline: MaybeUninit<[T; N]>) -> Self {
SmallVecData::Inline(inline)
}
}
#[cfg(not(feature = "union"))]
impl<A: Array> SmallVecData<A> {
#[inline]
unsafe fn inline(&self) -> ConstNonNull<A::Item> {
match self {
SmallVecData::Inline(a) => ConstNonNull::new(a.as_ptr() as *const A::Item).unwrap(),
_ => debug_unreachable!(),
}
}
#[inline]
unsafe fn inline_mut(&mut self) -> NonNull<A::Item> {
match self {
SmallVecData::Inline(a) => NonNull::new(a.as_mut_ptr() as *mut A::Item).unwrap(),
_ => debug_unreachable!(),
}
}
#[inline]
fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
SmallVecData::Inline(inline)
}
#[inline]
unsafe fn into_inline(self) -> MaybeUninit<A> {
match self {
SmallVecData::Inline(a) => a,
_ => debug_unreachable!(),
}
}
#[inline]
unsafe fn heap(&self) -> (ConstNonNull<A::Item>, usize) {
match self {
SmallVecData::Heap { ptr, len } => (ConstNonNull(*ptr), *len),
_ => debug_unreachable!(),
}
}
#[inline]
unsafe fn heap_mut(&mut self) -> (NonNull<A::Item>, &mut usize) {
match self {
SmallVecData::Heap { ptr, len } => (*ptr, len),
_ => debug_unreachable!(),
}
}
#[inline]
fn from_heap(ptr: NonNull<A::Item>, len: usize) -> SmallVecData<A> {
SmallVecData::Heap { ptr, len }
}
}
unsafe impl<A: Array + Send> Send for SmallVecData<A> {}
unsafe impl<A: Array + Sync> Sync for SmallVecData<A> {}
pub struct SmallVec<A: Array> {
capacity: usize,
data: SmallVecData<A>,
}
impl<A: Array> SmallVec<A> {
#[inline]
pub fn new() -> SmallVec<A> {
assert!(
mem::size_of::<A>() == A::size() * mem::size_of::<A::Item>()
&& mem::align_of::<A>() >= mem::align_of::<A::Item>()
);
SmallVec {
capacity: 0,
data: SmallVecData::from_inline(MaybeUninit::uninit()),
}
}
#[inline]
pub fn with_capacity(n: usize) -> Self {
let mut v = SmallVec::new();
v.reserve_exact(n);
v
}
#[inline]
pub fn from_vec(mut vec: Vec<A::Item>) -> SmallVec<A> {
if vec.capacity() <= Self::inline_capacity() {
unsafe {
let mut data = SmallVecData::<A>::from_inline(MaybeUninit::uninit());
let len = vec.len();
vec.set_len(0);
ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().as_ptr(), len);
SmallVec {
capacity: len,
data,
}
}
} else {
let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len());
mem::forget(vec);
let ptr = NonNull::new(ptr)
.expect("Cannot be null by `Vec` invariant");
SmallVec {
capacity: cap,
data: SmallVecData::from_heap(ptr, len),
}
}
}
#[inline]
pub fn from_buf(buf: A) -> SmallVec<A> {
SmallVec {
capacity: A::size(),
data: SmallVecData::from_inline(MaybeUninit::new(buf)),
}
}
#[inline]
pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec<A> {
assert!(len <= A::size());
unsafe { SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), len) }
}
#[inline]
pub unsafe fn from_buf_and_len_unchecked(buf: MaybeUninit<A>, len: usize) -> SmallVec<A> {
SmallVec {
capacity: len,
data: SmallVecData::from_inline(buf),
}
}
pub unsafe fn set_len(&mut self, new_len: usize) {
let (_, len_ptr, _) = self.triple_mut();
*len_ptr = new_len;
}
#[inline]
fn inline_capacity() -> usize {
if mem::size_of::<A::Item>() > 0 {
A::size()
} else {
core::usize::MAX
}
}
#[inline]
pub fn inline_size(&self) -> usize {
Self::inline_capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.triple().1
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn capacity(&self) -> usize {
self.triple().2
}
#[inline]
fn triple(&self) -> (ConstNonNull<A::Item>, usize, usize) {
unsafe {
if self.spilled() {
let (ptr, len) = self.data.heap();
(ptr, len, self.capacity)
} else {
(self.data.inline(), self.capacity, Self::inline_capacity())
}
}
}
#[inline]
fn triple_mut(&mut self) -> (NonNull<A::Item>, &mut usize, usize) {
unsafe {
if self.spilled() {
let (ptr, len_ptr) = self.data.heap_mut();
(ptr, len_ptr, self.capacity)
} else {
(
self.data.inline_mut(),
&mut self.capacity,
Self::inline_capacity(),
)
}
}
}
#[inline]
pub fn spilled(&self) -> bool {
self.capacity > Self::inline_capacity()
}
pub fn drain<R>(&mut self, range: R) -> Drain<'_, A>
where
R: RangeBounds<usize>,
{
use core::ops::Bound::*;
let len = self.len();
let start = match range.start_bound() {
Included(&n) => n,
Excluded(&n) => n.checked_add(1).expect("Range start out of bounds"),
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&n) => n.checked_add(1).expect("Range end out of bounds"),
Excluded(&n) => n,
Unbounded => len,
};
assert!(start <= end);
assert!(end <= len);
unsafe {
self.set_len(start);
let range_slice = slice::from_raw_parts(self.as_ptr().add(start), end - start);
Drain {
tail_start: end,
tail_len: len - end,
iter: range_slice.iter(),
vec: NonNull::new_unchecked(self as *mut _),
}
}
}
#[cfg(feature = "drain_filter")]
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, A, F,>
where
F: FnMut(&mut A::Item) -> bool,
{
let old_len = self.len();
unsafe {
self.set_len(0);
}
DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false }
}
#[inline]
pub fn push(&mut self, value: A::Item) {
unsafe {
let (mut ptr, mut len, cap) = self.triple_mut();
if *len == cap {
self.reserve_one_unchecked();
let (heap_ptr, heap_len) = self.data.heap_mut();
ptr = heap_ptr;
len = heap_len;
}
ptr::write(ptr.as_ptr().add(*len), value);
*len += 1;
}
}
#[inline]
pub fn pop(&mut self) -> Option<A::Item> {
unsafe {
let (ptr, len_ptr, _) = self.triple_mut();
let ptr: *const _ = ptr.as_ptr();
if *len_ptr == 0 {
return None;
}
let last_index = *len_ptr - 1;
*len_ptr = last_index;
Some(ptr::read(ptr.add(last_index)))
}
}
pub fn append<B>(&mut self, other: &mut SmallVec<B>)
where
B: Array<Item = A::Item>,
{
self.extend(other.drain(..))
}
pub fn grow(&mut self, new_cap: usize) {
infallible(self.try_grow(new_cap))
}
pub fn try_grow(&mut self, new_cap: usize) -> Result<(), CollectionAllocErr> {
unsafe {
let unspilled = !self.spilled();
let (ptr, &mut len, cap) = self.triple_mut();
assert!(new_cap >= len);
if new_cap <= Self::inline_capacity() {
if unspilled {
return Ok(());
}
self.data = SmallVecData::from_inline(MaybeUninit::uninit());
ptr::copy_nonoverlapping(ptr.as_ptr(), self.data.inline_mut().as_ptr(), len);
self.capacity = len;
deallocate(ptr, cap);
} else if new_cap != cap {
let layout = layout_array::<A::Item>(new_cap)?;
debug_assert!(layout.size() > 0);
let new_alloc;
if unspilled {
new_alloc = NonNull::new(alloc::alloc::alloc(layout))
.ok_or(CollectionAllocErr::AllocErr { layout })?
.cast();
ptr::copy_nonoverlapping(ptr.as_ptr(), new_alloc.as_ptr(), len);
} else {
let old_layout = layout_array::<A::Item>(cap)?;
let new_ptr =
alloc::alloc::realloc(ptr.as_ptr() as *mut u8, old_layout, layout.size());
new_alloc = NonNull::new(new_ptr)
.ok_or(CollectionAllocErr::AllocErr { layout })?
.cast();
}
self.data = SmallVecData::from_heap(new_alloc, len);
self.capacity = new_cap;
}
Ok(())
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
infallible(self.try_reserve(additional))
}
#[cold]
fn reserve_one_unchecked(&mut self) {
debug_assert_eq!(self.len(), self.capacity());
let new_cap = self.len()
.checked_add(1)
.and_then(usize::checked_next_power_of_two)
.expect("capacity overflow");
infallible(self.try_grow(new_cap))
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
let (_, &mut len, cap) = self.triple_mut();
if cap - len >= additional {
return Ok(());
}
let new_cap = len
.checked_add(additional)
.and_then(usize::checked_next_power_of_two)
.ok_or(CollectionAllocErr::CapacityOverflow)?;
self.try_grow(new_cap)
}
pub fn reserve_exact(&mut self, additional: usize) {
infallible(self.try_reserve_exact(additional))
}
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
let (_, &mut len, cap) = self.triple_mut();
if cap - len >= additional {
return Ok(());
}
let new_cap = len
.checked_add(additional)
.ok_or(CollectionAllocErr::CapacityOverflow)?;
self.try_grow(new_cap)
}
pub fn shrink_to_fit(&mut self) {
if !self.spilled() {
return;
}
let len = self.len();
if self.inline_size() >= len {
unsafe {
let (ptr, len) = self.data.heap();
self.data = SmallVecData::from_inline(MaybeUninit::uninit());
ptr::copy_nonoverlapping(ptr.as_ptr(), self.data.inline_mut().as_ptr(), len);
deallocate(ptr.0, self.capacity);
self.capacity = len;
}
} else if self.capacity() > len {
self.grow(len);
}
}
pub fn truncate(&mut self, len: usize) {
unsafe {
let (ptr, len_ptr, _) = self.triple_mut();
let ptr = ptr.as_ptr();
while len < *len_ptr {
let last_index = *len_ptr - 1;
*len_ptr = last_index;
ptr::drop_in_place(ptr.add(last_index));
}
}
}
pub fn as_slice(&self) -> &[A::Item] {
self
}
pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
self
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> A::Item {
let len = self.len();
self.swap(len - 1, index);
self.pop()
.unwrap_or_else(|| unsafe { unreachable_unchecked() })
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0);
}
pub fn remove(&mut self, index: usize) -> A::Item {
unsafe {
let (ptr, len_ptr, _) = self.triple_mut();
let len = *len_ptr;
assert!(index < len);
*len_ptr = len - 1;
let ptr = ptr.as_ptr().add(index);
let item = ptr::read(ptr);
ptr::copy(ptr.add(1), ptr, len - index - 1);
item
}
}
pub fn insert(&mut self, index: usize, element: A::Item) {
unsafe {
let (mut ptr, mut len_ptr, cap) = self.triple_mut();
if *len_ptr == cap {
self.reserve_one_unchecked();
let (heap_ptr, heap_len_ptr) = self.data.heap_mut();
ptr = heap_ptr;
len_ptr = heap_len_ptr;
}
let mut ptr = ptr.as_ptr();
let len = *len_ptr;
if index > len {
panic!("index exceeds length");
}
ptr = ptr.add(index);
if index < len {
ptr::copy(ptr, ptr.add(1), len - index);
}
*len_ptr = len + 1;
ptr::write(ptr, element);
}
}
pub fn insert_many<I: IntoIterator<Item = A::Item>>(&mut self, index: usize, iterable: I) {
let mut iter = iterable.into_iter();
if index == self.len() {
return self.extend(iter);
}
let (lower_size_bound, _) = iter.size_hint();
assert!(lower_size_bound <= core::isize::MAX as usize); assert!(index + lower_size_bound >= index);
let mut num_added = 0;
let old_len = self.len();
assert!(index <= old_len);
unsafe {
self.reserve(lower_size_bound);
let start = self.as_mut_ptr();
let ptr = start.add(index);
ptr::copy(ptr, ptr.add(lower_size_bound), old_len - index);
self.set_len(0);
let mut guard = DropOnPanic {
start,
skip: index..(index + lower_size_bound),
len: old_len + lower_size_bound,
};
let start = self.as_mut_ptr();
let ptr = start.add(index);
while num_added < lower_size_bound {
let element = match iter.next() {
Some(x) => x,
None => break,
};
let cur = ptr.add(num_added);
ptr::write(cur, element);
guard.skip.start += 1;
num_added += 1;
}
if num_added < lower_size_bound {
ptr::copy(
ptr.add(lower_size_bound),
ptr.add(num_added),
old_len - index,
);
}
self.set_len(old_len + num_added);
mem::forget(guard);
}
for element in iter {
self.insert(index + num_added, element);
num_added += 1;
}
struct DropOnPanic<T> {
start: *mut T,
skip: Range<usize>, len: usize,
}
impl<T> Drop for DropOnPanic<T> {
fn drop(&mut self) {
for i in 0..self.len {
if !self.skip.contains(&i) {
unsafe {
ptr::drop_in_place(self.start.add(i));
}
}
}
}
}
}
pub fn into_vec(mut self) -> Vec<A::Item> {
if self.spilled() {
unsafe {
let (ptr, &mut len) = self.data.heap_mut();
let v = Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity);
mem::forget(self);
v
}
} else {
self.into_iter().collect()
}
}
pub fn into_boxed_slice(self) -> Box<[A::Item]> {
self.into_vec().into_boxed_slice()
}
pub fn into_inner(self) -> Result<A, Self> {
if self.spilled() || self.len() != A::size() {
Err(self)
} else {
unsafe {
let data = ptr::read(&self.data);
mem::forget(self);
Ok(data.into_inline().assume_init())
}
}
}
pub fn retain<F: FnMut(&mut A::Item) -> bool>(&mut self, mut f: F) {
let mut del = 0;
let len = self.len();
for i in 0..len {
if !f(&mut self[i]) {
del += 1;
} else if del > 0 {
self.swap(i - del, i);
}
}
self.truncate(len - del);
}
pub fn retain_mut<F: FnMut(&mut A::Item) -> bool>(&mut self, f: F) {
self.retain(f)
}
pub fn dedup(&mut self)
where
A::Item: PartialEq<A::Item>,
{
self.dedup_by(|a, b| a == b);
}
pub fn dedup_by<F>(&mut self, mut same_bucket: F)
where
F: FnMut(&mut A::Item, &mut A::Item) -> bool,
{
let len = self.len();
if len <= 1 {
return;
}
let ptr = self.as_mut_ptr();
let mut w: usize = 1;
unsafe {
for r in 1..len {
let p_r = ptr.add(r);
let p_wm1 = ptr.add(w - 1);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.add(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
}
}
self.truncate(w);
}
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
where
F: FnMut(&mut A::Item) -> K,
K: PartialEq<K>,
{
self.dedup_by(|a, b| key(a) == key(b));
}
pub fn resize_with<F>(&mut self, new_len: usize, f: F)
where
F: FnMut() -> A::Item,
{
let old_len = self.len();
if old_len < new_len {
let mut f = f;
let additional = new_len - old_len;
self.reserve(additional);
for _ in 0..additional {
self.push(f());
}
} else if old_len > new_len {
self.truncate(new_len);
}
}
#[inline]
pub unsafe fn from_raw_parts(ptr: *mut A::Item, length: usize, capacity: usize) -> SmallVec<A> {
let ptr = unsafe {
debug_assert!(!ptr.is_null(), "Called `from_raw_parts` with null pointer.");
NonNull::new_unchecked(ptr)
};
assert!(capacity > Self::inline_capacity());
SmallVec {
capacity,
data: SmallVecData::from_heap(ptr, length),
}
}
pub fn as_ptr(&self) -> *const A::Item {
self.triple().0.as_ptr()
}
pub fn as_mut_ptr(&mut self) -> *mut A::Item {
self.triple_mut().0.as_ptr()
}
}
impl<A: Array> SmallVec<A>
where
A::Item: Copy,
{
pub fn from_slice(slice: &[A::Item]) -> Self {
let len = slice.len();
if len <= Self::inline_capacity() {
SmallVec {
capacity: len,
data: SmallVecData::from_inline(unsafe {
let mut data: MaybeUninit<A> = MaybeUninit::uninit();
ptr::copy_nonoverlapping(
slice.as_ptr(),
data.as_mut_ptr() as *mut A::Item,
len,
);
data
}),
}
} else {
let mut b = slice.to_vec();
let cap = b.capacity();
let ptr = NonNull::new(b.as_mut_ptr()).expect("Vec always contain non null pointers.");
mem::forget(b);
SmallVec {
capacity: cap,
data: SmallVecData::from_heap(ptr, len),
}
}
}
#[inline]
pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
self.reserve(slice.len());
let len = self.len();
assert!(index <= len);
unsafe {
let slice_ptr = slice.as_ptr();
let ptr = self.as_mut_ptr().add(index);
ptr::copy(ptr, ptr.add(slice.len()), len - index);
ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len());
self.set_len(len + slice.len());
}
}
#[inline]
pub fn extend_from_slice(&mut self, slice: &[A::Item]) {
let len = self.len();
self.insert_from_slice(len, slice);
}
}
impl<A: Array> SmallVec<A>
where
A::Item: Clone,
{
pub fn resize(&mut self, len: usize, value: A::Item) {
let old_len = self.len();
if len > old_len {
self.extend(repeat(value).take(len - old_len));
} else {
self.truncate(len);
}
}
pub fn from_elem(elem: A::Item, n: usize) -> Self {
if n > Self::inline_capacity() {
vec![elem; n].into()
} else {
let mut v = SmallVec::<A>::new();
unsafe {
let (ptr, len_ptr, _) = v.triple_mut();
let ptr = ptr.as_ptr();
let mut local_len = SetLenOnDrop::new(len_ptr);
for i in 0..n {
::core::ptr::write(ptr.add(i), elem.clone());
local_len.increment_len(1);
}
}
v
}
}
}
impl<A: Array> ops::Deref for SmallVec<A> {
type Target = [A::Item];
#[inline]
fn deref(&self) -> &[A::Item] {
unsafe {
let (ptr, len, _) = self.triple();
slice::from_raw_parts(ptr.as_ptr(), len)
}
}
}
impl<A: Array> ops::DerefMut for SmallVec<A> {
#[inline]
fn deref_mut(&mut self) -> &mut [A::Item] {
unsafe {
let (ptr, &mut len, _) = self.triple_mut();
slice::from_raw_parts_mut(ptr.as_ptr(), len)
}
}
}
impl<A: Array> AsRef<[A::Item]> for SmallVec<A> {
#[inline]
fn as_ref(&self) -> &[A::Item] {
self
}
}
impl<A: Array> AsMut<[A::Item]> for SmallVec<A> {
#[inline]
fn as_mut(&mut self) -> &mut [A::Item] {
self
}
}
impl<A: Array> Borrow<[A::Item]> for SmallVec<A> {
#[inline]
fn borrow(&self) -> &[A::Item] {
self
}
}
impl<A: Array> BorrowMut<[A::Item]> for SmallVec<A> {
#[inline]
fn borrow_mut(&mut self) -> &mut [A::Item] {
self
}
}
#[cfg(feature = "write")]
#[cfg_attr(docsrs, doc(cfg(feature = "write")))]
impl<A: Array<Item = u8>> io::Write for SmallVec<A> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.extend_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.extend_from_slice(buf);
Ok(())
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<A: Array> Serialize for SmallVec<A>
where
A::Item: Serialize,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut state = serializer.serialize_seq(Some(self.len()))?;
for item in self {
state.serialize_element(&item)?;
}
state.end()
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de, A: Array> Deserialize<'de> for SmallVec<A>
where
A::Item: Deserialize<'de>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_seq(SmallVecVisitor {
phantom: PhantomData,
})
}
}
#[cfg(feature = "serde")]
struct SmallVecVisitor<A> {
phantom: PhantomData<A>,
}
#[cfg(feature = "serde")]
impl<'de, A: Array> Visitor<'de> for SmallVecVisitor<A>
where
A::Item: Deserialize<'de>,
{
type Value = SmallVec<A>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<B>(self, mut seq: B) -> Result<Self::Value, B::Error>
where
B: SeqAccess<'de>,
{
use serde::de::Error;
let len = seq.size_hint().unwrap_or(0);
let mut values = SmallVec::new();
values.try_reserve(len).map_err(B::Error::custom)?;
while let Some(value) = seq.next_element()? {
values.push(value);
}
Ok(values)
}
}
#[cfg(feature = "malloc_size_of")]
impl<A: Array> MallocShallowSizeOf for SmallVec<A> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if self.spilled() {
unsafe { ops.malloc_size_of(self.as_ptr()) }
} else {
0
}
}
}
#[cfg(feature = "malloc_size_of")]
impl<A> MallocSizeOf for SmallVec<A>
where
A: Array,
A::Item: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for elem in self.iter() {
n += elem.size_of(ops);
}
n
}
}
#[cfg(feature = "specialization")]
trait SpecFrom<A: Array, S> {
fn spec_from(slice: S) -> SmallVec<A>;
}
#[cfg(feature = "specialization")]
mod specialization;
#[cfg(feature = "arbitrary")]
mod arbitrary;
#[cfg(feature = "specialization")]
impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A>
where
A::Item: Copy,
{
#[inline]
fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> {
SmallVec::from_slice(slice)
}
}
impl<'a, A: Array> From<&'a [A::Item]> for SmallVec<A>
where
A::Item: Clone,
{
#[cfg(not(feature = "specialization"))]
#[inline]
fn from(slice: &'a [A::Item]) -> SmallVec<A> {
slice.iter().cloned().collect()
}
#[cfg(feature = "specialization")]
#[inline]
fn from(slice: &'a [A::Item]) -> SmallVec<A> {
SmallVec::spec_from(slice)
}
}
impl<A: Array> From<Vec<A::Item>> for SmallVec<A> {
#[inline]
fn from(vec: Vec<A::Item>) -> SmallVec<A> {
SmallVec::from_vec(vec)
}
}
impl<A: Array> From<A> for SmallVec<A> {
#[inline]
fn from(array: A) -> SmallVec<A> {
SmallVec::from_buf(array)
}
}
impl<A: Array, I: SliceIndex<[A::Item]>> ops::Index<I> for SmallVec<A> {
type Output = I::Output;
fn index(&self, index: I) -> &I::Output {
&(**self)[index]
}
}
impl<A: Array, I: SliceIndex<[A::Item]>> ops::IndexMut<I> for SmallVec<A> {
fn index_mut(&mut self, index: I) -> &mut I::Output {
&mut (&mut **self)[index]
}
}
#[allow(deprecated)]
impl<A: Array> ExtendFromSlice<A::Item> for SmallVec<A>
where
A::Item: Copy,
{
fn extend_from_slice(&mut self, other: &[A::Item]) {
SmallVec::extend_from_slice(self, other)
}
}
impl<A: Array> FromIterator<A::Item> for SmallVec<A> {
#[inline]
fn from_iter<I: IntoIterator<Item = A::Item>>(iterable: I) -> SmallVec<A> {
let mut v = SmallVec::new();
v.extend(iterable);
v
}
}
impl<A: Array> Extend<A::Item> for SmallVec<A> {
fn extend<I: IntoIterator<Item = A::Item>>(&mut self, iterable: I) {
let mut iter = iterable.into_iter();
let (lower_size_bound, _) = iter.size_hint();
self.reserve(lower_size_bound);
unsafe {
let (ptr, len_ptr, cap) = self.triple_mut();
let ptr = ptr.as_ptr();
let mut len = SetLenOnDrop::new(len_ptr);
while len.get() < cap {
if let Some(out) = iter.next() {
ptr::write(ptr.add(len.get()), out);
len.increment_len(1);
} else {
return;
}
}
}
for elem in iter {
self.push(elem);
}
}
}
impl<A: Array> fmt::Debug for SmallVec<A>
where
A::Item: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<A: Array> Default for SmallVec<A> {
#[inline]
fn default() -> SmallVec<A> {
SmallVec::new()
}
}
#[cfg(feature = "may_dangle")]
unsafe impl<#[may_dangle] A: Array> Drop for SmallVec<A> {
fn drop(&mut self) {
unsafe {
if self.spilled() {
let (ptr, &mut len) = self.data.heap_mut();
Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity);
} else {
ptr::drop_in_place(&mut self[..]);
}
}
}
}
#[cfg(not(feature = "may_dangle"))]
impl<A: Array> Drop for SmallVec<A> {
fn drop(&mut self) {
unsafe {
if self.spilled() {
let (ptr, &mut len) = self.data.heap_mut();
drop(Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity));
} else {
ptr::drop_in_place(&mut self[..]);
}
}
}
}
impl<A: Array> Clone for SmallVec<A>
where
A::Item: Clone,
{
#[inline]
fn clone(&self) -> SmallVec<A> {
SmallVec::from(self.as_slice())
}
fn clone_from(&mut self, source: &Self) {
self.truncate(source.len());
let (init, tail) = source.split_at(self.len());
self.clone_from_slice(init);
self.extend(tail.iter().cloned());
}
}
impl<A: Array, B: Array> PartialEq<SmallVec<B>> for SmallVec<A>
where
A::Item: PartialEq<B::Item>,
{
#[inline]
fn eq(&self, other: &SmallVec<B>) -> bool {
self[..] == other[..]
}
}
impl<A: Array> Eq for SmallVec<A> where A::Item: Eq {}
impl<A: Array> PartialOrd for SmallVec<A>
where
A::Item: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &SmallVec<A>) -> Option<cmp::Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<A: Array> Ord for SmallVec<A>
where
A::Item: Ord,
{
#[inline]
fn cmp(&self, other: &SmallVec<A>) -> cmp::Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<A: Array> Hash for SmallVec<A>
where
A::Item: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
unsafe impl<A: Array> Send for SmallVec<A> where A::Item: Send {}
pub struct IntoIter<A: Array> {
data: SmallVec<A>,
current: usize,
end: usize,
}
impl<A: Array> fmt::Debug for IntoIter<A>
where
A::Item: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
}
}
impl<A: Array + Clone> Clone for IntoIter<A>
where
A::Item: Clone,
{
fn clone(&self) -> IntoIter<A> {
SmallVec::from(self.as_slice()).into_iter()
}
}
impl<A: Array> Drop for IntoIter<A> {
fn drop(&mut self) {
for _ in self {}
}
}
impl<A: Array> Iterator for IntoIter<A> {
type Item = A::Item;
#[inline]
fn next(&mut self) -> Option<A::Item> {
if self.current == self.end {
None
} else {
unsafe {
let current = self.current;
self.current += 1;
Some(ptr::read(self.data.as_ptr().add(current)))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.end - self.current;
(size, Some(size))
}
}
impl<A: Array> DoubleEndedIterator for IntoIter<A> {
#[inline]
fn next_back(&mut self) -> Option<A::Item> {
if self.current == self.end {
None
} else {
unsafe {
self.end -= 1;
Some(ptr::read(self.data.as_ptr().add(self.end)))
}
}
}
}
impl<A: Array> ExactSizeIterator for IntoIter<A> {}
impl<A: Array> FusedIterator for IntoIter<A> {}
impl<A: Array> IntoIter<A> {
pub fn as_slice(&self) -> &[A::Item] {
let len = self.end - self.current;
unsafe { core::slice::from_raw_parts(self.data.as_ptr().add(self.current), len) }
}
pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
let len = self.end - self.current;
unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().add(self.current), len) }
}
}
impl<A: Array> IntoIterator for SmallVec<A> {
type IntoIter = IntoIter<A>;
type Item = A::Item;
fn into_iter(mut self) -> Self::IntoIter {
unsafe {
let len = self.len();
self.set_len(0);
IntoIter {
data: self,
current: 0,
end: len,
}
}
}
}
impl<'a, A: Array> IntoIterator for &'a SmallVec<A> {
type IntoIter = slice::Iter<'a, A::Item>;
type Item = &'a A::Item;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, A: Array> IntoIterator for &'a mut SmallVec<A> {
type IntoIter = slice::IterMut<'a, A::Item>;
type Item = &'a mut A::Item;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
pub unsafe trait Array {
type Item;
fn size() -> usize;
}
struct SetLenOnDrop<'a> {
len: &'a mut usize,
local_len: usize,
}
impl<'a> SetLenOnDrop<'a> {
#[inline]
fn new(len: &'a mut usize) -> Self {
SetLenOnDrop {
local_len: *len,
len,
}
}
#[inline]
fn get(&self) -> usize {
self.local_len
}
#[inline]
fn increment_len(&mut self, increment: usize) {
self.local_len += increment;
}
}
impl<'a> Drop for SetLenOnDrop<'a> {
#[inline]
fn drop(&mut self) {
*self.len = self.local_len;
}
}
#[cfg(feature = "const_new")]
impl<T, const N: usize> SmallVec<[T; N]> {
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
#[inline]
pub const fn new_const() -> Self {
SmallVec {
capacity: 0,
data: SmallVecData::from_const(MaybeUninit::uninit()),
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
#[inline]
pub const fn from_const(items: [T; N]) -> Self {
SmallVec {
capacity: N,
data: SmallVecData::from_const(MaybeUninit::new(items)),
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
#[inline]
pub const unsafe fn from_const_with_len_unchecked(items: [T; N], len: usize) -> Self {
SmallVec {
capacity: len,
data: SmallVecData::from_const(MaybeUninit::new(items)),
}
}
}
#[cfg(feature = "const_generics")]
#[cfg_attr(docsrs, doc(cfg(feature = "const_generics")))]
unsafe impl<T, const N: usize> Array for [T; N] {
type Item = T;
#[inline]
fn size() -> usize {
N
}
}
#[cfg(not(feature = "const_generics"))]
macro_rules! impl_array(
($($size:expr),+) => {
$(
unsafe impl<T> Array for [T; $size] {
type Item = T;
#[inline]
fn size() -> usize { $size }
}
)+
}
);
#[cfg(not(feature = "const_generics"))]
impl_array!(
0, 1, 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, 28, 29, 30, 31, 32, 36, 0x40, 0x60, 0x80, 0x100, 0x200, 0x400, 0x600, 0x800, 0x1000,
0x2000, 0x4000, 0x6000, 0x8000, 0x10000, 0x20000, 0x40000, 0x60000, 0x80000, 0x10_0000
);
pub trait ToSmallVec<A: Array> {
fn to_smallvec(&self) -> SmallVec<A>;
}
impl<A: Array> ToSmallVec<A> for [A::Item]
where
A::Item: Copy,
{
#[inline]
fn to_smallvec(&self) -> SmallVec<A> {
SmallVec::from_slice(self)
}
}
#[repr(transparent)]
struct ConstNonNull<T>(NonNull<T>);
impl<T> ConstNonNull<T> {
#[inline]
fn new(ptr: *const T) -> Option<Self> {
NonNull::new(ptr as *mut T).map(Self)
}
#[inline]
fn as_ptr(self) -> *const T {
self.0.as_ptr()
}
}
impl<T> Clone for ConstNonNull<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for ConstNonNull<T> {}
#[cfg(feature = "impl_bincode")]
use bincode::{
de::{BorrowDecoder, Decode, Decoder, read::Reader},
enc::{Encode, Encoder, write::Writer},
error::{DecodeError, EncodeError},
BorrowDecode,
};
#[cfg(feature = "impl_bincode")]
impl<A, Context> Decode<Context> for SmallVec<A>
where
A: Array,
A::Item: Decode<Context>,
{
fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
use core::convert::TryInto;
let len = u64::decode(decoder)?;
let len = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
decoder.claim_container_read::<A::Item>(len)?;
let mut vec = SmallVec::with_capacity(len);
if unty::type_equal::<A::Item, u8>() {
let ptr = vec.as_mut_ptr();
unsafe {
core::ptr::write_bytes(ptr, 0, len);
vec.set_len(len);
}
let slice = vec.as_mut_slice();
let slice = unsafe { core::mem::transmute::<&mut [A::Item], &mut [u8]>(slice) };
decoder.reader().read(slice)?;
} else {
for _ in 0..len {
decoder.unclaim_bytes_read(core::mem::size_of::<A::Item>());
vec.push(A::Item::decode(decoder)?);
}
}
Ok(vec)
}
}
#[cfg(feature = "impl_bincode")]
impl<'de, A, Context> BorrowDecode<'de, Context> for SmallVec<A>
where
A: Array,
A::Item: BorrowDecode<'de, Context>,
{
fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
use core::convert::TryInto;
let len = u64::decode(decoder)?;
let len = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
decoder.claim_container_read::<A::Item>(len)?;
let mut vec = SmallVec::with_capacity(len);
if unty::type_equal::<A::Item, u8>() {
let ptr = vec.as_mut_ptr();
unsafe {
core::ptr::write_bytes(ptr, 0, len);
vec.set_len(len);
}
let slice = vec.as_mut_slice();
let slice = unsafe { core::mem::transmute::<&mut [A::Item], &mut [u8]>(slice) };
decoder.reader().read(slice)?;
} else {
for _ in 0..len {
decoder.unclaim_bytes_read(core::mem::size_of::<A::Item>());
vec.push(A::Item::borrow_decode(decoder)?);
}
}
Ok(vec)
}
}
#[cfg(feature = "impl_bincode")]
impl<A> Encode for SmallVec<A>
where
A: Array,
A::Item: Encode,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
(self.len() as u64).encode(encoder)?;
if unty::type_equal::<A::Item, u8>() {
let slice: &[u8] = unsafe { core::mem::transmute(self.as_slice()) };
encoder.writer().write(slice)?;
} else {
for item in self.iter() {
item.encode(encoder)?;
}
}
Ok(())
}
}