1use std::hash::{Hash, Hasher};
4use std::ops::{Deref, DerefMut};
5
6use xsd_parser_types::xml::NamespacesShared;
7
8use crate::models::{
9 meta::{MetaTypes, TypeEq},
10 schema::xs::{
11 FormChoiceType, NamespaceListType, NotNamespaceType, ProcessContentsType, QnameListAType,
12 Use,
13 },
14 AttributeIdent, TypeIdent,
15};
16
17#[derive(Debug, Clone)]
19pub struct AttributeMeta {
20 pub ident: AttributeIdent,
22
23 pub variant: AttributeMetaVariant,
25
26 pub use_: Use,
28
29 pub form: FormChoiceType,
31
32 pub default: Option<String>,
34
35 pub display_name: Option<String>,
37
38 pub documentation: Vec<String>,
40
41 pub namespaces: Option<NamespacesShared<'static>>,
43}
44
45#[derive(Debug, Clone)]
49pub enum AttributeMetaVariant {
50 Any(AnyAttributeMeta),
52
53 Type(TypeIdent),
55}
56
57#[allow(missing_docs)]
60#[derive(Debug, Clone, Eq, PartialEq)]
61pub struct AnyAttributeMeta {
62 pub id: Option<String>,
63 pub namespace: Option<NamespaceListType>,
64 pub not_q_name: Option<QnameListAType>,
65 pub not_namespace: Option<NotNamespaceType>,
66 pub process_contents: ProcessContentsType,
67}
68
69#[derive(Default, Debug, Clone)]
71pub struct AttributesMeta(Vec<AttributeMeta>);
72
73impl AttributeMeta {
76 #[must_use]
78 pub fn new(ident: AttributeIdent, type_: TypeIdent, form: FormChoiceType) -> Self {
79 Self {
80 ident,
81 variant: AttributeMetaVariant::Type(type_),
82 use_: Use::Optional,
83 form,
84 default: None,
85 display_name: None,
86 documentation: Vec::new(),
87 namespaces: None,
88 }
89 }
90
91 #[must_use]
93 pub fn any(ident: AttributeIdent, any: AnyAttributeMeta) -> Self {
94 Self {
95 ident,
96 variant: AttributeMetaVariant::Any(any),
97 use_: Use::Required,
98 form: FormChoiceType::Unqualified,
99 default: None,
100 display_name: None,
101 documentation: Vec::new(),
102 namespaces: None,
103 }
104 }
105
106 #[must_use]
108 pub fn with_use(mut self, use_: Use) -> Self {
109 self.use_ = use_;
110
111 self
112 }
113
114 #[must_use]
116 pub fn is_any(&self) -> bool {
117 matches!(&self.variant, AttributeMetaVariant::Any(_))
118 }
119
120 #[must_use]
122 pub fn as_any(&self) -> Option<&AnyAttributeMeta> {
123 if let AttributeMetaVariant::Any(any) = &self.variant {
124 Some(any)
125 } else {
126 None
127 }
128 }
129}
130
131impl TypeEq for AttributeMeta {
132 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &MetaTypes) {
133 let Self {
134 ident,
135 variant,
136 use_,
137 form,
138 default,
139 display_name,
140 documentation,
141 namespaces,
142 } = self;
143
144 ident.hash(hasher);
145 variant.type_hash(hasher, types);
146 use_.hash(hasher);
147 form.hash(hasher);
148 default.hash(hasher);
149 display_name.hash(hasher);
150 documentation.hash(hasher);
151 namespaces.hash(hasher);
152 }
153
154 fn type_eq(&self, other: &Self, types: &MetaTypes) -> bool {
155 let Self {
156 ident,
157 variant: type_,
158 use_,
159 form,
160 default,
161 display_name,
162 documentation,
163 namespaces,
164 } = self;
165
166 ident.eq(&other.ident)
167 && type_.type_eq(&other.variant, types)
168 && use_.eq(&other.use_)
169 && form.eq(&other.form)
170 && default.eq(&other.default)
171 && display_name.eq(&other.display_name)
172 && documentation.eq(&other.documentation)
173 && namespaces.eq(&other.namespaces)
174 }
175}
176
177impl Deref for AttributesMeta {
180 type Target = Vec<AttributeMeta>;
181
182 fn deref(&self) -> &Self::Target {
183 &self.0
184 }
185}
186
187impl DerefMut for AttributesMeta {
188 fn deref_mut(&mut self) -> &mut Self::Target {
189 &mut self.0
190 }
191}
192
193impl TypeEq for AttributesMeta {
194 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &MetaTypes) {
195 TypeEq::type_hash_slice(&self.0, hasher, types);
196 }
197
198 fn type_eq(&self, other: &Self, types: &MetaTypes) -> bool {
199 TypeEq::type_eq_iter(self.0.iter(), other.0.iter(), types)
200 }
201}
202
203impl TypeEq for AttributeMetaVariant {
206 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &MetaTypes) {
207 match self {
208 Self::Any(x) => {
209 hasher.write_u8(0);
210 x.hash(hasher);
211 }
212 Self::Type(x) => {
213 hasher.write_u8(1);
214 x.type_hash(hasher, types);
215 }
216 }
217 }
218
219 fn type_eq(&self, other: &Self, types: &MetaTypes) -> bool {
220 match (self, other) {
221 (Self::Any(a), Self::Any(b)) => a.eq(b),
222 (Self::Type(a), Self::Type(b)) => a.type_eq(b, types),
223 (_, _) => false,
224 }
225 }
226}
227
228impl Hash for AnyAttributeMeta {
231 fn hash<H: Hasher>(&self, hasher: &mut H) {
232 self.id.hash(hasher);
236 }
237}