use crate::Immutable;
use core::fmt::Debug;
use core::hash::Hash;
use core::num::NonZero;
use core::ptr;
pub unsafe trait Outlay {
type Metadata:
Debug
+ Copy
+ Hash
+ Immutable
+ Ord
+ Send
+ Sync
+ Unpin;
const ALIGN: usize;
#[must_use]
fn classify_size(size: usize) -> Option<Self::Metadata>;
#[must_use]
fn size_with_metadata(len: Self::Metadata) -> Option<usize>;
#[must_use]
fn ptr_from_raw_parts(data: *const u8, meta: Self::Metadata) -> *const Self;
#[must_use]
fn ptr_from_raw_parts_mut(data: *mut u8, meta: Self::Metadata) -> *mut Self;
}
unsafe impl<T> Outlay for T {
type Metadata = ();
const ALIGN: usize = align_of::<Self>();
#[inline]
fn classify_size(size: usize) -> Option<Self::Metadata> {
(size >= size_of::<Self>())
.then_some(())
}
#[inline(always)]
fn size_with_metadata(_meta: Self::Metadata) -> Option<usize> {
Some(size_of::<Self>())
}
#[inline(always)]
fn ptr_from_raw_parts(data: *const u8, _meta: Self::Metadata) -> *const Self {
data.cast::<Self>()
}
#[inline(always)]
fn ptr_from_raw_parts_mut(data: *mut u8, _meta: Self::Metadata) -> *mut Self {
data.cast::<Self>()
}
}
unsafe impl<T> Outlay for [T] {
type Metadata = usize;
const ALIGN: usize = align_of::<T>();
#[inline]
fn classify_size(size: usize) -> Option<Self::Metadata> {
let element_size = const {
NonZero::new(size_of::<T>())
.expect("cannot classify size for zst slice")
};
size.is_multiple_of(size_of::<T>())
.then(|| size / element_size)
}
#[inline]
fn size_with_metadata(meta: Self::Metadata) -> Option<usize> {
size_of::<T>().checked_mul(meta)
}
#[inline]
fn ptr_from_raw_parts(data: *const u8, meta: Self::Metadata) -> *const Self {
let data = data.cast::<T>();
ptr::slice_from_raw_parts(data, meta)
}
#[inline]
fn ptr_from_raw_parts_mut(data: *mut u8, meta: Self::Metadata) -> *mut Self {
let data = data.cast::<T>();
ptr::slice_from_raw_parts_mut(data, meta)
}
}
unsafe impl Outlay for str {
type Metadata = <[u8] as Outlay>::Metadata;
const ALIGN: usize = <[u8] as Outlay>::ALIGN;
#[inline(always)]
fn classify_size(size: usize) -> Option<Self::Metadata> {
<[u8]>::classify_size(size)
}
#[inline(always)]
fn size_with_metadata(meta: Self::Metadata) -> Option<usize> {
<[u8]>::size_with_metadata(meta)
}
#[inline(always)]
fn ptr_from_raw_parts(data: *const u8, meta: Self::Metadata) -> *const Self {
<[u8]>::ptr_from_raw_parts(data, meta) as *const Self
}
#[inline(always)]
fn ptr_from_raw_parts_mut(data: *mut u8, meta: Self::Metadata) -> *mut Self {
<[u8]>::ptr_from_raw_parts_mut(data, meta) as *mut Self
}
}