Update metadata and add safety comments

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

@ -2,6 +2,11 @@
name = "multi-trait-object"
version = "0.1.0"
edition = "2021"
readme = "README.md"
license = "Apache-2.0"
authors = ["trivernis"]
description = "A type to store an object with all associated traits"
repository = "https://github.com/Trivernis/multi-trait-object/tree/main"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -6,6 +6,12 @@ This is done by storing the pointer to the v-table for each
trait implementation on the type as well as the pointer to the
data.
## Safety
All unsafe parts are perfectly safe as far as my understanding goes.
As this crate is still in an early stage there might be some side effects that haven't
been noticed yet.
## Usage
```rust

@ -33,20 +33,21 @@ pub struct FatPointer {
/// ```
#[derive(Debug)]
pub struct MultitraitObject {
pub data: *mut (),
pub original_typeid: TypeId,
pub any_vtable: *const (),
pub traits: HashMap<TypeId, *const ()>,
data: *mut (),
original_typeid: TypeId,
traits: HashMap<TypeId, *const ()>,
}
impl MultitraitObject {
/// Creates a new multitrait object from the given value
/// All traits except Any must be registered on this object
/// in order to access them.
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 ();
let mut this = Self {
data,
any_vtable,
original_typeid: TypeId::of::<T>(),
traits: Default::default(),
};
@ -104,6 +105,7 @@ impl MultitraitObject {
pub fn downcast<T: Any>(self) -> Option<T> {
if TypeId::of::<T>() == self.original_typeid {
unsafe {
// SAFETY: We've checked for the type so it's safe to cast the data and consume it in the process
let typed_ptr = std::mem::transmute::<_, *mut T>(self.data);
let boxed = Box::from_raw(typed_ptr);
@ -121,6 +123,7 @@ impl MultitraitObject {
#[doc(hidden)]
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>())?;
let fat_pointer = FatPointer { data: self.data, vptr };
let value = std::mem::transmute::<_, &&T1>(&fat_pointer);
@ -130,6 +133,7 @@ impl MultitraitObject {
#[doc(hidden)]
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>())?;
let mut fat_pointer = FatPointer { data: self.data, vptr };
let value = std::mem::transmute::<_, &mut &mut T1>(&mut fat_pointer);
@ -139,6 +143,7 @@ impl MultitraitObject {
#[doc(hidden)]
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>())?;
let fat_pointer = FatPointer { data: self.data, vptr };
let value = std::mem::transmute::<_, *const *mut T1>(&fat_pointer);
@ -151,6 +156,7 @@ impl MultitraitObject {
impl Drop for MultitraitObject {
fn drop(&mut self) {
unsafe {
// Safety: The Multitrait object has exclusive access to the data pointer
let raw = Box::from_raw(self.data);
std::mem::drop(raw);
}

Loading…
Cancel
Save