lazy_array/
lib.rs

1use std::cell;
2
3#[derive(Debug)]
4pub struct LazyArray<T>(cell::UnsafeCell<Vec<Option<T>>>);
5
6impl<T> LazyArray<T> {
7  pub fn new(size: usize) -> LazyArray<T> {
8    let mut inner = Vec::new();
9    inner.reserve(size);
10    for _ in 0..size {
11      inner.push(None);
12    }
13    LazyArray(cell::UnsafeCell::new(inner))
14  }
15
16  pub fn get_or_insert(&self, index: usize, t: T) -> &T {
17    (&mut unsafe { &mut *self.0.get() }[index]).get_or_insert(t)
18  }
19
20  pub fn get(&self, index: usize) -> Option<&T> {
21    if let Some(ref element) = unsafe { &*self.0.get() }[index] {
22      Some(element)
23    } else {
24      None
25    }
26  }
27}
28
29#[cfg(test)]
30mod tests {
31  use super::LazyArray;
32
33  #[test]
34  fn it_works() {
35    let lazy_array = LazyArray::<i32>::new(10);
36    for i in 0..10 {
37      assert_eq!(lazy_array.get(i), None)
38    }
39
40    assert_eq!(lazy_array.get_or_insert(7, 112233), &112233);
41
42    for i in 0..10 {
43      assert_eq!(lazy_array.get(i), if i == 7 { Some(&112233) } else { None })
44    }
45  }
46
47  #[test]
48  fn cannot_insert_twice() {
49    let lazy_array = LazyArray::<i32>::new(10);
50    assert_eq!(lazy_array.get_or_insert(7, 112233), &112233);
51    assert_eq!(lazy_array.get_or_insert(7, 445566), &112233);
52  }
53
54  #[test]
55  #[should_panic]
56  fn cannot_put_out_of_bounds() {
57    let lazy_array = LazyArray::<i32>::new(10);
58    lazy_array.get_or_insert(10, 112233);
59  }
60}