#![cfg_attr(not(any(doc, feature = "std")), no_std)]
#![cfg_attr(
any(doc, feature = "nightly"),
feature(min_const_generics, unsafe_block_in_unsafe_fn)
)]
#![cfg_attr(
any(doc, feature = "nightly"),
feature(
trusted_len,
min_specialization,
exact_size_is_empty,
allocator_api,
alloc_layout_extra,
const_panic,
const_fn,
const_mut_refs,
const_raw_ptr_deref,
doc_cfg,
)
)]
#![cfg_attr(feature = "nightly", forbid(unsafe_op_in_unsafe_fn))]
#![allow(unused_unsafe)]
#![forbid(missing_docs, clippy::missing_safety_doc)]
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc as std;
use core::{
marker::PhantomData,
mem::MaybeUninit,
ops::{Deref, DerefMut, RangeBounds},
ptr,
};
mod extension;
mod impls;
mod slice;
pub mod iter;
pub mod raw;
use raw::Storage;
#[doc(hidden)]
pub use core;
#[cfg(any(doc, all(feature = "alloc", feature = "nightly")))]
#[cfg_attr(doc, doc(cfg(all(feature = "alloc", feature = "nightly"))))]
pub type HeapVec<T, A = std::alloc::Global> = GenericVec<T, raw::Heap<T, A>>;
#[cfg(all(not(doc), feature = "alloc", not(feature = "nightly")))]
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
pub type HeapVec<T> = GenericVec<T, raw::Heap<T>>;
#[cfg(any(doc, feature = "nightly"))]
#[cfg_attr(doc, doc(cfg(feature = "nightly")))]
pub type ArrayVec<T, const N: usize> = TypeVec<T, [T; N]>;
pub type SliceVec<'a, T> = GenericVec<T, &'a mut raw::UninitSlice<T>>;
#[cfg(any(doc, feature = "nightly"))]
#[cfg_attr(doc, doc(cfg(feature = "nightly")))]
pub type InitArrayVec<T, const N: usize> = GenericVec<T, [T; N]>;
pub type InitSliceVec<'a, T> = GenericVec<T, &'a mut [T]>;
pub type ZSVec<T> = GenericVec<T, raw::ZeroSized<T>>;
pub type TypeVec<T, B, A = T> = GenericVec<T, raw::UninitBuffer<B, A>>;
#[doc(hidden)]
pub mod macros {
pub use core::mem::MaybeUninit;
impl<T> Uninit for T {}
pub trait Uninit: Sized {
const UNINIT: MaybeUninit<Self> = MaybeUninit::uninit();
}
}
#[macro_export]
#[cfg(feature = "nightly")]
macro_rules! gvec {
($expr:expr; $n:expr) => {{
let len = $n;
let mut vec = $crate::GenericVec::with_capacity(len);
vec.grow(len, $expr);
vec
}};
($($expr:expr),*) => {{
let expr = [$($expr),*];
let mut vec = $crate::GenericVec::with_capacity(expr.len());
unsafe { vec.push_array_unchecked(expr); }
vec
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! count {
() => { 0 };
($($a:tt $b:tt)*) => { $crate::count!($($a)*) << 1 };
($c:tt $($a:tt $b:tt)*) => { ($crate::count!($($a)*) << 1) | 1 };
}
#[macro_export]
#[cfg(not(feature = "nightly"))]
macro_rules! gvec {
($expr:expr; $n:expr) => {{
let len = $n;
let mut vec = $crate::GenericVec::with_capacity(len);
vec.grow(len, $expr);
vec
}};
($($expr:expr),*) => {{
let mut vec = $crate::GenericVec::with_capacity($crate::count!($(($expr))*));
unsafe {
$(vec.push_unchecked($expr);)*
}
vec
}};
}
#[macro_export]
macro_rules! uninit_array {
(const $n:expr) => {
[$crate::macros::Uninit::UNINIT; $n]
};
($n:expr) => {
unsafe { $crate::macros::MaybeUninit::<[$crate::macros::MaybeUninit<_>; $n]>::uninit().assume_init() }
};
}
#[macro_export]
macro_rules! save_spare {
($spare:expr, $orig:expr) => {{
let spare: $crate::SliceVec<_> = $spare;
let spare = $crate::core::mem::ManuallyDrop::new(spare);
let len = spare.len();
let ptr = spare.as_ptr();
let orig: &mut $crate::GenericVec<_, _> = $orig;
$crate::validate_spare(ptr, orig);
let len = len + orig.len();
$orig.set_len_unchecked(len);
}};
}
#[doc(hidden)]
pub fn validate_spare<T>(spare_ptr: *const T, orig: &[T]) {
debug_assert!(
unsafe { orig.as_ptr().add(orig.len()) == spare_ptr },
"Tried to use `save_spare!` with a `SliceVec` that was not obtained from `GenricVec::spare_capacity_mut`. \
This is undefined behavior on release mode!"
)
}
#[macro_export]
macro_rules! ArrayVec {
($type:ty; $len:expr) => {
$crate::GenericVec<$type, $crate::raw::UninitBuffer<[$type; $len]>>
};
}
#[macro_export]
macro_rules! InitArrayVec {
($type:ty; $len:expr) => {
$crate::GenericVec<$type, [$type; $len]>
};
}
#[repr(C)]
pub struct GenericVec<T, S: ?Sized + Storage<T>> {
mark: PhantomData<T>,
len: usize,
storage: S,
}
impl<T, S: ?Sized + Storage<T>> Deref for GenericVec<T, S> {
type Target = [T];
fn deref(&self) -> &Self::Target {
let len = self.len();
unsafe { core::slice::from_raw_parts(self.as_ptr(), len) }
}
}
impl<T, S: ?Sized + Storage<T>> DerefMut for GenericVec<T, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
let len = self.len();
unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), len) }
}
}
impl<T, S: ?Sized + Storage<T>> Drop for GenericVec<T, S> {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.as_mut_slice()) }
}
}
#[cfg(not(feature = "nightly"))]
impl<T, S: Storage<T>> GenericVec<T, S> {
pub fn with_storage(storage: S) -> Self {
assert!(S::IS_ALIGNED, "The storage must be aligned to `T`");
Self {
storage,
len: 0,
mark: PhantomData,
}
}
}
#[cfg(feature = "nightly")]
impl<T, S: Storage<T>> GenericVec<T, S> {
pub const fn with_storage(storage: S) -> Self {
assert!(S::IS_ALIGNED, "The storage must be aligned to `T`");
Self {
storage,
len: 0,
mark: PhantomData,
}
}
}
impl<T, S: raw::StorageWithCapacity<T>> GenericVec<T, S> {
pub fn with_capacity(capacity: usize) -> Self { Self::with_storage(S::with_capacity(capacity)) }
#[inline]
#[allow(non_snake_case)]
fn __with_capacity__const_capacity_checked(capacity: usize, old_capacity: Option<usize>) -> Self {
Self::with_storage(S::__with_capacity__const_capacity_checked(capacity, old_capacity))
}
}
impl<T, B> TypeVec<T, B, T> {
pub const fn new() -> Self { Self::with_align() }
}
impl<T, B, A> TypeVec<T, B, A> {
pub const fn with_align() -> Self {
#[cfg(not(feature = "nightly"))]
#[allow(clippy::no_effect)]
{
[()][(!<raw::UninitBuffer<B, A> as raw::Storage<T>>::IS_ALIGNED) as usize];
}
#[cfg(feature = "nightly")]
{
assert!(
<raw::UninitBuffer<B, A> as raw::Storage<T>>::IS_ALIGNED,
"Your buffer is not sufficiently aligned"
)
}
Self {
len: 0,
storage: raw::UninitBuffer::uninit(),
mark: PhantomData,
}
}
}
#[cfg(any(doc, feature = "nightly"))]
#[cfg_attr(doc, doc(cfg(feature = "nightly")))]
impl<T, const N: usize> ArrayVec<T, N> {
pub const fn from_array(array: [T; N]) -> Self {
Self {
len: 0,
mark: PhantomData,
storage: raw::UninitBuffer::new(array),
}
}
pub fn into_array(self) -> [T; N] {
assert!(self.is_full());
let this = core::mem::ManuallyDrop::new(self);
unsafe { Storage::<[T; N]>::as_ptr(&this.storage).read() }
}
}
#[cfg(feature = "nightly")]
#[cfg_attr(doc, doc(cfg(feature = "nightly")))]
impl<T: Copy, const N: usize> InitArrayVec<T, N> {
pub fn new(storage: [T; N]) -> Self {
Self {
len: N,
mark: PhantomData,
storage,
}
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
impl<T> HeapVec<T> {
pub const fn new() -> Self {
Self {
len: 0,
mark: PhantomData,
storage: raw::Heap::new(),
}
}
}
#[cfg(any(doc, all(feature = "nightly", feature = "alloc")))]
#[cfg_attr(doc, doc(cfg(all(feature = "nightly", feature = "alloc"))))]
impl<T, A: std::alloc::AllocRef> HeapVec<T, A> {
pub fn with_alloc(alloc: A) -> Self { Self::with_storage(raw::Heap::with_alloc(alloc)) }
}
#[cfg(any(doc, not(feature = "nightly")))]
impl<'a, T> SliceVec<'a, T> {
pub fn new(slice: &'a mut [MaybeUninit<T>]) -> Self { Self::with_storage(raw::UninitSlice::from_mut(slice)) }
}
#[cfg(any(doc, feature = "nightly"))]
impl<'a, T> SliceVec<'a, T> {
pub const fn new(slice: &'a mut [MaybeUninit<T>]) -> Self { Self::with_storage(raw::UninitSlice::from_mut(slice)) }
}
#[cfg(any(doc, not(feature = "nightly")))]
impl<'a, T: Copy> InitSliceVec<'a, T> {
pub fn new(storage: &'a mut [T]) -> Self {
Self {
len: storage.len(),
storage,
mark: PhantomData,
}
}
}
#[cfg(feature = "nightly")]
impl<'a, T: Copy> InitSliceVec<'a, T> {
pub const fn new(storage: &'a mut [T]) -> Self {
Self {
len: storage.len(),
storage,
mark: PhantomData,
}
}
}
impl<T, S: Storage<T>> GenericVec<T, S> {
pub fn into_raw_parts(self) -> (usize, S) {
let this = core::mem::ManuallyDrop::new(self);
unsafe { (this.len, core::ptr::read(&this.storage)) }
}
#[cfg(not(feature = "nightly"))]
pub unsafe fn from_raw_parts(len: usize, storage: S) -> Self {
Self {
storage,
len,
mark: PhantomData,
}
}
}
#[cfg(feature = "nightly")]
impl<T, S: Storage<T>> GenericVec<T, S> {
pub const unsafe fn from_raw_parts(len: usize, storage: S) -> Self {
Self {
storage,
len,
mark: PhantomData,
}
}
}
impl<T> ZSVec<T> {
pub const NEW: Self = Self {
len: 0,
storage: raw::ZeroSized::NEW,
mark: PhantomData,
};
pub const fn new() -> Self { Self::NEW }
}
impl<T, S: ?Sized + Storage<T>> GenericVec<T, S> {
pub fn as_ptr(&self) -> *const T { self.storage.as_ptr() }
pub fn as_mut_ptr(&mut self) -> *mut T { self.storage.as_mut_ptr() }
pub fn len(&self) -> usize { self.len }
pub fn capacity(&self) -> usize {
if core::mem::size_of::<T>() == 0 {
isize::MAX as usize
} else {
self.storage.capacity()
}
}
pub fn is_empty(&self) -> bool { self.len() == 0 }
pub fn is_full(&self) -> bool { self.len() == self.capacity() }
pub fn remaining_capacity(&self) -> usize { self.capacity().wrapping_sub(self.len()) }
pub unsafe fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
pub fn set_len(&mut self, len: usize)
where
S: raw::StorageInit<T>,
{
unsafe {
assert!(
len <= self.capacity(),
"Tried to set the length to larger than the capacity"
);
self.set_len_unchecked(len);
}
}
pub fn as_slice(&self) -> &[T] { self }
pub fn as_mut_slice(&mut self) -> &mut [T] { self }
pub fn storage(&self) -> &S { &self.storage }
pub unsafe fn storage_mut(&mut self) -> &mut S { &mut self.storage }
pub fn spare_capacity_mut(&mut self) -> SliceVec<'_, T> {
unsafe {
let len = self.len();
let cap = self.capacity();
SliceVec::new(core::slice::from_raw_parts_mut(
self.storage.as_mut_ptr().add(len).cast(),
cap.wrapping_sub(len),
))
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
#[cold]
#[inline(never)]
fn allocation_failure(additional: usize) -> ! {
panic!("Tried to allocate: {} more space and failed", additional)
}
if self.remaining_capacity() < additional {
self.storage.reserve(match self.len().checked_add(additional) {
Some(new_capacity) => new_capacity,
None => allocation_failure(additional),
})
}
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> bool {
if self.remaining_capacity() < additional {
match self.len().checked_add(additional) {
Some(new_capacity) => self.storage.try_reserve(new_capacity),
None => false,
}
} else {
true
}
}
pub fn truncate(&mut self, len: usize) {
if let Some(diff) = self.len().checked_sub(len) {
unsafe {
self.set_len_unchecked(len);
let ptr = self.as_mut_ptr().add(len);
let len = diff;
core::ptr::drop_in_place(core::slice::from_raw_parts_mut(ptr, len));
}
}
}
pub fn grow(&mut self, additional: usize, value: T)
where
T: Clone,
{
self.reserve(additional);
unsafe { extension::Extension::grow(self, additional, value) }
}
pub fn grow_with<F>(&mut self, additional: usize, mut value: F)
where
F: FnMut() -> T,
{
self.reserve(additional);
let mut writer = self.spare_capacity_mut();
for _ in 0..additional {
unsafe {
writer.push_unchecked(value());
}
}
unsafe {
save_spare!(writer, self);
}
}
pub fn resize(&mut self, new_len: usize, value: T)
where
T: Clone,
{
match new_len.checked_sub(self.len()) {
Some(0) => (),
Some(additional) => self.grow(additional, value),
None => self.truncate(new_len),
}
}
pub fn resize_with<F: FnMut() -> T>(&mut self, new_len: usize, value: F) {
match new_len.checked_sub(self.len()) {
Some(0) => (),
Some(additional) => self.grow_with(additional, value),
None => self.truncate(new_len),
}
}
pub fn clear(&mut self) { self.truncate(0); }
pub fn push(&mut self, value: T) -> &mut T {
if self.len() == self.capacity() {
self.reserve(1);
}
unsafe { self.push_unchecked(value) }
}
#[cfg(any(doc, feature = "nightly"))]
pub fn push_array<const N: usize>(&mut self, value: [T; N]) -> &mut [T; N] {
self.reserve(N);
unsafe { self.push_array_unchecked(value) }
}
pub fn insert(&mut self, index: usize, value: T) -> &mut T {
#[cold]
#[inline(never)]
fn insert_fail(index: usize, len: usize) -> ! {
panic!("Tried to insert at {}, but length is {}", index, len);
}
if index > self.len() {
insert_fail(index, self.len())
}
if self.is_full() {
self.reserve(1);
}
unsafe { self.insert_unchecked(index, value) }
}
#[cfg(any(doc, feature = "nightly"))]
pub fn insert_array<const N: usize>(&mut self, index: usize, value: [T; N]) -> &mut [T; N] {
#[cold]
#[inline(never)]
fn insert_array_fail(index: usize, size: usize, len: usize) -> ! {
panic!(
"Tried to insert array of length {} at {}, but length is {}",
size, index, len
);
}
if index > self.len() {
insert_array_fail(index, N, self.len())
}
self.reserve(N);
unsafe { self.insert_array_unchecked(index, value) }
}
pub fn pop(&mut self) -> T {
#[cold]
#[inline(never)]
fn pop_fail() -> ! {
panic!("Tried to pop an element from an empty vector",);
}
if self.is_empty() {
pop_fail()
}
unsafe { self.pop_unchecked() }
}
#[cfg(any(doc, feature = "nightly"))]
pub fn pop_array<const N: usize>(&mut self) -> [T; N] {
#[cold]
#[inline(never)]
fn pop_array_fail(size: usize, len: usize) -> ! {
panic!("Tried to pop an array of size {}, a vector of length {}", size, len);
}
if self.len() < N {
pop_array_fail(N, self.len())
}
unsafe { self.pop_array_unchecked() }
}
pub fn remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn remove_fail(index: usize, len: usize) -> ! {
panic!("Tried to remove an element at {}, but length is {}", index, len);
}
if index > self.len() {
remove_fail(index, self.len())
}
unsafe { self.remove_unchecked(index) }
}
#[cfg(any(doc, feature = "nightly"))]
pub fn remove_array<const N: usize>(&mut self, index: usize) -> [T; N] {
#[cold]
#[inline(never)]
fn remove_array_fail(index: usize, size: usize, len: usize) -> ! {
panic!(
"Tried to remove an array length {} at {}, but length is {}",
size, index, len
);
}
if self.len() < index || self.len().wrapping_sub(index) < N {
remove_array_fail(index, N, self.len())
}
unsafe { self.remove_array_unchecked(index) }
}
pub fn swap_remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn swap_remove_fail(index: usize, len: usize) -> ! {
panic!("Tried to remove an element at {}, but length is {}", index, len);
}
if index > self.len() {
swap_remove_fail(index, self.len())
}
unsafe { self.swap_remove_unchecked(index) }
}
pub fn try_push(&mut self, value: T) -> Result<&mut T, T> {
if self.is_full() {
Err(value)
} else {
unsafe { Ok(self.push_unchecked(value)) }
}
}
#[cfg(any(doc, feature = "nightly"))]
pub fn try_push_array<const N: usize>(&mut self, value: [T; N]) -> Result<&mut [T; N], [T; N]> {
if self.remaining_capacity() < N {
Err(value)
} else {
unsafe { Ok(self.push_array_unchecked(value)) }
}
}
pub fn try_insert(&mut self, index: usize, value: T) -> Result<&mut T, T> {
if self.is_full() || index > self.len() {
Err(value)
} else {
unsafe { Ok(self.insert_unchecked(index, value)) }
}
}
#[cfg(any(doc, feature = "nightly"))]
pub fn try_insert_array<const N: usize>(&mut self, index: usize, value: [T; N]) -> Result<&mut [T; N], [T; N]> {
if self.capacity().wrapping_sub(self.len()) < N || index > self.len() {
Err(value)
} else {
unsafe { Ok(self.insert_array_unchecked(index, value)) }
}
}
pub fn try_pop(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
unsafe { Some(self.pop_unchecked()) }
}
}
#[cfg(any(doc, feature = "nightly"))]
pub fn try_pop_array<const N: usize>(&mut self) -> Option<[T; N]> {
if self.is_empty() {
None
} else {
unsafe { Some(self.pop_array_unchecked()) }
}
}
pub fn try_remove(&mut self, index: usize) -> Option<T> {
if self.len() < index {
None
} else {
unsafe { Some(self.remove_unchecked(index)) }
}
}
#[cfg(any(doc, feature = "nightly"))]
pub fn try_remove_array<const N: usize>(&mut self, index: usize) -> Option<[T; N]> {
if self.len() < index || self.len().wrapping_sub(index) < N {
None
} else {
unsafe { Some(self.remove_array_unchecked(index)) }
}
}
pub fn try_swap_remove(&mut self, index: usize) -> Option<T> {
if index < self.len() {
unsafe { Some(self.swap_remove_unchecked(index)) }
} else {
None
}
}
pub unsafe fn push_unchecked(&mut self, value: T) -> &mut T {
if Some(0) == S::CONST_CAPACITY {
panic!("Tried to push an element into a zero-capacity vector!")
}
debug_assert_ne!(
self.len(),
self.capacity(),
"Tried to `push_unchecked` past capacity! This is UB in release mode"
);
unsafe {
let len = self.len();
self.set_len_unchecked(len.wrapping_add(1));
let ptr = self.as_mut_ptr().add(len);
ptr.write(value);
&mut *ptr
}
}
#[cfg(any(doc, feature = "nightly"))]
pub unsafe fn push_array_unchecked<const N: usize>(&mut self, value: [T; N]) -> &mut [T; N] {
match S::CONST_CAPACITY {
Some(n) if n < N => {
panic!("Tried to push an array larger than the maximum capacity of the vector!")
}
_ => (),
}
unsafe {
let len = self.len();
self.set_len_unchecked(len.wrapping_add(N));
let ptr = self.as_mut_ptr();
let out = ptr.add(len) as *mut [T; N];
out.write(value);
&mut *out
}
}
pub unsafe fn insert_unchecked(&mut self, index: usize, value: T) -> &mut T {
unsafe {
if Some(0) == S::CONST_CAPACITY {
panic!("Tried to insert an element into a zero-capacity vector!")
}
let len = self.len();
self.set_len_unchecked(len.wrapping_add(1));
let ptr = self.storage.as_mut_ptr().add(index);
ptr.add(1).copy_from(ptr, len.wrapping_sub(index));
ptr.write(value);
&mut *ptr
}
}
#[cfg(any(doc, feature = "nightly"))]
pub unsafe fn insert_array_unchecked<const N: usize>(&mut self, index: usize, value: [T; N]) -> &mut [T; N] {
match S::CONST_CAPACITY {
Some(n) if n < N => {
panic!("Tried to push an array larger than the maximum capacity of the vector!")
}
_ => (),
}
unsafe {
let len = self.len();
self.set_len_unchecked(len.wrapping_add(N));
let ptr = self.as_mut_ptr();
let dist = len.wrapping_sub(index);
let out = ptr.add(index);
out.add(N).copy_from(out, dist);
let out = out as *mut [T; N];
out.write(value);
&mut *out
}
}
pub unsafe fn pop_unchecked(&mut self) -> T {
if Some(0) == S::CONST_CAPACITY {
panic!("Tried to remove an element from a zero-capacity vector!")
}
let len = self.len();
debug_assert_ne!(
len, 0,
"Tried to `pop_unchecked` an empty array vec! This is UB in release mode"
);
unsafe {
let len = len.wrapping_sub(1);
self.set_len_unchecked(len);
self.as_mut_ptr().add(len).read()
}
}
#[cfg(any(doc, feature = "nightly"))]
pub unsafe fn pop_array_unchecked<const N: usize>(&mut self) -> [T; N] {
match S::CONST_CAPACITY {
Some(n) if n < N => panic!("Tried to remove {} elements from a {} capacity vector!", N, n),
_ => (),
}
let len = self.len();
debug_assert!(
len > N,
"Tried to remove {} elements from a {} length vector! This is UB in release mode",
N,
len,
);
unsafe {
let len = len.wrapping_sub(N);
self.set_len_unchecked(len);
self.as_mut_ptr().add(len).cast::<[T; N]>().read()
}
}
pub unsafe fn remove_unchecked(&mut self, index: usize) -> T {
if Some(0) == S::CONST_CAPACITY {
panic!("Tried to remove an element from a zero-capacity vector!")
}
let len = self.len();
debug_assert!(
index <= len,
"Tried to remove an element at index {} from a {} length vector! This is UB in release mode",
index,
len,
);
unsafe {
self.set_len_unchecked(len.wrapping_sub(1));
let ptr = self.storage.as_mut_ptr().add(index);
let value = ptr.read();
ptr.copy_from(ptr.add(1), len.wrapping_sub(index).wrapping_sub(1));
value
}
}
#[cfg(any(doc, feature = "nightly"))]
pub unsafe fn remove_array_unchecked<const N: usize>(&mut self, index: usize) -> [T; N] {
match S::CONST_CAPACITY {
Some(n) if n < N => panic!("Tried to remove {} elements from a {} capacity vector!", N, n),
_ => (),
}
let len = self.len();
debug_assert!(
index <= len,
"Tried to remove elements at index {} from a {} length vector! This is UB in release mode",
index,
len,
);
debug_assert!(
len.wrapping_sub(index) > N,
"Tried to remove {} elements from a {} length vector! This is UB in release mode",
N,
len,
);
unsafe {
self.set_len_unchecked(len.wrapping_sub(N));
let ptr = self.as_mut_ptr().add(index);
let value = ptr.cast::<[T; N]>().read();
if N != 0 {
ptr.copy_from(ptr.add(N), len.wrapping_sub(index).wrapping_sub(N));
}
value
}
}
pub unsafe fn swap_remove_unchecked(&mut self, index: usize) -> T {
if Some(0) == S::CONST_CAPACITY {
panic!("Tried to remove an element from a zero-capacity vector!")
}
unsafe {
let len = self.len();
self.set_len_unchecked(len.wrapping_sub(1));
let ptr = self.storage.as_mut_ptr();
let at = ptr.add(index);
let end = ptr.add(len.wrapping_sub(1));
let value = at.read();
at.copy_from(end, 1);
value
}
}
pub fn split_off<B>(&mut self, index: usize) -> GenericVec<T, B>
where
B: raw::StorageWithCapacity<T>,
{
assert!(
index <= self.len(),
"Tried to split at index {}, but length is {}",
index,
self.len()
);
let mut vec = GenericVec::<T, B>::__with_capacity__const_capacity_checked(
self.len().wrapping_sub(index),
S::CONST_CAPACITY,
);
self.split_off_into(index, &mut vec);
vec
}
pub fn split_off_into<B>(&mut self, index: usize, other: &mut GenericVec<T, B>)
where
B: raw::Storage<T> + ?Sized,
{
assert!(
index <= self.len(),
"Tried to split at index {}, but length is {}",
index,
self.len()
);
unsafe {
let slice = self.get_unchecked(index..);
other.reserve(slice.len());
other.extend_from_slice_unchecked(slice);
self.set_len_unchecked(index);
}
}
pub fn append<B: Storage<T> + ?Sized>(&mut self, other: &mut GenericVec<T, B>) { other.split_off_into(0, self) }
pub fn convert<B: raw::StorageWithCapacity<T>>(mut self) -> GenericVec<T, B>
where
S: Sized,
{
self.split_off(0)
}
#[inline]
pub fn raw_cursor<R>(&mut self, range: R) -> iter::RawCursor<'_, T, S>
where
R: RangeBounds<usize>,
{
let range = slice::check_range(self.len(), range);
iter::RawCursor::new(self, range)
}
#[inline]
pub fn cursor<R>(&mut self, range: R) -> iter::Cursor<'_, T, S>
where
R: RangeBounds<usize>,
{
iter::Cursor::new(self.raw_cursor(range))
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> iter::Drain<'_, T, S>
where
R: RangeBounds<usize>,
{
iter::Drain::new(self.raw_cursor(range))
}
#[inline]
pub fn drain_filter<R, F>(&mut self, range: R, f: F) -> iter::DrainFilter<'_, T, S, F>
where
R: RangeBounds<usize>,
F: FnMut(&mut T) -> bool,
{
iter::DrainFilter::new(self.raw_cursor(range), f)
}
#[inline]
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> iter::Splice<'_, T, S, I::IntoIter>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = T>,
{
iter::Splice::new(self.raw_cursor(range), replace_with.into_iter())
}
#[inline]
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&mut T) -> bool,
{
fn not<F: FnMut(&mut T) -> bool, T>(mut f: F) -> impl FnMut(&mut T) -> bool { move |value| !f(value) }
self.drain_filter(.., not(f));
}
pub unsafe fn extend_from_slice_unchecked(&mut self, slice: &[T]) {
debug_assert!(
self.remaining_capacity() >= slice.len(),
"Not enough capacity to hold the slice"
);
unsafe {
let len = self.len();
self.as_mut_ptr()
.add(len)
.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
self.set_len_unchecked(len.wrapping_add(slice.len()));
}
}
pub fn extend_from_slice(&mut self, slice: &[T])
where
T: Clone,
{
self.reserve(self.len());
unsafe { extension::Extension::extend_from_slice(self, slice) }
}
pub fn clone_from(&mut self, source: &[T])
where
T: Clone,
{
self.truncate(source.len());
let (init, tail) = source.split_at(self.len());
self.clone_from_slice(init);
self.extend_from_slice(tail);
}
pub fn dedup_by<F>(&mut self, same_bucket: F)
where
F: FnMut(&mut T, &mut T) -> bool,
{
let (a, _) = slice::partition_dedup_by(self.as_mut_slice(), same_bucket);
let new_len = a.len();
self.truncate(new_len);
}
pub fn dedup_by_key<F, K>(&mut self, key: F)
where
F: FnMut(&mut T) -> K,
K: PartialEq,
{
#[inline]
fn key_to_same_bucket<T, F, K>(mut f: F) -> impl FnMut(&mut T, &mut T) -> bool
where
F: FnMut(&mut T) -> K,
K: PartialEq,
{
#[inline]
move |a, b| {
let a = f(a);
let b = f(b);
a == b
}
}
self.dedup_by(key_to_same_bucket(key))
}
pub fn dedup<F, K>(&mut self)
where
T: PartialEq,
{
#[inline]
fn eq_to_same_buckets<T, F>(mut f: F) -> impl FnMut(&mut T, &mut T) -> bool
where
F: FnMut(&T, &T) -> bool,
{
#[inline]
move |a, b| f(a, b)
}
self.dedup_by(eq_to_same_buckets(PartialEq::eq))
}
}