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