use core::{
borrow::{Borrow, BorrowMut},
fmt::Debug,
hash::Hash,
iter,
marker::PhantomData,
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut, Index, IndexMut, RangeBounds},
ptr::{self, NonNull},
slice::{self, SliceIndex},
};
use crate::{
BumpBox, ErrorBehavior, NoDrop, SetLenOnDrop, SizedTypeProperties,
alloc::AllocError,
destructure::destructure,
min_non_zero_cap,
mut_bump_vec::IntoIter,
owned_slice::{OwnedSlice, TakeOwnedSlice},
polyfill::{self, hint::likely, pointer},
traits::{MutBumpAllocatorTyped, MutBumpAllocatorTypedScope},
};
#[cfg(feature = "panic-on-alloc")]
use crate::panic_on_error;
#[macro_export]
macro_rules! mut_bump_vec_rev {
[in $bump:expr] => {
$crate::MutBumpVecRev::new_in($bump)
};
[in $bump:expr; $($values:expr),* $(,)?] => {
$crate::__mut_bump_vec_rev_panic_on_alloc![in $bump; $($values),*]
};
[in $bump:expr; $value:expr; $count:expr] => {
$crate::__mut_bump_vec_rev_panic_on_alloc![in $bump; $value; $count]
};
[try in $bump:expr] => {
Ok::<_, $crate::alloc::AllocError>($crate::MutBumpVecRev::new_in($bump))
};
[try in $bump:expr; $($values:expr),* $(,)?] => {
$crate::MutBumpVecRev::try_from_owned_slice_in([$($values),*], $bump)
};
[try in $bump:expr; $value:expr; $count:expr] => {
$crate::MutBumpVecRev::try_from_elem_in($value, $count, $bump)
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(feature = "panic-on-alloc")]
macro_rules! __mut_bump_vec_rev_panic_on_alloc {
[in $bump:expr; $($values:expr),* $(,)?] => {
$crate::MutBumpVecRev::from_owned_slice_in([$($values),*], $bump)
};
[in $bump:expr; $value:expr; $count:expr] => {
$crate::MutBumpVecRev::from_elem_in($value, $count, $bump)
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(feature = "panic-on-alloc"))]
macro_rules! __mut_bump_vec_rev_panic_on_alloc {
[in $bump:expr; $($values:expr),* $(,)?] => {
compile_error!(concat!(
"the potentially panicking api of `mut_bump_vec_rev!` is not available\n",
"help: enable `bump-scope`'s \"panic-on-alloc\" feature or use `try`:\n",
" `mut_bump_vec_rev![try in ",
stringify!($bump),
"; ",
stringify!($($values),*),
"]`"
))
};
[in $bump:expr; $value:expr; $count:expr] => {
compile_error!(concat!(
"the potentially panicking api of `mut_bump_vec_rev!` is not available\n",
"help: enable `bump-scope`'s \"panic-on-alloc\" feature or use `try`:\n",
" `mut_bump_vec_rev![try in ",
stringify!($bump),
"; ",
stringify!($value),
"; ",
stringify!($count),
"]`"
))
};
}
pub struct MutBumpVecRev<T, A> {
pub(crate) end: NonNull<T>,
pub(crate) len: usize,
cap: usize,
allocator: A,
marker: PhantomData<T>,
}
impl<T, A> MutBumpVecRev<T, A> {
#[inline]
pub fn new_in(allocator: A) -> Self {
Self {
end: NonNull::dangling(),
len: 0,
cap: if T::IS_ZST { usize::MAX } else { 0 },
allocator,
marker: PhantomData,
}
}
#[must_use]
#[inline(always)]
pub const fn capacity(&self) -> usize {
self.cap
}
#[must_use]
#[inline(always)]
pub const fn len(&self) -> usize {
self.len
}
#[must_use]
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline(always)]
pub unsafe fn push_unchecked(&mut self, value: T) {
_ = unsafe { self.push_mut_unchecked(value) };
}
#[inline(always)]
#[must_use = "if you don't need a reference to the value, use `push_unchecked` instead"]
pub unsafe fn push_mut_unchecked(&mut self, value: T) -> &mut T {
debug_assert!(self.len < self.cap);
self.len += 1;
unsafe {
let mut ptr = self.end.sub(self.len);
ptr.write(value);
ptr.as_mut()
}
}
#[inline(always)]
#[deprecated = "use `push_unchecked(f())` instead"]
pub unsafe fn push_with_unchecked(&mut self, f: impl FnOnce() -> T) {
unsafe { self.push_unchecked(f()) };
}
#[inline(always)]
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
let ptr = self.as_ptr();
self.len -= 1;
Some(ptr.read())
}
}
}
pub fn pop_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
let last = self.first_mut()?;
if predicate(last) { self.pop() } else { None }
}
#[inline(always)]
pub fn clear(&mut self) {
let elems: *mut [T] = self.as_mut_slice();
unsafe {
self.len = 0;
ptr::drop_in_place(elems);
}
}
#[must_use]
#[inline(always)]
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
}
#[must_use]
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
}
#[inline]
#[must_use]
pub fn as_ptr(&self) -> *const T {
self.as_non_null().as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.as_non_null().as_ptr()
}
#[must_use]
#[inline(always)]
pub const fn as_non_null(&self) -> NonNull<T> {
unsafe { self.end.sub(self.len) }
}
pub fn truncate(&mut self, len: usize) {
unsafe {
if len >= self.len {
return;
}
let remaining_len = self.len - len;
let ptr = self.as_mut_ptr();
let slice = ptr::slice_from_raw_parts_mut(ptr, remaining_len);
self.len = len;
slice.drop_in_place();
}
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.cap);
self.len = new_len;
}
#[inline]
pub(crate) unsafe fn inc_len(&mut self, amount: usize) {
self.len += amount;
}
#[inline(always)]
fn into_raw_parts(self) -> (NonNull<T>, usize, usize, A) {
destructure!(let Self { end, len, cap, allocator } = self);
(end, len, cap, allocator)
}
#[inline(always)]
unsafe fn from_raw_parts(end: NonNull<T>, len: usize, cap: usize, allocator: A) -> Self {
Self {
end,
len,
cap,
allocator,
marker: PhantomData,
}
}
}
impl<T, A: MutBumpAllocatorTyped> MutBumpVecRev<T, A> {
#[must_use]
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn with_capacity_in(capacity: usize, allocator: A) -> Self {
panic_on_error(Self::generic_with_capacity_in(capacity, allocator))
}
#[inline(always)]
pub fn try_with_capacity_in(capacity: usize, allocator: A) -> Result<Self, AllocError> {
Self::generic_with_capacity_in(capacity, allocator)
}
#[inline]
pub(crate) fn generic_with_capacity_in<E: ErrorBehavior>(capacity: usize, allocator: A) -> Result<Self, E> {
let mut allocator = allocator;
if T::IS_ZST {
return Ok(Self {
end: NonNull::dangling(),
len: 0,
cap: usize::MAX,
allocator,
marker: PhantomData,
});
}
if capacity == 0 {
return Ok(Self {
end: NonNull::dangling(),
len: 0,
cap: 0,
allocator,
marker: PhantomData,
});
}
let (end, cap) = unsafe { E::prepare_slice_allocation_rev::<T>(&mut allocator, capacity)? };
Ok(Self {
end,
len: 0,
cap,
allocator,
marker: PhantomData,
})
}
#[must_use]
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn from_elem_in(value: T, count: usize, allocator: A) -> Self
where
T: Clone,
{
panic_on_error(Self::generic_from_elem_in(value, count, allocator))
}
#[inline(always)]
pub fn try_from_elem_in(value: T, count: usize, allocator: A) -> Result<Self, AllocError>
where
T: Clone,
{
Self::generic_from_elem_in(value, count, allocator)
}
#[inline]
pub(crate) fn generic_from_elem_in<E: ErrorBehavior>(value: T, count: usize, allocator: A) -> Result<Self, E>
where
T: Clone,
{
let mut vec = Self::generic_with_capacity_in(count, allocator)?;
unsafe {
if count != 0 {
for _ in 0..(count - 1) {
vec.push_unchecked(value.clone());
}
vec.push_unchecked(value);
}
}
Ok(vec)
}
#[must_use]
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn from_owned_slice_in(owned_slice: impl OwnedSlice<Item = T>, allocator: A) -> Self {
panic_on_error(Self::generic_from_owned_slice_in(owned_slice, allocator))
}
#[inline(always)]
pub fn try_from_owned_slice_in(owned_slice: impl OwnedSlice<Item = T>, allocator: A) -> Result<Self, AllocError> {
Self::generic_from_owned_slice_in(owned_slice, allocator)
}
#[inline]
pub(crate) fn generic_from_owned_slice_in<E: ErrorBehavior>(
owned_slice: impl OwnedSlice<Item = T>,
allocator: A,
) -> Result<Self, E> {
let owned_slice = owned_slice.into_take_owned_slice();
let mut this = Self::generic_with_capacity_in(owned_slice.owned_slice_ref().len(), allocator)?;
this.generic_append(owned_slice)?;
Ok(this)
}
#[must_use]
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn from_iter_in<I>(iter: I, allocator: A) -> Self
where
I: IntoIterator<Item = T>,
{
panic_on_error(Self::generic_from_iter_in(iter, allocator))
}
#[inline(always)]
pub fn try_from_iter_in<I>(iter: I, allocator: A) -> Result<Self, AllocError>
where
I: IntoIterator<Item = T>,
{
Self::generic_from_iter_in(iter, allocator)
}
#[inline]
pub(crate) fn generic_from_iter_in<E: ErrorBehavior, I>(iter: I, allocator: A) -> Result<Self, E>
where
I: IntoIterator<Item = T>,
{
let iter = iter.into_iter();
let capacity = iter.size_hint().0;
let mut vec = Self::generic_with_capacity_in(capacity, allocator)?;
for value in iter {
vec.generic_push(value)?;
}
Ok(vec)
}
#[must_use]
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn from_iter_exact_in<I>(iter: I, allocator: A) -> Self
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
panic_on_error(Self::generic_from_iter_exact_in(iter, allocator))
}
#[inline(always)]
pub fn try_from_iter_exact_in<I>(iter: I, allocator: A) -> Result<Self, AllocError>
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
Self::generic_from_iter_exact_in(iter, allocator)
}
#[inline]
pub(crate) fn generic_from_iter_exact_in<E: ErrorBehavior, I>(iter: I, allocator: A) -> Result<Self, E>
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
let mut iter = iter.into_iter();
let len = iter.len();
let mut vec = Self::generic_with_capacity_in(len, allocator)?;
while vec.len() != vec.capacity() {
match iter.next() {
Some(value) => unsafe { vec.push_unchecked(value) },
None => break,
}
}
Ok(vec)
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn push(&mut self, value: T) {
panic_on_error(self.generic_push(value));
}
#[inline(always)]
pub fn try_push(&mut self, value: T) -> Result<(), AllocError> {
self.generic_push(value)
}
#[inline]
pub(crate) fn generic_push<E: ErrorBehavior>(&mut self, value: T) -> Result<(), E> {
self.generic_push_with(|| value)
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn push_with(&mut self, f: impl FnOnce() -> T) {
panic_on_error(self.generic_push_with(f));
}
#[inline(always)]
pub fn try_push_with(&mut self, f: impl FnOnce() -> T) -> Result<(), AllocError> {
self.generic_push_with(f)
}
#[inline]
pub(crate) fn generic_push_with<E: ErrorBehavior>(&mut self, f: impl FnOnce() -> T) -> Result<(), E> {
self.generic_push_mut_with(f).map(drop)
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
#[must_use = "if you don't need a reference to the value, use `push` instead"]
pub fn push_mut(&mut self, value: T) -> &mut T {
panic_on_error(self.generic_push_mut(value))
}
#[inline(always)]
#[must_use = "if you don't need a reference to the value, use `push` instead"]
pub fn try_push_mut(&mut self, value: T) -> Result<&mut T, AllocError> {
self.generic_push_mut(value)
}
#[inline]
pub(crate) fn generic_push_mut<E: ErrorBehavior>(&mut self, value: T) -> Result<&mut T, E> {
self.generic_push_mut_with(|| value)
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
#[must_use = "if you don't need a reference to the value, use `push` instead"]
pub fn push_mut_with(&mut self, f: impl FnOnce() -> T) -> &mut T {
panic_on_error(self.generic_push_mut_with(f))
}
#[inline(always)]
#[must_use = "if you don't need a reference to the value, use `push` instead"]
pub fn try_push_mut_with(&mut self, f: impl FnOnce() -> T) -> Result<&mut T, AllocError> {
self.generic_push_mut_with(f)
}
#[inline]
pub(crate) fn generic_push_mut_with<E: ErrorBehavior>(&mut self, f: impl FnOnce() -> T) -> Result<&mut T, E> {
self.generic_reserve_one()?;
Ok(unsafe { self.push_mut_unchecked(f()) })
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn insert(&mut self, index: usize, element: T) {
panic_on_error(self.generic_insert_mut(index, element));
}
#[inline(always)]
pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), AllocError> {
self.generic_insert_mut(index, element).map(drop)
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
#[must_use = "if you don't need a reference to the value, use `insert` instead"]
pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
panic_on_error(self.generic_insert_mut(index, element))
}
#[inline(always)]
#[must_use = "if you don't need a reference to the value, use `try_insert` instead"]
pub fn try_insert_mut(&mut self, index: usize, element: T) -> Result<&mut T, AllocError> {
self.generic_insert_mut(index, element)
}
#[inline]
pub(crate) fn generic_insert_mut<E: ErrorBehavior>(&mut self, index: usize, element: T) -> Result<&mut T, E> {
#[cold]
#[track_caller]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("insertion index (is {index}) should be <= len (is {len})");
}
if index > self.len {
assert_failed(index, self.len);
}
self.generic_reserve_one()?;
unsafe {
let ptr = if index == 0 {
self.len += 1;
self.as_mut_ptr()
} else {
let start = self.as_mut_ptr();
let start_sub = start.sub(1);
ptr::copy(start, start_sub, index);
self.len += 1;
start_sub.add(index)
};
ptr.write(element);
Ok(&mut *ptr)
}
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn extend_from_slice_copy(&mut self, slice: &[T])
where
T: Copy,
{
panic_on_error(self.generic_extend_from_slice_copy(slice));
}
#[inline(always)]
pub fn try_extend_from_slice_copy(&mut self, slice: &[T]) -> Result<(), AllocError>
where
T: Copy,
{
self.generic_extend_from_slice_copy(slice)
}
#[inline]
pub(crate) fn generic_extend_from_slice_copy<E: ErrorBehavior>(&mut self, slice: &[T]) -> Result<(), E>
where
T: Copy,
{
unsafe { self.extend_by_copy_nonoverlapping(slice) }
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn extend_from_slice_clone(&mut self, slice: &[T])
where
T: Clone,
{
panic_on_error(self.generic_extend_from_slice_clone(slice));
}
#[inline(always)]
pub fn try_extend_from_slice_clone(&mut self, slice: &[T]) -> Result<(), AllocError>
where
T: Clone,
{
self.generic_extend_from_slice_clone(slice)
}
#[inline]
pub(crate) fn generic_extend_from_slice_clone<E: ErrorBehavior>(&mut self, slice: &[T]) -> Result<(), E>
where
T: Clone,
{
self.generic_reserve(slice.len())?;
unsafe {
let src = slice.as_ptr().add(slice.len());
let mut pos = 0usize;
while likely(pos != slice.len()) {
let elem = &*src.sub(pos + 1);
self.push_unchecked(elem.clone());
pos += 1;
}
}
Ok(())
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn extend_from_within_copy<R>(&mut self, src: R)
where
T: Copy,
R: RangeBounds<usize>,
{
panic_on_error(self.generic_extend_from_within_copy(src));
}
#[inline(always)]
pub fn try_extend_from_within_copy<R>(&mut self, src: R) -> Result<(), AllocError>
where
T: Copy,
R: RangeBounds<usize>,
{
self.generic_extend_from_within_copy(src)
}
#[inline]
pub(crate) fn generic_extend_from_within_copy<E: ErrorBehavior, R>(&mut self, src: R) -> Result<(), E>
where
T: Copy,
R: RangeBounds<usize>,
{
let range = polyfill::slice::range(src, ..self.len());
let count = range.len();
self.generic_reserve(count)?;
unsafe {
let ptr = self.as_mut_ptr();
let src = ptr.add(range.start);
let dst = ptr.sub(count);
ptr::copy_nonoverlapping(src, dst, count);
}
self.len += count;
Ok(())
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn extend_from_within_clone<R>(&mut self, src: R)
where
T: Clone,
R: RangeBounds<usize>,
{
panic_on_error(self.generic_extend_from_within_clone(src));
}
#[inline(always)]
pub fn try_extend_from_within_clone<R>(&mut self, src: R) -> Result<(), AllocError>
where
T: Clone,
R: RangeBounds<usize>,
{
self.generic_extend_from_within_clone(src)
}
#[inline]
pub(crate) fn generic_extend_from_within_clone<E: ErrorBehavior, R>(&mut self, src: R) -> Result<(), E>
where
T: Clone,
R: RangeBounds<usize>,
{
let range = polyfill::slice::range(src, ..self.len());
let count = range.len();
self.generic_reserve(count)?;
if T::IS_ZST {
unsafe {
#[expect(clippy::uninit_assumed_init)]
let fake = ManuallyDrop::new(MaybeUninit::<T>::uninit().assume_init());
for _ in 0..count {
self.push_unchecked((*fake).clone());
}
return Ok(());
}
}
unsafe {
let ptr = self.as_mut_ptr();
let mut src = ptr.add(range.end);
let mut dst = ptr;
let src_end = src.sub(count);
while src != src_end {
src = src.sub(1);
dst = dst.sub(1);
dst.write((*src).clone());
self.len += 1;
}
}
Ok(())
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn reserve(&mut self, additional: usize) {
panic_on_error(self.generic_reserve(additional));
}
#[inline(always)]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), AllocError> {
self.generic_reserve(additional)
}
#[inline]
pub(crate) fn generic_reserve<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
if additional > (self.capacity() - self.len()) {
self.generic_grow_amortized(additional)?;
}
Ok(())
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn reserve_exact(&mut self, additional: usize) {
panic_on_error(self.generic_reserve_exact(additional));
}
#[inline(always)]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), AllocError> {
self.generic_reserve_exact(additional)
}
#[inline]
pub(crate) fn generic_reserve_exact<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
if additional > (self.capacity() - self.len()) {
self.generic_grow_exact(additional)?;
}
Ok(())
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn resize(&mut self, new_len: usize, value: T)
where
T: Clone,
{
panic_on_error(self.generic_resize(new_len, value));
}
#[inline(always)]
pub fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), AllocError>
where
T: Clone,
{
self.generic_resize(new_len, value)
}
#[inline]
pub(crate) fn generic_resize<E: ErrorBehavior>(&mut self, new_len: usize, value: T) -> Result<(), E>
where
T: Clone,
{
let len = self.len();
if new_len > len {
self.extend_with(new_len - len, value)
} else {
self.truncate(new_len);
Ok(())
}
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn resize_with<F>(&mut self, new_len: usize, f: F)
where
F: FnMut() -> T,
{
panic_on_error(self.generic_resize_with(new_len, f));
}
#[inline(always)]
pub fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), AllocError>
where
F: FnMut() -> T,
{
self.generic_resize_with(new_len, f)
}
#[inline]
pub(crate) fn generic_resize_with<E: ErrorBehavior, F>(&mut self, new_len: usize, f: F) -> Result<(), E>
where
F: FnMut() -> T,
{
let len = self.len();
if new_len > len {
unsafe { self.extend_trusted(iter::repeat_with(f).take(new_len - len)) }
} else {
self.truncate(new_len);
Ok(())
}
}
#[inline(always)]
#[cfg(feature = "panic-on-alloc")]
pub fn append(&mut self, other: impl OwnedSlice<Item = T>) {
panic_on_error(self.generic_append(other));
}
#[inline(always)]
pub fn try_append(&mut self, other: impl OwnedSlice<Item = T>) -> Result<(), AllocError> {
self.generic_append(other)
}
#[inline]
pub(crate) fn generic_append<E: ErrorBehavior>(&mut self, other: impl OwnedSlice<Item = T>) -> Result<(), E> {
unsafe {
let mut owned_slice = other.into_take_owned_slice();
let slice = NonNull::from(owned_slice.owned_slice_ref());
self.generic_reserve(slice.len())?;
let src = slice.cast::<T>().as_ptr();
let dst = self.end.as_ptr().sub(self.len + slice.len());
ptr::copy_nonoverlapping(src, dst, slice.len());
owned_slice.take_owned_slice();
self.inc_len(slice.len());
Ok(())
}
}
fn extend_with<B: ErrorBehavior>(&mut self, n: usize, value: T) -> Result<(), B>
where
T: Clone,
{
self.generic_reserve(n)?;
unsafe {
let mut ptr = self.as_mut_ptr().sub(1);
let mut local_len = SetLenOnDrop::new(&mut self.len);
for _ in 1..n {
pointer::write_with(ptr, || value.clone());
ptr = ptr.sub(1);
local_len.increment_len(1);
}
if n > 0 {
ptr.write(value);
local_len.increment_len(1);
}
Ok(())
}
}
#[inline(always)]
unsafe fn extend_by_copy_nonoverlapping<E: ErrorBehavior>(&mut self, other: *const [T]) -> Result<(), E> {
unsafe {
let len = other.len();
self.generic_reserve(len)?;
let src = other.cast::<T>();
self.len += len;
let dst = self.as_mut_ptr();
ptr::copy_nonoverlapping(src, dst, len);
Ok(())
}
}
#[inline]
fn generic_reserve_one<E: ErrorBehavior>(&mut self) -> Result<(), E> {
if self.cap == self.len {
self.generic_grow_amortized::<E>(1)?;
}
Ok(())
}
#[cold]
#[inline(never)]
fn generic_grow_amortized<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
if T::IS_ZST {
return Err(E::capacity_overflow());
}
let Some(required_cap) = self.len().checked_add(additional) else {
return Err(E::capacity_overflow())?;
};
let new_cap = (self.capacity() * 2).max(required_cap).max(min_non_zero_cap(T::SIZE));
unsafe { self.generic_grow_to(new_cap) }
}
#[cold]
#[inline(never)]
fn generic_grow_exact<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
if T::IS_ZST {
return Err(E::capacity_overflow());
}
let Some(required_cap) = self.len().checked_add(additional) else {
return Err(E::capacity_overflow());
};
unsafe { self.generic_grow_to(required_cap) }
}
unsafe fn generic_grow_to<E: ErrorBehavior>(&mut self, new_capacity: usize) -> Result<(), E> {
unsafe {
let (end, cap) = E::prepare_slice_allocation_rev::<T>(&mut self.allocator, new_capacity)?;
let src = self.as_mut_ptr();
let dst = end.as_ptr().sub(self.len);
ptr::copy_nonoverlapping(src, dst, self.len);
self.end = end;
self.cap = cap;
Ok(())
}
}
#[track_caller]
pub fn remove(&mut self, index: usize) -> T {
#[cold]
#[track_caller]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("removal index (is {index}) should be < len (is {len})");
}
if index >= self.len {
assert_failed(index, self.len);
}
unsafe {
let start = self.as_mut_ptr();
let value_ptr = start.add(index);
let value = value_ptr.read();
if index != 0 {
start.copy_to(start.add(1), index);
}
self.len -= 1;
value
}
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
#[track_caller]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("swap_remove index (is {index}) should be < len (is {len})");
}
if index >= self.len {
assert_failed(index, self.len);
}
unsafe {
let start = self.as_mut_ptr();
let value_ptr = start.add(index);
let value = value_ptr.read();
self.len -= 1;
start.copy_to(value_ptr, 1);
value
}
}
#[must_use]
#[inline]
fn into_slice_ptr(self) -> NonNull<[T]> {
let this = ManuallyDrop::new(self);
if T::IS_ZST {
return NonNull::slice_from_raw_parts(NonNull::dangling(), this.len());
}
if this.cap == 0 {
debug_assert_eq!(this.end, NonNull::<T>::dangling());
return NonNull::slice_from_raw_parts(NonNull::<T>::dangling(), 0);
}
let end = this.end;
let len = this.len;
let cap = this.cap;
unsafe { this.allocator.allocate_prepared_slice_rev(end, len, cap) }
}
unsafe fn extend_trusted<B: ErrorBehavior>(&mut self, iterator: impl Iterator<Item = T>) -> Result<(), B> {
unsafe {
let (low, high) = iterator.size_hint();
if let Some(additional) = high {
debug_assert_eq!(
low,
additional,
"TrustedLen iterator's size hint is not exact: {:?}",
(low, high)
);
self.generic_reserve(additional)?;
let ptr = self.end.as_ptr();
let mut local_len = SetLenOnDrop::new(&mut self.len);
iterator.for_each(move |element| {
let dst = ptr.sub(local_len.current_len() + 1);
ptr::write(dst, element);
local_len.increment_len(1);
});
Ok(())
} else {
Err(B::capacity_overflow())
}
}
}
#[inline]
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
unsafe {
slice::from_raw_parts_mut(
self.end.as_ptr().sub(self.capacity()).cast::<MaybeUninit<T>>(),
self.capacity() - self.len(),
)
}
}
#[inline]
pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit<T>]) {
let (init, spare, _) = unsafe { self.split_at_spare_mut_with_len() };
(init, spare)
}
unsafe fn split_at_spare_mut_with_len(&mut self) -> (&mut [T], &mut [MaybeUninit<T>], &mut usize) {
unsafe {
let end = self.end.as_ptr();
let spare_ptr = end.sub(self.cap);
let spare_ptr = spare_ptr.cast::<MaybeUninit<T>>();
let spare_len = self.cap - self.len;
let initialized = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len);
let spare = slice::from_raw_parts_mut(spare_ptr, spare_len);
(initialized, spare, &mut self.len)
}
}
#[must_use]
#[inline(always)]
pub fn allocator_stats(&self) -> A::TypedStats<'_> {
self.allocator.typed_stats()
}
}
impl<'a, T, A: MutBumpAllocatorTypedScope<'a>> MutBumpVecRev<T, A> {
#[must_use]
#[inline(always)]
pub fn into_boxed_slice(self) -> BumpBox<'a, [T]> {
unsafe { BumpBox::from_raw(self.into_slice_ptr()) }
}
#[must_use]
#[inline(always)]
pub fn into_slice(self) -> &'a mut [T]
where
[T]: NoDrop,
{
self.into_boxed_slice().into_mut()
}
}
impl<T, A, const N: usize> MutBumpVecRev<[T; N], A> {
#[must_use]
pub fn into_flattened(self) -> MutBumpVecRev<T, A> {
let (end, len, cap, allocator) = self.into_raw_parts();
let (new_len, new_cap) = if T::IS_ZST {
(len.checked_mul(N).expect("vec len overflow"), usize::MAX)
} else {
unsafe { (len.unchecked_mul(N), cap.unchecked_mul(N)) }
};
unsafe { MutBumpVecRev::from_raw_parts(end.cast(), new_len, new_cap, allocator) }
}
}
impl<T: Debug, A> Debug for MutBumpVecRev<T, A> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Debug::fmt(self.as_slice(), f)
}
}
impl<T, A> Deref for MutBumpVecRev<T, A> {
type Target = [T];
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T, A> DerefMut for MutBumpVecRev<T, A> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl<T, A: Default> Default for MutBumpVecRev<T, A> {
fn default() -> Self {
Self::new_in(A::default())
}
}
impl<T, A, I: SliceIndex<[T]>> Index<I> for MutBumpVecRev<T, A> {
type Output = I::Output;
#[inline(always)]
fn index(&self, index: I) -> &Self::Output {
Index::index(self.as_slice(), index)
}
}
impl<T, A, I: SliceIndex<[T]>> IndexMut<I> for MutBumpVecRev<T, A> {
#[inline(always)]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
IndexMut::index_mut(self.as_mut_slice(), index)
}
}
#[cfg(feature = "panic-on-alloc")]
impl<U, A: MutBumpAllocatorTyped> Extend<U> for MutBumpVecRev<U, A> {
#[inline]
fn extend<T: IntoIterator<Item = U>>(&mut self, iter: T) {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);
for value in iter {
self.push(value);
}
}
}
impl<T, A> MutBumpVecRev<T, A> {
#[inline]
unsafe fn drop_inner(&mut self) {
unsafe {
let to_drop = NonNull::slice_from_raw_parts(self.as_non_null(), self.len);
to_drop.drop_in_place();
}
}
}
#[cfg(feature = "nightly-dropck-eyepatch")]
unsafe impl<#[may_dangle] T, A> Drop for MutBumpVecRev<T, A> {
#[inline(always)]
fn drop(&mut self) {
unsafe { self.drop_inner() }
}
}
#[cfg(not(feature = "nightly-dropck-eyepatch"))]
impl<T, A> Drop for MutBumpVecRev<T, A> {
#[inline(always)]
fn drop(&mut self) {
unsafe { self.drop_inner() }
}
}
#[cfg(feature = "panic-on-alloc")]
impl<'t, T: Clone + 't, A: MutBumpAllocatorTyped> Extend<&'t T> for MutBumpVecRev<T, A> {
#[inline]
fn extend<I: IntoIterator<Item = &'t T>>(&mut self, iter: I) {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);
for value in iter {
self.push(value.clone());
}
}
}
impl<T, A> IntoIterator for MutBumpVecRev<T, A> {
type Item = T;
type IntoIter = IntoIter<T, A>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
let (end, len, _cap, allocator) = self.into_raw_parts();
let start = unsafe { end.sub(len) };
let slice = NonNull::slice_from_raw_parts(start, len);
unsafe { IntoIter::new(slice, allocator) }
}
}
impl<'c, T, A> IntoIterator for &'c MutBumpVecRev<T, A> {
type Item = &'c T;
type IntoIter = slice::Iter<'c, T>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<'c, T, A> IntoIterator for &'c mut MutBumpVecRev<T, A> {
type Item = &'c mut T;
type IntoIter = slice::IterMut<'c, T>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
}
}
impl<T, A> AsRef<Self> for MutBumpVecRev<T, A> {
#[inline(always)]
fn as_ref(&self) -> &Self {
self
}
}
impl<T, A> AsMut<Self> for MutBumpVecRev<T, A> {
#[inline(always)]
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<T, A> AsRef<[T]> for MutBumpVecRev<T, A> {
#[inline(always)]
fn as_ref(&self) -> &[T] {
self
}
}
impl<T, A> AsMut<[T]> for MutBumpVecRev<T, A> {
#[inline(always)]
fn as_mut(&mut self) -> &mut [T] {
self
}
}
impl<T, A> Borrow<[T]> for MutBumpVecRev<T, A> {
#[inline(always)]
fn borrow(&self) -> &[T] {
self
}
}
impl<T, A> BorrowMut<[T]> for MutBumpVecRev<T, A> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut [T] {
self
}
}
impl<T: Hash, A> Hash for MutBumpVecRev<T, A> {
#[inline(always)]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
#[cfg(feature = "panic-on-alloc")]
impl<T, A: MutBumpAllocatorTyped + Default> FromIterator<T> for MutBumpVecRev<T, A> {
#[inline]
#[track_caller]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self::from_iter_in(iter, A::default())
}
}