abi_stable 0.9.0

For doing Rust-to-Rust ffi,writing libraries loaded at program startup.
Documentation
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,
};


/// Gets the vtable of `NonExhaustive<Self,S,I>`.
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()
        )
    };
}



/// The vtable for NonExhaustive<>.
#[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>,
    }
}