I have a little XML writing helper. It writes to an inner impl Write
. But how do I make it accept either fmt::Write
or io::Write
?
Usage:
let mut string = String::new(); // what if I want this to be a File?
let mut xml = Xml::new(&mut string);
xml.open_element("html")?;
xml.text("hi")?;
xml.close_element()?;
println!("{}", string); // prints <html>hi</html>
pub(crate) struct Xml<'a, W>
where
W: Write,
{
writer: &'a mut W,
elements: Vec<&'static str>,
in_tag: bool,
}
impl<'a, W> Xml<'a, W>
where
W: Write,
{
pub fn new(writer: &'a mut W) -> Self {
Self {
writer,
elements: Vec::new(),
in_tag: false,
}
}
}
impl<W> Xml<'_, W>
where
W: Write,
{
pub fn open_element(&mut self, name: &'static str) -> Result {
if self.in_tag {
writeln!(self.writer, ">")?;
} else {
self.in_tag = true;
}
self.elements.push(name);
write!(self.writer, "<{}", name)
}
pub fn attribute(&mut self, name: &'static str, value: impl Display) -> Result {
write!(self.writer, r#" {}="{}""#, name, value)
}
pub fn close_element(&mut self) -> Result {
let name = self.elements.pop().unwrap();
if self.in_tag {
self.in_tag = false;
writeln!(self.writer, "/>")
} else {
writeln!(self.writer, "</{}>", name)
}
}
pub fn text(&mut self, text: impl Display) -> Result {
if self.in_tag {
write!(self.writer, ">")?;
self.in_tag = false;
}
write!(self.writer, "{}", text)
}
}