use std::hash::{Hash, Hasher};
use crate::schema::xs::{
Annotation, BasicNamespaceListType, NamespaceListType, ProcessContentsType, QnameListAType,
QnameListType,
};
use crate::schema::{MaxOccurs, MinOccurs};
use crate::types::{Ident, TypeEq, TypeVariant, Types};
use super::{AttributesInfo, Base, ElementsInfo};
#[derive(Debug, Clone)]
pub struct ComplexInfo {
pub base: Base,
pub content: Option<Ident>,
pub min_occurs: MinOccurs,
pub max_occurs: MaxOccurs,
pub is_dynamic: bool,
pub attributes: AttributesInfo,
pub any_attribute: Option<AnyAttributeInfo>,
}
#[derive(Default, Debug, Clone)]
pub struct GroupInfo {
pub any: Option<AnyInfo>,
pub elements: ElementsInfo,
}
#[allow(missing_docs)]
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct AnyInfo {
pub id: Option<String>,
pub namespace: Option<NamespaceListType>,
pub not_namespace: Option<BasicNamespaceListType>,
pub process_contents: Option<ProcessContentsType>,
pub not_q_name: Option<QnameListType>,
pub min_occurs: Option<MinOccurs>,
pub max_occurs: Option<MaxOccurs>,
pub annotation: Option<Annotation>,
}
#[allow(missing_docs)]
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct AnyAttributeInfo {
pub id: Option<String>,
pub namespace: Option<NamespaceListType>,
pub not_namespace: Option<BasicNamespaceListType>,
pub process_contents: Option<ProcessContentsType>,
pub not_q_name: Option<QnameListAType>,
pub annotation: Option<Annotation>,
}
impl TypeEq for GroupInfo {
fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &Types) {
let Self { any, elements } = self;
any.is_some().hash(hasher);
elements.type_hash(hasher, types);
}
fn type_eq(&self, other: &Self, types: &Types) -> bool {
let Self { any, elements } = self;
any.eq(&other.any) && elements.type_eq(&other.elements, types)
}
}
impl ComplexInfo {
#[must_use]
pub fn has_complex_choice_content(&self, types: &Types) -> bool {
matches!(
self.content
.as_ref()
.and_then(|ident| types.get_resolved_type(ident))
.map(|ty| &ty.variant),
Some(TypeVariant::Choice(_))
)
}
#[must_use]
pub fn has_complex_content(&self, types: &Types) -> bool {
matches!(
self.content
.as_ref()
.and_then(|ident| types.get_resolved_type(ident))
.map(|ty| &ty.variant),
Some(TypeVariant::All(_) | TypeVariant::Choice(_) | TypeVariant::Sequence(_))
)
}
#[must_use]
pub fn has_simple_content(&self, types: &Types) -> bool {
matches!(
self.content
.as_ref()
.and_then(|ident| types.get_resolved_type(ident))
.map(|ty| &ty.variant),
Some(
TypeVariant::Reference(_)
| TypeVariant::BuildIn(_)
| TypeVariant::Union(_)
| TypeVariant::Enumeration(_)
)
)
}
}
impl Default for ComplexInfo {
fn default() -> Self {
Self {
base: Base::None,
content: None,
min_occurs: 1,
max_occurs: MaxOccurs::Bounded(1),
is_dynamic: false,
attributes: AttributesInfo::default(),
any_attribute: None,
}
}
}
impl TypeEq for ComplexInfo {
fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &Types) {
let Self {
base,
content,
min_occurs,
max_occurs,
is_dynamic,
attributes,
any_attribute,
} = self;
base.type_hash(hasher, types);
content.type_hash(hasher, types);
min_occurs.hash(hasher);
max_occurs.hash(hasher);
is_dynamic.hash(hasher);
attributes.type_hash(hasher, types);
any_attribute.is_some().hash(hasher);
}
fn type_eq(&self, other: &Self, types: &Types) -> bool {
let Self {
base,
content,
min_occurs,
max_occurs,
is_dynamic,
attributes,
any_attribute,
} = self;
base.type_eq(&other.base, types)
&& content.type_eq(&other.content, types)
&& min_occurs.eq(&other.min_occurs)
&& max_occurs.eq(&other.max_occurs)
&& is_dynamic.eq(&other.is_dynamic)
&& attributes.type_eq(&other.attributes, types)
&& any_attribute.eq(&other.any_attribute)
}
}