1use std::hash::{Hash, Hasher};
4
5use crate::schema::xs::{
6 Annotation, BasicNamespaceListType, NamespaceListType, ProcessContentsType, QnameListAType,
7 QnameListType,
8};
9use crate::schema::{MaxOccurs, MinOccurs};
10use crate::types::{Ident, TypeEq, TypeVariant, Types};
11
12use super::{AttributesInfo, Base, ElementsInfo};
13
14#[derive(Debug, Clone)]
16pub struct ComplexInfo {
17 pub base: Base,
19
20 pub content: Option<Ident>,
23
24 pub min_occurs: MinOccurs,
26
27 pub max_occurs: MaxOccurs,
29
30 pub is_dynamic: bool,
32
33 pub attributes: AttributesInfo,
35
36 pub any_attribute: Option<AnyAttributeInfo>,
40}
41
42#[derive(Default, Debug, Clone)]
46pub struct GroupInfo {
47 pub any: Option<AnyInfo>,
51
52 pub elements: ElementsInfo,
54}
55
56#[allow(missing_docs)]
59#[derive(Default, Debug, Clone, Eq, PartialEq)]
60pub struct AnyInfo {
61 pub id: Option<String>,
62 pub namespace: Option<NamespaceListType>,
63 pub not_namespace: Option<BasicNamespaceListType>,
64 pub process_contents: Option<ProcessContentsType>,
65 pub not_q_name: Option<QnameListType>,
66 pub min_occurs: Option<MinOccurs>,
67 pub max_occurs: Option<MaxOccurs>,
68 pub annotation: Option<Annotation>,
69}
70
71#[allow(missing_docs)]
74#[derive(Default, Debug, Clone, Eq, PartialEq)]
75pub struct AnyAttributeInfo {
76 pub id: Option<String>,
77 pub namespace: Option<NamespaceListType>,
78 pub not_namespace: Option<BasicNamespaceListType>,
79 pub process_contents: Option<ProcessContentsType>,
80 pub not_q_name: Option<QnameListAType>,
81 pub annotation: Option<Annotation>,
82}
83
84impl TypeEq for GroupInfo {
87 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &Types) {
88 let Self { any, elements } = self;
89
90 any.is_some().hash(hasher);
93 elements.type_hash(hasher, types);
94 }
95
96 fn type_eq(&self, other: &Self, types: &Types) -> bool {
97 let Self { any, elements } = self;
98
99 any.eq(&other.any) && elements.type_eq(&other.elements, types)
100 }
101}
102
103impl ComplexInfo {
106 #[must_use]
109 pub fn has_complex_choice_content(&self, types: &Types) -> bool {
110 matches!(
111 self.content
112 .as_ref()
113 .and_then(|ident| types.get_resolved_type(ident))
114 .map(|ty| &ty.variant),
115 Some(TypeVariant::Choice(_))
116 )
117 }
118
119 #[must_use]
123 pub fn has_complex_content(&self, types: &Types) -> bool {
124 matches!(
125 self.content
126 .as_ref()
127 .and_then(|ident| types.get_resolved_type(ident))
128 .map(|ty| &ty.variant),
129 Some(TypeVariant::All(_) | TypeVariant::Choice(_) | TypeVariant::Sequence(_))
130 )
131 }
132
133 #[must_use]
137 pub fn has_simple_content(&self, types: &Types) -> bool {
138 matches!(
139 self.content
140 .as_ref()
141 .and_then(|ident| types.get_resolved_type(ident))
142 .map(|ty| &ty.variant),
143 Some(
144 TypeVariant::Reference(_)
145 | TypeVariant::BuildIn(_)
146 | TypeVariant::Union(_)
147 | TypeVariant::Enumeration(_)
148 )
149 )
150 }
151}
152
153impl Default for ComplexInfo {
154 fn default() -> Self {
155 Self {
156 base: Base::None,
157 content: None,
158 min_occurs: 1,
159 max_occurs: MaxOccurs::Bounded(1),
160 is_dynamic: false,
161 attributes: AttributesInfo::default(),
162 any_attribute: None,
163 }
164 }
165}
166
167impl TypeEq for ComplexInfo {
168 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &Types) {
169 let Self {
170 base,
171 content,
172 min_occurs,
173 max_occurs,
174 is_dynamic,
175 attributes,
176 any_attribute,
177 } = self;
178
179 base.type_hash(hasher, types);
180 content.type_hash(hasher, types);
181 min_occurs.hash(hasher);
182 max_occurs.hash(hasher);
183 is_dynamic.hash(hasher);
184 attributes.type_hash(hasher, types);
185
186 any_attribute.is_some().hash(hasher);
189 }
190
191 fn type_eq(&self, other: &Self, types: &Types) -> bool {
192 let Self {
193 base,
194 content,
195 min_occurs,
196 max_occurs,
197 is_dynamic,
198 attributes,
199 any_attribute,
200 } = self;
201
202 base.type_eq(&other.base, types)
203 && content.type_eq(&other.content, types)
204 && min_occurs.eq(&other.min_occurs)
205 && max_occurs.eq(&other.max_occurs)
206 && is_dynamic.eq(&other.is_dynamic)
207 && attributes.type_eq(&other.attributes, types)
208 && any_attribute.eq(&other.any_attribute)
209 }
210}