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 Ident, Name, Naming,
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<Ident, 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>(&'a self, ident: &'a Ident) -> Option<(&'a Ident, &'a MetaType)> {
81 let mut visit = Vec::new();
82
83 get_resolved_impl(self, ident, &mut visit)
84 }
85
86 #[must_use]
91 pub fn get_resolved_type<'a>(&'a self, ident: &'a Ident) -> Option<&'a MetaType> {
92 self.get_resolved(ident).map(|(_ident, ty)| ty)
93 }
94
95 #[must_use]
100 pub fn get_resolved_ident<'a>(&'a self, ident: &'a Ident) -> Option<&'a Ident> {
101 self.get_resolved(ident).map(|(ident, _ty)| ident)
102 }
103
104 #[inline]
108 #[must_use]
109 pub fn get_variant(&self, ident: &Ident) -> Option<&MetaTypeVariant> {
110 self.items.get(ident).map(|ty| &ty.variant)
111 }
112
113 #[inline]
117 #[must_use]
118 pub fn get_variant_mut(&mut self, ident: &Ident) -> Option<&mut MetaTypeVariant> {
119 self.items.get_mut(ident).map(|ty| &mut ty.variant)
120 }
121}
122
123impl Default for MetaTypes {
124 fn default() -> Self {
125 Self {
126 items: Default::default(),
127 modules: Default::default(),
128 schemas: Default::default(),
129 naming: Box::new(Naming::default()),
130 }
131 }
132}
133
134impl ModuleMeta {
135 #[must_use]
137 pub fn name(&self) -> Option<&Name> {
138 self.name.as_ref().or(self.prefix.as_ref())
139 }
140
141 #[must_use]
143 pub fn prefix(&self) -> Option<&Name> {
144 self.prefix.as_ref().or(self.name.as_ref())
145 }
146}
147
148fn get_resolved_impl<'a>(
149 types: &'a MetaTypes,
150 ident: &'a Ident,
151 visited: &mut Vec<&'a Ident>,
152) -> Option<(&'a Ident, &'a MetaType)> {
153 if visited.contains(&ident) {
154 let chain = visited
155 .iter()
156 .map(ToString::to_string)
157 .chain(Some(ident.to_string()))
158 .collect::<Vec<_>>()
159 .join(" >> ");
160
161 tracing::debug!("Detected type reference loop: {chain}");
162
163 return None;
164 }
165
166 let ty = types.items.get(ident)?;
167
168 match &ty.variant {
169 MetaTypeVariant::Reference(x) if x.is_simple() => {
170 visited.push(ident);
171
172 let ret = match get_resolved_impl(types, &x.type_, visited) {
173 None => Some((ident, ty)),
174 Some((ident, ty)) => Some((ident, ty)),
175 };
176
177 visited.pop();
178
179 ret
180 }
181 _ => Some((ident, ty)),
182 }
183}