xsd_parser/models/meta/
types.rs1use std::collections::BTreeMap;
2
3use xsd_parser_types::misc::Namespace;
4
5use crate::models::{
6 schema::{NamespaceId, SchemaId},
7 Name, Naming, TypeIdent,
8};
9use crate::traits::{NameBuilder as NameBuilderTrait, Naming as NamingTrait};
10
11use super::{MetaType, MetaTypeVariant};
12
13#[derive(Debug)]
23pub struct MetaTypes {
24 pub items: BTreeMap<TypeIdent, MetaType>,
26
27 pub modules: BTreeMap<NamespaceId, ModuleMeta>,
29
30 pub schemas: BTreeMap<SchemaId, SchemaMeta>,
32
33 pub naming: Box<dyn NamingTrait>,
35}
36
37#[derive(Debug)]
39pub struct ModuleMeta {
40 pub name: Option<Name>,
42
43 pub prefix: Option<Name>,
45
46 pub namespace: Option<Namespace>,
48
49 pub namespace_id: NamespaceId,
51
52 pub schema_count: usize,
54}
55
56#[derive(Debug)]
58pub struct SchemaMeta {
59 pub name: Option<Name>,
61
62 pub namespace: NamespaceId,
64}
65
66impl MetaTypes {
67 #[must_use]
69 pub fn name_builder(&self) -> Box<dyn NameBuilderTrait> {
70 self.naming.builder()
71 }
72
73 #[must_use]
80 pub fn get_resolved<'a>(
81 &'a self,
82 ident: &'a TypeIdent,
83 ) -> Option<(&'a TypeIdent, &'a MetaType)> {
84 let mut visit = Vec::new();
85
86 get_resolved_impl(self, ident, &mut visit)
87 }
88
89 #[must_use]
94 pub fn get_resolved_type<'a>(&'a self, ident: &'a TypeIdent) -> Option<&'a MetaType> {
95 self.get_resolved(ident).map(|(_ident, ty)| ty)
96 }
97
98 #[must_use]
103 pub fn get_resolved_ident<'a>(&'a self, ident: &'a TypeIdent) -> Option<&'a TypeIdent> {
104 self.get_resolved(ident).map(|(ident, _ty)| ident)
105 }
106
107 #[inline]
111 #[must_use]
112 pub fn get_variant(&self, ident: &TypeIdent) -> Option<&MetaTypeVariant> {
113 self.items.get(ident).map(|ty| &ty.variant)
114 }
115
116 #[inline]
120 #[must_use]
121 pub fn get_variant_mut(&mut self, ident: &TypeIdent) -> Option<&mut MetaTypeVariant> {
122 self.items.get_mut(ident).map(|ty| &mut ty.variant)
123 }
124}
125
126impl Default for MetaTypes {
127 fn default() -> Self {
128 Self {
129 items: Default::default(),
130 modules: Default::default(),
131 schemas: Default::default(),
132 naming: Box::new(Naming::default()),
133 }
134 }
135}
136
137impl ModuleMeta {
138 #[must_use]
140 pub fn name(&self) -> Option<&Name> {
141 self.name.as_ref().or(self.prefix.as_ref())
142 }
143
144 #[must_use]
146 pub fn prefix(&self) -> Option<&Name> {
147 self.prefix.as_ref().or(self.name.as_ref())
148 }
149}
150
151fn get_resolved_impl<'a>(
152 types: &'a MetaTypes,
153 ident: &'a TypeIdent,
154 visited: &mut Vec<&'a TypeIdent>,
155) -> Option<(&'a TypeIdent, &'a MetaType)> {
156 if visited.contains(&ident) {
157 let chain = visited
158 .iter()
159 .map(ToString::to_string)
160 .chain(Some(ident.to_string()))
161 .collect::<Vec<_>>()
162 .join(" >> ");
163
164 tracing::debug!("Detected type reference loop: {chain}");
165
166 return None;
167 }
168
169 let ty = types.items.get(ident)?;
170
171 match &ty.variant {
172 MetaTypeVariant::Reference(x) if x.is_simple() => {
173 visited.push(ident);
174
175 let ret = match get_resolved_impl(types, &x.type_, visited) {
176 None => Some((ident, ty)),
177 Some((ident, ty)) => Some((ident, ty)),
178 };
179
180 visited.pop();
181
182 ret
183 }
184 _ => Some((ident, ty)),
185 }
186}