Change register_traits to create_object to not associate wrong v-tables

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

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

@ -20,14 +20,21 @@ pub struct FatPointer {
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
/// allowing for casting down to trait_impl or the concrete type
/// ```rust
/// use multi_trait_object::*;
/// use std::fmt::{Debug, Display};
///
/// let mut mto = MultitraitObject::new(String::new());
/// register_traits!(mto, String, dyn Debug, dyn Display);
/// let mto = create_object!(String::new(), dyn Debug, dyn Display);
///
/// let debug = mto.downcast_trait::<dyn Debug>().unwrap();
/// println!("{:?}", debug);
@ -46,6 +53,7 @@ impl MultitraitObject {
/// Creates a new multitrait object from the given value
/// All trait_impl except Any must be registered on this object
/// in order to access them.
#[doc(hidden)]
pub fn new<T: 'static + Any>(value: T) -> Self {
let any_vtable = __fat_pointer!(T as dyn Any).vptr;
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 {
let mut mto = $crate::MultitraitObject::new(self);
$(
$crate::register_traits!(mto, $obj, $trt);
mto._register::<$trt>($crate::__fat_pointer!($obj as $trt).vptr);
)*
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
/// ```rust
/// use multi_trait_object::*;
/// use std::fmt::{Debug, Display};
///
/// let value = String::new();
/// let mut mto = MultitraitObject::new(value);
/// register_traits!(mto, String, dyn Debug, dyn Display);
/// let mto = create_object!(String::new(), dyn Debug, dyn Display);
/// ```
#[macro_export]
macro_rules! register_traits {
($r:expr, $v:ty, $($t:ty), +) => {
macro_rules! create_object {
($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 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)]
struct TestStruct {
@ -42,6 +42,8 @@ fn it_creates_fat_pointers() {
fn it_constructs() {
TestStruct::default().into_multitrait();
String::from("test").into_multitrait();
let mto = create_object!(String::from("test"), dyn Debug);
assert!(mto.is::<String>())
}
#[test]

Loading…
Cancel
Save