xsd_parser/types/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! The `types` module contains all type information related types.

pub mod custom;
pub mod ident;
pub mod info;
pub mod name;
pub mod type_;

mod helper;

use std::collections::BTreeMap;
use std::collections::HashSet;
use std::ops::Deref;
use std::ops::DerefMut;

pub use self::custom::CustomType;
pub use self::helper::{VecHelper, WithIdent};
pub use self::ident::{Ident, IdentType};
pub use self::info::{
    AbstractInfo, AnyAttributeInfo, AnyInfo, AttributeInfo, AttributesInfo, Base, ComplexInfo,
    ElementInfo, ElementMode, ElementsInfo, EnumerationInfo, GroupInfo, ReferenceInfo, UnionInfo,
    UnionTypeInfo, UnionTypesInfo, VariantInfo,
};
pub use self::name::Name;
pub use self::type_::{BuildInInfo, Type, TypeEq};

use crate::schema::{Namespace, NamespaceId};

/// This structure contains information about the type and module definitions.
///
/// It is created by the [`Interpreter`](crate::interpreter::Interpreter) by reading
/// the data of a specific [`Schemas`](crate::schema::Schemas). The types of this
/// structure can be optimized further using the [`Optimizer`](crate::optimizer::Optimizer).
#[derive(Default, Debug)]
pub struct Types {
    /// Map of the different types.
    pub types: BTreeMap<Ident, Type>,

    /// Map of the different namespaces.
    pub modules: BTreeMap<NamespaceId, Module>,

    next_name_id: usize,
}

/// Represents a module used by type information in the [`Types`] structure.
#[derive(Debug)]
pub struct Module {
    /// Name of the module (also used as xml prefix).
    pub name: Name,

    /// Namespace of the module.
    pub namespace: Namespace,
}

impl Types {
    /// Create a new [`Name::Unnamed`] name by using a unique io for this name.
    pub fn make_unnamed(&mut self) -> Name {
        self.next_name_id = self.next_name_id.wrapping_add(1);

        Name::Unnamed {
            id: self.next_name_id,
            ext: None,
        }
    }

    /// Get the type of the passed `ident` with all single type references resolved.
    ///
    /// Tries to find the type specified by the passed `ident` and resolve simple
    /// type definitions to the very base type. If the type could not be found `None`
    /// is returned.
    #[must_use]
    pub fn get_resolved(&self, ident: &Ident) -> Option<&Type> {
        let mut visit = HashSet::new();

        get_resolved(self, &mut visit, ident)
    }
}

impl Deref for Types {
    type Target = BTreeMap<Ident, Type>;

    fn deref(&self) -> &Self::Target {
        &self.types
    }
}

impl DerefMut for Types {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.types
    }
}

fn get_resolved<'a>(
    types: &'a Types,
    visited: &mut HashSet<Ident>,
    ident: &Ident,
) -> Option<&'a Type> {
    if !visited.insert(ident.clone()) {
        return None;
    }

    let ty = types.get(ident)?;

    match ty {
        Type::Reference(x) if x.is_single() => match get_resolved(types, visited, &x.type_) {
            None => Some(ty),
            Some(ty) => Some(ty),
        },
        _ => Some(ty),
    }
}