mod test;
use core::alloc::{Layout, LayoutError};
use core::fmt::Debug;
use core::hash::Hash;
use core::num::NonZero;
use core::panic::UnwindSafe;
use core::ptr::{self, dangling, dangling_mut, NonNull};
use oct::Immutable;
#[cfg(feature = "bstr")]
use core::bstr::ByteStr;
pub unsafe trait Outlay {
type Metadata:
Debug
+ Copy
+ Hash
+ Immutable
+ Ord
+ Send
+ Sync
+ Unpin
+ UnwindSafe;
const ALIGN: usize;
#[must_use]
fn classify_size(size: usize) -> Option<Self::Metadata>;
fn layout_for_metadata(metadata: Self::Metadata) -> Result<Layout, LayoutError>;
#[must_use]
fn ptr_from_raw_parts(data: *const u8, metadata: Self::Metadata) -> *const Self;
#[must_use]
fn ptr_from_raw_parts_mut(data: *mut u8, metadata: Self::Metadata) -> *mut Self;
#[must_use]
fn ptr_dangling_with_metadata(metadata: Self::Metadata) -> *const Self;
#[must_use]
fn ptr_dangling_with_metadata_mut(metadata: Self::Metadata) -> *mut Self;
#[inline(always)]
#[must_use]
#[track_caller]
fn non_null_dangling_with_metadata(metadata: Self::Metadata) -> NonNull<Self> {
let p = Self::ptr_dangling_with_metadata_mut(metadata);
debug_assert_eq!(
p.addr() % Self::ALIGN,
0,
"`ptr_dangling_with_metadata_mut` returned a non-aligned pointer",
);
debug_assert!(
p.is_null(),
"`ptr_dangling_with_metadata_mut` returned a null pointer",
);
unsafe { NonNull::new_unchecked(p) }
}
}
unsafe impl<T> Outlay for T {
type Metadata = ();
const ALIGN: usize = align_of::<Self>();
#[inline]
fn classify_size(size: usize) -> Option<Self::Metadata> {
if size >= size_of::<Self>() {
Some(())
} else {
None
}
}
#[inline]
fn layout_for_metadata((): Self::Metadata) -> Result<Layout, LayoutError> {
Ok(Layout::new::<T>())
}
#[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>()
}
#[inline(always)]
fn ptr_dangling_with_metadata((): Self::Metadata) -> *const Self {
dangling::<Self>()
}
#[inline(always)]
fn ptr_dangling_with_metadata_mut((): Self::Metadata) -> *mut Self {
dangling_mut::<Self>()
}
}
#[cfg(feature = "bstr")]
unsafe impl Outlay for ByteStr {
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 layout_for_metadata(metadata: Self::Metadata) -> Result<Layout, LayoutError> {
<[u8]>::layout_for_metadata(metadata)
}
#[inline(always)]
fn ptr_from_raw_parts(data: *const u8, metadata: Self::Metadata) -> *const Self {
<[u8]>::ptr_from_raw_parts(data, metadata) as *const Self
}
#[inline(always)]
fn ptr_from_raw_parts_mut(data: *mut u8, metadata: Self::Metadata) -> *mut Self {
<[u8]>::ptr_from_raw_parts_mut(data, metadata) as *mut Self
}
#[inline(always)]
fn ptr_dangling_with_metadata(metadata: Self::Metadata) -> *const Self {
<[u8]>::ptr_dangling_with_metadata(metadata) as *const Self
}
#[inline(always)]
fn ptr_dangling_with_metadata_mut(metadata: Self::Metadata) -> *mut Self {
<[u8]>::ptr_dangling_with_metadata_mut(metadata) as *mut 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 = NonZero::new(size_of::<T>())?;
if size % element_size == 0 {
Some(size / element_size)
} else {
None
}
}
#[inline]
fn layout_for_metadata(metadata: Self::Metadata) -> Result<Layout, LayoutError> {
Layout::array::<T>(metadata)
}
#[inline]
fn ptr_from_raw_parts(data: *const u8, metadata: Self::Metadata) -> *const Self {
let data = data.cast::<T>();
ptr::slice_from_raw_parts(data, metadata)
}
#[inline]
fn ptr_from_raw_parts_mut(data: *mut u8, metadata: Self::Metadata) -> *mut Self {
let data = data.cast::<T>();
ptr::slice_from_raw_parts_mut(data, metadata)
}
#[inline]
fn ptr_dangling_with_metadata(metadata: Self::Metadata) -> *const Self {
let data = dangling::<T>();
ptr::slice_from_raw_parts(data, metadata)
}
#[inline]
fn ptr_dangling_with_metadata_mut(metadata: Self::Metadata) -> *mut Self {
let data = dangling_mut::<T>();
ptr::slice_from_raw_parts_mut(data, metadata)
}
}
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 layout_for_metadata(metadata: Self::Metadata) -> Result<Layout, LayoutError> {
<[u8]>::layout_for_metadata(metadata)
}
#[inline(always)]
fn ptr_from_raw_parts(data: *const u8, metadata: Self::Metadata) -> *const Self {
<[u8]>::ptr_from_raw_parts(data, metadata) as *const Self
}
#[inline(always)]
fn ptr_from_raw_parts_mut(data: *mut u8, metadata: Self::Metadata) -> *mut Self {
<[u8]>::ptr_from_raw_parts_mut(data, metadata) as *mut Self
}
#[inline(always)]
fn ptr_dangling_with_metadata(metadata: Self::Metadata) -> *const Self {
<[u8]>::ptr_dangling_with_metadata(metadata) as *const Self
}
#[inline(always)]
fn ptr_dangling_with_metadata_mut(metadata: Self::Metadata) -> *mut Self {
<[u8]>::ptr_dangling_with_metadata_mut(metadata) as *mut Self
}
}