tux_owned_alloc/
maybe_uninit.rs1use super::{OwnedAlloc, UninitAlloc};
2use std::fmt;
3
4pub enum MaybeUninitAlloc<T>
8where
9 T: ?Sized,
10{
11 Init(OwnedAlloc<T>),
13
14 Uninit(UninitAlloc<T>),
16}
17
18impl<T> MaybeUninitAlloc<T> {
19 pub fn or_init<F>(self, init: F) -> OwnedAlloc<T>
23 where
24 F: FnOnce() -> T,
25 {
26 match self {
27 MaybeUninitAlloc::Init(ptr) => ptr,
28 MaybeUninitAlloc::Uninit(ptr) => ptr.init(init()),
29 }
30 }
31}
32
33impl<T> MaybeUninitAlloc<T>
34where
35 T: ?Sized,
36{
37 pub unsafe fn or_init_in_place<F>(self, init: F) -> OwnedAlloc<T>
46 where
47 F: FnOnce(&mut T),
48 {
49 match self {
50 MaybeUninitAlloc::Init(ptr) => ptr,
51 MaybeUninitAlloc::Uninit(ptr) => ptr.init_in_place(init),
52 }
53 }
54
55 pub fn is_initialized(&self) -> bool {
57 match self {
58 MaybeUninitAlloc::Init(_) => true,
59 MaybeUninitAlloc::Uninit(_) => false,
60 }
61 }
62
63 pub fn is_uninitialized(&self) -> bool {
65 match self {
66 MaybeUninitAlloc::Init(_) => true,
67 MaybeUninitAlloc::Uninit(_) => false,
68 }
69 }
70
71 pub fn drop_in_place(self) -> UninitAlloc<T> {
74 match self {
75 MaybeUninitAlloc::Init(ptr) => ptr.drop_in_place(),
76 MaybeUninitAlloc::Uninit(ptr) => ptr,
77 }
78 }
79
80 pub fn init_as_ok(self) -> Result<OwnedAlloc<T>, UninitAlloc<T>> {
82 match self {
83 MaybeUninitAlloc::Init(ptr) => Ok(ptr),
84 MaybeUninitAlloc::Uninit(ptr) => Err(ptr),
85 }
86 }
87
88 pub fn uninit_as_ok(self) -> Result<UninitAlloc<T>, OwnedAlloc<T>> {
90 match self {
91 MaybeUninitAlloc::Init(ptr) => Err(ptr),
92 MaybeUninitAlloc::Uninit(ptr) => Ok(ptr),
93 }
94 }
95
96 pub fn modify<F, A>(&mut self, visit: F) -> Option<A>
100 where
101 F: FnOnce(&mut T) -> A,
102 {
103 match self {
104 MaybeUninitAlloc::Init(ptr) => Some(visit(&mut **ptr)),
105 MaybeUninitAlloc::Uninit(_) => None,
106 }
107 }
108}
109
110impl<T> From<T> for MaybeUninitAlloc<T> {
111 fn from(val: T) -> Self {
112 MaybeUninitAlloc::Init(OwnedAlloc::new(val))
113 }
114}
115
116impl<T> From<OwnedAlloc<T>> for MaybeUninitAlloc<T>
117where
118 T: ?Sized,
119{
120 fn from(alloc: OwnedAlloc<T>) -> Self {
121 MaybeUninitAlloc::Init(alloc)
122 }
123}
124
125impl<T> From<UninitAlloc<T>> for MaybeUninitAlloc<T>
126where
127 T: ?Sized,
128{
129 fn from(alloc: UninitAlloc<T>) -> Self {
130 MaybeUninitAlloc::Uninit(alloc)
131 }
132}
133
134impl<T> fmt::Debug for MaybeUninitAlloc<T>
135where
136 T: ?Sized,
137{
138 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
139 match self {
140 MaybeUninitAlloc::Init(ptr) => write!(fmtr, "Init({:?})", ptr),
141 MaybeUninitAlloc::Uninit(ptr) => write!(fmtr, "Uninit({:?})", ptr),
142 }
143 }
144}
145
146#[cfg(test)]
147mod test {
148 use super::{super::UninitAlloc, MaybeUninitAlloc};
149
150 #[test]
151 fn or_init_is_noop_if_initialized() {
152 let init = MaybeUninitAlloc::from(90);
153
154 assert_eq!(*init.or_init(|| 50), 90);
155 }
156
157 #[test]
158 fn or_init_calls_if_uninit() {
159 let init = MaybeUninitAlloc::from(UninitAlloc::new());
160
161 assert_eq!(*init.or_init(|| 50), 50);
162 }
163
164 #[test]
165 fn modifies() {
166 let mut init = MaybeUninitAlloc::from(20);
167
168 assert!(init.modify(|addr| *addr = 2).is_some());
169 assert_eq!(*init.init_as_ok().unwrap(), 2);
170 }
171}