makepad/libs/relax/compiler/std/smallvec/lib.rs
Ivanolith1 7bb2047f05 relax: std, core, and x86_64 SIMD intrinsics for test & windowed GUI closure
- Add x86_64 runtime feature detection for cmpxchg16b, movbe, xsave, fxsr, adx, rdrand, and rdseed in std/arch.rs (fearless_simd, pulp).
- Add _MM_FROUND_NO_EXC, _CMP_* constants, and 37 SSE4.2/AVX2 intrinsics in core/arch/x86_64.rs (fearless_simd, tiny_skia, vello_cpu, epaint).
- Add all 12 integer RHS shift impls (Shl, Shr, ShlAssign, ShrAssign) in core/num/prim_traits.rs and gen_num.rs, plus Wrapping<T> ShlAssign/ShrAssign<usize> in wrapping.rs (zmij, skrifa).
- Add core::convert::FloatToInt and f32/f64::to_int_unchecked (num-traits), lossless NonZero<T> From conversions, and unsigned Div/Rem/DivAssign/RemAssign<NonZero<T>> (rav1e, tiny_skia).
- Replace fixed-size smallvec::Array impls with const-generic unsafe impl<T, const N: usize> Array for [T; N], and add SmallVec::new_const and ArrayVec::new_const (idna, kurbo, avif-serialize).
- Add Vec::push_mut, VecDeque::{pop_front_if, pop_back_if, push_back_mut, push_front_mut}, Layout::pad_to_align, ptr::slice_from_raw_parts(_mut), NonNull::slice_from_raw_parts, [T; N]::each_mut, tuple-array From conversions, [u8]::escape_ascii, iter::repeat_n, and From<TryReserveError> for io::Error.
2026-10-25 16:38:29 -05:00

1114 lines
34 KiB
Rust

