use node::{Node, NodeRef};
pub mod attlistdecl;
pub mod attr;
pub mod character_data;
pub mod document;
pub mod document_fragment;
pub mod document_type;
pub mod dom_configuration;
pub mod dom_error;
pub mod dom_implementation;
pub mod element;
pub mod elementdecl;
pub mod entity;
pub mod entity_reference;
pub mod name_list;
pub mod named_node_map;
pub mod node;
pub mod node_list;
pub mod notation;
pub mod pi;
pub mod user_data;
pub const XML_XML_NAMESPACE: &str = "http://www.w3.org/XML/1998/namespace";
pub const XML_NS_NAMESPACE: &str = "http://www.w3.org/2000/xmlns/";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DOMException {
IndexSizeErr = 1,
DOMStringSizeErr = 2,
HierarchyRequestErr = 3,
WrongDocumentErr = 4,
InvalidCharacterErr = 5,
NoDataAllowedErr = 6,
NoModificationAllowedErr = 7,
NotFoundErr = 8,
NotSupportedErr = 9,
InuseAttributeErr = 10,
InvalidStateErr = 11,
SyntaxErr = 12,
InvalidModificationErr = 13,
NamespaceErr = 14,
InvalidAccessErr = 15,
ValidationErr = 16,
TypeMismatchErr = 17,
}
const DOCUMENT_POSITION_DISCONNECTED: u16 = 0x01;
const DOCUMENT_POSITION_PRECEDING: u16 = 0x02;
const DOCUMENT_POSITION_FOLLOWING: u16 = 0x04;
const DOCUMENT_POSITION_CONTAINS: u16 = 0x08;
const DOCUMENT_POSITION_CONTAINED_BY: u16 = 0x10;
const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: u16 = 0x20;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DocumentPosition(u16);
impl DocumentPosition {
fn new() -> Self {
DocumentPosition(0)
}
fn set_flag(mut self, flag: u16) -> Self {
self.0 |= flag;
self
}
fn unset_flag(mut self, flag: u16) -> Self {
self.0 &= !flag;
self
}
pub fn is_same_node(self) -> bool {
self.0 == 0
}
pub fn is_disconnected(self) -> bool {
self.0 & DOCUMENT_POSITION_DISCONNECTED != 0
}
pub fn is_preceding(self) -> bool {
self.0 & DOCUMENT_POSITION_PRECEDING != 0
}
pub fn is_following(self) -> bool {
self.0 & DOCUMENT_POSITION_FOLLOWING != 0
}
pub fn is_contains(self) -> bool {
self.0 & DOCUMENT_POSITION_CONTAINS != 0
}
pub fn is_contained_by(self) -> bool {
self.0 & DOCUMENT_POSITION_CONTAINED_BY != 0
}
pub fn is_implementation_specific(self) -> bool {
self.0 & DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC != 0
}
}
impl From<DocumentPosition> for u16 {
fn from(value: DocumentPosition) -> Self {
value.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum NodeType {
Element = 1,
Attribute = 2,
Text = 3,
CDATASection = 4,
EntityReference = 5,
Entity = 6,
ProcessingInstruction = 7,
Comment = 8,
Document = 9,
DocumentType = 10,
DocumentFragment = 11,
Notation = 12,
}
fn check_horizontal_hierarchy(left: NodeType, right: NodeType) -> bool {
use NodeType::*;
match left {
Element | ProcessingInstruction | Comment => matches!(
right,
DocumentType
| Element
| Text
| Comment
| ProcessingInstruction
| CDATASection
| EntityReference
),
Text | CDATASection | EntityReference => matches!(
right,
Element | Text | Comment | ProcessingInstruction | CDATASection | EntityReference
),
DocumentType => matches!(right, Element | ProcessingInstruction | Comment),
_ => false,
}
}
fn check_vertical_hierarchy(parent: NodeType, child: NodeType) -> bool {
use NodeType::*;
match parent {
Element | DocumentFragment | EntityReference | Entity => matches!(
child,
Element | Text | Comment | ProcessingInstruction | CDATASection | EntityReference
),
Attribute => matches!(child, Text | EntityReference),
Document => matches!(
child,
Element | ProcessingInstruction | Comment | DocumentType
),
_ => false,
}
}
fn check_owner_document_sameness(l: &impl Node, r: &impl Node) -> bool {
match (l.node_type(), r.node_type()) {
(NodeType::DocumentType, NodeType::DocumentType) => {
let ldoc = l.owner_document();
let rdoc = r.owner_document();
ldoc.is_some() == rdoc.is_some()
&& ldoc
.zip(rdoc)
.is_none_or(|(l, r)| l.is_same_node(&r.into()))
}
(NodeType::DocumentType, _) if l.owner_document().is_none() => true,
(_, NodeType::DocumentType) if r.owner_document().is_none() => true,
(NodeType::Document, NodeType::Document) => l.is_same_node(&r.clone().into()),
(NodeType::Document, _) => r
.owner_document()
.is_some_and(|doc| l.is_same_node(&NodeRef::Document(doc))),
(_, NodeType::Document) => l
.owner_document()
.is_some_and(|doc| r.is_same_node(&NodeRef::Document(doc))),
_ => l
.owner_document()
.zip(r.owner_document())
.is_some_and(|(l, r)| l.is_same_node(&node::NodeRef::Document(r))),
}
}
fn check_no_modification_allowed_err(node: &impl Node) -> Result<(), DOMException> {
if node.is_read_only()
&& node
.owner_document()
.is_some_and(|doc| doc.is_enabled_read_only_check())
{
Err(DOMException::NoModificationAllowedErr)
} else {
Ok(())
}
}