abi_stable 0.9.0

For doing Rust-to-Rust ffi,writing libraries loaded at program startup.
Documentation
use std::{
    mem,
};

use crate::{
    *,
    std_types::{RBox, RStr},
    sabi_trait::prelude::*,
    type_level::bools::*,
};

use abi_stable_shared::{file_span,test_utils::{must_panic}};


mod empty{
    use super::*;
    #[sabi_trait]
    pub trait Trait{}

    impl Trait for () {}

    impl Trait for True {}
}

mod method_no_default{
    use super::*;
    #[sabi_trait]
    pub trait Trait{
        fn apply(&self,l:u32,r:u32)->u32;
    }
    
    impl Trait for () {
        fn apply(&self,l:u32,r:u32)->u32{
            (l+r)*2
        }
    }
}

mod method_disabled_one_default{
    use super::*;
    
    #[sabi_trait]
    pub trait Trait{
        fn first_method(&self)->u32{
            0xf000
        }
        #[sabi(no_default_fallback)]
        fn apply(&self,l:u32,r:u32)->u32{
            (l+r)*3
        }
        fn last_method(&self)->u32{
            0xfAAA
        }
    }
    
    impl Trait for () {
        fn apply(&self,l:u32,r:u32)->u32{
            (l+r)*4
        }
    }
}

mod method_disabled_all_default{
    use super::*;
    
    #[sabi_trait]
    #[sabi(no_default_fallback)]
    pub trait Trait{
        fn first_method(&self)->u32{
            0xf000
        }
        fn last_method(&self)->u32{
            0xfAAA
        }
    }
    
    impl Trait for () {}
}

mod method_default{
    use super::*;
    #[sabi_trait]
    pub trait Trait{
        fn apply(&self,l:u32,r:u32)->u32{
            (l+r)*3
        }
    }

    impl Trait for () {}

    impl Trait for True {
        fn apply(&self,l:u32,r:u32)->u32{
            (l+r)*4
        }
    }
}


#[test]
fn downcasting_tests(){


    unsafe{
        use self::method_disabled_one_default::*;
        let empty=empty::Trait_TO::from_value((),TU_Opaque);
        let object=mem::transmute::<_,Trait_TO<'_,RBox<()>>>(empty);
        assert_eq!(object.first_method(), 0xf000);
        assert_eq!(object.last_method(), 0xfAAA);
        must_panic(file_span!(),|| object.apply(2,5) ).unwrap();
    }
    unsafe{
        use self::method_disabled_all_default::*;
        let empty=empty::Trait_TO::from_value((),TU_Opaque);
        let object=mem::transmute::<_,Trait_TO<'_,RBox<()>>>(empty);
        must_panic(file_span!(),|| object.first_method() ).unwrap();
        must_panic(file_span!(),|| object.last_method() ).unwrap();
    }
    unsafe{
        use self::method_no_default::*;
        let empty=empty::Trait_TO::from_value((),TU_Opaque);
        let object=mem::transmute::<_,Trait_TO<'_,RBox<()>>>(empty);
        must_panic(file_span!(),|| object.apply(2,5) ).unwrap();
    }
    unsafe{
        use self::method_default::*;
        let empty=empty::Trait_TO::from_value((),TU_Opaque);
        let object=mem::transmute::<_,Trait_TO<'_,RBox<()>>>(empty);
        assert_eq!(object.apply(2,5),21);
    }
    

    {
        let no_default=method_no_default::Trait_TO::from_value((),TU_Opaque);
        {
            assert_eq!(no_default.apply(2,5), 14);
        }
        unsafe{            
            use self::method_default::*;
            let object=mem::transmute::<_,Trait_TO<'_,RBox<()>>>(no_default);
            assert_eq!(object.apply(2,5), 14);
        }
    }
    {
        let with_default=method_default::Trait_TO::from_value(True,TU_Opaque);
        {
            assert_eq!(with_default.apply(2,5), 28);
        }
        unsafe{
            use self::method_no_default::*;
            let object=mem::transmute::<_,Trait_TO<'_,RBox<()>>>(with_default);
            assert_eq!(object.apply(2,5), 28);
        }
    }
}




