xsd_parser/models/
ident.rs

1//! Contains the [`Ident`] helper type and all related types.
2
3use std::fmt::{Display, Formatter, Result as FmtResult};
4use std::hash::Hash;
5
6use crate::models::schema::NamespaceId;
7
8use super::Name;
9
10/// Represents a type identifier.
11#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
12pub struct Ident {
13    /// Namespace the type is defined in
14    pub ns: Option<NamespaceId>,
15
16    /// Name of the type.
17    pub name: Name,
18
19    /// Type of the identifier (because pure names are not unique in XSD).
20    pub type_: IdentType,
21}
22
23/// Type of the identifier.
24#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
25pub enum IdentType {
26    /// Used for `xs:simpleType` or `xs:complexType`.
27    Type = 0,
28
29    /// Used for `xs:group`.
30    Group = 1,
31
32    /// Used for `xs:element`.
33    Element = 2,
34
35    /// Used for inline types of `xs:element`.
36    ElementType = 3,
37
38    /// Used for `xs:attribute`.
39    Attribute = 4,
40
41    /// Used for `xs:attributeGroup`.
42    AttributeGroup = 5,
43
44    /// Used for build-in types.
45    BuildIn = 6,
46
47    /// Used for `xs:enumeration`.
48    Enumeration = 7,
49}
50
51#[allow(missing_docs)]
52impl Ident {
53    pub const UNKNOWN: Self = Self::type_("UNKNOWN");
54
55    pub const U8: Self = Self::build_in("u8");
56    pub const U16: Self = Self::build_in("u16");
57    pub const U32: Self = Self::build_in("u32");
58    pub const U64: Self = Self::build_in("u64");
59    pub const U128: Self = Self::build_in("u128");
60    pub const USIZE: Self = Self::build_in("usize");
61
62    pub const I8: Self = Self::build_in("i8");
63    pub const I16: Self = Self::build_in("i16");
64    pub const I32: Self = Self::build_in("i32");
65    pub const I64: Self = Self::build_in("i64");
66    pub const I128: Self = Self::build_in("i128");
67    pub const ISIZE: Self = Self::build_in("isize");
68
69    pub const F32: Self = Self::build_in("f32");
70    pub const F64: Self = Self::build_in("f64");
71
72    pub const BOOL: Self = Self::build_in("bool");
73    pub const STRING: Self = Self::build_in("String");
74
75    pub const ANY_TYPE: Self = Self::type_("anyType");
76
77    pub const BUILD_IN: &[Self] = &[
78        Self::U8,
79        Self::U16,
80        Self::U32,
81        Self::U64,
82        Self::U128,
83        Self::USIZE,
84        Self::I8,
85        Self::I16,
86        Self::I32,
87        Self::I64,
88        Self::I128,
89        Self::ISIZE,
90        Self::F32,
91        Self::F64,
92        Self::BOOL,
93        Self::STRING,
94    ];
95}
96
97impl Ident {
98    /// Create an [`Type`](IdentType::Type) [`Ident`]ifier with the given `name`.
99    #[must_use]
100    pub fn new(name: Name) -> Self {
101        Self {
102            ns: None,
103            name,
104            type_: IdentType::Type,
105        }
106    }
107
108    /// Create an [`Type`](IdentType::Type) [`Ident`]ifier with the given `name`.
109    #[must_use]
110    pub const fn type_(name: &'static str) -> Self {
111        Self {
112            ns: None,
113            name: Name::named(name),
114            type_: IdentType::Type,
115        }
116    }
117
118    /// Create an [`BuildIn`](IdentType::BuildIn) [`Ident`]ifier with the given `name`.
119    #[must_use]
120    pub const fn build_in(name: &'static str) -> Self {
121        Self {
122            ns: None,
123            name: Name::named(name),
124            type_: IdentType::BuildIn,
125        }
126    }
127
128    /// Create an [`Element`](IdentType::Element) [`Ident`]ifier with the given `name`.
129    #[must_use]
130    pub const fn element(name: &'static str) -> Self {
131        Self {
132            ns: None,
133            name: Name::named(name),
134            type_: IdentType::Element,
135        }
136    }
137
138    /// Create an [`Ident`]ifier suitable for field names with the given `name`.
139    #[must_use]
140    pub const fn name(name: &'static str) -> Self {
141        // We do not have a separate `IdentType` for fields, so we just use `IdentType::Type`
142        Self::type_(name)
143    }
144
145    /// Set the namespace of the identifier.
146    #[must_use]
147    pub fn with_ns(mut self, ns: Option<NamespaceId>) -> Self {
148        self.ns = ns;
149
150        self
151    }
152
153    /// Set the type of the identifier.
154    #[must_use]
155    pub fn with_type(mut self, type_: IdentType) -> Self {
156        self.type_ = type_;
157
158        self
159    }
160
161    /// Returns `true` if this is build-in type of the rust language, `false` otherwise.
162    #[must_use]
163    pub fn is_build_in(&self) -> bool {
164        Ident::BUILD_IN.contains(self)
165    }
166}
167
168impl Display for Ident {
169    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
170        let Self { ns, name, type_ } = self;
171
172        match type_ {
173            IdentType::Type => write!(f, "Type(")?,
174            IdentType::Group => write!(f, "Group(")?,
175            IdentType::BuildIn => write!(f, "BuildIn(")?,
176            IdentType::Element => write!(f, "Element(")?,
177            IdentType::ElementType => write!(f, "ElementType(")?,
178            IdentType::Attribute => write!(f, "Attribute(")?,
179            IdentType::AttributeGroup => write!(f, "AttributeGroup(")?,
180            IdentType::Enumeration => write!(f, "Enumeration(")?,
181        }
182
183        if f.sign_minus() {
184            write!(f, "{name})")?;
185        } else if let Some(ns) = ns {
186            write!(f, "ns={}, name={name})", ns.0)?;
187        } else {
188            write!(f, "ns=default, name={name})")?;
189        }
190
191        Ok(())
192    }
193}