diff --git a/Cargo.toml b/Cargo.toml index 58bd6b8..052d03a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-trait-object" -version = "0.1.2" +version = "0.1.3" edition = "2021" readme = "README.md" license = "Apache-2.0" diff --git a/src/tests.rs b/src/tests.rs index 9046d85..feb2bcf 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -26,7 +26,7 @@ impl ChangeStruct for TestStruct { } } -impl_trait_object!(TestStruct, dyn RawClone, dyn ChangeStruct, dyn Debug); +impl_trait_object!(TestStruct, dyn RawClone, dyn PartialEqAny, dyn ChangeStruct, dyn Debug); #[test] fn it_creates_fat_pointers() { @@ -94,4 +94,13 @@ fn it_returns_type_information() { assert!(mto.is::()); assert!(mto.implements::()); assert!(mto.implements::()); +} + +#[test] +fn it_tries_partial_eq() { + let mto = TestStruct::default().into_multitrait(); + let mto_eq = TestStruct::default().into_multitrait(); + let mto_neq = TestStruct {test: String::from("no"), a: 6}.into_multitrait(); + assert!(mto.try_eq(&mto_eq).unwrap()); + assert_eq!(mto.try_eq(&mto_neq).unwrap(), false); } \ No newline at end of file diff --git a/src/trait_impl/mod.rs b/src/trait_impl/mod.rs index 56cc473..72846d2 100644 --- a/src/trait_impl/mod.rs +++ b/src/trait_impl/mod.rs @@ -1,5 +1,7 @@ mod try_clone; mod debug; +mod try_partial_eq; pub use try_clone::*; -pub use debug::*; \ No newline at end of file +pub use debug::*; +pub use try_partial_eq::*; \ No newline at end of file diff --git a/src/trait_impl/try_clone.rs b/src/trait_impl/try_clone.rs index 8eba46f..a6cc349 100644 --- a/src/trait_impl/try_clone.rs +++ b/src/trait_impl/try_clone.rs @@ -15,14 +15,15 @@ pub unsafe trait RawClone { unsafe fn raw_clone(&self) -> *mut (); } +/// A trait that tries cloning an object and returns an option +/// with the variant depending on the result. For a multitrait object +/// to be clonable it needs to have the [RawClone] trait registered. unsafe impl RawClone for T { unsafe fn raw_clone(&self) -> *mut () { Box::into_raw(Box::new(self.clone())) as *mut () } } -/// A trait that tries cloning an object and returns an option -/// with the variant depending on the result. impl TryClone for MultitraitObject { fn try_clone(&self) -> Option { let clone = self.downcast_trait::()?; diff --git a/src/trait_impl/try_partial_eq.rs b/src/trait_impl/try_partial_eq.rs new file mode 100644 index 0000000..b66c8cb --- /dev/null +++ b/src/trait_impl/try_partial_eq.rs @@ -0,0 +1,37 @@ +use std::any::{Any}; +use crate::MultitraitObject; + +/// Compares the given value with an Any trait object. +/// Register this trait if you want to compare two Multitrait objects +/// with the [TryPartialEq] trait. +pub trait PartialEqAny { + fn partial_equal_any(&self, other: &dyn Any) -> bool; +} + +impl PartialEqAny for T { + fn partial_equal_any(&self, other: &dyn Any) -> bool { + if let Some(other) = other.downcast_ref::() { + self.eq(other) + } else { + false + } + } +} + +/// Tries to compare the MultitraitObject with another object +/// and returns Some(bool) when the underlying type implements PartialEq and +/// has the [PartialEqAny] trait registered on the object. +pub trait TryPartialEq { + fn try_eq(&self, other: &Self) -> Option; +} + +impl TryPartialEq for MultitraitObject { + fn try_eq(&self, other: &Self) -> Option { + if let Some(eq_any) = self.downcast_trait::() { + let any = other.downcast_trait::().unwrap(); + Some(eq_any.partial_equal_any(any)) + } else { + None + } + } +} \ No newline at end of file