#![deny(
missing_docs,
clippy::missing_panics_doc,
clippy::missing_const_for_fn,
clippy::missing_safety_doc,
clippy::missing_errors_doc,
// clippy::undocumented_unsafe_blocks
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(stabby_nightly, feature(freeze))]
#[cfg(feature = "alloc-rs")]
extern crate alloc as alloc_rs;
pub mod alloc;
pub mod num;
pub use stabby_macros::{canary_suffixes, dynptr, export, import, stabby, vtable as vtmacro};
use typenum2::unsigned::Alignment;
use core::fmt::{Debug, Display};
pub const fn assert_stable<T: IStable>() {}
pub use tuple::Tuple2 as Tuple;
#[macro_export]
macro_rules! primitive_report {
($name: expr, $ty: ty) => {
const REPORT: &'static $crate::report::TypeReport = &$crate::report::TypeReport {
name: $crate::str::Str::new($name),
module: $crate::str::Str::new(core::module_path!()),
fields: $crate::StableLike::new(Some(&$crate::report::FieldReport {
name: $crate::str::Str::new("inner"),
ty: <$ty as $crate::IStable>::REPORT,
next_field: $crate::StableLike::new(None),
})),
version: 0,
tyty: $crate::report::TyTy::Struct,
};
const ID: u64 = $crate::report::gen_id(Self::REPORT);
};
($name: expr) => {
const REPORT: &'static $crate::report::TypeReport = &$crate::report::TypeReport {
name: $crate::str::Str::new($name),
module: $crate::str::Str::new(core::module_path!()),
fields: $crate::StableLike::new(None),
version: 0,
tyty: $crate::report::TyTy::Struct,
};
const ID: u64 = $crate::report::gen_id(Self::REPORT);
};
}
pub mod typenum2;
use istable::{ISaturatingAdd, Saturator};
#[doc(hidden)]
pub use typenum2::*;
pub use rustversion as __rustversion;
#[macro_export]
macro_rules! impl_vtable_constructor {
($pre178: item => $post178: item) => {
#[$crate::__rustversion::before(1.78.0)]
$pre178
#[$crate::__rustversion::since(1.78.0)]
$post178
};
}
#[macro_export]
macro_rules! assert_optimal_layout {
($t: ty) => {
const _: () = {
assert!(<$t>::has_optimal_layout());
};
};
}
pub use crate::enums::IDeterminantProvider;
pub mod as_mut;
pub mod iter;
pub trait AccessAs {
fn ref_as<T: ?Sized>(&self) -> <Self as as_mut::IGuardRef<T>>::Guard<'_>
where
Self: as_mut::IGuardRef<T>;
fn mut_as<T: ?Sized>(&mut self) -> <Self as as_mut::IGuardMut<T>>::GuardMut<'_>
where
Self: as_mut::IGuardMut<T>;
}
pub use fatptr::*;
mod fatptr;
pub mod closure;
pub mod future;
mod stable_impls;
pub mod vtable;
pub struct AssertStable<T: IStable>(pub core::marker::PhantomData<T>);
impl<T: IStable> AssertStable<T> {
pub const fn assert() -> Self {
Self(core::marker::PhantomData)
}
}
#[repr(C)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StableLike<T, As> {
value: T,
marker: core::marker::PhantomData<As>,
}
impl<T: Debug, As> Debug for StableLike<T, As> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.value.fmt(f)
}
}
impl<T: Display, As> Display for StableLike<T, As> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.value.fmt(f)
}
}
impl<T: Clone, As> Clone for StableLike<T, As> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
marker: self.marker,
}
}
}
impl<T: Copy, As> Copy for StableLike<T, As> {}
trait ConstChecks {
const CHECK: ();
}
impl<T, As: IStable> ConstChecks for StableLike<T, As> {
const CHECK: () = {
if core::mem::size_of::<T>() != <As::Size as Unsigned>::USIZE {
panic!(
"Attempted to construct `StableLike<T, As>` despite As::Size not matching T's size"
)
}
if core::mem::align_of::<T>() != <As::Align as Unsigned>::USIZE {
panic!(
"Attempted to construct `StableLike<T, As>` despite As::Size not matching T's size"
)
}
};
}
impl<T, As: IStable> StableLike<T, As> {
#[allow(clippy::let_unit_value)]
pub const fn new(value: T) -> Self {
_ = Self::CHECK;
Self {
value,
marker: core::marker::PhantomData,
}
}
pub const unsafe fn as_ref_unchecked(&self) -> &T {
&self.value
}
pub const fn as_ref(&self) -> &T
where
T: IStable,
{
&self.value
}
#[rustversion::attr(since(1.86), const)]
pub unsafe fn as_mut_unchecked(&mut self) -> &mut T {
&mut self.value
}
pub unsafe fn into_inner_unchecked(self) -> T {
self.value
}
pub fn into_inner(self) -> T
where
T: IStable,
{
self.value
}
}
unsafe impl<T, As: IStable> IStable for StableLike<T, As> {
type Size = As::Size;
type Align = As::Align;
type ForbiddenValues = As::ForbiddenValues;
type UnusedBits = As::UnusedBits;
type HasExactlyOneNiche = As::HasExactlyOneNiche;
type ContainsIndirections = As::ContainsIndirections;
#[cfg(feature = "experimental-ctypes")]
type CType = As::CType;
const ID: u64 = crate::report::gen_id(Self::REPORT);
const REPORT: &'static report::TypeReport = As::REPORT;
}
pub struct NoNiches<
Size: Unsigned,
Align: Alignment,
HasExactlyOneNiche: ISaturatingAdd = Saturator,
ContainsIndirections: Bit = B0,
>(
Size::Padding,
core::marker::PhantomData<(Size, Align, HasExactlyOneNiche, ContainsIndirections)>,
);
unsafe impl<
Size: Unsigned,
Align: Alignment,
HasExactlyOneNiche: ISaturatingAdd,
ContainsIndirections: Bit,
> IStable for NoNiches<Size, Align, HasExactlyOneNiche, ContainsIndirections>
{
type Size = Size;
type Align = Align;
type ForbiddenValues = End;
type UnusedBits = End;
type HasExactlyOneNiche = HasExactlyOneNiche;
type ContainsIndirections = ContainsIndirections;
#[cfg(feature = "experimental-ctypes")]
type CType = ();
primitive_report!("NoNiches");
}
#[repr(C)]
pub struct StableIf<T, Cond> {
pub value: T,
marker: core::marker::PhantomData<Cond>,
}
impl<T: Clone, Cond> Clone for StableIf<T, Cond> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
marker: self.marker,
}
}
}
impl<T: Copy, Cond> Copy for StableIf<T, Cond> {}
impl<T, Cond> StableIf<T, Cond> {
pub const unsafe fn new(value: T) -> Self {
Self {
value,
marker: core::marker::PhantomData,
}
}
}
impl<T, Cond> core::ops::Deref for StableIf<T, Cond> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T, Cond> core::ops::DerefMut for StableIf<T, Cond> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.value
}
}
unsafe impl<T: IStable, Cond: IStable> IStable for StableIf<T, Cond> {
type Size = T::Size;
type Align = T::Align;
type ForbiddenValues = T::ForbiddenValues;
type UnusedBits = T::UnusedBits;
type HasExactlyOneNiche = T::HasExactlyOneNiche;
type ContainsIndirections = T::ContainsIndirections;
#[cfg(feature = "experimental-ctypes")]
type CType = T::CType;
const REPORT: &'static report::TypeReport = T::REPORT;
const ID: u64 = crate::report::gen_id(Self::REPORT);
}
#[repr(C)]
#[derive(Default, Clone, Copy)]
pub struct FieldPair<A, B>(core::marker::PhantomData<(A, B)>);
#[repr(transparent)]
pub struct Struct<T>(T);
pub struct AlignedStruct<T, Align>(core::marker::PhantomData<(T, Align)>);
#[repr(C)]
pub union Union<A, B> {
pub ok: core::mem::ManuallyDrop<A>,
pub err: core::mem::ManuallyDrop<B>,
}
impl<A, B> Clone for Union<A, B> {
fn clone(&self) -> Self {
unsafe { core::ptr::read(self) }
}
}
pub mod checked_import;
pub mod enums;
pub mod result;
pub use result::Result;
pub mod option;
pub use option::Option;
pub mod report;
pub mod slice;
pub mod str;
pub mod tuple {
include!(concat!(env!("OUT_DIR"), "/tuples.rs"));
}
pub use istable::{Array, End, IStable};
pub mod istable;
#[macro_export]
macro_rules! unreachable_unchecked {
() => {
if cfg!(any(debug_assertions, stabby_check_unreachable = "true")) {
::core::unreachable!()
} else {
::core::hint::unreachable_unchecked()
}
};
}
#[macro_export]
macro_rules! assert_unchecked {
($e: expr, $($t: tt)*) => {
if cfg!(any(debug_assertions, stabby_check_unreachable = "true")) {
::core::assert!($e, $($t)*);
} else {
if !$e {
::core::hint::unreachable_unchecked();
}
}
};
}
#[macro_export]
macro_rules! assert_eq_unchecked {
($a: expr, $b: expr, $($t: tt)*) => {
if cfg!(any(debug_assertions, stabby_check_unreachable = "true")) {
::core::assert_eq!($a, $b, $($t)*);
} else {
if $a != $b {
::core::hint::unreachable_unchecked();
}
}
};
}