use core_extensions::type_level_bool::{Boolean, False, True};
use std::{
fmt,
marker::PhantomData,
mem::ManuallyDrop,
num,
pin::Pin,
ptr::NonNull,
sync::atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize},
};
use crate::{
std_types::{RNone, RSome, StaticSlice, StaticStr,utypeid::UTypeId},
return_value_equality::ReturnValueEquality,
};
use super::{LifetimeIndex, RustPrimitive, TLData, TLField, TypeLayout, TypeLayoutParams};
pub unsafe trait StableAbi:SharedStableAbi<Kind=ValueKind> {
const LAYOUT: &'static TypeLayout;
const ABI_INFO: &'static AbiInfoWrapper;
}
pub unsafe trait SharedStableAbi {
type IsNonZeroType: Boolean;
type Kind:TypeKindTrait;
type StaticEquivalent:'static;
const S_LAYOUT: &'static TypeLayout;
const S_ABI_INFO: &'static AbiInfoWrapper = {
let info = AbiInfo {
kind:<Self::Kind as TypeKindTrait>::VALUE,
prefix_kind: <Self::Kind as TypeKindTrait>::IS_PREFIX,
type_id:make_rve_utypeid!(Self::StaticEquivalent),
is_nonzero: <Self::IsNonZeroType as Boolean>::VALUE,
layout: Self::S_LAYOUT,
};
&AbiInfoWrapper::new(info)
};
}
unsafe impl<This> StableAbi for This
where
This:SharedStableAbi<Kind=ValueKind>,
{
const LAYOUT: &'static TypeLayout=<This as SharedStableAbi>::S_LAYOUT;
const ABI_INFO: &'static AbiInfoWrapper=<This as SharedStableAbi>::S_ABI_INFO;
}
pub type StaticEquivalent<T>=
<T as SharedStableAbi>::StaticEquivalent;
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
#[derive(StableAbi)]
#[sabi(inside_abi_stable_crate)]
pub struct AbiInfoWrapper {
inner: AbiInfo,
_priv: (),
}
impl AbiInfoWrapper {
const fn new(inner: AbiInfo) -> Self {
Self { inner, _priv: () }
}
pub const unsafe fn new_unchecked(inner: AbiInfo) -> Self {
Self::new(inner)
}
pub const fn get(&self) -> &AbiInfo {
&self.inner
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
#[derive(StableAbi)]
#[sabi(inside_abi_stable_crate)]
pub struct AbiInfo {
pub kind:TypeKind,
pub prefix_kind: bool,
pub type_id:ReturnValueEquality<UTypeId>,
pub is_nonzero: bool,
pub layout: &'static TypeLayout,
}
impl AbiInfo{
pub fn get_utypeid(&self)->UTypeId{
(self.type_id.function)()
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq,Eq,Ord,PartialOrd,Hash,StableAbi)]
#[sabi(inside_abi_stable_crate)]
pub enum TypeKind{
Value,
Prefix,
}
pub trait TypeKindTrait:sealed::Sealed{
const VALUE:TypeKind;
const IS_PREFIX:bool;
}
pub struct ValueKind;
pub struct PrefixKind;
mod sealed{
pub trait Sealed{}
}
impl sealed::Sealed for ValueKind{}
impl sealed::Sealed for PrefixKind{}
impl TypeKindTrait for ValueKind {
const VALUE:TypeKind=TypeKind::Value;
const IS_PREFIX:bool=false;
}
impl TypeKindTrait for PrefixKind {
const VALUE:TypeKind=TypeKind::Prefix;
const IS_PREFIX:bool=true;
}
#[derive(Copy, Clone)]
#[repr(transparent)]
#[derive(StableAbi)]
#[sabi(inside_abi_stable_crate)]
pub struct GetAbiInfo {
abi_info: extern "C" fn() -> &'static AbiInfo,
}
impl fmt::Debug for GetAbiInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.get(), f)
}
}
impl GetAbiInfo {
pub fn get(self) -> &'static AbiInfo {
(self.abi_info)()
}
}
pub unsafe trait MakeGetAbiInfo<B> {
const CONST: GetAbiInfo;
}
unsafe impl<T> MakeGetAbiInfo<StableAbi_Bound> for T
where
T: StableAbi,
{
const CONST: GetAbiInfo = GetAbiInfo {
abi_info: get_abi_info::<T>,
};
}
unsafe impl<T> MakeGetAbiInfo<SharedStableAbi_Bound> for T
where
T: SharedStableAbi,
{
const CONST: GetAbiInfo = GetAbiInfo {
abi_info: get_ssa_abi_info::<T>,
};
}
unsafe impl<T> MakeGetAbiInfo<UnsafeOpaqueField_Bound> for T {
const CONST: GetAbiInfo = GetAbiInfo {
abi_info: get_abi_info::<UnsafeOpaqueField<T>>,
};
}
#[allow(non_camel_case_types)]
pub struct StableAbi_Bound;
#[allow(non_camel_case_types)]
pub struct SharedStableAbi_Bound;
#[allow(non_camel_case_types)]
pub struct UnsafeOpaqueField_Bound;
pub extern "C" fn get_abi_info<T>() -> &'static AbiInfo
where
T: StableAbi,
{
T::ABI_INFO.get()
}
pub extern "C" fn get_ssa_abi_info<T>() -> &'static AbiInfo
where
T: SharedStableAbi,
{
T::S_ABI_INFO.get()
}
unsafe impl<T> SharedStableAbi for PhantomData<T>
where T:StableAbi
{
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=PhantomData<T::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"PhantomData",
RNone,
TLData::Primitive,
tl_genparams!(;;),
&[TLField::new("0",&[],<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,)],
);
}
unsafe impl SharedStableAbi for () {
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=();
const S_LAYOUT: &'static TypeLayout =
&TypeLayout::from_std_lib::<Self>("()", TLData::Primitive, tl_genparams!(;;));
}
unsafe impl SharedStableAbi for core_extensions::Void {
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=Self;
const S_LAYOUT: &'static TypeLayout =
&TypeLayout::from_std_lib::<Self>("Void", TLData::Primitive, tl_genparams!(;;));
}
unsafe impl<'a, T> SharedStableAbi for &'a T
where
T: 'a + SharedStableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = True;
type StaticEquivalent=&'static T::StaticEquivalent;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"&",
RSome(RustPrimitive::Reference),
TLData::Primitive,
tl_genparams!('a;T;),
&[TLField::new(
"0",
&[LifetimeIndex::Param(0)],
<T as MakeGetAbiInfo<SharedStableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<'a, T> SharedStableAbi for &'a mut T
where
T: 'a + StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = True;
type StaticEquivalent=&'static mut T::StaticEquivalent;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"&mut",
RSome(RustPrimitive::MutReference),
TLData::Primitive,
tl_genparams!('a;T;),
&[TLField::new(
"0",
&[LifetimeIndex::Param(0)],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<T> SharedStableAbi for NonNull<T>
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = True;
type StaticEquivalent=NonNull<T::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"NonNull",
RNone,
TLData::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<T> SharedStableAbi for AtomicPtr<T>
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=AtomicPtr<T::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"AtomicPtr",
RNone,
TLData::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<T> SharedStableAbi for *const T
where
T: SharedStableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=*const T::StaticEquivalent;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"*const",
RSome(RustPrimitive::ConstPtr),
TLData::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<SharedStableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<T> SharedStableAbi for *mut T
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=*mut T::StaticEquivalent;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"*mut",
RSome(RustPrimitive::MutPtr),
TLData::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
macro_rules! impl_stable_abi_array {
($($size:expr),*)=>{
$(
unsafe impl<T> SharedStableAbi for [T;$size]
where T:StableAbi
{
type Kind=ValueKind;
type IsNonZeroType=False;
type StaticEquivalent=[T::StaticEquivalent;$size];
const S_LAYOUT:&'static TypeLayout=&TypeLayout::from_std_lib_phantom::<Self>(
stringify!(concat!("[_;",stringify!($size),"]")),
RSome(RustPrimitive::Array),
TLData::Primitive,
tl_genparams!(;T;$size),
&[TLField::new("0", &[], <T as MakeGetAbiInfo<SharedStableAbi_Bound>>::CONST)],
);
}
)*
}
}
impl_stable_abi_array! {
00,01,02,03,04,05,06,07,08,09,
10,11,12,13,14,15,16,17,18,19,
20,21,22,23,24,25,26,27,28,29,
30,31,32
}
unsafe impl<T> SharedStableAbi for Option<T>
where
T: StableAbi<IsNonZeroType = True>,
{
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=Option<T::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib_phantom::<Self>(
"Option",
RNone,
TLData::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
macro_rules! impl_for_concrete {
(
zeroable=[$( $zeroable:ty ,)*]
nonzero=[ $( $nonzero:ty ,)* ]
) => (
$(
unsafe impl SharedStableAbi for $zeroable {
type Kind=ValueKind;
type IsNonZeroType=False;
type StaticEquivalent=Self;
const S_LAYOUT:&'static TypeLayout=&TypeLayout::from_std_lib::<Self>(
stringify!($zeroable),
TLData::Primitive,
tl_genparams!(;;),
);
}
)*
$(
unsafe impl SharedStableAbi for $nonzero {
type Kind=ValueKind;
type IsNonZeroType=True;
type StaticEquivalent=Self;
const S_LAYOUT:&'static TypeLayout=&TypeLayout::from_std_lib::<Self>(
stringify!($nonzero),
TLData::Primitive,
tl_genparams!(;;),
);
}
)*
)
}
impl_for_concrete! {
zeroable=[
u8,i8,
u16,i16,
u32,i32,
u64,i64,
usize,isize,
bool,
AtomicBool,
AtomicIsize,
AtomicUsize,
]
nonzero=[
num::NonZeroU8,
num::NonZeroU16,
num::NonZeroU32,
num::NonZeroU64,
num::NonZeroUsize,
]
}
#[cfg(any(rust_1_34,feature="rust_1_34"))]
mod rust_1_34_impls{
use super::*;
use std::sync::atomic;
use core::num as core_num;
impl_for_concrete! {
zeroable=[
atomic::AtomicI16,
atomic::AtomicI32,
atomic::AtomicI64,
atomic::AtomicI8,
atomic::AtomicU16,
atomic::AtomicU32,
atomic::AtomicU64,
atomic::AtomicU8,
]
nonzero=[
core_num::NonZeroI8,
core_num::NonZeroI16,
core_num::NonZeroI32,
core_num::NonZeroI64,
core_num::NonZeroIsize,
]
}
}
unsafe impl<N> SharedStableAbi for num::Wrapping<N>
where
N: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = N::IsNonZeroType;
type StaticEquivalent=num::Wrapping<N::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib::<Self>(
"num::Wrapping",
TLData::struct_(&[
TLField::new("0",&[],<N as MakeGetAbiInfo<StableAbi_Bound>>::CONST,)
]),
tl_genparams!(;N;),
);
}
unsafe impl<P> SharedStableAbi for Pin<P>
where
P: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = P::IsNonZeroType;
type StaticEquivalent=Pin<P::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib::<Self>(
"Pin",
TLData::struct_(&[
TLField::new("0",&[],<P as MakeGetAbiInfo<StableAbi_Bound>>::CONST,)
]),
tl_genparams!(;P;),
);
}
unsafe impl<T> SharedStableAbi for ManuallyDrop<T>
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = T::IsNonZeroType;
type StaticEquivalent=ManuallyDrop<T::StaticEquivalent>;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_lib::<Self>(
"ManuallyDrop",
TLData::struct_(&[
TLField::new("0",&[],<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,)
]),
tl_genparams!(;T;),
);
}
macro_rules! empty_extern_fn_layout{
($this:ty) => (
&TypeLayout::from_params::<extern "C" fn()>(TypeLayoutParams {
name: "AFunctionPointer",
package: env!("CARGO_PKG_NAME"),
package_version: crate::version::VersionStrings {
major: StaticStr::new(env!("CARGO_PKG_VERSION_MAJOR")),
minor: StaticStr::new(env!("CARGO_PKG_VERSION_MINOR")),
patch: StaticStr::new(env!("CARGO_PKG_VERSION_PATCH")),
},
file:"<unavailable>",
line:0,
data: TLData::Struct {
fields: StaticSlice::new(&[]),
},
generics: tl_genparams!(;;),
phantom_fields: &[],
})
)
}
unsafe impl SharedStableAbi for extern "C" fn() {
type Kind=ValueKind;
type IsNonZeroType = True;
type StaticEquivalent=Self;
const S_LAYOUT: &'static TypeLayout = empty_extern_fn_layout!(Self);
}
unsafe impl SharedStableAbi for unsafe extern "C" fn() {
type Kind=ValueKind;
type IsNonZeroType = True;
type StaticEquivalent=Self;
const S_LAYOUT: &'static TypeLayout = empty_extern_fn_layout!(Self);
}
#[repr(transparent)]
pub struct UnsafeOpaqueField<T>(T);
unsafe impl<T> SharedStableAbi for UnsafeOpaqueField<T> {
type Kind=ValueKind;
type IsNonZeroType = False;
type StaticEquivalent=();
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_params::<Self>(TypeLayoutParams {
name: "OpaqueField",
package: env!("CARGO_PKG_NAME"),
package_version: crate::version::VersionStrings {
major: StaticStr::new(env!("CARGO_PKG_VERSION_MAJOR")),
minor: StaticStr::new(env!("CARGO_PKG_VERSION_MINOR")),
patch: StaticStr::new(env!("CARGO_PKG_VERSION_PATCH")),
},
file:"<unavailable>",
line:0,
data: TLData::Primitive,
generics: tl_genparams!(;;),
phantom_fields: &[],
});
}