use alloc::vec::Vec;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut, Index, IndexMut};
use core::ptr;
use core::slice;
use super::types::{
HeapHeader, SmallVec, SmallVecData, TAG_HEAP, TAG_INLINE, TAG_REFERENCED, Variant,
};
impl<T, const N: usize> SmallVec<'_, T, N> {
#[inline]
pub fn new() -> Self {
SmallVec {
tagged_len: SmallVec::<T, N>::encode(TAG_INLINE, 0),
data: SmallVecData {
inline: ManuallyDrop::new(unsafe { MaybeUninit::uninit().assume_init() }),
},
_marker: PhantomData,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
if capacity <= N { Self::new() } else { Self::new_heap(capacity) }
}
}
impl<'a, T, const N: usize> SmallVec<'a, T, N> {
#[inline]
pub fn from_ref(slice: &'a [T]) -> Self {
SmallVec {
tagged_len: Self::encode(TAG_REFERENCED, slice.len()),
data: SmallVecData { referenced: slice.as_ptr() },
_marker: PhantomData,
}
}
pub fn into_owned(self) -> SmallVec<'static, T, N>
where
T: Clone,
{
match self.variant() {
Variant::Inline => {
unsafe {
mem::transmute::<SmallVec<'_, T, N>, SmallVec<'static, T, N>>(self)
}
}
Variant::Referenced => {
let slice = self.as_slice();
let mut owned = if slice.len() <= N {
SmallVec::<'static, T, N>::new()
} else {
SmallVec::<'static, T, N>::new_heap(slice.len())
};
for item in slice {
owned.push(item.clone());
}
mem::forget(self);
owned
}
Variant::Heap => {
unsafe {
mem::transmute::<SmallVec<'_, T, N>, SmallVec<'static, T, N>>(self)
}
}
}
}
}
impl<T, const N: usize> SmallVec<'_, T, N> {
fn new_heap(capacity: usize) -> Self {
let layout = Self::heap_layout(capacity);
let alloc_ptr = unsafe {
let ptr = alloc::alloc::alloc(layout);
if ptr.is_null() {
alloc::alloc::handle_alloc_error(layout);
}
ptr
};
let data_ptr = unsafe { alloc_ptr.add(Self::heap_offset()) as *mut T };
unsafe {
ptr::write(alloc_ptr as *mut HeapHeader, HeapHeader { capacity });
}
SmallVec {
tagged_len: Self::encode(TAG_HEAP, 0),
data: SmallVecData { heap: data_ptr },
_marker: PhantomData,
}
}
}
impl<T, const N: usize> SmallVec<'_, T, N> {
#[inline]
pub fn is_inline(&self) -> bool {
self.tag() == TAG_INLINE
}
#[inline]
pub fn is_referenced(&self) -> bool {
self.tag() == TAG_REFERENCED
}
#[inline]
pub fn len(&self) -> usize {
self.raw_len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.raw_len() == 0
}
#[inline]
pub fn capacity(&self) -> usize {
match self.variant() {
Variant::Inline => N,
Variant::Referenced => self.raw_len(), Variant::Heap => unsafe { Self::header_from_ptr(self.data.heap).capacity },
}
}
#[inline]
pub fn as_slice(&self) -> &[T] {
let (ptr, len) = self.ptr_len();
unsafe { slice::from_raw_parts(ptr, len) }
}
#[inline]
#[track_caller]
pub fn as_mut_slice(&mut self) -> &mut [T] {
assert!(
self.variant() != Variant::Referenced,
"cannot mutably borrow a Referenced SmallVec; call make_mut() first"
);
let len = self.raw_len();
let ptr = self.mut_data_ptr();
unsafe { slice::from_raw_parts_mut(ptr, len) }
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self.ptr_len().0
}
#[inline]
fn ptr_len(&self) -> (*const T, usize) {
let len = self.raw_len();
let ptr = match self.variant() {
Variant::Inline => unsafe { (*self.data.inline).as_ptr() as *const T },
Variant::Referenced => unsafe { self.data.referenced },
Variant::Heap => unsafe { self.data.heap as *const T },
};
(ptr, len)
}
#[inline]
fn mut_data_ptr(&mut self) -> *mut T {
match self.variant() {
Variant::Inline => unsafe { (*self.data.inline).as_mut_ptr() as *mut T },
Variant::Heap => unsafe { self.data.heap },
Variant::Referenced => unreachable!("mut_data_ptr called on Referenced"),
}
}
}
impl<T, const N: usize> SmallVec<'_, T, N> {
#[inline]
pub fn make_mut(&mut self)
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
}
#[cold]
fn materialise_referenced(&mut self)
where
T: Clone,
{
debug_assert!(self.variant() == Variant::Referenced);
let slice = self.as_slice();
let len = slice.len();
if len <= N {
let mut new = Self::new();
for item in slice {
new.push(item.clone());
}
*self = new;
} else {
let mut new = Self::new_heap(len);
let dst = unsafe { new.data.heap };
for (i, item) in slice.iter().enumerate() {
unsafe { ptr::write(dst.add(i), item.clone()) };
}
new.tagged_len = Self::encode(TAG_HEAP, len);
*self = new;
}
}
#[inline]
pub fn push(&mut self, value: T)
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
self.push_owned(value);
}
#[inline]
pub fn push_owned(&mut self, value: T) {
let len = self.raw_len();
match self.variant() {
Variant::Inline => {
if len < N {
unsafe {
let arr = &mut *self.data.inline;
arr[len] = MaybeUninit::new(value);
}
self.tagged_len = Self::encode(TAG_INLINE, len + 1);
} else {
self.spill_and_push(value);
}
}
Variant::Heap => {
let cap = unsafe { Self::header_from_ptr(self.data.heap).capacity };
if len < cap {
unsafe {
ptr::write(self.data.heap.add(len), value);
}
self.tagged_len = Self::encode(TAG_HEAP, len + 1);
} else {
self.grow_and_push(value);
}
}
Variant::Referenced => unreachable!(),
}
}
#[cold]
#[inline(never)]
fn spill_and_push(&mut self, value: T) {
self.spill_with_extra(1);
let len = self.raw_len();
unsafe {
ptr::write(self.data.heap.add(len), value);
}
self.tagged_len = Self::encode(TAG_HEAP, len + 1);
}
#[cold]
#[inline(never)]
fn grow_and_push(&mut self, value: T) {
self.grow_heap(1);
let len = self.raw_len();
unsafe {
ptr::write(self.data.heap.add(len), value);
}
self.tagged_len = Self::encode(TAG_HEAP, len + 1);
}
#[inline]
pub fn pop(&mut self) -> Option<T>
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
let len = self.raw_len();
if len == 0 {
return None;
}
let new_len = len - 1;
let val = unsafe {
let ptr = self.mut_data_ptr();
ptr.add(new_len).read()
};
let tag = self.tag();
self.tagged_len = Self::encode(tag, new_len);
Some(val)
}
#[track_caller]
pub fn insert(&mut self, index: usize, value: T)
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
let len = self.raw_len();
assert!(index <= len, "index out of bounds");
match self.variant() {
Variant::Inline => {
if len >= N {
self.spill_with_extra(1);
}
}
Variant::Heap => {
let cap = unsafe { Self::header_from_ptr(self.data.heap).capacity };
if len >= cap {
self.grow_heap(1);
}
}
Variant::Referenced => unreachable!(),
}
let ptr = self.mut_data_ptr();
unsafe {
let p = ptr.add(index);
ptr::copy(p, p.add(1), len - index);
ptr::write(p, value);
}
let tag = self.tag();
self.tagged_len = Self::encode(tag, len + 1);
}
#[track_caller]
pub fn remove(&mut self, index: usize) -> T
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
let len = self.raw_len();
assert!(index < len, "index out of bounds");
let ptr = self.mut_data_ptr();
let val = unsafe {
let p = ptr.add(index);
let val = p.read();
ptr::copy(p.add(1), p, len - index - 1);
val
};
let tag = self.tag();
self.tagged_len = Self::encode(tag, len - 1);
val
}
#[track_caller]
pub fn swap_remove(&mut self, index: usize) -> T
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
let len = self.raw_len();
assert!(index < len, "index out of bounds");
let ptr = self.mut_data_ptr();
let new_len = len - 1;
let val = unsafe {
let val = ptr.add(index).read();
if index != new_len {
ptr::copy_nonoverlapping(ptr.add(new_len), ptr.add(index), 1);
}
val
};
let tag = self.tag();
self.tagged_len = Self::encode(tag, new_len);
val
}
#[track_caller]
pub fn swap_remove_owned(&mut self, index: usize) -> T {
debug_assert_ne!(self.variant(), Variant::Referenced);
let len = self.raw_len();
assert!(index < len, "index out of bounds");
let ptr = self.mut_data_ptr();
let new_len = len - 1;
let val = unsafe {
let val = ptr.add(index).read();
if index != new_len {
ptr::copy_nonoverlapping(ptr.add(new_len), ptr.add(index), 1);
}
val
};
let tag = self.tag();
self.tagged_len = Self::encode(tag, new_len);
val
}
#[inline]
pub fn clear(&mut self) {
match self.variant() {
Variant::Inline => {
let len = self.raw_len();
let ptr = unsafe { (*self.data.inline).as_mut_ptr() as *mut T };
self.tagged_len = Self::encode(TAG_INLINE, 0);
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(ptr, len));
}
}
Variant::Referenced => {
self.tagged_len = Self::encode(TAG_INLINE, 0);
self.data = SmallVecData {
inline: ManuallyDrop::new(unsafe {
MaybeUninit::uninit().assume_init()
}),
};
}
Variant::Heap => {
let len = self.raw_len();
let ptr = unsafe { self.data.heap };
self.tagged_len = Self::encode(TAG_HEAP, 0);
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(ptr, len));
}
}
}
}
pub fn truncate(&mut self, new_len: usize)
where
T: Clone,
{
let old_len = self.raw_len();
if new_len >= old_len {
return;
}
if self.variant() == Variant::Referenced {
self.tagged_len = Self::encode(TAG_REFERENCED, new_len);
return;
}
let ptr = self.mut_data_ptr();
let tag = self.tag();
self.tagged_len = Self::encode(tag, new_len);
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
ptr.add(new_len),
old_len - new_len,
));
}
}
#[inline]
pub fn reserve(&mut self, additional: usize)
where
T: Clone,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
let len = self.raw_len();
let needed = len + additional;
match self.variant() {
Variant::Inline => {
if needed > N {
self.spill_with_extra(additional);
}
}
Variant::Heap => {
let cap = unsafe { Self::header_from_ptr(self.data.heap).capacity };
if needed > cap {
self.grow_heap(additional);
}
}
Variant::Referenced => unreachable!(),
}
}
pub fn retain<F>(&mut self, mut f: F)
where
T: Clone,
F: FnMut(&T) -> bool,
{
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
let ptr = self.mut_data_ptr();
let mut len = self.raw_len();
let tag = self.tag();
let mut i = 0;
while i < len {
let keep = unsafe { f(&*ptr.add(i)) };
if keep {
i += 1;
} else {
unsafe {
ptr::drop_in_place(ptr.add(i));
ptr::copy(ptr.add(i + 1), ptr.add(i), len - i - 1);
}
len -= 1;
self.tagged_len = Self::encode(tag, len);
}
}
self.tagged_len = Self::encode(tag, len);
}
pub fn extend_from_slice(&mut self, slice: &[T])
where
T: Clone,
{
if slice.is_empty() {
return;
}
self.reserve(slice.len());
let len = self.raw_len();
let dst = unsafe { self.mut_data_ptr().add(len) };
let mut cloned = 0usize;
struct CloneGuard<T> {
dst: *mut T,
cloned: *mut usize,
}
impl<T> Drop for CloneGuard<T> {
fn drop(&mut self) {
let n = unsafe { *self.cloned };
if n > 0 {
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.dst, n));
}
}
}
}
let guard = CloneGuard { dst, cloned: &mut cloned };
#[allow(unused_assignments)] for (i, item) in slice.iter().enumerate() {
unsafe {
dst.add(i).write(item.clone());
}
cloned += 1;
}
mem::forget(guard);
let tag = self.tag();
self.tagged_len = Self::encode(tag, len + slice.len());
}
#[track_caller]
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, N>
where
R: core::ops::RangeBounds<usize>,
{
use core::ops::Bound;
assert!(
self.variant() != Variant::Referenced,
"cannot drain a Referenced SmallVec"
);
let len = self.raw_len();
let start = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&n) => n + 1,
Bound::Excluded(&n) => n,
Bound::Unbounded => len,
};
assert!(start <= end && end <= len, "drain range out of bounds");
let tag = self.tag();
self.tagged_len = Self::encode(tag, start);
#[allow(clippy::unnecessary_cast)]
let vec_static: &mut SmallVec<'static, T, N> = unsafe {
&mut *(self as *mut SmallVec<'_, T, N> as *mut SmallVec<'static, T, N>)
};
Drain {
vec: vec_static,
drain_start: start,
drain_end: end,
original_len: len,
current: start,
}
}
fn spill_with_extra(&mut self, extra: usize) {
debug_assert!(self.variant() == Variant::Inline);
let len = self.raw_len();
let new_cap = (len + extra).max(N * 2);
let layout = Self::heap_layout(new_cap);
let alloc_ptr = unsafe {
let p = alloc::alloc::alloc(layout);
if p.is_null() {
alloc::alloc::handle_alloc_error(layout);
}
p
};
let data_ptr = unsafe { alloc_ptr.add(Self::heap_offset()) as *mut T };
unsafe {
let src = (*self.data.inline).as_ptr() as *const T;
ptr::copy_nonoverlapping(src, data_ptr, len);
ptr::write(alloc_ptr as *mut HeapHeader, HeapHeader { capacity: new_cap });
}
self.tagged_len = Self::encode(TAG_HEAP, len);
self.data = SmallVecData { heap: data_ptr };
}
fn grow_heap(&mut self, extra: usize) {
debug_assert!(self.variant() == Variant::Heap);
let len = self.raw_len();
let old_cap = unsafe { Self::header_from_ptr(self.data.heap).capacity };
let new_cap = (len + extra).max(old_cap * 2);
let old_layout = Self::heap_layout(old_cap);
let new_layout = Self::heap_layout(new_cap);
let old_alloc = unsafe { Self::alloc_ptr_from_data(self.data.heap) };
let new_alloc = unsafe {
let p = alloc::alloc::realloc(old_alloc, old_layout, new_layout.size());
if p.is_null() {
alloc::alloc::handle_alloc_error(new_layout);
}
p
};
let data_ptr = unsafe { new_alloc.add(Self::heap_offset()) as *mut T };
unsafe {
(*(new_alloc as *mut HeapHeader)).capacity = new_cap;
}
self.data = SmallVecData { heap: data_ptr };
}
pub fn into_vec(mut self) -> Vec<T>
where
T: Clone,
{
match self.variant() {
Variant::Referenced => {
let slice = self.as_slice();
let v = slice.to_vec();
mem::forget(self);
v
}
Variant::Inline | Variant::Heap => {
let len = self.raw_len();
let mut v = Vec::with_capacity(len);
let src = self.ptr_len().0;
unsafe {
ptr::copy_nonoverlapping(src, v.as_mut_ptr(), len);
v.set_len(len);
}
let tag = self.tag();
self.tagged_len = Self::encode(tag, 0);
v
}
}
}
}
impl<T, const N: usize> Deref for SmallVec<'_, T, N> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> DerefMut for SmallVec<'_, T, N> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T, const N: usize> AsRef<[T]> for SmallVec<'_, T, N> {
#[inline]
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> Borrow<[T]> for SmallVec<'_, T, N> {
#[inline]
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> Index<usize> for SmallVec<'_, T, N> {
type Output = T;
#[inline]
#[track_caller]
fn index(&self, index: usize) -> &T {
&self.as_slice()[index]
}
}
impl<T, const N: usize> IndexMut<usize> for SmallVec<'_, T, N> {
#[inline]
#[track_caller]
fn index_mut(&mut self, index: usize) -> &mut T {
&mut self.as_mut_slice()[index]
}
}
impl<T: PartialEq, const N: usize> PartialEq for SmallVec<'_, T, N> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: Eq, const N: usize> Eq for SmallVec<'_, T, N> {}
impl<T: PartialEq, const N: usize> PartialEq<[T]> for SmallVec<'_, T, N> {
#[inline]
fn eq(&self, other: &[T]) -> bool {
self.as_slice() == other
}
}
impl<T: PartialEq, const N: usize> PartialEq<Vec<T>> for SmallVec<'_, T, N> {
#[inline]
fn eq(&self, other: &Vec<T>) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: PartialEq, const N: usize, const M: usize> PartialEq<[T; M]>
for SmallVec<'_, T, N>
{
#[inline]
fn eq(&self, other: &[T; M]) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: PartialOrd, const N: usize> PartialOrd for SmallVec<'_, T, N> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<T: Ord, const N: usize> Ord for SmallVec<'_, T, N> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T: Hash, const N: usize> Hash for SmallVec<'_, T, N> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl<T: Clone, const N: usize> Clone for SmallVec<'_, T, N> {
fn clone(&self) -> Self {
match self.variant() {
Variant::Inline => {
let len = self.raw_len();
struct CloneGuard<'a, T> {
data: &'a mut [MaybeUninit<T>],
len: usize,
}
impl<T> Drop for CloneGuard<'_, T> {
fn drop(&mut self) {
for i in 0..self.len {
unsafe { ptr::drop_in_place(self.data[i].as_mut_ptr()) };
}
}
}
let mut new_data: [MaybeUninit<T>; N] =
unsafe { MaybeUninit::uninit().assume_init() };
let mut guard = CloneGuard { data: &mut new_data, len: 0 };
let src = unsafe { &*self.data.inline };
for (i, slot) in src.iter().enumerate().take(len) {
let item = unsafe { slot.assume_init_ref() };
guard.data[i] = MaybeUninit::new(item.clone());
guard.len += 1;
}
mem::forget(guard);
SmallVec {
tagged_len: self.tagged_len,
data: SmallVecData { inline: ManuallyDrop::new(new_data) },
_marker: PhantomData,
}
}
Variant::Referenced => {
SmallVec {
tagged_len: self.tagged_len,
data: SmallVecData { referenced: unsafe { self.data.referenced } },
_marker: PhantomData,
}
}
Variant::Heap => {
let len = self.raw_len();
let mut new = Self::new_heap(len);
let src = unsafe { self.data.heap as *const T };
let dst = unsafe { new.data.heap };
struct CloneGuard<T> {
ptr: *mut T,
len: usize,
}
impl<T> Drop for CloneGuard<T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
self.ptr, self.len,
));
}
}
}
let mut guard = CloneGuard { ptr: dst, len: 0 };
for i in 0..len {
unsafe {
ptr::write(dst.add(i), (*src.add(i)).clone());
}
guard.len += 1;
}
mem::forget(guard);
new.tagged_len = Self::encode(TAG_HEAP, len);
new
}
}
}
}
impl<T, const N: usize> Drop for SmallVec<'_, T, N> {
fn drop(&mut self) {
match self.variant() {
Variant::Inline => {
let len = self.raw_len();
if len > 0 && mem::needs_drop::<T>() {
let ptr = unsafe { (*self.data.inline).as_mut_ptr() as *mut T };
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(ptr, len));
}
}
}
Variant::Referenced => {
}
Variant::Heap => {
let len = self.raw_len();
let data_ptr = unsafe { self.data.heap };
if len > 0 && mem::needs_drop::<T>() {
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(data_ptr, len));
}
}
let cap = unsafe { Self::header_from_ptr(data_ptr).capacity };
let layout = Self::heap_layout(cap);
let alloc_ptr = unsafe { Self::alloc_ptr_from_data(data_ptr) };
unsafe {
alloc::alloc::dealloc(alloc_ptr, layout);
}
}
}
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for SmallVec<'_, T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.as_slice()).finish()
}
}
impl<T, const N: usize> Default for SmallVec<'_, T, N> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T: Clone, const N: usize> From<Vec<T>> for SmallVec<'_, T, N> {
fn from(v: Vec<T>) -> Self {
if v.len() <= N {
let mut sv = SmallVec::new();
for item in &v {
sv.push_owned(item.clone());
}
sv
} else {
let len = v.len();
let mut sv = Self::new_heap(len);
unsafe {
ptr::copy_nonoverlapping(v.as_ptr(), sv.data.heap, len);
}
sv.tagged_len = Self::encode(TAG_HEAP, len);
let mut v = v;
unsafe { v.set_len(0) };
sv
}
}
}
impl<T: Clone, const N: usize> From<&[T]> for SmallVec<'_, T, N> {
fn from(slice: &[T]) -> Self {
let mut sv = SmallVec::with_capacity(slice.len());
sv.extend_from_slice(slice);
sv
}
}
impl<T, const N: usize, const M: usize> From<[T; M]> for SmallVec<'_, T, N> {
fn from(array: [T; M]) -> Self {
if M <= N {
let mut sv = SmallVec::<T, N>::new();
let src = &array as *const [T; M] as *const T;
unsafe {
let dst = (*sv.data.inline).as_mut_ptr() as *mut T;
ptr::copy_nonoverlapping(src, dst, M);
}
sv.tagged_len = Self::encode(TAG_INLINE, M);
mem::forget(array);
sv
} else {
let mut sv = Self::new_heap(M);
let src = &array as *const [T; M] as *const T;
unsafe {
ptr::copy_nonoverlapping(src, sv.data.heap, M);
}
sv.tagged_len = Self::encode(TAG_HEAP, M);
mem::forget(array);
sv
}
}
}
impl<T: Clone, const N: usize> From<SmallVec<'_, T, N>> for Vec<T> {
fn from(sv: SmallVec<'_, T, N>) -> Vec<T> {
sv.into_vec()
}
}
impl<T: Clone, const N: usize> Extend<T> for SmallVec<'_, T, N> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (hint, _) = iter.size_hint();
if hint > 0 {
self.reserve(hint);
}
for item in iter {
self.push_owned(item);
}
}
}
impl<T: Clone, const N: usize> FromIterator<T> for SmallVec<'_, T, N> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut sv = SmallVec::new();
sv.extend(iter);
sv
}
}
impl<'a, T, const N: usize> IntoIterator for &'a SmallVec<'_, T, N> {
type IntoIter = slice::Iter<'a, T>;
type Item = &'a T;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a mut SmallVec<'_, T, N> {
type IntoIter = slice::IterMut<'a, T>;
type Item = &'a mut T;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
}
}
impl<T: Clone, const N: usize> IntoIterator for SmallVec<'_, T, N> {
type IntoIter = IntoIter<T, N>;
type Item = T;
fn into_iter(mut self) -> IntoIter<T, N> {
if self.variant() == Variant::Referenced {
self.materialise_referenced();
}
debug_assert!(self.variant() != Variant::Referenced);
let len = self.raw_len();
let tag = self.tag();
self.tagged_len = Self::encode(tag, 0);
let vec: SmallVec<'static, T, N> = unsafe { mem::transmute(self) };
IntoIter { vec, front: 0, back: len }
}
}
pub struct IntoIter<T, const N: usize> {
vec: SmallVec<'static, T, N>,
front: usize,
back: usize,
}
impl<T, const N: usize> IntoIter<T, N> {
#[inline]
pub fn as_slice(&self) -> &[T] {
let ptr = self.vec.ptr_len().0;
unsafe { slice::from_raw_parts(ptr.add(self.front), self.back - self.front) }
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.front >= self.back {
return None;
}
let ptr = self.vec.ptr_len().0;
let val = unsafe { ptr.add(self.front).read() };
self.front += 1;
Some(val)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.back - self.front;
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.back - self.front
}
}
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
#[inline]
fn next_back(&mut self) -> Option<T> {
if self.back <= self.front {
return None;
}
self.back -= 1;
let ptr = self.vec.ptr_len().0;
Some(unsafe { ptr.add(self.back).read() })
}
}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
impl<T, const N: usize> Drop for IntoIter<T, N> {
fn drop(&mut self) {
if self.back > self.front {
let ptr = self.vec.mut_data_ptr();
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
ptr.add(self.front),
self.back - self.front,
));
}
}
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
}
}
pub struct Drain<'a, T, const N: usize> {
vec: &'a mut SmallVec<'static, T, N>,
drain_start: usize,
drain_end: usize,
original_len: usize,
current: usize,
}
impl<T, const N: usize> Iterator for Drain<'_, T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.current >= self.drain_end {
return None;
}
let ptr = self.vec.ptr_len().0;
let val = unsafe { ptr.add(self.current).read() };
self.current += 1;
Some(val)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.drain_end - self.current;
(len, Some(len))
}
}
impl<T, const N: usize> ExactSizeIterator for Drain<'_, T, N> {}
impl<T, const N: usize> Drop for Drain<'_, T, N> {
fn drop(&mut self) {
if self.current < self.drain_end {
let ptr = self.vec.mut_data_ptr();
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
ptr.add(self.current),
self.drain_end - self.current,
));
}
}
let tail_len = self.original_len - self.drain_end;
if tail_len > 0 {
let ptr = self.vec.mut_data_ptr();
unsafe {
ptr::copy(ptr.add(self.drain_end), ptr.add(self.drain_start), tail_len);
}
}
let new_len = self.drain_start + tail_len;
let tag = self.vec.tag();
self.vec.tagged_len = SmallVec::<T, N>::encode(tag, new_len);
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for Drain<'_, T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr = self.vec.ptr_len().0;
let remaining = unsafe {
slice::from_raw_parts(ptr.add(self.current), self.drain_end - self.current)
};
f.debug_tuple("Drain").field(&remaining).finish()
}
}
extern crate alloc;