1 use std::any::{Any, TypeId}; 2 use std::cell::UnsafeCell; 3 use std::collections::HashMap; 4 use std::fmt; 5 use std::mem; 6 use std::ops::Deref; 7 8 pub struct OptCell<T>(UnsafeCell<Option<T>>); 9 10 impl<T> OptCell<T> { 11 #[inline] new(val: Option<T>) -> OptCell<T>12 pub fn new(val: Option<T>) -> OptCell<T> { 13 OptCell(UnsafeCell::new(val)) 14 } 15 16 #[inline] set(&self, val: T)17 pub fn set(&self, val: T) { 18 unsafe { 19 let opt = self.0.get(); 20 debug_assert!((*opt).is_none()); 21 *opt = Some(val) 22 } 23 } 24 25 #[inline] get_mut(&mut self) -> &mut T26 pub unsafe fn get_mut(&mut self) -> &mut T { 27 let opt = &mut *self.0.get(); 28 opt.as_mut().unwrap() 29 } 30 } 31 32 impl<T> Deref for OptCell<T> { 33 type Target = Option<T>; 34 #[inline] deref(&self) -> &Option<T>35 fn deref(&self) -> &Option<T> { 36 unsafe { &*self.0.get() } 37 } 38 } 39 40 impl<T: Clone> Clone for OptCell<T> { 41 #[inline] clone(&self) -> OptCell<T>42 fn clone(&self) -> OptCell<T> { 43 OptCell::new((**self).clone()) 44 } 45 } 46 47 pub struct PtrMapCell<V: ?Sized>(UnsafeCell<PtrMap<Box<V>>>); 48 49 #[derive(Clone, Debug)] 50 enum PtrMap<T> { 51 Empty, 52 One(TypeId, T), 53 Many(HashMap<TypeId, T>) 54 } 55 56 impl<V: ?Sized + fmt::Debug + Any + 'static> PtrMapCell<V> { 57 #[inline] new() -> PtrMapCell<V>58 pub fn new() -> PtrMapCell<V> { 59 PtrMapCell(UnsafeCell::new(PtrMap::Empty)) 60 } 61 62 #[inline] get(&self, key: TypeId) -> Option<&V>63 pub fn get(&self, key: TypeId) -> Option<&V> { 64 let map = unsafe { &*self.0.get() }; 65 match *map { 66 PtrMap::Empty => None, 67 PtrMap::One(id, ref v) => if id == key { 68 Some(v) 69 } else { 70 None 71 }, 72 PtrMap::Many(ref hm) => hm.get(&key) 73 }.map(|val| &**val) 74 } 75 76 #[inline] get_mut(&mut self, key: TypeId) -> Option<&mut V>77 pub fn get_mut(&mut self, key: TypeId) -> Option<&mut V> { 78 let map = unsafe { &mut *self.0.get() }; 79 match *map { 80 PtrMap::Empty => None, 81 PtrMap::One(id, ref mut v) => if id == key { 82 Some(v) 83 } else { 84 None 85 }, 86 PtrMap::Many(ref mut hm) => hm.get_mut(&key) 87 }.map(|val| &mut **val) 88 } 89 90 #[inline] insert(&self, key: TypeId, val: Box<V>)91 pub unsafe fn insert(&self, key: TypeId, val: Box<V>) { 92 let map = &mut *self.0.get(); 93 match *map { 94 PtrMap::Empty => *map = PtrMap::One(key, val), 95 PtrMap::One(..) => { 96 let one = mem::replace(map, PtrMap::Empty); 97 match one { 98 PtrMap::One(id, one) => { 99 debug_assert!(id != key); 100 let mut hm = HashMap::with_capacity(2); 101 hm.insert(id, one); 102 hm.insert(key, val); 103 mem::replace(map, PtrMap::Many(hm)); 104 }, 105 _ => unreachable!() 106 } 107 }, 108 PtrMap::Many(ref mut hm) => { hm.insert(key, val); } 109 } 110 } 111 112 #[inline] one(&self) -> &V113 pub unsafe fn one(&self) -> &V { 114 let map = &*self.0.get(); 115 match *map { 116 PtrMap::One(_, ref one) => one, 117 _ => panic!("not PtrMap::One value, {:?}", *map) 118 } 119 } 120 } 121 122 impl<V: ?Sized + fmt::Debug + Any + 'static> Clone for PtrMapCell<V> where Box<V>: Clone { 123 #[inline] clone(&self) -> PtrMapCell<V>124 fn clone(&self) -> PtrMapCell<V> { 125 let cell = PtrMapCell::new(); 126 unsafe { 127 *cell.0.get() = (&*self.0.get()).clone() 128 } 129 cell 130 } 131 } 132 133 #[cfg(test)] 134 mod test { 135 use std::any::TypeId; 136 use super::*; 137 138 #[test] test_opt_cell_set()139 fn test_opt_cell_set() { 140 let one:OptCell<u32> = OptCell::new(None); 141 one.set(1); 142 assert_eq!(*one,Some(1)); 143 } 144 145 #[test] test_opt_cell_clone()146 fn test_opt_cell_clone() { 147 let one:OptCell<u32> = OptCell::new(Some(3)); 148 let stored = *one.clone(); 149 assert_eq!(stored,Some(3)); 150 } 151 152 153 #[test] test_ptr_map_cell_none()154 fn test_ptr_map_cell_none() { 155 let type_id = TypeId::of::<u32>(); 156 let pm:PtrMapCell<u32> = PtrMapCell::new(); 157 assert_eq!(pm.get(type_id),None); 158 } 159 160 #[test] test_ptr_map_cell_one()161 fn test_ptr_map_cell_one() { 162 let type_id = TypeId::of::<String>(); 163 let pm:PtrMapCell<String> = PtrMapCell::new(); 164 unsafe { pm.insert(type_id, Box::new("a".to_string())); } 165 assert_eq!(pm.get(type_id), Some(&"a".to_string())); 166 assert_eq!(unsafe {pm.one()}, "a"); 167 } 168 169 #[test] test_ptr_map_cell_two()170 fn test_ptr_map_cell_two() { 171 let type_id = TypeId::of::<String>(); 172 let type_id2 = TypeId::of::<Vec<u8>>(); 173 let pm:PtrMapCell<String> = PtrMapCell::new(); 174 unsafe { pm.insert(type_id, Box::new("a".to_string())); } 175 unsafe { pm.insert(type_id2, Box::new("b".to_string())); } 176 assert_eq!(pm.get(type_id), Some(&"a".to_string())); 177 assert_eq!(pm.get(type_id2), Some(&"b".to_string())); 178 } 179 180 #[test] test_ptr_map_cell_many()181 fn test_ptr_map_cell_many() { 182 let id1 = TypeId::of::<String>(); 183 let id2 = TypeId::of::<Vec<u8>>(); 184 let id3 = TypeId::of::<OptCell<String>>(); 185 let pm:PtrMapCell<String> = PtrMapCell::new(); 186 unsafe { pm.insert(id1, Box::new("a".to_string())); } 187 unsafe { pm.insert(id2, Box::new("b".to_string())); } 188 unsafe { pm.insert(id3, Box::new("c".to_string())); } 189 assert_eq!(pm.get(id1), Some(&"a".to_string())); 190 assert_eq!(pm.get(id2), Some(&"b".to_string())); 191 assert_eq!(pm.get(id3), Some(&"c".to_string())); 192 } 193 194 195 #[test] test_ptr_map_cell_clone()196 fn test_ptr_map_cell_clone() { 197 let type_id = TypeId::of::<String>(); 198 let pm:PtrMapCell<String> = PtrMapCell::new(); 199 unsafe { pm.insert(type_id, Box::new("a".to_string())); } 200 let cloned = pm.clone(); 201 assert_eq!(cloned.get(type_id), Some(&"a".to_string())); 202 } 203 204 } 205