facet_reflect/partial/partial_api/
ptr.rs1use super::*;
2
3impl<const BORROW: bool> Partial<'_, BORROW> {
7 pub fn begin_smart_ptr(mut self) -> Result<Self, ReflectError> {
9 crate::trace!("begin_smart_ptr()");
10
11 let (smart_ptr_def, pointee_shape) = {
13 let frame = self.frames().last().unwrap();
14
15 match &frame.shape.def {
16 Def::Pointer(smart_ptr_def) if smart_ptr_def.constructible_from_pointee() => {
17 let pointee_shape = match smart_ptr_def.pointee() {
18 Some(shape) => shape,
19 None => {
20 return Err(ReflectError::OperationFailed {
21 shape: frame.shape,
22 operation: "Smart pointer must have a pointee shape",
23 });
24 }
25 };
26 (*smart_ptr_def, pointee_shape)
27 }
28 _ => {
29 return Err(ReflectError::OperationFailed {
30 shape: frame.shape,
31 operation: "push_smart_ptr can only be called on compatible types",
32 });
33 }
34 }
35 };
36
37 self.prepare_for_reinitialization();
39
40 let frame = self.frames_mut().last_mut().unwrap();
41
42 if pointee_shape.layout.sized_layout().is_ok() {
43 frame.tracker = Tracker::SmartPointer;
47
48 let inner_layout = match pointee_shape.layout.sized_layout() {
49 Ok(layout) => layout,
50 Err(_) => {
51 return Err(ReflectError::Unsized {
52 shape: pointee_shape,
53 operation: "begin_smart_ptr, calculating inner value layout",
54 });
55 }
56 };
57 let inner_ptr: *mut u8 = unsafe { ::alloc::alloc::alloc(inner_layout) };
58 let Some(inner_ptr) = NonNull::new(inner_ptr) else {
59 return Err(ReflectError::OperationFailed {
60 shape: frame.shape,
61 operation: "failed to allocate memory for smart pointer inner value",
62 });
63 };
64
65 self.frames_mut().push(Frame::new(
67 PtrUninit::new(inner_ptr.as_ptr()),
68 pointee_shape,
69 FrameOwnership::Owned,
70 ));
71 } else {
72 if pointee_shape == str::SHAPE {
74 crate::trace!("Pointee is str");
75
76 let string_layout = String::SHAPE
78 .layout
79 .sized_layout()
80 .expect("String must have a sized layout");
81 let string_ptr: *mut u8 = unsafe { ::alloc::alloc::alloc(string_layout) };
82 let Some(string_ptr) = NonNull::new(string_ptr) else {
83 return Err(ReflectError::OperationFailed {
84 shape: frame.shape,
85 operation: "failed to allocate memory for string",
86 });
87 };
88 let frame = Frame::new(
89 PtrUninit::new(string_ptr.as_ptr()),
90 String::SHAPE,
91 FrameOwnership::Owned,
92 );
93 self.frames_mut().push(frame);
95 } else if let Type::Sequence(SequenceType::Slice(_st)) = pointee_shape.ty {
96 crate::trace!("Pointee is [{}]", _st.t);
97
98 let slice_builder_vtable = smart_ptr_def.vtable.slice_builder_vtable.ok_or(
100 ReflectError::OperationFailed {
101 shape: frame.shape,
102 operation: "smart pointer does not support slice building",
103 },
104 )?;
105
106 let builder_ptr = (slice_builder_vtable.new_fn)();
108
109 if let FrameOwnership::Owned = frame.ownership
111 && let Ok(layout) = frame.shape.layout.sized_layout()
112 && layout.size() > 0
113 {
114 unsafe { ::alloc::alloc::dealloc(frame.data.as_mut_byte_ptr(), layout) };
115 }
116
117 frame.data = builder_ptr.as_uninit();
119 frame.tracker = Tracker::SmartPointerSlice {
120 vtable: slice_builder_vtable,
121 building_item: false,
122 };
123 } else {
126 return Err(ReflectError::OperationFailed {
127 shape: frame.shape,
128 operation: "push_smart_ptr can only be called on pointers to supported pointee types",
129 });
130 }
131 }
132
133 Ok(self)
134 }
135}