pub mod xs;
mod occurs;
use std::collections::btree_map::{BTreeMap, Iter, IterMut};
use std::ops::Deref;
use url::Url;
use xsd_parser_types::misc::{Namespace, NamespacePrefix};
use self::xs::Schema;
pub use xsd_parser_types::xml::QName;
pub use self::occurs::{MaxOccurs, MinOccurs};
#[derive(Debug)]
pub struct Schemas {
pub(crate) schemas: SchemaFiles,
pub(crate) namespace_infos: NamespaceInfos,
pub(crate) known_prefixes: NamespacePrefixes,
pub(crate) known_namespaces: Namespaces,
pub(crate) last_schema_id: usize,
pub(crate) last_namespace_id: usize,
}
#[derive(Debug)]
pub struct NamespaceInfo {
pub prefix: Option<NamespacePrefix>,
pub namespace: Option<Namespace>,
pub schemas: Vec<SchemaId>,
pub module_name: Option<String>,
}
#[derive(Debug)]
pub struct SchemaInfo {
pub name: Option<String>,
pub schema: Schema,
pub location: Option<Url>,
pub(crate) namespace_id: NamespaceId,
pub(crate) dependencies: BTreeMap<String, Dependency<SchemaId>>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Dependency<T> {
Include(T),
Import(T),
Override(T),
Redefine(T),
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct SchemaId(pub usize);
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct NamespaceId(pub usize);
pub type SchemaFiles = BTreeMap<SchemaId, SchemaInfo>;
pub type NamespaceInfos = BTreeMap<NamespaceId, NamespaceInfo>;
pub type Namespaces = BTreeMap<Option<Namespace>, NamespaceId>;
pub type NamespacePrefixes = BTreeMap<NamespacePrefix, NamespaceId>;
impl Schemas {
pub fn schemas(&self) -> Iter<'_, SchemaId, SchemaInfo> {
self.schemas.iter()
}
pub fn schemas_mut(&mut self) -> IterMut<'_, SchemaId, SchemaInfo> {
self.schemas.iter_mut()
}
pub fn namespaces(&self) -> Iter<'_, NamespaceId, NamespaceInfo> {
self.namespace_infos.iter()
}
#[must_use]
pub fn get_schema(&self, id: &SchemaId) -> Option<&SchemaInfo> {
self.schemas.get(id)
}
#[must_use]
pub fn get_schema_mut(&mut self, id: &SchemaId) -> Option<&mut SchemaInfo> {
self.schemas.get_mut(id)
}
#[must_use]
pub fn get_namespace_info(&self, id: &NamespaceId) -> Option<&NamespaceInfo> {
self.namespace_infos.get(id)
}
#[must_use]
pub fn get_namespace_info_mut(&mut self, id: &NamespaceId) -> Option<&mut NamespaceInfo> {
self.namespace_infos.get_mut(id)
}
#[must_use]
pub fn get_namespace_info_by_namespace(
&self,
ns: &Option<Namespace>,
) -> Option<&NamespaceInfo> {
let id = self.resolve_namespace(ns)?;
self.get_namespace_info(&id)
}
#[must_use]
pub fn resolve_prefix(&self, prefix: &NamespacePrefix) -> Option<NamespaceId> {
Some(*self.known_prefixes.get(prefix)?)
}
#[must_use]
pub fn resolve_namespace(&self, ns: &Option<Namespace>) -> Option<NamespaceId> {
Some(*self.known_namespaces.get(ns)?)
}
#[must_use]
pub(crate) fn next_schema_id(&mut self) -> SchemaId {
self.last_schema_id = self.last_schema_id.wrapping_add(1);
SchemaId(self.last_schema_id)
}
}
impl Default for Schemas {
fn default() -> Self {
Self {
schemas: SchemaFiles::default(),
namespace_infos: NamespaceInfos::default(),
known_prefixes: NamespacePrefixes::default(),
known_namespaces: Namespaces::default(),
last_schema_id: SchemaId::UNKNOWN.0,
last_namespace_id: NamespaceId::ANONYMOUS.0,
}
}
}
impl NamespaceInfo {
#[must_use]
pub fn new(namespace: Option<Namespace>) -> Self {
Self {
prefix: None,
namespace,
schemas: Vec::new(),
module_name: None,
}
}
#[must_use]
pub fn name(&self) -> Option<String> {
self.module_name
.clone()
.or_else(|| self.prefix.as_ref().map(ToString::to_string))
}
}
impl SchemaInfo {
#[must_use]
pub fn namespace_id(&self) -> NamespaceId {
self.namespace_id
}
#[must_use]
pub fn dependencies(&self) -> &BTreeMap<String, Dependency<SchemaId>> {
&self.dependencies
}
#[must_use]
pub fn depends_on(&self, schema_id: &SchemaId) -> bool {
self.dependencies
.values()
.any(|id| id.as_ref() == schema_id)
}
}
impl<T> Dependency<T> {
pub fn map<F, U>(self, f: F) -> Dependency<U>
where
F: FnOnce(T) -> U,
{
match self {
Dependency::Include(x) => Dependency::Include(f(x)),
Dependency::Import(x) => Dependency::Import(f(x)),
Dependency::Override(x) => Dependency::Override(f(x)),
Dependency::Redefine(x) => Dependency::Redefine(f(x)),
}
}
}
impl<T> Deref for Dependency<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Dependency::Include(x)
| Dependency::Import(x)
| Dependency::Override(x)
| Dependency::Redefine(x) => x,
}
}
}
impl<T> AsRef<T> for Dependency<T> {
fn as_ref(&self) -> &T {
match self {
Dependency::Include(x)
| Dependency::Import(x)
| Dependency::Override(x)
| Dependency::Redefine(x) => x,
}
}
}
impl SchemaId {
pub const UNKNOWN: Self = Self(0);
#[must_use]
pub fn is_unknown(&self) -> bool {
self.eq(&Self::UNKNOWN)
}
#[inline]
#[must_use]
pub fn or(self, other: Self) -> Self {
if self.is_unknown() {
other
} else {
self
}
}
}
impl NamespaceId {
pub const UNKNOWN: Self = Self(0);
pub const ANONYMOUS: Self = Self(1);
#[inline]
#[must_use]
pub fn is_unknown(&self) -> bool {
self.eq(&Self::UNKNOWN)
}
#[inline]
#[must_use]
pub fn is_anonymous(&self) -> bool {
self.eq(&Self::ANONYMOUS)
}
#[inline]
#[must_use]
pub fn or(self, other: Self) -> Self {
if self.is_unknown() {
other
} else {
self
}
}
}