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 field_proxies.is_none()
1035 && let Some(&idx) = self.finished.get(&type_id)
1036 {
1037 return Ok(idx);
1038 }
1039
1040 if self.building.contains(&type_id) {
1042 let backref_node = TypePlanNode {
1044 shape,
1045 kind: TypePlanNodeKind::BackRef(type_id),
1046 strategy: DeserStrategy::BackRef {
1047 target_type_id: type_id,
1048 },
1049 has_default: shape.is(Characteristic::Default),
1050 proxies: ProxyNodes::default(), };
1052 let idx = self.nodes.alloc(backref_node);
1053 return Ok(idx);
1054 }
1055
1056 self.building.insert(type_id);
1058
1059 let (proxies, has_container_proxy, has_field_proxy) =
1061 self.build_all_proxy_nodes(shape, field_proxies.as_ref())?;
1062
1063 let (kind, children) = self.build_kind(shape)?;
1064
1065 let strategy = self.compute_strategy(
1066 shape,
1067 &kind,
1068 has_container_proxy,
1069 has_field_proxy,
1070 &children,
1071 )?;
1072
1073 let node = TypePlanNode {
1075 shape,
1076 kind,
1077 strategy,
1078 has_default: shape.is(Characteristic::Default),
1079 proxies,
1080 };
1081 let idx = self.nodes.alloc(node);
1082
1083 self.building.remove(&type_id);
1085 self.finished.insert(type_id, idx);
1086
1087 Ok(idx)
1088 }
1089
1090 fn build_all_proxy_nodes(
1094 &mut self,
1095 shape: &'static Shape,
1096 field_proxies: Option<&FieldProxies>,
1097 ) -> Result<(ProxyNodes, bool, bool), AllocError> {
1098 let mut proxies = ProxyNodes::default();
1099
1100 if let Some(fp) = field_proxies {
1102 if let Some(generic_proxy) = fp.generic {
1104 proxies.generic = Some(self.build_node(generic_proxy.shape)?);
1105 }
1106 for &(format, proxy_def) in fp.format_specific.iter() {
1107 let node = self.build_node(proxy_def.shape)?;
1108 proxies.format_specific.push((format, node));
1109 }
1110 let has_field_proxy = proxies.has_any();
1111 return Ok((proxies, false, has_field_proxy));
1112 }
1113
1114 if let Some(generic_proxy) = shape.proxy {
1117 proxies.generic = Some(self.build_node(generic_proxy.shape)?);
1118 }
1119
1120 for format_proxy in shape.format_proxies.iter() {
1122 let node = self.build_node(format_proxy.proxy.shape)?;
1123 proxies.format_specific.push((format_proxy.format, node));
1124 }
1125
1126 let has_container_proxy = proxies.has_any();
1127 Ok((proxies, has_container_proxy, false))
1128 }
1129
1130 fn compute_strategy(
1132 &self,
1133 shape: &'static Shape,
1134 kind: &TypePlanNodeKind,
1135 has_container_proxy: bool,
1136 has_field_proxy: bool,
1137 children: &[NodeId],
1138 ) -> Result<DeserStrategy, AllocError> {
1139 let nth_child = |n: usize| -> NodeId { children[n] };
1140 let first_child = || children[0];
1141
1142 if has_field_proxy {
1144 return Ok(DeserStrategy::FieldProxy);
1145 }
1146
1147 if has_container_proxy {
1149 return Ok(DeserStrategy::ContainerProxy);
1150 }
1151
1152 if matches!(kind, TypePlanNodeKind::Pointer) {
1154 return Ok(DeserStrategy::Pointer {
1155 pointee_node: first_child(),
1156 });
1157 }
1158
1159 if shape.is_metadata_container() {
1161 return Ok(DeserStrategy::MetadataContainer);
1162 }
1163
1164 if shape.inner.is_some()
1166 && shape.vtable.has_try_from()
1167 && !matches!(
1168 &shape.def,
1169 Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
1170 )
1171 {
1172 return Ok(DeserStrategy::TransparentConvert {
1173 inner_node: first_child(),
1174 });
1175 }
1176
1177 if matches!(kind, TypePlanNodeKind::Transparent) && shape.vtable.has_try_from() {
1179 return Ok(DeserStrategy::TransparentConvert {
1180 inner_node: first_child(),
1181 });
1182 }
1183
1184 if matches!(&shape.def, Def::Scalar) && shape.vtable.has_parse() {
1186 return Ok(DeserStrategy::Scalar {
1187 scalar_type: shape.scalar_type(),
1188 is_from_str: shape.vtable.has_parse(),
1189 });
1190 }
1191
1192 Ok(match kind {
1194 TypePlanNodeKind::Scalar => {
1195 if let Type::User(UserType::Struct(struct_def)) = &shape.ty {
1197 use facet_core::StructKind;
1198 if matches!(struct_def.kind, StructKind::Tuple | StructKind::TupleStruct) {
1199 let field_count = struct_def.fields.len();
1200 return Ok(DeserStrategy::Tuple {
1201 field_count,
1202 is_single_field_transparent: field_count == 1 && shape.is_transparent(),
1203 });
1204 }
1205 }
1206 DeserStrategy::Scalar {
1207 scalar_type: shape.scalar_type(),
1208 is_from_str: shape.vtable.has_parse(),
1209 }
1210 }
1211 TypePlanNodeKind::Struct(struct_plan) => {
1212 use facet_core::StructKind;
1213 match struct_plan.struct_def.kind {
1214 StructKind::Tuple | StructKind::TupleStruct => {
1215 let field_count = struct_plan.struct_def.fields.len();
1216 DeserStrategy::Tuple {
1217 field_count,
1218 is_single_field_transparent: field_count == 1 && shape.is_transparent(),
1219 }
1220 }
1221 StructKind::Struct | StructKind::Unit => DeserStrategy::Struct,
1222 }
1223 }
1224 TypePlanNodeKind::Enum(_) => DeserStrategy::Enum,
1225 TypePlanNodeKind::Option => DeserStrategy::Option {
1226 some_node: first_child(),
1227 },
1228 TypePlanNodeKind::Result => DeserStrategy::Result {
1229 ok_node: nth_child(0),
1230 err_node: nth_child(1),
1231 },
1232 TypePlanNodeKind::List | TypePlanNodeKind::Slice => {
1233 let is_byte_vec = *shape == *<alloc::vec::Vec<u8> as facet_core::Facet>::SHAPE;
1235 DeserStrategy::List {
1236 item_node: first_child(),
1237 is_byte_vec,
1238 }
1239 }
1240 TypePlanNodeKind::Map => DeserStrategy::Map {
1241 key_node: nth_child(0),
1242 value_node: nth_child(1),
1243 },
1244 TypePlanNodeKind::Set => DeserStrategy::Set {
1245 item_node: first_child(),
1246 },
1247 TypePlanNodeKind::Array { len } => DeserStrategy::Array {
1248 len: *len,
1249 item_node: first_child(),
1250 },
1251 TypePlanNodeKind::DynamicValue => DeserStrategy::DynamicValue,
1252 TypePlanNodeKind::Pointer => DeserStrategy::Pointer {
1253 pointee_node: first_child(),
1254 },
1255 TypePlanNodeKind::OpaquePointer => DeserStrategy::OpaquePointer,
1256 TypePlanNodeKind::Opaque => DeserStrategy::Opaque,
1257 TypePlanNodeKind::Transparent => {
1258 return Err(AllocError {
1260 shape,
1261 operation: "transparent wrapper requires try_from for deserialization",
1262 });
1263 }
1264 TypePlanNodeKind::BackRef(type_id) => DeserStrategy::BackRef {
1265 target_type_id: *type_id,
1266 },
1267 })
1268 }
1269
1270 fn build_kind(
1272 &mut self,
1273 shape: &'static Shape,
1274 ) -> Result<(TypePlanNodeKind, Vec<NodeId>), AllocError> {
1275 let mut children = Vec::new();
1276
1277 let kind = match &shape.def {
1279 Def::Scalar => {
1280 if let Some(inner_shape) = shape.inner {
1284 children.push(self.build_node(inner_shape)?);
1285 }
1286 TypePlanNodeKind::Scalar
1287 }
1288
1289 Def::Option(opt_def) => {
1290 children.push(self.build_node(opt_def.t())?);
1291 TypePlanNodeKind::Option
1292 }
1293
1294 Def::Result(res_def) => {
1295 children.push(self.build_node(res_def.t())?);
1296 children.push(self.build_node(res_def.e())?);
1297 TypePlanNodeKind::Result
1298 }
1299
1300 Def::List(list_def) => {
1301 children.push(self.build_node(list_def.t())?);
1302 TypePlanNodeKind::List
1303 }
1304
1305 Def::Map(map_def) => {
1306 children.push(self.build_node(map_def.k())?);
1307 children.push(self.build_node(map_def.v())?);
1308 TypePlanNodeKind::Map
1309 }
1310
1311 Def::Set(set_def) => {
1312 children.push(self.build_node(set_def.t())?);
1313 TypePlanNodeKind::Set
1314 }
1315
1316 Def::Array(arr_def) => {
1317 children.push(self.build_node(arr_def.t())?);
1318 TypePlanNodeKind::Array { len: arr_def.n }
1319 }
1320
1321 Def::Pointer(ptr_def) => {
1322 if let Some(pointee) = ptr_def.pointee() {
1323 children.push(self.build_node(pointee)?);
1324 TypePlanNodeKind::Pointer
1325 } else {
1326 TypePlanNodeKind::OpaquePointer
1328 }
1329 }
1330
1331 Def::DynamicValue(_) => TypePlanNodeKind::DynamicValue,
1332
1333 _ => {
1334 match &shape.ty {
1336 Type::User(UserType::Struct(struct_type)) => {
1337 let struct_plan = self.build_struct_plan(shape, struct_type)?;
1338 return Ok((TypePlanNodeKind::Struct(struct_plan), Vec::new()));
1340 }
1341 Type::User(UserType::Enum(enum_type)) => {
1342 TypePlanNodeKind::Enum(self.build_enum_plan(enum_type)?)
1344 }
1345 Type::Sequence(SequenceType::Slice(slice_type)) => {
1347 children.push(self.build_node(slice_type.t)?);
1348 TypePlanNodeKind::Slice
1350 }
1351 Type::User(UserType::Opaque) | Type::Undefined
1355 if shape.builder_shape.is_some() && shape.vtable.has_try_from() =>
1356 {
1357 children.push(self.build_node(shape.builder_shape.unwrap())?);
1358 TypePlanNodeKind::Transparent
1359 }
1360 Type::User(UserType::Opaque) | Type::Undefined => TypePlanNodeKind::Opaque,
1362 _ => {
1363 if let Some(inner) = shape.inner {
1365 children.push(self.build_node(inner)?);
1366 TypePlanNodeKind::Transparent
1367 } else {
1368 return Err(AllocError {
1369 shape,
1370 operation: "unsupported type for deserialization",
1371 });
1372 }
1373 }
1374 }
1375 }
1376 };
1377 Ok((kind, children))
1378 }
1379
1380 fn build_struct_plan(
1382 &mut self,
1383 shape: &'static Shape,
1384 struct_def: &'static StructType,
1385 ) -> Result<StructPlan, AllocError> {
1386 let mut field_plans = Vec::with_capacity(struct_def.fields.len());
1387
1388 let container_has_default = shape.is(Characteristic::Default);
1390
1391 for (index, field) in struct_def.fields.iter().enumerate() {
1392 let field_proxies = FieldProxies::from_field(field);
1394 let child_node = self.build_node_with_proxy(field.shape(), field_proxies)?;
1395
1396 let validators = self.extract_validators(field);
1398 let fill_rule = Self::determine_fill_rule(field, container_has_default);
1399
1400 field_plans
1402 .push(self.create_field_plan(index, field, child_node, fill_rule, validators));
1403 }
1404
1405 let has_flatten = field_plans.iter().any(|f| f.is_flattened);
1407 let fields = self.fields.alloc_extend(field_plans.iter().cloned());
1408
1409 let field_lookup = self.build_field_lookup(&field_plans);
1411
1412 let deny_unknown_fields = shape.has_deny_unknown_fields_attr();
1414
1415 Ok(StructPlan {
1416 struct_def,
1417 fields,
1418 field_lookup,
1419 has_flatten,
1420 deny_unknown_fields,
1421 })
1422 }
1423
1424 fn create_field_plan(
1426 &mut self,
1427 index: usize,
1428 field: &'static Field,
1429 type_node: NodeId,
1430 fill_rule: FillRule,
1431 validators: ValidatorRange,
1432 ) -> FieldPlan {
1433 let name = field.name;
1434 let effective_name = field.effective_name();
1435 let alias = field.alias;
1436 let is_flattened = field.is_flattened();
1437
1438 FieldPlan {
1439 field,
1441 name,
1442 effective_name,
1443 alias,
1444 is_flattened,
1445 type_node,
1446 index,
1448 offset: field.offset,
1449 field_shape: field.shape(),
1450 fill_rule,
1451 validators,
1452 }
1453 }
1454
1455 fn build_field_lookup(&mut self, field_plans: &[FieldPlan]) -> FieldLookup {
1457 let mut entries: Vec<FieldLookupEntry> = Vec::with_capacity(field_plans.len() * 2);
1458
1459 for (index, field_plan) in field_plans.iter().enumerate() {
1460 entries.push(FieldLookupEntry {
1462 name: field_plan.effective_name,
1463 index,
1464 is_alias: false,
1465 });
1466
1467 if let Some(alias) = field_plan.alias {
1469 entries.push(FieldLookupEntry {
1470 name: alias,
1471 index,
1472 is_alias: true,
1473 });
1474 }
1475 }
1476
1477 self.build_field_lookup_from_entries(entries)
1478 }
1479
1480 fn build_field_lookup_from_entries(&mut self, entries: Vec<FieldLookupEntry>) -> FieldLookup {
1482 let total_entries = entries.len();
1483 if total_entries <= LOOKUP_THRESHOLD {
1484 return FieldLookup::Small(entries.into_iter().collect());
1485 }
1486
1487 let long_key_count = entries.iter().filter(|e| e.name.len() >= 8).count();
1489 let prefix_len = if long_key_count > total_entries / 2 {
1490 8
1491 } else {
1492 4
1493 };
1494
1495 let mut prefix_map: hashbrown::HashMap<u64, Vec<FieldLookupEntry>> =
1497 hashbrown::HashMap::new();
1498 for entry in entries {
1499 let prefix = compute_prefix(entry.name, prefix_len);
1500 prefix_map.entry(prefix).or_default().push(entry);
1501 }
1502
1503 let mut bucket_list: Vec<_> = prefix_map.into_iter().collect();
1505 bucket_list.sort_by_key(|(prefix, _)| *prefix);
1506
1507 let mut all_entries = Vec::with_capacity(total_entries);
1508 let mut bucket_data = Vec::with_capacity(bucket_list.len());
1509
1510 for (prefix, bucket_entries) in bucket_list {
1511 let start = all_entries.len() as u32;
1512 let count = bucket_entries.len() as u32;
1513 bucket_data.push((prefix, start, count));
1514 all_entries.extend(bucket_entries);
1515 }
1516
1517 let entries_range = self.field_entries.alloc_extend(all_entries);
1519 let buckets_range = self.buckets.alloc_extend(bucket_data);
1520
1521 FieldLookup::PrefixBuckets {
1522 prefix_len,
1523 entries: entries_range,
1524 buckets: buckets_range,
1525 }
1526 }
1527
1528 fn determine_fill_rule(field: &'static Field, container_has_default: bool) -> FillRule {
1530 let field_shape = field.shape();
1531
1532 if let Some(default_source) = field.default_source() {
1534 let field_default = match default_source {
1535 DefaultSource::Custom(f) => FieldDefault::Custom(*f),
1536 DefaultSource::FromTrait => FieldDefault::FromTrait(field_shape),
1537 };
1538 return FillRule::Defaultable(field_default);
1539 }
1540
1541 let is_option = matches!(field_shape.def, Def::Option(_));
1543 if is_option && field_shape.is(Characteristic::Default) {
1544 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1545 }
1546
1547 if field.should_skip_deserializing() && field_shape.is(Characteristic::Default) {
1549 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1550 }
1551
1552 if let Type::User(UserType::Struct(struct_type)) = field_shape.ty
1554 && struct_type.fields.is_empty()
1555 && field_shape.is(Characteristic::Default)
1556 {
1557 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1558 }
1559
1560 if container_has_default && field_shape.is(Characteristic::Default) {
1563 return FillRule::Defaultable(FieldDefault::FromTrait(field_shape));
1564 }
1565
1566 FillRule::Required
1568 }
1569
1570 fn extract_validators(&mut self, field: &'static Field) -> ValidatorRange {
1572 let mut validators = Vec::new();
1573 let field_shape = field.shape();
1574 let scalar_type = field_shape.scalar_type();
1576
1577 for attr in field.attributes.iter() {
1578 if attr.ns != Some("validate") {
1579 continue;
1580 }
1581
1582 let kind = match attr.key {
1583 "custom" => {
1584 let validator_fn = unsafe { *attr.data.ptr().get::<ValidatorFn>() };
1586 ValidatorKind::Custom(validator_fn)
1587 }
1588 "min" => {
1589 let limit = *attr
1590 .get_as::<i64>()
1591 .expect("validate::min attribute must contain i64");
1592 let scalar_type =
1593 scalar_type.expect("validate::min requires numeric field type");
1594 ValidatorKind::Min { limit, scalar_type }
1595 }
1596 "max" => {
1597 let limit = *attr
1598 .get_as::<i64>()
1599 .expect("validate::max attribute must contain i64");
1600 let scalar_type =
1601 scalar_type.expect("validate::max requires numeric field type");
1602 ValidatorKind::Max { limit, scalar_type }
1603 }
1604 "min_length" => {
1605 let limit = *attr
1606 .get_as::<usize>()
1607 .expect("validate::min_length attribute must contain usize");
1608 let scalar_type =
1609 scalar_type.expect("validate::min_length requires string field type");
1610 ValidatorKind::MinLength { limit, scalar_type }
1611 }
1612 "max_length" => {
1613 let limit = *attr
1614 .get_as::<usize>()
1615 .expect("validate::max_length attribute must contain usize");
1616 let scalar_type =
1617 scalar_type.expect("validate::max_length requires string field type");
1618 ValidatorKind::MaxLength { limit, scalar_type }
1619 }
1620 "email" => {
1621 let scalar_type =
1622 scalar_type.expect("validate::email requires string field type");
1623 ValidatorKind::Email { scalar_type }
1624 }
1625 "url" => {
1626 let scalar_type =
1627 scalar_type.expect("validate::url requires string field type");
1628 ValidatorKind::Url { scalar_type }
1629 }
1630 "regex" => {
1631 let pattern = *attr
1632 .get_as::<&'static str>()
1633 .expect("validate::regex attribute must contain &'static str");
1634 let scalar_type =
1635 scalar_type.expect("validate::regex requires string field type");
1636 ValidatorKind::Regex {
1637 pattern,
1638 scalar_type,
1639 }
1640 }
1641 "contains" => {
1642 let needle = *attr
1643 .get_as::<&'static str>()
1644 .expect("validate::contains attribute must contain &'static str");
1645 let scalar_type =
1646 scalar_type.expect("validate::contains requires string field type");
1647 ValidatorKind::Contains {
1648 needle,
1649 scalar_type,
1650 }
1651 }
1652 _ => continue, };
1654
1655 validators.push(PrecomputedValidator { kind });
1656 }
1657
1658 self.validators.alloc_extend(validators)
1659 }
1660
1661 fn build_enum_plan(&mut self, enum_def: &'static EnumType) -> Result<EnumPlan, AllocError> {
1663 let mut variant_metas = Vec::with_capacity(enum_def.variants.len());
1664
1665 for variant in enum_def.variants.iter() {
1666 let mut field_plans = Vec::with_capacity(variant.data.fields.len());
1667
1668 for (index, field) in variant.data.fields.iter().enumerate() {
1669 let field_proxies = FieldProxies::from_field(field);
1671 let child_node = self.build_node_with_proxy(field.shape(), field_proxies)?;
1672
1673 let validators = self.extract_validators(field);
1675 let fill_rule = Self::determine_fill_rule(field, false);
1676
1677 field_plans
1679 .push(self.create_field_plan(index, field, child_node, fill_rule, validators));
1680 }
1681
1682 let has_flatten = field_plans.iter().any(|f| f.is_flattened);
1683 let fields = self.fields.alloc_extend(field_plans.iter().cloned());
1684 let field_lookup = self.build_field_lookup(&field_plans);
1685
1686 variant_metas.push(VariantPlanMeta {
1687 variant,
1688 name: variant.effective_name(),
1689 fields,
1690 field_lookup,
1691 has_flatten,
1692 });
1693 }
1694
1695 let variants = self.variants.alloc_extend(variant_metas.iter().cloned());
1696 let variant_lookup = self.build_variant_lookup(&variant_metas);
1697 let num_variants = variant_metas.len();
1698
1699 let other_variant_idx = variant_metas.iter().position(|v| v.variant.is_other());
1701
1702 Ok(EnumPlan {
1703 enum_def,
1704 variants,
1705 variant_lookup,
1706 num_variants,
1707 other_variant_idx,
1708 })
1709 }
1710
1711 fn build_variant_lookup(&self, variants: &[VariantPlanMeta]) -> VariantLookup {
1718 let entries: Vec<_> = variants
1719 .iter()
1720 .enumerate()
1721 .filter(|(_, v)| !v.variant.is_other())
1722 .map(|(i, v)| (v.name, i))
1723 .collect();
1724
1725 if entries.len() <= LOOKUP_THRESHOLD {
1726 VariantLookup::Small(entries.into_iter().collect())
1727 } else {
1728 let mut sorted = entries;
1729 sorted.sort_by_key(|(name, _)| *name);
1730 VariantLookup::Sorted(sorted)
1731 }
1732 }
1733}
1734
1735impl<'facet, T: facet_core::Facet<'facet> + ?Sized> TypePlan<T> {
1736 pub fn build() -> Result<Self, AllocError> {
1753 let core = unsafe { TypePlanCore::from_shape(T::SHAPE)? };
1755
1756 Ok(TypePlan {
1757 core,
1758 _marker: core::marker::PhantomData,
1759 })
1760 }
1761
1762 #[deprecated(
1770 since = "0.44.0",
1771 note = "format namespace no longer needed at build time; use build() instead"
1772 )]
1773 pub fn build_for_format(_format_namespace: Option<&'static str>) -> Result<Self, AllocError> {
1774 Self::build()
1775 }
1776
1777 #[inline]
1779 pub fn core(&self) -> Arc<TypePlanCore> {
1780 self.core.clone()
1781 }
1782
1783 #[inline]
1785 pub fn root(&self) -> &TypePlanNode {
1786 self.core.root()
1787 }
1788}
1789
1790impl TypePlanCore {
1791 pub unsafe fn from_shape(shape: &'static Shape) -> Result<Arc<Self>, AllocError> {
1802 #[cfg(feature = "std")]
1803 {
1804 let mut guard = type_plan_cache()
1805 .lock()
1806 .unwrap_or_else(|poison| poison.into_inner());
1807
1808 if let Some(plan) = guard.get(&shape) {
1809 return Ok(Arc::clone(plan));
1810 }
1811
1812 let plan = unsafe { Self::build_uncached(shape)? };
1814 guard.insert(shape, Arc::clone(&plan));
1815 Ok(plan)
1816 }
1817
1818 #[cfg(not(feature = "std"))]
1819 {
1820 unsafe { Self::build_uncached(shape) }
1822 }
1823 }
1824
1825 unsafe fn build_uncached(shape: &'static Shape) -> Result<Arc<Self>, AllocError> {
1831 let mut builder = TypePlanBuilder::new();
1832 let root = builder.build_node(shape)?;
1833 Ok(Arc::new(builder.finish(root)))
1834 }
1835
1836 #[inline]
1838 pub fn root(&self) -> &TypePlanNode {
1839 self.node(self.root)
1840 }
1841
1842 #[inline]
1844 pub fn root_id(&self) -> NodeId {
1845 self.root
1846 }
1847
1848 #[inline]
1850 pub fn node(&self, idx: NodeId) -> &TypePlanNode {
1851 self.nodes.get(idx)
1852 }
1853
1854 #[inline]
1856 pub fn field(&self, idx: Idx<FieldPlan>) -> &FieldPlan {
1857 self.fields.get(idx)
1858 }
1859
1860 #[inline]
1862 pub fn fields(&self, range: FieldRange) -> &[FieldPlan] {
1863 self.fields.get_slice(range)
1864 }
1865
1866 #[inline]
1868 pub fn variant(&self, idx: Idx<VariantPlanMeta>) -> &VariantPlanMeta {
1869 self.variants.get(idx)
1870 }
1871
1872 #[inline]
1874 pub fn variants(&self, range: VariantRange) -> &[VariantPlanMeta] {
1875 self.variants.get_slice(range)
1876 }
1877
1878 #[inline]
1880 pub fn validators(&self, range: ValidatorRange) -> &[PrecomputedValidator] {
1881 self.validators.get_slice(range)
1882 }
1883
1884 #[inline]
1886 fn lookup_node(&self, type_id: &ConstTypeId) -> Option<NodeId> {
1887 let idx = self
1888 .node_lookup
1889 .binary_search_by_key(type_id, |(id, _)| *id)
1890 .ok()?;
1891 Some(self.node_lookup[idx].1)
1892 }
1893
1894 #[inline]
1899 pub fn struct_field_node(&self, parent: &TypePlanNode, idx: usize) -> Option<&TypePlanNode> {
1900 let resolved = self.resolve_backref(parent);
1901 let struct_plan = match &resolved.kind {
1902 TypePlanNodeKind::Struct(p) => p,
1903 _ => return None,
1904 };
1905 let fields = self.fields(struct_plan.fields);
1906 Some(self.node(fields.get(idx)?.type_node))
1907 }
1908
1909 #[inline]
1912 pub fn enum_variant_field_node(
1913 &self,
1914 parent: &TypePlanNode,
1915 variant_idx: usize,
1916 field_idx: usize,
1917 ) -> Option<&TypePlanNode> {
1918 let resolved = self.resolve_backref(parent);
1919 let enum_plan = match &resolved.kind {
1920 TypePlanNodeKind::Enum(p) => p,
1921 _ => return None,
1922 };
1923 let variants = self.variants(enum_plan.variants);
1924 let variant = variants.get(variant_idx)?;
1925 let fields = self.fields(variant.fields);
1926 Some(self.node(fields.get(field_idx)?.type_node))
1927 }
1928
1929 #[inline]
1931 pub fn list_item_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1932 match &parent.strategy {
1933 DeserStrategy::List { item_node, .. } | DeserStrategy::Array { item_node, .. } => {
1934 Some(self.node(*item_node))
1935 }
1936 DeserStrategy::BackRef { target_type_id } => {
1937 let target = self.lookup_node(target_type_id)?;
1938 self.list_item_node(self.node(target))
1939 }
1940 _ => None,
1941 }
1942 }
1943
1944 #[inline]
1946 pub fn set_item_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1947 match &parent.strategy {
1948 DeserStrategy::Set { item_node } => Some(self.node(*item_node)),
1949 DeserStrategy::BackRef { target_type_id } => {
1950 let target = self.lookup_node(target_type_id)?;
1951 self.set_item_node(self.node(target))
1952 }
1953 _ => None,
1954 }
1955 }
1956
1957 #[inline]
1959 pub fn map_key_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1960 match &parent.strategy {
1961 DeserStrategy::Map { key_node, .. } => Some(self.node(*key_node)),
1962 DeserStrategy::BackRef { target_type_id } => {
1963 let target = self.lookup_node(target_type_id)?;
1964 self.map_key_node(self.node(target))
1965 }
1966 _ => None,
1967 }
1968 }
1969
1970 #[inline]
1972 pub fn map_value_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1973 match &parent.strategy {
1974 DeserStrategy::Map { value_node, .. } => Some(self.node(*value_node)),
1975 DeserStrategy::BackRef { target_type_id } => {
1976 let target = self.lookup_node(target_type_id)?;
1977 self.map_value_node(self.node(target))
1978 }
1979 _ => None,
1980 }
1981 }
1982
1983 #[inline]
1985 pub fn option_inner_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1986 match &parent.strategy {
1987 DeserStrategy::Option { some_node } => Some(self.node(*some_node)),
1988 DeserStrategy::BackRef { target_type_id } => {
1989 let target = self.lookup_node(target_type_id)?;
1990 self.option_inner_node(self.node(target))
1991 }
1992 _ => None,
1993 }
1994 }
1995
1996 #[inline]
1998 pub fn result_ok_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
1999 match &parent.strategy {
2000 DeserStrategy::Result { ok_node, .. } => Some(self.node(*ok_node)),
2001 DeserStrategy::BackRef { target_type_id } => {
2002 let target = self.lookup_node(target_type_id)?;
2003 self.result_ok_node(self.node(target))
2004 }
2005 _ => None,
2006 }
2007 }
2008
2009 #[inline]
2011 pub fn result_err_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2012 match &parent.strategy {
2013 DeserStrategy::Result { err_node, .. } => Some(self.node(*err_node)),
2014 DeserStrategy::BackRef { target_type_id } => {
2015 let target = self.lookup_node(target_type_id)?;
2016 self.result_err_node(self.node(target))
2017 }
2018 _ => None,
2019 }
2020 }
2021
2022 #[inline]
2024 pub fn pointer_pointee_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2025 match &parent.strategy {
2026 DeserStrategy::Pointer { pointee_node } => Some(self.node(*pointee_node)),
2027 DeserStrategy::BackRef { target_type_id } => {
2028 let target = self.lookup_node(target_type_id)?;
2029 self.pointer_pointee_node(self.node(target))
2030 }
2031 _ => None,
2032 }
2033 }
2034
2035 #[inline]
2037 pub fn inner_node(&self, parent: &TypePlanNode) -> Option<&TypePlanNode> {
2038 if parent.shape.inner.is_some() {
2039 match &parent.strategy {
2040 DeserStrategy::TransparentConvert { inner_node } => Some(self.node(*inner_node)),
2041 _ => None,
2042 }
2043 } else {
2044 None
2045 }
2046 }
2047
2048 #[inline]
2050 pub fn resolve_backref<'a>(&'a self, node: &'a TypePlanNode) -> &'a TypePlanNode {
2051 match &node.kind {
2052 TypePlanNodeKind::BackRef(type_id) => self.node(
2053 self.lookup_node(type_id)
2054 .expect("BackRef target must exist in node_lookup"),
2055 ),
2056 _ => node,
2057 }
2058 }
2059
2060 #[inline]
2063 pub fn as_struct_plan<'a>(&'a self, node: &'a TypePlanNode) -> Option<&'a StructPlan> {
2064 let resolved = self.resolve_backref(node);
2065 match &resolved.kind {
2066 TypePlanNodeKind::Struct(plan) => Some(plan),
2067 _ => None,
2068 }
2069 }
2070
2071 #[inline]
2074 pub fn as_enum_plan<'a>(&'a self, node: &'a TypePlanNode) -> Option<&'a EnumPlan> {
2075 let resolved = self.resolve_backref(node);
2076 match &resolved.kind {
2077 TypePlanNodeKind::Enum(plan) => Some(plan),
2078 _ => None,
2079 }
2080 }
2081
2082 #[inline]
2084 pub fn resolve_backref_id(&self, node_id: NodeId) -> &TypePlanNode {
2085 let node = self.node(node_id);
2086 self.resolve_backref(node)
2087 }
2088
2089 #[inline]
2092 pub fn struct_plan_by_id(&self, node_id: NodeId) -> Option<&StructPlan> {
2093 self.as_struct_plan(self.node(node_id))
2094 }
2095
2096 #[inline]
2099 pub fn enum_plan_by_id(&self, node_id: NodeId) -> Option<&EnumPlan> {
2100 self.as_enum_plan(self.node(node_id))
2101 }
2102
2103 #[inline]
2108 pub fn struct_field_node_id(&self, parent_id: NodeId, idx: usize) -> Option<NodeId> {
2109 let parent = self.node(parent_id);
2110 let resolved = self.resolve_backref(parent);
2111 let struct_plan = match &resolved.kind {
2112 TypePlanNodeKind::Struct(p) => p,
2113 _ => return None,
2114 };
2115 let fields = self.fields(struct_plan.fields);
2116 Some(fields.get(idx)?.type_node)
2117 }
2118
2119 #[inline]
2122 pub fn enum_variant_field_node_id(
2123 &self,
2124 parent_id: NodeId,
2125 variant_idx: usize,
2126 field_idx: usize,
2127 ) -> Option<NodeId> {
2128 let parent = self.node(parent_id);
2129 let resolved = self.resolve_backref(parent);
2130 let enum_plan = match &resolved.kind {
2131 TypePlanNodeKind::Enum(p) => p,
2132 _ => return None,
2133 };
2134 let variants = self.variants(enum_plan.variants);
2135 let variant = variants.get(variant_idx)?;
2136 let fields = self.fields(variant.fields);
2137 Some(fields.get(field_idx)?.type_node)
2138 }
2139
2140 #[inline]
2142 pub fn list_item_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2143 let parent = self.node(parent_id);
2144 match &parent.strategy {
2145 DeserStrategy::List { item_node, .. } | DeserStrategy::Array { item_node, .. } => {
2146 Some(*item_node)
2147 }
2148 DeserStrategy::BackRef { target_type_id } => {
2149 let target = self.lookup_node(target_type_id)?;
2150 self.list_item_node_id(target)
2151 }
2152 _ => None,
2153 }
2154 }
2155
2156 #[inline]
2158 pub fn set_item_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2159 let parent = self.node(parent_id);
2160 match &parent.strategy {
2161 DeserStrategy::Set { item_node } => Some(*item_node),
2162 DeserStrategy::BackRef { target_type_id } => {
2163 let target = self.lookup_node(target_type_id)?;
2164 self.set_item_node_id(target)
2165 }
2166 _ => None,
2167 }
2168 }
2169
2170 #[inline]
2172 pub fn map_key_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2173 let parent = self.node(parent_id);
2174 match &parent.strategy {
2175 DeserStrategy::Map { key_node, .. } => Some(*key_node),
2176 DeserStrategy::BackRef { target_type_id } => {
2177 let target = self.lookup_node(target_type_id)?;
2178 self.map_key_node_id(target)
2179 }
2180 _ => None,
2181 }
2182 }
2183
2184 #[inline]
2186 pub fn map_value_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2187 let parent = self.node(parent_id);
2188 match &parent.strategy {
2189 DeserStrategy::Map { value_node, .. } => Some(*value_node),
2190 DeserStrategy::BackRef { target_type_id } => {
2191 let target = self.lookup_node(target_type_id)?;
2192 self.map_value_node_id(target)
2193 }
2194 _ => None,
2195 }
2196 }
2197
2198 #[inline]
2200 pub fn option_some_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2201 let parent = self.node(parent_id);
2202 match &parent.strategy {
2203 DeserStrategy::Option { some_node, .. } => Some(*some_node),
2204 DeserStrategy::BackRef { target_type_id } => {
2205 let target = self.lookup_node(target_type_id)?;
2206 self.option_some_node_id(target)
2207 }
2208 _ => None,
2209 }
2210 }
2211
2212 #[inline]
2214 pub fn result_nodes_id(&self, parent_id: NodeId) -> Option<(NodeId, NodeId)> {
2215 let parent = self.node(parent_id);
2216 match &parent.strategy {
2217 DeserStrategy::Result {
2218 ok_node, err_node, ..
2219 } => Some((*ok_node, *err_node)),
2220 DeserStrategy::BackRef { target_type_id } => {
2221 let target = self.lookup_node(target_type_id)?;
2222 self.result_nodes_id(target)
2223 }
2224 _ => None,
2225 }
2226 }
2227
2228 #[inline]
2230 pub fn pointer_inner_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2231 let parent = self.node(parent_id);
2232 match &parent.strategy {
2233 DeserStrategy::Pointer { pointee_node, .. } => Some(*pointee_node),
2234 DeserStrategy::BackRef { target_type_id } => {
2235 let target = self.lookup_node(target_type_id)?;
2236 self.pointer_inner_node_id(target)
2237 }
2238 _ => None,
2239 }
2240 }
2241
2242 #[inline]
2244 pub fn inner_node_id(&self, parent_id: NodeId) -> Option<NodeId> {
2245 let parent = self.node(parent_id);
2246 if parent.shape.inner.is_some() {
2247 match &parent.strategy {
2248 DeserStrategy::TransparentConvert { inner_node } => Some(*inner_node),
2249 _ => None,
2250 }
2251 } else {
2252 None
2253 }
2254 }
2255
2256 pub(crate) fn empty() -> TypePlanCore {
2257 TypePlanCore {
2258 nodes: Arena::new(),
2259 fields: Arena::new(),
2260 variants: Arena::new(),
2261 validators: Arena::new(),
2262 field_entries: Arena::new(),
2263 buckets: Arena::new(),
2264 node_lookup: Vec::new(),
2265 root: NodeId::new(0),
2266 }
2267 }
2268}
2269
2270#[cfg(test)]
2271mod tests {
2272 use super::*;
2273 use facet::Facet;
2274
2275 #[derive(Facet)]
2276 struct TestStruct {
2277 name: String,
2278 age: u32,
2279 email: Option<String>,
2280 }
2281
2282 #[derive(Facet)]
2283 #[repr(u8)]
2284 #[allow(dead_code)] enum TestEnum {
2286 Unit,
2287 Tuple(u32),
2288 Struct { value: String },
2289 }
2290
2291 #[derive(Facet)]
2292 struct RecursiveStruct {
2293 value: u32,
2294 next: Option<Box<RecursiveStruct>>,
2296 }
2297
2298 #[test]
2299 fn test_typeplan_build_reuses_cached_core() {
2300 #[derive(Facet)]
2301 struct CacheProbe {
2302 value: u32,
2303 }
2304
2305 let first = TypePlan::<CacheProbe>::build().unwrap().core();
2306 let second = TypePlan::<CacheProbe>::build().unwrap().core();
2307 assert!(Arc::ptr_eq(&first, &second));
2308
2309 let third =
2311 unsafe { TypePlanCore::from_shape(<CacheProbe as facet_core::Facet<'static>>::SHAPE) }
2312 .unwrap();
2313 assert!(Arc::ptr_eq(&first, &third));
2314 }
2315
2316 #[test]
2317 fn test_typeplan_struct() {
2318 let plan = TypePlan::<TestStruct>::build().unwrap();
2319 let root = plan.root();
2320 let core = plan.core();
2321
2322 assert_eq!(root.shape, TestStruct::SHAPE);
2323 assert!(!root.has_default);
2324
2325 match &root.kind {
2326 TypePlanNodeKind::Struct(struct_plan) => {
2327 let fields = core.fields(struct_plan.fields);
2328 assert_eq!(fields.len(), 3);
2329 assert!(!struct_plan.has_flatten);
2330
2331 assert_eq!(struct_plan.field_lookup.find("name", &core), Some(0));
2333 assert_eq!(struct_plan.field_lookup.find("age", &core), Some(1));
2334 assert_eq!(struct_plan.field_lookup.find("email", &core), Some(2));
2335 assert_eq!(struct_plan.field_lookup.find("unknown", &core), None);
2336
2337 assert_eq!(fields[0].name, "name");
2339 assert!(fields[0].is_required());
2340
2341 assert_eq!(fields[1].name, "age");
2342 assert!(fields[1].is_required());
2343
2344 assert_eq!(fields[2].name, "email");
2345 assert!(!fields[2].is_required()); let email_node = core.struct_field_node(plan.root(), 2).unwrap();
2349 match &email_node.kind {
2350 TypePlanNodeKind::Option => {
2351 let inner_node = core.option_inner_node(email_node).unwrap();
2353 match &inner_node.kind {
2354 TypePlanNodeKind::Scalar => {}
2355 other => panic!("Expected Scalar for String, got {:?}", other),
2356 }
2357 }
2358 other => panic!("Expected Option, got {:?}", other),
2359 }
2360 }
2361 other => panic!("Expected Struct, got {:?}", other),
2362 }
2363 }
2364
2365 #[test]
2366 fn test_typeplan_enum() {
2367 let plan = TypePlan::<TestEnum>::build().unwrap();
2368 let root = plan.root();
2369 let core = plan.core();
2370
2371 assert_eq!(root.shape, TestEnum::SHAPE);
2372
2373 match &root.kind {
2374 TypePlanNodeKind::Enum(enum_plan) => {
2375 let variants = core.variants(enum_plan.variants);
2376 assert_eq!(enum_plan.num_variants, 3);
2377
2378 assert_eq!(enum_plan.variant_lookup.find("Unit"), Some(0));
2380 assert_eq!(enum_plan.variant_lookup.find("Tuple"), Some(1));
2381 assert_eq!(enum_plan.variant_lookup.find("Struct"), Some(2));
2382 assert_eq!(enum_plan.variant_lookup.find("Unknown"), None);
2383
2384 assert!(core.fields(variants[0].fields).is_empty());
2386
2387 assert_eq!(core.fields(variants[1].fields).len(), 1);
2389
2390 let struct_variant_fields = core.fields(variants[2].fields);
2392 assert_eq!(struct_variant_fields.len(), 1);
2393 assert_eq!(variants[2].field_lookup.find("value", &core), Some(0));
2394 }
2395 other => panic!("Expected Enum, got {:?}", other),
2396 }
2397 }
2398
2399 #[test]
2400 fn test_typeplan_list() {
2401 let plan = TypePlan::<Vec<u32>>::build().unwrap();
2402 let root = plan.root();
2403 let core = plan.core();
2404
2405 match &root.kind {
2406 TypePlanNodeKind::List => {
2407 let item_node = core.list_item_node(plan.root()).unwrap();
2408 match &item_node.kind {
2409 TypePlanNodeKind::Scalar => {}
2410 other => panic!("Expected Scalar for u32, got {:?}", other),
2411 }
2412 }
2413 other => panic!("Expected List, got {:?}", other),
2414 }
2415 }
2416
2417 #[test]
2418 fn test_typeplan_recursive() {
2419 let plan = TypePlan::<RecursiveStruct>::build().unwrap();
2421 let root = plan.root();
2422 let core = plan.core();
2423
2424 match &root.kind {
2425 TypePlanNodeKind::Struct(struct_plan) => {
2426 let fields = core.fields(struct_plan.fields);
2427 assert_eq!(fields.len(), 2);
2428 assert_eq!(fields[0].name, "value");
2429 assert_eq!(fields[1].name, "next");
2430
2431 let next_node = core.struct_field_node(plan.root(), 1).unwrap();
2434
2435 assert!(matches!(next_node.kind, TypePlanNodeKind::Option));
2437
2438 let inner_node = core.option_inner_node(next_node).unwrap();
2440 assert!(matches!(inner_node.kind, TypePlanNodeKind::Pointer));
2441
2442 let pointee_node = core.pointer_pointee_node(inner_node).unwrap();
2444
2445 match &pointee_node.kind {
2447 TypePlanNodeKind::BackRef(type_id) => {
2448 assert_eq!(type_id, &plan.root().shape.id);
2450 }
2451 _ => panic!(
2452 "Expected BackRef for recursive type, got {:?}",
2453 pointee_node.kind
2454 ),
2455 }
2456 }
2457 other => panic!("Expected Struct, got {:?}", other),
2458 }
2459 }
2460
2461 #[test]
2462 fn test_typeplan_structure_sharing() {
2463 macro_rules! make_ty {
2465 ($name:ident, $subty:ty) => {
2466 #[derive(Facet)]
2467 #[repr(u8)]
2468 #[expect(dead_code)]
2469 enum $name {
2470 A($subty),
2471 B($subty),
2472 C($subty),
2473 D($subty),
2474 }
2475 };
2476 }
2477 make_ty!(L1, u32);
2478 make_ty!(L2, L1);
2479 make_ty!(L3, L2);
2480 make_ty!(L4, L3);
2481
2482 let plan = TypePlan::<L4>::build().expect("typeplan build");
2483 let core = plan.core();
2484 let node_count = core.nodes.len();
2485 assert_eq!(node_count, 5);
2487 }
2488
2489 #[test]
2490 fn test_field_lookup_small() {
2491 let lookup = FieldLookup::Small(smallvec::smallvec![
2492 FieldLookupEntry {
2493 name: "foo",
2494 index: 0,
2495 is_alias: false,
2496 },
2497 FieldLookupEntry {
2498 name: "bar",
2499 index: 1,
2500 is_alias: false,
2501 },
2502 FieldLookupEntry {
2503 name: "baz",
2504 index: 2,
2505 is_alias: false,
2506 },
2507 ]);
2508
2509 assert_eq!(lookup.find_small("foo"), Some(0));
2510 assert_eq!(lookup.find_small("bar"), Some(1));
2511 assert_eq!(lookup.find_small("baz"), Some(2));
2512 assert_eq!(lookup.find_small("qux"), None);
2513 }
2514
2515 #[test]
2516 fn test_variant_lookup_small() {
2517 let lookup = VariantLookup::Small(smallvec::smallvec![("A", 0), ("B", 1), ("C", 2)]);
2518
2519 assert_eq!(lookup.find("A"), Some(0));
2520 assert_eq!(lookup.find("B"), Some(1));
2521 assert_eq!(lookup.find("C"), Some(2));
2522 assert_eq!(lookup.find("D"), None);
2523 }
2524}