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 {
39 variant: Option<Variant>,
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 IState {
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}
132
133pub struct Wip<'facet_lifetime> {
135 frames: alloc::vec::Vec<Frame>,
137
138 istates: FlatMap<ValueId, IState>,
140
141 invariant: PhantomData<fn(&'facet_lifetime ()) -> &'facet_lifetime ()>,
142}
143
144impl<'facet_lifetime> Wip<'facet_lifetime> {
145 pub fn put_peek(
147 self,
148 peek: crate::Peek<'_, 'facet_lifetime>,
149 ) -> Result<Wip<'facet_lifetime>, ReflectError> {
150 self.put_shape(peek.data, peek.shape)
151 }
152
153 pub fn frames_count(&self) -> usize {
155 self.frames.len()
156 }
157
158 pub fn alloc_shape(shape: &'static Shape) -> Result<Self, ReflectError> {
160 let data = shape
161 .allocate()
162 .map_err(|_| ReflectError::Unsized { shape })?;
163 Ok(Self {
164 frames: alloc::vec![Frame {
165 data,
166 shape,
167 field_index_in_parent: None,
168 istate: IState::new(0, FrameMode::Root, FrameFlags::ALLOCATED),
169 }],
170 istates: Default::default(),
171 invariant: PhantomData,
172 })
173 }
174
175 pub fn alloc<S: Facet<'facet_lifetime>>() -> Result<Self, ReflectError> {
177 Self::alloc_shape(S::SHAPE)
178 }
179
180 fn track(&mut self, frame: Frame) {
181 if frame.istate.flags.contains(FrameFlags::MOVED) {
187 return;
189 }
190
191 self.istates.insert(frame.id(), frame.istate);
192 }
193
194 unsafe fn mark_moved_out_of(&mut self, frame: &mut Frame) {
195 unsafe fn mark_subtree_moved(wip: &mut Wip, id: ValueId) {
198 unsafe {
200 if let Some(mut istate) = wip.istates.remove(&id) {
202 istate.flags.insert(FrameFlags::MOVED);
204
205 match id.shape.ty {
207 Type::User(UserType::Struct(sd)) => {
208 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
209 for field in sd.fields.iter() {
210 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
211 let field_id =
212 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
213 mark_subtree_moved(wip, field_id);
215 }
216 }
217 Type::User(UserType::Enum(_)) => {
218 if let Some(variant) = &istate.variant {
220 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
221 for field in variant.data.fields.iter() {
222 let field_ptr_uninit =
223 container_ptr.field_uninit_at(field.offset);
224 let field_id =
225 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
226 mark_subtree_moved(wip, field_id);
228 }
229 }
230 }
231 _ => {}
235 }
236
237 if istate.flags.contains(FrameFlags::ALLOCATED) {
240 let mut temp_frame = Frame::recompose(id, istate);
242 temp_frame.dealloc_if_needed();
243 }
244 }
245 }
247 }
248
249 unsafe {
252 let frame_id = frame.id();
254
255 let variant_opt = frame.istate.variant;
257
258 frame.istate.flags.insert(FrameFlags::MOVED);
260 ISet::clear(&mut frame.istate.fields);
261
262 match frame.shape.ty {
265 Type::User(UserType::Struct(sd)) => {
266 let container_ptr = PtrUninit::new(frame_id.ptr as *mut u8);
267 for field in sd.fields.iter() {
268 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
269 let field_id = ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
270 mark_subtree_moved(self, field_id);
271 }
272 }
273 Type::User(UserType::Enum(_)) => {
274 if let Some(variant) = &variant_opt {
276 let container_ptr = PtrUninit::new(frame_id.ptr as *mut u8);
277 for field in variant.data.fields.iter() {
278 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
279 let field_id =
280 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
281 mark_subtree_moved(self, field_id);
282 }
283 }
284 }
285 _ => {}
287 }
288
289 frame.istate.variant = None;
291
292 self.istates.remove(&frame_id);
294
295 if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
297 frame.dealloc_if_needed();
298 }
299 }
300 }
301
302 pub fn shape(&self) -> &'static Shape {
304 self.frames.last().expect("must have frames left").shape
305 }
306
307 pub fn innermost_shape(&self) -> &'static Shape {
311 let mut current_shape = self.shape();
312
313 while let Some(inner_fn) = current_shape.inner {
315 current_shape = inner_fn();
316 }
317
318 current_shape
319 }
320
321 pub fn in_option(&self) -> bool {
323 let Some(frame) = self.frames.last() else {
324 return false;
325 };
326 matches!(frame.istate.mode, FrameMode::OptionSome)
327 }
328
329 pub fn mode(&self) -> FrameMode {
331 self.frames.last().unwrap().istate.mode
332 }
333
334 pub fn build(mut self) -> Result<HeapValue<'facet_lifetime>, ReflectError> {
336 debug!("[{}] ⚒️ It's BUILD time", self.frames.len());
337
338 if self.frames.is_empty() {
340 panic!("No frames in WIP during build: stack is empty (you popped too much)");
341 }
342 if self.frames.len() != 1 {
343 panic!(
344 "You must pop frames so that only the root frame remains before calling build (frames left: {})",
345 self.frames.len()
346 );
347 }
348
349 let root_frame = &self.frames[0];
351
352 enum FrameRef {
353 Root,
354 ById(ValueId),
355 }
356 let mut to_check = alloc::vec![FrameRef::Root];
357
358 while let Some(fr) = to_check.pop() {
360 let (id, istate) = match fr {
361 FrameRef::Root => (root_frame.id(), &root_frame.istate),
362 FrameRef::ById(id) => {
363 let istate = self.istates.get(&id).unwrap();
365 (id, istate)
366 }
367 };
368
369 trace!(
370 "Checking shape {} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
371 id.shape.blue(),
372 id.ptr,
373 istate.flags.bright_magenta(),
374 istate.mode.yellow(),
375 if is_fully_initialized(id.shape, istate) {
376 "✅"
377 } else {
378 "❌"
379 }
380 );
381
382 if istate.flags.contains(FrameFlags::MOVED) {
384 trace!(
385 "{}",
386 "Frame was moved out of, skipping initialization check".yellow()
387 );
388 continue;
389 }
390
391 if let Def::Array(array_def) = id.shape.def {
395 let pushed_count = istate.list_index.unwrap_or(0);
397
398 if pushed_count != array_def.n {
400 return Err(ReflectError::ArrayNotFullyInitialized {
401 shape: id.shape,
402 pushed_count,
403 expected_size: array_def.n,
404 });
405 }
406 }
407 else if !matches!(id.shape.def, Def::Undefined) {
411 if !istate.fields.are_all_set(1) {
412 match istate.mode {
414 FrameMode::OptionNone => {
415 debug!("Found uninitialized value (option none) — {}", id.shape);
417 return Err(ReflectError::UninitializedValue { shape: id.shape });
418 }
419 _ => {
421 debug!(
422 "Found uninitialized value (list/map/option/etc. — {})",
423 id.shape
424 );
425 return Err(ReflectError::UninitializedValue { shape: id.shape });
426 }
427 }
428 }
429 } else {
437 match id.shape.ty {
438 Type::User(UserType::Struct(sd)) => {
439 for i in 0..sd.fields.len() {
441 if !istate.fields.has(i) {
442 let field = &sd.fields[i];
443 trace!("Found uninitialized field: {}", field.name);
444 return Err(ReflectError::UninitializedField {
445 shape: id.shape,
446 field_name: field.name,
447 });
448 }
449 }
450
451 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
452
453 #[allow(clippy::unused_enumerate_index)]
455 for (_i, field) in sd.fields.iter().enumerate() {
456 let field_shape = field.shape();
457 let field_ptr = unsafe { container_ptr.field_init_at(field.offset) };
458 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
459
460 if self.istates.contains_key(&field_id) {
461 debug!(
462 "Queueing struct field check: #{} '{}' of {}: shape={}, ptr={:p}",
463 _i.to_string().bright_cyan(),
464 field.name.bright_blue(),
465 id.shape.blue(),
466 field_shape.green(),
467 field_ptr.as_byte_ptr()
468 );
469 to_check.push(FrameRef::ById(field_id));
470 }
471 }
472 }
473 Type::User(UserType::Enum(_ed)) => {
474 if let Some(variant) = &istate.variant {
475 for (i, field) in variant.data.fields.iter().enumerate() {
477 if !istate.fields.has(i) {
478 trace!("Found uninitialized field: {}", field.name);
479 return Err(ReflectError::UninitializedEnumField {
480 shape: id.shape,
481 variant_name: variant.name,
482 field_name: field.name,
483 });
484 }
485 }
486
487 #[allow(clippy::unused_enumerate_index)]
489 for (_i, field) in variant.data.fields.iter().enumerate() {
490 let field_shape = field.shape();
491 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
492 let field_ptr =
494 unsafe { container_ptr.field_init_at(field.offset) };
495 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
496
497 if self.istates.contains_key(&field_id) {
498 debug!(
499 "Queueing enum field check: #{} '{}' of variant '{}' of {}: shape={}, ptr={:p}",
500 _i.to_string().bright_cyan(),
501 field.name.bright_blue(),
502 variant.name.yellow(),
503 id.shape.blue(),
504 field_shape.green(),
505 field_ptr.as_byte_ptr()
506 );
507 to_check.push(FrameRef::ById(field_id));
508 }
509 }
510 } else {
511 debug!("Found no variant selected for enum");
513 return Err(ReflectError::NoVariantSelected { shape: id.shape });
514 }
515 }
516 _ => {
518 if !istate.fields.are_all_set(1) {
520 debug!("Found uninitialized value (other)");
521 return Err(ReflectError::UninitializedValue { shape: id.shape });
522 }
523 }
524 }
525 }
526 }
527
528 debug!("All reachable frames checked and initialized.");
530
531 let root_shape = root_frame.shape;
534 let root_data = unsafe { root_frame.data.assume_init() };
535 if let Some(invariant_fn) = root_shape.vtable.invariants {
536 debug!(
537 "Checking invariants for root shape {} at {:p}",
538 root_shape.green(),
539 root_data.as_byte_ptr()
540 );
541 if !unsafe { invariant_fn(PtrConst::new(root_data.as_byte_ptr())) } {
542 return Err(ReflectError::InvariantViolation {
543 invariant: "Custom validation function returned false",
544 });
545 }
546 } else {
547 debug!(
548 "No invariants to check for root shape {}",
549 root_shape.blue()
550 );
551 }
552
553 {
555 FlatMap::clear(&mut self.istates);
556 self.frames.clear();
557 }
558
559 let guard = Guard {
561 ptr: root_data.as_mut_byte_ptr(),
562 layout: match root_shape.layout {
563 facet_core::ShapeLayout::Sized(layout) => layout,
564 facet_core::ShapeLayout::Unsized => panic!("Unsized layout not supported"),
565 },
566 };
567
568 Ok(HeapValue {
569 guard: Some(guard),
570 shape: root_shape,
571 phantom: PhantomData,
572 })
573 }
574
575 pub fn field(mut self, index: usize) -> Result<Self, ReflectError> {
587 let frame = self.frames.last_mut().unwrap();
588 let shape = frame.shape;
589
590 let (field, field_offset) = match shape.ty {
591 Type::User(UserType::Struct(def)) => {
592 if index >= def.fields.len() {
593 return Err(ReflectError::FieldError {
594 shape,
595 field_error: FieldError::NoSuchField,
596 });
597 }
598 let field = &def.fields[index];
599 (field, field.offset)
600 }
601 Type::User(UserType::Enum(_)) => {
602 let Some(variant) = frame.istate.variant.as_ref() else {
603 return Err(ReflectError::OperationFailed {
604 shape,
605 operation: "tried to access a field but no variant was selected",
606 });
607 };
608
609 if index >= variant.data.fields.len() {
610 return Err(ReflectError::FieldError {
611 shape,
612 field_error: FieldError::NoSuchField,
613 });
614 }
615
616 let field = &variant.data.fields[index];
617 (field, field.offset)
618 }
619 _ => {
620 return Err(ReflectError::WasNotA {
621 expected: "struct or enum",
622 actual: shape,
623 });
624 }
625 };
626
627 let field_data = unsafe { frame.data.field_uninit_at(field_offset) };
628
629 let mut frame = Frame {
630 data: field_data,
631 shape: field.shape(),
632 field_index_in_parent: Some(index),
633 istate: IState::new(self.frames.len(), FrameMode::Field, FrameFlags::EMPTY),
635 };
636 debug!(
637 "[{}] Selecting field {} ({}#{}) of {}",
638 self.frames.len(),
639 field.name.blue(),
640 field.shape().green(),
641 index.yellow(),
642 shape.blue(),
643 );
644 if let Some(iset) = self.istates.remove(&frame.id()) {
645 trace!(
646 "[{}] Restoring saved state for {} (istate.mode = {:?}, istate.fields = {:?}, istate.flags = {:?}, istate.depth = {:?})",
647 self.frames.len(),
648 frame.id().shape.blue(),
649 iset.mode,
650 iset.fields,
651 iset.flags,
652 iset.depth
653 );
654 frame.istate = iset;
655 } else {
656 trace!(
657 "[{}] no saved state for field {} ({}#{}) of {}",
658 self.frames.len(),
659 field.name.blue(),
660 field.shape().green(),
661 index.yellow(),
662 shape.blue(),
663 );
664 }
665 self.frames.push(frame);
666 Ok(self)
667 }
668
669 pub fn field_index(&self, name: &str) -> Option<usize> {
681 fn find_field_index(fields: &'static [facet_core::Field], name: &str) -> Option<usize> {
682 fields.iter().position(|f| f.name == name)
683 }
684
685 let frame = self.frames.last()?;
686 match frame.shape.ty {
687 Type::User(UserType::Struct(def)) => find_field_index(def.fields, name),
688 Type::User(UserType::Enum(_)) => {
689 let variant = frame.istate.variant.as_ref()?;
690 find_field_index(variant.data.fields, name)
691 }
692 _ => None,
693 }
694 }
695
696 pub fn field_named(self, name: &str) -> Result<Self, ReflectError> {
708 let frame = self.frames.last().unwrap();
709 let shape = frame.shape;
710
711 if let Type::User(UserType::Enum(_)) = shape.ty {
713 if frame.istate.variant.is_none() {
714 return Err(ReflectError::OperationFailed {
715 shape,
716 operation: "tried to access a field by name but no variant was selected",
717 });
718 }
719 }
720
721 let index = self.field_index(name).ok_or(ReflectError::FieldError {
722 shape,
723 field_error: FieldError::NoSuchField,
724 })?;
725
726 self.field(index)
727 }
728
729 pub fn put<T: Facet<'facet_lifetime>>(
740 self,
741 t: T,
742 ) -> Result<Wip<'facet_lifetime>, ReflectError> {
743 let shape = T::SHAPE;
744 let ptr_const = PtrConst::new(&t as *const T as *const u8);
745 let res = self.put_shape(ptr_const, shape);
746 core::mem::forget(t); res
748 }
749
750 pub fn try_put<T: Facet<'facet_lifetime>>(
761 self,
762 t: T,
763 ) -> Result<Wip<'facet_lifetime>, ReflectError> {
764 let shape = T::SHAPE;
765 let ptr_const = PtrConst::new(&t as *const T as *const u8);
766 let res = self.put_shape(ptr_const, shape);
767 core::mem::forget(t); res
769 }
770
771 pub fn parse(mut self, s: &str) -> Result<Self, ReflectError> {
773 let Some(frame) = self.frames.last_mut() else {
774 return Err(ReflectError::OperationFailed {
775 shape: <()>::SHAPE,
776 operation: "tried to parse value but there was no frame",
777 });
778 };
779
780 let shape = frame.shape;
781 let index = frame.field_index_in_parent;
782
783 let Some(parse_fn) = frame.shape.vtable.parse else {
784 return Err(ReflectError::OperationFailed {
785 shape: frame.shape,
786 operation: "type does not implement Parse",
787 });
788 };
789 match unsafe { (parse_fn)(s, frame.data) } {
790 Ok(_res) => {
791 unsafe {
792 frame.mark_fully_initialized();
793 }
794
795 self.mark_field_as_initialized(shape, index)?;
797
798 Ok(self)
799 }
800 Err(_) => Err(ReflectError::OperationFailed {
801 shape,
802 operation: "parsing",
803 }),
804 }
805 }
806
807 pub fn put_from_fn(mut self, default_in_place: DefaultInPlaceFn) -> Result<Self, ReflectError> {
809 let Some(frame) = self.frames.last_mut() else {
810 return Err(ReflectError::OperationFailed {
811 shape: <()>::SHAPE,
812 operation: "tried to put value from fn but there was no frame",
813 });
814 };
815
816 if let Def::Array(array_def) = frame.shape.def {
819 trace!(
820 "[{}] Setting array as default-initialized with {} elements",
821 frame.istate.depth, array_def.n
822 );
823 frame.istate.list_index = Some(array_def.n);
825 }
826
827 unsafe {
828 default_in_place(frame.data);
829 trace!("Marking frame as fully initialized...");
830 frame.mark_fully_initialized();
831 trace!("Marking frame as fully initialized... done!");
832 }
833
834 let shape = frame.shape;
835 let index = frame.field_index_in_parent;
836
837 self.mark_field_as_initialized(shape, index)?;
839
840 Ok(self)
841 }
842
843 pub fn put_default(self) -> Result<Self, ReflectError> {
845 let Some(frame) = self.frames.last() else {
846 return Err(ReflectError::OperationFailed {
847 shape: <()>::SHAPE,
848 operation: "tried to put default value but there was no frame",
849 });
850 };
851
852 let vtable = frame.shape.vtable;
853 let Some(default_in_place) = vtable.default_in_place else {
854 return Err(ReflectError::OperationFailed {
855 shape: frame.shape,
856 operation: "type does not implement Default",
857 });
858 };
859
860 self.put_from_fn(default_in_place)
861 }
862
863 fn mark_field_as_initialized(
865 &mut self,
866 shape: &'static Shape,
867 index: Option<usize>,
868 ) -> Result<(), ReflectError> {
869 if let Some(index) = index {
870 let parent_index = self.frames.len().saturating_sub(2);
871 #[cfg(feature = "log")]
872 let num_frames = self.frames.len();
873 let Some(parent) = self.frames.get_mut(parent_index) else {
874 return Err(ReflectError::OperationFailed {
875 shape,
876 operation: "was supposed to mark a field as initialized, but there was no parent frame",
877 });
878 };
879 #[cfg(feature = "log")]
880 let parent_shape = parent.shape;
881 trace!(
882 "[{}] {}.{} initialized with {}",
883 num_frames,
884 parent_shape.blue(),
885 index.yellow(),
886 shape.green()
887 );
888
889 if matches!(parent.shape.ty, Type::User(UserType::Enum(_)))
890 && parent.istate.variant.is_none()
891 {
892 return Err(ReflectError::OperationFailed {
893 shape,
894 operation: "was supposed to mark a field as initialized, but the parent frame was an enum and didn't have a variant chosen",
895 });
896 }
897
898 if parent.istate.fields.has(index) {
899 return Err(ReflectError::OperationFailed {
900 shape,
901 operation: "was supposed to mark a field as initialized, but the parent frame already had it marked as initialized",
902 });
903 }
904
905 parent.istate.fields.set(index);
906 }
907 Ok(())
908 }
909
910 pub fn element_shape(&self) -> Result<&'static Shape, ReflectError> {
912 let frame = self.frames.last().unwrap();
913 let shape = frame.shape;
914
915 match shape.def {
916 Def::List(list_def) => Ok(list_def.t()),
917 _ => Err(ReflectError::WasNotA {
918 expected: "list or array",
919 actual: shape,
920 }),
921 }
922 }
923
924 pub fn key_shape(&self) -> Result<&'static Shape, ReflectError> {
926 let frame = self.frames.last().unwrap();
927 let shape = frame.shape;
928
929 match shape.def {
930 Def::Map(map_def) => Ok(map_def.k()),
931 _ => Err(ReflectError::WasNotA {
932 expected: "map",
933 actual: shape,
934 }),
935 }
936 }
937
938 pub fn put_empty_list(mut self) -> Result<Self, ReflectError> {
940 let Some(frame) = self.frames.last_mut() else {
941 return Err(ReflectError::OperationFailed {
942 shape: <()>::SHAPE,
943 operation: "tried to create empty list but there was no frame",
944 });
945 };
946
947 if !matches!(frame.shape.def, Def::List(_)) {
948 return Err(ReflectError::WasNotA {
949 expected: "list or array",
950 actual: frame.shape,
951 });
952 }
953
954 let vtable = frame.shape.vtable;
955
956 let Some(default_in_place) = vtable.default_in_place else {
958 return Err(ReflectError::OperationFailed {
959 shape: frame.shape,
960 operation: "list type does not implement Default",
961 });
962 };
963
964 unsafe {
965 default_in_place(frame.data);
966 frame.mark_fully_initialized();
967 }
968
969 let shape = frame.shape;
970 let index = frame.field_index_in_parent;
971
972 self.mark_field_as_initialized(shape, index)?;
974
975 Ok(self)
976 }
977
978 pub fn put_empty_map(mut self) -> Result<Self, ReflectError> {
980 let Some(frame) = self.frames.last_mut() else {
981 return Err(ReflectError::OperationFailed {
982 shape: <()>::SHAPE,
983 operation: "tried to create empty map but there was no frame",
984 });
985 };
986
987 if !matches!(frame.shape.def, Def::Map(_)) {
988 return Err(ReflectError::WasNotA {
989 expected: "map or hash map",
990 actual: frame.shape,
991 });
992 }
993
994 let vtable = frame.shape.vtable;
995
996 let Some(default_in_place) = vtable.default_in_place else {
998 return Err(ReflectError::OperationFailed {
999 shape: frame.shape,
1000 operation: "map type does not implement Default",
1001 });
1002 };
1003
1004 unsafe {
1005 default_in_place(frame.data);
1006 frame.mark_fully_initialized();
1007 }
1008
1009 let shape = frame.shape;
1010 let index = frame.field_index_in_parent;
1011
1012 self.mark_field_as_initialized(shape, index)?;
1014
1015 Ok(self)
1016 }
1017
1018 pub fn begin_pushback(mut self) -> Result<Self, ReflectError> {
1023 let Some(frame) = self.frames.last_mut() else {
1024 return Err(ReflectError::OperationFailed {
1025 shape: <()>::SHAPE,
1026 operation: "tried to begin pushback but there was no frame",
1027 });
1028 };
1029
1030 let is_list = matches!(frame.shape.def, Def::List(_));
1031 let is_array = matches!(frame.shape.def, Def::Array(_));
1032 let is_tuple_struct_or_variant = match (frame.shape.ty, frame.shape.def) {
1033 (_, Def::Scalar(sd)) => matches!(sd.affinity, ScalarAffinity::Empty(_)),
1034 (Type::Sequence(_), _) => true,
1035 (Type::User(UserType::Struct(sd)), _) => sd.kind == facet_core::StructKind::Tuple,
1036 (Type::User(UserType::Enum(_)), _) => {
1037 if let Some(variant) = &frame.istate.variant {
1039 variant.data.kind == facet_core::StructKind::Tuple
1040 } else {
1041 false }
1050 }
1051 _ => false,
1052 };
1053
1054 if !is_list && !is_array && !is_tuple_struct_or_variant {
1055 return Err(ReflectError::WasNotA {
1056 expected: "list, array, or tuple-like struct/enum variant",
1057 actual: frame.shape,
1058 });
1059 }
1060
1061 if is_list {
1063 let vtable = frame.shape.vtable;
1064 if !frame.istate.fields.has(0) {
1066 let Some(default_in_place) = vtable.default_in_place else {
1067 return Err(ReflectError::OperationFailed {
1068 shape: frame.shape,
1069 operation: "list type does not implement Default, cannot begin pushback",
1070 });
1071 };
1072
1073 unsafe {
1074 default_in_place(frame.data);
1075 frame.istate.fields.set(0);
1077 }
1078 }
1079 }
1080 else if is_array {
1082 frame.istate.list_index = Some(0);
1084 }
1085 Ok(self)
1088 }
1089
1090 pub fn begin_map_insert(mut self) -> Result<Self, ReflectError> {
1092 let Some(frame) = self.frames.last_mut() else {
1093 return Err(ReflectError::OperationFailed {
1094 shape: <()>::SHAPE,
1095 operation: "tried to begin map insertion but there was no frame",
1096 });
1097 };
1098
1099 if !matches!(frame.shape.def, Def::Map(_)) {
1100 return Err(ReflectError::WasNotA {
1101 expected: "map or hash map",
1102 actual: frame.shape,
1103 });
1104 }
1105
1106 let vtable = frame.shape.vtable;
1107
1108 if !frame.istate.fields.has(0) {
1110 let Some(default_in_place) = vtable.default_in_place else {
1111 return Err(ReflectError::OperationFailed {
1112 shape: frame.shape,
1113 operation: "map type does not implement Default",
1114 });
1115 };
1116
1117 unsafe {
1118 default_in_place(frame.data);
1119 frame.istate.fields.set(0);
1120 }
1121 }
1122
1123 Ok(self)
1124 }
1125
1126 pub fn push(mut self) -> Result<Self, ReflectError> {
1131 let frame_len = self.frames.len();
1133 let frame = self
1134 .frames
1135 .last_mut()
1136 .ok_or(ReflectError::OperationFailed {
1137 shape: <()>::SHAPE,
1138 operation: "tried to push but there was no frame",
1139 })?;
1140 let seq_shape = frame.shape;
1141
1142 let (element_shape, context_str): (&'static Shape, &'static str) =
1144 match (seq_shape.ty, seq_shape.def) {
1145 (_, Def::List(_)) => {
1146 if !frame.istate.fields.has(0) {
1148 return self.begin_pushback()?.push();
1151 }
1152 let shape = self.element_shape()?;
1155 (shape, "list")
1156 }
1157 (_, Def::Array(array_def)) => {
1158 let index = frame.istate.list_index.unwrap_or(0);
1160
1161 if index >= array_def.n {
1163 return Err(ReflectError::ArrayIndexOutOfBounds {
1164 shape: seq_shape,
1165 index,
1166 size: array_def.n,
1167 });
1168 }
1169
1170 frame.istate.list_index = Some(index + 1);
1172
1173 let element_shape = array_def.t;
1175 (element_shape, "array")
1176 }
1177 (Type::Sequence(SequenceType::Tuple(tt)), _) => {
1178 let field_index = {
1180 let next_idx = frame.istate.list_index.unwrap_or(0);
1182 frame.istate.list_index = Some(next_idx + 1);
1183 next_idx
1184 };
1185 if field_index >= tt.fields.len() {
1187 return Err(ReflectError::FieldError {
1188 shape: seq_shape,
1189 field_error: FieldError::NoSuchField,
1190 });
1191 }
1192 (tt.fields[field_index].shape(), "tuple")
1194 }
1195 (Type::User(UserType::Struct(sd)), _)
1196 if sd.kind == facet_core::StructKind::Tuple =>
1197 {
1198 let field_index = {
1200 let next_idx = frame.istate.list_index.unwrap_or(0);
1202 frame.istate.list_index = Some(next_idx + 1);
1203 next_idx
1204 };
1205 if field_index >= sd.fields.len() {
1207 return Err(ReflectError::FieldError {
1208 shape: seq_shape,
1209 field_error: FieldError::NoSuchField, });
1211 }
1212 (sd.fields[field_index].shape(), "tuple struct")
1214 }
1215
1216 (Type::User(UserType::Enum(_)), _) => {
1217 let variant =
1219 frame
1220 .istate
1221 .variant
1222 .as_ref()
1223 .ok_or(ReflectError::OperationFailed {
1224 shape: seq_shape,
1225 operation: "tried to push onto enum but no variant was selected",
1226 })?;
1227 if variant.data.kind != facet_core::StructKind::Tuple {
1229 return Err(ReflectError::WasNotA {
1230 expected: "tuple-like enum variant",
1231 actual: seq_shape, });
1233 }
1234 let field_index = {
1236 let next_idx = frame.istate.list_index.unwrap_or(0);
1238 frame.istate.list_index = Some(next_idx + 1);
1239 next_idx
1240 };
1241 if field_index >= variant.data.fields.len() {
1243 return Err(ReflectError::FieldError {
1244 shape: seq_shape, field_error: FieldError::NoSuchField,
1246 });
1247 }
1248 (
1250 variant.data.fields[field_index].shape(),
1251 "tuple enum variant",
1252 )
1253 }
1254 (_, Def::Scalar(sd)) if matches!(sd.affinity, ScalarAffinity::Empty(_)) => {
1255 return Err(ReflectError::OperationFailed {
1257 shape: seq_shape,
1258 operation: "cannot push elements to unit type ()",
1259 });
1260 }
1261 _ => {
1262 return Err(ReflectError::WasNotA {
1264 expected: "list, array, tuple, tuple struct, or tuple enum variant",
1265 actual: seq_shape,
1266 });
1267 }
1268 };
1269
1270 let element_data = element_shape
1272 .allocate()
1273 .map_err(|_| ReflectError::Unsized {
1274 shape: element_shape,
1275 })?;
1276
1277 let element_frame = Frame {
1279 data: element_data,
1280 shape: element_shape,
1281 field_index_in_parent: None, istate: IState::new(
1283 frame_len, FrameMode::ListElement, FrameFlags::ALLOCATED,
1286 ),
1287 };
1288
1289 trace!(
1290 "[{}] Pushing element of type {} to {} {}",
1291 frame_len,
1292 element_shape.green(),
1293 context_str, seq_shape.blue(),
1295 );
1296 let _ = context_str;
1297
1298 self.frames.push(element_frame);
1299 Ok(self)
1300 }
1301
1302 pub fn push_some(mut self) -> Result<Self, ReflectError> {
1304 let frame = self.frames.last().unwrap();
1306 let option_shape = frame.shape;
1307
1308 let Def::Option(option_def) = option_shape.def else {
1310 return Err(ReflectError::WasNotA {
1311 expected: "option",
1312 actual: option_shape,
1313 });
1314 };
1315
1316 let inner_shape = option_def.t();
1318
1319 let inner_data = inner_shape
1321 .allocate()
1322 .map_err(|_| ReflectError::Unsized { shape: inner_shape })?;
1323
1324 let inner_frame = Frame {
1326 data: inner_data,
1327 shape: inner_shape,
1328 field_index_in_parent: None,
1330 istate: IState::new(
1331 self.frames.len(),
1332 FrameMode::OptionSome,
1333 FrameFlags::ALLOCATED,
1335 ),
1336 };
1337
1338 trace!(
1339 "[{}] Pushing option frame for {}",
1340 self.frames.len(),
1341 option_shape.blue(),
1342 );
1343
1344 self.frames.push(inner_frame);
1345 Ok(self)
1346 }
1347
1348 pub fn pop_some_push_none(mut self) -> Result<Self, ReflectError> {
1358 let Some(frame) = self.frames.last_mut() else {
1360 return Err(ReflectError::OperationFailed {
1361 shape: <()>::SHAPE,
1362 operation: "tried to pop_some_push_none but there was no frame",
1363 });
1364 };
1365
1366 if frame.istate.mode != FrameMode::OptionSome {
1368 return Err(ReflectError::OperationFailed {
1369 shape: frame.shape,
1370 operation: "pop_some_push_none called, but frame was not in Option mode",
1371 });
1372 }
1373
1374 if frame.is_fully_initialized() {
1376 return Err(ReflectError::OperationFailed {
1377 shape: frame.shape,
1378 operation: "option frame already initialized, cannot pop_some_push_none",
1379 });
1380 }
1381
1382 frame.dealloc_if_needed();
1383
1384 let _frame = self.frames.pop().expect("frame already checked");
1386
1387 let parent_frame = self
1389 .frames
1390 .last_mut()
1391 .ok_or(ReflectError::OperationFailed {
1392 shape: <()>::SHAPE,
1393 operation: "tried to pop_some_push_none but there was no parent frame",
1394 })?;
1395
1396 unsafe {
1398 if let Some(default_fn) = parent_frame.shape.vtable.default_in_place {
1399 default_fn(parent_frame.data);
1400 } else {
1401 return Err(ReflectError::OperationFailed {
1402 shape: parent_frame.shape,
1403 operation: "option type does not implement Default",
1404 });
1405 }
1406 parent_frame.mark_fully_initialized();
1407 }
1408
1409 let Def::Option(od) = parent_frame.shape.def else {
1410 return Err(ReflectError::OperationFailed {
1411 shape: parent_frame.shape,
1412 operation: "pop_some_push_none and the parent isn't of type Option???",
1413 });
1414 };
1415
1416 let data = parent_frame.data;
1418
1419 let mut frame = Frame {
1420 data,
1421 shape: od.t(),
1422 field_index_in_parent: Some(0),
1423 istate: IState::new(self.frames.len(), FrameMode::OptionNone, FrameFlags::EMPTY),
1424 };
1425 unsafe {
1426 frame.mark_fully_initialized();
1427 }
1428
1429 self.frames.push(frame);
1430
1431 Ok(self)
1432 }
1433
1434 pub fn push_map_key(mut self) -> Result<Self, ReflectError> {
1439 let frame = self.frames.last().unwrap();
1441 let map_shape = frame.shape;
1442
1443 if !matches!(map_shape.def, Def::Map(_)) {
1444 return Err(ReflectError::WasNotA {
1445 expected: "map or hash map",
1446 actual: map_shape,
1447 });
1448 }
1449
1450 if !frame.istate.fields.has(0) {
1452 self = self.begin_map_insert()?;
1453 }
1454
1455 let key_shape = self.key_shape()?;
1457
1458 let key_data = key_shape
1460 .allocate()
1461 .map_err(|_| ReflectError::Unsized { shape: key_shape })?;
1462
1463 let key_frame = Frame {
1465 data: key_data,
1466 shape: key_shape,
1467 field_index_in_parent: None,
1468 istate: IState::new(self.frames.len(), FrameMode::MapKey, FrameFlags::ALLOCATED),
1469 };
1470
1471 trace!(
1472 "[{}] Pushing key of type {} for map {}",
1473 self.frames.len(),
1474 key_shape.green(),
1475 map_shape.blue(),
1476 );
1477
1478 self.frames.push(key_frame);
1479 Ok(self)
1480 }
1481
1482 pub fn push_map_value(mut self) -> Result<Self, ReflectError> {
1487 trace!("Wants to push map value. Frames = ");
1488 #[cfg(feature = "log")]
1489 for (i, f) in self.frames.iter().enumerate() {
1490 trace!("Frame {}: {:?}", i, f);
1491 }
1492
1493 if self.frames.len() < 2 {
1495 return Err(ReflectError::OperationFailed {
1496 shape: <()>::SHAPE,
1497 operation: "tried to push map value but there was no key frame",
1498 });
1499 }
1500
1501 let key_frame_index = self.frames.len() - 1;
1503 let key_frame = &self.frames[key_frame_index];
1504
1505 match key_frame.istate.mode {
1507 FrameMode::MapKey => {} _ => {
1509 return Err(ReflectError::OperationFailed {
1510 shape: key_frame.shape,
1511 operation: "current frame is not a map key",
1512 });
1513 }
1514 }
1515
1516 if !key_frame.is_fully_initialized() {
1518 return Err(ReflectError::OperationFailed {
1519 shape: key_frame.shape,
1520 operation: "map key is not fully initialized",
1521 });
1522 }
1523
1524 let map_frame_index = self.frames.len() - 2;
1526 let map_frame = &self.frames[map_frame_index];
1527 let map_shape = map_frame.shape;
1528
1529 let Def::Map(map_def) = map_shape.def else {
1530 return Err(ReflectError::WasNotA {
1531 expected: "map",
1532 actual: map_frame.shape,
1533 });
1534 };
1535
1536 let value_shape = map_def.v();
1537
1538 let value_data = value_shape
1540 .allocate()
1541 .map_err(|_| ReflectError::Unsized { shape: value_shape })?;
1542
1543 let value_frame = Frame {
1545 data: value_data,
1546 shape: value_shape,
1547 field_index_in_parent: None,
1548 istate: IState::new(
1549 self.frames.len(),
1550 FrameMode::MapValue {
1551 index: key_frame_index,
1552 },
1553 FrameFlags::ALLOCATED,
1554 ),
1555 };
1556
1557 trace!(
1558 "[{}] Pushing value of type {} for map {} with key type {}",
1559 self.frames.len(),
1560 value_shape.green(),
1561 map_shape.blue(),
1562 key_frame.shape.yellow(),
1563 );
1564
1565 self.frames.push(value_frame);
1566 Ok(self)
1567 }
1568
1569 pub(crate) fn evict_tree(&mut self, frame: Frame) -> Frame {
1573 match frame.shape.ty {
1574 Type::User(UserType::Struct(sd)) => {
1575 for f in sd.fields {
1576 let id = ValueId {
1577 shape: f.shape(),
1578 ptr: unsafe { frame.data.field_uninit_at(f.offset) }.as_byte_ptr(),
1579 };
1580 if let Some(istate) = self.istates.remove(&id) {
1581 let frame = Frame::recompose(id, istate);
1582 self.evict_tree(frame);
1583 } else {
1584 trace!("No istate found for field {}", f.name);
1585 }
1586 }
1587 }
1588 Type::User(UserType::Enum(_ed)) => {
1589 if let Some(variant) = &frame.istate.variant {
1591 trace!(
1592 "Evicting enum {} variant '{}' fields",
1593 frame.shape.blue(),
1594 variant.name.yellow()
1595 );
1596 for field in variant.data.fields {
1598 let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
1600 let field_shape = field.shape();
1601 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
1602
1603 if let Some(field_istate) = self.istates.remove(&field_id) {
1605 trace!(
1606 "Evicting field '{}' (shape {}) of enum variant '{}'",
1607 field.name.bright_blue(),
1608 field_shape.green(),
1609 variant.name.yellow()
1610 );
1611 let field_frame = Frame::recompose(field_id, field_istate);
1613 self.evict_tree(field_frame);
1615 } else {
1616 trace!(
1617 "Field '{}' (shape {}) of enum variant '{}' not found in istates, skipping eviction",
1618 field.name.red(),
1619 field_shape.red(),
1620 variant.name.yellow()
1621 );
1622 }
1623 }
1624 } else {
1625 trace!(
1627 "Enum {} has no variant selected, no fields to evict.",
1628 frame.shape.blue()
1629 );
1630 }
1631 }
1632 _ => {}
1633 }
1634 frame
1635 }
1636
1637 #[allow(rustdoc::broken_intra_doc_links)]
1638 pub fn path(&self) -> String {
1641 let mut path = String::from("$");
1642
1643 for (i, frame) in self.frames.iter().enumerate() {
1644 if i == 0 {
1646 continue;
1647 }
1648
1649 match frame.istate.mode {
1650 FrameMode::ListElement => {
1651 if let Some(index) = frame.istate.list_index {
1653 path.push_str(&format!("[{}]", index));
1654 } else {
1655 path.push_str("[?]");
1656 }
1657 }
1658 FrameMode::MapKey => {
1659 path.push_str(".key");
1660 }
1661 FrameMode::MapValue { index: _ } => {
1662 path.push_str(".value");
1663 }
1664 FrameMode::OptionSome => {
1665 path.push_str(".some");
1666 }
1667 FrameMode::OptionNone => {
1668 path.push_str(".none");
1669 }
1670 FrameMode::Root => {
1671 }
1673 FrameMode::Field => {
1674 if let Some(index) = frame.field_index_in_parent {
1676 if let Some(parent) = self.frames.get(i - 1) {
1678 if let Type::User(UserType::Struct(sd)) = parent.shape.ty {
1679 if index < sd.fields.len() {
1680 let field_name = sd.fields[index].name;
1681 path.push('.');
1682 path.push_str(field_name);
1683 }
1684 } else if let Type::User(UserType::Enum(_)) = parent.shape.ty {
1685 if let Some(variant) = &parent.istate.variant {
1686 if index < variant.data.fields.len() {
1687 let field_name = variant.data.fields[index].name;
1688 path.push('.');
1689 path.push_str(field_name);
1690 }
1691 }
1692 }
1693 }
1694 }
1695 }
1696 }
1697 }
1698
1699 path
1700 }
1701
1702 pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError> {
1704 let frame = self.frames.last().ok_or(ReflectError::OperationFailed {
1705 shape: <()>::SHAPE,
1706 operation: "tried to check if field is set, but there was no frame",
1707 })?;
1708
1709 match frame.shape.ty {
1710 Type::User(UserType::Struct(ref sd)) => {
1711 if index >= sd.fields.len() {
1712 return Err(ReflectError::FieldError {
1713 shape: frame.shape,
1714 field_error: FieldError::NoSuchField,
1715 });
1716 }
1717 Ok(frame.istate.fields.has(index))
1718 }
1719 Type::User(UserType::Enum(_)) => {
1720 let variant = frame.istate.variant.as_ref().ok_or(
1721 ReflectError::OperationFailed {
1722 shape: frame.shape,
1723 operation: "tried to check if field is set, but no variant was selected",
1724 },
1725 )?;
1726 if index >= variant.data.fields.len() {
1727 return Err(ReflectError::FieldError {
1728 shape: frame.shape,
1729 field_error: FieldError::NoSuchField,
1730 });
1731 }
1732 Ok(frame.istate.fields.has(index))
1733 }
1734 _ => Err(ReflectError::WasNotA {
1735 expected: "struct or enum",
1736 actual: frame.shape,
1737 }),
1738 }
1739 }
1740}