#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "alloc")]
extern crate alloc;
mod _alloc;
mod _box;
mod _str;
mod _string;
pub use _alloc::*;
pub use _box::*;
pub use _str::*;
pub use _string::*;
pub mod till_null;
#[cfg(feature = "macros")]
pub use seasick_macros::TransmuteFrom;
#[expect(clippy::missing_safety_doc)]
pub unsafe trait TransmuteFrom<T: Sized>: Sized {
#[expect(clippy::missing_safety_doc)]
unsafe fn transmute_from(src: T) -> Self;
}
#[expect(clippy::missing_safety_doc)]
pub unsafe trait TransmuteRefFrom<T: ?Sized> {
#[expect(clippy::missing_safety_doc)]
unsafe fn transmute_ref(src: &T) -> &Self;
}
#[expect(clippy::missing_safety_doc)]
pub unsafe trait TransmuteMutFrom<T: ?Sized> {
#[expect(clippy::missing_safety_doc)]
unsafe fn transmute_mut(src: &mut T) -> &mut Self;
}
unsafe impl<T, U> TransmuteRefFrom<T> for U
where
U: TransmuteFrom<T>,
{
unsafe fn transmute_ref(src: &T) -> &Self {
let src = src as *const T as *const U;
unsafe { &*src }
}
}
unsafe impl<T, U> TransmuteMutFrom<T> for U
where
U: TransmuteFrom<T>,
{
unsafe fn transmute_mut(src: &mut T) -> &mut Self {
let src = src as *mut T as *mut U;
unsafe { &mut *src }
}
}
#[macro_export]
macro_rules! assert_abi {
(fn $left:path = $right:path as $ty:ty $(; $($tt:tt)*)?) => {
const _: () = {
let _ = $left as $ty;
let _ = $right as $ty;
$crate::__private::assert!($crate::__private::abi_eq($left as $ty, $right as $ty));
};
$(
$crate::assert_abi!($($tt)*);
)?
};
(#[non_exhaustive] struct $left_ty:path = $right_ty:path {
$($left_field:ident = $right_field:ident),* $(,)?
} $(; $($tt:tt)*)?) => {
$crate::assert_abi! {
__struct $left_ty = $right_ty {
$($left_field = $right_field,)*
}
}
$(
$crate::assert_abi!($($tt)*);
)?
};
(struct $left_ty:path = $right_ty:path {
$($left_field:ident = $right_field:ident),* $(,)?
} $(; $($tt:tt)*)?) => {
$crate::assert_abi! {
__struct $left_ty = $right_ty {
$($left_field = $right_field,)*
}
}
const _: () = {
fn exhaustive($left_ty { $($left_field: _),* }: $left_ty, $right_ty { $($right_field: _),* }: $right_ty) {}
};
$(
$crate::assert_abi!($($tt)*);
)?
};
(__struct $left_ty:path = $right_ty:path {
$($left_field:ident = $right_field:ident),* $(,)?
} $(; $($tt:tt)*)?) => {
const _: () = {
use $crate::__private::*;
let left = Layout::new::<$left_ty>();
let right = Layout::new::<$right_ty>();
assert! {
left.size() == right.size(),
concat!("size mismatch between ", stringify!($left_ty), " and ", stringify!($right_ty))
};
assert! {
left.align() == right.align(),
concat!("aligment mismatch between ", stringify!($left_ty), " and ", stringify!($right_ty))
};
$(
assert! {
offset_of!($left_ty, $left_field) == offset_of!($right_ty, $right_field),
concat!("mismatched offsets between ", stringify!($left_field), " and ", stringify!($right_field))
};
let left = layout_of_field(|it: &$left_ty| &it.$left_field);
let right = layout_of_field(|it: &$right_ty| &it.$right_field);
assert! {
left.size() == right.size(),
concat!("size mismatch between ", stringify!($left_field), " and ", stringify!($right_field))
};
assert! {
left.align() == right.align(),
concat!("aligment mismatch between ", stringify!($left_field), " and ", stringify!($right_field))
};
)*
};
};
($(;)?) => {}; }
#[doc(hidden)]
pub mod __private {
pub use core;
pub const fn layout_of_field<T, U>(_: fn(&T) -> &U) -> Layout {
Layout::new::<U>()
}
pub use ::core::{alloc::Layout, assert, concat, mem::offset_of, stringify};
pub trait AbiEq<T> {
const ABI_EQ: bool;
}
macro_rules! define {
($($l:ident $r:ident)*) => {
impl<LR, RR, $($l, $r),*> AbiEq<fn($($l),*) -> LR> for fn($($r),*) -> RR {
const ABI_EQ: bool = layout_eq::<LR, RR>() $(&& layout_eq::<$l, $r>())*;
}
impl<LR, RR, $($l, $r),*> AbiEq<unsafe fn($($l),*) -> LR> for unsafe fn($($r),*) -> RR {
const ABI_EQ: bool = layout_eq::<LR, RR>() $(&& layout_eq::<$l, $r>())*;
}
impl<LR, RR, $($l, $r),*> AbiEq<extern "C" fn($($l),*) -> LR> for extern "C" fn($($r),*) -> RR {
const ABI_EQ: bool = layout_eq::<LR, RR>() $(&& layout_eq::<$l, $r>())*;
}
impl<LR, RR, $($l, $r),*> AbiEq<unsafe extern "C" fn($($l),*) -> LR> for unsafe extern "C" fn($($r),*) -> RR {
const ABI_EQ: bool = layout_eq::<LR, RR>() $(&& layout_eq::<$l, $r>())*;
}
};
}
define!();
define!(L0 R0);
define!(L0 R0 L1 R1);
define!(L0 R0 L1 R1 L2 R2);
define!(L0 R0 L1 R1 L2 R2 L3 R3);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9 L10 R10);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9 L10 R10 L11 R11);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9 L10 R10 L11 R11 L12 R12);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9 L10 R10 L11 R11 L12 R12 L13 R13);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9 L10 R10 L11 R11 L12 R12 L13 R13 L14 R14);
define!(L0 R0 L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7 L8 R8 L9 R9 L10 R10 L11 R11 L12 R12 L13 R13 L14 R14 L15 R15);
const fn layout_eq<L, R>() -> bool {
let left = Layout::new::<L>();
let right = Layout::new::<R>();
left.size() == right.size() && left.align() == right.align()
}
pub const fn abi_eq<L, R>(_: L, _: R) -> bool
where
L: AbiEq<R>,
L: Copy,
R: Copy,
{
L::ABI_EQ
}
}