1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
use std::cell; #[derive(Debug)] pub struct LazyArray<T>(cell::UnsafeCell<Box<[Option<T>]>>); impl<T> LazyArray<T> { pub fn new(size: usize) -> LazyArray<T> { let mut init = Vec::<Option<T>>::with_capacity(size); for _ in 0..size { init.push(None) } LazyArray(cell::UnsafeCell::new(init.into_boxed_slice())) } 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 } } } impl<T> Default for LazyArray<T> { fn default() -> Self { Self::new(0) } } #[cfg(test)] mod tests { use super::LazyArray; #[test] fn it_works() { let lazy_array = LazyArray::<i32>::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::<i32>::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::<i32>::new(10); lazy_array.get_or_insert(10, 112233); } }