Change register_traits to create_object to not associate wrong v-tables

Signed-off-by: trivernis <trivernis@protonmail.com>
main
trivernis 3 years ago
parent ab11e37da0
commit db608c8eb1
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,6 +1,6 @@
[package] [package]
name = "multi-trait-object" name = "multi-trait-object"
version = "0.1.3" version = "0.2.0"
edition = "2021" edition = "2021"
readme = "README.md" readme = "README.md"
license = "Apache-2.0" license = "Apache-2.0"

@ -20,14 +20,21 @@ pub struct FatPointer {
pub vptr: *const (), pub vptr: *const (),
} }
#[allow(unused)]
#[doc(hidden)]
#[inline]
pub unsafe fn null_ptr<T: Sized>(_value: &T) -> *const T {
// creates a typed clone that is actually null
std::ptr::null::<T>() as *const T
}
/// A container to store data with the associated type and trait objects /// A container to store data with the associated type and trait objects
/// allowing for casting down to trait_impl or the concrete type /// allowing for casting down to trait_impl or the concrete type
/// ```rust /// ```rust
/// use multi_trait_object::*; /// use multi_trait_object::*;
/// use std::fmt::{Debug, Display}; /// use std::fmt::{Debug, Display};
/// ///
/// let mut mto = MultitraitObject::new(String::new()); /// let mto = create_object!(String::new(), dyn Debug, dyn Display);
/// register_traits!(mto, String, dyn Debug, dyn Display);
/// ///
/// let debug = mto.downcast_trait::<dyn Debug>().unwrap(); /// let debug = mto.downcast_trait::<dyn Debug>().unwrap();
/// println!("{:?}", debug); /// println!("{:?}", debug);
@ -46,6 +53,7 @@ impl MultitraitObject {
/// Creates a new multitrait object from the given value /// Creates a new multitrait object from the given value
/// All trait_impl except Any must be registered on this object /// All trait_impl except Any must be registered on this object
/// in order to access them. /// in order to access them.
#[doc(hidden)]
pub fn new<T: 'static + Any>(value: T) -> Self { pub fn new<T: 'static + Any>(value: T) -> Self {
let any_vtable = __fat_pointer!(T as dyn Any).vptr; let any_vtable = __fat_pointer!(T as dyn Any).vptr;
let data = Box::into_raw(Box::new(value)) as *mut (); let data = Box::into_raw(Box::new(value)) as *mut ();

@ -20,7 +20,7 @@ macro_rules! impl_trait_object {
fn into_multitrait(self) -> $crate::MultitraitObject { fn into_multitrait(self) -> $crate::MultitraitObject {
let mut mto = $crate::MultitraitObject::new(self); let mut mto = $crate::MultitraitObject::new(self);
$( $(
$crate::register_traits!(mto, $obj, $trt); mto._register::<$trt>($crate::__fat_pointer!($obj as $trt).vptr);
)* )*
mto mto
@ -29,32 +29,43 @@ macro_rules! impl_trait_object {
} }
} }
#[doc(hidden)]
#[macro_export]
macro_rules! __fat_pointer {
($v:ty as $t:ty) => {{
let x = ::std::ptr::null::<$v>() as *const $v as *const $t;
#[allow(unused_unsafe)]
unsafe {
std::mem::transmute::<_, $crate::FatPointer>(x)
}
}}
}
/// Registers multiple trait_impl on a multitrait object /// Registers multiple trait_impl on a multitrait object
/// ```rust /// ```rust
/// use multi_trait_object::*; /// use multi_trait_object::*;
/// use std::fmt::{Debug, Display}; /// use std::fmt::{Debug, Display};
/// ///
/// let value = String::new(); /// let mto = create_object!(String::new(), dyn Debug, dyn Display);
/// let mut mto = MultitraitObject::new(value);
/// register_traits!(mto, String, dyn Debug, dyn Display);
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! register_traits { macro_rules! create_object {
($r:expr, $v:ty, $($t:ty), +) => { ($v:expr, $($t:ty), +) => {
{
let null_ptr = unsafe {
// SAFETY: We're never accessing the null value
$crate::null_ptr(&$v)
};
let mut mto = $crate::MultitraitObject::new($v);
$( $(
$r._register::<$t>($crate::__fat_pointer!($v as $t).vptr); let vptr = unsafe {
// SAFETY: We're never accessing the null value
let ptr = $crate::null_ptr(&*null_ptr) as *const $t;
std::mem::transmute::<_, $crate::FatPointer>(ptr).vptr
};
mto._register::<$t>(vptr);
)+ )+
mto
} }
} }
#[doc(hidden)]
#[macro_export]
macro_rules! __fat_pointer {
($v:ty as $t:ty) => {{
let x = ::std::ptr::null::<$v>() as *const $v as *const $t;
#[allow(unused_unsafe)]
unsafe {
std::mem::transmute::<_, $crate::FatPointer>(x)
}
}}
} }

@ -1,5 +1,5 @@
use std::fmt::Debug; use std::fmt::Debug;
use crate::{__fat_pointer, impl_trait_object, IntoMultitrait, TryClone, TryPartialEq, RawClone, PartialEqAny}; use crate::{__fat_pointer, impl_trait_object, IntoMultitrait, TryClone, TryPartialEq, RawClone, PartialEqAny, create_object};
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
struct TestStruct { struct TestStruct {
@ -42,6 +42,8 @@ fn it_creates_fat_pointers() {
fn it_constructs() { fn it_constructs() {
TestStruct::default().into_multitrait(); TestStruct::default().into_multitrait();
String::from("test").into_multitrait(); String::from("test").into_multitrait();
let mto = create_object!(String::from("test"), dyn Debug);
assert!(mto.is::<String>())
} }
#[test] #[test]

Loading…
Cancel
Save