Skip to content

Instantly share code, notes, and snippets.

@Kimundi
Forked from anonymous/playground.rs
Created September 19, 2015 14:42
Show Gist options
  • Save Kimundi/bdc59228b89345ee25af to your computer and use it in GitHub Desktop.
Save Kimundi/bdc59228b89345ee25af 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 = D> {
meta: Cell<Meta>,
_marker: PhantomData<Cell<*const D>>,
data: T,
}
impl<D: ?Sized + Dst, T> MetaField<D, T> {
const fn new(t: T) -> MetaField<D, T> {
MetaField {
meta: Cell::new(0 as *const _),
data: t,
_marker: PhantomData,
}
}
}
impl<D: ?Sized + Dst, T: ?Sized> 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> 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, Meta)
{
let this = super_transmute::<Self, TraitObject>(self);
let meta = super_transmute(this.vtable);
(super_transmute(this.data), meta)
}
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 {
let meta_ref: &Cell<Meta> = super_transmute(&*dst);
let (data, meta) = dst.erase();
meta_ref.set(meta);
Thin {
data: data,
_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::<&(), &Cell<Meta>>(&*self.data);
let meta = meta.get();
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,
}
static mut X: MetaField<Display, i32> = MetaField::new(5);
static mut Y: MetaField<DstWrap<Display>, DstWrap<i32>> = MetaField::new(DstWrap { _stuff: [0,0,0], _t: 10 });
fn main() {
// 'static default prevents creating these borrowed DST on the stack.
let x: &MetaField<_> = unsafe { &X };
let y: &MetaField<_> = unsafe { &Y };
println!("size_of x: {} display: {}", mem::size_of_val(&x), &**x);
println!("size_of y: {}", mem::size_of_val(&y));
let x_thin: Thin<&MetaField<Display>> = Thin::new(x);
let y_thin: Thin<&MetaField<DstWrap<Display>>> = Thin::new(y);
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));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment