use std::collections::BTreeMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Occurs {
pub min: usize,
pub max: Option<usize>,
}
impl Default for Occurs {
fn default() -> Self {
Self {
min: 1,
max: Some(1),
}
}
}
impl Occurs {
#[must_use]
pub fn permits(self, count: usize) -> bool {
count >= self.min && self.max.is_none_or(|m| count <= m)
}
#[must_use]
pub fn describe(self) -> String {
match (self.min, self.max) {
(1, Some(1)) => "exactly once".to_owned(),
(0, Some(1)) => "at most once".to_owned(),
(0, None) => "any number of times".to_owned(),
(n, None) => format!("at least {n} times"),
(a, Some(b)) if a == b => format!("exactly {a} times"),
(a, Some(b)) => format!("between {a} and {b} times"),
}
}
}
pub use crate::datatype::Datatype as BuiltIn;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Facets {
pub enumeration: Vec<String>,
pub pattern: Option<crate::pattern::Pattern>,
pub min_length: Option<usize>,
pub max_length: Option<usize>,
pub length: Option<usize>,
pub min_inclusive: Option<String>,
pub max_inclusive: Option<String>,
pub min_exclusive: Option<String>,
pub max_exclusive: Option<String>,
pub total_digits: Option<usize>,
pub fraction_digits: Option<usize>,
pub white_space: Option<crate::datatype::WhiteSpace>,
}
impl Facets {
#[must_use]
pub fn is_empty(&self) -> bool {
*self == Self::default()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SimpleType {
pub base: BuiltIn,
pub facets: Facets,
pub variety: Variety,
}
impl SimpleType {
#[must_use]
pub fn atomic(base: BuiltIn) -> Self {
Self {
base,
facets: Facets::default(),
variety: Variety::Atomic,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Variety {
Atomic,
List(Box<SimpleType>),
Union(Vec<SimpleType>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Content {
Simple(Box<SimpleType>),
Sequence(Vec<Particle>),
All(Vec<Particle>),
Choice(Vec<Particle>),
Any,
Empty,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Particle {
pub name: String,
pub occurs: Occurs,
pub content: Box<Content>,
pub attributes: Vec<AttributeDecl>,
pub fixed: Option<String>,
pub nillable: bool,
pub wildcard: Option<Wildcard>,
pub any_attribute: Option<Wildcard>,
pub identities: Vec<Identity>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IdentityKind {
Unique,
Key,
KeyRef,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Identity {
pub kind: IdentityKind,
pub name: String,
pub selector: String,
pub fields: Vec<String>,
pub refer: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Wildcard {
pub namespaces: NamespaceConstraint,
pub process: ProcessContents,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NamespaceConstraint {
Any,
Other,
List(Vec<Option<String>>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProcessContents {
Strict,
Lax,
Skip,
}
#[derive(Debug, Clone, PartialEq)]
pub struct AttributeDecl {
pub name: String,
pub required: bool,
pub simple_type: SimpleType,
pub fixed: Option<String>,
pub prohibited: bool,
}
#[derive(Debug, Clone)]
pub struct Schema {
pub target_namespace: Option<String>,
pub elements: BTreeMap<String, Particle>,
pub named_simple_types: BTreeMap<String, SimpleType>,
pub named_complex_types: BTreeMap<String, Content>,
}
impl Schema {
#[must_use]
pub fn element(&self, name: &str) -> Option<&Particle> {
self.elements.get(name)
}
}