Skip to content

Commit 6d88c78

Browse files
committed
Use iterative algorithm for rcdom serialization.
1 parent 1b4e978 commit 6d88c78

File tree

1 file changed

+56
-46
lines changed

1 file changed

+56
-46
lines changed

markup5ever/rcdom.rs

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -418,61 +418,71 @@ impl Default for RcDom {
418418
}
419419
}
420420

421+
enum SerializeOp {
422+
Open(Handle),
423+
Close(QualName)
424+
}
425+
421426
impl Serialize for Handle {
422427
fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()>
423428
where
424429
S: Serializer,
425430
{
426-
match (&traversal_scope, &self.data) {
427-
(
428-
_,
429-
&NodeData::Element {
430-
ref name,
431-
ref attrs,
432-
..
433-
},
434-
) => {
435-
if traversal_scope == IncludeNode {
436-
try!(serializer.start_elem(
437-
name.clone(),
438-
attrs.borrow().iter().map(|at| (&at.name, &at.value[..]))
439-
));
440-
}
441-
442-
for handle in self.children.borrow().iter() {
443-
try!(handle.clone().serialize(serializer, IncludeNode));
444-
}
431+
let mut ops = match traversal_scope {
432+
IncludeNode => vec![SerializeOp::Open(self.clone())],
433+
ChildrenOnly(_) => self
434+
.children
435+
.borrow()
436+
.iter()
437+
.map(|h| SerializeOp::Open(h.clone())).collect(),
438+
};
445439

446-
if traversal_scope == IncludeNode {
447-
try!(serializer.end_elem(name.clone()));
440+
while !ops.is_empty() {
441+
match ops.remove(0) {
442+
SerializeOp::Open(handle) => {
443+
match &handle.data {
444+
&NodeData::Element {
445+
ref name,
446+
ref attrs,
447+
..
448+
} => {
449+
try!(serializer.start_elem(
450+
name.clone(),
451+
attrs.borrow().iter().map(|at| (&at.name, &at.value[..]))
452+
));
453+
454+
ops.insert(0, SerializeOp::Close(name.clone()));
455+
456+
for child in handle.children.borrow().iter().rev() {
457+
ops.insert(0, SerializeOp::Open(child.clone()));
458+
}
459+
}
460+
461+
&NodeData::Doctype { ref name, .. } => serializer.write_doctype(&name)?,
462+
463+
&NodeData::Text { ref contents } => {
464+
serializer.write_text(&contents.borrow())?
465+
}
466+
467+
&NodeData::Comment { ref contents } => {
468+
serializer.write_comment(&contents)?
469+
},
470+
471+
&NodeData::ProcessingInstruction {
472+
ref target,
473+
ref contents,
474+
} => serializer.write_processing_instruction(target, contents)?,
475+
476+
&NodeData::Document => panic!("Can't serialize Document node itself"),
477+
}
448478
}
449-
Ok(())
450-
},
451479

452-
(&ChildrenOnly(_), &NodeData::Document) => {
453-
for handle in self.children.borrow().iter() {
454-
try!(handle.clone().serialize(serializer, IncludeNode));
480+
SerializeOp::Close(name) => {
481+
try!(serializer.end_elem(name));
455482
}
456-
Ok(())
457-
},
458-
459-
(&ChildrenOnly(_), _) => Ok(()),
460-
461-
(&IncludeNode, &NodeData::Doctype { ref name, .. }) => serializer.write_doctype(&name),
462-
(&IncludeNode, &NodeData::Text { ref contents }) => {
463-
serializer.write_text(&contents.borrow())
464-
},
465-
(&IncludeNode, &NodeData::Comment { ref contents }) => {
466-
serializer.write_comment(&contents)
467-
},
468-
(
469-
&IncludeNode,
470-
&NodeData::ProcessingInstruction {
471-
ref target,
472-
ref contents,
473-
},
474-
) => serializer.write_processing_instruction(target, contents),
475-
(&IncludeNode, &NodeData::Document) => panic!("Can't serialize Document node itself"),
483+
}
476484
}
485+
486+
Ok(())
477487
}
478488
}

0 commit comments

Comments
 (0)