Last active
February 28, 2016 19:33
-
-
Save Sgeo/87e24d8cd798abc8deb4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
use std::rc::{Rc, Weak}; | |
use std::cell::RefCell; | |
pub struct Scope<'t, T: 't> { | |
filled: bool, | |
hole: &'t mut T | |
} | |
impl<'t, T: 't> Scope<'t, T> { | |
unsafe fn new(mut_ref: &'t mut T) -> (T, Self) { | |
use std::ptr; | |
(ptr::read(mut_ref), Scope { filled: false, hole: mut_ref }) | |
} | |
} | |
pub struct Hole<'t, T: 't> { | |
scope: Weak<RefCell<Scope<'t, T>>>, | |
} | |
impl<'t, T> Drop for Scope<'t, T> { | |
fn drop(&mut self) { | |
if !self.filled { | |
panic!("Unfilled hole!"); | |
} | |
} | |
} | |
impl<'t, T: 't> Hole<'t, T> { | |
fn new(scope: Weak<RefCell<Scope<'t, T>>>) -> Self { | |
Hole { scope: scope } | |
} | |
fn fill(self, t: T) { | |
use std::ptr; | |
let scope_option_rc = self.scope.upgrade(); | |
let scope_rc = scope_option_rc.expect("A Hole's Scope was destructed. Should be impossible?"); | |
let mut scope_mut = scope_rc.borrow_mut(); | |
unsafe { | |
use std::ops::DerefMut; | |
ptr::write(scope_mut.deref_mut().hole, t); | |
} | |
scope_mut.filled = true; | |
} | |
} | |
unsafe fn create_scope_hole_t<'t, T: 't>(mut_ref: &'t mut T) -> (Rc<RefCell<Scope<'t, T>>>, Hole<'t, T>, T) { | |
let (t, scope) = Scope::new(mut_ref); | |
let scope_ref = Rc::new(RefCell::new(scope)); | |
let hole = Hole::new(Rc::downgrade(&scope_ref)); | |
(scope_ref, hole, t) | |
} | |
macro_rules! take_mut { | |
($into:pat, $hole:pat = $mut_ref:expr) => { | |
let (_scope, $hole, $into) = unsafe { create_scope_hole_t($mut_ref) }; | |
} | |
} | |
fn main() { | |
#[derive(Debug)] | |
struct Foo; | |
#[derive(Debug)] | |
struct Bar { | |
a: Foo, | |
b: Foo | |
} | |
let mut bar = Bar { a: Foo, b: Foo }; | |
{ | |
take_mut!(a, a_hole = &mut bar.a); | |
take_mut!(b, b_hole = &mut bar.b); | |
a_hole.fill(Foo); | |
b_hole.fill(Foo); | |
} | |
println!("{:?}", &bar); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment