abi_stable 0.9.0

For doing Rust-to-Rust ffi,writing libraries loaded at program startup.
Documentation
/*!
Tests the fields related to reflection generated in the StableAbi derive macro.
*/


use crate::{
    abi_stability::{PrefixStableAbi, StableAbi},
    reflection::ModReflMode,
    type_layout::{TLData,FieldAccessor,TLField},
    std_types::*,
};


#[repr(u8)]
#[derive(StableAbi)]
pub enum PubEnum {
    Variant0,
    Variant1(RString),
    Variant2{
        field0:u32,
    },
}


#[repr(C)]
#[derive(StableAbi)]
#[allow(dead_code)]
enum PrivEnum {
    Variant0,
    Variant1(RString),
    Variant2{
        field0:u32,
    },
}


#[repr(C)]
#[derive(StableAbi)]
//#[sabi(debug_print)]
pub struct RegularPubFields {
    pub field0: u8,
    pub field1: u8,
    #[sabi(refl(pub_getter="what_the"))]
    pub field2: u8,
}

#[repr(C)]
#[derive(StableAbi)]
#[sabi(module_reflection( Opaque ))]
pub struct RegularPubFieldsOpaque {
    pub field0: u8,
    pub field1: u8,
}



#[repr(C)]
#[derive(StableAbi)]
pub struct RegularMostPrivacies {
    pub field0: u8,
    pub(super)field1: u16,
    field2: u32,
}



#[repr(C)]
#[derive(StableAbi)]
pub struct RegularPriv {
    field0: u8,
    field1: u16,
    #[sabi(refl(pub_getter="hello"))]
    field2: u32,
}



#[repr(C)]
#[derive(StableAbi)]
#[sabi(
    kind(Prefix),
    missing_field(panic),
)]
pub struct PrefixPubFields {
    #[sabi(last_prefix_field)]
    pub field0: u8,
    pub field1: u8,
    #[sabi(missing_field(option))]
    pub field2: u8,
    #[sabi(refl(pub_getter="hello"))]
    #[sabi(missing_field(default))]
    pub field3: u8,
    #[sabi(missing_field(panic))]
    pub field4: u8,
}

#[repr(C)]
#[derive(StableAbi)]
#[sabi(
    kind(Prefix),
    missing_field(panic),
    module_reflection(Opaque),
)]
pub struct PrefixPubFieldsOpaque {
    #[sabi(last_prefix_field)]
    pub field0: u8,
    #[sabi(missing_field(panic))]
    pub field1: u8,
}


#[allow(dead_code)]
mod some_prefixes{
    #[repr(C)]
    #[derive(StableAbi)]
    #[sabi(kind(Prefix))]
    pub struct PrefMostPrivacies {
        pub field0: u8,
        #[sabi(last_prefix_field)]
        pub field1: u8,
        pub field2: u8,
        pub field3: u8,
        pub(super)field4: u16,
        #[sabi(missing_field(default))]
        field5: u32,
    }


    #[repr(C)]
    #[derive(StableAbi)]
    #[sabi(kind(Prefix))]
    pub struct PrefPriv {
        field0: u8,
        pub(super) field1: u16,
        #[sabi(last_prefix_field)]
        #[sabi(missing_field(default))]
        pub(crate) field2: u32,
    }
}

pub use self::some_prefixes::*;




///////////////////////////////////////////////////////////////////////////////


fn check_fields(
    fields:&[TLField],
    accessors:&[FieldAccessor],
){
    for (field,expec_acc) in fields.iter().zip( accessors ) {
        assert_eq!(
            field.field_accessor(),
            *expec_acc,
            "field:{}\nfields:{:#?}",
            field.name(),
            fields
        );
    }
}


fn check_enum_accessors<T>(
    mod_refl_mode:ModReflMode,
    accessors:&[&[FieldAccessor]],
)where
    T:StableAbi
{
    let layout=T::LAYOUT;

    let mut fields=match layout.data() {
        TLData::Enum(enum_)=>enum_.fields.iter(),
        x=>panic!("layout.data must be TLData::Struct{{..}}:\n{:#?}",x)
    };

    assert_eq!(layout.mod_refl_mode(),mod_refl_mode);
    
    for expec_vari in accessors {
        let subfields=fields.by_ref().take(expec_vari.len()).collect::<Vec<_>>();
        check_fields(&subfields,expec_vari)
    }
}