#[sabi_trait]
trait DefaultMethodPair{
    fn foo(&self,x:u32)->u32{
        self.bar(x+10)
    }
    fn bar(&self,y:u32)->u32{
        self.baz(y+20)
    }
    fn baz(&self,z:u32)->u32{
        z+40
    }
}

struct A;
struct B;
struct C;


impl DefaultMethodPair for A{
    fn foo(&self,x:u32)->u32{
        x+100
    }
}

impl DefaultMethodPair for B{
    fn bar(&self,y:u32)->u32{
        y+200
    }
}

impl DefaultMethodPair for C{
    fn baz(&self,z:u32)->u32{
        z+300
    }
}


#[test]
fn default_methods(){
    let a=DefaultMethodPair_TO::from_value(A,TU_Opaque);
    let b=DefaultMethodPair_TO::from_value(B,TU_Opaque);
    let c=DefaultMethodPair_TO::from_value(C,TU_Opaque);

    assert_eq!(a.foo(1), 101);
    assert_eq!(b.foo(1), 211);
    assert_eq!(c.foo(1), 331);
}



/*////////////////////////////////////////////////////////////////////////////////
Test that #[sabi(no_trait_impl)] disables the trait impl for the trait object.
*/////////////////////////////////////////////////////////////////////////////////

#[sabi_trait]
#[sabi(no_trait_impl)]
trait NoTraitImplA{}

impl<P> NoTraitImplA for NoTraitImplA_TO<'_,P>
where P:crate::pointer_trait::GetPointerKind,
{}



#[sabi_trait]
#[sabi(no_trait_impl)]
trait NoTraitImplB{}

impl<This:?Sized> NoTraitImplB for This{}



/*////////////////////////////////////////////////////////////////////////////////
Test that prefix methods can have a default impl.
*/////////////////////////////////////////////////////////////////////////////////


mod defaulted_prefix_method{
    use super::*;
    #[sabi_trait]
    pub trait Trait{
        #[sabi(last_prefix_field)]
        fn apply(&self)->u32 {
            3
        }
    }
    
    impl Trait for () {}
    impl Trait for u32 {
        fn apply(&self)->u32 {
            *self + 5
        }
    }

}

#[test]
fn defaulted_prefix_method_works(){
    use defaulted_prefix_method::Trait_TO;
    {
        let obj = Trait_TO::from_value((), TU_Opaque);
        assert_eq!(obj.apply(), 3);
    }
    {
        let obj = Trait_TO::from_value(0u32, TU_Opaque);
        assert_eq!(obj.apply(), 5);
    }
    {
        let obj = Trait_TO::from_value(10u32, TU_Opaque);
        assert_eq!(obj.apply(), 15);
    }
}


/*////////////////////////////////////////////////////////////////////////////////
Test all the kinds of borrows in return types.
*/////////////////////////////////////////////////////////////////////////////////


#[sabi_trait]
trait BorrowKinds {
    fn ref_borrow_a(&self) -> &bool {
        &true
    }
    fn ref_borrow_b(&self) -> &RStr<'_> {
        &rstr!("foo")
    }

    fn other_borrow(&self) -> RStr<'_> {
        RStr::from_str("bar")
    }

    fn non_self_borrow(&self) -> RStr<'static> {
        RStr::from_str("baz")
    }

    fn mut_borrow(&mut self) -> &mut u32;

    fn not_borrow(&self) -> u64 {
        89
    }
}

impl BorrowKinds for u32{
    fn mut_borrow(&mut self) -> &mut u32 {
        self
    }
}


#[test]
fn borrow_kinds(){
    let mut obj = BorrowKinds_TO::from_value(3u32, TU_Opaque);

    assert_eq!(obj.ref_borrow_a(), &true);
    assert_eq!(obj.ref_borrow_b().as_str(), "foo");
    assert_eq!(obj.other_borrow().as_str(), "bar");
    assert_eq!(obj.non_self_borrow().as_str(), "baz");
    assert_eq!(*obj.mut_borrow(), 3);
    assert_eq!(obj.not_borrow(), 89);

}