facet_core/impls_core/
option.rs1use core::{alloc::Layout, mem::MaybeUninit};
2
3use crate::{
4 ConstTypeId, Def, Facet, OptionDef, OptionVTable, PtrConst, PtrUninit, Shape,
5 value_vtable_inner,
6};
7
8unsafe impl<'a, T: Facet<'a>> Facet<'a> for Option<T> {
9 const SHAPE: &'static Shape = &const {
10 Shape::builder()
11 .id(ConstTypeId::of::<Self>())
12 .layout(Layout::new::<Self>())
13 .type_params(&[crate::TypeParam {
14 name: "T",
15 shape: || T::SHAPE,
16 }])
17 .def(Def::Option(
18 OptionDef::builder()
19 .t(|| T::SHAPE)
20 .vtable(
21 const {
22 &OptionVTable::builder()
23 .is_some(|option| unsafe { option.get::<Option<T>>().is_some() })
24 .get_value(|option| unsafe {
25 option
26 .get::<Option<T>>()
27 .as_ref()
28 .map(|t| PtrConst::new(t as *const T))
29 })
30 .init_some(|option, value| unsafe {
31 option.put(Option::Some(value.read::<T>()))
32 })
33 .init_none(|option| unsafe { option.put(<Option<T>>::None) })
34 .replace_with(|option, value| unsafe {
35 let option = option.as_mut::<Option<T>>();
36 match value {
37 Some(value) => option.replace(value.read::<T>()),
38 None => option.take(),
39 };
40 })
41 .build()
42 },
43 )
44 .build(),
45 ))
46 .vtable(
47 &const {
48 let mut vtable = value_vtable_inner!(core::option::Option<T>, |f, opts| {
49 write!(f, "Option")?;
50 if let Some(opts) = opts.for_children() {
51 write!(f, "<")?;
52 (T::SHAPE.vtable.type_name)(f, opts)?;
53 write!(f, ">")?;
54 } else {
55 write!(f, "<…>")?;
56 }
57 Ok(())
58 });
59
60 if T::SHAPE.is_debug() {
61 vtable.debug = Some(|this, f| {
62 let this = unsafe { this.get::<Self>() };
63 if let Some(value) = &this {
64 write!(f, "Some(")?;
65 unsafe {
66 (T::SHAPE.vtable.debug.unwrap_unchecked())(
67 PtrConst::new(value),
68 f,
69 )?;
70 }
71 write!(f, ")")?;
72 } else {
73 write!(f, "None")?;
74 }
75 Ok(())
76 });
77 }
78
79 if T::SHAPE.is_from_str() {
80 vtable.parse = Some(|str, target| {
81 let mut t = MaybeUninit::<T>::uninit();
82 let parse = unsafe { T::SHAPE.vtable.parse.unwrap_unchecked() };
83 let _res = unsafe { (parse)(str, PtrUninit::new(t.as_mut_ptr()))? };
84 unsafe {
86 target.put(Some(t.assume_init()));
87 Ok(target.assume_init())
88 }
89 });
90 }
91
92 vtable
93 },
94 )
95 .build()
96 };
97}