fn check_struct_accessors<T>(
    mod_refl_mode:ModReflMode,
    accessors:&[FieldAccessor],
)where
    T:StableAbi
{
    let layout=T::LAYOUT;

    let fields=match layout.data() {
        TLData::Struct{fields}=>fields.to_vec(),
        x=>panic!("layout.data must be TLData::Struct{{..}}:\n{:#?}",x)
    };

    assert_eq!(layout.mod_refl_mode(),mod_refl_mode);

    check_fields(&fields,accessors);
}


fn check_prefix_accessors<T>(
    mod_refl_mode:ModReflMode,
    accessors:&[FieldAccessor],
)where
    T:PrefixStableAbi
{
    let layout=T::LAYOUT;

    let fields=match layout.data() {
        TLData::PrefixType(prefix)=>prefix.fields.to_vec(),
        x=>panic!("layout.data must be TLData::Struct{{..}}:\n{:#?}",x)
    };

    assert_eq!(layout.mod_refl_mode(),mod_refl_mode);

    check_fields(&fields,accessors);
}

///////////////////////////////////////////////////////////////////////////////


#[test]
fn test_pub_enum(){
    check_enum_accessors::<PubEnum>(
        ModReflMode::Module,
        &[
            &[],
            &[FieldAccessor::Direct],
            &[FieldAccessor::Direct],
        ]
    );
}


#[test]
fn test_priv_enum(){
    check_enum_accessors::<PrivEnum>(
        ModReflMode::Opaque,
        &[
            &[],
            &[FieldAccessor::Opaque],
            &[FieldAccessor::Opaque],
        ]
    );
}



///////////////////////////////////////////////////////////////////////////////


#[test]
fn test_regular_pub_fields(){
    check_struct_accessors::<RegularPubFields>(
        ModReflMode::Module,
        &[
            FieldAccessor::Direct,
            FieldAccessor::Direct,
            {const FA:FieldAccessor=FieldAccessor::method_named(rstr!("what_the"));FA},
        ]
    );
}


#[test]
fn test_regular_pub_fields_opaque(){
    check_struct_accessors::<RegularPubFieldsOpaque>(
        ModReflMode::Opaque,
        &[
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
        ]
    );
}


#[test]
fn test_regular_most_privacies(){
    check_struct_accessors::<RegularMostPrivacies>(
        ModReflMode::Module,
        &[
            FieldAccessor::Direct,
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
        ]
    );
}


#[test]
fn test_regular_priv(){
    check_struct_accessors::<RegularPriv>(
        ModReflMode::Opaque,
        &[
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
            {const FA:FieldAccessor=FieldAccessor::method_named(rstr!("hello"));FA},
        ]
    );
}


///////////////////////////////////////////////////////////////////////////////


#[test]
fn test_prefix_pub_fields(){
    check_prefix_accessors::<PrefixPubFields_Prefix>(
        ModReflMode::Module,
        &[
            FieldAccessor::Method,
            FieldAccessor::Method,
            FieldAccessor::MethodOption,
            {const FA:FieldAccessor=FieldAccessor::method_named(rstr!("hello"));FA},
            FieldAccessor::Method,
        ]
    );
}


#[test]
fn test_prefix_pub_fields_opaque(){
    check_prefix_accessors::<PrefixPubFieldsOpaque_Prefix>(
        ModReflMode::Opaque,
        &[
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
        ]
    );
}


#[test]
fn test_prefix_most_privacies(){
    check_prefix_accessors::<PrefMostPrivacies_Prefix>(
        ModReflMode::Module,
        &[
            FieldAccessor::Method,
            FieldAccessor::Method,
            FieldAccessor::MethodOption,
            FieldAccessor::MethodOption,
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
        ]
    );
}


#[test]
fn test_prefix_priv(){
    check_prefix_accessors::<PrefPriv_Prefix>(
        ModReflMode::Opaque,
        &[
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
            FieldAccessor::Opaque,
        ]
    );
}