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(crate) fn locs(&self) -> impl Iterator<Item = &Location> {
654 self.locs.iter()
655 }
656
657 #[allow(dead_code)]
658 pub(crate) fn with_locs<'a>(&self, locs: impl IntoIterator<Item = &'a Location>) -> Self {
659 let mut clone = self.clone();
660 clone.add_locs(locs);
661 clone
662 }
663
664 #[allow(dead_code)]
665 pub(crate) fn add_locs<'a>(&mut self, locs: impl IntoIterator<Item = &'a Location>) -> bool {
666 let mut changed = false;
667 for loc in locs {
668 if !self.locs.contains(loc) {
669 Ref::make_mut(&mut self.locs).insert(loc.clone());
670 changed = true;
671 }
672 }
673 changed
674 }
675
676 pub(crate) fn parent(&self) -> Option<&Name> {
677 self.case.parent()
678 }
679}
680
681#[derive(Clone, Debug, PartialEq, Eq, Hash)]
682pub enum NameCase {
683 Base(String),
684 Field(Name, String),
685 AnyField(Name),
686 Item(Name, usize),
687 AnyItem(Name),
688 Question(Name),
689 NotNone(Name),
690}
691
692impl NameCase {
693 pub(crate) fn parent(&self) -> Option<&Name> {
694 match self {
695 Self::Base(_) => None,
696 Self::Field(parent, _)
697 | Self::AnyField(parent)
698 | Self::Item(parent, _)
699 | Self::Question(parent)
700 | Self::NotNone(parent)
701 | Self::AnyItem(parent) => Some(parent),
702 }
703 }
704
705 pub(crate) fn parent_mut(&mut self) -> Option<&mut Name> {
706 match self {
707 Self::Base(_) => None,
708 Self::Field(parent, _)
709 | Self::AnyField(parent)
710 | Self::Item(parent, _)
711 | Self::Question(parent)
712 | Self::NotNone(parent)
713 | Self::AnyItem(parent) => Some(parent),
714 }
715 }
716
717 pub(crate) fn merge_parent_meta_from(&mut self, other: &NameCase) -> bool {
718 match (self.parent_mut(), other.parent()) {
719 (Some(self_parent), Some(other_parent))
720 if self_parent.case() == other_parent.case() =>
721 {
722 self_parent.merge_meta_from(other_parent)
725 }
726
727 _ => false,
736 }
737 }
738}
739
740impl Display for Name {
741 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
742 if let Some(parent) = self.parent() {
743 write!(f, "{parent}")?;
744 }
745 write!(f, "{}", self.case())
746 }
747}
748
749impl Display for NameCase {
750 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
751 match self {
752 Self::Base(name) => write!(f, "{name}"),
753 Self::Field(_parent, field) => write!(f, ".{}", quote_non_identifier(field)),
754 Self::AnyField(_parent) => write!(f, ".**"),
755 Self::Item(_parent, index) => write!(f, ".{index}"),
756 Self::AnyItem(_parent) => write!(f, ".*"),
757 Self::Question(_parent) => write!(f, "?"),
758 Self::NotNone(_parent) => write!(f, "!"),
759 }
760 }
761}
762
763#[cfg(test)]
764mod tests {
765 use super::*;
766 use crate::Shape;
767
768 #[test]
769 fn test_name() {
770 let args = Name::base("$args", []);
771 assert_eq!(args.to_string(), "$args");
772
773 let args_limit = args.field("limit", []);
774 assert_eq!(args_limit.to_string(), "$args.limit");
775
776 let args_object_any_field = args.field("object", []).any_field([]);
777 assert_eq!(args_object_any_field.to_string(), "$args.object.**");
778
779 let args_array_item_0 = args.field("array", []).item(0, []);
780 assert_eq!(args_array_item_0.to_string(), "$args.array.0");
781
782 let args_array_any_item = args.field("array", []).any_item([]);
783 assert_eq!(args_array_any_item.to_string(), "$args.array.*");
784
785 let args_array_name = args_array_any_item.field("name", []);
786 assert_eq!(args_array_name.to_string(), "$args.array.*.name");
787 }
788
789 #[test]
790 fn test_shapes_with_names() {
791 let args = Shape::record(
792 {
793 let mut fields = Shape::empty_map();
794 fields.insert("value".to_string(), Shape::int_value(123, []));
795 fields.insert("array".to_string(), Shape::list(Shape::string([]), []));
796 fields
797 },
798 [],
799 )
800 .with_base_name("$args", []);
801
802 let args_value = args.field("value", []);
803 assert_eq!(
804 args_value.pretty_print_with_names(),
805 "123 (aka $args.value)"
806 );
807
808 let list_of_args_value = Shape::list(args_value.clone(), []);
809 assert_eq!(
810 list_of_args_value.pretty_print_with_names(),
811 "List<123 (aka $args.value)>"
812 );
813 assert_eq!(
814 list_of_args_value
815 .with_base_name("TheList", [])
816 .pretty_print_with_names(),
817 "List<123 (aka $args.value, TheList.*)> (aka TheList)"
818 );
819
820 let record_of_args_value = Shape::record(
821 {
822 let mut fields = Shape::empty_map();
823 fields.insert("limit".to_string(), Shape::int([]));
824 fields.insert("value".to_string(), args_value.clone());
825 fields
826 },
827 [],
828 );
829 assert_eq!(
830 record_of_args_value.pretty_print_with_names(),
831 "{ limit: Int, value: 123 (aka $args.value) }"
832 );
833 assert_eq!(
834 record_of_args_value
835 .with_base_name("SomeRecord", [])
836 .pretty_print_with_names(),
837 r#"{
838 limit: Int (aka SomeRecord.limit),
839 value: 123 (aka $args.value, SomeRecord.value),
840} (aka SomeRecord)"#,
841 );
842
843 let args_value_any_item = args_value.any_item([]);
844 assert_eq!(
845 args_value_any_item.pretty_print_with_names(),
846 "123 (aka $args.value)"
848 );
849
850 let args_any_field = args.any_field([]);
851 assert_eq!(
852 args_any_field.pretty_print_with_names(),
853 r#"One<
854 123 (aka $args.value),
855 List<String (aka $args.array.*)> (aka $args.array),
856>"#
857 );
858
859 let args_array_item_2 = args.field("array", []).item(2, []);
860 assert_eq!(
861 args_array_item_2.pretty_print_with_names(),
862 r#"One<
863 String (aka $args.array.*, $args.array.2),
864 None (aka $args.array.2),
865> (aka $args.array.2)"#
866 );
867 }
868
869 #[test]
870 fn test_name_merging() {
871 let record = Shape::record(
872 {
873 let mut fields = Shape::empty_map();
874
875 fields.insert("a".to_string(), Shape::int([]));
876 fields.insert("b".to_string(), Shape::string([]));
877 fields.insert("c".to_string(), Shape::bool([]));
878 fields.insert("d".to_string(), Shape::null([]));
879
880 fields.insert("A".to_string(), Shape::int([]));
881 fields.insert("B".to_string(), Shape::string([]));
882 fields.insert("C".to_string(), Shape::bool([]));
883 fields.insert("D".to_string(), Shape::null([]));
884
885 fields.insert("xyz".to_string(), Shape::list(Shape::string([]), []));
886
887 fields
888 },
889 [],
890 )
891 .with_base_name("Record", []);
892
893 assert_eq!(
894 record.pretty_print(),
895 r#"{
896 A: Int,
897 B: String,
898 C: Bool,
899 D: null,
900 a: Int,
901 b: String,
902 c: Bool,
903 d: null,
904 xyz: List<String>,
905}"#
906 );
907
908 assert_eq!(
909 record.pretty_print_with_names(),
910 r#"{
911 A: Int (aka Record.A),
912 B: String (aka Record.B),
913 C: Bool (aka Record.C),
914 D: null (aka Record.D),
915 a: Int (aka Record.a),
916 b: String (aka Record.b),
917 c: Bool (aka Record.c),
918 d: null (aka Record.d),
919 xyz: List<String (aka Record.xyz.*)> (aka Record.xyz),
920} (aka Record)"#
921 );
922
923 let record_any_field = record.any_field([]);
924
925 assert_eq!(
926 record_any_field.pretty_print(),
927 "One<Int, String, Bool, null, List<String>>"
928 );
929
930 assert_eq!(
931 record_any_field.pretty_print_with_names(),
932 r#"One<
933 Int (aka Record.a, Record.A),
934 String (aka Record.b, Record.B),
935 Bool (aka Record.c, Record.C),
936 null (aka Record.d, Record.D),
937 List<String (aka Record.xyz.*)> (aka Record.xyz),
938>"#,
939 );
940
941 let case_insensitive_a = Shape::one([record.field("a", []), record.field("A", [])], []);
942
943 assert_eq!(case_insensitive_a.pretty_print(), "Int");
944
945 assert_eq!(
946 case_insensitive_a.pretty_print_with_names(),
947 "Int (aka Record.a, Record.A)",
948 );
949 }
950}