1use alloc::sync::Arc;
12use alloc::vec::Vec;
13
14use facet_core::{
15 Characteristic, ConstTypeId, Def, DefaultInPlaceFn, DefaultSource, EnumType, Field, ProxyDef,
16 ScalarType, SequenceType, Shape, StructType, Type, UserType, ValidatorFn, Variant,
17};
18use hashbrown::HashMap;
19use smallvec::SmallVec;
20
21use super::arena::{Arena, Idx, SliceRange};
22use crate::AllocError;
23
24#[cfg(feature = "std")]
25#[allow(clippy::std_instead_of_core)]
26fn type_plan_cache() -> &'static std::sync::Mutex<HashMap<&'static Shape, Arc<TypePlanCore>>> {
27 use std::sync::{Mutex, OnceLock};
28
29 static PLAN_CACHE: OnceLock<Mutex<HashMap<&'static Shape, Arc<TypePlanCore>>>> =
30 OnceLock::new();
31 PLAN_CACHE.get_or_init(|| Mutex::new(HashMap::new()))
32}
33
34pub type NodeId = Idx<TypePlanNode>;
36
37pub type FieldRange = SliceRange<FieldPlan>;
39
40pub type VariantRange = SliceRange<VariantPlanMeta>;
42
43pub type ValidatorRange = SliceRange<PrecomputedValidator>;
45
46#[derive(Debug)]
56pub struct TypePlan<T: ?Sized> {
57 core: Arc<TypePlanCore>,
59 _marker: core::marker::PhantomData<fn() -> T>,
61}
62
63#[derive(Debug)]
71pub struct TypePlanCore {
72 nodes: Arena<TypePlanNode>,
74 fields: Arena<FieldPlan>,
76 variants: Arena<VariantPlanMeta>,
78 validators: Arena<PrecomputedValidator>,
80 field_entries: Arena<FieldLookupEntry>,
82 buckets: Arena<(u64, u32, u32)>,
84 node_lookup: Vec<(ConstTypeId, NodeId)>,
86 root: NodeId,
88}
89
90#[derive(Debug)]
92pub struct TypePlanNode {
93 pub shape: &'static Shape,
95 pub kind: TypePlanNodeKind,
97 pub strategy: DeserStrategy,
99 pub has_default: bool,
101 pub proxies: ProxyNodes,
106}
107
108#[derive(Debug, Clone, Default)]
113pub struct ProxyNodes {
114 pub generic: Option<NodeId>,
116 pub format_specific: SmallVec<(&'static str, NodeId), 2>,
119}
120
121impl ProxyNodes {
122 #[inline]
128 pub fn node_for(&self, format: Option<&str>) -> Option<NodeId> {
129 if let Some(fmt) = format {
130 if let Some((_, node)) = self.format_specific.iter().find(|(f, _)| *f == fmt) {
132 return Some(*node);
133 }
134 }
135 self.generic
137 }
138
139 #[inline]
141 pub fn has_any(&self) -> bool {
142 self.generic.is_some() || !self.format_specific.is_empty()
143 }
144
145 #[inline]
147 pub fn is_empty(&self) -> bool {
148 self.generic.is_none() && self.format_specific.is_empty()
149 }
150}
151
152#[derive(Debug, Clone)]
156struct FieldProxies {
157 generic: Option<&'static ProxyDef>,
159 format_specific: SmallVec<(&'static str, &'static ProxyDef), 2>,
161}
162
163impl FieldProxies {
164 fn from_field(field: &'static Field) -> Option<Self> {
166 let generic = field.proxy();
167 let format_specific: SmallVec<_, 2> = field
168 .format_proxies
169 .iter()
170 .map(|fp| (fp.format, fp.proxy))
171 .collect();
172
173 if generic.is_none() && format_specific.is_empty() {
174 None
175 } else {
176 Some(Self {
177 generic,
178 format_specific,
179 })
180 }
181 }
182}
183
184#[derive(Debug)]
189pub enum DeserStrategy {
190 ContainerProxy,
196 FieldProxy,
202 Pointer {
204 pointee_node: NodeId,
206 },
207 OpaquePointer,
209 Opaque,
211 TransparentConvert {
213 inner_node: NodeId,
215 },
216 Scalar {
218 scalar_type: Option<ScalarType>,
221 is_from_str: bool,
223 },
224 Struct,
226 Tuple {
228 field_count: usize,
230 is_single_field_transparent: bool,
232 },
233 Enum,
235 Option {
237 some_node: NodeId,
239 },
240 Result {
242 ok_node: NodeId,
244 err_node: NodeId,
246 },
247 List {
249 item_node: NodeId,
251 is_byte_vec: bool,
253 },
254 Map {
256 key_node: NodeId,
258 value_node: NodeId,
260 },
261 Set {
263 item_node: NodeId,
265 },
266 Array {
268 len: usize,
270 item_node: NodeId,
272 },
273 DynamicValue,
275 MetadataContainer,
278 BackRef {
280 target_type_id: ConstTypeId,
282 },
283}
284
285#[derive(Debug)]
287#[allow(clippy::large_enum_variant)] pub enum TypePlanNodeKind {
289 Scalar,
291
292 Struct(StructPlan),
294
295 Enum(EnumPlan),
297
298 Option,
300
301 Result,
303
304 List,
306
307 Slice,
309
310 Map,
312
313 Set,
315
316 Array {
318 len: usize,
320 },
321
322 Pointer,
324
325 OpaquePointer,
327
328 Opaque,
330
331 DynamicValue,
333
334 Transparent,
336
337 BackRef(ConstTypeId),
340}
341
342#[derive(Debug)]
344pub struct StructPlan {
345 pub struct_def: &'static StructType,
347 pub fields: FieldRange,
350 pub field_lookup: FieldLookup,
352 pub has_flatten: bool,
354 pub deny_unknown_fields: bool,
356}
357
358#[derive(Debug, Clone)]
363pub struct FieldPlan {
364 pub field: &'static Field,
367 pub name: &'static str,
369 pub effective_name: &'static str,
371 pub alias: Option<&'static str>,
373 pub is_flattened: bool,
375 pub type_node: NodeId,
377
378 pub index: usize,
381 pub offset: usize,
383 pub field_shape: &'static Shape,
385 pub fill_rule: FillRule,
387 pub validators: ValidatorRange,
389}
390
391impl FieldPlan {
392 #[inline]
394 pub fn has_default(&self) -> bool {
395 matches!(self.fill_rule, FillRule::Defaultable(_))
396 }
397
398 #[inline]
400 pub fn is_required(&self) -> bool {
401 matches!(self.fill_rule, FillRule::Required)
402 }
403}
404
405pub type FieldInitPlan = FieldPlan;
407
408#[derive(Debug, Clone)]
410pub enum FillRule {
411 Defaultable(FieldDefault),
414 Required,
416}
417
418#[derive(Debug, Clone, Copy)]
420pub enum FieldDefault {
421 Custom(DefaultInPlaceFn),
423 FromTrait(&'static Shape),
426}
427
428#[derive(Debug, Clone)]
430pub struct PrecomputedValidator {
431 pub kind: ValidatorKind,
433}
434
435impl PrecomputedValidator {
436 #[allow(unsafe_code)]
441 pub fn run(
442 &self,
443 field_ptr: facet_core::PtrConst,
444 field_name: &'static str,
445 container_shape: &'static Shape,
446 ) -> Result<(), crate::ReflectErrorKind> {
447 use crate::ReflectErrorKind;
448 use alloc::format;
449
450 let result: Result<(), alloc::string::String> = match self.kind {
451 ValidatorKind::Custom(validator_fn) => {
452 unsafe { validator_fn(field_ptr) }
454 }
455 ValidatorKind::Min { limit, scalar_type } => {
456 Self::validate_min(field_ptr, limit, scalar_type)
457 }
458 ValidatorKind::Max { limit, scalar_type } => {
459 Self::validate_max(field_ptr, limit, scalar_type)
460 }
461 ValidatorKind::MinLength { limit, scalar_type } => {
462 let len = Self::get_string_length(field_ptr, scalar_type);
463 if len < limit {
464 Err(format!("length must be >= {}, got {}", limit, len))
465 } else {
466 Ok(())
467 }
468 }
469 ValidatorKind::MaxLength { limit, scalar_type } => {
470 let len = Self::get_string_length(field_ptr, scalar_type);
471 if len > limit {
472 Err(format!("length must be <= {}, got {}", limit, len))
473 } else {
474 Ok(())
475 }
476 }
477 ValidatorKind::Email { scalar_type } => {
478 let s = unsafe { Self::get_string(field_ptr, scalar_type) };
479 if Self::is_valid_email(s) {
480 Ok(())
481 } else {
482 Err(format!("'{}' is not a valid email address", s))
483 }
484 }
485 ValidatorKind::Url { scalar_type } => {
486 let s = unsafe { Self::get_string(field_ptr, scalar_type) };
487 if Self::is_valid_url(s) {
488 Ok(())
489 } else {
490 Err(format!("'{}' is not a valid URL", s))
491 }
492 }
493 ValidatorKind::Regex {
494 pattern,
495 scalar_type,
496 } => {
497 let s = unsafe { Self::get_string(field_ptr, scalar_type) };
498 if Self::matches_pattern(s, pattern) {
499 Ok(())
500 } else {
501 Err(format!("'{}' does not match pattern '{}'", s, pattern))
502 }
503 }
504 ValidatorKind::Contains {
505 needle,
506 scalar_type,
507 } => {
508 let s = unsafe { Self::get_string(field_ptr, scalar_type) };
509 if s.contains(needle) {
510 Ok(())
511 } else {
512 Err(format!("'{}' does not contain '{}'", s, needle))
513 }
514 }
515 };
516
517 result.map_err(|message| ReflectErrorKind::ValidationFailed {
518 shape: container_shape,
519 field_name,
520 message,
521 })
522 }
523
524 #[allow(unsafe_code)]
525 fn validate_min(
526 field_ptr: facet_core::PtrConst,
527 limit: i64,
528 scalar_type: ScalarType,
529 ) -> Result<(), alloc::string::String> {
530 use alloc::format;
531 match scalar_type {
532 ScalarType::I8 => {
533 let v = unsafe { *field_ptr.get::<i8>() } as i64;
534 if v < limit {
535 Err(format!("must be >= {}, got {}", limit, v))
536 } else {
537 Ok(())
538 }
539 }
540 ScalarType::I16 => {
541 let v = unsafe { *field_ptr.get::<i16>() } as i64;
542 if v < limit {
543 Err(format!("must be >= {}, got {}", limit, v))
544 } else {
545 Ok(())
546 }
547 }
548 ScalarType::I32 => {
549 let v = unsafe { *field_ptr.get::<i32>() } as i64;
550 if v < limit {
551 Err(format!("must be >= {}, got {}", limit, v))
552 } else {
553 Ok(())
554 }
555 }
556 ScalarType::I64 => {
557 let v = unsafe { *field_ptr.get::<i64>() };
558 if v < limit {
559 Err(format!("must be >= {}, got {}", limit, v))
560 } else {
561 Ok(())
562 }
563 }
564 ScalarType::U8 => {
565 let v = unsafe { *field_ptr.get::<u8>() } as i64;
566 if v < limit {
567 Err(format!("must be >= {}, got {}", limit, v))
568 } else {
569 Ok(())
570 }
571 }
572 ScalarType::U16 => {
573 let v = unsafe { *field_ptr.get::<u16>() } as i64;
574 if v < limit {
575 Err(format!("must be >= {}, got {}", limit, v))
576 } else {
577 Ok(())
578 }
579 }
580 ScalarType::U32 => {
581 let v = unsafe { *field_ptr.get::<u32>() } as i64;
582 if v < limit {
583 Err(format!("must be >= {}, got {}", limit, v))
584 } else {
585 Ok(())
586 }
587 }
588 ScalarType::U64 => {
589 let v = unsafe { *field_ptr.get::<u64>() };
590 if v > i64::MAX as u64 {
591 Ok(()) } else if (v as i64) < limit {
593 Err(format!("must be >= {}, got {}", limit, v))
594 } else {
595 Ok(())
596 }
597 }
598 _ => Ok(()), }
600 }
601
602 #[allow(unsafe_code)]
603 fn validate_max(
604 field_ptr: facet_core::PtrConst,
605 limit: i64,
606 scalar_type: ScalarType,
607 ) -> Result<(), alloc::string::String> {
608 use alloc::format;
609 match scalar_type {
610 ScalarType::I8 => {
611 let v = unsafe { *field_ptr.get::<i8>() } as i64;
612 if v > limit {
613 Err(format!("must be <= {}, got {}", limit, v))
614 } else {
615 Ok(())
616 }
617 }
618 ScalarType::I16 => {
619 let v = unsafe { *field_ptr.get::<i16>() } as i64;
620 if v > limit {
621 Err(format!("must be <= {}, got {}", limit, v))
622 } else {
623 Ok(())
624 }
625 }
626 ScalarType::I32 => {
627 let v = unsafe { *field_ptr.get::<i32>() } as i64;
628 if v > limit {
629 Err(format!("must be <= {}, got {}", limit, v))
630 } else {
631 Ok(())
632 }
633 }
634 ScalarType::I64 => {
635 let v = unsafe { *field_ptr.get::<i64>() };
636 if v > limit {
637 Err(format!("must be <= {}, got {}", limit, v))
638 } else {
639 Ok(())
640 }
641 }
642 ScalarType::U8 => {
643 let v = unsafe { *field_ptr.get::<u8>() } as i64;
644 if v > limit {
645 Err(format!("must be <= {}, got {}", limit, v))
646 } else {
647 Ok(())
648 }
649 }
650 ScalarType::U16 => {
651 let v = unsafe { *field_ptr.get::<u16>() } as i64;
652 if v > limit {
653 Err(format!("must be <= {}, got {}", limit, v))
654 } else {
655 Ok(())
656 }
657 }
658 ScalarType::U32 => {
659 let v = unsafe { *field_ptr.get::<u32>() } as i64;
660 if v > limit {
661 Err(format!("must be <= {}, got {}", limit, v))
662 } else {
663 Ok(())
664 }
665 }
666 ScalarType::U64 => {
667 let v = unsafe { *field_ptr.get::<u64>() };
668 if v > i64::MAX as u64 || (v as i64) > limit {
671 Err(format!("must be <= {}, got {}", limit, v))
672 } else {
673 Ok(())
674 }
675 }
676 _ => Ok(()), }
678 }
679
680 #[allow(unsafe_code)]
681 fn get_string_length(field_ptr: facet_core::PtrConst, scalar_type: ScalarType) -> usize {
682 unsafe {
684 match scalar_type {
685 ScalarType::String => (*field_ptr.get::<alloc::string::String>()).len(),
686 ScalarType::CowStr => (*field_ptr.get::<alloc::borrow::Cow<'_, str>>()).len(),
687 _ => 0, }
689 }
690 }
691
692 #[allow(unsafe_code)]
696 unsafe fn get_string(field_ptr: facet_core::PtrConst, scalar_type: ScalarType) -> &'static str {
697 match scalar_type {
702 ScalarType::String => {
703 let s: &str = unsafe { (*field_ptr.get::<alloc::string::String>()).as_str() };
704 unsafe { core::mem::transmute::<&str, &'static str>(s) }
706 }
707 ScalarType::CowStr => {
708 let s: &str = unsafe { (*field_ptr.get::<alloc::borrow::Cow<'_, str>>()).as_ref() };
709 unsafe { core::mem::transmute::<&str, &'static str>(s) }
711 }
712 _ => "", }
714 }
715
716 fn is_valid_email(s: &str) -> bool {
717 let parts: Vec<&str> = s.split('@').collect();
719 parts.len() == 2 && !parts[0].is_empty() && !parts[1].is_empty() && parts[1].contains('.')
720 }
721
722 fn is_valid_url(s: &str) -> bool {
723 s.starts_with("http://") || s.starts_with("https://")
725 }
726
727 fn matches_pattern(s: &str, pattern: &str) -> bool {
728 #[cfg(feature = "regex")]
730 {
731 regex::Regex::new(pattern)
732 .map(|re| re.is_match(s))
733 .unwrap_or(false)
734 }
735 #[cfg(not(feature = "regex"))]
736 {
737 s.contains(pattern)
739 }
740 }
741}
742
743#[derive(Debug, Clone, Copy)]
745pub enum ValidatorKind {
746 Custom(ValidatorFn),
748 Min {
750 limit: i64,
752 scalar_type: ScalarType,
754 },
755 Max {
757 limit: i64,
759 scalar_type: ScalarType,
761 },
762 MinLength {
764 limit: usize,
766 scalar_type: ScalarType,
768 },
769 MaxLength {
771 limit: usize,
773 scalar_type: ScalarType,
775 },
776 Email {
778 scalar_type: ScalarType,
780 },
781 Url {
783 scalar_type: ScalarType,
785 },
786 Regex {
788 pattern: &'static str,
790 scalar_type: ScalarType,
792 },
793 Contains {
795 needle: &'static str,
797 scalar_type: ScalarType,
799 },
800}
801
802#[derive(Debug)]
804pub struct EnumPlan {
805 pub enum_def: &'static EnumType,
807 pub variants: VariantRange,
809 pub variant_lookup: VariantLookup,
811 pub num_variants: usize,
813 pub other_variant_idx: Option<usize>,
815}
816
817#[derive(Debug, Clone)]
819pub struct VariantPlanMeta {
820 pub variant: &'static Variant,
822 pub name: &'static str,
824 pub fields: FieldRange,
826 pub field_lookup: FieldLookup,
828 pub has_flatten: bool,
830}
831
832#[derive(Debug, Clone)]
838#[allow(clippy::large_enum_variant)] pub enum FieldLookup {
840 Small(SmallVec<FieldLookupEntry, 16>),
843 PrefixBuckets {
846 prefix_len: usize,
848 entries: SliceRange<FieldLookupEntry>,
850 buckets: SliceRange<(u64, u32, u32)>,
852 },
853}
854
855#[derive(Debug, Clone)]
857pub struct FieldLookupEntry {
858 pub name: &'static str,
860 pub index: usize,
862 pub is_alias: bool,
864}
865
866#[derive(Debug, Clone)]
868#[allow(clippy::large_enum_variant)] pub enum VariantLookup {
870 Small(SmallVec<(&'static str, usize), 8>),
872 Sorted(Vec<(&'static str, usize)>),
874}
875
876const LOOKUP_THRESHOLD: usize = 8;
878
879#[inline]
882fn compute_prefix(name: &str, prefix_len: usize) -> u64 {
883 let bytes = name.as_bytes();
884 let actual_len = bytes.len().min(prefix_len);
885 let mut prefix: u64 = 0;
886 for (i, &byte) in bytes.iter().take(actual_len).enumerate() {
887 prefix |= (byte as u64) << (i * 8);
888 }
889 prefix
890}
891
892impl FieldLookup {
893 #[inline]
895 pub fn find(&self, name: &str, core: &TypePlanCore) -> Option<usize> {
896 match self {
897 FieldLookup::Small(entries) => entries.iter().find(|e| e.name == name).map(|e| e.index),
898 FieldLookup::PrefixBuckets {
899 prefix_len,
900 entries,
901 buckets,
902 } => {
903 let prefix = compute_prefix(name, *prefix_len);
904
905 let bucket_slice = core.buckets.get_slice(*buckets);
907 let bucket_idx = bucket_slice
908 .binary_search_by_key(&prefix, |(p, _, _)| *p)
909 .ok()?;
910 let (_, start, count) = bucket_slice[bucket_idx];
911
912 let all_entries = core.field_entries.get_slice(*entries);
914 let bucket_entries = &all_entries[start as usize..(start + count) as usize];
915 bucket_entries
916 .iter()
917 .find(|e| e.name == name)
918 .map(|e| e.index)
919 }
920 }
921 }
922
923 #[inline]
926 pub fn find_small(&self, name: &str) -> Option<usize> {
927 match self {
928 FieldLookup::Small(entries) => entries.iter().find(|e| e.name == name).map(|e| e.index),
929 FieldLookup::PrefixBuckets { .. } => {
930 panic!("find_small called on PrefixBuckets - use find() with TypePlanCore")
931 }
932 }
933 }
934
935 #[inline]
937 pub fn is_empty(&self) -> bool {
938 match self {
939 FieldLookup::Small(entries) => entries.is_empty(),
940 FieldLookup::PrefixBuckets { entries, .. } => entries.is_empty(),
941 }
942 }
943}
944
945impl VariantLookup {
946 #[inline]
948 pub fn find(&self, name: &str) -> Option<usize> {
949 match self {
950 VariantLookup::Small(entries) => {
951 entries.iter().find(|(n, _)| *n == name).map(|(_, i)| *i)
952 }
953 VariantLookup::Sorted(entries) => entries
954 .binary_search_by_key(&name, |(n, _)| *n)
955 .ok()
956 .map(|i| entries[i].1),
957 }
958 }
959}
960
961struct TypePlanBuilder {
963 nodes: Arena<TypePlanNode>,
965 fields: Arena<FieldPlan>,
967 variants: Arena<VariantPlanMeta>,
969 validators: Arena<PrecomputedValidator>,
971 field_entries: Arena<FieldLookupEntry>,
973 buckets: Arena<(u64, u32, u32)>,
975 building: hashbrown::HashSet<ConstTypeId>,
978 finished: HashMap<ConstTypeId, NodeId>,
981}
982
983impl TypePlanBuilder {
984 fn new() -> Self {
985 Self {
986 nodes: Arena::new(),
987 fields: Arena::new(),
988 variants: Arena::new(),
989 validators: Arena::new(),
990 field_entries: Arena::new(),
991 buckets: Arena::new(),
992 building: hashbrown::HashSet::new(),
993 finished: HashMap::new(),
994 }
995 }
996
997 fn finish(self, root: NodeId) -> TypePlanCore {
999 let mut node_lookup: Vec<_> = self.finished.into_iter().collect();
1000 node_lookup.sort_by_key(|(id, _)| *id);
1001
1002 TypePlanCore {
1003 nodes: self.nodes,
1004 fields: self.fields,
1005 variants: self.variants,
1006 validators: self.validators,
1007 field_entries: self.field_entries,
1008 buckets: self.buckets,
1009 node_lookup,
1010 root,
1011 }
1012 }
1013
1014 fn build_node(&mut self, shape: &'static Shape) -> Result<NodeId, AllocError> {
1017 self.build_node_with_proxy(shape, None)
1020 }
1021
1022 fn build_node_with_proxy(
1025 &mut self,
1026 shape: &'static Shape,
1027 field_proxies: Option<FieldProxies>,
1028 ) -> Result<NodeId, AllocError> {
1029 let type_id = shape.id;
1030
1031 if self.building.contains(&type_id) {
1033 let backref_node = TypePlanNode {
1035 shape,
1036 kind: TypePlanNodeKind::BackRef(type_id),
1037 strategy: DeserStrategy::BackRef {
1038 target_type_id: type_id,
1039 },
1040 has_default: shape.is(Characteristic::Default),
1041 proxies: ProxyNodes::default(), };
1043 let idx = self.nodes.alloc(backref_node);
1044 return Ok(idx);
1045 }
1046
1047 self.building.insert(type_id);
1049
1050 let (proxies, has_container_proxy, has_field_proxy) =
1052 self.build_all_proxy_nodes(shape, field_proxies.as_ref())?;
1053
1054 let (kind, children) = self.build_kind(shape)?;
1055
1056 let strategy = self.compute_strategy(
1057 shape,
1058 &kind,
1059 has_container_proxy,
1060 has_field_proxy,
1061 &children,
1062 )?;
1063
1064 let node = TypePlanNode {
1066 shape,
1067 kind,
1068 strategy,
1069 has_default: shape.is(Characteristic::Default),
1070 proxies,
1071 };
1072 let idx = self.nodes.alloc(node);
1073
1074 self.building.remove(&type_id);
1076 self.finished.insert(type_id, idx);
1077
1078 Ok(idx)
1079 }
1080
1081 fn build_all_proxy_nodes(
1085 &mut self,
1086 shape: &'static Shape,
1087 field_proxies: Option<&FieldProxies>,
1088 ) -> Result<(ProxyNodes, bool, bool), AllocError> {
1089 let mut proxies = ProxyNodes::default();
1090
1091 if let Some(fp) = field_proxies {
1093 if let Some(generic_proxy) = fp.generic {
1095 proxies.generic = Some(self.build_node(generic_proxy.shape)?);
1096 }
1097 for &(format, proxy_def) in fp.format_specific.iter() {
1098 let node = self.build_node(proxy_def.shape)?;
1099 proxies.format_specific.push((format, node));
1100 }
1101 let has_field_proxy = proxies.has_any();
1102 return Ok((proxies, false, has_field_proxy));
1103 }
1104
1105 if let Some(generic_proxy) = shape.proxy {
1108 proxies.generic = Some(self.build_node(generic_proxy.shape)?);
1109 }
1110
1111 for format_proxy in shape.format_proxies.iter() {
1113 let node = self.build_node(format_proxy.proxy.shape)?;
1114 proxies.format_specific.push((format_proxy.format, node));
1115 }
1116
1117 let has_container_proxy = proxies.has_any();
1118 Ok((proxies, has_container_proxy, false))
1119 }
1120
1121 fn compute_strategy(
1123 &self,
1124 shape: &'static Shape,
1125 kind: &TypePlanNodeKind,
1126 has_container_proxy: bool,
1127 has_field_proxy: bool,
1128 children: &[NodeId],
1129 ) -> Result<DeserStrategy, AllocError> {
1130 let nth_child = |n: usize| -> NodeId { children[n] };
1131 let first_child = || children[0];
1132
1133 if has_field_proxy {
1135 return Ok(DeserStrategy::FieldProxy);
1136 }
1137
1138 if has_container_proxy {
1140 return Ok(DeserStrategy::ContainerProxy);
1141 }
1142
1143 if matches!(kind, TypePlanNodeKind::Pointer) {
1145 return Ok(DeserStrategy::Pointer {
1146 pointee_node: first_child(),
1147 });
1148 }
1149
1150 if shape.is_metadata_container() {
1152 return Ok(DeserStrategy::MetadataContainer);
1153 }
1154
1155 if shape.inner.is_some()
1157 && shape.vtable.has_try_from()
1158 && !matches!(
1159 &shape.def,
1160 Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
1161 )
1162 {
1163 return Ok(DeserStrategy::TransparentConvert {
1164 inner_node: first_child(),
1165 });
1166 }
1167
1168 if matches!(kind, TypePlanNodeKind::Transparent) && shape.vtable.has_try_from() {
1170 return Ok(DeserStrategy::TransparentConvert {
1171 inner_node: first_child(),
1172 });
1173 }
1174
1175 if matches!(&shape.def, Def::Scalar) && shape.vtable.has_parse() {
1177 return Ok(DeserStrategy::Scalar {
1178 scalar_type: shape.scalar_type(),
1179 is_from_str: shape.vtable.has_parse(),
1180 });
1181 }
1182
1183 Ok(match kind {
1185 TypePlanNodeKind::Scalar => {
1186 if let Type::User(UserType::Struct(struct_def)) = &shape.ty {
1188 use facet_core::StructKind;
1189 if matches!(struct_def.kind, StructKind::Tuple | StructKind::TupleStruct) {
1190 let field_count = struct_def.fields.len();
1191 return Ok(DeserStrategy::Tuple {
1192 field_count,
1193 is_single_field_transparent: field_count == 1 && shape.is_transparent(),
1194 });
1195 }
1196 }
1197 DeserStrategy::Scalar {
1198 scalar_type: shape.scalar_type(),
1199 is_from_str: shape.vtable.has_parse(),
1200 }
1201 }
1202 TypePlanNodeKind::Struct(struct_plan) => {
1203 use facet_core::StructKind;
1204 match struct_plan.struct_def.kind {
1205 StructKind::Tuple | StructKind::TupleStruct => {
1206 let field_count = struct_plan.struct_def.fields.len();
1207 DeserStrategy::Tuple {
1208 field_count,
1209 is_single_field_transparent: field_count == 1 && shape.is_transparent(),
1210 }
1211 }
1212 StructKind::Struct | StructKind::Unit => DeserStrategy::Struct,
1213 }
1214 }
1215 TypePlanNodeKind::Enum(_) => DeserStrategy::Enum,
1216 TypePlanNodeKind::Option => DeserStrategy::Option {
1217 some_node: first_child(),
1218 },
1219 TypePlanNodeKind::Result => DeserStrategy::Result {
1220 ok_node: nth_child(0),
1221 err_node: nth_child(1),
1222 },
1223 TypePlanNodeKind::List | TypePlanNodeKind::Slice => {
1224 let is_byte_vec = *shape == *<alloc::vec::Vec<u8> as facet_core::Facet>::SHAPE;
1226 DeserStrategy::List {
1227 item_node: first_child(),
1228 is_byte_vec,
1229 }
1230 }
1231 TypePlanNodeKind::Map => DeserStrategy::Map {
1232 key_node: nth_child(0),
1233 value_node: nth_child(1),
1234 },
1235 TypePlanNodeKind::Set => DeserStrategy::Set {
1236 item_node: first_child(),
1237 },
1238 TypePlanNodeKind::Array { len } => DeserStrategy::Array {
1239 len: *len,
1240 item_node: first_child(),
1241 },
1242 TypePlanNodeKind::DynamicValue => DeserStrategy::DynamicValue,
1243 TypePlanNodeKind::Pointer => DeserStrategy::Pointer {
1244 pointee_node: first_child(),
1245 },
1246 TypePlanNodeKind::OpaquePointer => DeserStrategy::OpaquePointer,
1247 TypePlanNodeKind::Opaque => DeserStrategy::Opaque,
1248 TypePlanNodeKind::Transparent => {
1249 return Err(AllocError {
1251 shape,
1252 operation: "transparent wrapper requires try_from for deserialization",
1253 });
1254 }
1255 TypePlanNodeKind::BackRef(type_id) => DeserStrategy::BackRef {
1256 target_type_id: *type_id,
1257 },
1258 })
1259 }
1260
1261 fn build_kind(
1263 &mut self,
1264 shape: &'static Shape,
1265 ) -> Result<(TypePlanNodeKind, Vec<NodeId>), AllocError> {
1266 let mut children = Vec::new();
1267
1268 let kind = match &shape.def {
1270 Def::Scalar => {
1271 if let Some(inner_shape) = shape.inner {
1275 children.push(self.build_node(inner_shape)?);
1276 }
1277 TypePlanNodeKind::Scalar
1278 }
1279
1280 Def::Option(opt_def) => {
1281 children.push(self.build_node(opt_def.t())?);
1282 TypePlanNodeKind::Option
1283 }
1284
1285 Def::Result(res_def) => {
1286 children.push(self.build_node(res_def.t())?);
1287 children.push(self.build_node(res_def.e())?);
1288 TypePlanNodeKind::Result
1289 }
1290
1291 Def::List(list_def) => {
1292 children.push(self.build_node(list_def.t())?);
1293 TypePlanNodeKind::List
1294 }
1295
1296 Def::Map(map_def) => {
1297 children.push(self.build_node(map_def.k())?);
1298 children.push(self.build_node(map_def.v())?);
1299 TypePlanNodeKind::Map
1300 }
1301
1302 Def::Set(set_def) => {
1303 children.push(self.build_node(set_def.t())?);
1304 TypePlanNodeKind::Set
1305 }
1306
1307 Def::Array(arr_def) => {
1308 children.push(self.build_node(arr_def.t())?);
1309 TypePlanNodeKind::Array { len: arr_def.n }
1310 }
1311
1312 Def::Pointer(ptr_def) => {
1313 if let Some(pointee) = ptr_def.pointee() {
1314 children.push(self.build_node(pointee)?);
1315 TypePlanNodeKind::Pointer
1316 } else {
1317 TypePlanNodeKind::OpaquePointer
1319 }
1320 }
1321
1322 Def::DynamicValue(_) => TypePlanNodeKind::DynamicValue,
1323
1324 _ => {
1325 match &shape.ty {
1327 Type::User(UserType::Struct(struct_type)) => {
1328 let struct_plan = self.build_struct_plan(shape, struct_type)?;
1329 return Ok((TypePlanNodeKind::Struct(struct_plan), Vec::new()));
1331 }
1332 Type::User(UserType::Enum(enum_type)) => {
1333 TypePlanNodeKind::Enum(self.build_enum_plan(enum_type)?)
1335 }
1336 Type::Sequence(SequenceType::Slice(slice_type)) => {
1338 children.push(self.build_node(slice_type.t)?);
1339 TypePlanNodeKind::Slice
1341 }
1342 Type::User(UserType::Opaque) | Type::Undefined => TypePlanNodeKind::Opaque,
1344 _ => {
1345 if let Some(inner) = shape.inner {
1347 children.push(self.build_node(inner)?);
1348 TypePlanNodeKind::Transparent
1349 } else {
1350 return Err(AllocError {
1351 shape,
1352 operation: "unsupported type for deserialization",
1353 });
1354 }
1355 }
1356 }
1357 }
1358 };
1359 Ok((kind, children))
1360 }
1361
1362 fn build_struct_plan(
1364 &mut self,
1365 shape: &'static Shape,
1366 struct_def: &'static StructType,
1367 ) -> Result<StructPlan, AllocError> {
1368 let mut field_plans = Vec::with_capacity(struct_def.fields.len());
1369
1370 let container_has_default = shape.is(Characteristic::Default);
1372
1373 for (index, field) in struct_def.fields.iter().enumerate() {
1374 let field_proxies = FieldProxies::from_field(field);
1376 let child_node = self.build_node_with_proxy(field.shape(), field_proxies)?;
1377
1378 let validators = self.extract_validators(field);
1380 let fill_rule = Self::determine_fill_rule(field, container_has_default);
1381
1382 field_plans
1384 .push(self.create_field_plan(index, field, child_node, fill_rule, validators));
1385 }
1386
1387 let has_flatten = field_plans.iter().any(|f| f.is_flattened);
1389 let fields = self.fields.alloc_extend(field_plans.iter().cloned());
1390
1391 let field_lookup = self.build_field_lookup(&field_plans);
1393
1394 let deny_unknown_fields = shape.has_deny_unknown_fields_attr();
1396
1397 Ok(StructPlan {
1398 struct_def,
1399 fields,
1400 field_lookup,
1401 has_flatten,
1402 deny_unknown_fields,
1403 })
1404 }
1405
1406 fn create_field_plan(
1408 &mut self,
1409 index: usize,
1410 field: &'static Field,
1411 type_node: NodeId,
1412 fill_rule: FillRule,
1413 validators: ValidatorRange,
1414 ) -> FieldPlan {
1415 let name = field.name;
1416 let effective_name = field.effective_name();
1417 let alias = field.alias;
1418 let is_flattened = field.is_flattened();
1419
1420 FieldPlan {
1421 field,
1423 name,
1424 effective_name,
1425 alias,
1426 is_flattened,
1427 type_node,
1428 index,
1430 offset: field.offset,
1431 field_shape: field.shape(),
1432 fill_rule,
1433 validators,
1434 }
1435 }
1436
1437 fn build_field_lookup(&mut self, field_plans: &[FieldPlan]) -> FieldLookup {
1439 let mut entries: Vec<FieldLookupEntry> = Vec::with_capacity(field_plans.len() * 2);
1440
1441 for (index, field_plan) in field_plans.iter().enumerate() {
1442 entries.push(FieldLookupEntry {
1444 name: field_plan.effective_name,
1445 index,
1446 is_alias: false,
1447 });
1448
1449 if let Some(alias) = field_plan.alias {
1451 entries.push(FieldLookupEntry {
1452 name: alias,
1453 index,
1454 is_alias: true,
1455 });
1456 }
1457 }
1458
1459 self.build_field_lookup_from_entries(entries)
1460 }
1461
1462 fn build_field_lookup_from_entries(&mut self, entries: Vec<FieldLookupEntry>) -> FieldLookup {
1464 let total_entries = entries.len();
1465 if total_entries <= LOOKUP_THRESHOLD {
1466 return FieldLookup::Small(entries.into_iter().collect());
1467 }
1468
1469 let long_key_count = entries.iter().filter(|e| e.name.len() >= 8).count();
1471 let prefix_len = if long_key_count > total_entries / 2 {
1472 8
1473 } else {
1474 4
1475 };
1476
1477 let mut prefix_map: hashbrown::HashMap<u64, Vec<FieldLookupEntry>> =
1479 hashbrown::HashMap::new();
1480 for entry in entries {
1481 let prefix = compute_prefix(entry.name, prefix_len);
1482 prefix_map.entry(prefix).or_default().push(entry);
1483 }
1484
1485 let mut bucket_list: Vec<_> = prefix_map.into_iter().collect();
1487 bucket_list.sort_by_key(|(prefix, _)| *prefix);
1488
1489 let mut all_entries = Vec::with_capacity(total_entries);
1490 let mut bucket_data = Vec::with_capacity(bucket_list.len());
1491
1492 for (prefix, bucket_entries) in bucket_list {
1493 let start = all_entries.len() as u32;
1494 let count = bucket_entries.len() as u32;
1495 bucket_data.push((prefix, start, count));
1496 all_entries.extend(bucket_entries);
1497 }
1498
1499 let entries_range = self.field_entries.alloc_extend(all_entries);
1501 let buckets_range = self.buckets.alloc_extend(bucket_data);
1502
1503 FieldLookup::PrefixBuckets {
1504 prefix_len,
1505 entries: entries_range,
1506 buckets: buckets_range,
1507 }
1508 }
1509
1510 fn determine_fill_rule(field: &'static Field, container_has_default: bool) -> FillRule {
1512 let field_shape = field.shape();
1513
1514 if let Some(default_source) = field.default_source() {
1516 let field_default = match default_source {
1517 DefaultSource::Custom(f) => FieldDefault::Custom(*f),
1518 DefaultSource::FromTrait => FieldDefault::FromTrait(field_shape),
1519 };
1520 return FillRule::Defaultable(field_default);
1521 }
1522
1523 let is_option = matches!(field_shape.def, Def::Option(_));
1525 if is_option && field_shape.is(Characteristic::Default) {
1526 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1527 }
1528
1529 if field.should_skip_deserializing() && field_shape.is(Characteristic::Default) {
1531 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1532 }
1533
1534 if let Type::User(UserType::Struct(struct_type)) = field_shape.ty
1536 && struct_type.fields.is_empty()
1537 && field_shape.is(Characteristic::Default)
1538 {
1539 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1540 }
1541
1542 if container_has_default && field_shape.is(Characteristic::Default) {
1545 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1546 }
1547
1548 FillRule::Required
1550 }
1551
1552 fn extract_validators(&mut self, field: &'static Field) -> ValidatorRange {
1554 let mut validators = Vec::new();
1555 let field_shape = field.shape();
1556 let scalar_type = field_shape.scalar_type();
1558
1559 for attr in field.attributes.iter() {
1560 if attr.ns != Some("validate") {
1561 continue;
1562 }
1563
1564 let kind = match attr.key {
1565 "custom" => {
1566 let validator_fn = unsafe { *attr.data.ptr().get::<ValidatorFn>() };
1568 ValidatorKind::Custom(validator_fn)
1569 }
1570 "min" => {
1571 let limit = *attr
1572 .get_as::<i64>()
1573 .expect("validate::min attribute must contain i64");
1574 let scalar_type =
1575 scalar_type.expect("validate::min requires numeric field type");
1576 ValidatorKind::Min { limit, scalar_type }
1577 }
1578 "max" => {
1579 let limit = *attr
1580 .get_as::<i64>()
1581 .expect("validate::max attribute must contain i64");
1582 let scalar_type =
1583 scalar_type.expect("validate::max requires numeric field type");
1584 ValidatorKind::Max { limit, scalar_type }
1585 }
1586 "min_length" => {
1587 let limit = *attr
1588 .get_as::<usize>()
1589 .expect("validate::min_length attribute must contain usize");
1590 let scalar_type =
1591 scalar_type.expect("validate::min_length requires string field type");
1592 ValidatorKind::MinLength { limit, scalar_type }
1593 }
1594 "max_length" => {
1595 let limit = *attr
1596 .get_as::<usize>()
1597 .expect("validate::max_length attribute must contain usize");
1598 let scalar_type =
1599 scalar_type.expect("validate::max_length requires string field type");
1600 ValidatorKind::MaxLength { limit, scalar_type }
1601 }
1602 "email" => {
1603 let scalar_type =
1604 scalar_type.expect("validate::email requires string field type");
1605 ValidatorKind::Email { scalar_type }
1606 }
1607 "url" => {
1608 let scalar_type =
1609 scalar_type.expect("validate::url requires string field type");
1610 ValidatorKind::Url { scalar_type }
1611 }
1612 "regex" => {
1613 let pattern = *attr
1614 .get_as::<&'static str>()
1615 .expect("validate::regex attribute must contain &'static str");
1616 let scalar_type =
1617 scalar_type.expect("validate::regex requires string field type");
1618 ValidatorKind::Regex {
1619 pattern,
1620 scalar_type,
1621 }
1622 }
1623 "contains" => {
1624 let needle = *attr
1625 .get_as::<&'static str>()
1626 .expect("validate::contains attribute must contain &'static str");
1627 let scalar_type =
1628 scalar_type.expect("validate::contains requires string field type");
1629 ValidatorKind::Contains {
1630 needle,
1631 scalar_type,
1632 }
1633 }
1634 _ => continue, };
1636
1637 validators.push(PrecomputedValidator { kind });
1638 }
1639
1640 self.validators.alloc_extend(validators)
1641 }
1642
1643 fn build_enum_plan(&mut self, enum_def: &'static EnumType) -> Result<EnumPlan, AllocError> {
1645 let mut variant_metas = Vec::with_capacity(enum_def.variants.len());
1646
1647 for variant in enum_def.variants.iter() {
1648 let mut field_plans = Vec::with_capacity(variant.data.fields.len());
1649
1650 for (index, field) in variant.data.fields.iter().enumerate() {
1651 let field_proxies = FieldProxies::from_field(field);
1653 let child_node = self.build_node_with_proxy(field.shape(), field_proxies)?;
1654
1655 let validators = self.extract_validators(field);
1657 let fill_rule = Self::determine_fill_rule(field, false);
1658
1659 field_plans
1661 .push(self.create_field_plan(index, field, child_node, fill_rule, validators));
1662 }
1663
1664 let has_flatten = field_plans.iter().any(|f| f.is_flattened);
1665 let fields = self.fields.alloc_extend(field_plans.iter().cloned());
1666 let field_lookup = self.build_field_lookup(&field_plans);
1667
1668 variant_metas.push(VariantPlanMeta {
1669 variant,
1670 name: variant.effective_name(),
1671 fields,
1672 field_lookup,
1673 has_flatten,
1674 });
1675 }
1676
1677 let variants = self.variants.alloc_extend(variant_metas.iter().cloned());
1678 let variant_lookup = self.build_variant_lookup(&variant_metas);
1679 let num_variants = variant_metas.len();
1680
1681 let other_variant_idx = variant_metas.iter().position(|v| v.variant.is_other());
1683
1684 Ok(EnumPlan {
1685 enum_def,
1686 variants,
1687 variant_lookup,
1688 num_variants,
1689 other_variant_idx,
1690 })
1691 }
1692
1693 fn build_variant_lookup(&self, variants: &[VariantPlanMeta]) -> VariantLookup {
1700 let entries: Vec<_> = variants
1701 .iter()
1702 .enumerate()
1703 .filter(|(_, v)| !v.variant.is_other())
1704 .map(|(i, v)| (v.name, i))
1705 .collect();
1706
1707 if entries.len() <= LOOKUP_THRESHOLD {
1708 VariantLookup::Small(entries.into_iter().collect())
1709 } else {
1710 let mut sorted = entries;
1711 sorted.sort_by_key(|(name, _)| *name);
1712 VariantLookup::Sorted(sorted)
1713 }
1714 }
1715}
1716
1717impl<'facet, T: facet_core::Facet<'facet> + ?Sized> TypePlan<T> {
1718 pub fn build() -> Result<Self, AllocError> {
1735 let core = unsafe { TypePlanCore::from_shape(T::SHAPE)? };
1737
1738 Ok(TypePlan {
1739 core,
1740 _marker: core::marker::PhantomData,
1741 })
1742 }
1743
1744 #[deprecated(
1752 since = "0.44.0",
1753 note = "format namespace no longer needed at build time; use build() instead"
1754 )]
1755 pub fn build_for_format(_format_namespace: Option<&'static str>) -> Result<Self, AllocError> {
1756 Self::build()
1757 }
1758
1759 #[inline]
1761 pub fn core(&self) -> Arc<TypePlanCore> {
1762 self.core.clone()
1763 }
1764
1765 #[inline]
1767 pub fn root(&self) -> &TypePlanNode {
1768 self.core.root()
1769 }
1770}
1771
1772impl TypePlanCore {
1773 pub unsafe fn from_shape(shape: &'static Shape) -> Result<Arc<Self>, AllocError> {
1784 #[cfg(feature = "std")]
1785 {
1786 let mut guard = type_plan_cache()
1787 .lock()
1788 .unwrap_or_else(|poison| poison.into_inner());
1789
1790 if let Some(plan) = guard.get(&shape) {
1791 return Ok(Arc::clone(plan));
1792 }
1793
1794 let plan = unsafe { Self::build_uncached(shape)? };
1796 guard.insert(shape, Arc::clone(&plan));
1797 Ok(plan)
1798 }
1799
1800 #[cfg(not(feature = "std"))]
1801 {
1802 unsafe { Self::build_uncached(shape) }
1804 }
1805 }
1806
1807 unsafe fn build_uncached(shape: &'static Shape) -> Result<Arc<Self>, AllocError> {
1813 let mut builder = TypePlanBuilder::new();
1814 let root = builder.build_node(shape)?;
1815 Ok(Arc::new(builder.finish(root)))
1816 }
1817
1818 #[inline]
1820 pub fn root(&self) -> &TypePlanNode {
1821 self.node(self.root)
1822 }
1823
1824 #[inline]
1826 pub fn root_id(&self) -> NodeId {
1827 self.root
1828 }
1829
1830 #[inline]
1832 pub fn node(&self, idx: NodeId) -> &TypePlanNode {
1833 self.nodes.get(idx)
1834 }
1835
1836 #[inline]
1838 pub fn field(&self, idx: Idx<FieldPlan>) -> &FieldPlan {
1839 self.fields.get(idx)
1840 }
1841
1842 #[inline]
1844 pub fn fields(&self, range: FieldRange) -> &[FieldPlan] {
1845 self.fields.get_slice(range)
1846 }
1847
1848 #[inline]
1850 pub fn variant(&self, idx: Idx<VariantPlanMeta>) -> &VariantPlanMeta {
1851 self.variants.get(idx)
1852 }
1853
1854 #[inline]
1856 pub fn variants(&self, range: VariantRange) -> &[VariantPlanMeta] {
1857 self.variants.get_slice(range)
1858 }
1859
1860 #[inline]
1862 pub fn validators(&self, range: ValidatorRange) -> &[PrecomputedValidator] {
1863 self.validators.get_slice(range)
1864 }
1865
1866 #[inline]
1868 fn lookup_node(&self, type_id: &ConstTypeId) -> Option<NodeId> {
1869 let idx = self
1870 .node_lookup
1871 .binary_search_by_key(type_id, |(id, _)| *id)
1872 .ok()?;
1873 Some(self.node_lookup[idx].1)
1874 }
1875
1876 #[inline]
1881 pub fn struct_field_node(&self, parent: &TypePlanNode, idx: usize) -> Option<&TypePlanNode> {
1882 let resolved = self.resolve_backref(parent);
1883 let struct_plan = match &resolved.kind {
1884 TypePlanNodeKind::Struct(p) => p,
1885 _ => return None,
1886 };
1887 let fields = self.fields(struct_plan.fields);
1888 Some(self.node(fields.get(idx)?.type_node))
1889 }
1890
1891 #[inline]
1894 pub fn enum_variant_field_node(
1895 &self,
1896 parent: &TypePlanNode,
1897 variant_idx: usize,
1898 field_idx: usize,
1899 ) -> Option<&TypePlanNode> {
1900 let resolved = self.resolve_backref(parent);
1901 let enum_plan = match &resolved.kind {
1902 TypePlanNodeKind::Enum(p) => p,
1903 _ => return None,
1904 };
1905 let variants = self.variants(enum_plan.variants);
1906 let variant = variants.get(variant_idx)?;
1907 let fields = self.fields(variant.fields);
1908 Some(self.node(fields.get(field_idx)?.type_node))
1909 }
1910
1911 #[inline]
1913 pub fn list_item_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1914 match &parent.strategy {
1915 DeserStrategy::List { item_node, .. } | DeserStrategy::Array { item_node, .. } => {
1916 Some(self.node(*item_node))
1917 }
1918 DeserStrategy::BackRef { target_type_id } => {
1919 let target = self.lookup_node(target_type_id)?;
1920 self.list_item_node(self.node(target))
1921 }
1922 _ => None,
1923 }
1924 }
1925
1926 #[inline]
1928 pub fn set_item_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1929 match &parent.strategy {
1930 DeserStrategy::Set { item_node } => Some(self.node(*item_node)),
1931 DeserStrategy::BackRef { target_type_id } => {
1932 let target = self.lookup_node(target_type_id)?;
1933 self.set_item_node(self.node(target))
1934 }
1935 _ => None,
1936 }
1937 }
1938
1939 #[inline]
1941 pub fn map_key_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1942 match &parent.strategy {
1943 DeserStrategy::Map { key_node, .. } => Some(self.node(*key_node)),
1944 DeserStrategy::BackRef { target_type_id } => {
1945 let target = self.lookup_node(target_type_id)?;
1946 self.map_key_node(self.node(target))
1947 }
1948 _ => None,
1949 }
1950 }
1951
1952 #[inline]
1954 pub fn map_value_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1955 match &parent.strategy {
1956 DeserStrategy::Map { value_node, .. } => Some(self.node(*value_node)),
1957 DeserStrategy::BackRef { target_type_id } => {
1958 let target = self.lookup_node(target_type_id)?;
1959 self.map_value_node(self.node(target))
1960 }
1961 _ => None,
1962 }
1963 }
1964
1965 #[inline]
1967 pub fn option_inner_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1968 match &parent.strategy {
1969 DeserStrategy::Option { some_node } => Some(self.node(*some_node)),
1970 DeserStrategy::BackRef { target_type_id } => {
1971 let target = self.lookup_node(target_type_id)?;
1972 self.option_inner_node(self.node(target))
1973 }
1974 _ => None,
1975 }
1976 }
1977
1978 #[inline]
1980 pub fn result_ok_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1981 match &parent.strategy {
1982 DeserStrategy::Result { ok_node, .. } => Some(self.node(*ok_node)),
1983 DeserStrategy::BackRef { target_type_id } => {
1984 let target = self.lookup_node(target_type_id)?;
1985 self.result_ok_node(self.node(target))
1986 }
1987 _ => None,
1988 }
1989 }
1990
1991 #[inline]
1993 pub fn result_err_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1994 match &parent.strategy {
1995 DeserStrategy::Result { err_node, .. } => Some(self.node(*err_node)),
1996 DeserStrategy::BackRef { target_type_id } => {
1997 let target = self.lookup_node(target_type_id)?;
1998 self.result_err_node(self.node(target))
1999 }
2000 _ => None,
2001 }
2002 }
2003
2004 #[inline]
2006 pub fn pointer_pointee_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2007 match &parent.strategy {
2008 DeserStrategy::Pointer { pointee_node } => Some(self.node(*pointee_node)),
2009 DeserStrategy::BackRef { target_type_id } => {
2010 let target = self.lookup_node(target_type_id)?;
2011 self.pointer_pointee_node(self.node(target))
2012 }
2013 _ => None,
2014 }
2015 }
2016
2017 #[inline]
2019 pub fn inner_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2020 if parent.shape.inner.is_some() {
2021 match &parent.strategy {
2022 DeserStrategy::TransparentConvert { inner_node } => Some(self.node(*inner_node)),
2023 _ => None,
2024 }
2025 } else {
2026 None
2027 }
2028 }
2029
2030 #[inline]
2032 pub fn resolve_backref<'a>(&'a self, node: &'a TypePlanNode) -> &'a TypePlanNode {
2033 match &node.kind {
2034 TypePlanNodeKind::BackRef(type_id) => self.node(
2035 self.lookup_node(type_id)
2036 .expect("BackRef target must exist in node_lookup"),
2037 ),
2038 _ => node,
2039 }
2040 }
2041
2042 #[inline]
2045 pub fn as_struct_plan<'a>(&'a self, node: &'a TypePlanNode) -> Option<&'a StructPlan> {
2046 let resolved = self.resolve_backref(node);
2047 match &resolved.kind {
2048 TypePlanNodeKind::Struct(plan) => Some(plan),
2049 _ => None,
2050 }
2051 }
2052
2053 #[inline]
2056 pub fn as_enum_plan<'a>(&'a self, node: &'a TypePlanNode) -> Option<&'a EnumPlan> {
2057 let resolved = self.resolve_backref(node);
2058 match &resolved.kind {
2059 TypePlanNodeKind::Enum(plan) => Some(plan),
2060 _ => None,
2061 }
2062 }
2063
2064 #[inline]
2066 pub fn resolve_backref_id(&self, node_id: NodeId) -> &TypePlanNode {
2067 let node = self.node(node_id);
2068 self.resolve_backref(node)
2069 }
2070
2071 #[inline]
2074 pub fn struct_plan_by_id(&self, node_id: NodeId) -> Option<&StructPlan> {
2075 self.as_struct_plan(self.node(node_id))
2076 }
2077
2078 #[inline]
2081 pub fn enum_plan_by_id(&self, node_id: NodeId) -> Option<&EnumPlan> {
2082 self.as_enum_plan(self.node(node_id))
2083 }
2084
2085 #[inline]
2090 pub fn struct_field_node_id(&self, parent_id: NodeId, idx: usize) -> Option<NodeId> {
2091 let parent = self.node(parent_id);
2092 let resolved = self.resolve_backref(parent);
2093 let struct_plan = match &resolved.kind {
2094 TypePlanNodeKind::Struct(p) => p,
2095 _ => return None,
2096 };
2097 let fields = self.fields(struct_plan.fields);
2098 Some(fields.get(idx)?.type_node)
2099 }
2100
2101 #[inline]
2104 pub fn enum_variant_field_node_id(
2105 &self,
2106 parent_id: NodeId,
2107 variant_idx: usize,
2108 field_idx: usize,
2109 ) -> Option<NodeId> {
2110 let parent = self.node(parent_id);
2111 let resolved = self.resolve_backref(parent);
2112 let enum_plan = match &resolved.kind {
2113 TypePlanNodeKind::Enum(p) => p,
2114 _ => return None,
2115 };
2116 let variants = self.variants(enum_plan.variants);
2117 let variant = variants.get(variant_idx)?;
2118 let fields = self.fields(variant.fields);
2119 Some(fields.get(field_idx)?.type_node)
2120 }
2121
2122 #[inline]
2124 pub fn list_item_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2125 let parent = self.node(parent_id);
2126 match &parent.strategy {
2127 DeserStrategy::List { item_node, .. } | DeserStrategy::Array { item_node, .. } => {
2128 Some(*item_node)
2129 }
2130 DeserStrategy::BackRef { target_type_id } => {
2131 let target = self.lookup_node(target_type_id)?;
2132 self.list_item_node_id(target)
2133 }
2134 _ => None,
2135 }
2136 }
2137
2138 #[inline]
2140 pub fn set_item_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2141 let parent = self.node(parent_id);
2142 match &parent.strategy {
2143 DeserStrategy::Set { item_node } => Some(*item_node),
2144 DeserStrategy::BackRef { target_type_id } => {
2145 let target = self.lookup_node(target_type_id)?;
2146 self.set_item_node_id(target)
2147 }
2148 _ => None,
2149 }
2150 }
2151
2152 #[inline]
2154 pub fn map_key_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2155 let parent = self.node(parent_id);
2156 match &parent.strategy {
2157 DeserStrategy::Map { key_node, .. } => Some(*key_node),
2158 DeserStrategy::BackRef { target_type_id } => {
2159 let target = self.lookup_node(target_type_id)?;
2160 self.map_key_node_id(target)
2161 }
2162 _ => None,
2163 }
2164 }
2165
2166 #[inline]
2168 pub fn map_value_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2169 let parent = self.node(parent_id);
2170 match &parent.strategy {
2171 DeserStrategy::Map { value_node, .. } => Some(*value_node),
2172 DeserStrategy::BackRef { target_type_id } => {
2173 let target = self.lookup_node(target_type_id)?;
2174 self.map_value_node_id(target)
2175 }
2176 _ => None,
2177 }
2178 }
2179
2180 #[inline]
2182 pub fn option_some_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2183 let parent = self.node(parent_id);
2184 match &parent.strategy {
2185 DeserStrategy::Option { some_node, .. } => Some(*some_node),
2186 DeserStrategy::BackRef { target_type_id } => {
2187 let target = self.lookup_node(target_type_id)?;
2188 self.option_some_node_id(target)
2189 }
2190 _ => None,
2191 }
2192 }
2193
2194 #[inline]
2196 pub fn result_nodes_id(&self, parent_id: NodeId) -> Option<(NodeId, NodeId)> {
2197 let parent = self.node(parent_id);
2198 match &parent.strategy {
2199 DeserStrategy::Result {
2200 ok_node, err_node, ..
2201 } => Some((*ok_node, *err_node)),
2202 DeserStrategy::BackRef { target_type_id } => {
2203 let target = self.lookup_node(target_type_id)?;
2204 self.result_nodes_id(target)
2205 }
2206 _ => None,
2207 }
2208 }
2209
2210 #[inline]
2212 pub fn pointer_inner_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2213 let parent = self.node(parent_id);
2214 match &parent.strategy {
2215 DeserStrategy::Pointer { pointee_node, .. } => Some(*pointee_node),
2216 DeserStrategy::BackRef { target_type_id } => {
2217 let target = self.lookup_node(target_type_id)?;
2218 self.pointer_inner_node_id(target)
2219 }
2220 _ => None,
2221 }
2222 }
2223
2224 #[inline]
2226 pub fn inner_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2227 let parent = self.node(parent_id);
2228 if parent.shape.inner.is_some() {
2229 match &parent.strategy {
2230 DeserStrategy::TransparentConvert { inner_node } => Some(*inner_node),
2231 _ => None,
2232 }
2233 } else {
2234 None
2235 }
2236 }
2237
2238 pub(crate) fn empty() -> TypePlanCore {
2239 TypePlanCore {
2240 nodes: Arena::new(),
2241 fields: Arena::new(),
2242 variants: Arena::new(),
2243 validators: Arena::new(),
2244 field_entries: Arena::new(),
2245 buckets: Arena::new(),
2246 node_lookup: Vec::new(),
2247 root: NodeId::new(0),
2248 }
2249 }
2250}
2251
2252#[cfg(test)]
2253mod tests {
2254 use super::*;
2255 use facet::Facet;
2256
2257 #[derive(Facet)]
2258 struct TestStruct {
2259 name: String,
2260 age: u32,
2261 email: Option<String>,
2262 }
2263
2264 #[derive(Facet)]
2265 #[repr(u8)]
2266 #[allow(dead_code)] enum TestEnum {
2268 Unit,
2269 Tuple(u32),
2270 Struct { value: String },
2271 }
2272
2273 #[derive(Facet)]
2274 struct RecursiveStruct {
2275 value: u32,
2276 next: Option<Box<RecursiveStruct>>,
2278 }
2279
2280 #[test]
2281 fn test_typeplan_build_reuses_cached_core() {
2282 #[derive(Facet)]
2283 struct CacheProbe {
2284 value: u32,
2285 }
2286
2287 let first = TypePlan::<CacheProbe>::build().unwrap().core();
2288 let second = TypePlan::<CacheProbe>::build().unwrap().core();
2289 assert!(Arc::ptr_eq(&first, &second));
2290
2291 let third =
2293 unsafe { TypePlanCore::from_shape(<CacheProbe as facet_core::Facet<'static>>::SHAPE) }
2294 .unwrap();
2295 assert!(Arc::ptr_eq(&first, &third));
2296 }
2297
2298 #[test]
2299 fn test_typeplan_struct() {
2300 let plan = TypePlan::<TestStruct>::build().unwrap();
2301 let root = plan.root();
2302 let core = plan.core();
2303
2304 assert_eq!(root.shape, TestStruct::SHAPE);
2305 assert!(!root.has_default);
2306
2307 match &root.kind {
2308 TypePlanNodeKind::Struct(struct_plan) => {
2309 let fields = core.fields(struct_plan.fields);
2310 assert_eq!(fields.len(), 3);
2311 assert!(!struct_plan.has_flatten);
2312
2313 assert_eq!(struct_plan.field_lookup.find("name", &core), Some(0));
2315 assert_eq!(struct_plan.field_lookup.find("age", &core), Some(1));
2316 assert_eq!(struct_plan.field_lookup.find("email", &core), Some(2));
2317 assert_eq!(struct_plan.field_lookup.find("unknown", &core), None);
2318
2319 assert_eq!(fields[0].name, "name");
2321 assert!(fields[0].is_required());
2322
2323 assert_eq!(fields[1].name, "age");
2324 assert!(fields[1].is_required());
2325
2326 assert_eq!(fields[2].name, "email");
2327 assert!(!fields[2].is_required()); let email_node = core.struct_field_node(plan.root(), 2).unwrap();
2331 match &email_node.kind {
2332 TypePlanNodeKind::Option => {
2333 let inner_node = core.option_inner_node(email_node).unwrap();
2335 match &inner_node.kind {
2336 TypePlanNodeKind::Scalar => {}
2337 other => panic!("Expected Scalar for String, got {:?}", other),
2338 }
2339 }
2340 other => panic!("Expected Option, got {:?}", other),
2341 }
2342 }
2343 other => panic!("Expected Struct, got {:?}", other),
2344 }
2345 }
2346
2347 #[test]
2348 fn test_typeplan_enum() {
2349 let plan = TypePlan::<TestEnum>::build().unwrap();
2350 let root = plan.root();
2351 let core = plan.core();
2352
2353 assert_eq!(root.shape, TestEnum::SHAPE);
2354
2355 match &root.kind {
2356 TypePlanNodeKind::Enum(enum_plan) => {
2357 let variants = core.variants(enum_plan.variants);
2358 assert_eq!(enum_plan.num_variants, 3);
2359
2360 assert_eq!(enum_plan.variant_lookup.find("Unit"), Some(0));
2362 assert_eq!(enum_plan.variant_lookup.find("Tuple"), Some(1));
2363 assert_eq!(enum_plan.variant_lookup.find("Struct"), Some(2));
2364 assert_eq!(enum_plan.variant_lookup.find("Unknown"), None);
2365
2366 assert!(core.fields(variants[0].fields).is_empty());
2368
2369 assert_eq!(core.fields(variants[1].fields).len(), 1);
2371
2372 let struct_variant_fields = core.fields(variants[2].fields);
2374 assert_eq!(struct_variant_fields.len(), 1);
2375 assert_eq!(variants[2].field_lookup.find("value", &core), Some(0));
2376 }
2377 other => panic!("Expected Enum, got {:?}", other),
2378 }
2379 }
2380
2381 #[test]
2382 fn test_typeplan_list() {
2383 let plan = TypePlan::<Vec<u32>>::build().unwrap();
2384 let root = plan.root();
2385 let core = plan.core();
2386
2387 match &root.kind {
2388 TypePlanNodeKind::List => {
2389 let item_node = core.list_item_node(plan.root()).unwrap();
2390 match &item_node.kind {
2391 TypePlanNodeKind::Scalar => {}
2392 other => panic!("Expected Scalar for u32, got {:?}", other),
2393 }
2394 }
2395 other => panic!("Expected List, got {:?}", other),
2396 }
2397 }
2398
2399 #[test]
2400 fn test_typeplan_recursive() {
2401 let plan = TypePlan::<RecursiveStruct>::build().unwrap();
2403 let root = plan.root();
2404 let core = plan.core();
2405
2406 match &root.kind {
2407 TypePlanNodeKind::Struct(struct_plan) => {
2408 let fields = core.fields(struct_plan.fields);
2409 assert_eq!(fields.len(), 2);
2410 assert_eq!(fields[0].name, "value");
2411 assert_eq!(fields[1].name, "next");
2412
2413 let next_node = core.struct_field_node(plan.root(), 1).unwrap();
2416
2417 assert!(matches!(next_node.kind, TypePlanNodeKind::Option));
2419
2420 let inner_node = core.option_inner_node(next_node).unwrap();
2422 assert!(matches!(inner_node.kind, TypePlanNodeKind::Pointer));
2423
2424 let pointee_node = core.pointer_pointee_node(inner_node).unwrap();
2426
2427 match &pointee_node.kind {
2429 TypePlanNodeKind::BackRef(type_id) => {
2430 assert_eq!(type_id, &plan.root().shape.id);
2432 }
2433 _ => panic!(
2434 "Expected BackRef for recursive type, got {:?}",
2435 pointee_node.kind
2436 ),
2437 }
2438 }
2439 other => panic!("Expected Struct, got {:?}", other),
2440 }
2441 }
2442
2443 #[test]
2444 fn test_field_lookup_small() {
2445 let lookup = FieldLookup::Small(smallvec::smallvec![
2446 FieldLookupEntry {
2447 name: "foo",
2448 index: 0,
2449 is_alias: false,
2450 },
2451 FieldLookupEntry {
2452 name: "bar",
2453 index: 1,
2454 is_alias: false,
2455 },
2456 FieldLookupEntry {
2457 name: "baz",
2458 index: 2,
2459 is_alias: false,
2460 },
2461 ]);
2462
2463 assert_eq!(lookup.find_small("foo"), Some(0));
2464 assert_eq!(lookup.find_small("bar"), Some(1));
2465 assert_eq!(lookup.find_small("baz"), Some(2));
2466 assert_eq!(lookup.find_small("qux"), None);
2467 }
2468
2469 #[test]
2470 fn test_variant_lookup_small() {
2471 let lookup = VariantLookup::Small(smallvec::smallvec![("A", 0), ("B", 1), ("C", 2)]);
2472
2473 assert_eq!(lookup.find("A"), Some(0));
2474 assert_eq!(lookup.find("B"), Some(1));
2475 assert_eq!(lookup.find("C"), Some(2));
2476 assert_eq!(lookup.find("D"), None);
2477 }
2478}