xsd_parser/types/
mod.rs

1//! The `types` module contains all type information related types.
2
3pub 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/// This structure contains information about the type and module definitions.
29///
30/// It is created by the [`Interpreter`](crate::interpreter::Interpreter) by reading
31/// the data of a specific [`Schemas`](crate::schema::Schemas). The types of this
32/// structure can be optimized further using the [`Optimizer`](crate::optimizer::Optimizer).
33#[derive(Default, Debug)]
34pub struct Types {
35    /// Map of the different types.
36    pub types: BTreeMap<Ident, Type>,
37
38    /// Map of the different namespaces.
39    pub modules: BTreeMap<NamespaceId, Module>,
40
41    next_name_id: usize,
42}
43
44/// Represents a module used by type information in the [`Types`] structure.
45#[derive(Debug)]
46pub struct Module {
47    /// Name of the module (also used as xml prefix).
48    pub name: Option<Name>,
49
50    /// Namespace of the module.
51    pub namespace: Option<Namespace>,
52}
53
54impl Types {
55    /// Create a new [`Name::Unnamed`] name by using a unique io for this name.
56    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    /// Get the identifier and the type of the passed `ident` with all single
66    /// type references resolved.
67    ///
68    /// Tries to find the type specified by the passed `ident` and resolve simple
69    /// type definitions to the very base type. If the type could not be found `None`
70    /// is returned.
71    #[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    /// Get the type of the passed `ident` with all single type references resolved.
79    ///
80    /// Like [`get_resolved`](Self::get_resolved), but instead of returning the identifier and
81    /// the type it will return only the resolved type.
82    #[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    /// Get the type ident of the passed `ident` with all single type references resolved.
88    ///
89    /// Like [`get_resolved`](Self::get_resolved), but instead of returning the identifier and
90    /// the type it will return only the identifier of the resolved type.
91    #[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    /// Return the [`TypeVariant`] of corresponding type for the passed identifier.
97    ///
98    /// This is a shorthand for `self.get(ident).map(|ty| &type.variant)`.
99    #[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    /// Return the [`TypeVariant`] of corresponding type for the passed identifier.
106    ///
107    /// This is a shorthand for `self.get_mut(ident).map(|ty| &type.variant)`.
108    #[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}