facet_core/impls_core/
option.rs1use core::mem::MaybeUninit;
2
3use crate::{
4 Def, Facet, OptionDef, OptionVTable, PtrConst, PtrMut, PtrUninit, Shape, TryBorrowInnerError,
5 TryFromError, TryIntoInnerError, TypedPtrUninit, VTableView, value_vtable,
6};
7unsafe impl<'a, T: Facet<'a>> Facet<'a> for Option<T> {
8 const SHAPE: &'static Shape = &const {
9 unsafe fn try_from<'a, 'src, 'dst, T: Facet<'a>>(
11 src_ptr: PtrConst<'src>,
12 src_shape: &'static Shape,
13 dst: PtrUninit<'dst>,
14 ) -> Result<PtrMut<'dst>, TryFromError> {
15 if src_shape.id != T::SHAPE.id {
16 return Err(TryFromError::UnsupportedSourceShape {
17 src_shape,
18 expected: &[T::SHAPE],
19 });
20 }
21 let t = unsafe { src_ptr.read::<T>() };
22 let option = Some(t);
23 Ok(unsafe { dst.put(option) })
24 }
25
26 unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
27 src_ptr: PtrConst<'src>,
28 dst: PtrUninit<'dst>,
29 ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
30 let option = unsafe { src_ptr.read::<Option<T>>() };
31 match option {
32 Some(t) => Ok(unsafe { dst.put(t) }),
33 None => Err(TryIntoInnerError::Unavailable),
34 }
35 }
36
37 unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
38 src_ptr: PtrConst<'src>,
39 ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
40 let option = unsafe { src_ptr.get::<Option<T>>() };
41 match option {
42 Some(t) => Ok(PtrConst::new(t)),
43 None => Err(TryBorrowInnerError::Unavailable),
44 }
45 }
46
47 fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
49 T::SHAPE
50 }
51
52 Shape::builder_for_sized::<Self>()
53 .type_params(&[crate::TypeParam {
54 name: "T",
55 shape: || T::SHAPE,
56 }])
57 .def(Def::Option(
58 OptionDef::builder()
59 .t(|| T::SHAPE)
60 .vtable(
61 const {
62 &OptionVTable::builder()
63 .is_some(|option| unsafe { option.get::<Option<T>>().is_some() })
64 .get_value(|option| unsafe {
65 option
66 .get::<Option<T>>()
67 .as_ref()
68 .map(|t| PtrConst::new(t as *const T))
69 })
70 .init_some(|option, value| unsafe {
71 option.put(Option::Some(value.read::<T>()))
72 })
73 .init_none(|option| unsafe { option.put(<Option<T>>::None) })
74 .replace_with(|option, value| unsafe {
75 let option = option.as_mut::<Option<T>>();
76 match value {
77 Some(value) => option.replace(value.read::<T>()),
78 None => option.take(),
79 };
80 })
81 .build()
82 },
83 )
84 .build(),
85 ))
86 .vtable(
87 &const {
88 let mut vtable = value_vtable!(core::option::Option<T>, |f, opts| {
89 write!(f, "Option")?;
90 if let Some(opts) = opts.for_children() {
91 write!(f, "<")?;
92 (T::SHAPE.vtable.type_name)(f, opts)?;
93 write!(f, ">")?;
94 } else {
95 write!(f, "<…>")?;
96 }
97 Ok(())
98 });
99
100 if T::SHAPE.is_debug() {
101 vtable.debug = Some(|this, f| {
102 let this = unsafe { this.get::<Self>() };
103 if let Some(value) = &this {
104 write!(f, "Some(")?;
105 (<VTableView<T>>::of().debug().unwrap())(value, f)?;
106 write!(f, ")")?;
107 } else {
108 write!(f, "None")?;
109 }
110 Ok(())
111 });
112 }
113
114 if T::SHAPE.is_from_str() {
115 vtable.parse = Some(|str, target| {
116 let mut t = MaybeUninit::<T>::uninit();
117 let parse = <VTableView<T>>::of().parse().unwrap();
118 let _res = (parse)(str, TypedPtrUninit::new(t.as_mut_ptr()))?;
119 unsafe {
121 target.put(Some(t.assume_init()));
122 Ok(target.assume_init())
123 }
124 });
125 }
126
127 vtable.try_from = Some(try_from::<T>);
128 vtable.try_into_inner = Some(try_into_inner::<T>);
129 vtable.try_borrow_inner = Some(try_borrow_inner::<T>);
130
131 vtable
132 },
133 )
134 .inner(inner_shape::<T>)
135 .build()
136 };
137}