Skip to content

Instantly share code, notes, and snippets.

@Kimundi
Forked from anonymous/playground.rs
Created September 19, 2015 15:14
Show Gist options
  • Save Kimundi/ff3ddcf80dc778f611a6 to your computer and use it in GitHub Desktop.
Save Kimundi/ff3ddcf80dc778f611a6 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
#![feature(unsize)]
#![feature(raw)]
#![feature(const_fn)]
use std::marker::{Unsize, PhantomData};
use std::fmt::Display;
use std::fmt::Debug;
use std::raw::TraitObject;
use std::cell::Cell;
use std::mem;
use std::ops::Deref;
use std::rc::Rc;
use std::sync::Arc;
trait Dst: Unsize<Self> {}
impl<T: ?Sized + Unsize<T>> Dst for T {}
type Meta = *const ();
#[repr(C)]
struct MetaField<D: ?Sized + Dst, T: ?Sized + Unsize<D> = D> {
meta: Meta,
_marker: PhantomData<Cell<*const D>>,
data: T,
}
impl<D: ?Sized + Dst, T: Unsize<D>> MetaField<D, T> {
fn new(t: T) -> MetaField<D, T> {
MetaField {
meta: unsafe {
super_transmute::<*const D, TraitObject>(&t as &D).vtable
},
data: t,
_marker: PhantomData,
}
}
}
impl<D: ?Sized + Dst, T: ?Sized + Unsize<D>> Deref for MetaField<D, T> {
type Target = T;
fn deref(&self) -> &T {
&self.data
}
}
unsafe trait MetaPrefix<D: ?Sized + Dst> {}
unsafe impl<D: ?Sized + Dst, T: ?Sized + Unsize<D>> MetaPrefix<D> for MetaField<D, T> {}
unsafe trait Unaliased {}
unsafe impl<T: ?Sized> Unaliased for Box<T> {}
unsafe impl<'a, T: ?Sized> Unaliased for &'a mut T {}
unsafe trait Ptr: Sized + Deref {
type Erased: Ptr;
unsafe fn erase(self) -> Self::Erased
{
let this = super_transmute::<Self, TraitObject>(self);
super_transmute(this.data)
}
unsafe fn unerase<T>(self, meta: Meta) -> T {
let this = TraitObject {
data: super_transmute(self),
vtable: super_transmute(meta),
};
super_transmute(this)
}
unsafe fn as_unerased<T: ?Sized + Dst>(&self, meta: Meta) -> &T {
let this = TraitObject {
data: super_transmute(&**self),
vtable: super_transmute(meta),
};
super_transmute(this)
}
}
unsafe impl<'a, T: ?Sized> Ptr for &'a T { type Erased = &'a (); }
unsafe impl<'a, T: ?Sized> Ptr for &'a mut T { type Erased = &'a mut (); }
unsafe impl<T: ?Sized> Ptr for Box<T> { type Erased = Box<()>; }
unsafe impl<T: ?Sized> Ptr for Rc<T> { type Erased = Rc<()>; }
unsafe impl<T: ?Sized> Ptr for Arc<T> { type Erased = Arc<()>; }
struct Thin<P: Ptr>
where P::Erased: Deref<Target = ()>
{
data: P::Erased,
_marker: PhantomData<P>,
}
impl<P: Ptr> Thin<P>
where P::Erased: Deref<Target = ()>
{
fn new(dst: P) -> Thin<P>
{
unsafe {
Thin {
data: dst.erase(),
_marker: PhantomData,
}
}
}
}
impl<P: Ptr + Deref> Deref for Thin<P>
where P::Erased: Deref<Target = ()>,
P::Target: Dst,
{
type Target = P::Target;
fn deref(&self) -> &Self::Target {
unsafe {
let meta = *super_transmute::<&(), &Meta>(&*self.data);
self.data.as_unerased(meta)
}
}
}
use std::ptr;
unsafe fn super_transmute<T, U>(t: T) -> U {
let p: *const T = &t;
let p: *const U = p as *const _;
let u: U = ptr::read(&*p);
mem::forget(t);
u
}
////////////////////////////////////////////////////////////////////////////////
struct DstWrap<T: ?Sized> {
_stuff: [u64; 3],
_t: T,
}
fn main() {
let x: &MetaField<Display, i32> = &MetaField::new(5);
let y: &MetaField<DstWrap<Display>, DstWrap<i32>> = &MetaField::new(DstWrap { _stuff: [0,0,0], _t: 10 });
let z: Box<MetaField<Display, i32>> = Box::new(MetaField::new(42));
let rc: Rc<MetaField<Display, i32>> = Rc::new(MetaField::new(64211));
println!("size_of x: {} display: {}", mem::size_of_val(&x), &**x);
println!("size_of y: {}", mem::size_of_val(&y));
println!("size_of z: {} display: {}", mem::size_of_val(&z), &**z);
println!("size_of rc: {} display: {}", mem::size_of_val(&rc), &**rc);
let x_thin: Thin<&MetaField<Display>> = Thin::new(x);
let y_thin: Thin<&MetaField<DstWrap<Display>>> = Thin::new(y);
let z_thin: Thin<Box<MetaField<Display>>> = Thin::new(z);
let rc_thin: Thin<Rc<MetaField<Display>>> = Thin::new(rc);
println!("size_of x_thin: {} display {}", mem::size_of_val(&x_thin), &**x_thin);
println!("size_of y_thin: {}", mem::size_of_val(&y_thin));
println!("size_of z_thin: {} display {}", mem::size_of_val(&z_thin), &**z_thin);
println!("size_of rc_thin: {} display {}", mem::size_of_val(&rc_thin), &**rc_thin);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment