Browse Source

Separate out xml module

Getty Ritter 5 years ago
parent
commit
60a15ed000
2 changed files with 85 additions and 53 deletions
  1. 5 53
      src/lib.rs
  2. 80 0
      src/xml.rs

+ 5 - 53
src/lib.rs

@@ -3,6 +3,9 @@ use std::fs::{self, OpenOptions};
 use std::io::{self, Write};
 use std::path::Path;
 
+mod xml;
+use xml::XMLWriter;
+
 const MAX_OUTPUT_FILES: u32 = 500;
 
 /// An SVG document, which has a fixed size (computed in inches) as
@@ -24,57 +27,6 @@ impl Display for Inches {
 
 fn inches(amt: f64) -> Inches { Inches { amt } }
 
-pub struct XMLWriter<'a>{
-    writer: &'a mut Write,
-}
-
-impl<'a> XMLWriter<'a> {
-    pub fn start(buf: &'a mut Write) -> io::Result<XMLWriter<'a>> {
-        writeln!(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?;
-        Ok(XMLWriter { writer: buf })
-    }
-
-    /// create an entire closed tag with the given attributes
-    pub fn tag(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> {
-        write!(self.writer, "<{}", name)?;
-        for &(k, v) in attrs {
-            write!(self.writer, " {}=\"{}\"", k, v)?;
-        }
-        writeln!(self.writer, "/>")?;
-        Ok(())
-    }
-
-    /// create an open tag with the given attributes
-    pub fn open(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> {
-        write!(self.writer, "<{}", name)?;
-        for &(k, v) in attrs {
-            write!(self.writer, " {}=\"{}\"", k, v)?;
-        }
-        writeln!(self.writer, ">")?;
-        Ok(())
-    }
-
-    /// close a tag with the given attributes
-    pub fn close(&mut self, name: &str) -> io::Result<()> {
-        write!(self.writer, "</{}>", name)?;
-        Ok(())
-    }
-
-    pub fn block<F>(&mut self, name: &str, attrs: &[(&str, &Display)], cb: F) -> io::Result<()>
-    where F: FnOnce(&mut XMLWriter<'a>) -> io::Result<()>
-    {
-        write!(self.writer, "<{}", name)?;
-        for &(k, v) in attrs {
-            write!(self.writer, " {}=\"{}\"", k, v)?;
-        }
-        writeln!(self.writer, ">")?;
-        cb(self)?;
-        write!(self.writer, "</{}>", name)?;
-        Ok(())
-    }
-
-}
-
 /// Create a new empty SVG document of the specified width and height
 pub fn svg(w: f64, h: f64) -> SVG {
     SVG {
@@ -251,7 +203,7 @@ impl AsSVG for Rect {
               ("width", &w),
               ("height", &h),
               ("stroke", &"black"),
-              ("fill", &"white"),
+              ("fill", &"none"),
             ]
         )
     }
@@ -281,7 +233,7 @@ impl AsSVG for Circle {
               ("cy", &y),
               ("r", &r),
               ("stroke", &"black"),
-              ("fill", &"white"),
+              ("fill", &"none"),
             ]
         )
     }

+ 80 - 0
src/xml.rs

@@ -0,0 +1,80 @@
+use std::fmt::{Display};
+use std::io::{self, Write};
+use std::iter::repeat;
+
+
+/// An `XMLWriter` is a wrapper over a `Write` value that provides
+/// helper functions for generating (mostly) well-formed XML.
+pub struct XMLWriter<'a>{
+    writer: &'a mut Write,
+    indent: usize,
+}
+
+impl<'a> XMLWriter<'a> {
+    /// Create a new XMLWriter and add an XML version/encoding header
+    /// on top
+    pub fn start(buf: &'a mut Write) -> io::Result<XMLWriter<'a>> {
+        writeln!(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?;
+        Ok(XMLWriter { writer: buf, indent: 0, })
+    }
+
+    fn indent(&mut self) -> io::Result<()> {
+        write!(self.writer, "{}", repeat(' ').take(self.indent).collect::<String>())?;
+        Ok(())
+    }
+
+    /// create an complete tag with the given attributes
+    pub fn tag(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> {
+        self.indent()?;
+        write!(self.writer, "<{}", name)?;
+        for &(k, v) in attrs {
+            write!(self.writer, " {}=\"{}\"", k, v)?;
+        }
+        writeln!(self.writer, "/>")?;
+        Ok(())
+    }
+
+    /// create an open tag with the given attributes; you must close
+    /// it manually later
+    pub fn open(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> {
+        self.indent()?;
+        write!(self.writer, "<{}", name)?;
+        for &(k, v) in attrs {
+            write!(self.writer, " {}=\"{}\"", k, v)?;
+        }
+        writeln!(self.writer, ">")?;
+        Ok(())
+    }
+
+    /// close a tag with the given attributes
+    pub fn close(&mut self, name: &str) -> io::Result<()> {
+        self.indent()?;
+        write!(self.writer, "</{}>", name)?;
+        Ok(())
+    }
+
+    /// create an open-close tag pair with the given attributes,
+    /// calling the provided function in order to fill in the interior
+    /// tags as well
+    pub fn block<F>(
+        &mut self,
+        name: &str,
+        attrs: &[(&str, &Display)],
+        cb: F
+    ) -> io::Result<()>
+    where F: FnOnce(&mut XMLWriter<'a>) -> io::Result<()>
+    {
+        self.indent()?;
+        write!(self.writer, "<{}", name)?;
+        for &(k, v) in attrs {
+            write!(self.writer, " {}=\"{}\"", k, v)?;
+        }
+        writeln!(self.writer, ">")?;
+        self.indent += 2;
+        cb(self)?;
+        self.indent -= 2;
+        write!(self.writer, "</{}>", name)?;
+        Ok(())
+    }
+
+}