From 55c2d410405bf7519bbdf47a4346ecd50a1f7d18 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 13 Mar 2022 18:49:22 +0100 Subject: [PATCH] Add is and implements functions Signed-off-by: trivernis --- Cargo.toml | 2 +- src/lib.rs | 28 +++++++++++++++++++++++++++- src/tests.rs | 8 ++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db28c1c..58bd6b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "multi-trait-object" -version = "0.1.1" +version = "0.1.2" edition = "2021" readme = "README.md" license = "Apache-2.0" diff --git a/src/lib.rs b/src/lib.rs index 6c76cfc..e10ffce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,12 +94,14 @@ impl MultitraitObject { } /// Downcasts the object into a reference of the given type + #[inline] pub fn downcast_ref(&self) -> Option<&T> { let any = self.downcast_trait::().unwrap(); any.downcast_ref::() } /// Downcasts the object into a mutable reference of the given type + #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { let any = self.downcast_trait_mut::().unwrap(); any.downcast_mut::() @@ -120,12 +122,28 @@ impl MultitraitObject { } } + /// Returns if the object stores the given concrete type + /// Use [MultitraitObject::implements] to check if the object + /// has a given trait + #[inline] + pub fn is(&self) -> bool { + self.original_typeid == TypeId::of::() + } + + /// Returns if the object implements a given trait + #[inline] + pub fn implements(&self) -> bool { + self.traits.contains_key(&TypeId::of::()) + } + #[doc(hidden)] + #[inline] pub fn _register(&mut self, vtable_ptr: *const ()) { self.traits.insert(TypeId::of::(), vtable_ptr); } #[doc(hidden)] + #[inline] unsafe fn _downcast_trait(&self) -> Option<&T1> { // SAFETY: Creating a fat pointer from the given v-table and data has no side effects let vptr = *self.traits.get(&TypeId::of::())?; @@ -136,6 +154,7 @@ impl MultitraitObject { } #[doc(hidden)] + #[inline] unsafe fn _downcast_trait_mut(&mut self) -> Option<&mut T1> { // SAFETY: Creating a fat pointer from the given v-table and data has no side effects let vptr = *self.traits.get(&TypeId::of::())?; @@ -146,6 +165,7 @@ impl MultitraitObject { } #[doc(hidden)] + #[inline] unsafe fn _downcast_boxed_trait(&mut self) -> Option> { // SAFETY: Creating a fat pointer from the given v-table and data has no side effects let vptr = *self.traits.get(&TypeId::of::())?; @@ -160,7 +180,7 @@ impl MultitraitObject { impl Drop for MultitraitObject { fn drop(&mut self) { unsafe { - // Safety: The Multitrait object has exclusive access to the data pointer + // SAFETY: The Multitrait object has exclusive access to the data pointer let raw = Box::from_raw(self.data); std::mem::drop(raw); } @@ -171,6 +191,12 @@ pub trait IntoMultitrait { fn into_multitrait(self) -> MultitraitObject; } +impl From for MultitraitObject where T: IntoMultitrait { + fn from(other: T) -> Self { + other.into_multitrait() + } +} + pub mod prelude { pub use crate::*; } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 4459eff..9046d85 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -86,4 +86,12 @@ fn it_tries_cloning() { let obj1 = mto.downcast::(); let obj2 = mto2.downcast::(); assert_eq!(obj1, obj2); +} + +#[test] +fn it_returns_type_information() { + let mto = TestStruct::default().into_multitrait(); + assert!(mto.is::()); + assert!(mto.implements::()); + assert!(mto.implements::()); } \ No newline at end of file