use std::{
fmt::Debug,
hash::Hash,
sync::Arc,
};
use core_extensions::SelfOps;
use crate::{
*,
std_types::{RBox,RString,RStr,RArc,ROption,Tuple1,Tuple2,Tuple3},
sabi_trait::prelude::*,
};
#[sabi_trait]
pub trait RSomething<T>:Send+Sync+Clone+Debug{
type Element:Debug;
fn get(&self)->&Self::Element;
fn get_mut(&mut self)->&mut Self::Element;
#[sabi(last_prefix_field)]
fn into_value(self)->Self::Element;
}
macro_rules! impls_for_something {
(
$traitname:ident ,
extra_bounds[ $($extra_bounds:tt)* ]
) => (
impl $traitname<()> for u32{
type Element=u32;
fn get(&self)->&Self::Element{
self
}
fn get_mut(&mut self)->&mut Self::Element{
self
}
fn into_value(self)->Self::Element{
self
}
}
impl<'a,T> $traitname<()> for &'a T
where
T:Send+Sync+Debug+$($extra_bounds)*
{
type Element=Self;
fn get(&self)->&Self::Element{
self
}
fn get_mut(&mut self)->&mut Self::Element{
self
}
fn into_value(self)->Self::Element{
self
}
}
impl<T> $traitname<()> for RBox<T>
where
T:Send+Sync+Debug+Clone+$($extra_bounds)*
{
type Element=T;
fn get(&self)->&Self::Element{
&**self
}
fn get_mut(&mut self)->&mut Self::Element{
&mut **self
}
fn into_value(self)->Self::Element{
RBox::into_inner(self)
}
}
impl<T> $traitname<()> for RArc<T>
where
T:Send+Sync+Debug+Clone+$($extra_bounds)*
{
type Element=T;
fn get(&self)->&Self::Element{
&**self
}
fn get_mut(&mut self)->&mut Self::Element{
RArc::make_mut(self)
}
fn into_value(self)->Self::Element{
(*self).clone()
}
}
)
}
impls_for_something!{ RSomething, extra_bounds[ Sized ] }
impls_for_something!{ DSomething, extra_bounds[ Hash ] }
#[sabi_trait]
#[sabi(use_dyn_trait)]
pub trait DSomething<T>:Send+Sync+Clone+Debug+Hash{
type Element:Debug;
fn get(&self)->&Self::Element;
fn get_mut(&mut self)->&mut Self::Element;
#[sabi(last_prefix_field)]
fn into_value(self)->Self::Element;
}
#[sabi_trait]
pub trait EmptyTrait{}
impl EmptyTrait for () {}
impl EmptyTrait for u32 {}
impl<T> EmptyTrait for RArc<T> {}
impl<T> EmptyTrait for RBox<T> {}
#[sabi_trait]
pub trait StaticTrait:'static{}
pub struct Dummy0;
#[sabi_trait]
pub trait RSomethingElse<T:Copy>:Send+Debug{
fn get(&self)->&T;
#[sabi(last_prefix_field)]
fn into_value(self)->T;
fn passthrough_string(&self,value:RString)->RString{
value
}
fn passthrough_arc(&self,value:RArc<u32>)->RArc<u32>{
value
}
}
impl RSomethingElse<u32> for u32{
fn get(&self)->&u32{
self
}
fn into_value(self)->u32{
self
}
fn passthrough_string(&self,_:RString)->RString{
RString::new()
}
fn passthrough_arc(&self,_:RArc<u32>)->RArc<u32>{
RArc::new(77)
}
}
impl<T> RSomethingElse<T> for RArc<T>
where
T:Copy+Send+Sync+Debug
{
fn get(&self)->&T{
&**self
}
fn into_value(self)->T{
*self
}
}
impl<T> RSomethingElse<T> for RBox<T>
where
T:Copy+Send+Debug
{
fn get(&self)->&T{
&**self
}
fn into_value(self)->T{
*self
}
}
#[sabi_trait]
pub trait RFoo<'a,T:Copy+'a>{
fn get(&'a self)->&'a T;
}
impl<'a,A:Copy+'a> RFoo<'a,A> for Tuple1<A>{
fn get(&'a self)->&'a A{
&self.0
}
}
impl<'a,A:'a,B:Copy+'a> RFoo<'a,B> for Tuple2<A,B>{
fn get(&'a self)->&'a B{
&self.1
}
}
impl<'a,A:'a,B:'a,C:Copy+'a> RFoo<'a,C> for Tuple3<A,B,C>{
fn get(&'a self)->&'a C{
&self.2
}
}
impl<'a,T> RFoo<'a,T> for RArc<T>
where
T:'a+Copy
{
fn get(&'a self)->&'a T{
&**self
}
}
#[sabi_trait]
pub trait Dictionary{
type Value;
type Unused;
fn what(&self,_:&Self::Unused);
fn get(&self,key:RStr<'_>)->Option<&Self::Value>;
fn insert(&mut self,key:RString,value:Self::Value)->ROption<Self::Value>;
}
#[cfg(all(test))]
mod tests{
use super::*;
use crate::traits::IntoReprC;
fn assert_sync_send_debug_clone<T:Sync+Send+Debug+Clone>(_:&T){}
macro_rules! _something_test {
(
fn $fn_name:ident,
fn $something_methods:ident,
$typename:ident,
$traitname:ident,
) => (
#[test]
fn $fn_name(){
let number=100_u32;
let object=$typename::<_,(),u32>::from_value(number,TU_Unerasable);
let arcobj=$typename::<_,(),u32>::from_ptr(RArc::new(number),TU_Unerasable);
let erased=$typename::<_,(),u32>::from_ptr(RBox::new(number),TU_Opaque);
assert_sync_send_debug_clone(&object);
assert_sync_send_debug_clone(&arcobj);
assert_sync_send_debug_clone(&erased);
fn assertions_unerased(mut object:$typename<'_,RBox<()>,(),u32>){
assert_eq!(object.obj.as_unerased::<u32>().ok(),Some(&100));
assert_eq!(object.obj.as_unerased::<i8>().ok(),None::<&i8>);
assert_eq!(object.obj.as_unerased_mut::<u32>().ok(),Some(&mut 100));
assert_eq!(object.obj.as_unerased_mut::<i8>().ok(),None::<&mut i8>);
object=object.obj.into_unerased::<i8>()
.unwrap_err()
.into_inner()
.piped($typename::from_sabi);
assert_eq!(object.obj.into_unerased::<u32>().ok(),Some(RBox::new(100)));
}
fn assertions_unerased_arc(mut object:$typename<'_,RArc<()>,(),u32>){
assert_eq!(object.obj.as_unerased::<u32>().ok(),Some(&100));
assert_eq!(object.obj.as_unerased::<i8>().ok(),None::<&i8>);
object=object.obj.into_unerased::<i8>()
.unwrap_err()
.into_inner()
.piped($typename::from_sabi);
assert_eq!(object.obj.into_unerased::<u32>().ok(),Some(RArc::new(100)));
}
fn assertions_erased(mut object:$typename<'_,RBox<()>,(),u32>){
assert_eq!(object.obj.as_unerased::<u32>().ok(),None);
assert_eq!(object.obj.as_unerased::<i8>().ok(),None);
assert_eq!(object.obj.as_unerased_mut::<u32>().ok(),None);
assert_eq!(object.obj.as_unerased_mut::<i8>().ok(),None);
object=object.obj.into_unerased::<u32>()
.unwrap_err()
.into_inner()
.piped($typename::from_sabi);
let _=object.obj.into_unerased::<i8>().unwrap_err().into_inner();
}
fn create_from_ref<'a,T>(value:&'a T)->$typename<'a,&'a(),(),T::Element>
where
T:$traitname<()>+'a
{
$typename::<_,(),T::Element>::from_ptr(value,TU_Opaque)
}
fn create_from_val<'a,T>(value:T)->$typename<'a,RBox<()>,(),T::Element>
where
T:$traitname<()>+'a,
{
$typename::<_,(),T::Element>::from_value(value,TU_Opaque)
}
let what=RBox::new(100);
let _=create_from_ref(&*what);
let _=create_from_val(&*what);
assert_eq!(format!("{:?}",number),format!("{:?}",erased));
assert_eq!(format!("{:?}",number),format!("{:?}",arcobj));
assert_eq!(format!("{:?}",number),format!("{:?}",object));
assert_eq!(format!("{:#?}",number),format!("{:?}",erased));
assert_eq!(format!("{:#?}",number),format!("{:?}",arcobj));
assert_eq!(format!("{:#?}",number),format!("{:?}",object));
assertions_unerased(object.clone());
assertions_unerased(object);
assertions_unerased_arc(arcobj.clone());
assertions_unerased_arc(arcobj);
assertions_erased(erased.clone());
assertions_erased(erased);
}
#[test]
fn $something_methods(){
let mut object=$typename::<_,(),_>::from_value(100,TU_Opaque);
let mut cloned=object.clone();
assert_eq!(object.get(),&100);
assert_eq!(object.get_mut(),&mut 100);
assert_eq!(object.into_value(),100);
assert_eq!($traitname::get(&cloned),&100);
assert_eq!($traitname::get_mut(&mut cloned),&mut 100);
assert_eq!($traitname::into_value(cloned),100);
}
)
}
_something_test!{
fn construct_rsomething,
fn rsomething_methods,
RSomething_TO,
RSomething,
}
_something_test!{
fn construct_dsomething,
fn dsomething_methods,
DSomething_TO,
DSomething,
}
#[test]
fn construct_rempty(){
let arc=Arc::new(107_u32);
let rarc=arc.clone().into_c();
assert_eq!(Arc::strong_count(&arc), 2);
let mut object:EmptyTrait_TO<'_,RBox<()>>=
EmptyTrait_TO::from_value(rarc.clone(),TU_Unerasable);
assert_eq!(Arc::strong_count(&arc), 3);
let erased:EmptyTrait_TO<'_,RArc<()>>=
EmptyTrait_TO::from_ptr(rarc.clone(),TU_Opaque);
assert_eq!(Arc::strong_count(&arc), 4);
assert_eq!(
**object.obj.as_unerased::<RArc<u32>>().unwrap(),
107
);
assert_eq!(
**object.obj.as_unerased_mut::<RArc<u32>>().unwrap(),
107
);
assert_eq!(Arc::strong_count(&arc), 4);
object=object.obj.into_unerased::<u32>()
.unwrap_err()
.into_inner()
.piped(EmptyTrait_TO::from_sabi);
assert_eq!(Arc::strong_count(&arc), 4);
assert_eq!(
object.obj.into_unerased::<RArc<u32>>().unwrap(),
RBox::new(RArc::new(107))
);
assert_eq!(Arc::strong_count(&arc), 3);
erased.obj.into_unerased::<u32>().unwrap_err();
assert_eq!(Arc::strong_count(&arc), 2);
}
#[test]
fn test_reborrowing(){
let arc=Arc::new(107_u32);
let rarc=arc.clone().into_c();
assert_eq!(Arc::strong_count(&arc), 2);
let mut object:RSomething_TO<'_,RBox<()>,(),u32>=
RSomething_TO::<_,(),u32>::from_value(rarc.clone(),TU_Unerasable);
assert_eq!(Arc::strong_count(&arc), 3);
for _ in 0..10{
assert_eq!(
object.obj.reborrow().into_unerased::<RArc<u32>>().unwrap(),
&RArc::new(107)
);
}
assert_eq!(Arc::strong_count(&arc), 3);
for _ in 0..10{
assert_eq!(
object.obj.reborrow_mut().into_unerased::<RArc<u32>>().unwrap(),
&mut RArc::new(107)
);
}
assert_eq!(Arc::strong_count(&arc), 3);
{
let cloned=object.obj.reborrow().clone();
assert_eq!(format!("{:?}",cloned),"107");
}
assert_eq!(Arc::strong_count(&arc), 3);
drop(object);
assert_eq!(Arc::strong_count(&arc), 2);
}
#[test]
fn rsomething_else(){
{
let object=RSomethingElse_TO::from_value(RArc::new(100_u32),TU_Opaque);
let _:&dyn RSomethingElse<u32>=&object;
assert_eq!(object.get(),&100);
assert_eq!(object.passthrough_arc(RArc::new(90)), RArc::new(90));
assert_eq!(object.passthrough_string(RString::from("what")), RString::from("what"));
assert_eq!(object.into_value(),100);
}
{
let object=RSomethingElse_TO::from_value(RArc::new(100_u32),TU_Opaque);
assert_eq!(
RSomethingElse::get(&object,),
&100
);
assert_eq!(
RSomethingElse::passthrough_arc(&object,RArc::new(90)),
RArc::new(90)
);
assert_eq!(
RSomethingElse::passthrough_string(&object,RString::from("what")),
RString::from("what")
);
assert_eq!(
RSomethingElse::into_value(object),
100
);
}
{
let object=RSomethingElse_TO::<_,u32>::from_value(100u32,TU_Unerasable);
assert_eq!(
RSomethingElse::passthrough_arc(&object,RArc::new(90)),
RArc::new(77)
);
assert_eq!(
RSomethingElse::passthrough_string(&object,RString::from("what")),
RString::from("")
);
}
}
#[test]
fn rfoo(){
let object = &RFoo_TO::from_ptr(RBox::new(RArc::new(76)),TU_Opaque);
let tuple1_object = &RFoo_TO::from_ptr(RArc::new(Tuple1(100)),TU_Opaque);
let tuple2_object = &RFoo_TO::from_value(Tuple2(101u32,202_u32),TU_Opaque);
let tuple3_object = &RFoo_TO::from_value(Tuple3(11,22,300_u32),TU_Opaque);
assert_eq!(object.get(),&76);
assert_eq!(tuple1_object.get(),&100);
assert_eq!(tuple2_object.get(),&202);
assert_eq!(tuple3_object.get(),&300);
assert_eq!(RFoo::get(object),&76);
assert_eq!(RFoo::get(tuple1_object),&100);
assert_eq!(RFoo::get(tuple2_object),&202);
assert_eq!(RFoo::get(tuple3_object),&300);
}
#[test]
fn test_from_const(){
const RS_U32:RSomething_CTO<'static,'static,(),u32>=
RSomething_CTO::from_const(
&0,
TU_Opaque,
RSomething_MV::VTABLE,
);
assert_eq!(RS_U32.get(), &0);
fn make_const_rsomething<'borr,'a,T,U>(ref_:&'a T)->RSomething_CTO<'borr,'a,(),U>
where
T:'borr+RSomething<(),Element=U>,
U:Debug,
{
RSomething_CTO::from_const(
ref_,
TU_Opaque,
RSomething_MV::VTABLE,
)
}
let hi=make_const_rsomething(&77);
assert_eq!(hi.get(), &77);
}
}