-
-
Save Kimundi/ff3ddcf80dc778f611a6 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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