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(self.err(ReflectErrorKind::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(self.err(ReflectErrorKind::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 shape = self.frames().last().unwrap().allocated.shape();
43 let parent_type_plan = self.frames().last().unwrap().type_plan;
44
45 if pointee_shape.layout.sized_layout().is_ok() {
46 self.mode.stack_mut().last_mut().unwrap().tracker = Tracker::SmartPointer {
50 building_inner: true,
51 pending_inner: None,
52 };
53
54 let inner_layout = match pointee_shape.layout.sized_layout() {
55 Ok(layout) => layout,
56 Err(_) => {
57 return Err(self.err(ReflectErrorKind::Unsized {
58 shape: pointee_shape,
59 operation: "begin_smart_ptr, calculating inner value layout",
60 }));
61 }
62 };
63 let inner_ptr = facet_core::alloc_for_layout(inner_layout);
64
65 let child_plan_id = self
68 .root_plan
69 .pointer_inner_node_id(parent_type_plan)
70 .expect("TypePlan should have pointee node for sized pointer");
71 self.mode.stack_mut().push(Frame::new(
72 inner_ptr,
73 AllocatedShape::new(pointee_shape, inner_layout.size()),
74 FrameOwnership::Owned,
75 child_plan_id,
76 ));
77 } else {
78 if pointee_shape == str::SHAPE {
80 crate::trace!("Pointee is str");
81
82 self.mode.stack_mut().last_mut().unwrap().tracker = Tracker::SmartPointer {
85 building_inner: true,
86 pending_inner: None,
87 };
88
89 let string_layout = String::SHAPE
91 .layout
92 .sized_layout()
93 .expect("String must have a sized layout");
94 let string_ptr = facet_core::alloc_for_layout(string_layout);
95 let string_size = string_layout.size();
96 let child_plan_id = self
98 .root_plan
99 .pointer_inner_node_id(parent_type_plan)
100 .expect("TypePlan should have pointee node for str->String conversion");
101 let new_frame = Frame::new(
102 string_ptr,
103 AllocatedShape::new(String::SHAPE, string_size),
104 FrameOwnership::Owned,
105 child_plan_id,
106 );
107 self.mode.stack_mut().push(new_frame);
109 } else if let Type::Sequence(SequenceType::Slice(_st)) = pointee_shape.ty {
110 crate::trace!("Pointee is [{}]", _st.t);
111
112 let slice_builder_vtable = match smart_ptr_def.vtable.slice_builder_vtable {
114 Some(vtable) => vtable,
115 None => {
116 return Err(self.err(ReflectErrorKind::OperationFailed {
117 shape,
118 operation: "smart pointer does not support slice building",
119 }));
120 }
121 };
122
123 let builder_ptr = (slice_builder_vtable.new_fn)();
125
126 let frame = self.mode.stack_mut().last_mut().unwrap();
128 if let FrameOwnership::Owned = frame.ownership
129 && let Ok(layout) = shape.layout.sized_layout()
130 && layout.size() > 0
131 {
132 unsafe { ::alloc::alloc::dealloc(frame.data.as_mut_byte_ptr(), layout) };
133 }
134
135 frame.data = builder_ptr.as_uninit();
137 frame.tracker = Tracker::SmartPointerSlice {
138 vtable: slice_builder_vtable,
139 building_item: false,
140 current_child: None,
141 };
142 } else {
145 return Err(self.err(ReflectErrorKind::OperationFailed {
146 shape,
147 operation: "push_smart_ptr can only be called on pointers to supported pointee types",
148 }));
149 }
150 }
151
152 Ok(self)
153 }
154}