1use std::fmt::{Display, Formatter, Result as FmtResult};
4use std::hash::{Hash, Hasher};
5
6use crate::schema::NamespaceId;
7
8use super::{get_resolved, Name, TypeEq, Types};
9
10#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
12pub struct Ident {
13 pub ns: Option<NamespaceId>,
15
16 pub name: Name,
18
19 pub type_: IdentType,
21}
22
23#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
25pub enum IdentType {
26 Type = 0,
28
29 Group = 1,
31
32 Element = 2,
34
35 ElementType = 3,
37
38 Attribute = 4,
40
41 AttributeGroup = 5,
43
44 BuildIn = 6,
46
47 Enumeration = 7,
49}
50
51#[allow(missing_docs)]
52impl Ident {
53 pub const U8: Self = Self::build_in("u8");
54 pub const U16: Self = Self::build_in("u16");
55 pub const U32: Self = Self::build_in("u32");
56 pub const U64: Self = Self::build_in("u64");
57 pub const U128: Self = Self::build_in("u128");
58 pub const USIZE: Self = Self::build_in("usize");
59
60 pub const I8: Self = Self::build_in("i8");
61 pub const I16: Self = Self::build_in("i16");
62 pub const I32: Self = Self::build_in("i32");
63 pub const I64: Self = Self::build_in("i64");
64 pub const I128: Self = Self::build_in("i128");
65 pub const ISIZE: Self = Self::build_in("isize");
66
67 pub const F32: Self = Self::build_in("f32");
68 pub const F64: Self = Self::build_in("f64");
69
70 pub const BOOL: Self = Self::build_in("bool");
71 pub const STRING: Self = Self::build_in("String");
72
73 pub const ANY_TYPE: Self = Self::type_("anyType");
74
75 pub const BUILD_IN: &[Self] = &[
76 Self::U8,
77 Self::U16,
78 Self::U32,
79 Self::U64,
80 Self::U128,
81 Self::USIZE,
82 Self::I8,
83 Self::I16,
84 Self::I32,
85 Self::I64,
86 Self::I128,
87 Self::ISIZE,
88 Self::F32,
89 Self::F64,
90 Self::BOOL,
91 Self::STRING,
92 ];
93}
94
95impl Ident {
96 #[must_use]
98 pub fn new(name: Name) -> Self {
99 Self {
100 ns: None,
101 name,
102 type_: IdentType::Type,
103 }
104 }
105
106 #[must_use]
108 pub const fn type_(name: &'static str) -> Self {
109 Self {
110 ns: None,
111 name: Name::named(name),
112 type_: IdentType::Type,
113 }
114 }
115
116 #[must_use]
118 pub const fn build_in(name: &'static str) -> Self {
119 Self {
120 ns: None,
121 name: Name::named(name),
122 type_: IdentType::BuildIn,
123 }
124 }
125
126 #[must_use]
128 pub const fn element(name: &'static str) -> Self {
129 Self {
130 ns: None,
131 name: Name::named(name),
132 type_: IdentType::Element,
133 }
134 }
135
136 #[must_use]
138 pub fn with_ns(mut self, ns: Option<NamespaceId>) -> Self {
139 self.ns = ns;
140
141 self
142 }
143
144 #[must_use]
146 pub fn with_type(mut self, type_: IdentType) -> Self {
147 self.type_ = type_;
148
149 self
150 }
151
152 #[must_use]
154 pub fn is_build_in(&self) -> bool {
155 Ident::BUILD_IN.contains(self)
156 }
157}
158
159impl Display for Ident {
160 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
161 let Self { ns, name, type_ } = self;
162
163 match type_ {
164 IdentType::Type => write!(f, "Type(")?,
165 IdentType::Group => write!(f, "Group(")?,
166 IdentType::BuildIn => write!(f, "BuildIn(")?,
167 IdentType::Element => write!(f, "Element(")?,
168 IdentType::ElementType => write!(f, "ElementType(")?,
169 IdentType::Attribute => write!(f, "Attribute(")?,
170 IdentType::AttributeGroup => write!(f, "AttributeGroup(")?,
171 IdentType::Enumeration => write!(f, "Enumeration(")?,
172 }
173
174 if f.sign_minus() {
175 write!(f, "{name})")?;
176 } else if let Some(ns) = ns {
177 write!(f, "ns={}, name={name})", ns.0)?;
178 } else {
179 write!(f, "ns=default, name={name})")?;
180 }
181
182 Ok(())
183 }
184}
185
186impl TypeEq for Ident {
187 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &Types) {
188 let mut visit = Vec::new();
189
190 get_resolved(types, self, &mut visit)
191 .map_or(self, |(ident, _ty)| ident)
192 .hash(hasher);
193 }
194
195 fn type_eq(&self, other: &Self, types: &Types) -> bool {
196 let a = {
197 let mut visit = Vec::new();
198
199 get_resolved(types, self, &mut visit).map(|(ident, _ty)| ident)
200 };
201
202 let b = {
203 let mut visit = Vec::new();
204
205 get_resolved(types, other, &mut visit).map(|(ident, _ty)| ident)
206 };
207
208 a == b
209 }
210}