use std::cell::RefCell;
use std::thread_local::scoped::Key;
#[macro_export]
macro_rules! current {
(|| $f:expr) => {{
$f
}};
($HEAD:ident: $head:ident $(,$TAIL:ident: $tail:ident)* || $f:expr) => {{
$HEAD.set(&$head, || {
current!{ $($TAIL: $tail),* || $f }
})
}};
}
pub struct Current<T: 'static> {
key: &'static Key<RefCell<T>>,
marker: ::std::kinds::marker::NoSync,
}
impl<T: 'static> Current<T> {
pub unsafe fn new(key: &'static Key<RefCell<T>>) -> Current<T> {
Current { key: key, marker: ::std::kinds::marker::NoSync }
}
pub unsafe fn current(&mut self) -> Option<&mut T> {
use std::mem::transmute;
if self.key.is_set() {
self.key.with(|key| {
Some(transmute(key.borrow_mut().deref_mut()))
})
} else {
None
}
}
pub unsafe fn current_unwrap(&mut self) -> &mut T {
match self.current() {
None => {
use std::intrinsics::get_tydesc;
let name = (*get_tydesc::<T>()).name;
panic!("No current `{}` is set", name);
}
Some(x) => x
}
}
}
impl<T: 'static> Deref<T> for Current<T> {
#[inline(always)]
fn deref<'a>(&'a self) -> &'a T {
use std::mem::transmute;
unsafe {
transmute::<_, &'a mut Current<T>>(self).current_unwrap()
}
}
}
impl<T: 'static> DerefMut<T> for Current<T> {
#[inline(always)]
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
unsafe { self.current_unwrap() }
}
}