use core::{array, mem};
#[cfg(feature = "alloc")]
use core::mem::ManuallyDrop;
#[cfg(feature = "alloc")]
use alloc_crate::{
boxed::Box,
vec::{self, Vec},
};
use crate::{BumpBox, BumpVec, FixedBumpVec, MutBumpVec, MutBumpVecRev, traits::BumpAllocatorTyped, unsize_bump_box};
mod drain;
mod extract_if;
mod into_iter;
pub use drain::Drain;
pub use extract_if::ExtractIf;
pub use into_iter::IntoIter;
pub trait OwnedSlice {
type Item;
type Take: TakeOwnedSlice<Item = Self::Item>;
fn into_take_owned_slice(self) -> Self::Take;
}
impl<T: TakeOwnedSlice> OwnedSlice for T {
type Item = <Self as TakeOwnedSlice>::Item;
type Take = Self;
fn into_take_owned_slice(self) -> Self::Take {
self
}
}
impl<T, const N: usize> OwnedSlice for [T; N] {
type Item = T;
type Take = array::IntoIter<T, N>;
fn into_take_owned_slice(self) -> Self::Take {
self.into_iter()
}
}
impl<'a, T, const N: usize> OwnedSlice for BumpBox<'a, [T; N]> {
type Item = T;
type Take = BumpBox<'a, [T]>;
fn into_take_owned_slice(self) -> Self::Take {
unsize_bump_box!(self)
}
}
#[cfg(feature = "alloc")]
impl<T, const N: usize> OwnedSlice for Box<[T; N]> {
type Item = T;
type Take = Box<[T]>;
fn into_take_owned_slice(self) -> Self::Take {
self
}
}
pub unsafe trait TakeOwnedSlice {
type Item;
fn owned_slice_ref(&self) -> &[Self::Item];
fn take_owned_slice(&mut self);
}
unsafe impl<T: TakeOwnedSlice + ?Sized> TakeOwnedSlice for &mut T {
type Item = T::Item;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
T::owned_slice_ref(self)
}
#[inline]
fn take_owned_slice(&mut self) {
T::take_owned_slice(self);
}
}
unsafe impl<T, const N: usize> TakeOwnedSlice for array::IntoIter<T, N> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self.as_slice()
}
#[inline]
fn take_owned_slice(&mut self) {
self.for_each(mem::forget);
}
}
unsafe impl<T> TakeOwnedSlice for BumpBox<'_, [T]> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
unsafe { self.set_len(0) }
}
}
unsafe impl<T> TakeOwnedSlice for FixedBumpVec<'_, T> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
unsafe { self.set_len(0) }
}
}
unsafe impl<T, A: BumpAllocatorTyped> TakeOwnedSlice for BumpVec<T, A> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
unsafe { self.set_len(0) }
}
}
unsafe impl<T, A> TakeOwnedSlice for MutBumpVec<T, A> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
unsafe { self.set_len(0) }
}
}
unsafe impl<T, A> TakeOwnedSlice for MutBumpVecRev<T, A> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
unsafe { self.set_len(0) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> TakeOwnedSlice for Box<[T]> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
let ptr = Box::into_raw(mem::take(self));
let forget_elements_box = unsafe { Box::<[ManuallyDrop<T>]>::from_raw(ptr as *mut [ManuallyDrop<T>]) };
drop(forget_elements_box);
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> TakeOwnedSlice for Vec<T> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self
}
#[inline]
fn take_owned_slice(&mut self) {
unsafe { self.set_len(0) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> TakeOwnedSlice for vec::IntoIter<T> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self.as_slice()
}
#[inline]
fn take_owned_slice(&mut self) {
self.for_each(mem::forget);
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> TakeOwnedSlice for vec::Drain<'_, T> {
type Item = T;
#[inline]
fn owned_slice_ref(&self) -> &[Self::Item] {
self.as_slice()
}
#[inline]
fn take_owned_slice(&mut self) {
self.for_each(mem::forget);
}
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use crate::Bump;
use super::*;
const _: () = {
const fn is_dyn_compatible<T: TakeOwnedSlice + ?Sized>() {}
is_dyn_compatible::<dyn TakeOwnedSlice<Item = i32>>();
is_dyn_compatible::<&mut dyn TakeOwnedSlice<Item = i32>>();
};
macro_rules! assert_implements {
($($ty:ty)*) => {
const _: () = {
type T = i32;
const fn implements<S: OwnedSlice + ?Sized>() {}
$(implements::<$ty>();)*
};
};
}
assert_implements! {
&mut dyn TakeOwnedSlice<Item = T>
[T; 3]
BumpBox<[T; 3]>
BumpBox<[T]>
&mut BumpBox<[T]>
FixedBumpVec<T>
&mut FixedBumpVec<T>
BumpVec<T, &Bump>
&mut BumpVec<T, &Bump>
MutBumpVec<T, &mut Bump>
&mut MutBumpVec<T, &mut Bump>
MutBumpVecRev<T, &mut Bump>
&mut MutBumpVecRev<T, &mut Bump>
BumpVec<T, Bump>
&mut BumpVec<T, Bump>
MutBumpVec<T, Bump>
&mut MutBumpVec<T, Bump>
MutBumpVecRev<T, Bump>
&mut MutBumpVecRev<T, Bump>
}
#[cfg(feature = "alloc")]
assert_implements! {
Box<[T; 3]>
Box<[T]>
&mut Box<[T]>
Vec<T>
&mut Vec<T>
}
}