1pub mod custom;
4pub mod ident;
5pub mod info;
6pub mod name;
7pub mod type_;
8
9mod helper;
10
11use std::collections::BTreeMap;
12use std::ops::Deref;
13use std::ops::DerefMut;
14
15pub use self::custom::CustomType;
16pub use self::helper::{VecHelper, WithIdent};
17pub use self::ident::{Ident, IdentType};
18pub use self::info::{
19 AnyAttributeInfo, AnyInfo, AttributeInfo, AttributesInfo, Base, ComplexInfo, DynamicInfo,
20 ElementInfo, ElementMode, ElementsInfo, EnumerationInfo, GroupInfo, ReferenceInfo, UnionInfo,
21 UnionTypeInfo, UnionTypesInfo, VariantInfo,
22};
23pub use self::name::Name;
24pub use self::type_::{BuildInInfo, Type, TypeEq, TypeVariant};
25
26use crate::schema::{Namespace, NamespaceId};
27
28#[derive(Default, Debug)]
34pub struct Types {
35 pub types: BTreeMap<Ident, Type>,
37
38 pub modules: BTreeMap<NamespaceId, Module>,
40
41 next_name_id: usize,
42}
43
44#[derive(Debug)]
46pub struct Module {
47 pub name: Option<Name>,
49
50 pub namespace: Option<Namespace>,
52}
53
54impl Types {
55 pub fn make_unnamed(&mut self) -> Name {
57 self.next_name_id = self.next_name_id.wrapping_add(1);
58
59 Name::Unnamed {
60 id: self.next_name_id,
61 ext: None,
62 }
63 }
64
65 #[must_use]
72 pub fn get_resolved<'a>(&'a self, ident: &'a Ident) -> Option<(&'a Ident, &'a Type)> {
73 let mut visit = Vec::new();
74
75 get_resolved_impl(self, ident, &mut visit)
76 }
77
78 #[must_use]
83 pub fn get_resolved_type<'a>(&'a self, ident: &'a Ident) -> Option<&'a Type> {
84 self.get_resolved(ident).map(|(_ident, ty)| ty)
85 }
86
87 #[must_use]
92 pub fn get_resolved_ident<'a>(&'a self, ident: &'a Ident) -> Option<&'a Ident> {
93 self.get_resolved(ident).map(|(ident, _ty)| ident)
94 }
95
96 #[inline]
100 #[must_use]
101 pub fn get_variant(&self, ident: &Ident) -> Option<&TypeVariant> {
102 self.get(ident).map(|ty| &ty.variant)
103 }
104
105 #[inline]
109 #[must_use]
110 pub fn get_variant_mut(&mut self, ident: &Ident) -> Option<&mut TypeVariant> {
111 self.get_mut(ident).map(|ty| &mut ty.variant)
112 }
113}
114
115impl Deref for Types {
116 type Target = BTreeMap<Ident, Type>;
117
118 fn deref(&self) -> &Self::Target {
119 &self.types
120 }
121}
122
123impl DerefMut for Types {
124 fn deref_mut(&mut self) -> &mut Self::Target {
125 &mut self.types
126 }
127}
128
129fn get_resolved_impl<'a>(
130 types: &'a Types,
131 ident: &'a Ident,
132 visited: &mut Vec<&'a Ident>,
133) -> Option<(&'a Ident, &'a Type)> {
134 if visited.contains(&ident) {
135 let chain = visited
136 .iter()
137 .map(ToString::to_string)
138 .chain(Some(ident.to_string()))
139 .collect::<Vec<_>>()
140 .join(" >> ");
141
142 tracing::debug!("Detected type reference loop: {chain}");
143
144 return None;
145 }
146
147 let ty = types.get(ident)?;
148
149 match &ty.variant {
150 TypeVariant::Reference(x) if x.is_single() => {
151 visited.push(ident);
152
153 let ret = match get_resolved_impl(types, &x.type_, visited) {
154 None => Some((ident, ty)),
155 Some((ident, ty)) => Some((ident, ty)),
156 };
157
158 visited.pop();
159
160 ret
161 }
162 _ => Some((ident, ty)),
163 }
164}