use std::{
alloc::Layout,
mem,
num::NonZeroUsize,
ops::Range,
ptr::{
null,
slice_from_raw_parts,
write,
},
};
use crate::util::can_try_alloc;
use super::Handle;
impl<T, S> Handle<T, [S]> {
pub(crate) fn populate(
handle: *mut Self,
slice_len: Range<usize>,
value: T,
slice: &mut impl Iterator<Item=S>,
) -> usize {
unsafe { write(Self::value_ptr(handle), value) };
Self::extend(handle, slice_len, 0, slice)
}
pub(crate) fn extend(
handle: *mut Self,
slice_len: Range<usize>,
start: usize,
slice: &mut impl Iterator<Item=S>,
) -> usize {
let slice_values = Self::tail_ptr(handle) as *mut S;
for offset in start..(slice_len.end) {
if let Some(value) = slice.next() {
unsafe {
write(
slice_values.offset(offset as isize),
value,
)
}
} else {
if !slice_len.contains(&offset) {
panic!("Not enough values to populate handle")
}
return offset;
}
}
slice_len.end
}
pub(crate) fn layout_slice(slice_size: usize, count: NonZeroUsize) -> Layout {
let size = Self::size_slice(slice_size)
.checked_mul(count.get())
.expect("Overflow");
if !can_try_alloc(size) {
panic!("Overflow");
}
Layout::from_size_align(
size,
Self::alignment_slice(slice_size),
)
.expect("Bad Layout")
}
}
#[cfg(feature = "unstable")]
impl<T, S> Handle<T, [S]> {
#[inline(always)]
pub(crate) const fn null_ptr_slice(slice_size: usize) -> *const Self {
slice_from_raw_parts::<S>(null(), slice_size)
as *const Self
}
}
#[cfg(not(feature = "unstable"))]
impl<T, S> Handle<T, [S]> {
#[inline(always)]
pub(crate) fn null_ptr_slice(slice_size: usize) -> *const Self {
slice_from_raw_parts::<S>(null(), slice_size)
as *const Self
}
}
#[cfg(all(not(feature = "undefined_behavior"), feature = "unstable"))]
impl<V, T: ?Sized> Handle<V, T> {
#[inline(always)]
pub(crate) const fn tail_ptr(handle: *mut Self) -> *mut T {
unsafe {
std::ptr::addr_of_mut!((*handle).tail) as *mut T
}
}
#[inline(always)]
pub(crate) const fn value_ptr(handle: *mut Self) -> *mut V {
unsafe {
std::ptr::addr_of_mut!((*handle).value) as *mut V
}
}
#[inline(always)]
pub(crate) const fn size(ptr: *const Self) -> usize {
unsafe {
mem::size_of_val_raw::<Self>(ptr)
}
}
#[inline(always)]
pub(crate) const fn alignment(ptr: *const Self) -> usize {
unsafe {
mem::align_of_val_raw::<Self>(ptr)
}
}
}
#[cfg(all(not(feature = "undefined_behavior"), feature = "unstable"))]
impl<T, S> Handle<T, [S]> {
#[inline(always)]
pub(crate) const fn size_slice(slice_size: usize) -> usize {
Self::size(Self::null_ptr_slice(slice_size))
}
#[inline(always)]
pub(crate) const fn alignment_slice(slice_size: usize) -> usize {
Self::alignment(Self::null_ptr_slice(slice_size))
}
}
#[cfg(feature = "undefined_behavior")]
impl<V, T: ?Sized> Handle<V, T> {
#[inline(always)]
pub(crate) fn tail_ptr(handle: *mut Self) -> *mut T {
unsafe {
&mut (*handle).tail as *mut T
}
}
#[inline(always)]
pub(crate) fn value_ptr(handle: *mut Self) -> *mut V {
unsafe {
&mut (*handle).value as *mut V
}
}
#[inline(always)]
pub(crate) fn alignment(ptr: *const Self) -> usize {
mem::align_of_val(unsafe {&*ptr})
}
#[inline(always)]
pub(crate) fn size(ptr: *const Self) -> usize {
mem::size_of_val(unsafe {&*ptr})
}
}
#[cfg(feature = "undefined_behavior")]
impl<T, S> Handle<T, [S]> {
#[inline(always)]
pub(crate) fn alignment_slice(slice_size: usize) -> usize {
Self::alignment(Self::null_ptr_slice(slice_size))
}
#[inline(always)]
pub(crate) fn size_slice(slice_size: usize) -> usize {
Self::size(Self::null_ptr_slice(slice_size))
}
}