Skip to content

Instantly share code, notes, and snippets.

@krdln
Last active August 29, 2015 14:06
Show Gist options
  • Save krdln/08764f70a1e5aeda2338 to your computer and use it in GitHub Desktop.
Save krdln/08764f70a1e5aeda2338 to your computer and use it in GitHub Desktop.
Slim pointers to fat objects using DST
#![feature(unsafe_destructor, macro_rules)]
#[macro_escape] mod fat {
use std::mem::transmute;
use std::raw::TraitObject;
#[unsafe_no_drop_flag]
pub struct SlimPtr<Sized? T> {
ptr: *mut *mut ()
}
impl<Sized? T> SlimPtr<T> {
pub unsafe fn as_trait_object(&self) -> TraitObject {
TraitObject{
data: self.ptr.offset(1) as *mut (),
vtable: *self.ptr
}
}
}
#[unsafe_destructor]
impl<Sized? T> Drop for SlimPtr<T> {
fn drop(&mut self) {
let _dropme: Box<T> = unsafe {
transmute(self.as_trait_object())
};
self.ptr = 0 as *mut *mut ();
}
}
impl<Sized? T> Deref<T> for SlimPtr<T> {
fn deref(&self) -> &T {
unsafe { transmute(self.as_trait_object()) }
}
}
pub struct FatObj<Sized? T> {
pub fat: *mut (),
pub data: T
}
macro_rules! factory( ($name:ident -> $Trait:ident) => (
fn $name<T: $Trait + 'static>
(val: T) -> fat::SlimPtr<$Trait + 'static> {
use std::mem::transmute;
use std::raw::TraitObject;
let mut foo = box fat::FatObj{ fat: 0 as *mut (), data: val };
let TraitObject{vtable: fat, ..}: TraitObject = unsafe { transmute({
let reff: &$Trait = &foo.data;
reff
}) };
foo.fat = fat;
unsafe { transmute(foo) }
}
))
}
trait Foo {
fn foo(&self);
}
factory!(create_foo -> Foo)
impl<T: std::fmt::Show> Foo for Vec<T> {
fn foo(&self) { println!("{}", *self); }
}
fn main() {
let foo = create_foo(vec![1, 2, 14i]);
println!("size: {}", std::mem::size_of_val(&foo));
foo.foo();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment