deferred_box/
lib.rs

1use std::cell::UnsafeCell;
2use std::fmt::{Debug, Formatter};
3
4pub struct DeferredBox<T> {
5    unsafe_cell: UnsafeCell<Option<T>>,
6}
7
8impl <T> DeferredBox<T> {
9    pub fn new() -> Self {
10        Self {
11            unsafe_cell: UnsafeCell::new(None),
12        }
13    }
14
15    pub fn get(&self) -> Option<&T> {
16        (unsafe { &*self.unsafe_cell.get() }).as_ref()
17    }
18
19    pub fn get_or_init<F>(&self, init: F) -> &T where F: FnOnce() -> T {
20        if self.get().is_none() {
21            unsafe {
22                *self.unsafe_cell.get() = Some(init());
23            }
24        }
25        self.get().unwrap()
26    }
27
28    pub unsafe fn get_mut(&self) -> Option<&mut T> {
29        { &mut *self.unsafe_cell.get() }.as_mut()
30    }
31
32    pub unsafe fn alter(&self, value: T) {
33        *self.unsafe_cell.get() = Some(value);
34    }
35
36    pub fn set(&self, value: T) -> Result<(), DeferredBoxSetError> {
37        if self.get().is_some() {
38            return Err(DeferredBoxSetError());
39        }
40        unsafe {
41            *self.unsafe_cell.get() = Some(value);
42        }
43        Ok(())
44    }
45}
46
47impl<T> Default for DeferredBox<T> {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53unsafe impl<T> Send for DeferredBox<T> where T: Send { }
54unsafe impl<T> Sync for DeferredBox<T> where T: Sync { }
55
56impl<T> Debug for DeferredBox<T> where T: Debug {
57    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58        write!(f, "DeferredBox {{ {:?} }})", self.get())
59    }
60}
61
62#[derive(Eq, PartialEq, Copy, Clone)]
63pub struct DeferredBoxSetError();
64
65impl Debug for DeferredBoxSetError {
66    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
67        write!(f, "value has been set, trying to set it twice")
68    }
69}
70
71#[cfg(test)]
72mod test {
73    #[test]
74    fn test_deferred_box_for_number() {
75        let deferred_box = super::DeferredBox::new();
76        assert_eq!(deferred_box.get(), None);
77        assert_eq!(deferred_box.set(1), Ok(()));
78        assert_eq!(deferred_box.get(), Some(&1));
79        assert_eq!(deferred_box.set(2), Err(super::DeferredBoxSetError()));
80        assert_eq!(deferred_box.get(), Some(&1));
81    }
82
83    #[test]
84    fn test_deferred_box_for_string() {
85        let deferred_box = super::DeferredBox::new();
86        assert_eq!(deferred_box.get(), None);
87        assert_eq!(deferred_box.set("hello".to_string()), Ok(()));
88        assert_eq!(deferred_box.get(), Some(&"hello".to_string()));
89        assert_eq!(deferred_box.set("world".to_string()), Err(super::DeferredBoxSetError()));
90        assert_eq!(deferred_box.get(), Some(&"hello".to_string()));
91    }
92
93    #[test]
94    fn test_get_or_init() {
95        let deferred_box = super::DeferredBox::new();
96        assert_eq!(deferred_box.get(), None);
97        assert_eq!(deferred_box.get_or_init(|| 1), &1);
98        assert_eq!(deferred_box.get(), Some(&1));
99        assert_eq!(deferred_box.get_or_init(|| 2), &1);
100        assert_eq!(deferred_box.get(), Some(&1));
101    }
102
103    #[test]
104    fn test_debug_message() {
105        let deferred_box: super::DeferredBox<i32> = super::DeferredBox::new();
106        deferred_box.set(50).unwrap();
107        assert_eq!(&format!("{:?}", deferred_box), "DeferredBox { Some(50) })");
108    }
109}