Separate out xml module
Getty Ritter
7 years ago
| 2 | 2 | use std::fs::{self, OpenOptions}; |
| 3 | 3 | use std::io::{self, Write}; |
| 4 | 4 | use std::path::Path; |
| 5 | ||
| 6 | mod xml; | |
| 7 | use xml::XMLWriter; | |
| 5 | 8 | |
| 6 | 9 | const MAX_OUTPUT_FILES: u32 = 500; |
| 7 | 10 | |
| 23 | 26 | } |
| 24 | 27 | |
| 25 | 28 | fn inches(amt: f64) -> Inches { Inches { amt } } |
| 26 | ||
| 27 | pub struct XMLWriter<'a>{ | |
| 28 | writer: &'a mut Write, | |
| 29 | } | |
| 30 | ||
| 31 | impl<'a> XMLWriter<'a> { | |
| 32 | pub fn start(buf: &'a mut Write) -> io::Result<XMLWriter<'a>> { | |
| 33 | writeln!(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?; | |
| 34 | Ok(XMLWriter { writer: buf }) | |
| 35 | } | |
| 36 | ||
| 37 | /// create an entire closed tag with the given attributes | |
| 38 | pub fn tag(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> { | |
| 39 | write!(self.writer, "<{}", name)?; | |
| 40 | for &(k, v) in attrs { | |
| 41 | write!(self.writer, " {}=\"{}\"", k, v)?; | |
| 42 | } | |
| 43 | writeln!(self.writer, "/>")?; | |
| 44 | Ok(()) | |
| 45 | } | |
| 46 | ||
| 47 | /// create an open tag with the given attributes | |
| 48 | pub fn open(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> { | |
| 49 | write!(self.writer, "<{}", name)?; | |
| 50 | for &(k, v) in attrs { | |
| 51 | write!(self.writer, " {}=\"{}\"", k, v)?; | |
| 52 | } | |
| 53 | writeln!(self.writer, ">")?; | |
| 54 | Ok(()) | |
| 55 | } | |
| 56 | ||
| 57 | /// close a tag with the given attributes | |
| 58 | pub fn close(&mut self, name: &str) -> io::Result<()> { | |
| 59 | write!(self.writer, "</{}>", name)?; | |
| 60 | Ok(()) | |
| 61 | } | |
| 62 | ||
| 63 | pub fn block<F>(&mut self, name: &str, attrs: &[(&str, &Display)], cb: F) -> io::Result<()> | |
| 64 | where F: FnOnce(&mut XMLWriter<'a>) -> io::Result<()> | |
| 65 | { | |
| 66 | write!(self.writer, "<{}", name)?; | |
| 67 | for &(k, v) in attrs { | |
| 68 | write!(self.writer, " {}=\"{}\"", k, v)?; | |
| 69 | } | |
| 70 | writeln!(self.writer, ">")?; | |
| 71 | cb(self)?; | |
| 72 | write!(self.writer, "</{}>", name)?; | |
| 73 | Ok(()) | |
| 74 | } | |
| 75 | ||
| 76 | } | |
| 77 | 29 | |
| 78 | 30 | /// Create a new empty SVG document of the specified width and height |
| 79 | 31 | pub fn svg(w: f64, h: f64) -> SVG { |
| 251 | 203 | ("width", &w), |
| 252 | 204 | ("height", &h), |
| 253 | 205 | ("stroke", &"black"), |
| 254 |
("fill", &" |
|
| 206 | ("fill", &"none"), | |
| 255 | 207 | ] |
| 256 | 208 | ) |
| 257 | 209 | } |
| 281 | 233 | ("cy", &y), |
| 282 | 234 | ("r", &r), |
| 283 | 235 | ("stroke", &"black"), |
| 284 |
("fill", &" |
|
| 236 | ("fill", &"none"), | |
| 285 | 237 | ] |
| 286 | 238 | ) |
| 287 | 239 | } |
| 1 | use std::fmt::{Display}; | |
| 2 | use std::io::{self, Write}; | |
| 3 | use std::iter::repeat; | |
| 4 | ||
| 5 | ||
| 6 | /// An `XMLWriter` is a wrapper over a `Write` value that provides | |
| 7 | /// helper functions for generating (mostly) well-formed XML. | |
| 8 | pub struct XMLWriter<'a>{ | |
| 9 | writer: &'a mut Write, | |
| 10 | indent: usize, | |
| 11 | } | |
| 12 | ||
| 13 | impl<'a> XMLWriter<'a> { | |
| 14 | /// Create a new XMLWriter and add an XML version/encoding header | |
| 15 | /// on top | |
| 16 | pub fn start(buf: &'a mut Write) -> io::Result<XMLWriter<'a>> { | |
| 17 | writeln!(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?; | |
| 18 | Ok(XMLWriter { writer: buf, indent: 0, }) | |
| 19 | } | |
| 20 | ||
| 21 | fn indent(&mut self) -> io::Result<()> { | |
| 22 | write!(self.writer, "{}", repeat(' ').take(self.indent).collect::<String>())?; | |
| 23 | Ok(()) | |
| 24 | } | |
| 25 | ||
| 26 | /// create an complete tag with the given attributes | |
| 27 | pub fn tag(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> { | |
| 28 | self.indent()?; | |
| 29 | write!(self.writer, "<{}", name)?; | |
| 30 | for &(k, v) in attrs { | |
| 31 | write!(self.writer, " {}=\"{}\"", k, v)?; | |
| 32 | } | |
| 33 | writeln!(self.writer, "/>")?; | |
| 34 | Ok(()) | |
| 35 | } | |
| 36 | ||
| 37 | /// create an open tag with the given attributes; you must close | |
| 38 | /// it manually later | |
| 39 | pub fn open(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> { | |
| 40 | self.indent()?; | |
| 41 | write!(self.writer, "<{}", name)?; | |
| 42 | for &(k, v) in attrs { | |
| 43 | write!(self.writer, " {}=\"{}\"", k, v)?; | |
| 44 | } | |
| 45 | writeln!(self.writer, ">")?; | |
| 46 | Ok(()) | |
| 47 | } | |
| 48 | ||
| 49 | /// close a tag with the given attributes | |
| 50 | pub fn close(&mut self, name: &str) -> io::Result<()> { | |
| 51 | self.indent()?; | |
| 52 | write!(self.writer, "</{}>", name)?; | |
| 53 | Ok(()) | |
| 54 | } | |
| 55 | ||
| 56 | /// create an open-close tag pair with the given attributes, | |
| 57 | /// calling the provided function in order to fill in the interior | |
| 58 | /// tags as well | |
| 59 | pub fn block<F>( | |
| 60 | &mut self, | |
| 61 | name: &str, | |
| 62 | attrs: &[(&str, &Display)], | |
| 63 | cb: F | |
| 64 | ) -> io::Result<()> | |
| 65 | where F: FnOnce(&mut XMLWriter<'a>) -> io::Result<()> | |
| 66 | { | |
| 67 | self.indent()?; | |
| 68 | write!(self.writer, "<{}", name)?; | |
| 69 | for &(k, v) in attrs { | |
| 70 | write!(self.writer, " {}=\"{}\"", k, v)?; | |
| 71 | } | |
| 72 | writeln!(self.writer, ">")?; | |
| 73 | self.indent += 2; | |
| 74 | cb(self)?; | |
| 75 | self.indent -= 2; | |
| 76 | write!(self.writer, "</{}>", name)?; | |
| 77 | Ok(()) | |
| 78 | } | |
| 79 | ||
| 80 | } |