use std::collections::HashMap;
use std::cell::{RefCell, Ref, RefMut};
use std::fmt;
use std::rc::{Rc, Weak};
use std::str::FromStr;
use attribute::*;
use parser::parse_svg;
use write;
use super::{
AttributeId,
Attributes,
ElementId,
Error,
ParseOptions,
WriteBuffer,
WriteOptions,
WriteToString,
};
pub struct Document {
root: Node,
}
impl Document {
pub fn new() -> Document {
Document {
root: Document::new_node(None, NodeType::Root, None, None)
}
}
pub fn from_data(data: &[u8]) -> Result<Document, Error> {
Document::from_data_with_opt(data, &ParseOptions::default())
}
pub fn from_data_with_opt(data: &[u8], opt: &ParseOptions) -> Result<Document, Error> {
parse_svg(data, opt)
}
pub fn create_element(&self, eid: ElementId) -> Node {
Document::new_node(Some(self.root.0.clone()), NodeType::Element,
Some(TagName::Id(eid)), None)
}
pub fn create_nonsvg_element(&self, tag_name: &str) -> Result<Node, Error> {
if tag_name.is_empty() {
return Err(Error::EmptyTagName);
}
Ok(Document::new_node(Some(self.root.0.clone()), NodeType::Element,
Some(TagName::Name(tag_name.to_owned())), None))
}
pub fn create_node(&self, node_type: NodeType, text: &str) -> Node {
debug_assert!(node_type != NodeType::Element && node_type != NodeType::Root);
Document::new_node(Some(self.root.0.clone()), node_type, None, Some(text.to_owned()))
}
pub fn root(&self) -> Node {
self.root.clone()
}
pub fn first_child(&self) -> Option<Node> {
self.root().first_child()
}
pub fn svg_element(&self) -> Option<Node> {
for n in self.root.children() {
if n.is_tag_id(ElementId::Svg) {
return Some(n.clone());
}
}
None
}
pub fn append(&self, new_child: &Node) -> Node {
self.root.append(new_child);
new_child.clone()
}
pub fn descendants(&self) -> Descendants {
self.root.descendants()
}
pub fn descendant_nodes(&self) -> DescendantNodes {
self.root.descendant_nodes()
}
pub fn children(&self) -> Children {
self.root.children()
}
fn new_node(doc: Option<Link>, node_type: NodeType, tag_name: Option<TagName>,
text: Option<String>)
-> Node {
Node(Rc::new(RefCell::new(NodeData {
doc: doc,
parent: None,
first_child: None,
last_child: None,
previous_sibling: None,
next_sibling: None,
node_type: node_type,
tag_name: tag_name,
id: String::new(),
attributes: Attributes::new(),
ext_attributes: HashMap::new(),
linked_nodes: Vec::new(),
text: text,
})))
}
}
impl Default for Document {
fn default() -> Self {
Self::new()
}
}
impl WriteBuffer for Document {
fn write_buf_opt(&self, opt: &WriteOptions, buf: &mut Vec<u8>) {
write::write_dom(self, opt, buf);
}
}
impl_display!(Document);
macro_rules! try_opt {
($expr: expr) => {
match $expr {
Some(value) => value,
None => return None
}
}
}
pub struct Node(Rc<RefCell<NodeData>>);
impl Node {
pub fn document(&self) -> Document {
Document { root: Node(self.0.borrow().doc.as_ref().unwrap().clone()) }
}
pub fn parent(&self) -> Option<Node> {
Some(Node(try_opt!(try_opt!(self.0.borrow().parent.as_ref()).upgrade())))
}
pub fn parent_element<T>(&self, tag_name: T) -> Option<Node>
where TagName: From<T>
{
let tg = TagName::from(tag_name);
let mut parent = self.parent();
while let Some(p) = parent {
if p.is_tag_name(&tg) {
return Some(p.clone());
}
parent = p.parent();
}
None
}
pub fn has_parent(&self) -> bool {
match self.parent() {
Some(node) => {
match node.node_type() {
NodeType::Root => false,
_ => true,
}
}
None => false,
}
}
pub fn children(&self) -> Children {
if let Some(mut child) = self.first_child() {
loop {
if child.is_svg_element() {
return Children(Some(child));
}
if let Some(c) = child.next_sibling() {
child = c;
} else {
break;
}
}
}
Children(None)
}
pub fn has_children(&self) -> bool {
if let Some(mut child) = self.first_child() {
loop {
if child.is_svg_element() {
return true;
}
if let Some(c) = child.next_sibling() {
child = c;
} else {
break;
}
}
}
false
}
pub fn children_nodes(&self) -> ChildrenNodes {
ChildrenNodes(self.first_child())
}
pub fn has_children_nodes(&self) -> bool {
self.first_child().is_some()
}
pub fn first_child(&self) -> Option<Node> {
Some(Node(try_opt!(self.0.borrow().first_child.as_ref()).clone()))
}
pub fn last_child(&self) -> Option<Node> {
Some(Node(try_opt!(try_opt!(self.0.borrow().last_child.as_ref()).upgrade())))
}
pub fn previous_sibling(&self) -> Option<Node> {
Some(Node(try_opt!(try_opt!(self.0.borrow().previous_sibling.as_ref()).upgrade())))
}
pub fn next_sibling(&self) -> Option<Node> {
Some(Node(try_opt!(self.0.borrow().next_sibling.as_ref()).clone()))
}
pub fn same_node(&self, other: &Node) -> bool {
same_rc(&self.0, &other.0)
}
pub fn detach(&self) {
self.0.borrow_mut().detach();
}
pub fn remove(&self) {
Node::_remove(self);
self.detach();
}
fn _remove(node: &Node) {
let mut ids: Vec<AttributeId> = node.attributes().iter()
.filter(|a| a.is_link() || a.is_func_link())
.map(|a| a.id)
.collect();
for id in &ids {
node.remove_attribute(*id);
}
for linked in node.linked_nodes() {
ids.clear();
for attr in linked.attributes().iter() {
match attr.value {
AttributeValue::Link(ref link) | AttributeValue::FuncLink(ref link) => {
if link == node {
ids.push(attr.id);
}
}
_ => {}
}
}
for id in &ids {
linked.remove_attribute(*id);
}
}
for child in node.children() {
Node::_remove(&child);
}
}
pub fn append(&self, new_child: &Node) {
let mut self_borrow = self.0.borrow_mut();
let mut last_child_opt = None;
let nc = new_child.clone();
{
let mut new_child_borrow = nc.0.borrow_mut();
new_child_borrow.detach();
new_child_borrow.parent = Some(Rc::downgrade(&self.0));
if let Some(last_child_weak) = self_borrow.last_child.take() {
if let Some(last_child_strong) = last_child_weak.upgrade() {
new_child_borrow.previous_sibling = Some(last_child_weak);
last_child_opt = Some(last_child_strong);
}
}
self_borrow.last_child = Some(Rc::downgrade(&nc.0));
}
if let Some(last_child_strong) = last_child_opt {
let mut last_child_borrow = last_child_strong.borrow_mut();
debug_assert!(last_child_borrow.next_sibling.is_none());
last_child_borrow.next_sibling = Some(nc.0);
} else {
debug_assert!(self_borrow.first_child.is_none());
self_borrow.first_child = Some(nc.0);
}
}
pub fn prepend(&self, new_child: Node) {
let mut self_borrow = self.0.borrow_mut();
{
let mut new_child_borrow = new_child.0.borrow_mut();
new_child_borrow.detach();
new_child_borrow.parent = Some(Rc::downgrade(&self.0));
match self_borrow.first_child.take() {
Some(first_child_strong) => {
{
let mut first_child_borrow = first_child_strong.borrow_mut();
debug_assert!(first_child_borrow.previous_sibling.is_none());
first_child_borrow.previous_sibling = Some(Rc::downgrade(&new_child.0));
}
new_child_borrow.next_sibling = Some(first_child_strong);
}
None => {
debug_assert!(self_borrow.first_child.is_none());
self_borrow.last_child = Some(Rc::downgrade(&new_child.0));
}
}
}
self_borrow.first_child = Some(new_child.0);
}
pub fn insert_after(&self, new_sibling: Node) {
let mut self_borrow = self.0.borrow_mut();
{
let mut new_sibling_borrow = new_sibling.0.borrow_mut();
new_sibling_borrow.detach();
new_sibling_borrow.parent = self_borrow.parent.clone();
new_sibling_borrow.previous_sibling = Some(Rc::downgrade(&self.0));
match self_borrow.next_sibling.take() {
Some(next_sibling_strong) => {
{
let mut next_sibling_borrow = next_sibling_strong.borrow_mut();
debug_assert!({
let weak = next_sibling_borrow.previous_sibling.as_ref().unwrap();
same_rc(&weak.upgrade().unwrap(), &self.0)
});
next_sibling_borrow.previous_sibling = Some(Rc::downgrade(&new_sibling.0));
}
new_sibling_borrow.next_sibling = Some(next_sibling_strong);
}
None => {
if let Some(parent_ref) = self_borrow.parent.as_ref() {
if let Some(parent_strong) = parent_ref.upgrade() {
let mut parent_borrow = parent_strong.borrow_mut();
parent_borrow.last_child = Some(Rc::downgrade(&new_sibling.0));
}
}
}
}
}
self_borrow.next_sibling = Some(new_sibling.0);
}
pub fn insert_before(&self, new_sibling: Node) {
let mut self_borrow = self.0.borrow_mut();
let mut previous_sibling_opt = None;
{
let mut new_sibling_borrow = new_sibling.0.borrow_mut();
new_sibling_borrow.detach();
new_sibling_borrow.parent = self_borrow.parent.clone();
new_sibling_borrow.next_sibling = Some(self.0.clone());
if let Some(previous_sibling_weak) = self_borrow.previous_sibling.take() {
if let Some(previous_sibling_strong) = previous_sibling_weak.upgrade() {
new_sibling_borrow.previous_sibling = Some(previous_sibling_weak);
previous_sibling_opt = Some(previous_sibling_strong);
}
}
self_borrow.previous_sibling = Some(Rc::downgrade(&new_sibling.0));
}
if let Some(previous_sibling_strong) = previous_sibling_opt {
let mut previous_sibling_borrow = previous_sibling_strong.borrow_mut();
debug_assert!({
let rc = previous_sibling_borrow.next_sibling.as_ref().unwrap();
same_rc(rc, &self.0)
});
previous_sibling_borrow.next_sibling = Some(new_sibling.0);
} else {
if let Some(parent_ref) = self_borrow.parent.as_ref() {
if let Some(parent_strong) = parent_ref.upgrade() {
let mut parent_borrow = parent_strong.borrow_mut();
parent_borrow.first_child = Some(new_sibling.0);
}
}
}
}
pub fn node_type(&self) -> NodeType {
self.0.borrow().node_type
}
pub fn text(&self) -> Option<Ref<String>> {
let b = self.0.borrow();
match b.text {
Some(_) => Some(Ref::map(self.0.borrow(), |n| n.text.as_ref().unwrap())),
None => None,
}
}
pub fn set_text(&self, text: &str) {
debug_assert!(self.node_type() != NodeType::Element);
let mut b = self.0.borrow_mut();
b.text = Some(text.to_owned());
}
pub fn has_text_children(&self) -> bool {
for node in self.descendant_nodes() {
if node.node_type() == NodeType::Text {
return true;
}
}
false
}
pub fn set_id<S: Into<String>>(&self, id: S) {
debug_assert!(self.node_type() == NodeType::Element);
let mut self_borrow = self.0.borrow_mut();
self_borrow.id = id.into();
}
pub fn id(&self) -> Ref<String> {
Ref::map(self.0.borrow(), |n| &n.id)
}
pub fn has_id(&self) -> bool {
!self.0.borrow().id.is_empty()
}
pub fn is_svg_element(&self) -> bool {
let b = self.0.borrow();
match b.tag_name {
Some(ref tag) => {
match *tag {
TagName::Id(_) => true,
TagName::Name(_) => false,
}
}
None => false,
}
}
pub fn set_tag_id(&self, eid: ElementId) {
debug_assert!(self.node_type() == NodeType::Element);
let mut self_borrow = self.0.borrow_mut();
self_borrow.tag_name = Some(TagName::Id(eid));
}
pub fn set_tag_name(&self, tag_name: &str) -> Result<(), Error> {
debug_assert!(self.node_type() == NodeType::Element);
if tag_name.is_empty() {
return Err(Error::EmptyTagName);
}
let mut self_borrow = self.0.borrow_mut();
self_borrow.tag_name = Some(TagName::Name(tag_name.to_owned()));
Ok(())
}
pub fn tag_name(&self) -> Option<Ref<TagName>> {
let b = self.0.borrow();
match b.tag_name {
Some(_) => Some(Ref::map(self.0.borrow(), |n| n.tag_name.as_ref().unwrap())),
None => None,
}
}
pub fn tag_id(&self) -> Option<ElementId> {
let b = self.0.borrow();
match b.tag_name {
Some(ref t) => {
match *t {
TagName::Id(ref id) => Some(*id),
TagName::Name(_) => None,
}
}
None => None,
}
}
pub fn is_tag_id(&self, eid: ElementId) -> bool {
let b = self.0.borrow();
match b.tag_name {
Some(ref v) => {
match *v {
TagName::Id(ref id) => *id == eid,
TagName::Name(_) => false,
}
}
None => false,
}
}
pub fn is_tag_name(&self, tag_name: &TagName) -> bool {
let b = self.0.borrow();
match b.tag_name {
Some(ref v) => v == tag_name,
None => false,
}
}
pub fn has_child_with_tag_name(&self, tag_name: &TagName) -> bool {
self.children().any(|n| n.is_tag_name(tag_name))
}
pub fn set_attribute<T>(&self, id: AttributeId, value: T)
where AttributeValue: From<T>
{
self.remove_attribute(id);
let a = Attribute::new(id, value);
let mut attrs = self.attributes_mut();
attrs.insert(a);
}
pub fn set_attribute_object(&self, attr: Attribute) {
match attr.value {
AttributeValue::Link(_) | AttributeValue::FuncLink(_) =>
panic!("Link attributes must be set via set_link_attribute()"),
_ => {}
}
self.remove_attribute(attr.id);
let mut attrs = self.attributes_mut();
attrs.insert(attr);
}
pub fn set_link_attribute(&self, id: AttributeId, node: Node) -> Result<(), Error> {
if node.id().is_empty() {
return Err(Error::ElementMustHaveAnId);
}
if *self.id() == *node.id() {
return Err(Error::ElementCrosslink);
}
{
let self_borrow = self.0.borrow();
let v = &self_borrow.linked_nodes;
if v.iter().any(|n| Node(n.upgrade().unwrap()) == node) {
return Err(Error::ElementCrosslink);
}
}
self.remove_attribute(id);
{
let a = if id == AttributeId::XlinkHref {
Attribute::new(id, AttributeValue::Link(node.clone()))
} else {
Attribute::new(id, AttributeValue::FuncLink(node.clone()))
};
let mut attributes = self.attributes_mut();
attributes.insert(a);
}
{
let mut value_borrow = node.0.borrow_mut();
value_borrow.linked_nodes.push(Rc::downgrade(&self.0));
}
Ok(())
}
pub fn linked_nodes(&self) -> LinkAttributes {
let self_borrow = self.0.borrow();
LinkAttributes {
data: self_borrow.linked_nodes.clone(),
idx: 0,
}
}
pub fn attribute_value(&self, id: AttributeId) -> Option<AttributeValue> {
self.attributes().get_value(id).cloned()
}
pub fn attribute(&self, id: AttributeId) -> Option<Attribute> {
self.attributes().get(id).cloned()
}
pub fn attributes(&self) -> Ref<Attributes> {
Ref::map(self.0.borrow(), |n| &n.attributes)
}
pub fn attributes_mut(&self) -> RefMut<Attributes> {
RefMut::map(self.0.borrow_mut(), |n| &mut n.attributes)
}
pub fn parent_attribute(&self, id: AttributeId) -> Option<Attribute> {
let mut parent = self.parent();
while let Some(p) = parent {
if p.has_attribute(id) {
return p.attribute(id);
}
parent = p.parent();
}
None
}
#[inline]
pub fn has_attribute(&self, id: AttributeId) -> bool {
self.0.borrow().attributes.contains(id)
}
pub fn has_visible_attribute(&self, id: AttributeId) -> bool {
self.has_attribute(id) && self.attributes().get(id).unwrap().visible
}
pub fn has_attributes(&self, ids: &[AttributeId]) -> bool {
let attrs = self.attributes();
for id in ids {
if attrs.contains(*id) {
return true;
}
}
false
}
pub fn has_attribute_with_value<T>(&self, id: AttributeId, value: T) -> bool
where AttributeValue: From<T>
{
match self.attribute_value(id) {
Some(a) => a == AttributeValue::from(value),
None => false,
}
}
pub fn remove_attribute(&self, id: AttributeId) {
if !self.has_attribute(id) {
return;
}
let mut attrs = self.attributes_mut();
if let Some(value) = attrs.get_value(id) {
match *value {
AttributeValue::Link(ref node) | AttributeValue::FuncLink(ref node) => {
let mut self_borrow = node.0.borrow_mut();
let ln = &mut self_borrow.linked_nodes;
let index = ln.iter().position(|x| {
same_rc(&x.upgrade().unwrap(), &self.0)
}).unwrap();
ln.remove(index);
}
_ => {}
}
}
attrs.remove(id);
}
pub fn remove_attributes(&self, ids: &[AttributeId]) {
for id in ids {
self.remove_attribute(*id);
}
}
pub fn unknown_attributes(&self) -> Ref<HashMap<String,String>> {
Ref::map(self.0.borrow(), |n| &n.ext_attributes)
}
pub fn unknown_attributes_mut(&self) -> RefMut<HashMap<String,String>> {
RefMut::map(self.0.borrow_mut(), |n| &mut n.ext_attributes)
}
pub fn is_used(&self) -> bool {
let self_borrow = self.0.borrow();
!self_borrow.linked_nodes.is_empty()
}
pub fn uses_count(&self) -> usize {
let self_borrow = self.0.borrow();
self_borrow.linked_nodes.len()
}
pub fn is_referenced(&self) -> bool {
if let Some(id) = self.tag_id() {
match id {
ElementId::AltGlyphDef
| ElementId::ClipPath
| ElementId::Cursor
| ElementId::Filter
| ElementId::LinearGradient
| ElementId::Marker
| ElementId::Mask
| ElementId::Pattern
| ElementId::RadialGradient
| ElementId::Symbol => true,
_ => false,
}
} else {
false
}
}
pub fn is_basic_shape(&self) -> bool {
if let Some(id) = self.tag_id() {
match id {
ElementId::Rect
| ElementId::Circle
| ElementId::Ellipse
| ElementId::Line
| ElementId::Polyline
| ElementId::Polygon => true,
_ => false,
}
} else {
false
}
}
pub fn is_container(&self) -> bool {
if let Some(id) = self.tag_id() {
match id {
ElementId::A
| ElementId::Defs
| ElementId::Glyph
| ElementId::G
| ElementId::Marker
| ElementId::Mask
| ElementId::MissingGlyph
| ElementId::Pattern
| ElementId::Svg
| ElementId::Switch
| ElementId::Symbol => true,
_ => false,
}
} else {
false
}
}
pub fn child_by_tag_name(&self, tag_name: &TagName) -> Option<Node> {
let iter = self.descendant_nodes().skip(1);
for node in iter {
if node.is_tag_name(tag_name) {
return Some(node.clone());
}
}
None
}
pub fn child_by_tag_id(&self, id: ElementId) -> Option<Node> {
self.child_by_tag_name(&TagName::Id(id))
}
pub fn descendants(&self) -> Descendants {
Descendants(self.traverse())
}
pub fn descendant_nodes(&self) -> DescendantNodes {
DescendantNodes(self.traverse())
}
pub fn traverse(&self) -> Traverse {
Traverse {
root: self.clone(),
next: Some(NodeEdge::Start(self.clone())),
}
}
}
fn same_rc<T>(a: &Rc<T>, b: &Rc<T>) -> bool {
let a: *const T = &**a;
let b: *const T = &**b;
a == b
}
impl Clone for Node {
fn clone(&self) -> Node {
Node(self.0.clone())
}
}
impl PartialEq for Node {
fn eq(&self, other: &Node) -> bool {
self.same_node(other)
}
}
impl fmt::Debug for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.node_type() {
NodeType::Root => write!(f, "Root node"),
NodeType::Element => write!(f, "<{:?} id={:?}>", self.tag_name().unwrap(), self.id()),
NodeType::Declaration => write!(f, "Declaration node"),
NodeType::Comment => write!(f, "Comment node"),
NodeType::Cdata => write!(f, "CDATA node"),
NodeType::Text => write!(f, "Text node"),
}
}
}
#[derive(Clone,Copy,PartialEq,Debug)]
pub enum NodeType {
Root,
Element,
Declaration,
Comment,
Cdata,
Text,
}
type Link = Rc<RefCell<NodeData>>;
type WeakLink = Weak<RefCell<NodeData>>;
#[allow(dead_code)]
struct NodeData {
doc: Option<Link>,
parent: Option<WeakLink>,
first_child: Option<Link>,
last_child: Option<WeakLink>,
previous_sibling: Option<WeakLink>,
next_sibling: Option<Link>,
node_type: NodeType, tag_name: Option<TagName>,
id: String,
attributes: Attributes,
ext_attributes: HashMap<String,String>,
linked_nodes: Vec<WeakLink>,
text: Option<String>,
}
impl NodeData {
fn detach(&mut self) {
let parent_weak = self.parent.take();
let previous_sibling_weak = self.previous_sibling.take();
let next_sibling_strong = self.next_sibling.take();
let previous_sibling_opt = previous_sibling_weak.as_ref().and_then(|weak| weak.upgrade());
if let Some(next_sibling_ref) = next_sibling_strong.as_ref() {
let mut next_sibling_borrow = next_sibling_ref.borrow_mut();
next_sibling_borrow.previous_sibling = previous_sibling_weak;
} else if let Some(parent_ref) = parent_weak.as_ref() {
if let Some(parent_strong) = parent_ref.upgrade() {
let mut parent_borrow = parent_strong.borrow_mut();
parent_borrow.last_child = previous_sibling_weak;
}
}
if let Some(previous_sibling_strong) = previous_sibling_opt {
let mut previous_sibling_borrow = previous_sibling_strong.borrow_mut();
previous_sibling_borrow.next_sibling = next_sibling_strong;
} else if let Some(parent_ref) = parent_weak.as_ref() {
if let Some(parent_strong) = parent_ref.upgrade() {
let mut parent_borrow = parent_strong.borrow_mut();
parent_borrow.first_child = next_sibling_strong;
}
}
}
}
#[derive(Clone,PartialEq)]
pub enum TagName {
Id(ElementId),
Name(String),
}
impl From<ElementId> for TagName {
fn from(value: ElementId) -> TagName {
TagName::Id(value)
}
}
impl From<String> for TagName {
fn from(value: String) -> TagName {
TagName::Name(value)
}
}
impl<'a> From<&'a str> for TagName {
fn from(value: &str) -> TagName {
TagName::Name(String::from_str(value).unwrap())
}
}
impl fmt::Debug for TagName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TagName::Id(ref id) => write!(f, "{}", id.name()),
TagName::Name(ref name) => write!(f, "{}", name),
}
}
}
pub struct LinkAttributes {
data: Vec<WeakLink>,
idx: usize,
}
impl Iterator for LinkAttributes {
type Item = Node;
fn next(&mut self) -> Option<Node> {
let i = self.idx;
self.idx += 1;
if i < self.data.len() {
match self.data[i].upgrade() {
Some(n) => Some(Node(n)),
None => None,
}
} else {
None
}
}
}
#[allow(missing_docs)]
#[derive(Clone)]
pub enum NodeEdge {
Start(Node),
End(Node),
}
#[derive(Clone)]
pub struct Traverse {
root: Node,
next: Option<NodeEdge>,
}
impl Iterator for Traverse {
type Item = NodeEdge;
fn next(&mut self) -> Option<NodeEdge> {
match self.next.take() {
Some(item) => {
self.next = match item {
NodeEdge::Start(ref node) => {
match node.first_child() {
Some(first_child) => Some(NodeEdge::Start(first_child)),
None => Some(NodeEdge::End(node.clone()))
}
}
NodeEdge::End(ref node) => {
if node.same_node(&self.root) {
None
} else {
match node.next_sibling() {
Some(next_sibling) => Some(NodeEdge::Start(next_sibling)),
None => match node.parent() {
Some(parent) => Some(NodeEdge::End(parent)),
None => None
}
}
}
}
};
Some(item)
}
None => None
}
}
}
pub struct DescendantNodes(Traverse);
impl Iterator for DescendantNodes {
type Item = Node;
fn next(&mut self) -> Option<Node> {
loop {
match self.0.next() {
Some(NodeEdge::Start(node)) => return Some(node),
Some(NodeEdge::End(_)) => {}
None => return None
}
}
}
}
#[derive(Clone)]
pub struct Descendants(Traverse);
impl Descendants {
pub fn skip_children(&mut self) {
let n = match self.next() {
Some(n) => n.parent().unwrap(),
None => return,
};
if !n.has_children() {
return;
}
loop {
match self.0.next() {
Some(NodeEdge::Start(_)) => {}
Some(NodeEdge::End(node)) => {
if n == node {
break;
}
}
None => break
}
}
}
}
impl Iterator for Descendants {
type Item = Node;
fn next(&mut self) -> Option<Node> {
loop {
match self.0.next() {
Some(NodeEdge::Start(node)) => {
if node.is_svg_element() {
return Some(node)
}
}
Some(NodeEdge::End(_)) => {}
None => return None
}
}
}
}
macro_rules! impl_node_iterator {
($name: ident, $next: expr) => {
impl Iterator for $name {
type Item = Node;
fn next(&mut self) -> Option<Node> {
match self.0.take() {
Some(node) => {
self.0 = $next(&node);
Some(node)
}
None => None
}
}
}
}
}
pub struct Children(Option<Node>);
impl_node_iterator!(Children, |node: &Node| {
let mut curr = node.clone();
while let Some(n) = curr.next_sibling() {
if n.node_type() == NodeType::Element {
return Some(n);
}
curr = n.clone();
}
None
});
pub struct ChildrenNodes(Option<Node>);
impl_node_iterator!(ChildrenNodes, |node: &Node| node.next_sibling());