-
-
Save jdm/9332689 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
#[feature(macro_rules)]; | |
use std::cast; | |
trait RootedReference<T> { | |
fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>>; | |
} | |
impl<T> RootedReference<T> for Option<Rooted<T>> { | |
fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>> { | |
self.as_ref().map(|js| js.root_ref()) | |
} | |
} | |
macro_rules! root( | |
($($name:ident = $js:expr),+ in $rest:expr) => { | |
{ | |
$(let $name;)+ | |
unsafe { | |
$($name = Rooted::new(&$js);)+ | |
} | |
$(let _you_cannot_move_a_rooted_javascript_object = &$name;)+ | |
$rest | |
} | |
} | |
) | |
macro_rules! maybe_root( | |
($($name:ident = $js:expr),+ in $rest:expr) => { | |
{ | |
$(let $name;)+ | |
unsafe { | |
$($name = ($js).map(|val| Rooted::new(&val));)+ | |
} | |
$(let _you_cannot_move_a_rooted_javascript_object = &$name;)+ | |
$rest | |
} | |
} | |
) | |
pub struct JS<T> { | |
priv ptr: *mut T, | |
} | |
impl<T> JS<T> { | |
pub fn get<'a>(&'a self) -> &'a mut T { | |
unsafe { | |
cast::transmute(self.ptr) | |
} | |
} | |
pub fn set(&mut self, other: JSRef<T>) { | |
self.ptr = other.ptr; | |
} | |
} | |
#[unsafe_destructor] | |
impl<T> Drop for JS<T> { | |
fn drop(&mut self) {} | |
} | |
pub struct Rooted<T> { | |
priv ptr: *mut T, | |
} | |
impl<T> Rooted<T> { | |
pub unsafe fn new(js_object: &JS<T>) -> Rooted<T> { | |
println!("rooting!"); | |
Rooted { | |
ptr: js_object.ptr, | |
} | |
} | |
pub fn get<'a>(&'a self) -> &'a mut T { | |
unsafe { | |
cast::transmute(self.ptr) | |
} | |
} | |
pub fn root_ref<'a>(&'a self) -> JSRef<'a,T> { | |
unsafe { | |
JSRef { | |
ptr: self.ptr, | |
chain: ::std::cast::transmute_region(&()), | |
} | |
} | |
} | |
} | |
#[unsafe_destructor] | |
impl<T> Drop for Rooted<T> { | |
fn drop(&mut self) { | |
println!("dropping root!"); | |
} | |
} | |
/// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable. | |
pub struct JSRef<'a,T> { | |
priv ptr: *mut T, | |
priv chain: &'a (), | |
} | |
impl<'a,T> JSRef<'a,T> { | |
pub fn get<'a>(&'a self) -> &'a mut T { | |
unsafe { | |
cast::transmute(self.ptr) | |
} | |
} | |
} | |
pub struct IntContainer { | |
value: JS<int>, | |
} | |
pub fn main() { | |
// setup | |
let mut value = 3; | |
let three: JS<int> = JS { | |
ptr: &mut value, | |
}; | |
let mut value = 5; | |
let five: JS<int> = JS { | |
ptr: &mut value, | |
}; | |
let mut value = IntContainer { | |
value: five, | |
}; | |
let int_container: JS<IntContainer> = JS { | |
ptr: &mut value, | |
}; | |
// rooting! | |
root!(rooted_three = three, | |
rooted_int_container = int_container in { | |
println!("rooted object has value {}", *rooted_three.get()); | |
// let _ = you_cannot_move_a_rooted_javascript_object; -- prohibited; inaccessible | |
// drop(rooted_three); -- prohibited; cannot move out because borrowed | |
other_function(rooted_int_container.root_ref(), rooted_three.root_ref()); | |
}); | |
let mut value = 6; | |
let six: JS<int> = JS { | |
ptr: &mut value, | |
}; | |
maybe_root!(rooted_possible_six = Some(six), | |
rooted_possible_seven = None in { | |
another_function(rooted_possible_six.root_ref()); | |
another_function(rooted_possible_seven.root_ref()); | |
}); | |
let mut value = 7; | |
root!(rooted_seven = return_value(&mut value) in { | |
another_function(Some(rooted_seven.root_ref())) | |
}); | |
} | |
fn other_function(int_container: JSRef<IntContainer>, value: JSRef<int>) { | |
println!("I had {}", *int_container.get().value.get()); | |
int_container.get().value.set(value); | |
println!("I now have {}", *int_container.get().value.get()); | |
} | |
fn another_function(maybe_value: Option<JSRef<int>>) { | |
match maybe_value { | |
Some(val) => println!("I had {}", *val.get()), | |
None => println!("didn't have anything"), | |
} | |
} | |
fn return_value(unboxed: &mut int) -> JS<int> { | |
JS { | |
ptr: unboxed | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment