use std::{
cmp::{PartialEq,Ord,PartialOrd},
fmt::{Debug,Display},
hash::Hash,
};
use crate::{
erased_types::{c_functions,trait_objects,InterfaceType,FormattingMode,InterfaceBound},
inline_storage::InlineStorage,
marker_type::{ErasedObject,UnsafeIgnoredType},
nonexhaustive_enum::{
alt_c_functions,NonExhaustive,EnumInfo,GetEnumInfo,SerializeEnum,GetSerializeEnumProxy,
},
prefix_type::{PrefixTypeTrait,WithMetadata,panic_on_missing_fieldname},
type_level::{
impl_enum::{Implemented,Unimplemented},
trait_marker,
},
std_types::{ROption,RResult,RString,RCmpOrdering,RBoxError},
utils::Transmuter,
StableAbi,
};
pub unsafe trait GetVTable<S,I>:GetEnumInfo{
#[doc(hidden)]
const VTABLE_VAL:NonExhaustiveVtable<Self,S,I>;
#[doc(hidden)]
const VTABLE_REF:NonExhaustiveVtable_Ref<Self,S,I> = unsafe{
NonExhaustiveVtable_Ref(
WithMetadata::new(
PrefixTypeTrait::METADATA,
Self::VTABLE_VAL
).as_prefix()
)
};
}
#[doc(hidden)]
#[repr(C)]
#[derive(StableAbi)]
#[sabi(
bound="I:GetSerializeEnumProxy<NonExhaustive<E,S,I>>",
bound="<I as GetSerializeEnumProxy<NonExhaustive<E,S,I>>>::ProxyType: StableAbi",
not_stableabi(E,S,I),
missing_field(default),
kind(Prefix),
with_field_indices,
//debug_print,
)]
pub struct NonExhaustiveVtable<E,S,I>{
pub(crate) _sabi_tys:UnsafeIgnoredType<(E,S,I)>,
pub enum_info:&'static EnumInfo,
pub(crate) _sabi_drop :unsafe extern "C" fn(this:&mut ErasedObject),
#[sabi(unsafe_opaque_field)]
pub(crate) _sabi_clone:Option<
unsafe extern "C" fn(
&ErasedObject,
NonExhaustiveVtable_Ref<E,S,I>,
)->NonExhaustive<E,S,I>
>,
pub(crate) _sabi_debug:Option<
unsafe extern "C" fn(&ErasedObject,FormattingMode,&mut RString)->RResult<(),()>
>,
pub(crate) _sabi_display:Option<
unsafe extern "C" fn(&ErasedObject,FormattingMode,&mut RString)->RResult<(),()>
>,
#[sabi(unsafe_change_type=r##"
unsafe extern "C" fn(
&ErasedObject
)->RResult< <I as GetSerializeEnumProxy<NonExhaustive<E,S,I>>>::ProxyType, RBoxError>
"##)]
pub(crate) erased_sabi_serialize: Option<
unsafe extern "C" fn(&ErasedObject)->RResult<ErasedObject,RBoxError>
>,
pub(crate) _sabi_partial_eq: Option<
unsafe extern "C" fn(&ErasedObject,&ErasedObject)->bool
>,
pub(crate) _sabi_cmp: Option<
unsafe extern "C" fn(&ErasedObject,&ErasedObject)->RCmpOrdering,
>,
pub(crate) _sabi_partial_cmp: Option<
unsafe extern "C" fn(&ErasedObject,&ErasedObject)->ROption<RCmpOrdering>,
>,
#[sabi(last_prefix_field)]
pub(crate) _sabi_hash:Option<
unsafe extern "C" fn(&ErasedObject,trait_objects::HasherObject<'_>)
>,
}
unsafe impl<E,S,I> Sync for NonExhaustiveVtable<E,S,I>{}
unsafe impl<E,S,I> Send for NonExhaustiveVtable<E,S,I>{}
unsafe impl<E,S,I> GetVTable<S,I> for E
where
S:InlineStorage,
I:InterfaceType,
E:GetEnumInfo,
I::Sync:RequiresSync<E,S,I>,
I::Send:RequiresSend<E,S,I>,
I::Clone:InitCloneField<E,S,I>,
I::Debug:InitDebugField<E,S,I>,
I::Display:InitDisplayField<E,S,I>,
I::Serialize:InitSerializeField<E,S,I>,
I::PartialEq:InitPartialEqField<E,S,I>,
I::PartialOrd:InitPartialOrdField<E,S,I>,
I::Ord:InitOrdField<E,S,I>,
I::Hash:InitHashField<E,S,I>,
{
#[doc(hidden)]
const VTABLE_VAL:NonExhaustiveVtable<E,S,I>=
NonExhaustiveVtable{
_sabi_tys:UnsafeIgnoredType::DEFAULT,
enum_info:E::ENUM_INFO,
_sabi_drop:alt_c_functions::drop_impl::<E>,
_sabi_clone:<I::Clone as InitCloneField<E,S,I>>::VALUE,
_sabi_debug:<I::Debug as InitDebugField<E,S,I>>::VALUE,
_sabi_display:<I::Display as InitDisplayField<E,S,I>>::VALUE,
erased_sabi_serialize:<I::Serialize as InitSerializeField<E,S,I>>::VALUE,
_sabi_partial_eq:<I::PartialEq as InitPartialEqField<E,S,I>>::VALUE,
_sabi_partial_cmp:<I::PartialOrd as InitPartialOrdField<E,S,I>>::VALUE,
_sabi_cmp:<I::Ord as InitOrdField<E,S,I>>::VALUE,
_sabi_hash:<I::Hash as InitHashField<E,S,I>>::VALUE,
};
}
type UnerasedSerializeFn<E,S,I>=
unsafe extern "C" fn(
&ErasedObject
)->RResult< <I as GetSerializeEnumProxy<NonExhaustive<E,S,I>>>::ProxyType, RBoxError>;
impl<E,S,I> NonExhaustiveVtable_Ref<E,S,I>{
pub fn serialize(self)->UnerasedSerializeFn<E,S,I>
where
I:InterfaceBound<Serialize=Implemented<trait_marker::Serialize>>,
I:GetSerializeEnumProxy<NonExhaustive<E,S,I>>,
{
unsafe{
std::mem::transmute::<
unsafe extern "C" fn(&ErasedObject)->RResult<ErasedObject,RBoxError>,
UnerasedSerializeFn<E,S,I>,
>( self.priv_serialize() )
}
}
}
use self::trait_bounds::*;
pub mod trait_bounds{
use super::*;
macro_rules! declare_conditional_marker {
(
type $selector:ident;
trait $trait_name:ident[$self_:ident,$Filler:ident,$OrigPtr:ident]
where [ $($where_preds:tt)* ]
) => (
pub trait $trait_name<$self_,$Filler,$OrigPtr>{}
impl<$self_,$Filler,$OrigPtr> $trait_name<$self_,$Filler,$OrigPtr>
for Unimplemented<trait_marker::$selector>
{}
impl<$self_,$Filler,$OrigPtr> $trait_name<$self_,$Filler,$OrigPtr>
for Implemented<trait_marker::$selector>
where
$($where_preds)*
{}
)
}
macro_rules! declare_field_initalizer {
(
type $selector:ident;
trait $trait_name:ident[$enum_:ident,$filler:ident,$interf:ident]
$( where_for_both[ $($where_preds_both:tt)* ] )?
where [ $($where_preds:tt)* ]
$priv_field:ident,$field:ident : $field_ty:ty;
field_index=$field_index:ident;
value=$field_value:expr,
) => (
pub trait $trait_name<$enum_,$filler,$interf>
where
$($($where_preds_both)*)?
{
const VALUE:Option<$field_ty>;
}
impl<$enum_,$filler,$interf> $trait_name<$enum_,$filler,$interf>
for Unimplemented<trait_marker::$selector>
where
$($($where_preds_both)*)?
{
const VALUE:Option<$field_ty>=None;
}
impl<$enum_,$filler,$interf> $trait_name<$enum_,$filler,$interf>
for Implemented<trait_marker::$selector>
where
$($($where_preds_both)*)?
$($where_preds)*
{
const VALUE:Option<$field_ty>=Some($field_value);
}
impl<E,S,$interf> NonExhaustiveVtable_Ref<E,S,$interf>{
pub fn $field(self)->$field_ty
where
$interf:InterfaceType<$selector=Implemented<trait_marker::$selector>>,
{
match self.$priv_field().into() {
Some(v)=>v,
None=>panic_on_missing_fieldname::<
NonExhaustiveVtable<E,S,$interf>,
>(
Self::$field_index,
self._prefix_type_layout(),
)
}
}
}
)
}
declare_conditional_marker!{
type Send;
trait RequiresSend[E,S,I]
where [ E:Send ]
}
declare_conditional_marker!{
type Sync;
trait RequiresSync[E,S,I]
where [ E:Sync ]
}
declare_field_initalizer!{
type Clone;
trait InitCloneField[E,S,I]
where_for_both[ E:GetEnumInfo, ]
where [ E:Clone ]
_sabi_clone,clone_:
unsafe extern "C" fn(
&ErasedObject,
NonExhaustiveVtable_Ref<E,S,I>
)->NonExhaustive<E,S,I>;
field_index=field_index_for__sabi_clone;
value=alt_c_functions::clone_impl::<E,S,I>,
}
declare_field_initalizer!{
type Debug;
trait InitDebugField[E,S,I]
where [ E:Debug ]
_sabi_debug,debug:
unsafe extern "C" fn(&ErasedObject,FormattingMode,&mut RString)->RResult<(),()>;
field_index=field_index_for__sabi_debug;
value=c_functions::debug_impl::<E>,
}
declare_field_initalizer!{
type Display;
trait InitDisplayField[E,S,I]
where [ E:Display ]
_sabi_display,display:
unsafe extern "C" fn(&ErasedObject,FormattingMode,&mut RString)->RResult<(),()>;
field_index=field_index_for__sabi_display;
value=c_functions::display_impl::<E>,
}
declare_field_initalizer!{
type Serialize;
trait InitSerializeField[E,S,I]
where [ I:SerializeEnum<NonExhaustive<E,S,I>> ]
erased_sabi_serialize,priv_serialize:
unsafe extern "C" fn(&ErasedObject)->RResult<ErasedObject,RBoxError>;
field_index=field_index_for_erased_sabi_serialize;
value=unsafe{
Transmuter::<
unsafe extern "C" fn(
&ErasedObject
)->RResult<<I as SerializeEnum<NonExhaustive<E,S,I>>>::Proxy,RBoxError>,
unsafe extern "C" fn(&ErasedObject)->RResult<ErasedObject,RBoxError>
>{
from:alt_c_functions::serialize_impl::<NonExhaustive<E,S,I>,I>
}.to
},
}
declare_field_initalizer!{
type PartialEq;
trait InitPartialEqField[E,S,I]
where_for_both[ E:GetEnumInfo, ]
where [ E:PartialEq ]
_sabi_partial_eq,partial_eq: unsafe extern "C" fn(&ErasedObject,&ErasedObject)->bool;
field_index=field_index_for__sabi_partial_eq;
value=alt_c_functions::partial_eq_impl::<E,S,I>,
}
declare_field_initalizer!{
type PartialOrd;
trait InitPartialOrdField[E,S,I]
where_for_both[ E:GetEnumInfo, ]
where [ E:PartialOrd ]
_sabi_partial_cmp,partial_cmp:
unsafe extern "C" fn(&ErasedObject,&ErasedObject)->ROption<RCmpOrdering>;
field_index=field_index_for__sabi_partial_cmp;
value=alt_c_functions::partial_cmp_ord::<E,S,I>,
}
declare_field_initalizer!{
type Ord;
trait InitOrdField[E,S,I]
where_for_both[ E:GetEnumInfo, ]
where [ E:Ord ]
_sabi_cmp,cmp: unsafe extern "C" fn(&ErasedObject,&ErasedObject)->RCmpOrdering;
field_index=field_index_for__sabi_cmp;
value=alt_c_functions::cmp_ord::<E,S,I>,
}
declare_field_initalizer!{
type Hash;
trait InitHashField[E,S,I]
where [ E:Hash ]
_sabi_hash,hash: unsafe extern "C" fn(&ErasedObject,trait_objects::HasherObject<'_>);
field_index=field_index_for__sabi_hash;
value=c_functions::hash_Hash::<E>,
}
}