//! Relax's built-in `smallvec` crate: under Relax the crate path `smallvec` resolves here
//! (crate substitution, coord.md "SV1") instead of compiling libs/smallvec. Behaviour follows
//! smallvec 1.15.1 exactly (inline storage up to the array size, spill policy, capacities,
//! panic messages); the algorithms are ported from it (Copyright (c) 2018 The Servo Project
//! Developers, MIT/Apache-2.0; see libs/relax/compiler/std/CREDITS.md). Dialect form: no
//! macro_rules (`smallvec!` is a Relax built-in that expands per SV2), no features.
//! The rustc path keeps using the real crate; std/check_ext tests this file against it.
extern crate alloc;
use alloc::alloc::Layout;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::borrow::{Borrow, BorrowMut};
use core::cmp;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::{FromIterator, FusedIterator, IntoIterator};
use core::mem;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ops::{self, RangeBounds};
use core::ptr;
use core::slice::{self, SliceIndex};
mod arrays;
/// Error type for APIs with fallible heap allocation.
#[derive(Debug)]
pub enum CollectionAllocErr {
/// Overflow `usize::MAX` or other error during size computation
CapacityOverflow,
/// The allocator return an error
AllocErr {
/// The layout that was passed to the allocator
layout: Layout,
},
}
impl fmt::Display for CollectionAllocErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Allocation error: {:?}", self)
}
}
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 = match mem::size_of::<T>().checked_mul(n) {
Some(s) => s,
None => return Err(CollectionAllocErr::CapacityOverflow),
};
let align = mem::align_of::<T>();
match Layout::from_size_align(size, align) {
Ok(l) => Ok(l),
Err(_) => Err(CollectionAllocErr::CapacityOverflow),
}
}
unsafe fn deallocate<T>(ptr: *mut T, capacity: usize) {
let layout = layout_array::<T>(capacity).unwrap();
alloc::alloc::dealloc(ptr as *mut u8, layout)
}
/// Types that can be used as the backing store for a SmallVec (implemented for `[T; N]` for
/// the same sizes smallvec 1.x implements without its const_generics feature: arrays.rs).
pub unsafe trait Array {
/// The type of the array's elements.
type Item;
/// Returns the number of items the array can hold.
fn size() -> usize;
}
/// Converts a slice of Copy items into a SmallVec.
pub trait ToSmallVec<A: Array> {
/// Construct a new `SmallVec` from a slice.
fn to_smallvec(&self) -> SmallVec<A>;
}
impl<A: Array> ToSmallVec<A> for [A::Item]
where
A::Item: Copy,
{
fn to_smallvec(&self) -> SmallVec<A> {
SmallVec::from_slice(self)
}
}
#[repr(C)]
union SmallVecData<A: Array> {
inline: ManuallyDrop<MaybeUninit<A>>,
heap: (*mut A::Item, usize),
}
impl<A: Array> SmallVecData<A> {
fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
SmallVecData { inline: ManuallyDrop::new(inline) }
}
fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData<A> {
SmallVecData { heap: (ptr, len) }
}
unsafe fn inline(&self) -> *const A::Item {
self.inline.as_ptr() as *const A::Item
}
unsafe fn inline_mut(&mut self) -> *mut A::Item {
self.inline.as_mut_ptr() as *mut A::Item
}
unsafe fn into_inline(self) -> MaybeUninit<A> {
ManuallyDrop::into_inner(self.inline)
}
}
/// A Vec-like container that stores up to `A::size()` items inline.
pub struct SmallVec<A: Array> {
// capacity <= inline_capacity(): inline, and capacity holds the length;
// otherwise heap, and capacity is the allocation's capacity.
capacity: usize,
data: SmallVecData<A>,
}
unsafe impl<A: Array> Send for SmallVec<A> where A::Item: Send {}
unsafe impl<A: Array> Sync for SmallVec<A> where A::Item: Sync {}
impl<T, const N: usize> SmallVec<[T; N]> {
/// Construct an empty vector without a heap allocation.
pub const fn new_const() -> SmallVec<[T; N]> {
SmallVec { capacity: 0, data: SmallVecData { inline: ManuallyDrop::new(MaybeUninit::uninit()) } }
}
}
impl<A: Array> SmallVec<A> {
/// Construct an empty vector
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()) }
}
/// Construct an empty vector with room for at least `n` elements.
pub fn with_capacity(n: usize) -> SmallVec<A> {
let mut v = SmallVec::new();
v.reserve_exact(n);
v
}
/// Construct a new `SmallVec` from a `Vec<A::Item>`.
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(), len);
SmallVec { capacity: len, data }
}
} else {
let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len());
mem::forget(vec);
SmallVec { capacity: cap, data: SmallVecData::from_heap(ptr, len) }
}
}
/// Constructs a new `SmallVec` from an `A` without copying elements.
pub fn from_buf(buf: A) -> SmallVec<A> {
SmallVec { capacity: A::size(), data: SmallVecData::from_inline(MaybeUninit::new(buf)) }
}
/// Constructs a new `SmallVec` from an `A`, with length `len <= A::size()`.
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) }
}
/// Like from_buf_and_len without the length check.
pub unsafe fn from_buf_and_len_unchecked(buf: MaybeUninit<A>, len: usize) -> SmallVec<A> {
SmallVec { capacity: len, data: SmallVecData::from_inline(buf) }
}
/// Sets the length of a vector.
pub unsafe fn set_len(&mut self, new_len: usize) {
*self.len_mut() = new_len;
}
fn inline_capacity() -> usize {
if mem::size_of::<A::Item>() > 0 {
A::size()
} else {
usize::MAX
}
}
/// The maximum number of elements this vector can hold inline
pub fn inline_size(&self) -> usize {
Self::inline_capacity()
}
/// The number of elements stored in the vector
pub fn len(&self) -> usize {
if self.spilled() {
unsafe { self.data.heap.1 }
} else {
self.capacity
}
}
/// Returns `true` if the vector is empty
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// The number of items the vector can hold without reallocating
pub fn capacity(&self) -> usize {
if self.spilled() {
self.capacity
} else {
Self::inline_capacity()
}
}
fn data_ptr(&self) -> *const A::Item {
unsafe {
if self.spilled() {
self.data.heap.0 as *const A::Item
} else {
self.data.inline()
}
}
}
fn data_ptr_mut(&mut self) -> *mut A::Item {
unsafe {
if self.spilled() {
self.data.heap.0
} else {
self.data.inline_mut()
}
}
}
fn len_mut(&mut self) -> &mut usize {
unsafe {
if self.spilled() {
&mut self.data.heap.1
} else {
&mut self.capacity
}
}
}
/// Returns `true` if the data has spilled into a separate heap-allocated buffer.
pub fn spilled(&self) -> bool {
self.capacity > Self::inline_capacity()
}
/// Creates a draining iterator that removes the specified range and yields the removed items.
#[track_caller]
pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> Drain<'_, A> {
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: self as *mut SmallVec<A> }
}
}
/// Append an item to the vector.
pub fn push(&mut self, value: A::Item) {
unsafe {
if self.len() == self.capacity() {
self.reserve_one_unchecked();
}
let len = self.len();
ptr::write(self.data_ptr_mut().add(len), value);
*self.len_mut() = len + 1;
}
}
/// Remove an item from the end of the vector and return it, or None if empty.
pub fn pop(&mut self) -> Option<A::Item> {
unsafe {
let len = self.len();
if len == 0 {
return None;
}
let last_index = len - 1;
*self.len_mut() = last_index;
Some(ptr::read(self.data_ptr().add(last_index)))
}
}
/// Moves all the elements of `other` into `self`, leaving `other` empty.
pub fn append<B: Array<Item = A::Item>>(&mut self, other: &mut SmallVec<B>) {
self.extend(other.drain(..))
}
/// Re-allocate to set the capacity to `max(new_cap, inline_size())`.
pub fn grow(&mut self, new_cap: usize) {
infallible(self.try_grow(new_cap))
}
/// Re-allocate to set the capacity to `max(new_cap, inline_size())`.
pub fn try_grow(&mut self, new_cap: usize) -> Result<(), CollectionAllocErr> {
unsafe {
let unspilled = !self.spilled();
let ptr = self.data_ptr_mut();
let len = self.len();
let cap = self.capacity();
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, self.data.inline_mut(), len);
self.capacity = len;
deallocate(ptr, cap);
} else if new_cap != cap {
let layout = layout_array::<A::Item>(new_cap)?;
let new_alloc: *mut A::Item;
if unspilled {
new_alloc = alloc::alloc::alloc(layout) as *mut A::Item;
if new_alloc.is_null() {
return Err(CollectionAllocErr::AllocErr { layout });
}
ptr::copy_nonoverlapping(ptr, new_alloc, len);
} else {
let old_layout = layout_array::<A::Item>(cap)?;
new_alloc = alloc::alloc::realloc(ptr as *mut u8, old_layout, layout.size()) as *mut A::Item;
if new_alloc.is_null() {
return Err(CollectionAllocErr::AllocErr { layout });
}
}
self.data = SmallVecData::from_heap(new_alloc, len);
self.capacity = new_cap;
}
Ok(())
}
}
/// Reserve capacity for `additional` more elements to be inserted.
pub fn reserve(&mut self, additional: usize) {
infallible(self.try_reserve(additional))
}
#[cold]
fn reserve_one_unchecked(&mut self) {
let new_cap = match self.len().checked_add(1).and_then(usize::checked_next_power_of_two) {
Some(c) => c,
None => panic!("capacity overflow"),
};
infallible(self.try_grow(new_cap))
}
/// Reserve capacity for `additional` more elements to be inserted.
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
let len = self.len();
let cap = self.capacity();
if cap - len >= additional {
return Ok(());
}
let new_cap = match len.checked_add(additional).and_then(usize::checked_next_power_of_two) {
Some(c) => c,
None => return Err(CollectionAllocErr::CapacityOverflow),
};
self.try_grow(new_cap)
}
/// Reserve the minimum capacity for `additional` more elements to be inserted.
pub fn reserve_exact(&mut self, additional: usize) {
infallible(self.try_reserve_exact(additional))
}
/// Reserve the minimum capacity for `additional` more elements to be inserted.
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
let len = self.len();
let cap = self.capacity();
if cap - len >= additional {
return Ok(());
}
let new_cap = match len.checked_add(additional) {
Some(c) => c,
None => return Err(CollectionAllocErr::CapacityOverflow),
};
self.try_grow(new_cap)
}
/// Shrink the capacity of the vector as much as possible.
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, self.data.inline_mut(), len);
deallocate(ptr, self.capacity);
self.capacity = len;
}
} else if self.capacity() > len {
self.grow(len);
}
}
/// Shorten the vector, keeping the first `len` elements and dropping the rest.
pub fn truncate(&mut self, len: usize) {
unsafe {
let ptr = self.data_ptr_mut();
while len < self.len() {
let last_index = self.len() - 1;
*self.len_mut() = last_index;
ptr::drop_in_place(ptr.add(last_index));
}
}
}
/// Extracts a slice containing the entire vector.
pub fn as_slice(&self) -> &[A::Item] {
unsafe { slice::from_raw_parts(self.data_ptr(), self.len()) }
}
/// Extracts a mutable slice of the entire vector.
pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
let len = self.len();
unsafe { slice::from_raw_parts_mut(self.data_ptr_mut(), len) }
}
/// Remove the element at position `index`, replacing it with the last element.
#[track_caller]
pub fn swap_remove(&mut self, index: usize) -> A::Item {
let len = self.len();
self.as_mut_slice().swap(len - 1, index);
match self.pop() {
Some(v) => v,
None => unsafe { core::hint::unreachable_unchecked() },
}
}
/// Remove all elements from the vector.
pub fn clear(&mut self) {
self.truncate(0);
}
/// Remove and return the element at position `index`, shifting the rest left.
#[track_caller]
pub fn remove(&mut self, index: usize) -> A::Item {
unsafe {
let len = self.len();
assert!(index < len);
*self.len_mut() = len - 1;
let ptr = self.data_ptr_mut().add(index);
let item = ptr::read(ptr);
ptr::copy(ptr.add(1), ptr, len - index - 1);
item
}
}
/// Insert an element at position `index`, shifting all elements after it to the right.
#[track_caller]
pub fn insert(&mut self, index: usize, element: A::Item) {
unsafe {
if self.len() == self.capacity() {
self.reserve_one_unchecked();
}
let len = self.len();
if index > len {
panic!("index exceeds length");
}
let ptr = self.data_ptr_mut().add(index);
if index < len {
ptr::copy(ptr, ptr.add(1), len - index);
}
*self.len_mut() = len + 1;
ptr::write(ptr, element);
}
}
/// Insert multiple elements at position `index`, shifting following elements back.
#[track_caller]
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 <= 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 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,
};
ptr::write(ptr.add(num_added), element);
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);
}
for element in iter {
self.insert(index + num_added, element);
num_added += 1;
}
}
/// Convert to a `Vec`, reusing the heap buffer if spilled.
pub fn into_vec(self) -> Vec<A::Item> {
if self.spilled() {
unsafe {
let (ptr, len) = self.data.heap;
let v = Vec::from_raw_parts(ptr, len, self.capacity);
mem::forget(self);
v
}
} else {
self.into_iter().collect()
}
}
/// Converts into a `Box<[A::Item]>`.
pub fn into_boxed_slice(self) -> Box<[A::Item]> {
self.into_vec().into_boxed_slice()
}
/// Convert to the inline array if it is full and not spilled.
pub fn into_inner(self) -> Result<A, SmallVec<A>> {
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())
}
}
}
/// Retains only the elements for which `f` returns true (order preserved).
pub fn retain<F: FnMut(&mut A::Item) -> bool>(&mut self, f: F) {
let mut f = f;
let mut del = 0;
let len = self.len();
let mut i = 0;
while i < len {
if !f(&mut self.as_mut_slice()[i]) {
del += 1;
} else if del > 0 {
self.as_mut_slice().swap(i - del, i);
}
i += 1;
}
self.truncate(len - del);
}
/// Same as `retain` (kept for API compatibility with Vec).
pub fn retain_mut<F: FnMut(&mut A::Item) -> bool>(&mut self, f: F) {
self.retain(f)
}
/// Removes consecutive duplicate elements.
pub fn dedup(&mut self)
where
A::Item: PartialEq<A::Item>,
{
self.dedup_by(|a, b| a == b);
}
/// Removes consecutive elements for which `same_bucket` returns true.
pub fn dedup_by<F: FnMut(&mut A::Item, &mut A::Item) -> bool>(&mut self, same_bucket: F) {
let mut same_bucket = same_bucket;
let len = self.len();
if len <= 1 {
return;
}
let ptr = self.as_mut_ptr();
let mut w: usize = 1;
unsafe {
let mut r = 1;
while r < 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;
}
r += 1;
}
}
self.truncate(w);
}
/// Removes consecutive elements that map to the same key.
pub fn dedup_by_key<K: PartialEq<K>, F: FnMut(&mut A::Item) -> K>(&mut self, key: F) {
let mut key = key;
self.dedup_by(|a, b| key(a) == key(b));
}
/// Resizes to `new_len`, filling new slots with values from `f`.
pub fn resize_with<F: FnMut() -> A::Item>(&mut self, new_len: usize, f: F) {
let old_len = self.len();
if old_len < new_len {
let mut f = f;
let additional = new_len - old_len;
self.reserve(additional);
let mut i = 0;
while i < additional {
self.push(f());
i += 1;
}
} else if old_len > new_len {
self.truncate(new_len);
}
}
/// Creates a `SmallVec` directly from a heap buffer (capacity must exceed the inline size).
#[track_caller]
pub unsafe fn from_raw_parts(ptr: *mut A::Item, length: usize, capacity: usize) -> SmallVec<A> {
assert!(capacity > Self::inline_capacity());
SmallVec { capacity, data: SmallVecData::from_heap(ptr, length) }
}
/// Returns a raw pointer to the vector's buffer.
pub fn as_ptr(&self) -> *const A::Item {
self.data_ptr()
}
/// Returns a raw mutable pointer to the vector's buffer.
pub fn as_mut_ptr(&mut self) -> *mut A::Item {
self.data_ptr_mut()
}
}
impl<A: Array> SmallVec<A>
where
A::Item: Copy,
{
/// Copy the elements from a slice into a new `SmallVec`.
pub fn from_slice(slice: &[A::Item]) -> SmallVec<A> {
let len = slice.len();
if len <= Self::inline_capacity() {
let mut data: MaybeUninit<A> = MaybeUninit::uninit();
unsafe { ptr::copy_nonoverlapping(slice.as_ptr(), data.as_mut_ptr() as *mut A::Item, len) };
SmallVec { capacity: len, data: SmallVecData::from_inline(data) }
} else {
let mut b = slice.to_vec();
let cap = b.capacity();
let ptr = b.as_mut_ptr();
mem::forget(b);
SmallVec { capacity: cap, data: SmallVecData::from_heap(ptr, len) }
}
}
/// Copy elements from a slice into the vector at position `index`.
#[track_caller]
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());
}
}
/// Copy elements from a slice and append them to the vector.
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,
{
/// Resizes the vector so that its length is equal to `len`.
pub fn resize(&mut self, len: usize, value: A::Item) {
let old_len = self.len();
if len > old_len {
self.extend(core::iter::repeat(value).take(len - old_len));
} else {
self.truncate(len);
}
}
/// Creates a `SmallVec` with `n` copies of `elem`.
pub fn from_elem(elem: A::Item, n: usize) -> SmallVec<A> {
if n > Self::inline_capacity() {
{
let mut v = Vec::with_capacity(n);
v.resize(n, elem);
SmallVec::from_vec(v)
}
} else {
let mut v = SmallVec::<A>::new();
unsafe {
let ptr = v.data_ptr_mut();
let mut i = 0;
while i < n {
ptr::write(ptr.add(i), elem.clone());
v.capacity += 1;
i += 1;
}
}
v
}
}
}
impl<A: Array> ops::Deref for SmallVec<A> {
type Target = [A::Item];
fn deref(&self) -> &[A::Item] {
self.as_slice()
}
}
impl<A: Array> ops::DerefMut for SmallVec<A> {
fn deref_mut(&mut self) -> &mut [A::Item] {
self.as_mut_slice()
}
}
impl<A: Array> AsRef<[A::Item]> for SmallVec<A> {
fn as_ref(&self) -> &[A::Item] {
self
}
}
impl<A: Array> AsMut<[A::Item]> for SmallVec<A> {
fn as_mut(&mut self) -> &mut [A::Item] {
self
}
}
impl<A: Array> Borrow<[A::Item]> for SmallVec<A> {
fn borrow(&self) -> &[A::Item] {
self
}
}
impl<A: Array> BorrowMut<[A::Item]> for SmallVec<A> {
fn borrow_mut(&mut self) -> &mut [A::Item] {
self
}
}
impl<'a, A: Array> From<&'a [A::Item]> for SmallVec<A>
where
A::Item: Clone,
{
fn from(slice: &'a [A::Item]) -> SmallVec<A> {
slice.iter().cloned().collect()
}
}
impl<A: Array> From<Vec<A::Item>> for SmallVec<A> {
fn from(vec: Vec<A::Item>) -> SmallVec<A> {
SmallVec::from_vec(vec)
}
}
impl<A: Array> From<A> for SmallVec<A> {
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;
#[track_caller]
fn index(&self, index: I) -> &I::Output {
&(**self)[index]
}
}
impl<A: Array, I: SliceIndex<[A::Item]>> ops::IndexMut<I> for SmallVec<A> {
#[track_caller]
fn index_mut(&mut self, index: I) -> &mut I::Output {
&mut (&mut **self)[index]
}
}
impl<A: Array> FromIterator<A::Item> for SmallVec<A> {
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 cap = self.capacity();
let ptr = self.data_ptr_mut();
let mut len = self.len();
while len < cap {
match iter.next() {
Some(out) => {
ptr::write(ptr.add(len), out);
len += 1;
*self.len_mut() = len;
}
None => 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> {
fn default() -> SmallVec<A> {
SmallVec::new()
}
}
impl<A: Array> Drop for SmallVec<A> {
fn drop(&mut self) {
unsafe {
if self.spilled() {
let (ptr, len) = self.data.heap;
drop(Vec::from_raw_parts(ptr, len, self.capacity));
} else {
ptr::drop_in_place(self.as_mut_slice() as *mut [A::Item]);
}
}
}
}
impl<A: Array> Clone for SmallVec<A>
where
A::Item: Clone,
{
fn clone(&self) -> SmallVec<A> {
SmallVec::from(self.as_slice())
}
fn clone_from(&mut self, source: &SmallVec<A>) {
self.truncate(source.len());
let (init, tail) = source.split_at(self.len());
self.as_mut_slice().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>,
{
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,
{
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,
{
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)
}
}
// ---------------------------------------------------------------- IntoIter
/// An iterator that consumes a `SmallVec` and yields its items by value.
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) {
while let Some(x) = self.next() {
drop(x);
}
}
}
impl<A: Array> Iterator for IntoIter<A> {
type Item = A::Item;
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)))
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.end - self.current;
(size, Some(size))
}
}
impl<A: Array> DoubleEndedIterator for IntoIter<A> {
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> {
/// Returns the remaining items of this iterator as a slice.
pub fn as_slice(&self) -> &[A::Item] {
let len = self.end - self.current;
unsafe { slice::from_raw_parts(self.data.as_ptr().add(self.current), len) }
}
/// Returns the remaining items of this iterator as a mutable slice.
pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
let len = self.end - self.current;
unsafe { 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(self) -> IntoIter<A> {
let mut data = self;
unsafe {
let len = data.len();
data.set_len(0);
IntoIter { data, 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) -> slice::Iter<'a, A::Item> {
self.as_slice().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) -> slice::IterMut<'a, A::Item> {
self.as_mut_slice().iter_mut()
}
}
// ---------------------------------------------------------------- Drain
/// An iterator that removes the items from a `SmallVec` and yields them by value.
pub struct Drain<'a, T: 'a + Array> {
tail_start: usize,
tail_len: usize,
iter: slice::Iter<'a, T::Item>,
vec: *mut 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;
fn next(&mut self) -> Option<T::Item> {
match self.iter.next() {
Some(reference) => Some(unsafe { ptr::read(reference) }),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, T: 'a + Array> DoubleEndedIterator for Drain<'a, T> {
fn next_back(&mut self) -> Option<T::Item> {
match self.iter.next_back() {
Some(reference) => Some(unsafe { ptr::read(reference) }),
None => None,
}
}
}
impl<'a, T: Array> ExactSizeIterator for Drain<'a, T> {}
impl<'a, T: Array> FusedIterator for Drain<'a, T> {}
impl<'a, T: 'a + Array> Drop for Drain<'a, T> {
fn drop(&mut self) {
while let Some(x) = self.next() {
drop(x);
}
if self.tail_len > 0 {
unsafe {
let source_vec = &mut *self.vec;
let start = source_vec.len();
let tail = self.tail_start;
if tail != start {
let ptr = source_vec.as_mut_ptr();
ptr::copy(ptr.add(tail), ptr.add(start), self.tail_len);
}
source_vec.set_len(start + self.tail_len);
}
}
}
}