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
1346 if shape.builder_shape.is_some() && shape.vtable.has_try_from() =>
1347 {
1348 children.push(self.build_node(shape.builder_shape.unwrap())?);
1349 TypePlanNodeKind::Transparent
1350 }
1351 Type::User(UserType::Opaque) | Type::Undefined => TypePlanNodeKind::Opaque,
1353 _ => {
1354 if let Some(inner) = shape.inner {
1356 children.push(self.build_node(inner)?);
1357 TypePlanNodeKind::Transparent
1358 } else {
1359 return Err(AllocError {
1360 shape,
1361 operation: "unsupported type for deserialization",
1362 });
1363 }
1364 }
1365 }
1366 }
1367 };
1368 Ok((kind, children))
1369 }
1370
1371 fn build_struct_plan(
1373 &mut self,
1374 shape: &'static Shape,
1375 struct_def: &'static StructType,
1376 ) -> Result<StructPlan, AllocError> {
1377 let mut field_plans = Vec::with_capacity(struct_def.fields.len());
1378
1379 let container_has_default = shape.is(Characteristic::Default);
1381
1382 for (index, field) in struct_def.fields.iter().enumerate() {
1383 let field_proxies = FieldProxies::from_field(field);
1385 let child_node = self.build_node_with_proxy(field.shape(), field_proxies)?;
1386
1387 let validators = self.extract_validators(field);
1389 let fill_rule = Self::determine_fill_rule(field, container_has_default);
1390
1391 field_plans
1393 .push(self.create_field_plan(index, field, child_node, fill_rule, validators));
1394 }
1395
1396 let has_flatten = field_plans.iter().any(|f| f.is_flattened);
1398 let fields = self.fields.alloc_extend(field_plans.iter().cloned());
1399
1400 let field_lookup = self.build_field_lookup(&field_plans);
1402
1403 let deny_unknown_fields = shape.has_deny_unknown_fields_attr();
1405
1406 Ok(StructPlan {
1407 struct_def,
1408 fields,
1409 field_lookup,
1410 has_flatten,
1411 deny_unknown_fields,
1412 })
1413 }
1414
1415 fn create_field_plan(
1417 &mut self,
1418 index: usize,
1419 field: &'static Field,
1420 type_node: NodeId,
1421 fill_rule: FillRule,
1422 validators: ValidatorRange,
1423 ) -> FieldPlan {
1424 let name = field.name;
1425 let effective_name = field.effective_name();
1426 let alias = field.alias;
1427 let is_flattened = field.is_flattened();
1428
1429 FieldPlan {
1430 field,
1432 name,
1433 effective_name,
1434 alias,
1435 is_flattened,
1436 type_node,
1437 index,
1439 offset: field.offset,
1440 field_shape: field.shape(),
1441 fill_rule,
1442 validators,
1443 }
1444 }
1445
1446 fn build_field_lookup(&mut self, field_plans: &[FieldPlan]) -> FieldLookup {
1448 let mut entries: Vec<FieldLookupEntry> = Vec::with_capacity(field_plans.len() * 2);
1449
1450 for (index, field_plan) in field_plans.iter().enumerate() {
1451 entries.push(FieldLookupEntry {
1453 name: field_plan.effective_name,
1454 index,
1455 is_alias: false,
1456 });
1457
1458 if let Some(alias) = field_plan.alias {
1460 entries.push(FieldLookupEntry {
1461 name: alias,
1462 index,
1463 is_alias: true,
1464 });
1465 }
1466 }
1467
1468 self.build_field_lookup_from_entries(entries)
1469 }
1470
1471 fn build_field_lookup_from_entries(&mut self, entries: Vec<FieldLookupEntry>) -> FieldLookup {
1473 let total_entries = entries.len();
1474 if total_entries <= LOOKUP_THRESHOLD {
1475 return FieldLookup::Small(entries.into_iter().collect());
1476 }
1477
1478 let long_key_count = entries.iter().filter(|e| e.name.len() >= 8).count();
1480 let prefix_len = if long_key_count > total_entries / 2 {
1481 8
1482 } else {
1483 4
1484 };
1485
1486 let mut prefix_map: hashbrown::HashMap<u64, Vec<FieldLookupEntry>> =
1488 hashbrown::HashMap::new();
1489 for entry in entries {
1490 let prefix = compute_prefix(entry.name, prefix_len);
1491 prefix_map.entry(prefix).or_default().push(entry);
1492 }
1493
1494 let mut bucket_list: Vec<_> = prefix_map.into_iter().collect();
1496 bucket_list.sort_by_key(|(prefix, _)| *prefix);
1497
1498 let mut all_entries = Vec::with_capacity(total_entries);
1499 let mut bucket_data = Vec::with_capacity(bucket_list.len());
1500
1501 for (prefix, bucket_entries) in bucket_list {
1502 let start = all_entries.len() as u32;
1503 let count = bucket_entries.len() as u32;
1504 bucket_data.push((prefix, start, count));
1505 all_entries.extend(bucket_entries);
1506 }
1507
1508 let entries_range = self.field_entries.alloc_extend(all_entries);
1510 let buckets_range = self.buckets.alloc_extend(bucket_data);
1511
1512 FieldLookup::PrefixBuckets {
1513 prefix_len,
1514 entries: entries_range,
1515 buckets: buckets_range,
1516 }
1517 }
1518
1519 fn determine_fill_rule(field: &'static Field, container_has_default: bool) -> FillRule {
1521 let field_shape = field.shape();
1522
1523 if let Some(default_source) = field.default_source() {
1525 let field_default = match default_source {
1526 DefaultSource::Custom(f) => FieldDefault::Custom(*f),
1527 DefaultSource::FromTrait => FieldDefault::FromTrait(field_shape),
1528 };
1529 return FillRule::Defaultable(field_default);
1530 }
1531
1532 let is_option = matches!(field_shape.def, Def::Option(_));
1534 if is_option && field_shape.is(Characteristic::Default) {
1535 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1536 }
1537
1538 if field.should_skip_deserializing() && field_shape.is(Characteristic::Default) {
1540 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1541 }
1542
1543 if let Type::User(UserType::Struct(struct_type)) = field_shape.ty
1545 && struct_type.fields.is_empty()
1546 && field_shape.is(Characteristic::Default)
1547 {
1548 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1549 }
1550
1551 if container_has_default && field_shape.is(Characteristic::Default) {
1554 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1555 }
1556
1557 FillRule::Required
1559 }
1560
1561 fn extract_validators(&mut self, field: &'static Field) -> ValidatorRange {
1563 let mut validators = Vec::new();
1564 let field_shape = field.shape();
1565 let scalar_type = field_shape.scalar_type();
1567
1568 for attr in field.attributes.iter() {
1569 if attr.ns != Some("validate") {
1570 continue;
1571 }
1572
1573 let kind = match attr.key {
1574 "custom" => {
1575 let validator_fn = unsafe { *attr.data.ptr().get::<ValidatorFn>() };
1577 ValidatorKind::Custom(validator_fn)
1578 }
1579 "min" => {
1580 let limit = *attr
1581 .get_as::<i64>()
1582 .expect("validate::min attribute must contain i64");
1583 let scalar_type =
1584 scalar_type.expect("validate::min requires numeric field type");
1585 ValidatorKind::Min { limit, scalar_type }
1586 }
1587 "max" => {
1588 let limit = *attr
1589 .get_as::<i64>()
1590 .expect("validate::max attribute must contain i64");
1591 let scalar_type =
1592 scalar_type.expect("validate::max requires numeric field type");
1593 ValidatorKind::Max { limit, scalar_type }
1594 }
1595 "min_length" => {
1596 let limit = *attr
1597 .get_as::<usize>()
1598 .expect("validate::min_length attribute must contain usize");
1599 let scalar_type =
1600 scalar_type.expect("validate::min_length requires string field type");
1601 ValidatorKind::MinLength { limit, scalar_type }
1602 }
1603 "max_length" => {
1604 let limit = *attr
1605 .get_as::<usize>()
1606 .expect("validate::max_length attribute must contain usize");
1607 let scalar_type =
1608 scalar_type.expect("validate::max_length requires string field type");
1609 ValidatorKind::MaxLength { limit, scalar_type }
1610 }
1611 "email" => {
1612 let scalar_type =
1613 scalar_type.expect("validate::email requires string field type");
1614 ValidatorKind::Email { scalar_type }
1615 }
1616 "url" => {
1617 let scalar_type =
1618 scalar_type.expect("validate::url requires string field type");
1619 ValidatorKind::Url { scalar_type }
1620 }
1621 "regex" => {
1622 let pattern = *attr
1623 .get_as::<&'static str>()
1624 .expect("validate::regex attribute must contain &'static str");
1625 let scalar_type =
1626 scalar_type.expect("validate::regex requires string field type");
1627 ValidatorKind::Regex {
1628 pattern,
1629 scalar_type,
1630 }
1631 }
1632 "contains" => {
1633 let needle = *attr
1634 .get_as::<&'static str>()
1635 .expect("validate::contains attribute must contain &'static str");
1636 let scalar_type =
1637 scalar_type.expect("validate::contains requires string field type");
1638 ValidatorKind::Contains {
1639 needle,
1640 scalar_type,
1641 }
1642 }
1643 _ => continue, };
1645
1646 validators.push(PrecomputedValidator { kind });
1647 }
1648
1649 self.validators.alloc_extend(validators)
1650 }
1651
1652 fn build_enum_plan(&mut self, enum_def: &'static EnumType) -> Result<EnumPlan, AllocError> {
1654 let mut variant_metas = Vec::with_capacity(enum_def.variants.len());
1655
1656 for variant in enum_def.variants.iter() {
1657 let mut field_plans = Vec::with_capacity(variant.data.fields.len());
1658
1659 for (index, field) in variant.data.fields.iter().enumerate() {
1660 let field_proxies = FieldProxies::from_field(field);
1662 let child_node = self.build_node_with_proxy(field.shape(), field_proxies)?;
1663
1664 let validators = self.extract_validators(field);
1666 let fill_rule = Self::determine_fill_rule(field, false);
1667
1668 field_plans
1670 .push(self.create_field_plan(index, field, child_node, fill_rule, validators));
1671 }
1672
1673 let has_flatten = field_plans.iter().any(|f| f.is_flattened);
1674 let fields = self.fields.alloc_extend(field_plans.iter().cloned());
1675 let field_lookup = self.build_field_lookup(&field_plans);
1676
1677 variant_metas.push(VariantPlanMeta {
1678 variant,
1679 name: variant.effective_name(),
1680 fields,
1681 field_lookup,
1682 has_flatten,
1683 });
1684 }
1685
1686 let variants = self.variants.alloc_extend(variant_metas.iter().cloned());
1687 let variant_lookup = self.build_variant_lookup(&variant_metas);
1688 let num_variants = variant_metas.len();
1689
1690 let other_variant_idx = variant_metas.iter().position(|v| v.variant.is_other());
1692
1693 Ok(EnumPlan {
1694 enum_def,
1695 variants,
1696 variant_lookup,
1697 num_variants,
1698 other_variant_idx,
1699 })
1700 }
1701
1702 fn build_variant_lookup(&self, variants: &[VariantPlanMeta]) -> VariantLookup {
1709 let entries: Vec<_> = variants
1710 .iter()
1711 .enumerate()
1712 .filter(|(_, v)| !v.variant.is_other())
1713 .map(|(i, v)| (v.name, i))
1714 .collect();
1715
1716 if entries.len() <= LOOKUP_THRESHOLD {
1717 VariantLookup::Small(entries.into_iter().collect())
1718 } else {
1719 let mut sorted = entries;
1720 sorted.sort_by_key(|(name, _)| *name);
1721 VariantLookup::Sorted(sorted)
1722 }
1723 }
1724}
1725
1726impl<'facet, T: facet_core::Facet<'facet> + ?Sized> TypePlan<T> {
1727 pub fn build() -> Result<Self, AllocError> {
1744 let core = unsafe { TypePlanCore::from_shape(T::SHAPE)? };
1746
1747 Ok(TypePlan {
1748 core,
1749 _marker: core::marker::PhantomData,
1750 })
1751 }
1752
1753 #[deprecated(
1761 since = "0.44.0",
1762 note = "format namespace no longer needed at build time; use build() instead"
1763 )]
1764 pub fn build_for_format(_format_namespace: Option<&'static str>) -> Result<Self, AllocError> {
1765 Self::build()
1766 }
1767
1768 #[inline]
1770 pub fn core(&self) -> Arc<TypePlanCore> {
1771 self.core.clone()
1772 }
1773
1774 #[inline]
1776 pub fn root(&self) -> &TypePlanNode {
1777 self.core.root()
1778 }
1779}
1780
1781impl TypePlanCore {
1782 pub unsafe fn from_shape(shape: &'static Shape) -> Result<Arc<Self>, AllocError> {
1793 #[cfg(feature = "std")]
1794 {
1795 let mut guard = type_plan_cache()
1796 .lock()
1797 .unwrap_or_else(|poison| poison.into_inner());
1798
1799 if let Some(plan) = guard.get(&shape) {
1800 return Ok(Arc::clone(plan));
1801 }
1802
1803 let plan = unsafe { Self::build_uncached(shape)? };
1805 guard.insert(shape, Arc::clone(&plan));
1806 Ok(plan)
1807 }
1808
1809 #[cfg(not(feature = "std"))]
1810 {
1811 unsafe { Self::build_uncached(shape) }
1813 }
1814 }
1815
1816 unsafe fn build_uncached(shape: &'static Shape) -> Result<Arc<Self>, AllocError> {
1822 let mut builder = TypePlanBuilder::new();
1823 let root = builder.build_node(shape)?;
1824 Ok(Arc::new(builder.finish(root)))
1825 }
1826
1827 #[inline]
1829 pub fn root(&self) -> &TypePlanNode {
1830 self.node(self.root)
1831 }
1832
1833 #[inline]
1835 pub fn root_id(&self) -> NodeId {
1836 self.root
1837 }
1838
1839 #[inline]
1841 pub fn node(&self, idx: NodeId) -> &TypePlanNode {
1842 self.nodes.get(idx)
1843 }
1844
1845 #[inline]
1847 pub fn field(&self, idx: Idx<FieldPlan>) -> &FieldPlan {
1848 self.fields.get(idx)
1849 }
1850
1851 #[inline]
1853 pub fn fields(&self, range: FieldRange) -> &[FieldPlan] {
1854 self.fields.get_slice(range)
1855 }
1856
1857 #[inline]
1859 pub fn variant(&self, idx: Idx<VariantPlanMeta>) -> &VariantPlanMeta {
1860 self.variants.get(idx)
1861 }
1862
1863 #[inline]
1865 pub fn variants(&self, range: VariantRange) -> &[VariantPlanMeta] {
1866 self.variants.get_slice(range)
1867 }
1868
1869 #[inline]
1871 pub fn validators(&self, range: ValidatorRange) -> &[PrecomputedValidator] {
1872 self.validators.get_slice(range)
1873 }
1874
1875 #[inline]
1877 fn lookup_node(&self, type_id: &ConstTypeId) -> Option<NodeId> {
1878 let idx = self
1879 .node_lookup
1880 .binary_search_by_key(type_id, |(id, _)| *id)
1881 .ok()?;
1882 Some(self.node_lookup[idx].1)
1883 }
1884
1885 #[inline]
1890 pub fn struct_field_node(&self, parent: &TypePlanNode, idx: usize) -> Option<&TypePlanNode> {
1891 let resolved = self.resolve_backref(parent);
1892 let struct_plan = match &resolved.kind {
1893 TypePlanNodeKind::Struct(p) => p,
1894 _ => return None,
1895 };
1896 let fields = self.fields(struct_plan.fields);
1897 Some(self.node(fields.get(idx)?.type_node))
1898 }
1899
1900 #[inline]
1903 pub fn enum_variant_field_node(
1904 &self,
1905 parent: &TypePlanNode,
1906 variant_idx: usize,
1907 field_idx: usize,
1908 ) -> Option<&TypePlanNode> {
1909 let resolved = self.resolve_backref(parent);
1910 let enum_plan = match &resolved.kind {
1911 TypePlanNodeKind::Enum(p) => p,
1912 _ => return None,
1913 };
1914 let variants = self.variants(enum_plan.variants);
1915 let variant = variants.get(variant_idx)?;
1916 let fields = self.fields(variant.fields);
1917 Some(self.node(fields.get(field_idx)?.type_node))
1918 }
1919
1920 #[inline]
1922 pub fn list_item_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1923 match &parent.strategy {
1924 DeserStrategy::List { item_node, .. } | DeserStrategy::Array { item_node, .. } => {
1925 Some(self.node(*item_node))
1926 }
1927 DeserStrategy::BackRef { target_type_id } => {
1928 let target = self.lookup_node(target_type_id)?;
1929 self.list_item_node(self.node(target))
1930 }
1931 _ => None,
1932 }
1933 }
1934
1935 #[inline]
1937 pub fn set_item_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1938 match &parent.strategy {
1939 DeserStrategy::Set { item_node } => Some(self.node(*item_node)),
1940 DeserStrategy::BackRef { target_type_id } => {
1941 let target = self.lookup_node(target_type_id)?;
1942 self.set_item_node(self.node(target))
1943 }
1944 _ => None,
1945 }
1946 }
1947
1948 #[inline]
1950 pub fn map_key_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1951 match &parent.strategy {
1952 DeserStrategy::Map { key_node, .. } => Some(self.node(*key_node)),
1953 DeserStrategy::BackRef { target_type_id } => {
1954 let target = self.lookup_node(target_type_id)?;
1955 self.map_key_node(self.node(target))
1956 }
1957 _ => None,
1958 }
1959 }
1960
1961 #[inline]
1963 pub fn map_value_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1964 match &parent.strategy {
1965 DeserStrategy::Map { value_node, .. } => Some(self.node(*value_node)),
1966 DeserStrategy::BackRef { target_type_id } => {
1967 let target = self.lookup_node(target_type_id)?;
1968 self.map_value_node(self.node(target))
1969 }
1970 _ => None,
1971 }
1972 }
1973
1974 #[inline]
1976 pub fn option_inner_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1977 match &parent.strategy {
1978 DeserStrategy::Option { some_node } => Some(self.node(*some_node)),
1979 DeserStrategy::BackRef { target_type_id } => {
1980 let target = self.lookup_node(target_type_id)?;
1981 self.option_inner_node(self.node(target))
1982 }
1983 _ => None,
1984 }
1985 }
1986
1987 #[inline]
1989 pub fn result_ok_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1990 match &parent.strategy {
1991 DeserStrategy::Result { ok_node, .. } => Some(self.node(*ok_node)),
1992 DeserStrategy::BackRef { target_type_id } => {
1993 let target = self.lookup_node(target_type_id)?;
1994 self.result_ok_node(self.node(target))
1995 }
1996 _ => None,
1997 }
1998 }
1999
2000 #[inline]
2002 pub fn result_err_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2003 match &parent.strategy {
2004 DeserStrategy::Result { err_node, .. } => Some(self.node(*err_node)),
2005 DeserStrategy::BackRef { target_type_id } => {
2006 let target = self.lookup_node(target_type_id)?;
2007 self.result_err_node(self.node(target))
2008 }
2009 _ => None,
2010 }
2011 }
2012
2013 #[inline]
2015 pub fn pointer_pointee_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2016 match &parent.strategy {
2017 DeserStrategy::Pointer { pointee_node } => Some(self.node(*pointee_node)),
2018 DeserStrategy::BackRef { target_type_id } => {
2019 let target = self.lookup_node(target_type_id)?;
2020 self.pointer_pointee_node(self.node(target))
2021 }
2022 _ => None,
2023 }
2024 }
2025
2026 #[inline]
2028 pub fn inner_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2029 if parent.shape.inner.is_some() {
2030 match &parent.strategy {
2031 DeserStrategy::TransparentConvert { inner_node } => Some(self.node(*inner_node)),
2032 _ => None,
2033 }
2034 } else {
2035 None
2036 }
2037 }
2038
2039 #[inline]
2041 pub fn resolve_backref<'a>(&'a self, node: &'a TypePlanNode) -> &'a TypePlanNode {
2042 match &node.kind {
2043 TypePlanNodeKind::BackRef(type_id) => self.node(
2044 self.lookup_node(type_id)
2045 .expect("BackRef target must exist in node_lookup"),
2046 ),
2047 _ => node,
2048 }
2049 }
2050
2051 #[inline]
2054 pub fn as_struct_plan<'a>(&'a self, node: &'a TypePlanNode) -> Option<&'a StructPlan> {
2055 let resolved = self.resolve_backref(node);
2056 match &resolved.kind {
2057 TypePlanNodeKind::Struct(plan) => Some(plan),
2058 _ => None,
2059 }
2060 }
2061
2062 #[inline]
2065 pub fn as_enum_plan<'a>(&'a self, node: &'a TypePlanNode) -> Option<&'a EnumPlan> {
2066 let resolved = self.resolve_backref(node);
2067 match &resolved.kind {
2068 TypePlanNodeKind::Enum(plan) => Some(plan),
2069 _ => None,
2070 }
2071 }
2072
2073 #[inline]
2075 pub fn resolve_backref_id(&self, node_id: NodeId) -> &TypePlanNode {
2076 let node = self.node(node_id);
2077 self.resolve_backref(node)
2078 }
2079
2080 #[inline]
2083 pub fn struct_plan_by_id(&self, node_id: NodeId) -> Option<&StructPlan> {
2084 self.as_struct_plan(self.node(node_id))
2085 }
2086
2087 #[inline]
2090 pub fn enum_plan_by_id(&self, node_id: NodeId) -> Option<&EnumPlan> {
2091 self.as_enum_plan(self.node(node_id))
2092 }
2093
2094 #[inline]
2099 pub fn struct_field_node_id(&self, parent_id: NodeId, idx: usize) -> Option<NodeId> {
2100 let parent = self.node(parent_id);
2101 let resolved = self.resolve_backref(parent);
2102 let struct_plan = match &resolved.kind {
2103 TypePlanNodeKind::Struct(p) => p,
2104 _ => return None,
2105 };
2106 let fields = self.fields(struct_plan.fields);
2107 Some(fields.get(idx)?.type_node)
2108 }
2109
2110 #[inline]
2113 pub fn enum_variant_field_node_id(
2114 &self,
2115 parent_id: NodeId,
2116 variant_idx: usize,
2117 field_idx: usize,
2118 ) -> Option<NodeId> {
2119 let parent = self.node(parent_id);
2120 let resolved = self.resolve_backref(parent);
2121 let enum_plan = match &resolved.kind {
2122 TypePlanNodeKind::Enum(p) => p,
2123 _ => return None,
2124 };
2125 let variants = self.variants(enum_plan.variants);
2126 let variant = variants.get(variant_idx)?;
2127 let fields = self.fields(variant.fields);
2128 Some(fields.get(field_idx)?.type_node)
2129 }
2130
2131 #[inline]
2133 pub fn list_item_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2134 let parent = self.node(parent_id);
2135 match &parent.strategy {
2136 DeserStrategy::List { item_node, .. } | DeserStrategy::Array { item_node, .. } => {
2137 Some(*item_node)
2138 }
2139 DeserStrategy::BackRef { target_type_id } => {
2140 let target = self.lookup_node(target_type_id)?;
2141 self.list_item_node_id(target)
2142 }
2143 _ => None,
2144 }
2145 }
2146
2147 #[inline]
2149 pub fn set_item_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2150 let parent = self.node(parent_id);
2151 match &parent.strategy {
2152 DeserStrategy::Set { item_node } => Some(*item_node),
2153 DeserStrategy::BackRef { target_type_id } => {
2154 let target = self.lookup_node(target_type_id)?;
2155 self.set_item_node_id(target)
2156 }
2157 _ => None,
2158 }
2159 }
2160
2161 #[inline]
2163 pub fn map_key_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2164 let parent = self.node(parent_id);
2165 match &parent.strategy {
2166 DeserStrategy::Map { key_node, .. } => Some(*key_node),
2167 DeserStrategy::BackRef { target_type_id } => {
2168 let target = self.lookup_node(target_type_id)?;
2169 self.map_key_node_id(target)
2170 }
2171 _ => None,
2172 }
2173 }
2174
2175 #[inline]
2177 pub fn map_value_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2178 let parent = self.node(parent_id);
2179 match &parent.strategy {
2180 DeserStrategy::Map { value_node, .. } => Some(*value_node),
2181 DeserStrategy::BackRef { target_type_id } => {
2182 let target = self.lookup_node(target_type_id)?;
2183 self.map_value_node_id(target)
2184 }
2185 _ => None,
2186 }
2187 }
2188
2189 #[inline]
2191 pub fn option_some_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2192 let parent = self.node(parent_id);
2193 match &parent.strategy {
2194 DeserStrategy::Option { some_node, .. } => Some(*some_node),
2195 DeserStrategy::BackRef { target_type_id } => {
2196 let target = self.lookup_node(target_type_id)?;
2197 self.option_some_node_id(target)
2198 }
2199 _ => None,
2200 }
2201 }
2202
2203 #[inline]
2205 pub fn result_nodes_id(&self, parent_id: NodeId) -> Option<(NodeId, NodeId)> {
2206 let parent = self.node(parent_id);
2207 match &parent.strategy {
2208 DeserStrategy::Result {
2209 ok_node, err_node, ..
2210 } => Some((*ok_node, *err_node)),
2211 DeserStrategy::BackRef { target_type_id } => {
2212 let target = self.lookup_node(target_type_id)?;
2213 self.result_nodes_id(target)
2214 }
2215 _ => None,
2216 }
2217 }
2218
2219 #[inline]
2221 pub fn pointer_inner_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2222 let parent = self.node(parent_id);
2223 match &parent.strategy {
2224 DeserStrategy::Pointer { pointee_node, .. } => Some(*pointee_node),
2225 DeserStrategy::BackRef { target_type_id } => {
2226 let target = self.lookup_node(target_type_id)?;
2227 self.pointer_inner_node_id(target)
2228 }
2229 _ => None,
2230 }
2231 }
2232
2233 #[inline]
2235 pub fn inner_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2236 let parent = self.node(parent_id);
2237 if parent.shape.inner.is_some() {
2238 match &parent.strategy {
2239 DeserStrategy::TransparentConvert { inner_node } => Some(*inner_node),
2240 _ => None,
2241 }
2242 } else {
2243 None
2244 }
2245 }
2246
2247 pub(crate) fn empty() -> TypePlanCore {
2248 TypePlanCore {
2249 nodes: Arena::new(),
2250 fields: Arena::new(),
2251 variants: Arena::new(),
2252 validators: Arena::new(),
2253 field_entries: Arena::new(),
2254 buckets: Arena::new(),
2255 node_lookup: Vec::new(),
2256 root: NodeId::new(0),
2257 }
2258 }
2259}
2260
2261#[cfg(test)]
2262mod tests {
2263 use super::*;
2264 use facet::Facet;
2265
2266 #[derive(Facet)]
2267 struct TestStruct {
2268 name: String,
2269 age: u32,
2270 email: Option<String>,
2271 }
2272
2273 #[derive(Facet)]
2274 #[repr(u8)]
2275 #[allow(dead_code)] enum TestEnum {
2277 Unit,
2278 Tuple(u32),
2279 Struct { value: String },
2280 }
2281
2282 #[derive(Facet)]
2283 struct RecursiveStruct {
2284 value: u32,
2285 next: Option<Box<RecursiveStruct>>,
2287 }
2288
2289 #[test]
2290 fn test_typeplan_build_reuses_cached_core() {
2291 #[derive(Facet)]
2292 struct CacheProbe {
2293 value: u32,
2294 }
2295
2296 let first = TypePlan::<CacheProbe>::build().unwrap().core();
2297 let second = TypePlan::<CacheProbe>::build().unwrap().core();
2298 assert!(Arc::ptr_eq(&first, &second));
2299
2300 let third =
2302 unsafe { TypePlanCore::from_shape(<CacheProbe as facet_core::Facet<'static>>::SHAPE) }
2303 .unwrap();
2304 assert!(Arc::ptr_eq(&first, &third));
2305 }
2306
2307 #[test]
2308 fn test_typeplan_struct() {
2309 let plan = TypePlan::<TestStruct>::build().unwrap();
2310 let root = plan.root();
2311 let core = plan.core();
2312
2313 assert_eq!(root.shape, TestStruct::SHAPE);
2314 assert!(!root.has_default);
2315
2316 match &root.kind {
2317 TypePlanNodeKind::Struct(struct_plan) => {
2318 let fields = core.fields(struct_plan.fields);
2319 assert_eq!(fields.len(), 3);
2320 assert!(!struct_plan.has_flatten);
2321
2322 assert_eq!(struct_plan.field_lookup.find("name", &core), Some(0));
2324 assert_eq!(struct_plan.field_lookup.find("age", &core), Some(1));
2325 assert_eq!(struct_plan.field_lookup.find("email", &core), Some(2));
2326 assert_eq!(struct_plan.field_lookup.find("unknown", &core), None);
2327
2328 assert_eq!(fields[0].name, "name");
2330 assert!(fields[0].is_required());
2331
2332 assert_eq!(fields[1].name, "age");
2333 assert!(fields[1].is_required());
2334
2335 assert_eq!(fields[2].name, "email");
2336 assert!(!fields[2].is_required()); let email_node = core.struct_field_node(plan.root(), 2).unwrap();
2340 match &email_node.kind {
2341 TypePlanNodeKind::Option => {
2342 let inner_node = core.option_inner_node(email_node).unwrap();
2344 match &inner_node.kind {
2345 TypePlanNodeKind::Scalar => {}
2346 other => panic!("Expected Scalar for String, got {:?}", other),
2347 }
2348 }
2349 other => panic!("Expected Option, got {:?}", other),
2350 }
2351 }
2352 other => panic!("Expected Struct, got {:?}", other),
2353 }
2354 }
2355
2356 #[test]
2357 fn test_typeplan_enum() {
2358 let plan = TypePlan::<TestEnum>::build().unwrap();
2359 let root = plan.root();
2360 let core = plan.core();
2361
2362 assert_eq!(root.shape, TestEnum::SHAPE);
2363
2364 match &root.kind {
2365 TypePlanNodeKind::Enum(enum_plan) => {
2366 let variants = core.variants(enum_plan.variants);
2367 assert_eq!(enum_plan.num_variants, 3);
2368
2369 assert_eq!(enum_plan.variant_lookup.find("Unit"), Some(0));
2371 assert_eq!(enum_plan.variant_lookup.find("Tuple"), Some(1));
2372 assert_eq!(enum_plan.variant_lookup.find("Struct"), Some(2));
2373 assert_eq!(enum_plan.variant_lookup.find("Unknown"), None);
2374
2375 assert!(core.fields(variants[0].fields).is_empty());
2377
2378 assert_eq!(core.fields(variants[1].fields).len(), 1);
2380
2381 let struct_variant_fields = core.fields(variants[2].fields);
2383 assert_eq!(struct_variant_fields.len(), 1);
2384 assert_eq!(variants[2].field_lookup.find("value", &core), Some(0));
2385 }
2386 other => panic!("Expected Enum, got {:?}", other),
2387 }
2388 }
2389
2390 #[test]
2391 fn test_typeplan_list() {
2392 let plan = TypePlan::<Vec<u32>>::build().unwrap();
2393 let root = plan.root();
2394 let core = plan.core();
2395
2396 match &root.kind {
2397 TypePlanNodeKind::List => {
2398 let item_node = core.list_item_node(plan.root()).unwrap();
2399 match &item_node.kind {
2400 TypePlanNodeKind::Scalar => {}
2401 other => panic!("Expected Scalar for u32, got {:?}", other),
2402 }
2403 }
2404 other => panic!("Expected List, got {:?}", other),
2405 }
2406 }
2407
2408 #[test]
2409 fn test_typeplan_recursive() {
2410 let plan = TypePlan::<RecursiveStruct>::build().unwrap();
2412 let root = plan.root();
2413 let core = plan.core();
2414
2415 match &root.kind {
2416 TypePlanNodeKind::Struct(struct_plan) => {
2417 let fields = core.fields(struct_plan.fields);
2418 assert_eq!(fields.len(), 2);
2419 assert_eq!(fields[0].name, "value");
2420 assert_eq!(fields[1].name, "next");
2421
2422 let next_node = core.struct_field_node(plan.root(), 1).unwrap();
2425
2426 assert!(matches!(next_node.kind, TypePlanNodeKind::Option));
2428
2429 let inner_node = core.option_inner_node(next_node).unwrap();
2431 assert!(matches!(inner_node.kind, TypePlanNodeKind::Pointer));
2432
2433 let pointee_node = core.pointer_pointee_node(inner_node).unwrap();
2435
2436 match &pointee_node.kind {
2438 TypePlanNodeKind::BackRef(type_id) => {
2439 assert_eq!(type_id, &plan.root().shape.id);
2441 }
2442 _ => panic!(
2443 "Expected BackRef for recursive type, got {:?}",
2444 pointee_node.kind
2445 ),
2446 }
2447 }
2448 other => panic!("Expected Struct, got {:?}", other),
2449 }
2450 }
2451
2452 #[test]
2453 fn test_field_lookup_small() {
2454 let lookup = FieldLookup::Small(smallvec::smallvec![
2455 FieldLookupEntry {
2456 name: "foo",
2457 index: 0,
2458 is_alias: false,
2459 },
2460 FieldLookupEntry {
2461 name: "bar",
2462 index: 1,
2463 is_alias: false,
2464 },
2465 FieldLookupEntry {
2466 name: "baz",
2467 index: 2,
2468 is_alias: false,
2469 },
2470 ]);
2471
2472 assert_eq!(lookup.find_small("foo"), Some(0));
2473 assert_eq!(lookup.find_small("bar"), Some(1));
2474 assert_eq!(lookup.find_small("baz"), Some(2));
2475 assert_eq!(lookup.find_small("qux"), None);
2476 }
2477
2478 #[test]
2479 fn test_variant_lookup_small() {
2480 let lookup = VariantLookup::Small(smallvec::smallvec![("A", 0), ("B", 1), ("C", 2)]);
2481
2482 assert_eq!(lookup.find("A"), Some(0));
2483 assert_eq!(lookup.find("B"), Some(1));
2484 assert_eq!(lookup.find("C"), Some(2));
2485 assert_eq!(lookup.find("D"), None);
2486 }
2487}