facet_reflect/poke/
option.rs1use core::mem::ManuallyDrop;
2
3use facet_core::{Facet, OptionDef, OptionVTable};
4
5use crate::{HeapValue, ReflectError, ReflectErrorKind};
6
7use super::Poke;
8
9pub struct PokeOption<'mem, 'facet> {
11 value: Poke<'mem, 'facet>,
12 def: OptionDef,
13}
14
15impl<'mem, 'facet> core::fmt::Debug for PokeOption<'mem, 'facet> {
16 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17 f.debug_struct("PokeOption").finish_non_exhaustive()
18 }
19}
20
21impl<'mem, 'facet> PokeOption<'mem, 'facet> {
22 #[inline]
30 pub const unsafe fn new(value: Poke<'mem, 'facet>, def: OptionDef) -> Self {
31 Self { value, def }
32 }
33
34 fn err(&self, kind: ReflectErrorKind) -> ReflectError {
35 self.value.err(kind)
36 }
37
38 #[inline(always)]
40 pub const fn def(&self) -> OptionDef {
41 self.def
42 }
43
44 #[inline(always)]
46 pub const fn vtable(&self) -> &'static OptionVTable {
47 self.def.vtable
48 }
49
50 #[inline]
52 pub fn is_some(&self) -> bool {
53 unsafe { (self.vtable().is_some)(self.value.data()) }
54 }
55
56 #[inline]
58 pub fn is_none(&self) -> bool {
59 !self.is_some()
60 }
61
62 #[inline]
64 pub fn value(&self) -> Option<crate::Peek<'_, 'facet>> {
65 unsafe {
66 let inner_data = (self.vtable().get_value)(self.value.data());
67 if inner_data.is_null() {
68 None
69 } else {
70 Some(crate::Peek::unchecked_new(
71 facet_core::PtrConst::new_sized(inner_data),
72 self.def.t(),
73 ))
74 }
75 }
76 }
77
78 #[inline]
80 pub fn value_mut(&mut self) -> Option<Poke<'_, 'facet>> {
81 unsafe {
82 let inner_data = (self.vtable().get_value)(self.value.data());
83 if inner_data.is_null() {
84 None
85 } else {
86 let offset = inner_data.offset_from(self.value.data().as_byte_ptr()) as usize;
89 let inner_data = self.value.data_mut().field(offset);
90 Some(Poke::from_raw_parts(inner_data, self.def.t()))
91 }
92 }
93 }
94
95 pub fn set_some<T: Facet<'facet>>(&mut self, value: T) -> Result<(), ReflectError> {
97 if self.def.t() != T::SHAPE {
98 return Err(self.err(ReflectErrorKind::WrongShape {
99 expected: self.def.t(),
100 actual: T::SHAPE,
101 }));
102 }
103
104 let mut value = ManuallyDrop::new(value);
105 unsafe {
106 (self.vtable().replace_with)(
107 self.value.data_mut(),
108 &mut value as *mut ManuallyDrop<T> as *mut u8,
109 );
110 }
111 Ok(())
112 }
113
114 pub fn set_some_from_heap<const BORROW: bool>(
122 &mut self,
123 value: HeapValue<'facet, BORROW>,
124 ) -> Result<(), ReflectError> {
125 if self.def.t() != value.shape() {
126 return Err(self.err(ReflectErrorKind::WrongShape {
127 expected: self.def.t(),
128 actual: value.shape(),
129 }));
130 }
131
132 let mut value = value;
133 let guard = value
134 .guard
135 .take()
136 .expect("HeapValue guard was already taken");
137 unsafe {
138 (self.vtable().replace_with)(self.value.data_mut(), guard.ptr.as_ptr());
139 }
140 drop(guard);
141 Ok(())
142 }
143
144 pub fn set_none(&mut self) {
146 unsafe {
147 (self.vtable().replace_with)(self.value.data_mut(), core::ptr::null_mut());
148 }
149 }
150
151 #[inline]
153 pub const fn into_inner(self) -> Poke<'mem, 'facet> {
154 self.value
155 }
156
157 #[inline]
159 pub fn as_peek_option(&self) -> crate::PeekOption<'_, 'facet> {
160 crate::PeekOption {
161 value: self.value.as_peek(),
162 def: self.def,
163 }
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn poke_option_is_some_is_none() {
173 let mut x: Option<i32> = Some(42);
174 let poke = Poke::new(&mut x);
175 let opt = poke.into_option().unwrap();
176 assert!(opt.is_some());
177 assert!(!opt.is_none());
178
179 let mut y: Option<i32> = None;
180 let poke = Poke::new(&mut y);
181 let opt = poke.into_option().unwrap();
182 assert!(opt.is_none());
183 }
184
185 #[test]
186 fn poke_option_set_some_then_none() {
187 let mut x: Option<i32> = None;
188 let poke = Poke::new(&mut x);
189 let mut opt = poke.into_option().unwrap();
190
191 opt.set_some(42i32).unwrap();
192 assert_eq!(x, Some(42));
193
194 let poke = Poke::new(&mut x);
195 let mut opt = poke.into_option().unwrap();
196 opt.set_none();
197 assert_eq!(x, None);
198 }
199
200 #[test]
201 fn poke_option_value_mut() {
202 let mut x: Option<i32> = Some(1);
203 let poke = Poke::new(&mut x);
204 let mut opt = poke.into_option().unwrap();
205
206 {
207 let mut inner = opt.value_mut().unwrap();
208 inner.set(100i32).unwrap();
209 }
210 assert_eq!(x, Some(100));
211 }
212
213 #[test]
214 fn poke_option_set_some_from_heap() {
215 let mut x: Option<i32> = None;
216 let poke = Poke::new(&mut x);
217 let mut opt = poke.into_option().unwrap();
218
219 let hv = crate::Partial::alloc::<i32>()
220 .unwrap()
221 .set(7i32)
222 .unwrap()
223 .build()
224 .unwrap();
225 opt.set_some_from_heap(hv).unwrap();
226 assert_eq!(x, Some(7));
227 }
228
229 #[test]
230 fn poke_option_set_some_from_heap_wrong_shape_fails() {
231 let mut x: Option<i32> = None;
232 let poke = Poke::new(&mut x);
233 let mut opt = poke.into_option().unwrap();
234
235 let hv = crate::Partial::alloc::<u32>()
236 .unwrap()
237 .set(7u32)
238 .unwrap()
239 .build()
240 .unwrap();
241 let res = opt.set_some_from_heap(hv);
242 assert!(matches!(
243 res,
244 Err(ref err) if matches!(err.kind, ReflectErrorKind::WrongShape { .. })
245 ));
246 }
247}