1use std::{cell::UnsafeCell, fmt::{self, Display}, mem::MaybeUninit, ops::Deref};
2
3pub struct RoCell<T> {
7 inner: UnsafeCell<MaybeUninit<T>>,
8 #[cfg(debug_assertions)]
9 initialized: UnsafeCell<bool>,
10}
11
12unsafe impl<T> Sync for RoCell<T> {}
13
14impl<T> RoCell<T> {
15 #[inline]
16 pub const fn new() -> Self {
17 Self {
18 inner: UnsafeCell::new(MaybeUninit::uninit()),
19 #[cfg(debug_assertions)]
20 initialized: UnsafeCell::new(false),
21 }
22 }
23
24 #[inline]
25 pub const fn new_const(value: T) -> Self {
26 Self {
27 inner: UnsafeCell::new(MaybeUninit::new(value)),
28 #[cfg(debug_assertions)]
29 initialized: UnsafeCell::new(true),
30 }
31 }
32
33 #[inline]
34 pub fn init(&self, value: T) {
35 unsafe {
36 #[cfg(debug_assertions)]
37 assert!(!self.initialized.get().replace(true));
38 *self.inner.get() = MaybeUninit::new(value);
39 }
40 }
41
42 #[inline]
43 pub fn with<F>(&self, f: F)
44 where
45 F: FnOnce() -> T,
46 {
47 self.init(f());
48 }
49
50 #[inline]
51 pub fn drop(&self) -> T {
52 unsafe {
53 #[cfg(debug_assertions)]
54 assert!(self.initialized.get().replace(false));
55 self.inner.get().replace(MaybeUninit::uninit()).assume_init()
56 }
57 }
58}
59
60impl<T> Default for RoCell<T> {
61 fn default() -> Self { Self::new() }
62}
63
64impl<T> Deref for RoCell<T> {
65 type Target = T;
66
67 fn deref(&self) -> &Self::Target {
68 unsafe {
69 #[cfg(debug_assertions)]
70 assert!(*self.initialized.get());
71 (*self.inner.get()).assume_init_ref()
72 }
73 }
74}
75
76impl<T> Display for RoCell<T>
77where
78 T: Display,
79{
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.deref().fmt(f) }
81}