use std::cell; #[derive(Debug)] pub struct LazyArray(cell::UnsafeCell>>); impl LazyArray { pub fn new(size: usize) -> LazyArray { let mut inner = Vec::new(); inner.reserve(size); for _ in 0..size { inner.push(None); } LazyArray(cell::UnsafeCell::new(inner)) } pub fn get_or_insert(&self, index: usize, t: T) -> &T { (&mut unsafe { &mut *self.0.get() }[index]).get_or_insert(t) } pub fn get(&self, index: usize) -> Option<&T> { if let Some(ref element) = unsafe { &*self.0.get() }[index] { Some(element) } else { None } } } #[cfg(test)] mod tests { use super::LazyArray; #[test] fn it_works() { let lazy_array = LazyArray::::new(10); for i in 0..10 { assert_eq!(lazy_array.get(i), None) } assert_eq!(lazy_array.get_or_insert(7, 112233), &112233); for i in 0..10 { assert_eq!(lazy_array.get(i), if i == 7 { Some(&112233) } else { None }) } } #[test] fn cannot_insert_twice() { let lazy_array = LazyArray::::new(10); assert_eq!(lazy_array.get_or_insert(7, 112233), &112233); assert_eq!(lazy_array.get_or_insert(7, 445566), &112233); } #[test] #[should_panic] fn cannot_put_out_of_bounds() { let lazy_array = LazyArray::::new(10); lazy_array.get_or_insert(10, 112233); } }