facet_reflect/partial/partial_api/
maps.rs1use super::*;
2
3impl<const BORROW: bool> Partial<'_, BORROW> {
7 pub fn begin_map(mut self) -> Result<Self, ReflectError> {
14 let frame = self.frames_mut().last_mut().unwrap();
15
16 match &frame.tracker {
18 Tracker::Scalar if !frame.is_init => {
19 }
21 Tracker::Scalar => {
22 match frame.shape.def {
24 Def::Map(_) => {
25 frame.tracker = Tracker::Map {
26 insert_state: MapInsertState::Idle,
27 };
28 return Ok(self);
29 }
30 Def::DynamicValue(_) => {
31 frame.tracker = Tracker::DynamicValue {
32 state: DynamicValueState::Object {
33 insert_state: DynamicObjectInsertState::Idle,
34 },
35 };
36 return Ok(self);
37 }
38 _ => {
39 return Err(ReflectError::OperationFailed {
40 shape: frame.shape,
41 operation: "begin_map can only be called on Map or DynamicValue types",
42 });
43 }
44 }
45 }
46 Tracker::Map { .. } => {
47 if frame.is_init {
48 return Ok(self);
50 }
51 }
52 Tracker::DynamicValue { state } => {
53 if matches!(state, DynamicValueState::Object { .. }) {
55 return Ok(self);
56 }
57 frame.deinit();
59 }
60 _ => {
61 return Err(ReflectError::UnexpectedTracker {
62 message: "begin_map called but tracker isn't Scalar, Map, or DynamicValue",
63 current_tracker: frame.tracker.kind(),
64 });
65 }
66 }
67
68 match &frame.shape.def {
70 Def::Map(map_def) => {
71 let init_fn = map_def.vtable.init_in_place_with_capacity;
72
73 unsafe {
75 init_fn(frame.data, 0);
76 }
77
78 frame.tracker = Tracker::Map {
80 insert_state: MapInsertState::Idle,
81 };
82 frame.is_init = true;
83 }
84 Def::DynamicValue(dyn_def) => {
85 unsafe {
87 (dyn_def.vtable.begin_object)(frame.data);
88 }
89
90 frame.tracker = Tracker::DynamicValue {
92 state: DynamicValueState::Object {
93 insert_state: DynamicObjectInsertState::Idle,
94 },
95 };
96 frame.is_init = true;
97 }
98 _ => {
99 return Err(ReflectError::OperationFailed {
100 shape: frame.shape,
101 operation: "begin_map can only be called on Map or DynamicValue types",
102 });
103 }
104 }
105
106 Ok(self)
107 }
108
109 pub fn begin_key(mut self) -> Result<Self, ReflectError> {
113 let frame = self.frames_mut().last_mut().unwrap();
114
115 let map_def = match (&frame.shape.def, &frame.tracker) {
117 (
118 Def::Map(map_def),
119 Tracker::Map {
120 insert_state: MapInsertState::Idle,
121 },
122 ) if frame.is_init => map_def,
123 (
124 Def::Map(_),
125 Tracker::Map {
126 insert_state: MapInsertState::PushingKey { .. },
127 },
128 ) => {
129 return Err(ReflectError::OperationFailed {
130 shape: frame.shape,
131 operation: "already pushing a key, call end() first",
132 });
133 }
134 (
135 Def::Map(_),
136 Tracker::Map {
137 insert_state: MapInsertState::PushingValue { .. },
138 },
139 ) => {
140 return Err(ReflectError::OperationFailed {
141 shape: frame.shape,
142 operation: "must complete current operation before begin_key()",
143 });
144 }
145 _ => {
146 return Err(ReflectError::OperationFailed {
147 shape: frame.shape,
148 operation: "must call begin_map() before begin_key()",
149 });
150 }
151 };
152
153 let key_shape = map_def.k();
155
156 let key_layout = match key_shape.layout.sized_layout() {
158 Ok(layout) => layout,
159 Err(_) => {
160 return Err(ReflectError::Unsized {
161 shape: key_shape,
162 operation: "begin_key allocating key",
163 });
164 }
165 };
166 let key_ptr_raw: *mut u8 = unsafe { ::alloc::alloc::alloc(key_layout) };
167
168 let Some(key_ptr_raw) = NonNull::new(key_ptr_raw) else {
169 return Err(ReflectError::OperationFailed {
170 shape: frame.shape,
171 operation: "failed to allocate memory for map key",
172 });
173 };
174
175 let key_ptr = PtrUninit::new(key_ptr_raw.as_ptr());
176
177 match &mut frame.tracker {
179 Tracker::Map { insert_state, .. } => {
180 *insert_state = MapInsertState::PushingKey {
181 key_ptr,
182 key_initialized: false,
183 };
184 }
185 _ => unreachable!(),
186 }
187
188 self.frames_mut().push(Frame::new(
190 PtrUninit::new(key_ptr_raw.as_ptr()),
191 key_shape,
192 FrameOwnership::ManagedElsewhere, ));
194
195 Ok(self)
196 }
197
198 pub fn begin_value(mut self) -> Result<Self, ReflectError> {
201 let frame = self.frames_mut().last_mut().unwrap();
202
203 let (map_def, key_ptr) = match (&frame.shape.def, &frame.tracker) {
205 (
206 Def::Map(map_def),
207 Tracker::Map {
208 insert_state:
209 MapInsertState::PushingValue {
210 value_ptr: None,
211 key_ptr,
212 ..
213 },
214 ..
215 },
216 ) => (map_def, *key_ptr),
217 (
218 Def::Map(_),
219 Tracker::Map {
220 insert_state:
221 MapInsertState::PushingValue {
222 value_ptr: Some(_), ..
223 },
224 ..
225 },
226 ) => {
227 return Err(ReflectError::OperationFailed {
228 shape: frame.shape,
229 operation: "already pushing a value, call end() first",
230 });
231 }
232 _ => {
233 return Err(ReflectError::OperationFailed {
234 shape: frame.shape,
235 operation: "must complete key before begin_value()",
236 });
237 }
238 };
239
240 let value_shape = map_def.v();
242
243 let value_layout = match value_shape.layout.sized_layout() {
245 Ok(layout) => layout,
246 Err(_) => {
247 return Err(ReflectError::Unsized {
248 shape: value_shape,
249 operation: "begin_value allocating value",
250 });
251 }
252 };
253 let value_ptr_raw: *mut u8 = unsafe { ::alloc::alloc::alloc(value_layout) };
254
255 let Some(value_ptr_raw) = NonNull::new(value_ptr_raw) else {
256 return Err(ReflectError::OperationFailed {
257 shape: frame.shape,
258 operation: "failed to allocate memory for map value",
259 });
260 };
261
262 let value_ptr = PtrUninit::new(value_ptr_raw.as_ptr());
263
264 match &mut frame.tracker {
266 Tracker::Map { insert_state, .. } => {
267 *insert_state = MapInsertState::PushingValue {
268 key_ptr,
269 value_ptr: Some(value_ptr),
270 value_initialized: false,
271 };
272 }
273 _ => unreachable!(),
274 }
275
276 self.frames_mut().push(Frame::new(
278 value_ptr,
279 value_shape,
280 FrameOwnership::ManagedElsewhere, ));
282
283 Ok(self)
284 }
285
286 pub fn begin_object_entry(mut self, key: &str) -> Result<Self, ReflectError> {
295 crate::trace!("begin_object_entry({key:?})");
296 let frame = self.frames_mut().last_mut().unwrap();
297
298 let dyn_def = match (&frame.shape.def, &frame.tracker) {
300 (
301 Def::DynamicValue(dyn_def),
302 Tracker::DynamicValue {
303 state:
304 DynamicValueState::Object {
305 insert_state: DynamicObjectInsertState::Idle,
306 },
307 },
308 ) if frame.is_init => {
309 dyn_def
311 }
312 (
313 Def::DynamicValue(_),
314 Tracker::DynamicValue {
315 state:
316 DynamicValueState::Object {
317 insert_state: DynamicObjectInsertState::BuildingValue { .. },
318 },
319 },
320 ) => {
321 return Err(ReflectError::OperationFailed {
322 shape: frame.shape,
323 operation: "already building a value, call end() first",
324 });
325 }
326 (Def::DynamicValue(_), _) => {
327 return Err(ReflectError::OperationFailed {
328 shape: frame.shape,
329 operation: "must call begin_map() before begin_object_entry()",
330 });
331 }
332 _ => {
333 return Err(ReflectError::OperationFailed {
334 shape: frame.shape,
335 operation: "begin_object_entry can only be called on DynamicValue types",
336 });
337 }
338 };
339
340 let value_shape = frame.shape;
342
343 if let Some(get_mut_fn) = dyn_def.vtable.object_get_mut {
346 let object_ptr = unsafe { frame.data.assume_init() };
347 if let Some(existing_ptr) = unsafe { get_mut_fn(object_ptr, key) } {
348 let mut new_frame = Frame::new(
352 existing_ptr.as_uninit(),
353 value_shape,
354 FrameOwnership::ManagedElsewhere,
355 );
356 new_frame.is_init = true;
357 new_frame.tracker = Tracker::Scalar;
360 self.frames_mut().push(new_frame);
361 return Ok(self);
362 }
363 }
364
365 let value_layout = match value_shape.layout.sized_layout() {
367 Ok(layout) => layout,
368 Err(_) => {
369 return Err(ReflectError::Unsized {
370 shape: value_shape,
371 operation: "begin_object_entry: calculating value layout",
372 });
373 }
374 };
375
376 let value_ptr: *mut u8 = unsafe { ::alloc::alloc::alloc(value_layout) };
377 let Some(value_ptr) = NonNull::new(value_ptr) else {
378 return Err(ReflectError::OperationFailed {
379 shape: frame.shape,
380 operation: "failed to allocate memory for object value",
381 });
382 };
383
384 match &mut frame.tracker {
386 Tracker::DynamicValue {
387 state: DynamicValueState::Object { insert_state },
388 } => {
389 *insert_state = DynamicObjectInsertState::BuildingValue {
390 key: String::from(key),
391 };
392 }
393 _ => unreachable!(),
394 }
395
396 self.frames_mut().push(Frame::new(
398 PtrUninit::new(value_ptr.as_ptr()),
399 value_shape,
400 FrameOwnership::Owned,
401 ));
402
403 Ok(self)
404 }
405}