Add is and implements functions

Signed-off-by: trivernis <trivernis@protonmail.com>
main
trivernis 2 years ago
parent 8e6b111b75
commit 55c2d41040
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -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"

@ -94,12 +94,14 @@ impl MultitraitObject {
}
/// Downcasts the object into a reference of the given type
#[inline]
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
let any = self.downcast_trait::<dyn Any>().unwrap();
any.downcast_ref::<T>()
}
/// Downcasts the object into a mutable reference of the given type
#[inline]
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
let any = self.downcast_trait_mut::<dyn Any>().unwrap();
any.downcast_mut::<T>()
@ -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<T: Any>(&self) -> bool {
self.original_typeid == TypeId::of::<T>()
}
/// Returns if the object implements a given trait
#[inline]
pub fn implements<T: 'static + ?Sized>(&self) -> bool {
self.traits.contains_key(&TypeId::of::<T>())
}
#[doc(hidden)]
#[inline]
pub fn _register<T2: 'static + ?Sized>(&mut self, vtable_ptr: *const ()) {
self.traits.insert(TypeId::of::<T2>(), vtable_ptr);
}
#[doc(hidden)]
#[inline]
unsafe fn _downcast_trait<T1: 'static + ?Sized>(&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::<T1>())?;
@ -136,6 +154,7 @@ impl MultitraitObject {
}
#[doc(hidden)]
#[inline]
unsafe fn _downcast_trait_mut<T1: 'static + ?Sized>(&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::<T1>())?;
@ -146,6 +165,7 @@ impl MultitraitObject {
}
#[doc(hidden)]
#[inline]
unsafe fn _downcast_boxed_trait<T1: 'static + ?Sized>(&mut self) -> Option<Box<T1>> {
// SAFETY: Creating a fat pointer from the given v-table and data has no side effects
let vptr = *self.traits.get(&TypeId::of::<T1>())?;
@ -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<T> From<T> for MultitraitObject where T: IntoMultitrait {
fn from(other: T) -> Self {
other.into_multitrait()
}
}
pub mod prelude {
pub use crate::*;
}

@ -86,4 +86,12 @@ fn it_tries_cloning() {
let obj1 = mto.downcast::<TestStruct>();
let obj2 = mto2.downcast::<TestStruct>();
assert_eq!(obj1, obj2);
}
#[test]
fn it_returns_type_information() {
let mto = TestStruct::default().into_multitrait();
assert!(mto.is::<TestStruct>());
assert!(mto.implements::<dyn Debug>());
assert!(mto.implements::<dyn ChangeStruct>());
}
Loading…
Cancel
Save