Separate out xml module
Getty Ritter
6 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 | } |