#![deny(
unsafe_op_in_unsafe_fn,
clippy::alloc_instead_of_core,
clippy::std_instead_of_alloc,
clippy::std_instead_of_core
)]
#![warn(
missing_docs,
clippy::semicolon_if_nothing_returned,
clippy::undocumented_unsafe_blocks
)]
#![feature(
allocator_api,
array_zip,
closure_lifetime_binder,
forget_unsized,
min_specialization,
ptr_metadata,
strict_provenance,
type_alias_impl_trait,
unchecked_math,
unsize,
unsized_fn_params
)]
#![no_std]
#[doc(hidden)]
#[cfg(feature = "alloc")]
pub extern crate alloc as alloc_crate;
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "alloc")]
use alloc_crate::{alloc, boxed::Box, rc::Rc, string::String, sync::Arc, vec::Vec};
use core::{
alloc::{AllocError, Allocator, Layout},
cell::Cell,
ffi::CStr,
marker::{PhantomData, Unsize},
mem::{self, ManuallyDrop, MaybeUninit},
ops::FnMut,
pin::Pin,
ptr::{self, addr_of, NonNull, Pointee},
};
#[cfg(feature = "std")]
use std::{ffi::OsStr, path::Path};
#[doc(hidden)]
pub mod macro_exports {
#[cfg(feature = "alloc")]
pub use alloc_crate;
pub use core;
pub use u8;
}
#[cfg(all(feature = "alloc", not(miri)))]
#[macro_export]
macro_rules! unsize {
($e:expr, ($src:ty) -> $dst:ty) => {{
use $crate::{
ImplementationDetailDoNotUse,
macro_exports::{
alloc_crate::boxed::Box,
},
};
let val: $src = $e;
let new_alloc: ImplementationDetailDoNotUse<$src> = ImplementationDetailDoNotUse::NEW;
let boxed_sized: Box<$src, &ImplementationDetailDoNotUse<$src>> = Box::new_in(val, &new_alloc);
let boxed_unsized: Box<$dst, &ImplementationDetailDoNotUse<$src>> = boxed_sized;
*boxed_unsized
}};
}
#[doc(hidden)]
#[repr(transparent)]
pub struct ImplementationDetailDoNotUse<T>(Cell<MaybeUninit<T>>);
#[doc(hidden)]
impl<T> ImplementationDetailDoNotUse<T> {
pub const NEW: Self = Self(Cell::new(MaybeUninit::uninit()));
}
unsafe impl<T> Allocator for ImplementationDetailDoNotUse<T> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
debug_assert_eq!(layout, Layout::new::<T>());
let thin_ptr = unsafe { NonNull::new_unchecked(self.0.as_ptr()) };
Ok(NonNull::from_raw_parts(
thin_ptr.cast(),
mem::size_of::<T>(),
))
}
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
}
#[cfg(all(feature = "alloc", not(miri)))]
#[macro_export]
macro_rules! by_value_str {
($s:literal) => {{
use $crate::{
macro_exports::{
alloc_crate::boxed::Box,
core::{
alloc::{AllocError, Allocator, Layout},
cell::Cell,
mem::{self, MaybeUninit},
ptr::{self, addr_of_mut, NonNull},
},
u8,
},
NonAllocator,
};
const STRING: &str = $s;
const LEN: usize = STRING.len();
let mut buf: [MaybeUninit<u8>; LEN] = [MaybeUninit::uninit(); LEN];
unsafe {
ptr::copy(STRING.as_ptr().cast::<u8>(), addr_of_mut!(buf).cast(), LEN);
}
let wide_ptr: *mut str = ptr::from_raw_parts_mut(addr_of_mut!(buf).cast(), LEN);
let boxed_str: Box<str, NonAllocator> = unsafe { Box::from_raw_in(wide_ptr, NonAllocator) };
*boxed_str
}};
}
#[doc(hidden)]
pub struct NonAllocator;
unsafe impl Allocator for NonAllocator {
fn allocate(&self, _: Layout) -> Result<NonNull<[u8]>, AllocError> {
unreachable!()
}
#[inline]
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
}
pub trait EmplacableFn<T>: for<'a> FnOnce(&'a mut Emplacer<T>)
where
T: ?Sized,
{
}
impl<T, F> EmplacableFn<T> for F
where
T: ?Sized,
F: for<'a> FnOnce(&'a mut Emplacer<T>),
{
}
#[repr(transparent)]
pub struct Emplacable<T, F>
where
T: ?Sized,
F: EmplacableFn<T>,
{
closure: ManuallyDrop<F>,
phantom: PhantomData<fn(&mut Emplacer<T>)>,
}
impl<T, F> Emplacable<T, F>
where
T: ?Sized,
F: EmplacableFn<T>,
{
#[must_use]
#[inline]
pub unsafe fn from_fn(closure: F) -> Self {
Emplacable {
closure: ManuallyDrop::new(closure),
phantom: PhantomData,
}
}
#[must_use]
#[inline]
pub fn into_fn(self) -> F {
let mut manually_drop_self = ManuallyDrop::new(self);
unsafe { ManuallyDrop::take(&mut manually_drop_self.closure) }
}
#[must_use]
#[inline]
pub fn get(self) -> T
where
T: Sized,
{
let mut buf: MaybeUninit<T> = MaybeUninit::uninit();
let emplacer_closure =
&mut |_: Layout, (), inner_closure: &mut dyn FnMut(*mut PhantomData<T>)| {
inner_closure(buf.as_mut_ptr().cast());
};
let emplacer = unsafe { Emplacer::from_fn(emplacer_closure) };
let closure = self.into_fn();
closure(emplacer);
unsafe { buf.assume_init() }
}
#[inline]
pub fn forget(self) {
#[inline]
fn forgetting_emplacer_closure<T: ?Sized>(
_: Layout,
_: <T as Pointee>::Metadata,
_: &mut dyn FnMut(*mut PhantomData<T>),
) {
}
let emplacable_closure = self.into_fn();
let ref_to_fn = &mut forgetting_emplacer_closure::<T>;
let forgetting_emplacer = unsafe { Emplacer::from_fn(ref_to_fn) };
emplacable_closure(forgetting_emplacer);
}
#[must_use]
#[inline]
pub fn unsize<U: ?Sized>(self) -> Emplacable<U, impl EmplacableFn<U>>
where
T: Sized + Unsize<U>,
{
const fn metadata<T: Unsize<U>, U: ?Sized>() -> <U as Pointee>::Metadata {
let null_ptr_to_t: *const T = ptr::null();
let null_ptr_to_u: *const U = null_ptr_to_t;
ptr::metadata(null_ptr_to_u)
}
let sized_emplacable_closure = self.into_fn();
let unsized_emplacable_closure = move |unsized_emplacer: &mut Emplacer<U>| {
let unsized_emplacer_closure = unsafe { unsized_emplacer.into_fn() };
let mut sized_emplacer_closure =
|_: Layout, _: (), sized_inner_closure: &mut dyn FnMut(*mut PhantomData<T>)| {
let unsized_inner_closure: &mut dyn FnMut(*mut PhantomData<U>) =
&mut |unsized_ptr: *mut PhantomData<U>| {
sized_inner_closure(unsized_ptr.cast());
};
unsized_emplacer_closure(
Layout::new::<T>(),
metadata::<T, U>(),
unsized_inner_closure,
);
};
let sized_emplacer = unsafe { Emplacer::from_fn(&mut sized_emplacer_closure) };
sized_emplacable_closure(sized_emplacer);
};
unsafe { Emplacable::from_fn(unsized_emplacable_closure) }
}
#[allow(clippy::should_implement_trait)] #[inline]
pub fn from_iter<I>(iter: I) -> Emplacable<[T], impl EmplacableFn<[T]>>
where
T: Sized,
I: IntoIterator<Item = Self>,
I::IntoIter: ExactSizeIterator,
{
fn from_iter_inner<
T,
F: EmplacableFn<T>,
I: Iterator<Item = Emplacable<T, F>> + ExactSizeIterator,
>(
iter: I,
) -> Emplacable<[T], impl EmplacableFn<[T]>> {
let len = iter.len();
let layout = Layout::from_size_align(
mem::size_of::<T>().checked_mul(len).unwrap(),
mem::align_of::<T>(),
)
.unwrap();
let slice_emplacer_closure = move |slice_emplacer: &mut Emplacer<[T]>| {
let emplacables_iter = ManuallyDrop::new(iter);
let slice_emplacer_fn = unsafe { slice_emplacer.into_fn() };
slice_emplacer_fn(layout, len, &mut |arr_out_ptr: *mut PhantomData<[T]>| {
if !arr_out_ptr.is_null() {
let elem_emplacables: I =
unsafe { ptr::read(&*emplacables_iter) };
let mut num_elems_copied: usize = 0;
let indexed_elem_emplacables = (0..len).zip(elem_emplacables);
indexed_elem_emplacables.for_each(|(index, elem_emplacable)| {
let elem_emplacable_closure = elem_emplacable.into_fn();
let elem_emplacer_closure = &mut move |
_: Layout,
(),
inner_closure: &mut dyn FnMut(*mut PhantomData<T>),
| {
inner_closure(unsafe { arr_out_ptr.cast::<T>().add(index).cast() });
};
let elem_emplacer = unsafe { Emplacer::from_fn(elem_emplacer_closure) };
elem_emplacable_closure(elem_emplacer);
num_elems_copied += 1;
});
assert_eq!(num_elems_copied, len);
} else {
let emplacables_iter: I =
unsafe { ptr::read(&*emplacables_iter) };
for _emplacable in emplacables_iter {
}
}
});
};
unsafe { Emplacable::from_fn(slice_emplacer_closure) }
}
let emplacables_iter = iter.into_iter();
from_iter_inner(emplacables_iter)
}
}
impl<T, F> Drop for Emplacable<T, F>
where
T: ?Sized,
F: EmplacableFn<T>,
{
fn drop(&mut self) {
#[inline]
fn dropping_emplacer_closure<T: ?Sized>(
_: Layout,
_: <T as Pointee>::Metadata,
inner_closure: &mut dyn FnMut(*mut PhantomData<T>),
) {
inner_closure(ptr::null_mut());
}
let ref_to_fn = &mut dropping_emplacer_closure::<T>;
let dropping_emplacer = unsafe { Emplacer::from_fn(ref_to_fn) };
let emplacable_closure = unsafe { ManuallyDrop::take(&mut self.closure) };
emplacable_closure(dropping_emplacer);
}
}
#[doc(hidden)]
pub trait IntoEmplacable<T: ?Sized> {
type Closure: EmplacableFn<T>;
#[must_use]
fn into_emplacable(self) -> Emplacable<T, Self::Closure>;
}
impl<T> IntoEmplacable<T> for T {
type Closure = impl EmplacableFn<Self>;
#[inline]
fn into_emplacable(self) -> Emplacable<T, Self::Closure> {
let closure = move |emplacer: &mut Emplacer<T>| {
let mut manually_drop_self = ManuallyDrop::new(self);
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(Layout::new::<T>(), (), &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(
addr_of!(*manually_drop_self).cast::<T>(),
out_ptr.cast(),
1,
);
}
} else {
unsafe { ManuallyDrop::drop(&mut manually_drop_self) }
}
});
};
unsafe { Emplacable::from_fn(closure) }
}
}
impl<T> From<T> for Emplacable<T, <T as IntoEmplacable<T>>::Closure> {
#[inline]
fn from(value: T) -> Self {
value.into_emplacable()
}
}
trait CopyToBuf: Sized {
unsafe fn copy_to_buf(slice: &[Self], buf: *mut Self);
}
impl<T: Clone> CopyToBuf for T {
#[inline]
default unsafe fn copy_to_buf(slice: &[Self], buf: *mut Self) {
for (index, elem) in slice.iter().enumerate() {
let owned = elem.clone();
unsafe { buf.cast::<T>().add(index).write(owned) };
}
}
}
impl<T: Copy> CopyToBuf for T {
#[inline]
unsafe fn copy_to_buf(slice: &[Self], buf: *mut Self) {
unsafe {
ptr::copy_nonoverlapping(addr_of!(slice).cast(), buf, slice.len());
}
}
}
impl<'s, T: Clone + 's> IntoEmplacable<[T]> for &'s [T] {
type Closure = impl for<'a> FnOnce(&'a mut Emplacer<[T]>) + 's;
#[inline]
fn into_emplacable(self) -> Emplacable<[T], Self::Closure> {
let metadata = ptr::metadata(self);
let layout = Layout::for_value(self);
let closure = move |emplacer: &mut Emplacer<[T]>| {
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, metadata, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe { <T as CopyToBuf>::copy_to_buf(self, out_ptr.cast()) }
}
});
};
unsafe { Emplacable::from_fn(closure) }
}
}
impl<'s, T: Clone + 's> From<&'s [T]>
for Emplacable<[T], <&'s [T] as IntoEmplacable<[T]>>::Closure>
{
#[inline]
fn from(value: &'s [T]) -> Self {
<&[T] as IntoEmplacable<[T]>>::into_emplacable(value)
}
}
impl<'s> IntoEmplacable<str> for &'s str {
type Closure = impl for<'a> FnOnce(&'a mut Emplacer<str>) + 's;
#[inline]
fn into_emplacable(self) -> Emplacable<str, Self::Closure> {
let metadata = ptr::metadata(self);
let layout = Layout::for_value(self);
let closure = move |emplacer: &mut Emplacer<str>| {
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, metadata, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(
addr_of!(*self).cast::<u8>(),
out_ptr.cast(),
layout.size(),
);
}
}
});
};
unsafe { Emplacable::from_fn(closure) }
}
}
impl<'s> From<&'s str> for Emplacable<str, <&'s str as IntoEmplacable<str>>::Closure> {
#[inline]
fn from(value: &'s str) -> Self {
<&str as IntoEmplacable<str>>::into_emplacable(value)
}
}
impl<'s> IntoEmplacable<CStr> for &'s CStr {
type Closure = impl for<'a> FnOnce(&'a mut Emplacer<CStr>) + 's;
#[inline]
fn into_emplacable(self) -> Emplacable<CStr, Self::Closure> {
let metadata = ptr::metadata(self);
let layout = Layout::for_value(self);
let closure = move |emplacer: &mut Emplacer<CStr>| {
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, metadata, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(
addr_of!(*self).cast::<u8>(),
out_ptr.cast(),
layout.size(),
);
}
}
});
};
unsafe { Emplacable::from_fn(closure) }
}
}
impl<'s> From<&'s CStr> for Emplacable<CStr, <&'s CStr as IntoEmplacable<CStr>>::Closure> {
#[inline]
fn from(value: &'s CStr) -> Self {
<&CStr as IntoEmplacable<CStr>>::into_emplacable(value)
}
}
#[cfg(feature = "std")]
impl<'s> IntoEmplacable<OsStr> for &'s OsStr {
type Closure = impl for<'a> FnOnce(&'a mut Emplacer<OsStr>) + 's;
#[must_use]
#[inline]
fn into_emplacable(self) -> Emplacable<OsStr, Self::Closure> {
let metadata = ptr::metadata(self);
let layout = Layout::for_value(self);
let closure = move |emplacer: &mut Emplacer<OsStr>| {
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, metadata, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(
addr_of!(*self).cast::<u8>(),
out_ptr.cast(),
layout.size(),
);
}
}
});
};
unsafe { Emplacable::from_fn(closure) }
}
}
#[cfg(feature = "std")]
impl<'s> From<&'s OsStr> for Emplacable<OsStr, <&'s OsStr as IntoEmplacable<OsStr>>::Closure> {
#[inline]
fn from(value: &'s OsStr) -> Self {
<&OsStr as IntoEmplacable<OsStr>>::into_emplacable(value)
}
}
#[cfg(feature = "std")]
impl<'s> IntoEmplacable<Path> for &'s Path {
type Closure = impl for<'a> FnOnce(&'a mut Emplacer<Path>) + 's;
#[must_use]
#[inline]
fn into_emplacable(self) -> Emplacable<Path, Self::Closure> {
let metadata = ptr::metadata(self);
let layout = Layout::for_value(self);
let closure = move |emplacer: &mut Emplacer<Path>| {
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, metadata, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(
addr_of!(*self).cast::<u8>(),
out_ptr.cast(),
layout.size(),
);
}
}
});
};
unsafe { Emplacable::from_fn(closure) }
}
}
#[cfg(feature = "std")]
impl<'s> From<&'s Path> for Emplacable<Path, <&'s Path as IntoEmplacable<Path>>::Closure> {
#[inline]
fn from(value: &'s Path) -> Self {
<&Path as IntoEmplacable<Path>>::into_emplacable(value)
}
}
#[doc(hidden)]
pub trait FromEmplacable<T: ?Sized> {
type OutputClosure<F: EmplacableFn<T>>: EmplacableFn<Self>;
fn from_emplacable<F: EmplacableFn<T>>(
emplacable: Emplacable<T, F>,
) -> Emplacable<Self, Self::OutputClosure<F>>;
}
impl<F: EmplacableFn<str>> IntoEmplacable<[u8]> for Emplacable<str, F> {
type Closure = impl EmplacableFn<[u8]>;
#[inline]
fn into_emplacable(self) -> Emplacable<[u8], Self::Closure> {
let str_closure = self.into_fn();
#[allow(clippy::unused_unit)] let u8_emplacer_closure = for<'a, 'b> move |u8_emplacer: &'a mut Emplacer<'b, [u8]>| -> () {
let u8_emplacer_fn: &mut EmplacerFn<[u8]> =
unsafe { u8_emplacer.into_fn() };
let mut str_emplacer_fn =
|layout: Layout,
metadata: usize,
str_inner_closure: &mut dyn FnMut(*mut PhantomData<str>)| {
let u8_inner_closure: &mut dyn FnMut(*mut PhantomData<[u8]>) =
&mut |u8_ptr: *mut PhantomData<[u8]>| str_inner_closure(u8_ptr.cast());
u8_emplacer_fn(layout, metadata, u8_inner_closure);
};
let str_emplacer: &mut Emplacer<str> =
unsafe { Emplacer::from_fn(&mut str_emplacer_fn) };
str_closure(str_emplacer);
};
unsafe { Emplacable::from_fn(u8_emplacer_closure) }
}
}
impl<F> From<Emplacable<str, F>>
for Emplacable<[u8], <Emplacable<str, F> as IntoEmplacable<[u8]>>::Closure>
where
F: EmplacableFn<str>,
{
#[inline]
fn from(emplacable: Emplacable<str, F>) -> Self {
<Emplacable<str, F> as IntoEmplacable<[u8]>>::into_emplacable(emplacable)
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized> IntoEmplacable<T> for Box<T> {
type Closure = impl EmplacableFn<T>;
fn into_emplacable(self) -> Emplacable<T, Self::Closure> {
let closure = move |emplacer: &mut Emplacer<T>| {
let layout = Layout::for_value(&*self);
let ptr = Box::into_raw(self);
let metadata = ptr::metadata(ptr);
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, metadata, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(ptr.cast(), out_ptr.cast::<u8>(), layout.size());
}
} else {
unsafe {
ptr::drop_in_place(ptr);
}
}
});
if layout.size() > 0 {
unsafe { alloc::dealloc(ptr.cast(), layout) }
}
};
unsafe { Emplacable::from_fn(closure) }
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized> From<Box<T>> for Emplacable<T, <Box<T> as IntoEmplacable<T>>::Closure> {
#[inline]
fn from(value: Box<T>) -> Self {
<Box<T> as IntoEmplacable<T>>::into_emplacable(value)
}
}
#[cfg(feature = "alloc")]
impl<T> IntoEmplacable<[T]> for Vec<T> {
type Closure = impl EmplacableFn<[T]>;
fn into_emplacable(self) -> Emplacable<[T], Self::Closure> {
let closure = move |emplacer: &mut Emplacer<[T]>| {
let mut vec = ManuallyDrop::new(self);
let ptr = vec.as_mut_ptr();
let len = vec.len();
let capacity = vec.capacity();
let layout = unsafe {
Layout::from_size_align_unchecked(
capacity.unchecked_mul(mem::size_of::<T>()),
mem::align_of::<T>(),
)
};
let emplacer_closure = unsafe { emplacer.into_fn() };
emplacer_closure(layout, len, &mut |out_ptr| {
if !out_ptr.is_null() {
unsafe {
ptr::copy_nonoverlapping(ptr, out_ptr.cast::<T>(), len);
}
} else {
for elem in &mut *vec {
unsafe {
ptr::drop_in_place(elem);
}
}
}
});
if layout.size() > 0 {
unsafe { alloc::dealloc(ptr.cast(), layout) }
}
};
unsafe { Emplacable::from_fn(closure) }
}
}
#[cfg(feature = "alloc")]
impl<T> From<Vec<T>> for Emplacable<[T], <Vec<T> as IntoEmplacable<[T]>>::Closure> {
#[inline]
fn from(value: Vec<T>) -> Self {
<Vec<T> as IntoEmplacable<[T]>>::into_emplacable(value)
}
}
impl<T, const N: usize, F: EmplacableFn<[T; N]>> IntoEmplacable<[T]> for Emplacable<[T; N], F> {
type Closure = impl EmplacableFn<[T]>;
#[inline]
fn into_emplacable(self) -> Emplacable<[T], Self::Closure> {
self.unsize()
}
}
impl<T, const N: usize, F> From<Emplacable<[T; N], F>>
for Emplacable<[T], <Emplacable<[T; N], F> as IntoEmplacable<[T]>>::Closure>
where
F: EmplacableFn<[T; N]>,
{
#[inline]
fn from(value: Emplacable<[T; N], F>) -> Self {
<Emplacable<[T; N], F> as IntoEmplacable<[T]>>::into_emplacable(value)
}
}
impl<T, const N: usize, F: EmplacableFn<T>> IntoEmplacable<[T; N]> for [Emplacable<T, F>; N] {
type Closure = impl EmplacableFn<[T; N]>;
#[inline]
fn into_emplacable(self) -> Emplacable<[T; N], Self::Closure> {
let arr_emplacer_closure = move |arr_emplacer: &mut Emplacer<[T; N]>| {
let mut elem_emplacables = ManuallyDrop::new(self);
let arr_emplacer_fn = unsafe { arr_emplacer.into_fn() };
arr_emplacer_fn(
Layout::new::<[T; N]>(),
(),
&mut |arr_out_ptr: *mut PhantomData<[T; N]>| {
if !arr_out_ptr.is_null() {
let elem_emplacables: [Emplacable<T, F>; N] =
unsafe { ptr::read(&*elem_emplacables) };
let n_zeros: [usize; N] = [0; N];
let mut i: usize = 0;
let indexes: [usize; N] = n_zeros.map(|_| {
i = i.wrapping_add(1);
i.wrapping_sub(1)
});
let indexed_elem_emplacables = indexes.zip(elem_emplacables);
indexed_elem_emplacables.map(|(index, elem_emplacable)| {
let elem_emplacable_closure = elem_emplacable.into_fn();
let elem_emplacer_closure = &mut move |
_: Layout,
(),
inner_closure: &mut dyn FnMut(*mut PhantomData<T>),
| {
inner_closure(unsafe { arr_out_ptr.cast::<T>().add(index).cast() });
};
let elem_emplacer = unsafe { Emplacer::from_fn(elem_emplacer_closure) };
elem_emplacable_closure(elem_emplacer);
});
} else {
unsafe {
ManuallyDrop::drop(&mut elem_emplacables);
}
}
},
);
};
unsafe { Emplacable::from_fn(arr_emplacer_closure) }
}
}
impl<T, const N: usize, F> From<[Emplacable<T, F>; N]>
for Emplacable<[T; N], <[Emplacable<T, F>; N] as IntoEmplacable<[T; N]>>::Closure>
where
F: EmplacableFn<T>,
{
#[inline]
fn from(value: [Emplacable<T, F>; N]) -> Self {
<[Emplacable<T, F>; N] as IntoEmplacable<[T; N]>>::into_emplacable(value)
}
}
impl<T, const N: usize, F: EmplacableFn<T>> IntoEmplacable<[T]> for [Emplacable<T, F>; N] {
type Closure = impl EmplacableFn<[T]>;
#[inline]
fn into_emplacable(self) -> Emplacable<[T], Self::Closure> {
<[Emplacable<T, F>; N] as IntoEmplacable<[T; N]>>::into_emplacable(self).into()
}
}
impl<T, const N: usize, F> From<[Emplacable<T, F>; N]>
for Emplacable<[T], <[Emplacable<T, F>; N] as IntoEmplacable<[T]>>::Closure>
where
F: EmplacableFn<T>,
{
#[inline]
fn from(value: [Emplacable<T, F>; N]) -> Self {
<[Emplacable<T, F>; N] as IntoEmplacable<[T]>>::into_emplacable(value)
}
}
pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(Layout, <T as Pointee>::Metadata, &'b mut (dyn FnMut(*mut PhantomData<T>)))
+ 'a;
#[repr(transparent)]
pub struct Emplacer<'a, T>(EmplacerFn<'a, T>)
where
T: ?Sized;
impl<'a, T> Emplacer<'a, T>
where
T: ?Sized,
{
#[must_use]
#[inline]
pub unsafe fn from_fn<'b>(emplacer_fn: &'b mut EmplacerFn<'a, T>) -> &'b mut Self {
unsafe { &mut *((emplacer_fn as *mut EmplacerFn<'a, T>) as *mut Self) }
}
#[inline]
pub unsafe fn into_fn<'b>(&'b mut self) -> &'b mut EmplacerFn<'a, T> {
&mut self.0
}
}
#[cfg(all(feature = "alloc", not(miri)))]
#[inline]
pub fn box_new<T>(x: T) -> Box<T>
where
T: ?Sized,
{
let layout = Layout::for_value(&x);
let metadata = ptr::metadata(&x);
let alloc_ptr = if layout.size() > 0 {
let maybe_ptr = unsafe { alloc::alloc(layout) };
if maybe_ptr.is_null() {
alloc::handle_alloc_error(layout)
};
unsafe { ptr::copy_nonoverlapping(addr_of!(x).cast(), maybe_ptr, layout.size()) };
maybe_ptr
} else {
ptr::invalid_mut(layout.align())
};
mem::forget_unsized(x);
let wide_ptr = ptr::from_raw_parts_mut(alloc_ptr.cast(), metadata);
unsafe { Box::from_raw(wide_ptr) }
}
#[cfg(feature = "alloc")]
#[inline]
pub fn box_new_with<T>(emplacable: Emplacable<T, impl EmplacableFn<T>>) -> Box<T>
where
T: ?Sized,
{
struct PointerDeallocer {
ptr: *mut u8,
layout: Layout,
}
impl Drop for PointerDeallocer {
#[inline]
fn drop(&mut self) {
if self.layout.size() != 0 {
unsafe { alloc::dealloc(self.ptr, self.layout) }
}
}
}
let mut uninit_box = MaybeUninit::uninit();
let emplacer_closure =
&mut |layout: Layout, meta, closure: &mut dyn FnMut(*mut PhantomData<T>)| {
let deallocer = PointerDeallocer {
ptr: if layout.size() == 0 {
ptr::invalid_mut(layout.align())
} else {
unsafe { alloc::alloc(layout) }
},
layout,
};
if deallocer.ptr.is_null() {
mem::forget(deallocer);
alloc::handle_alloc_error(layout);
}
closure(deallocer.ptr.cast());
let wide_ptr = ptr::from_raw_parts_mut(deallocer.ptr.cast::<()>(), meta);
let init_box = unsafe { Box::from_raw(wide_ptr) };
mem::forget(deallocer);
uninit_box.write(init_box);
};
let emplacer = unsafe { Emplacer::from_fn(emplacer_closure) };
let emplacing_clousre = emplacable.into_fn();
emplacing_clousre(emplacer);
unsafe { uninit_box.assume_init() }
}
impl<T, F> Emplacable<[T], F>
where
F: EmplacableFn<[T]>,
{
#[cfg(feature = "alloc")]
#[inline]
pub fn into_vec(self) -> Vec<T> {
self.into()
}
}
#[cfg(feature = "alloc")]
impl<T, F> From<Emplacable<[T], F>> for Vec<T>
where
F: EmplacableFn<[T]>,
{
#[inline]
fn from(emplacable: Emplacable<[T], F>) -> Self {
box_new_with(emplacable).into_vec()
}
}
#[cfg(feature = "alloc")]
impl<T, F> FromIterator<Emplacable<T, F>> for Vec<T>
where
F: EmplacableFn<T>,
{
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Emplacable<T, F>>,
{
let mut vec = Vec::new();
vec.extend(iter);
vec
}
}
#[cfg(feature = "alloc")]
impl<T, F> Extend<Emplacable<T, F>> for Vec<T>
where
F: EmplacableFn<T>,
{
#[inline]
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = Emplacable<T, F>>,
{
fn extend_inner<T, F: EmplacableFn<T>, I: Iterator<Item = Emplacable<T, F>>>(
vec: &mut Vec<T>,
iter: I,
) {
vec.reserve_exact(iter.size_hint().0);
for emplacable in iter {
vec.push(emplacable.get());
}
}
extend_inner(self, iter.into_iter());
}
}
impl<F> Emplacable<str, F>
where
F: EmplacableFn<str>,
{
#[cfg(feature = "alloc")]
#[must_use]
#[inline]
pub fn into_string(self) -> String {
self.into()
}
}
#[cfg(feature = "alloc")]
impl<F> From<Emplacable<str, F>> for String
where
F: EmplacableFn<str>,
{
#[inline]
fn from(emplacable: Emplacable<str, F>) -> Self {
box_new_with(emplacable).into_string()
}
}
#[cfg(all(feature = "alloc", not(miri)))]
#[inline]
pub fn box_pin<T>(x: T) -> Pin<Box<T>>
where
T: ?Sized,
{
Box::into_pin(box_new(x))
}
#[cfg(feature = "alloc")]
#[inline]
pub fn box_pin_with<T>(emplacable: Emplacable<T, impl EmplacableFn<T>>) -> Pin<Box<T>>
where
T: ?Sized,
{
Box::into_pin(box_new_with(emplacable))
}
#[cfg(all(feature = "alloc", not(miri)))]
#[inline]
pub fn rc_new<T>(value: T) -> Rc<T>
where
T: ?Sized,
{
box_new(value).into()
}
#[cfg(feature = "alloc")]
#[inline]
pub fn rc_new_with<T>(emplacable: Emplacable<T, impl EmplacableFn<T>>) -> Rc<T>
where
T: ?Sized,
{
box_new_with(emplacable).into()
}
#[cfg(feature = "alloc")]
impl<T, F> From<Emplacable<T, F>> for Rc<T>
where
T: ?Sized,
F: EmplacableFn<T>,
{
#[inline]
fn from(emplacable: Emplacable<T, F>) -> Self {
rc_new_with(emplacable)
}
}
#[cfg(all(feature = "alloc", not(miri)))]
#[inline]
pub fn rc_pin<T>(x: T) -> Pin<Rc<T>>
where
T: ?Sized,
{
unsafe { Pin::new_unchecked(rc_new(x)) }
}
#[cfg(feature = "alloc")]
#[inline]
pub fn rc_pin_with<T>(emplacable: Emplacable<T, impl EmplacableFn<T>>) -> Pin<Rc<T>>
where
T: ?Sized,
{
unsafe { Pin::new_unchecked(rc_new_with(emplacable)) }
}
#[cfg(all(feature = "alloc", not(miri)))]
#[inline]
pub fn arc_new<T>(value: T) -> Arc<T>
where
T: ?Sized,
{
box_new(value).into()
}
#[cfg(feature = "alloc")]
#[inline]
pub fn arc_new_with<T>(emplacable: Emplacable<T, impl EmplacableFn<T>>) -> Arc<T>
where
T: ?Sized,
{
box_new_with(emplacable).into()
}
#[cfg(feature = "alloc")]
impl<T, F> From<Emplacable<T, F>> for Arc<T>
where
T: ?Sized,
F: EmplacableFn<T>,
{
#[inline]
fn from(emplacable: Emplacable<T, F>) -> Self {
arc_new_with(emplacable)
}
}
#[cfg(all(feature = "alloc", not(miri)))]
#[inline]
pub fn arc_pin<T>(x: T) -> Pin<Arc<T>>
where
T: ?Sized,
{
unsafe { Pin::new_unchecked(arc_new(x)) }
}
#[cfg(feature = "alloc")]
#[inline]
pub fn arc_pin_with<T>(emplacable: Emplacable<T, impl EmplacableFn<T>>) -> Pin<Arc<T>>
where
T: ?Sized,
{
unsafe { Pin::new_unchecked(arc_new_with(emplacable)) }
}