1use std::hash::{Hash, Hasher};
4
5use crate::schema::xs::{
6 Annotation, NamespaceListType, NotNamespaceType, ProcessContentsType, QnameListAType,
7 QnameListType,
8};
9use crate::schema::{MaxOccurs, MinOccurs};
10use crate::types::{Ident, Type, TypeEq, 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<NotNamespaceType>,
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<NotNamespaceType>,
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]
110 pub fn has_complex_content(&self, types: &Types) -> bool {
111 matches!(
112 self.content
113 .as_ref()
114 .and_then(|ident| types.get_resolved(ident)),
115 Some(Type::All(_) | Type::Choice(_) | Type::Sequence(_))
116 )
117 }
118
119 #[must_use]
123 pub fn has_simple_content(&self, types: &Types) -> bool {
124 matches!(
125 self.content
126 .as_ref()
127 .and_then(|ident| types.get_resolved(ident)),
128 Some(Type::Reference(_) | Type::BuildIn(_) | Type::Union(_) | Type::Enumeration(_))
129 )
130 }
131}
132
133impl Default for ComplexInfo {
134 fn default() -> Self {
135 Self {
136 base: Base::None,
137 content: None,
138 min_occurs: 1,
139 max_occurs: MaxOccurs::Bounded(1),
140 is_dynamic: false,
141 attributes: AttributesInfo::default(),
142 any_attribute: None,
143 }
144 }
145}
146
147impl TypeEq for ComplexInfo {
148 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &Types) {
149 let Self {
150 base,
151 content,
152 min_occurs,
153 max_occurs,
154 is_dynamic,
155 attributes,
156 any_attribute,
157 } = self;
158
159 base.type_hash(hasher, types);
160 content.type_hash(hasher, types);
161 min_occurs.hash(hasher);
162 max_occurs.hash(hasher);
163 is_dynamic.hash(hasher);
164 attributes.type_hash(hasher, types);
165
166 any_attribute.is_some().hash(hasher);
169 }
170
171 fn type_eq(&self, other: &Self, types: &Types) -> bool {
172 let Self {
173 base,
174 content,
175 min_occurs,
176 max_occurs,
177 is_dynamic,
178 attributes,
179 any_attribute,
180 } = self;
181
182 base.type_eq(&other.base, types)
183 && content.type_eq(&other.content, types)
184 && min_occurs.eq(&other.min_occurs)
185 && max_occurs.eq(&other.max_occurs)
186 && is_dynamic.eq(&other.is_dynamic)
187 && attributes.type_eq(&other.attributes, types)
188 && any_attribute.eq(&other.any_attribute)
189 }
190}