1use std::fmt::Debug;
2use std::fmt::Display;
3use std::hash::Hash;
4use std::hash::Hasher;
5use std::marker::PhantomData;
6use std::sync::RwLock;
7
8use indexmap::IndexMap;
9use indexmap::IndexSet;
10
11use crate::helpers::quote_non_identifier;
12use crate::helpers::RefWeak;
13use crate::location::Location;
14use crate::merge::MetaMergeable;
15use crate::MergeSet;
16use crate::Ref;
17use crate::Shape;
18use crate::ShapeCase;
19
20#[derive(Debug, PartialEq, Eq, Clone)]
32pub struct Namespace<T = NotFinal> {
33 map: Ref<IndexMap<String, Ref<Shape>>>,
38 _final_state: PhantomData<T>,
39}
40
41#[derive(Debug, PartialEq, Eq, Clone)]
42pub struct NotFinal;
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub struct Final;
46
47impl Namespace {
48 #[must_use]
50 pub fn new() -> Namespace<NotFinal> {
51 Namespace::<NotFinal> {
52 map: Ref::new(IndexMap::new()),
53 _final_state: PhantomData::<NotFinal>,
54 }
55 }
56}
57
58impl Default for Namespace<NotFinal> {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64impl<T> Namespace<T> {
65 #[must_use]
68 pub fn has(&self, name: &str) -> bool {
69 self.map.contains_key(name)
70 }
71
72 pub fn names(&self) -> impl Iterator<Item = &str> + '_ {
74 self.map.keys().map(String::as_str)
75 }
76
77 #[must_use]
84 pub fn merge<U>(&self, other: &Namespace<U>) -> Namespace<NotFinal> {
85 let mut merged = Namespace::<NotFinal> {
86 map: self.map.clone(),
87 _final_state: PhantomData::<NotFinal>,
88 };
89 merged.extend(other);
90 merged
91 }
92}
93
94impl Namespace<NotFinal> {
95 pub fn extend<T>(&mut self, other: &Namespace<T>) {
100 for (name, shape) in other.map.as_ref() {
101 self.insert(name.clone(), shape.as_ref().clone());
102 }
103 }
104
105 pub fn insert(&mut self, name: impl Into<String>, shape: Shape) -> Shape {
111 let name = name.into();
112 if let Some(existing_shape) = self.map.get(&name) {
113 let merged = Ref::new(
114 Shape::all([existing_shape.as_ref().clone(), shape], [])
115 .with_base_name(&name, []),
120 );
121 let merged_shape = merged.as_ref().clone();
122 Ref::make_mut(&mut self.map).insert(name.clone(), merged);
123 merged_shape
124 } else {
125 let named_shape_ref = Ref::new(shape.with_base_name(&name, []));
126 let named_shape_clone = named_shape_ref.as_ref().clone();
127 Ref::make_mut(&mut self.map).insert(name, named_shape_ref);
128 named_shape_clone
129 }
130 }
131
132 #[must_use]
136 pub fn finalize(&self) -> Namespace<Final> {
137 let weak_scope = WeakScope::none();
141
142 let final_map = Ref::new(
143 self.map
144 .iter()
145 .map(|(name, shape)| {
146 let named_shape = shape.as_ref().clone().with_base_name(name, []);
149 (
150 name.clone(),
151 Ref::new(ensure_deep_exclusive_name_ownership(
158 named_shape,
159 &weak_scope,
160 )),
161 )
162 })
163 .collect::<IndexMap<_, _>>(),
164 );
165
166 weak_scope.set_weak(Ref::downgrade(&final_map));
170
171 if cfg!(debug_assertions) {
172 for (name, shape_ref) in final_map.as_ref() {
173 debug_assert!(shape_ref.has_base_name(name));
174 }
175 }
176
177 Namespace::<Final> {
178 map: final_map,
179 _final_state: PhantomData::<Final>,
180 }
181 }
182}
183
184fn ensure_deep_exclusive_name_ownership(mut shape: Shape, weak_scope: &WeakScope) -> Shape {
185 if shape.meta.nested_base_names().next().is_none() {
186 return shape;
189 }
190
191 match Ref::make_mut(&mut shape.case) {
192 ShapeCase::Object { fields, rest } => {
193 for field_shape in fields.values_mut() {
194 *field_shape =
195 ensure_deep_exclusive_name_ownership(field_shape.clone(), weak_scope);
196 }
197 *rest = ensure_deep_exclusive_name_ownership(rest.clone(), weak_scope);
198 }
199
200 ShapeCase::Array { prefix, tail } => {
201 for element_shape in prefix {
202 *element_shape =
203 ensure_deep_exclusive_name_ownership(element_shape.clone(), weak_scope);
204 }
205 *tail = ensure_deep_exclusive_name_ownership(tail.clone(), weak_scope);
206 }
207
208 ShapeCase::One(shapes) => {
209 shapes.shapes = MergeSet::new(
210 shapes
211 .iter()
212 .map(|shape| ensure_deep_exclusive_name_ownership(shape.clone(), weak_scope)),
213 );
214 }
215
216 ShapeCase::All(shapes) => {
217 shapes.shapes = MergeSet::new(
218 shapes
219 .iter()
220 .map(|shape| ensure_deep_exclusive_name_ownership(shape.clone(), weak_scope)),
221 );
222 }
223
224 ShapeCase::Name(_name, weak) => {
225 *weak = weak_scope.clone();
230 }
231
232 ShapeCase::Null
233 | ShapeCase::None
234 | ShapeCase::Unknown
235 | ShapeCase::Bool(_)
236 | ShapeCase::Int(_)
237 | ShapeCase::Float
238 | ShapeCase::String(_) => {}
239 }
240
241 shape
242}
243
244#[derive(Clone, Debug)]
250pub struct WeakScope(Ref<RwLock<Option<WeakShapeMap>>>);
251
252type WeakShapeMap = RefWeak<IndexMap<String, Ref<Shape>>>;
257
258impl WeakScope {
259 #[must_use]
260 pub fn none() -> Self {
261 Self(Ref::new(RwLock::new(None)))
262 }
263
264 #[must_use]
267 pub fn upgrade(&self, name: &Name) -> Option<Shape> {
268 match name.case() {
269 NameCase::Base(base_name) => {
270 if let Ok(guard) = self.0.read() {
271 guard
272 .as_ref()
273 .and_then(RefWeak::upgrade)
274 .and_then(|map| map.get(base_name).map(|shape| shape.as_ref().clone()))
275 } else {
276 None
277 }
278 }
279 NameCase::Field(parent, field_name) => self
280 .upgrade(parent)
281 .map(|shape| shape.field(field_name, name.locations().cloned())),
282 NameCase::Item(parent, index) => self
283 .upgrade(parent)
284 .map(|shape| shape.item(*index, name.locations().cloned())),
285 NameCase::AnyField(parent) => self
286 .upgrade(parent)
287 .map(|shape| shape.any_field(name.locations().cloned())),
288 NameCase::AnyItem(parent) => self
289 .upgrade(parent)
290 .map(|shape| shape.any_item(name.locations().cloned())),
291 NameCase::Question(parent) => self
292 .upgrade(parent)
293 .map(|shape| shape.question(name.locations().cloned())),
294 NameCase::NotNone(parent) => self
295 .upgrade(parent)
296 .map(|shape| shape.not_none(name.locations().cloned())),
297 }
298 }
299
300 fn set_weak(&self, weak: WeakShapeMap) {
301 *self.0.write().unwrap() = Some(weak);
302 }
303}
304
305impl Namespace<Final> {
306 #[must_use]
307 pub fn finalize(&self) -> Namespace<Final> {
308 self.clone()
313 }
314
315 pub fn iter(&self) -> impl Iterator<Item = (String, Shape)> + '_ {
317 self.map
318 .iter()
319 .map(|(name, shape)| (name.clone(), shape.as_ref().clone()))
320 }
321
322 #[must_use]
329 pub fn get(&self, name: &str) -> Option<Shape> {
330 self.map.get(name).map(|shape| shape.as_ref().clone())
331 }
332
333 #[must_use]
336 pub fn get_or_none(&self, name: &str) -> Shape {
337 if let Some(shape) = self.get(name) {
338 shape
339 } else {
340 Shape::none().with_base_name(name, [])
341 }
342 }
343
344 #[must_use]
347 pub fn get_or_unknown(&self, name: &str) -> Shape {
348 if let Some(shape) = self.get(name) {
349 shape
350 } else {
351 Shape::unknown([]).with_base_name(name, [])
352 }
353 }
354}
355
356impl Shape {
357 pub fn has_base_name(&self, base_name: impl Into<String>) -> bool {
360 let name = Name::base(base_name.into(), []);
361 self.meta.has_name(&name)
362 }
363
364 #[must_use]
371 pub fn with_base_name(
372 self,
373 name: impl Into<String>,
374 locs: impl IntoIterator<Item = Location>,
375 ) -> Self {
376 self.with_name(&Name::base(name, locs))
377 }
378
379 #[must_use]
380 pub(crate) fn with_name(mut self, name: &Name) -> Self {
381 if self.meta.has_name(name) {
382 return self;
385 }
386
387 Ref::make_mut(&mut self.meta).add_name(name.clone());
388
389 match Ref::make_mut(&mut self.case) {
391 ShapeCase::Object { fields, rest } => {
392 for (field_name, field_shape) in fields.iter_mut() {
393 *field_shape = field_shape.clone().with_name(&name.field(field_name, []));
394 }
395 *rest = rest.clone().with_name(&name.any_field([]));
398 self
399 }
400
401 ShapeCase::Array { prefix, tail } => {
402 for (index, prefix_shape) in prefix.iter_mut().enumerate() {
403 *prefix_shape = prefix_shape.clone().with_name(&name.item(index, []));
404 }
405 *tail = tail.clone().with_name(&name.any_item([]));
408 self
409 }
410
411 ShapeCase::One(shapes) => {
412 shapes.shapes =
413 MergeSet::new(shapes.iter().map(|shape| shape.clone().with_name(name)));
414 self
415 }
416
417 ShapeCase::All(shapes) => {
418 shapes.shapes =
419 MergeSet::new(shapes.iter().map(|shape| shape.clone().with_name(name)));
420 self
421 }
422
423 ShapeCase::Bool(_)
426 | ShapeCase::String(_)
427 | ShapeCase::Int(_)
428 | ShapeCase::Float
429 | ShapeCase::Null
430 | ShapeCase::Unknown
431 | ShapeCase::None => {
432 self
434 }
435 ShapeCase::Name(_, _) => self,
443 }
444 }
445}
446
447#[derive(Clone, Eq)]
448pub struct Name {
449 case: Ref<NameCase>,
450 locs: Ref<IndexSet<Location>>,
454}
455
456impl Debug for Name {
457 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
458 write!(f, "Name(")?;
459 <Name as Display>::fmt(self, f)?;
460 write!(f, ")")
461 }
462}
463
464impl Hash for Name {
465 fn hash<H: Hasher>(&self, state: &mut H) {
466 self.case.hash(state);
469 }
470}
471
472impl PartialEq for Name {
473 fn eq(&self, other: &Self) -> bool {
474 self.case == other.case
476 }
477}
478
479impl MetaMergeable for Name {
480 fn merge_meta_from(&mut self, other: &Self) -> bool {
481 let mut locs_changed = false;
482
483 if !Ref::ptr_eq(&self.locs, &other.locs) {
484 let self_locs_backup = if Ref::strong_count(&self.locs) > 1 {
494 Some(self.locs.clone())
495 } else {
496 None
497 };
498
499 for locs in other.locs.as_ref() {
500 if !self.locs.contains(locs) {
501 Ref::make_mut(&mut self.locs).insert(locs.clone());
502 locs_changed = true;
503 }
504 }
505
506 if let (false, Some(backup)) = (locs_changed, self_locs_backup) {
507 self.locs = backup;
508 }
509 }
510
511 let case_changed = if Ref::ptr_eq(&self.case, &other.case) {
529 false
530 } else {
531 let self_case_backup = if Ref::strong_count(&self.case) > 1 {
533 Some(self.case.clone())
534 } else {
535 None
536 };
537
538 let case_changed = Ref::make_mut(&mut self.case).merge_parent_meta_from(&other.case);
539
540 if let (false, Some(backup)) = (case_changed, self_case_backup) {
541 self.case = backup;
542 }
543
544 case_changed
545 };
546
547 locs_changed || case_changed
548 }
549}
550
551impl Name {
552 pub(crate) fn new(case: NameCase, locs: impl IntoIterator<Item = Location>) -> Self {
553 Self {
554 case: Ref::new(case),
555 locs: Ref::new(locs.into_iter().collect()),
556 }
557 }
558
559 pub(crate) fn base(name: impl Into<String>, locs: impl IntoIterator<Item = Location>) -> Self {
560 Self::new(NameCase::Base(name.into()), locs)
561 }
562
563 #[must_use]
564 pub fn base_shape_name(&self) -> &str {
565 match self.case() {
566 NameCase::Base(name) => name.as_str(),
567 NameCase::Field(parent, _)
568 | NameCase::AnyField(parent)
569 | NameCase::Item(parent, _)
570 | NameCase::Question(parent)
571 | NameCase::NotNone(parent)
572 | NameCase::AnyItem(parent) => parent.base_shape_name(),
573 }
574 }
575
576 pub(crate) fn field(
577 &self,
578 field: impl Into<String>,
579 locs: impl IntoIterator<Item = Location>,
580 ) -> Self {
581 Self::new(NameCase::Field(self.clone(), field.into()), locs)
582 }
583
584 pub(crate) fn any_field(&self, locs: impl IntoIterator<Item = Location>) -> Self {
585 Self::new(NameCase::AnyField(self.clone()), locs)
586 }
587
588 pub(crate) fn item(&self, index: usize, locs: impl IntoIterator<Item = Location>) -> Self {
589 Self::new(NameCase::Item(self.clone(), index), locs)
590 }
591
592 pub(crate) fn any_item(&self, locs: impl IntoIterator<Item = Location>) -> Self {
593 if let NameCase::AnyItem(_) = self.case() {
596 self.clone()
597 } else {
598 Self::new(NameCase::AnyItem(self.clone()), locs)
599 }
600 }
601
602 pub(crate) fn question(&self, locs: impl IntoIterator<Item = Location>) -> Self {
603 if let NameCase::Question(_) = self.case() {
606 self.clone()
607 } else {
608 Self::new(NameCase::Question(self.clone()), locs)
609 }
610 }
611
612 pub(crate) fn not_none(&self, locs: impl IntoIterator<Item = Location>) -> Self {
613 if let NameCase::NotNone(_) = self.case() {
616 self.clone()
617 } else {
618 Self::new(NameCase::NotNone(self.clone()), locs)
619 }
620 }
621
622 #[must_use]
624 pub fn case(&self) -> &NameCase {
625 self.case.as_ref()
626 }
627
628 pub fn iter(&self) -> impl Iterator<Item = &Name> {
629 self.parent().map_or_else(
630 || vec![self].into_iter(),
631 |parent| {
632 let mut previous = parent.iter().collect::<Vec<_>>();
633 previous.push(self);
634 previous.into_iter()
635 },
636 )
637 }
638
639 #[allow(dead_code)]
640 pub(crate) fn iter_cases(&self) -> impl Iterator<Item = &NameCase> {
641 self.iter().map(Name::case)
642 }
643
644 pub fn locations(&self) -> impl Iterator<Item = &Location> {
646 let mut unique_locs = self
647 .parent()
648 .map_or_else(IndexSet::new, |parent| parent.locations().collect());
649 unique_locs.extend(self.locs.iter());
650 unique_locs.into_iter()
651 }
652
653 pub fn locs(&self) -> impl Iterator<Item = &Location> {
657 self.locs.iter()
658 }
659
660 #[allow(dead_code)]
661 pub(crate) fn with_locs<'a>(&self, locs: impl IntoIterator<Item = &'a Location>) -> Self {
662 let mut clone = self.clone();
663 clone.add_locs(locs);
664 clone
665 }
666
667 #[allow(dead_code)]
668 pub(crate) fn add_locs<'a>(&mut self, locs: impl IntoIterator<Item = &'a Location>) -> bool {
669 let mut changed = false;
670 for loc in locs {
671 if !self.locs.contains(loc) {
672 Ref::make_mut(&mut self.locs).insert(loc.clone());
673 changed = true;
674 }
675 }
676 changed
677 }
678
679 pub(crate) fn parent(&self) -> Option<&Name> {
680 self.case.parent()
681 }
682}
683
684#[derive(Clone, Debug, PartialEq, Eq, Hash)]
685pub enum NameCase {
686 Base(String),
687 Field(Name, String),
688 AnyField(Name),
689 Item(Name, usize),
690 AnyItem(Name),
691 Question(Name),
692 NotNone(Name),
693}
694
695impl NameCase {
696 pub(crate) fn parent(&self) -> Option<&Name> {
697 match self {
698 Self::Base(_) => None,
699 Self::Field(parent, _)
700 | Self::AnyField(parent)
701 | Self::Item(parent, _)
702 | Self::Question(parent)
703 | Self::NotNone(parent)
704 | Self::AnyItem(parent) => Some(parent),
705 }
706 }
707
708 pub(crate) fn parent_mut(&mut self) -> Option<&mut Name> {
709 match self {
710 Self::Base(_) => None,
711 Self::Field(parent, _)
712 | Self::AnyField(parent)
713 | Self::Item(parent, _)
714 | Self::Question(parent)
715 | Self::NotNone(parent)
716 | Self::AnyItem(parent) => Some(parent),
717 }
718 }
719
720 pub(crate) fn merge_parent_meta_from(&mut self, other: &NameCase) -> bool {
721 match (self.parent_mut(), other.parent()) {
722 (Some(self_parent), Some(other_parent))
723 if self_parent.case() == other_parent.case() =>
724 {
725 self_parent.merge_meta_from(other_parent)
728 }
729
730 _ => false,
739 }
740 }
741}
742
743impl Display for Name {
744 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
745 if let Some(parent) = self.parent() {
746 write!(f, "{parent}")?;
747 }
748 write!(f, "{}", self.case())
749 }
750}
751
752impl Display for NameCase {
753 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
754 match self {
755 Self::Base(name) => write!(f, "{name}"),
756 Self::Field(_parent, field) => write!(f, ".{}", quote_non_identifier(field)),
757 Self::AnyField(_parent) => write!(f, ".**"),
758 Self::Item(_parent, index) => write!(f, ".{index}"),
759 Self::AnyItem(_parent) => write!(f, ".*"),
760 Self::Question(_parent) => write!(f, "?"),
761 Self::NotNone(_parent) => write!(f, "!"),
762 }
763 }
764}
765
766#[cfg(test)]
767mod tests {
768 use super::*;
769 use crate::Shape;
770
771 #[test]
772 fn test_name() {
773 let args = Name::base("$args", []);
774 assert_eq!(args.to_string(), "$args");
775
776 let args_limit = args.field("limit", []);
777 assert_eq!(args_limit.to_string(), "$args.limit");
778
779 let args_object_any_field = args.field("object", []).any_field([]);
780 assert_eq!(args_object_any_field.to_string(), "$args.object.**");
781
782 let args_array_item_0 = args.field("array", []).item(0, []);
783 assert_eq!(args_array_item_0.to_string(), "$args.array.0");
784
785 let args_array_any_item = args.field("array", []).any_item([]);
786 assert_eq!(args_array_any_item.to_string(), "$args.array.*");
787
788 let args_array_name = args_array_any_item.field("name", []);
789 assert_eq!(args_array_name.to_string(), "$args.array.*.name");
790 }
791
792 #[test]
793 fn test_shapes_with_names() {
794 let args = Shape::strict_record(
795 {
796 let mut fields = Shape::empty_map();
797 fields.insert("value".to_string(), Shape::int_value(123, []));
798 fields.insert("array".to_string(), Shape::list(Shape::string([]), []));
799 fields
800 },
801 [],
802 )
803 .with_base_name("$args", []);
804
805 let args_value = args.field("value", []);
806 assert_eq!(
807 args_value.pretty_print_with_names(),
808 "123 (aka $args.value)"
809 );
810
811 let list_of_args_value = Shape::list(args_value.clone(), []);
812 assert_eq!(
813 list_of_args_value.pretty_print_with_names(),
814 "List<123 (aka $args.value)>"
815 );
816 assert_eq!(
817 list_of_args_value
818 .with_base_name("TheList", [])
819 .pretty_print_with_names(),
820 "List<123 (aka $args.value, TheList.*)> (aka TheList)"
821 );
822
823 let record_of_args_value = Shape::strict_record(
824 {
825 let mut fields = Shape::empty_map();
826 fields.insert("limit".to_string(), Shape::int([]));
827 fields.insert("value".to_string(), args_value.clone());
828 fields
829 },
830 [],
831 );
832 assert_eq!(
833 record_of_args_value.pretty_print_with_names(),
834 "{ limit: Int, value: 123 (aka $args.value) }"
835 );
836 assert_eq!(
837 record_of_args_value
838 .with_base_name("SomeRecord", [])
839 .pretty_print_with_names(),
840 r#"{
841 limit: Int (aka SomeRecord.limit),
842 value: 123 (aka $args.value, SomeRecord.value),
843} (aka SomeRecord)"#,
844 );
845
846 let args_value_any_item = args_value.any_item([]);
847 assert_eq!(
848 args_value_any_item.pretty_print_with_names(),
849 "123 (aka $args.value)"
851 );
852
853 let args_any_field = args.any_field([]);
854 assert_eq!(
855 args_any_field.pretty_print_with_names(),
856 r#"One<
857 123 (aka $args.value),
858 List<String (aka $args.array.*)> (aka $args.array),
859>"#
860 );
861
862 let args_array_item_2 = args.field("array", []).item(2, []);
863 assert_eq!(
864 args_array_item_2.pretty_print_with_names(),
865 r#"One<
866 String (aka $args.array.*, $args.array.2),
867 None (aka $args.array.2),
868> (aka $args.array.2)"#
869 );
870 }
871
872 #[test]
873 fn test_name_merging() {
874 let record = Shape::strict_record(
875 {
876 let mut fields = Shape::empty_map();
877
878 fields.insert("a".to_string(), Shape::int([]));
879 fields.insert("b".to_string(), Shape::string([]));
880 fields.insert("c".to_string(), Shape::bool([]));
881 fields.insert("d".to_string(), Shape::null([]));
882
883 fields.insert("A".to_string(), Shape::int([]));
884 fields.insert("B".to_string(), Shape::string([]));
885 fields.insert("C".to_string(), Shape::bool([]));
886 fields.insert("D".to_string(), Shape::null([]));
887
888 fields.insert("xyz".to_string(), Shape::list(Shape::string([]), []));
889
890 fields
891 },
892 [],
893 )
894 .with_base_name("Record", []);
895
896 assert_eq!(
897 record.pretty_print(),
898 r#"{
899 A: Int,
900 B: String,
901 C: Bool,
902 D: null,
903 a: Int,
904 b: String,
905 c: Bool,
906 d: null,
907 xyz: List<String>,
908}"#
909 );
910
911 assert_eq!(
912 record.pretty_print_with_names(),
913 r#"{
914 A: Int (aka Record.A),
915 B: String (aka Record.B),
916 C: Bool (aka Record.C),
917 D: null (aka Record.D),
918 a: Int (aka Record.a),
919 b: String (aka Record.b),
920 c: Bool (aka Record.c),
921 d: null (aka Record.d),
922 xyz: List<String (aka Record.xyz.*)> (aka Record.xyz),
923} (aka Record)"#
924 );
925
926 let record_any_field = record.any_field([]);
927
928 assert_eq!(
929 record_any_field.pretty_print(),
930 "One<Int, String, Bool, null, List<String>>"
931 );
932
933 assert_eq!(
934 record_any_field.pretty_print_with_names(),
935 r#"One<
936 Int (aka Record.a, Record.A),
937 String (aka Record.b, Record.B),
938 Bool (aka Record.c, Record.C),
939 null (aka Record.d, Record.D),
940 List<String (aka Record.xyz.*)> (aka Record.xyz),
941>"#,
942 );
943
944 let case_insensitive_a = Shape::one([record.field("a", []), record.field("A", [])], []);
945
946 assert_eq!(case_insensitive_a.pretty_print(), "Int");
947
948 assert_eq!(
949 case_insensitive_a.pretty_print_with_names(),
950 "Int (aka Record.a, Record.A)",
951 );
952 }
953}