1#![deny(missing_docs)]
2#![feature(core_intrinsics)]
3#![allow(mutable_transmutes)]
4
5
6use std::cell::RefCell;
10use std::any::{ TypeId, Any };
11use std::collections::HashMap;
12use std::collections::hash_map::Entry::{ Occupied, Vacant };
13use std::ops::{ Deref, DerefMut };
14use std::marker::PhantomData;
15
16thread_local!(static KEY_CURRENT: RefCell<HashMap<TypeId, usize>>
18 = RefCell::new(HashMap::new()));
19
20pub struct CurrentGuard<'a, T> where T: Any {
22 _val: &'a mut T,
23 old_ptr: Option<usize>
24}
25
26#[allow(trivial_casts)]
27impl<'a, T> CurrentGuard<'a, T> where T: Any {
28 pub fn new(val: &mut T) -> CurrentGuard<T> {
30 let id = TypeId::of::<T>();
31 let ptr = val as *mut T as usize;
32 let old_ptr = KEY_CURRENT.with(|current| {
33 match current.borrow_mut().entry(id) {
34 Occupied(mut entry) => Some(entry.insert(ptr)),
35 Vacant(entry) => {
36 entry.insert(ptr);
37 None
38 }
39 }
40 });
41 CurrentGuard { old_ptr: old_ptr, _val: val }
42 }
43}
44
45impl<'a, T> Drop for CurrentGuard<'a, T> where T: Any {
46 fn drop(&mut self) {
47 let id = TypeId::of::<T>();
48 match self.old_ptr {
49 None => {
50 KEY_CURRENT.with(|current| {
51 current.borrow_mut().remove(&id);
52 });
53 return;
54 }
55 Some(old_ptr) => {
56 KEY_CURRENT.with(|current| {
57 match current.borrow_mut().entry(id) {
58 Occupied(mut entry) => { entry.insert(old_ptr); }
59 Vacant(entry) => { entry.insert(old_ptr); }
60 };
61 });
62 }
63 };
64 }
65}
66
67pub struct Current<T>(PhantomData<T>);
69
70impl<T> Current<T> where T: Any {
71 pub unsafe fn new() -> Current<T> { Current(PhantomData) }
73
74 pub unsafe fn current(&mut self) -> Option<&mut T> {
79 use std::mem::transmute;
80 let id = TypeId::of::<T>();
81 let ptr: Option<usize> = KEY_CURRENT.with(|current| {
82 current.borrow().get(&id).map(|id| *id)
83 });
84 let ptr = match ptr { None => { return None; } Some(x) => x };
85 Some(transmute(ptr as *mut T))
86 }
87
88 pub unsafe fn current_unwrap(&mut self) -> &mut T {
91 match self.current() {
92 None => {
93 use std::intrinsics::type_name;
94 panic!("No current `{}` is set", type_name::<T>());
95 }
96 Some(x) => x
97 }
98 }
99}
100
101impl<T> Deref for Current<T> where T: Any {
102 type Target = T;
103
104 #[inline(always)]
105 fn deref<'a>(&'a self) -> &'a T {
106 use std::mem::transmute;
107 unsafe {
108 transmute::<_, &'a mut Current<T>>(self).current_unwrap()
111 }
112 }
113}
114
115impl<T> DerefMut for Current<T> where T: Any {
116 #[inline(always)]
117 fn deref_mut<'a>(&'a mut self) -> &'a mut T {
118 unsafe { self.current_unwrap() }
119 }
120}