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    /// Used to define the content for [`Nillable`](xsd_parser_types::xml::Nillable) types.
51    NillableContent = 8,
52
53    /// One concrete element in a substitution group.
54    DynamicElement = 9,
55}
56
57#[allow(missing_docs)]
58impl Ident {
59    pub const UNKNOWN: Self = Self::type_("UNKNOWN");
60
61    pub const U8: Self = Self::build_in("u8");
62    pub const U16: Self = Self::build_in("u16");
63    pub const U32: Self = Self::build_in("u32");
64    pub const U64: Self = Self::build_in("u64");
65    pub const U128: Self = Self::build_in("u128");
66    pub const USIZE: Self = Self::build_in("usize");
67
68    pub const I8: Self = Self::build_in("i8");
69    pub const I16: Self = Self::build_in("i16");
70    pub const I32: Self = Self::build_in("i32");
71    pub const I64: Self = Self::build_in("i64");
72    pub const I128: Self = Self::build_in("i128");
73    pub const ISIZE: Self = Self::build_in("isize");
74
75    pub const F32: Self = Self::build_in("f32");
76    pub const F64: Self = Self::build_in("f64");
77
78    pub const BOOL: Self = Self::build_in("bool");
79    pub const STRING: Self = Self::build_in("String");
80
81    pub const ANY_TYPE: Self = Self::type_("anyType");
82
83    pub const BUILD_IN: &[Self] = &[
84        Self::U8,
85        Self::U16,
86        Self::U32,
87        Self::U64,
88        Self::U128,
89        Self::USIZE,
90        Self::I8,
91        Self::I16,
92        Self::I32,
93        Self::I64,
94        Self::I128,
95        Self::ISIZE,
96        Self::F32,
97        Self::F64,
98        Self::BOOL,
99        Self::STRING,
100    ];
101}
102
103impl Ident {
104    /// Create an [`Type`](IdentType::Type) [`Ident`]ifier with the given `name`.
105    #[must_use]
106    pub fn new(name: Name) -> Self {
107        Self {
108            ns: None,
109            name,
110            type_: IdentType::Type,
111        }
112    }
113
114    /// Create an [`Type`](IdentType::Type) [`Ident`]ifier with the given `name`.
115    #[must_use]
116    pub const fn type_(name: &'static str) -> Self {
117        Self {
118            ns: None,
119            name: Name::named(name),
120            type_: IdentType::Type,
121        }
122    }
123
124    /// Create an [`BuildIn`](IdentType::BuildIn) [`Ident`]ifier with the given `name`.
125    #[must_use]
126    pub const fn build_in(name: &'static str) -> Self {
127        Self {
128            ns: None,
129            name: Name::named(name),
130            type_: IdentType::BuildIn,
131        }
132    }
133
134    /// Create an [`Element`](IdentType::Element) [`Ident`]ifier with the given `name`.
135    #[must_use]
136    pub const fn element(name: &'static str) -> Self {
137        Self {
138            ns: None,
139            name: Name::named(name),
140            type_: IdentType::Element,
141        }
142    }
143
144    /// Create an [`Ident`]ifier suitable for field names with the given `name`.
145    #[must_use]
146    pub const fn name(name: &'static str) -> Self {
147        // We do not have a separate `IdentType` for fields, so we just use `IdentType::Type`
148        Self::type_(name)
149    }
150
151    /// Set the namespace of the identifier.
152    #[must_use]
153    pub fn with_ns(mut self, ns: Option<NamespaceId>) -> Self {
154        self.ns = ns;
155
156        self
157    }
158
159    /// Set the type of the identifier.
160    #[must_use]
161    pub fn with_type(mut self, type_: IdentType) -> Self {
162        self.type_ = type_;
163
164        self
165    }
166
167    /// Returns `true` if this is build-in type of the rust language, `false` otherwise.
168    #[must_use]
169    pub fn is_build_in(&self) -> bool {
170        Ident::BUILD_IN.contains(self)
171    }
172}
173
174impl Display for Ident {
175    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
176        let Self { ns, name, type_ } = self;
177
178        match type_ {
179            IdentType::Type => write!(f, "Type(")?,
180            IdentType::Group => write!(f, "Group(")?,
181            IdentType::BuildIn => write!(f, "BuildIn(")?,
182            IdentType::Element => write!(f, "Element(")?,
183            IdentType::ElementType => write!(f, "ElementType(")?,
184            IdentType::Attribute => write!(f, "Attribute(")?,
185            IdentType::AttributeGroup => write!(f, "AttributeGroup(")?,
186            IdentType::Enumeration => write!(f, "Enumeration(")?,
187            IdentType::NillableContent => write!(f, "NillableContent(")?,
188            IdentType::DynamicElement => write!(f, "DynamicElement(")?,
189        }
190
191        if f.sign_minus() {
192            write!(f, "{name})")?;
193        } else if let Some(ns) = ns {
194            write!(f, "ns={}, name={name})", ns.0)?;
195        } else {
196            write!(f, "ns=default, name={name})")?;
197        }
198
199        Ok(())
200    }
201}