Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(raw)]
- #![feature(untagged_unions)]
- use std::mem;
- use std::ops::{Deref, DerefMut, Drop};
- use std::ptr;
- use std::raw::TraitObject;
- fn main() {
- let foo = Foo("les baguettes c'est merveilleux".to_owned());
- let bar = Bar(vec![29, 87]);
- let a_just_do = ClosedJustDo::from(foo);
- let another_just_do = ClosedJustDo::from(bar);
- a_just_do.just_do();
- another_just_do.just_do();
- }
- trait JustDo {
- fn just_do(&self) {}
- }
- struct Foo(String);
- impl JustDo for Foo {
- fn just_do(&self) {
- println!("{}", self.0);
- }
- }
- struct Bar(Vec<u8>);
- impl JustDo for Bar {
- fn just_do(&self) {
- println!("{:?}", self.0);
- }
- }
- struct ClosedJustDo {
- vtable: *mut (),
- drop: unsafe fn(*mut ()),
- payload: ClosedJustDoPayload,
- }
- #[allow(unions_with_drop_fields)]
- union ClosedJustDoPayload {
- foo: Foo,
- bar: Bar,
- }
- impl From<Foo> for ClosedJustDo {
- fn from(foo: Foo) -> Self {
- let vtable = unsafe { mem::transmute::<&dyn JustDo, TraitObject>(&foo).vtable };
- let drop = unsafe {
- mem::transmute::<unsafe fn(*mut Foo), unsafe fn(*mut ())>(ptr::drop_in_place)
- };
- let payload = ClosedJustDoPayload { foo };
- Self {
- vtable,
- drop,
- payload,
- }
- }
- }
- impl From<Bar> for ClosedJustDo {
- fn from(bar: Bar) -> Self {
- let vtable = unsafe { mem::transmute::<&dyn JustDo, TraitObject>(&bar).vtable };
- let drop = unsafe {
- mem::transmute::<unsafe fn(*mut Bar), unsafe fn(*mut ())>(ptr::drop_in_place)
- };
- let payload = ClosedJustDoPayload { bar };
- Self {
- vtable,
- drop,
- payload,
- }
- }
- }
- impl Deref for ClosedJustDo {
- type Target = dyn JustDo;
- fn deref(&self) -> &Self::Target {
- unsafe {
- let vtable = self.vtable;
- let data = &self.payload as *const ClosedJustDoPayload as *mut ();
- let object = TraitObject { vtable, data };
- mem::transmute::<TraitObject, &Self::Target>(object)
- }
- }
- }
- impl DerefMut for ClosedJustDo {
- fn deref_mut(&mut self) -> &mut Self::Target {
- unsafe {
- let vtable = self.vtable;
- let data = &mut self.payload as *mut ClosedJustDoPayload as *mut ();
- let object = TraitObject { vtable, data };
- mem::transmute::<TraitObject, &mut Self::Target>(object)
- }
- }
- }
- impl Drop for ClosedJustDo {
- fn drop(&mut self) {
- unsafe {
- (self.drop)(&mut self.payload as *mut ClosedJustDoPayload as *mut ());
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement