use alloc::vec::Vec;
pub use attribute::Attribute;
use core::fmt;
use core::fmt::{Debug, Formatter};
pub use element::Element;
pub(crate) mod attribute;
mod element;
#[derive(Clone, Debug, PartialEq)]
pub enum Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
Element(Element<Ns, Tag, Leaf, Att, Val>),
NodeList(Vec<Node<Ns, Tag, Leaf, Att, Val>>),
Fragment(Vec<Node<Ns, Tag, Leaf, Att, Val>>),
Leaf(Leaf),
}
#[derive(Debug, Copy, Clone)]
pub enum Error {
AddChildrenNotAllowed,
AttributesNotAllowed,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
match self {
Self::AddChildrenNotAllowed => {
write!(f, "Adding children on this node variant is not allowed")
}
Self::AttributesNotAllowed => {
write!(
f,
"Adding or setting attibutes on this node variant is not allowed"
)
}
}
}
}
impl std::error::Error for Error {}
impl<Ns, Tag, Leaf, Att, Val> Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
pub fn take_element(self) -> Option<Element<Ns, Tag, Leaf, Att, Val>> {
match self {
Node::Element(element) => Some(element),
_ => None,
}
}
pub fn leaf(&self) -> Option<&Leaf> {
match self {
Node::Leaf(leaf) => Some(leaf),
_ => None,
}
}
pub fn is_element(&self) -> bool {
matches!(self, Node::Element(_))
}
pub fn is_leaf(&self) -> bool {
matches!(self, Node::Leaf(_))
}
pub fn is_fragment(&self) -> bool {
matches!(self, Node::Fragment(_))
}
pub fn element_mut(
&mut self,
) -> Option<&mut Element<Ns, Tag, Leaf, Att, Val>> {
match *self {
Node::Element(ref mut element) => Some(element),
_ => None,
}
}
pub fn element_ref(&self) -> Option<&Element<Ns, Tag, Leaf, Att, Val>> {
match *self {
Node::Element(ref element) => Some(element),
_ => None,
}
}
pub fn with_children(
mut self,
children: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
) -> Self {
if let Some(element) = self.element_mut() {
element.add_children(children);
} else {
panic!("Can not add children to a text node");
}
self
}
pub fn add_children(
&mut self,
children: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
) -> Result<(), Error> {
if let Some(element) = self.element_mut() {
element.add_children(children);
Ok(())
} else {
Err(Error::AddChildrenNotAllowed)
}
}
pub fn with_attributes(
mut self,
attributes: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
) -> Self {
if let Some(elm) = self.element_mut() {
elm.add_attributes(attributes);
} else {
panic!("Can not add attributes to a text node");
}
self
}
pub fn add_attributes(
&mut self,
attributes: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
) -> Result<(), Error> {
if let Some(elm) = self.element_mut() {
elm.add_attributes(attributes);
Ok(())
} else {
Err(Error::AttributesNotAllowed)
}
}
pub fn attributes(&self) -> Option<&[Attribute<Ns, Att, Val>]> {
match *self {
Node::Element(ref element) => Some(element.attributes()),
_ => None,
}
}
pub fn tag(&self) -> Option<&Tag> {
if let Some(e) = self.element_ref() {
Some(&e.tag)
} else {
None
}
}
pub fn children(&self) -> &[Node<Ns, Tag, Leaf, Att, Val>] {
if let Some(element) = self.element_ref() {
element.children()
} else {
&[]
}
}
pub fn children_count(&self) -> usize {
self.children().len()
}
pub fn children_mut(
&mut self,
) -> Option<&mut [Node<Ns, Tag, Leaf, Att, Val>]> {
if let Some(element) = self.element_mut() {
Some(element.children_mut())
} else {
None
}
}
pub fn swap_remove_child(
&mut self,
index: usize,
) -> Node<Ns, Tag, Leaf, Att, Val> {
match self {
Node::Element(element) => element.swap_remove_child(index),
_ => panic!("text has no child"),
}
}
pub fn swap_children(&mut self, a: usize, b: usize) {
match self {
Node::Element(element) => element.swap_children(a, b),
_ => panic!("text has no child"),
}
}
pub fn node_count(&self) -> usize {
1 + self.descendant_node_count()
}
pub fn descendant_node_count(&self) -> usize {
let mut cnt = 0;
if let Node::Element(element) = self {
for child in element.children.iter() {
cnt += child.node_count();
}
}
cnt
}
pub fn set_attributes(
&mut self,
attributes: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
) -> Result<(), Error> {
if let Some(elm) = self.element_mut() {
elm.set_attributes(attributes);
Ok(())
} else {
Err(Error::AttributesNotAllowed)
}
}
pub fn merge_attributes(
mut self,
attributes: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
) -> Self {
if let Some(elm) = self.element_mut() {
elm.merge_attributes(attributes);
}
self
}
pub fn attribute_value(&self, name: &Att) -> Option<Vec<&Val>> {
if let Some(elm) = self.element_ref() {
elm.attribute_value(name)
} else {
None
}
}
}
#[inline]
pub fn element<Ns, Tag, Leaf, Att, Val>(
tag: Tag,
attrs: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
children: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
) -> Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
element_ns(None, tag, attrs, children, false)
}
pub fn element_ns<Ns, Tag, Leaf, Att, Val>(
namespace: Option<Ns>,
tag: Tag,
attrs: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
children: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
self_closing: bool,
) -> Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
Node::Element(Element::new(namespace, tag, attrs, children, self_closing))
}
pub fn leaf<Ns, Tag, Leaf, Att, Val>(
leaf: Leaf,
) -> Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
Node::Leaf(leaf)
}
pub fn node_list<Ns, Tag, Leaf, Att, Val>(
nodes: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
) -> Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
Node::NodeList(nodes.into_iter().collect())
}
pub fn fragment<Ns, Tag, Leaf, Att, Val>(
nodes: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
) -> Node<Ns, Tag, Leaf, Att, Val>
where
Ns: PartialEq + Clone + Debug,
Tag: PartialEq + Debug,
Leaf: PartialEq + Clone + Debug,
Att: PartialEq + Clone + Debug,
Val: PartialEq + Clone + Debug,
{
Node::Fragment(nodes.into_iter().collect())
}