1use crate::{ReflectError, ValueId};
2use crate::{debug, trace};
3#[cfg(feature = "log")]
4use alloc::string::ToString;
5#[cfg(feature = "log")]
6use owo_colors::OwoColorize;
7
8mod drop;
9mod pop;
10
11mod frame;
12pub(crate) use frame::*;
13
14use alloc::format;
15use bitflags::bitflags;
16use core::marker::PhantomData;
17use facet_core::{
18 Def, DefaultInPlaceFn, Facet, FieldError, PtrConst, PtrUninit, ScalarAffinity, SequenceType,
19 Shape, Type, UserType, Variant,
20};
21use flat_map::FlatMap;
22
23use alloc::string::String;
24
25mod iset;
26pub use iset::*;
27
28mod put_f64;
29mod put_shape;
30
31mod enum_;
32mod flat_map;
33
34mod heap_value;
35pub use heap_value::*;
36
37pub(crate) struct IState<'shape> {
39 variant: Option<Variant<'shape>>,
41
42 fields: ISet,
44
45 depth: usize,
47
48 mode: FrameMode,
50
51 flags: FrameFlags,
53
54 list_index: Option<usize>,
56
57 #[allow(dead_code)]
59 map_key: Option<String>,
60}
61
62bitflags! {
63 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65 pub struct FrameFlags: u64 {
66 const EMPTY = 0;
68
69 const ALLOCATED = 1 << 0;
71
72 const MOVED = 1 << 1;
76 }
77
78 }
80
81impl<'shape> IState<'shape> {
82 pub fn new(depth: usize, mode: FrameMode, flags: FrameFlags) -> Self {
84 Self {
85 variant: None,
86 fields: Default::default(),
87 depth,
88 mode,
89 flags,
90 list_index: None,
91 map_key: None,
92 }
93 }
94
95 #[allow(dead_code)]
97 pub fn with_list_index(mut self, index: usize) -> Self {
98 self.list_index = Some(index);
99 self
100 }
101
102 #[allow(dead_code)]
104 pub fn with_map_key(mut self, key: String) -> Self {
105 self.map_key = Some(key);
106 self
107 }
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub enum FrameMode {
113 Root,
115 Field,
117 ListElement,
119 MapKey,
121 MapValue {
123 index: usize,
125 },
126 OptionSome,
128 OptionNone,
131 SmartPointee,
133 Inner,
135}
136
137pub struct Wip<'facet, 'shape> {
144 frames: alloc::vec::Vec<Frame<'shape>>,
146
147 istates: FlatMap<ValueId<'shape>, IState<'shape>>,
149
150 invariant: PhantomData<fn(&'facet ()) -> &'facet ()>,
151}
152
153impl<'facet, 'shape> Wip<'facet, 'shape> {
154 pub fn put_peek(
156 self,
157 peek: crate::Peek<'_, 'facet, 'shape>,
158 ) -> Result<Wip<'facet, 'shape>, ReflectError<'shape>> {
159 self.put_shape(peek.data, peek.shape)
160 }
161
162 pub fn frames_count(&self) -> usize {
164 self.frames.len()
165 }
166
167 pub fn alloc_shape(shape: &'shape Shape<'shape>) -> Result<Self, ReflectError<'shape>> {
169 let data = shape
170 .allocate()
171 .map_err(|_| ReflectError::Unsized { shape })?;
172 Ok(Self {
173 frames: alloc::vec![Frame {
174 data,
175 shape,
176 field_index_in_parent: None,
177 istate: IState::new(0, FrameMode::Root, FrameFlags::ALLOCATED),
178 }],
179 istates: Default::default(),
180 invariant: PhantomData,
181 })
182 }
183
184 pub fn alloc<S: Facet<'facet>>() -> Result<Self, ReflectError<'shape>> {
186 Self::alloc_shape(S::SHAPE)
187 }
188
189 fn track(&mut self, frame: Frame<'shape>) {
190 if frame.istate.flags.contains(FrameFlags::MOVED) {
196 return;
198 }
199
200 self.istates.insert(frame.id(), frame.istate);
201 }
202
203 unsafe fn mark_moved_out_of(&mut self, frame: &mut Frame<'shape>) {
204 unsafe fn mark_subtree_moved<'facet, 'shape>(
207 wip: &mut Wip<'facet, 'shape>,
208 id: ValueId<'shape>,
209 ) {
210 unsafe {
212 if let Some(mut istate) = wip.istates.remove(&id) {
214 istate.flags.insert(FrameFlags::MOVED);
216
217 match id.shape.ty {
219 Type::User(UserType::Struct(sd)) => {
220 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
221 for field in sd.fields.iter() {
222 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
223 let field_id =
224 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
225 mark_subtree_moved(wip, field_id);
227 }
228 }
229 Type::User(UserType::Enum(_)) => {
230 if let Some(variant) = &istate.variant {
232 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
233 for field in variant.data.fields.iter() {
234 let field_ptr_uninit =
235 container_ptr.field_uninit_at(field.offset);
236 let field_id =
237 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
238 mark_subtree_moved(wip, field_id);
240 }
241 }
242 }
243 _ => {}
247 }
248
249 if istate.flags.contains(FrameFlags::ALLOCATED) {
252 let mut temp_frame = Frame::recompose(id, istate);
254 temp_frame.dealloc_if_needed();
255 }
256 }
257 }
259 }
260
261 unsafe {
264 let frame_id = frame.id();
266
267 let variant_opt = frame.istate.variant;
269
270 frame.istate.flags.insert(FrameFlags::MOVED);
272 ISet::clear(&mut frame.istate.fields);
273
274 match frame.shape.ty {
277 Type::User(UserType::Struct(sd)) => {
278 let container_ptr = PtrUninit::new(frame_id.ptr as *mut u8);
279 for field in sd.fields.iter() {
280 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
281 let field_id = ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
282 mark_subtree_moved(self, field_id);
283 }
284 }
285 Type::User(UserType::Enum(_)) => {
286 if let Some(variant) = &variant_opt {
288 let container_ptr = PtrUninit::new(frame_id.ptr as *mut u8);
289 for field in variant.data.fields.iter() {
290 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
291 let field_id =
292 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
293 mark_subtree_moved(self, field_id);
294 }
295 }
296 }
297 _ => {}
299 }
300
301 frame.istate.variant = None;
303
304 self.istates.remove(&frame_id);
306
307 if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
309 frame.dealloc_if_needed();
310 }
311 }
312 }
313
314 pub fn shape(&self) -> &'shape Shape<'shape> {
316 self.frames.last().expect("must have frames left").shape
317 }
318
319 pub fn innermost_shape(&self) -> &'shape Shape<'shape> {
323 let mut current_shape = self.shape();
324
325 while let Some(inner_fn) = current_shape.inner {
327 current_shape = inner_fn();
328 }
329
330 current_shape
331 }
332
333 pub fn in_option(&self) -> bool {
335 let Some(frame) = self.frames.last() else {
336 return false;
337 };
338 matches!(frame.istate.mode, FrameMode::OptionSome)
339 }
340
341 pub fn mode(&self) -> FrameMode {
343 self.frames.last().unwrap().istate.mode
344 }
345
346 pub fn build(mut self) -> Result<HeapValue<'facet, 'shape>, ReflectError<'shape>> {
348 debug!("[{}] ⚒️ It's BUILD time", self.frames.len());
349
350 if self.frames.is_empty() {
352 panic!("No frames in WIP during build: stack is empty (you popped too much)");
353 }
354 if self.frames.len() != 1 {
355 panic!(
356 "You must pop frames so that only the root frame remains before calling build (frames left: {})",
357 self.frames.len()
358 );
359 }
360
361 let root_frame = &self.frames[0];
363
364 enum FrameRef<'shape> {
365 Root,
366 ById(ValueId<'shape>),
367 }
368 let mut to_check = alloc::vec![FrameRef::Root];
369
370 while let Some(fr) = to_check.pop() {
372 let (id, istate) = match fr {
373 FrameRef::Root => (root_frame.id(), &root_frame.istate),
374 FrameRef::ById(id) => {
375 let istate = self.istates.get(&id).unwrap();
377 (id, istate)
378 }
379 };
380
381 trace!(
382 "Checking shape {} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
383 id.shape.blue(),
384 id.ptr,
385 istate.flags.bright_magenta(),
386 istate.mode.yellow(),
387 if is_fully_initialized(id.shape, istate) {
388 "✅"
389 } else {
390 "❌"
391 }
392 );
393
394 if istate.flags.contains(FrameFlags::MOVED) {
396 trace!(
397 "{}",
398 "Frame was moved out of, skipping initialization check".yellow()
399 );
400 continue;
401 }
402
403 if let Def::Array(array_def) = id.shape.def {
407 let pushed_count = istate.list_index.unwrap_or(0);
409
410 if pushed_count != array_def.n {
412 return Err(ReflectError::ArrayNotFullyInitialized {
413 shape: id.shape,
414 pushed_count,
415 expected_size: array_def.n,
416 });
417 }
418 }
419 else if !matches!(id.shape.def, Def::Undefined) {
423 if !istate.fields.are_all_set(1) {
424 match istate.mode {
426 FrameMode::OptionNone => {
427 debug!("Found uninitialized value (option none) — {}", id.shape);
429 return Err(ReflectError::UninitializedValue { shape: id.shape });
430 }
431 _ => {
433 debug!(
434 "Found uninitialized value (list/map/option/etc. — {})",
435 id.shape
436 );
437 return Err(ReflectError::UninitializedValue { shape: id.shape });
438 }
439 }
440 }
441 } else {
449 match id.shape.ty {
450 Type::User(UserType::Struct(sd)) => {
451 for i in 0..sd.fields.len() {
453 if !istate.fields.has(i) {
454 let field = &sd.fields[i];
455 trace!("Found uninitialized field: {}", field.name);
456 return Err(ReflectError::UninitializedField {
457 shape: id.shape,
458 field_name: field.name,
459 });
460 }
461 }
462
463 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
464
465 #[allow(clippy::unused_enumerate_index)]
467 for (_i, field) in sd.fields.iter().enumerate() {
468 let field_shape = field.shape();
469 let field_ptr = unsafe { container_ptr.field_init_at(field.offset) };
470 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
471
472 if self.istates.contains_key(&field_id) {
473 debug!(
474 "Queueing struct field check: #{} '{}' of {}: shape={}, ptr={:p}",
475 _i.to_string().bright_cyan(),
476 field.name.bright_blue(),
477 id.shape.blue(),
478 field_shape.green(),
479 field_ptr.as_byte_ptr()
480 );
481 to_check.push(FrameRef::ById(field_id));
482 }
483 }
484 }
485 Type::User(UserType::Enum(_ed)) => {
486 if let Some(variant) = &istate.variant {
487 for (i, field) in variant.data.fields.iter().enumerate() {
489 if !istate.fields.has(i) {
490 trace!("Found uninitialized field: {}", field.name);
491 return Err(ReflectError::UninitializedEnumField {
492 shape: id.shape,
493 variant_name: variant.name,
494 field_name: field.name,
495 });
496 }
497 }
498
499 #[allow(clippy::unused_enumerate_index)]
501 for (_i, field) in variant.data.fields.iter().enumerate() {
502 let field_shape = field.shape();
503 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
504 let field_ptr =
506 unsafe { container_ptr.field_init_at(field.offset) };
507 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
508
509 if self.istates.contains_key(&field_id) {
510 debug!(
511 "Queueing enum field check: #{} '{}' of variant '{}' of {}: shape={}, ptr={:p}",
512 _i.to_string().bright_cyan(),
513 field.name.bright_blue(),
514 variant.name.yellow(),
515 id.shape.blue(),
516 field_shape.green(),
517 field_ptr.as_byte_ptr()
518 );
519 to_check.push(FrameRef::ById(field_id));
520 }
521 }
522 } else {
523 debug!("Found no variant selected for enum");
525 return Err(ReflectError::NoVariantSelected { shape: id.shape });
526 }
527 }
528 _ => {
530 if !istate.fields.are_all_set(1) {
532 debug!("Found uninitialized value (other)");
533 return Err(ReflectError::UninitializedValue { shape: id.shape });
534 }
535 }
536 }
537 }
538 }
539
540 debug!("All reachable frames checked and initialized.");
542
543 let root_shape = root_frame.shape;
546 let root_data = unsafe { root_frame.data.assume_init() };
547 if let Some(invariant_fn) = (root_shape.vtable.invariants)() {
548 debug!(
549 "Checking invariants for root shape {} at {:p}",
550 root_shape.green(),
551 root_data.as_byte_ptr()
552 );
553 if !unsafe { invariant_fn(PtrConst::new(root_data.as_byte_ptr())) } {
554 return Err(ReflectError::InvariantViolation {
555 invariant: "Custom validation function returned false",
556 });
557 }
558 } else {
559 debug!(
560 "No invariants to check for root shape {}",
561 root_shape.blue()
562 );
563 }
564
565 {
567 FlatMap::clear(&mut self.istates);
568 self.frames.clear();
569 }
570
571 let guard = Guard {
573 ptr: root_data.as_mut_byte_ptr(),
574 layout: match root_shape.layout {
575 facet_core::ShapeLayout::Sized(layout) => layout,
576 facet_core::ShapeLayout::Unsized => panic!("Unsized layout not supported"),
577 },
578 };
579
580 Ok(HeapValue {
581 guard: Some(guard),
582 shape: root_shape,
583 phantom: PhantomData,
584 })
585 }
586
587 pub fn field(mut self, index: usize) -> Result<Self, ReflectError<'shape>> {
599 let frame = self.frames.last_mut().unwrap();
600 let shape = frame.shape;
601
602 let (field, field_offset) = match shape.ty {
603 Type::User(UserType::Struct(def)) => {
604 if index >= def.fields.len() {
605 return Err(ReflectError::FieldError {
606 shape,
607 field_error: FieldError::NoSuchField,
608 });
609 }
610 let field = &def.fields[index];
611 (field, field.offset)
612 }
613 Type::User(UserType::Enum(_)) => {
614 let Some(variant) = frame.istate.variant.as_ref() else {
615 return Err(ReflectError::OperationFailed {
616 shape,
617 operation: "tried to access a field but no variant was selected",
618 });
619 };
620
621 if index >= variant.data.fields.len() {
622 return Err(ReflectError::FieldError {
623 shape,
624 field_error: FieldError::NoSuchField,
625 });
626 }
627
628 let field = &variant.data.fields[index];
629 (field, field.offset)
630 }
631 _ => {
632 return Err(ReflectError::WasNotA {
633 expected: "struct or enum",
634 actual: shape,
635 });
636 }
637 };
638
639 let field_data = unsafe { frame.data.field_uninit_at(field_offset) };
640
641 let mut frame = Frame {
642 data: field_data,
643 shape: field.shape(),
644 field_index_in_parent: Some(index),
645 istate: IState::new(self.frames.len(), FrameMode::Field, FrameFlags::EMPTY),
647 };
648
649 debug!(
650 "[{}] Selecting field {}::{}: {} (#{})",
651 self.frames.len(),
652 shape.blue(),
653 field.name.yellow(),
654 field.shape().green(),
655 index.yellow(),
656 );
657 if let Some(iset) = self.istates.remove(&frame.id()) {
658 trace!(
659 "[{}] Restoring saved state for {}::{}: {} (#{}) (istate.mode = {:?}, istate.fields = {:?}, istate.flags = {:?}, istate.depth = {:?})",
660 self.frames.len(),
661 shape.blue(),
662 field.name.yellow(),
663 field.shape().green(),
664 index.yellow(),
665 iset.mode,
666 iset.fields,
667 iset.flags,
668 iset.depth
669 );
670 frame.istate = iset;
671 }
672 self.frames.push(frame);
673
674 Ok(self)
675 }
676
677 pub fn field_index(&self, name: &str) -> Option<usize> {
689 fn find_field_index(fields: &[facet_core::Field], name: &str) -> Option<usize> {
690 fields.iter().position(|f| f.name == name)
691 }
692
693 let frame = self.frames.last()?;
694 match frame.shape.ty {
695 Type::User(UserType::Struct(def)) => find_field_index(def.fields, name),
696 Type::User(UserType::Enum(_)) => {
697 let variant = frame.istate.variant.as_ref()?;
698 find_field_index(variant.data.fields, name)
699 }
700 _ => None,
701 }
702 }
703
704 pub fn field_named(self, name: &str) -> Result<Self, ReflectError<'shape>> {
716 let frame = self.frames.last().unwrap();
717 let shape = frame.shape;
718
719 if let Type::User(UserType::Enum(_)) = shape.ty {
721 if frame.istate.variant.is_none() {
722 return Err(ReflectError::OperationFailed {
723 shape,
724 operation: "tried to access a field by name but no variant was selected",
725 });
726 }
727 }
728
729 if let Def::SmartPointer(_) = shape.def {
731 return Err(ReflectError::MissingPushPointee { shape });
733 }
734
735 let index = self.field_index(name).ok_or(ReflectError::FieldError {
736 shape,
737 field_error: FieldError::NoSuchField,
738 })?;
739
740 self.field(index)
741 }
742
743 pub fn put<T: Facet<'facet>>(self, t: T) -> Result<Wip<'facet, 'shape>, ReflectError<'shape>> {
754 let shape = T::SHAPE;
755 let ptr_const = PtrConst::new(&t as *const T as *const u8);
756 let res = self.put_shape(ptr_const, shape);
757 core::mem::forget(t); res
759 }
760
761 pub fn try_put<T: Facet<'facet>>(
772 self,
773 t: T,
774 ) -> Result<Wip<'facet, 'shape>, ReflectError<'shape>> {
775 let shape = T::SHAPE;
776 let ptr_const = PtrConst::new(&t as *const T as *const u8);
777 let res = self.put_shape(ptr_const, shape);
778 core::mem::forget(t); res
780 }
781
782 pub fn parse<'ínput>(mut self, s: &'ínput str) -> Result<Self, ReflectError<'shape>> {
784 let Some(frame) = self.frames.last_mut() else {
785 return Err(ReflectError::OperationFailed {
786 shape: <()>::SHAPE,
787 operation: "tried to parse value but there was no frame",
788 });
789 };
790
791 let shape = frame.shape;
792 let index = frame.field_index_in_parent;
793
794 let Some(parse_fn) = (frame.shape.vtable.parse)() else {
795 return Err(ReflectError::OperationFailed {
796 shape: frame.shape,
797 operation: "type does not implement Parse",
798 });
799 };
800 match unsafe { (parse_fn)(s, frame.data) } {
801 Ok(_res) => {
802 unsafe {
803 frame.mark_fully_initialized();
804 }
805
806 self.mark_field_as_initialized(shape, index)?;
808
809 Ok(self)
810 }
811 Err(_) => Err(ReflectError::OperationFailed {
812 shape,
813 operation: "parsing",
814 }),
815 }
816 }
817
818 pub fn put_from_fn(
820 mut self,
821 default_in_place: DefaultInPlaceFn,
822 ) -> Result<Self, ReflectError<'shape>> {
823 let Some(frame) = self.frames.last_mut() else {
824 return Err(ReflectError::OperationFailed {
825 shape: <()>::SHAPE,
826 operation: "tried to put value from fn but there was no frame",
827 });
828 };
829
830 if let Def::Array(array_def) = frame.shape.def {
833 trace!(
834 "[{}] Setting array as default-initialized with {} elements",
835 frame.istate.depth, array_def.n
836 );
837 frame.istate.list_index = Some(array_def.n);
839 }
840
841 unsafe {
842 default_in_place(frame.data);
843 frame.mark_fully_initialized();
844 }
845
846 let shape = frame.shape;
847 let index = frame.field_index_in_parent;
848
849 self.mark_field_as_initialized(shape, index)?;
851
852 Ok(self)
853 }
854
855 pub fn put_default(self) -> Result<Self, ReflectError<'shape>> {
857 let Some(frame) = self.frames.last() else {
858 return Err(ReflectError::OperationFailed {
859 shape: <()>::SHAPE,
860 operation: "tried to put default value but there was no frame",
861 });
862 };
863
864 let vtable = frame.shape.vtable;
865 let Some(default_in_place) = (vtable.default_in_place)() else {
866 return Err(ReflectError::OperationFailed {
867 shape: frame.shape,
868 operation: "type does not implement Default",
869 });
870 };
871
872 self.put_from_fn(default_in_place)
873 }
874
875 fn mark_field_as_initialized(
877 &mut self,
878 shape: &'shape Shape<'shape>,
879 index: Option<usize>,
880 ) -> Result<(), ReflectError<'shape>> {
881 if let Some(index) = index {
882 let parent_index = self.frames.len().saturating_sub(2);
883 #[cfg(feature = "log")]
884 let num_frames = self.frames.len();
885 let Some(parent) = self.frames.get_mut(parent_index) else {
886 return Err(ReflectError::OperationFailed {
887 shape,
888 operation: "was supposed to mark a field as initialized, but there was no parent frame",
889 });
890 };
891 #[cfg(feature = "log")]
892 let parent_shape = parent.shape;
893 trace!(
894 "[{}] {}.{} initialized with {}",
895 num_frames,
896 parent_shape.blue(),
897 index.yellow(),
898 shape.green()
899 );
900
901 if matches!(parent.shape.ty, Type::User(UserType::Enum(_)))
902 && parent.istate.variant.is_none()
903 {
904 return Err(ReflectError::OperationFailed {
905 shape,
906 operation: "was supposed to mark a field as initialized, but the parent frame was an enum and didn't have a variant chosen",
907 });
908 }
909
910 if parent.istate.fields.has(index) {
911 return Err(ReflectError::OperationFailed {
912 shape,
913 operation: "was supposed to mark a field as initialized, but the parent frame already had it marked as initialized",
914 });
915 }
916
917 parent.istate.fields.set(index);
918 }
919 Ok(())
920 }
921
922 pub fn element_shape(&self) -> Result<&'shape Shape<'shape>, ReflectError<'shape>> {
924 let frame = self.frames.last().unwrap();
925 let shape = frame.shape;
926
927 match shape.def {
928 Def::List(list_def) => Ok(list_def.t()),
929 _ => Err(ReflectError::WasNotA {
930 expected: "list or array",
931 actual: shape,
932 }),
933 }
934 }
935
936 pub fn key_shape(&self) -> Result<&'shape Shape<'shape>, ReflectError<'shape>> {
938 let frame = self.frames.last().unwrap();
939 let shape = frame.shape;
940
941 match shape.def {
942 Def::Map(map_def) => Ok(map_def.k()),
943 _ => Err(ReflectError::WasNotA {
944 expected: "map",
945 actual: shape,
946 }),
947 }
948 }
949
950 pub fn put_empty_list(mut self) -> Result<Self, ReflectError<'shape>> {
952 let Some(frame) = self.frames.last_mut() else {
953 return Err(ReflectError::OperationFailed {
954 shape: <()>::SHAPE,
955 operation: "tried to create empty list but there was no frame",
956 });
957 };
958
959 if !matches!(frame.shape.def, Def::List(_)) {
960 return Err(ReflectError::WasNotA {
961 expected: "list or array",
962 actual: frame.shape,
963 });
964 }
965
966 let vtable = frame.shape.vtable;
967
968 let Some(default_in_place) = (vtable.default_in_place)() else {
970 return Err(ReflectError::OperationFailed {
971 shape: frame.shape,
972 operation: "list type does not implement Default",
973 });
974 };
975
976 unsafe {
977 default_in_place(frame.data);
978 frame.mark_fully_initialized();
979 }
980
981 let shape = frame.shape;
982 let index = frame.field_index_in_parent;
983
984 self.mark_field_as_initialized(shape, index)?;
986
987 Ok(self)
988 }
989
990 pub fn put_empty_map(mut self) -> Result<Self, ReflectError<'shape>> {
992 let Some(frame) = self.frames.last_mut() else {
993 return Err(ReflectError::OperationFailed {
994 shape: <()>::SHAPE,
995 operation: "tried to create empty map but there was no frame",
996 });
997 };
998
999 if !matches!(frame.shape.def, Def::Map(_)) {
1000 return Err(ReflectError::WasNotA {
1001 expected: "map or hash map",
1002 actual: frame.shape,
1003 });
1004 }
1005
1006 let vtable = frame.shape.vtable;
1007
1008 let Some(default_in_place) = (vtable.default_in_place)() else {
1010 return Err(ReflectError::OperationFailed {
1011 shape: frame.shape,
1012 operation: "map type does not implement Default",
1013 });
1014 };
1015
1016 unsafe {
1017 default_in_place(frame.data);
1018 frame.mark_fully_initialized();
1019 }
1020
1021 if let Some(index) = frame.field_index_in_parent {
1023 let parent_index = self.frames.len().saturating_sub(2);
1024 if let Some(parent) = self.frames.get_mut(parent_index) {
1025 parent.istate.fields.set(index);
1026 }
1027 }
1028
1029 Ok(self)
1030 }
1031
1032 pub fn begin_pushback(mut self) -> Result<Self, ReflectError<'shape>> {
1037 let Some(frame) = self.frames.last_mut() else {
1038 return Err(ReflectError::OperationFailed {
1039 shape: <()>::SHAPE,
1040 operation: "tried to begin pushback but there was no frame",
1041 });
1042 };
1043
1044 let is_list = matches!(frame.shape.def, Def::List(_));
1045 let is_array = matches!(frame.shape.def, Def::Array(_));
1046 let is_tuple_struct_or_variant = match (frame.shape.ty, frame.shape.def) {
1047 (_, Def::Scalar(sd)) => matches!(sd.affinity, ScalarAffinity::Empty(_)),
1048 (Type::Sequence(_), _) => true,
1049 (Type::User(UserType::Struct(sd)), _) => sd.kind == facet_core::StructKind::Tuple,
1050 (Type::User(UserType::Enum(_)), _) => {
1051 if let Some(variant) = &frame.istate.variant {
1053 variant.data.kind == facet_core::StructKind::Tuple
1054 } else {
1055 false }
1064 }
1065 _ => false,
1066 };
1067
1068 if !is_list && !is_array && !is_tuple_struct_or_variant {
1069 return Err(ReflectError::WasNotA {
1070 expected: "list, array, or tuple-like struct/enum variant",
1071 actual: frame.shape,
1072 });
1073 }
1074
1075 if is_list {
1077 let vtable = frame.shape.vtable;
1078 if !frame.istate.fields.has(0) {
1080 let Some(default_in_place) = (vtable.default_in_place)() else {
1081 return Err(ReflectError::OperationFailed {
1082 shape: frame.shape,
1083 operation: "list type does not implement Default, cannot begin pushback",
1084 });
1085 };
1086
1087 unsafe {
1088 default_in_place(frame.data);
1089 frame.istate.fields.set(0);
1091 }
1092 }
1093 }
1094 else if is_array {
1096 frame.istate.list_index = Some(0);
1098 }
1099 Ok(self)
1102 }
1103
1104 pub fn begin_map_insert(mut self) -> Result<Self, ReflectError<'shape>> {
1106 let Some(frame) = self.frames.last_mut() else {
1107 return Err(ReflectError::OperationFailed {
1108 shape: <()>::SHAPE,
1109 operation: "tried to begin map insertion but there was no frame",
1110 });
1111 };
1112
1113 if !matches!(frame.shape.def, Def::Map(_)) {
1114 return Err(ReflectError::WasNotA {
1115 expected: "map or hash map",
1116 actual: frame.shape,
1117 });
1118 }
1119
1120 let vtable = frame.shape.vtable;
1121
1122 if !frame.istate.fields.has(0) {
1124 let Some(default_in_place) = (vtable.default_in_place)() else {
1125 return Err(ReflectError::OperationFailed {
1126 shape: frame.shape,
1127 operation: "map type does not implement Default",
1128 });
1129 };
1130
1131 unsafe {
1132 default_in_place(frame.data);
1133 frame.istate.fields.set(0);
1134 }
1135 }
1136
1137 Ok(self)
1138 }
1139
1140 pub fn push(mut self) -> Result<Self, ReflectError<'shape>> {
1145 let frame_len = self.frames.len();
1147 let frame = self
1148 .frames
1149 .last_mut()
1150 .ok_or(ReflectError::OperationFailed {
1151 shape: <()>::SHAPE,
1152 operation: "tried to push but there was no frame",
1153 })?;
1154 let seq_shape = frame.shape;
1155
1156 let (element_shape, context_str): (&'shape Shape<'shape>, &'shape str) =
1158 match (seq_shape.ty, seq_shape.def) {
1159 (_, Def::List(list_def)) => {
1160 if !frame.istate.fields.has(0) {
1162 return self.begin_pushback()?.push();
1165 }
1166 let shape = list_def.t();
1168 (shape, "list")
1169 }
1170 (_, Def::Array(array_def)) => {
1171 let index = frame.istate.list_index.unwrap_or(0);
1173
1174 if index >= array_def.n {
1176 return Err(ReflectError::ArrayIndexOutOfBounds {
1177 shape: seq_shape,
1178 index,
1179 size: array_def.n,
1180 });
1181 }
1182
1183 frame.istate.list_index = Some(index + 1);
1185
1186 let element_shape = array_def.t;
1188 (element_shape, "array")
1189 }
1190 (Type::Sequence(SequenceType::Tuple(tt)), _) => {
1191 let field_index = {
1193 let next_idx = frame.istate.list_index.unwrap_or(0);
1195 frame.istate.list_index = Some(next_idx + 1);
1196 next_idx
1197 };
1198 if field_index >= tt.fields.len() {
1200 return Err(ReflectError::FieldError {
1201 shape: seq_shape,
1202 field_error: FieldError::NoSuchField,
1203 });
1204 }
1205 (tt.fields[field_index].shape(), "tuple")
1207 }
1208 (Type::User(UserType::Struct(sd)), _)
1209 if sd.kind == facet_core::StructKind::Tuple =>
1210 {
1211 let field_index = {
1213 let next_idx = frame.istate.list_index.unwrap_or(0);
1215 frame.istate.list_index = Some(next_idx + 1);
1216 next_idx
1217 };
1218 if field_index >= sd.fields.len() {
1220 return Err(ReflectError::FieldError {
1221 shape: seq_shape,
1222 field_error: FieldError::NoSuchField, });
1224 }
1225 (sd.fields[field_index].shape(), "tuple struct")
1227 }
1228
1229 (Type::User(UserType::Enum(_)), _) => {
1230 let variant =
1232 frame
1233 .istate
1234 .variant
1235 .as_ref()
1236 .ok_or(ReflectError::OperationFailed {
1237 shape: seq_shape,
1238 operation: "tried to push onto enum but no variant was selected",
1239 })?;
1240 if variant.data.kind != facet_core::StructKind::Tuple {
1242 return Err(ReflectError::WasNotA {
1243 expected: "tuple-like enum variant",
1244 actual: seq_shape, });
1246 }
1247 let field_index = {
1249 let next_idx = frame.istate.list_index.unwrap_or(0);
1251 frame.istate.list_index = Some(next_idx + 1);
1252 next_idx
1253 };
1254 if field_index >= variant.data.fields.len() {
1256 return Err(ReflectError::FieldError {
1257 shape: seq_shape, field_error: FieldError::NoSuchField,
1259 });
1260 }
1261 (
1263 variant.data.fields[field_index].shape(),
1264 "tuple enum variant",
1265 )
1266 }
1267 (_, Def::Scalar(sd)) if matches!(sd.affinity, ScalarAffinity::Empty(_)) => {
1268 return Err(ReflectError::OperationFailed {
1270 shape: seq_shape,
1271 operation: "cannot push elements to unit type ()",
1272 });
1273 }
1274 _ => {
1275 return Err(ReflectError::WasNotA {
1277 expected: "list, array, tuple, tuple struct, or tuple enum variant",
1278 actual: seq_shape,
1279 });
1280 }
1281 };
1282
1283 let element_data = element_shape
1285 .allocate()
1286 .map_err(|_| ReflectError::Unsized {
1287 shape: element_shape,
1288 })?;
1289
1290 let element_frame = Frame {
1292 data: element_data,
1293 shape: element_shape,
1294 field_index_in_parent: None, istate: IState::new(
1296 frame_len, FrameMode::ListElement, FrameFlags::ALLOCATED,
1299 ),
1300 };
1301
1302 trace!(
1303 "[{}] Pushing element of type {} to {} {}",
1304 frame_len,
1305 element_shape.green(),
1306 context_str, seq_shape.blue(),
1308 );
1309 let _ = context_str;
1310
1311 self.frames.push(element_frame);
1312 Ok(self)
1313 }
1314
1315 pub fn push_some(mut self) -> Result<Self, ReflectError<'shape>> {
1317 let frame = self.frames.last().unwrap();
1319 let option_shape = frame.shape;
1320
1321 let Def::Option(option_def) = option_shape.def else {
1323 return Err(ReflectError::WasNotA {
1324 expected: "option",
1325 actual: option_shape,
1326 });
1327 };
1328
1329 let inner_shape = option_def.t();
1331
1332 let inner_data = inner_shape
1334 .allocate()
1335 .map_err(|_| ReflectError::Unsized { shape: inner_shape })?;
1336
1337 let inner_frame = Frame {
1339 data: inner_data,
1340 shape: inner_shape,
1341 field_index_in_parent: None,
1343 istate: IState::new(
1344 self.frames.len(),
1345 FrameMode::OptionSome,
1346 FrameFlags::ALLOCATED,
1348 ),
1349 };
1350
1351 trace!(
1352 "[{}] Pushing option frame for {}",
1353 self.frames.len(),
1354 option_shape.blue(),
1355 );
1356
1357 self.frames.push(inner_frame);
1358 Ok(self)
1359 }
1360
1361 pub fn push_pointee(mut self) -> Result<Self, ReflectError<'shape>> {
1365 let frame = self.frames.last().unwrap();
1367 let smart_ptr_shape = frame.shape;
1368
1369 let Def::SmartPointer(smart_ptr_def) = smart_ptr_shape.def else {
1371 return Err(ReflectError::WasNotA {
1372 expected: "smart pointer (pointee type)",
1373 actual: smart_ptr_shape,
1374 });
1375 };
1376
1377 let Some(pointee_fn) = smart_ptr_def.pointee else {
1379 return Err(ReflectError::OperationFailed {
1380 shape: smart_ptr_shape,
1381 operation: "smart pointer does not specify a pointee type",
1382 });
1383 };
1384 let inner_shape = pointee_fn();
1385
1386 let inner_data = inner_shape
1388 .allocate()
1389 .map_err(|_| ReflectError::Unsized { shape: inner_shape })?;
1390
1391 let inner_frame = Frame {
1393 data: inner_data,
1394 shape: inner_shape,
1395 field_index_in_parent: None, istate: IState::new(
1397 self.frames.len(),
1398 FrameMode::SmartPointee, FrameFlags::ALLOCATED,
1400 ),
1401 };
1402
1403 trace!(
1404 "[{}] Pushing smart pointer pointee frame for {}",
1405 self.frames.len(),
1406 smart_ptr_shape.blue(),
1407 );
1408
1409 self.frames.push(inner_frame);
1410
1411 Ok(self)
1412 }
1413
1414 pub fn push_inner(mut self) -> Result<Self, ReflectError<'shape>> {
1417 let frame = self.frames.last().unwrap();
1419 let outer_shape = frame.shape;
1420
1421 let Some(inner_fn) = outer_shape.inner else {
1423 return Err(ReflectError::WasNotA {
1424 expected: "wrapper type",
1425 actual: outer_shape,
1426 });
1427 };
1428 let inner_shape = inner_fn();
1429
1430 let inner_data = inner_shape
1432 .allocate()
1433 .map_err(|_| ReflectError::Unsized { shape: inner_shape })?;
1434
1435 let inner_frame = Frame {
1437 data: inner_data,
1438 shape: inner_shape,
1439 field_index_in_parent: None, istate: IState::new(
1441 self.frames.len(),
1442 FrameMode::Inner, FrameFlags::ALLOCATED,
1444 ),
1445 };
1446
1447 trace!(
1448 "[{}] Pushing wrapped inner frame for {}",
1449 self.frames.len(),
1450 outer_shape.blue(),
1451 );
1452
1453 self.frames.push(inner_frame);
1454
1455 Ok(self)
1456 }
1457
1458 pub fn pop_some_push_none(mut self) -> Result<Self, ReflectError<'shape>> {
1468 let Some(frame) = self.frames.last_mut() else {
1470 return Err(ReflectError::OperationFailed {
1471 shape: <()>::SHAPE,
1472 operation: "tried to pop_some_push_none but there was no frame",
1473 });
1474 };
1475
1476 if frame.istate.mode != FrameMode::OptionSome {
1478 return Err(ReflectError::OperationFailed {
1479 shape: frame.shape,
1480 operation: "pop_some_push_none called, but frame was not in Option mode",
1481 });
1482 }
1483
1484 if frame.is_fully_initialized() {
1486 return Err(ReflectError::OperationFailed {
1487 shape: frame.shape,
1488 operation: "option frame already initialized, cannot pop_some_push_none",
1489 });
1490 }
1491
1492 frame.dealloc_if_needed();
1493
1494 let _frame = self.frames.pop().expect("frame already checked");
1496
1497 let parent_frame = self
1499 .frames
1500 .last_mut()
1501 .ok_or(ReflectError::OperationFailed {
1502 shape: <()>::SHAPE,
1503 operation: "tried to pop_some_push_none but there was no parent frame",
1504 })?;
1505
1506 unsafe {
1508 if let Some(default_fn) = (parent_frame.shape.vtable.default_in_place)() {
1509 default_fn(parent_frame.data);
1510 } else {
1511 return Err(ReflectError::OperationFailed {
1512 shape: parent_frame.shape,
1513 operation: "option type does not implement Default",
1514 });
1515 }
1516 parent_frame.mark_fully_initialized();
1517 }
1518
1519 let Def::Option(od) = parent_frame.shape.def else {
1520 return Err(ReflectError::OperationFailed {
1521 shape: parent_frame.shape,
1522 operation: "pop_some_push_none and the parent isn't of type Option???",
1523 });
1524 };
1525
1526 let data = parent_frame.data;
1528
1529 let mut frame = Frame {
1530 data,
1531 shape: od.t(),
1532 field_index_in_parent: Some(0),
1533 istate: IState::new(self.frames.len(), FrameMode::OptionNone, FrameFlags::EMPTY),
1534 };
1535 unsafe {
1536 frame.mark_fully_initialized();
1537 }
1538
1539 self.frames.push(frame);
1540
1541 Ok(self)
1542 }
1543
1544 pub fn push_map_key(mut self) -> Result<Self, ReflectError<'shape>> {
1549 let frame = self.frames.last().unwrap();
1551 let map_shape = frame.shape;
1552
1553 if !matches!(map_shape.def, Def::Map(_)) {
1554 return Err(ReflectError::WasNotA {
1555 expected: "map or hash map",
1556 actual: map_shape,
1557 });
1558 }
1559
1560 if !frame.istate.fields.has(0) {
1562 self = self.begin_map_insert()?;
1563 }
1564
1565 let key_shape = match map_shape.def {
1567 Def::Map(map_def) => map_def.k(),
1568 _ => unreachable!("Already checked map type above"),
1569 };
1570
1571 let key_data = key_shape
1573 .allocate()
1574 .map_err(|_| ReflectError::Unsized { shape: key_shape })?;
1575
1576 let key_frame = Frame {
1578 data: key_data,
1579 shape: key_shape,
1580 field_index_in_parent: None,
1581 istate: IState::new(self.frames.len(), FrameMode::MapKey, FrameFlags::ALLOCATED),
1582 };
1583
1584 trace!(
1585 "[{}] Pushing key of type {} for map {}",
1586 self.frames.len(),
1587 key_shape.green(),
1588 map_shape.blue(),
1589 );
1590
1591 self.frames.push(key_frame);
1592 Ok(self)
1593 }
1594
1595 pub fn push_map_value(mut self) -> Result<Self, ReflectError<'shape>> {
1600 trace!("Wants to push map value. Frames = ");
1601 #[cfg(feature = "log")]
1602 for (i, f) in self.frames.iter().enumerate() {
1603 trace!("Frame {}: {:?}", i, f);
1604 }
1605
1606 if self.frames.len() < 2 {
1608 return Err(ReflectError::OperationFailed {
1609 shape: <()>::SHAPE,
1610 operation: "tried to push map value but there was no key frame",
1611 });
1612 }
1613
1614 let key_frame_index = self.frames.len() - 1;
1616 let key_frame = &self.frames[key_frame_index];
1617
1618 match key_frame.istate.mode {
1620 FrameMode::MapKey => {} _ => {
1622 return Err(ReflectError::OperationFailed {
1623 shape: key_frame.shape,
1624 operation: "current frame is not a map key",
1625 });
1626 }
1627 }
1628
1629 if !key_frame.is_fully_initialized() {
1631 return Err(ReflectError::OperationFailed {
1632 shape: key_frame.shape,
1633 operation: "map key is not fully initialized",
1634 });
1635 }
1636
1637 let map_frame_index = self.frames.len() - 2;
1639 let map_frame = &self.frames[map_frame_index];
1640 let map_shape = map_frame.shape;
1641
1642 let Def::Map(map_def) = map_shape.def else {
1643 return Err(ReflectError::WasNotA {
1644 expected: "map",
1645 actual: map_frame.shape,
1646 });
1647 };
1648
1649 let value_shape = map_def.v();
1650
1651 let value_data = value_shape
1653 .allocate()
1654 .map_err(|_| ReflectError::Unsized { shape: value_shape })?;
1655
1656 let value_frame = Frame {
1658 data: value_data,
1659 shape: value_shape,
1660 field_index_in_parent: None,
1661 istate: IState::new(
1662 self.frames.len(),
1663 FrameMode::MapValue {
1664 index: key_frame_index,
1665 },
1666 FrameFlags::ALLOCATED,
1667 ),
1668 };
1669
1670 trace!(
1671 "[{}] Pushing value of type {} for map {} with key type {}",
1672 self.frames.len(),
1673 value_shape.green(),
1674 map_shape.blue(),
1675 key_frame.shape.yellow(),
1676 );
1677
1678 self.frames.push(value_frame);
1679 Ok(self)
1680 }
1681
1682 pub(crate) fn evict_tree(&mut self, frame: Frame<'shape>) -> Frame<'shape> {
1686 match frame.shape.ty {
1687 Type::User(UserType::Struct(sd)) => {
1688 for f in sd.fields {
1689 let id = ValueId {
1690 shape: f.shape(),
1691 ptr: unsafe { frame.data.field_uninit_at(f.offset) }.as_byte_ptr(),
1692 };
1693 if let Some(istate) = self.istates.remove(&id) {
1694 let frame = Frame::recompose(id, istate);
1695 self.evict_tree(frame);
1696 } else {
1697 trace!("No istate found for field {}", f.name);
1698 }
1699 }
1700 }
1701 Type::User(UserType::Enum(_ed)) => {
1702 if let Some(variant) = &frame.istate.variant {
1704 trace!(
1705 "Evicting enum {} variant '{}' fields",
1706 frame.shape.blue(),
1707 variant.name.yellow()
1708 );
1709 for field in variant.data.fields {
1711 let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
1713 let field_shape = field.shape();
1714 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
1715
1716 if let Some(field_istate) = self.istates.remove(&field_id) {
1718 trace!(
1719 "Evicting field '{}' (shape {}) of enum variant '{}'",
1720 field.name.bright_blue(),
1721 field_shape.green(),
1722 variant.name.yellow()
1723 );
1724 let field_frame = Frame::recompose(field_id, field_istate);
1726 self.evict_tree(field_frame);
1728 } else {
1729 trace!(
1730 "Field '{}' (shape {}) of enum variant '{}' not found in istates, skipping eviction",
1731 field.name.red(),
1732 field_shape.red(),
1733 variant.name.yellow()
1734 );
1735 }
1736 }
1737 } else {
1738 trace!(
1740 "Enum {} has no variant selected, no fields to evict.",
1741 frame.shape.blue()
1742 );
1743 }
1744 }
1745 _ => {}
1746 }
1747 frame
1748 }
1749
1750 #[allow(rustdoc::broken_intra_doc_links)]
1751 pub fn path(&self) -> String {
1754 let mut path = String::from("$");
1755
1756 for (i, frame) in self.frames.iter().enumerate() {
1757 if i == 0 {
1759 continue;
1760 }
1761
1762 match frame.istate.mode {
1763 FrameMode::ListElement => {
1764 if let Some(index) = frame.istate.list_index {
1766 path.push_str(&format!("[{}]", index));
1767 } else {
1768 path.push_str("[?]");
1769 }
1770 }
1771 FrameMode::MapKey => {
1772 path.push_str(".key");
1773 }
1774 FrameMode::MapValue { index: _ } => {
1775 path.push_str(".value");
1776 }
1777 FrameMode::OptionSome => {
1778 path.push_str(".some");
1779 }
1780 FrameMode::OptionNone => {
1781 path.push_str(".none");
1782 }
1783 FrameMode::SmartPointee | FrameMode::Inner => {
1784 path.push_str(".*");
1785 }
1786 FrameMode::Root => {
1787 }
1789 FrameMode::Field => {
1790 if let Some(index) = frame.field_index_in_parent {
1792 if let Some(parent) = self.frames.get(i - 1) {
1794 if let Type::User(UserType::Struct(sd)) = parent.shape.ty {
1795 if index < sd.fields.len() {
1796 let field_name = sd.fields[index].name;
1797 path.push('.');
1798 path.push_str(field_name);
1799 }
1800 } else if let Type::User(UserType::Enum(_)) = parent.shape.ty {
1801 if let Some(variant) = &parent.istate.variant {
1802 if index < variant.data.fields.len() {
1803 let field_name = variant.data.fields[index].name;
1804 path.push('.');
1805 path.push_str(field_name);
1806 }
1807 }
1808 }
1809 }
1810 }
1811 }
1812 }
1813 }
1814
1815 path
1816 }
1817
1818 pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError<'shape>> {
1820 let frame = self.frames.last().ok_or(ReflectError::OperationFailed {
1821 shape: <()>::SHAPE,
1822 operation: "tried to check if field is set, but there was no frame",
1823 })?;
1824
1825 match frame.shape.ty {
1826 Type::User(UserType::Struct(ref sd)) => {
1827 if index >= sd.fields.len() {
1828 return Err(ReflectError::FieldError {
1829 shape: frame.shape,
1830 field_error: FieldError::NoSuchField,
1831 });
1832 }
1833 Ok(frame.istate.fields.has(index))
1834 }
1835 Type::User(UserType::Enum(_)) => {
1836 let variant = frame.istate.variant.as_ref().ok_or(
1837 ReflectError::OperationFailed {
1838 shape: frame.shape,
1839 operation: "tried to check if field is set, but no variant was selected",
1840 },
1841 )?;
1842 if index >= variant.data.fields.len() {
1843 return Err(ReflectError::FieldError {
1844 shape: frame.shape,
1845 field_error: FieldError::NoSuchField,
1846 });
1847 }
1848 Ok(frame.istate.fields.has(index))
1849 }
1850 _ => Err(ReflectError::WasNotA {
1851 expected: "struct or enum",
1852 actual: frame.shape,
1853 }),
1854 }
1855 }
1856}