use core_extensions::type_level_bool::{Boolean, False, True};
use std::{
cell::{Cell,UnsafeCell},
cmp::{Eq,PartialEq},
fmt,
marker::{PhantomData,PhantomPinned},
mem::ManuallyDrop,
num::{NonZeroU8,NonZeroU16,NonZeroU32,NonZeroU64,NonZeroUsize,Wrapping},
pin::Pin,
ptr::NonNull,
sync::atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize},
};
use crate::{
abi_stability::get_static_equivalent::GetStaticEquivalent_,
std_types::{RNone, RSome, utypeid::UTypeId},
sabi_types::ReturnValueEquality,
reflection::ModReflMode,
type_layout::{
LifetimeIndex, TLData, TLField, TypeLayout, TypeLayoutParams,
ItemInfo,ReprAttr,TLPrimitive,TLEnum,TLDiscriminants,IsExhaustive,
},
};
pub unsafe trait StableAbi:SharedStableAbi<Kind=ValueKind> {
const LAYOUT: &'static TypeLayout;
const ABI_INFO: &'static AbiInfoWrapper;
}
pub unsafe trait SharedStableAbi:GetStaticEquivalent_ {
type IsNonZeroType: Boolean;
type Kind:TypeKindTrait;
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;
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
#[derive(StableAbi)]
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)]
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(u8)]
#[derive(Debug, Copy, Clone, PartialEq,Eq,Ord,PartialOrd,Hash,StableAbi)]
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)]
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)()
}
}
impl Eq for GetAbiInfo{}
impl PartialEq for GetAbiInfo{
fn eq(&self,other:&Self)->bool{
self.get()==other.get()
}
}
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>>,
};
}
#[doc(hidden)]
pub struct MakeGetAbiInfoSA<T>(T);
impl<T> MakeGetAbiInfoSA<T>
where T: StableAbi,
{
pub const STABLE_ABI:GetAbiInfo=GetAbiInfo {
abi_info: get_abi_info::<T>,
};
}
#[doc(hidden)]
pub struct MakeGetAbiInfoUF<T>(T);
impl<T> MakeGetAbiInfoUF<T>{
pub const OPAQUE_FIELD: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> GetStaticEquivalent_ for PhantomData<T>
where T:GetStaticEquivalent_
{
type StaticEquivalent=PhantomData<T::StaticEquivalent>;
}
unsafe impl<T> SharedStableAbi for PhantomData<T>
where T:StableAbi
{
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"PhantomData",
RNone,
ItemInfo::std_type_in("std::marker"),
TLData::EMPTY,
ReprAttr::c(),
tl_genparams!(;;),
&[TLField::new("0",&[],<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,)],
);
}
unsafe impl GetStaticEquivalent_ for () {
type StaticEquivalent=();
}
unsafe impl SharedStableAbi for () {
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout =
&TypeLayout::from_std::<Self>(
"()",
TLData::EMPTY,
ReprAttr::c(),
ItemInfo::primitive(),
tl_genparams!(;;)
);
}
unsafe impl<'a, T> GetStaticEquivalent_ for &'a T
where
T: 'a + GetStaticEquivalent_,
{
type StaticEquivalent=&'static T::StaticEquivalent;
}
unsafe impl<'a, T> SharedStableAbi for &'a T
where
T: 'a + SharedStableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = True;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"&",
RSome(TLPrimitive::SharedRef),
ItemInfo::primitive(),
TLData::Primitive(TLPrimitive::SharedRef),
ReprAttr::Primitive,
tl_genparams!('a;T;),
&[TLField::new(
"0",
&[LifetimeIndex::Param(0)],
<T as MakeGetAbiInfo<SharedStableAbi_Bound>>::CONST,
)],
).set_mod_refl_mode(ModReflMode::DelegateDeref{phantom_field_index:0});
}
unsafe impl<'a, T> GetStaticEquivalent_ for &'a mut T
where
T: 'a + GetStaticEquivalent_,
{
type StaticEquivalent=&'static mut T::StaticEquivalent;
}
unsafe impl<'a, T> SharedStableAbi for &'a mut T
where
T: 'a + StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = True;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"&mut",
RSome(TLPrimitive::MutRef),
ItemInfo::primitive(),
TLData::Primitive(TLPrimitive::MutRef),
ReprAttr::Primitive,
tl_genparams!('a;T;),
&[TLField::new(
"0",
&[LifetimeIndex::Param(0)],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<T> GetStaticEquivalent_ for NonNull<T>
where
T: GetStaticEquivalent_,
{
type StaticEquivalent=NonNull<T::StaticEquivalent>;
}
unsafe impl<T> SharedStableAbi for NonNull<T>
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = True;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"NonNull",
RNone,
ItemInfo::std_type_in("std::ptr"),
TLData::struct_(&[
TLField::new(
"0",
&[],
<*mut T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)
]),
ReprAttr::Transparent,
tl_genparams!(;T;),
&[],
);
}
unsafe impl<T> GetStaticEquivalent_ for AtomicPtr<T>
where
T: GetStaticEquivalent_,
{
type StaticEquivalent=AtomicPtr<T::StaticEquivalent>;
}
unsafe impl<T> SharedStableAbi for AtomicPtr<T>
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"AtomicPtr",
RNone,
ItemInfo::std_type_in("std::sync::atomic"),
TLData::struct_(&[
TLField::new(
"0",
&[],
<*mut T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)
]),
ReprAttr::Transparent,
tl_genparams!(;T;),
&[],
);
}
unsafe impl<T> GetStaticEquivalent_ for *const T
where
T: GetStaticEquivalent_,
{
type StaticEquivalent=*const T::StaticEquivalent;
}
unsafe impl<T> SharedStableAbi for *const T
where
T: SharedStableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"*const",
RSome(TLPrimitive::ConstPtr),
ItemInfo::primitive(),
TLData::Primitive(TLPrimitive::ConstPtr),
ReprAttr::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<SharedStableAbi_Bound>>::CONST,
)],
);
}
unsafe impl<T> GetStaticEquivalent_ for *mut T
where
T: GetStaticEquivalent_,
{
type StaticEquivalent=*mut T::StaticEquivalent;
}
unsafe impl<T> SharedStableAbi for *mut T
where
T: StableAbi,
{
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"*mut",
RSome(TLPrimitive::MutPtr),
ItemInfo::primitive(),
TLData::Primitive(TLPrimitive::MutPtr),
ReprAttr::Primitive,
tl_genparams!(;T;),
&[TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)],
);
}
macro_rules! impl_stable_abi_array {
($($size:expr),*)=>{
$(
unsafe impl<T> GetStaticEquivalent_ for [T;$size]
where T:GetStaticEquivalent_
{
type StaticEquivalent=[T::StaticEquivalent;$size];
}
unsafe impl<T> SharedStableAbi for [T;$size]
where T:StableAbi
{
type Kind=ValueKind;
type IsNonZeroType=False;
const S_LAYOUT:&'static TypeLayout=&TypeLayout::from_std_full::<Self>(
"array",
RSome(TLPrimitive::Array{len:$size}),
ItemInfo::primitive(),
TLData::Primitive(TLPrimitive::Array{len:$size}),
ReprAttr::Primitive,
tl_genparams!(;T;$size),
&[
TLField::new(
"element",
&[],
<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> GetStaticEquivalent_ for Option<T>
where
T: GetStaticEquivalent_,
{
type StaticEquivalent=Option<T::StaticEquivalent>;
}
unsafe impl<T> SharedStableAbi for Option<T>
where
T: StableAbi<IsNonZeroType = True>,
{
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std_full::<Self>(
"Option",
RNone,
ItemInfo::primitive(),
TLData::Enum(&TLEnum::new(
"Some;None;",
IsExhaustive::exhaustive(),
&[
TLField::new(
"0",
&[],
<T as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)
],
TLDiscriminants::from_u8_slice(&[0,1]),
&[1,0]
)),
ReprAttr::OptionNonZero,
tl_genparams!(;T;),
&[],
);
}
macro_rules! impl_for_primitive_ints {
(
$( ($zeroable:ty,$tl_primitive:expr) ,)*
) => (
$(
unsafe impl GetStaticEquivalent_ for $zeroable {
type StaticEquivalent=Self;
}
unsafe impl SharedStableAbi for $zeroable {
type Kind=ValueKind;
type IsNonZeroType=False;
const S_LAYOUT:&'static TypeLayout=&TypeLayout::from_std_full::<Self>(
stringify!($zeroable),
RSome($tl_primitive),
ItemInfo::primitive(),
TLData::Primitive($tl_primitive),
ReprAttr::Primitive,
tl_genparams!(;;),
&[],
);
}
)*
)
}
impl_for_primitive_ints!{
(u8 ,TLPrimitive::U8),
(i8 ,TLPrimitive::I8),
(u16 ,TLPrimitive::U16),
(i16 ,TLPrimitive::I16),
(u32 ,TLPrimitive::U32),
(i32 ,TLPrimitive::I32),
(u64 ,TLPrimitive::U64),
(i64 ,TLPrimitive::I64),
(usize,TLPrimitive::Usize),
(isize,TLPrimitive::Isize),
(bool ,TLPrimitive::Bool),
}
macro_rules! impl_for_concrete {
(
type IsNonZeroType=$zeroness:ty;
[
$( ($this:ty,$prim_repr:ty,$in_mod:expr) ,)*
]
) => (
$(
unsafe impl GetStaticEquivalent_ for $this {
type StaticEquivalent=Self;
}
unsafe impl SharedStableAbi for $this {
type Kind=ValueKind;
type IsNonZeroType=$zeroness;
const S_LAYOUT:&'static TypeLayout=&TypeLayout::from_std::<Self>(
stringify!($this),
TLData::struct_(&[
TLField::new(
"0",
&[],
<$prim_repr as MakeGetAbiInfo<StableAbi_Bound>>::CONST,
)
]),
ReprAttr::Transparent,
ItemInfo::std_type_in($in_mod),
tl_genparams!(;;),
);
}
)*
)
}
impl_for_concrete! {
type IsNonZeroType=False;
[
(AtomicBool ,bool,"std::sync::atomic"),
(AtomicIsize,isize,"std::sync::atomic"),
(AtomicUsize,usize,"std::sync::atomic"),
]
}
impl_for_concrete! {
type IsNonZeroType=True;
[
(NonZeroU8 ,u8,"std::num"),
(NonZeroU16 ,u16,"std::num"),
(NonZeroU32 ,u32,"std::num"),
(NonZeroU64 ,u64,"std::num"),
(NonZeroUsize,usize,"std::num"),
]
}
#[cfg(any(rust_1_34,feature="rust_1_34"))]
mod rust_1_34_impls{
use super::*;
use std::sync::atomic::*;
use core::num::*;
impl_for_concrete! {
type IsNonZeroType=False;
[
(AtomicI8 ,i8,"std::sync::atomic"),
(AtomicI16,i16,"std::sync::atomic"),
(AtomicI32,i32,"std::sync::atomic"),
(AtomicI64,i64,"std::sync::atomic"),
(AtomicU8 ,u8,"std::sync::atomic"),
(AtomicU16,u16,"std::sync::atomic"),
(AtomicU32,u32,"std::sync::atomic"),
(AtomicU64,u64,"std::sync::atomic"),
]
}
impl_for_concrete! {
type IsNonZeroType=True;
[
(NonZeroI8 ,i8,"core::num"),
(NonZeroI16 ,i16,"core::num"),
(NonZeroI32 ,i32,"core::num"),
(NonZeroI64 ,i64,"core::num"),
(NonZeroIsize,isize,"core::num"),
]
}
}
macro_rules! impl_stableabi_for_repr_transparent {
(
$type_constr:ident
$(where[ $($where_clause:tt)* ])* ,
$item_info:expr
) => (
unsafe impl<P> GetStaticEquivalent_ for $type_constr<P>
where
P: GetStaticEquivalent_,
$($($where_clause)*)*
{
type StaticEquivalent=$type_constr<P::StaticEquivalent>;
}
unsafe impl<P> SharedStableAbi for $type_constr<P>
where
P: StableAbi,
$($($where_clause)*)*
{
type Kind=ValueKind;
type IsNonZeroType = P::IsNonZeroType;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std::<Self>(
stringify!($type_constr),
TLData::struct_(&[
TLField::new("0",&[],<P as MakeGetAbiInfo<StableAbi_Bound>>::CONST,)
]),
ReprAttr::Transparent,
$item_info,
tl_genparams!(;P;),
);
}
)
}
impl_stableabi_for_repr_transparent!{ Wrapping ,ItemInfo::std_type_in("std::num") }
impl_stableabi_for_repr_transparent!{ Pin ,ItemInfo::std_type_in("std::pin") }
impl_stableabi_for_repr_transparent!{ ManuallyDrop,ItemInfo::std_type_in("std::mem") }
impl_stableabi_for_repr_transparent!{ Cell ,ItemInfo::std_type_in("std::cell") }
impl_stableabi_for_repr_transparent!{ UnsafeCell ,ItemInfo::std_type_in("std::cell") }
macro_rules! impl_stableabi_for_unit_struct {
(
$type_constr:ident,
$item_info:expr
) => (
unsafe impl GetStaticEquivalent_ for $type_constr{
type StaticEquivalent=$type_constr;
}
unsafe impl SharedStableAbi for $type_constr{
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_std::<Self>(
stringify!($type_constr),
TLData::EMPTY,
ReprAttr::c(),
$item_info,
tl_genparams!(;;),
);
}
)
}
impl_stableabi_for_unit_struct!{ PhantomPinned,ItemInfo::std_type_in("std::marker") }
unsafe impl GetStaticEquivalent_ for core_extensions::Void {
type StaticEquivalent=Self;
}
unsafe impl SharedStableAbi for core_extensions::Void {
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout =
&TypeLayout::from_params::<Self>(TypeLayoutParams {
name: "Void",
item_info:ItemInfo::package_and_mod("core_extensions;0.0.0","core_extensions"),
data: TLData::Enum(&TLEnum::new(
"",
IsExhaustive::exhaustive(),
&[],
TLDiscriminants::from_u8_slice(&[]),
&[]
)),
generics: tl_genparams!(;;),
});
}
macro_rules! empty_extern_fn_layout{
($this:ty) => (
&TypeLayout::from_params::<extern "C" fn()>(TypeLayoutParams {
name: "AFunctionPointer",
item_info:make_item_info!(),
data: TLData::struct_(&[]),
generics: tl_genparams!(;;),
})
)
}
unsafe impl GetStaticEquivalent_ for extern "C" fn() {
type StaticEquivalent=Self;
}
unsafe impl SharedStableAbi for extern "C" fn() {
type Kind=ValueKind;
type IsNonZeroType = True;
const S_LAYOUT: &'static TypeLayout = empty_extern_fn_layout!(Self);
}
unsafe impl GetStaticEquivalent_ for unsafe extern "C" fn() {
type StaticEquivalent=Self;
}
unsafe impl SharedStableAbi for unsafe extern "C" fn() {
type Kind=ValueKind;
type IsNonZeroType = True;
const S_LAYOUT: &'static TypeLayout = empty_extern_fn_layout!(Self);
}
pub const UNSAFE_EXTERN_FN_ABI_INFO:GetAbiInfo=MakeGetAbiInfoSA::<unsafe extern fn()>::STABLE_ABI;
pub const EXTERN_FN_ABI_INFO:GetAbiInfo=MakeGetAbiInfoSA::<extern fn()>::STABLE_ABI;
#[repr(transparent)]
pub struct UnsafeOpaqueField<T>(T);
unsafe impl<T> GetStaticEquivalent_ for UnsafeOpaqueField<T> {
type StaticEquivalent=();
}
unsafe impl<T> SharedStableAbi for UnsafeOpaqueField<T> {
type Kind=ValueKind;
type IsNonZeroType = False;
const S_LAYOUT: &'static TypeLayout = &TypeLayout::from_params::<Self>(TypeLayoutParams {
name: "OpaqueField",
item_info:make_item_info!(),
data: TLData::Opaque,
generics: tl_genparams!(;;),
});
}