]>
Commit | Line | Data |
---|---|---|
476ff2be SL |
1 | use std::fmt; |
2 | ||
3 | use Table as TomlTable; | |
4 | use Value::{self, String, Integer, Float, Boolean, Datetime, Array, Table}; | |
5 | ||
6 | struct Printer<'a, 'b:'a> { | |
7 | output: &'a mut fmt::Formatter<'b>, | |
8 | stack: Vec<&'a str>, | |
9 | } | |
10 | ||
11 | struct Key<'a>(&'a [&'a str]); | |
12 | ||
13 | impl fmt::Display for Value { | |
14 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
15 | match *self { | |
16 | String(ref s) => write_str(f, s), | |
17 | Integer(i) => write!(f, "{}", i), | |
18 | Float(fp) => { | |
19 | try!(write!(f, "{}", fp)); | |
20 | if fp % 1.0 == 0.0 { try!(write!(f, ".0")) } | |
21 | Ok(()) | |
22 | } | |
23 | Boolean(b) => write!(f, "{}", b), | |
24 | Datetime(ref s) => write!(f, "{}", s), | |
25 | Table(ref t) => { | |
26 | let mut p = Printer { output: f, stack: Vec::new() }; | |
27 | p.print(t) | |
28 | } | |
29 | Array(ref a) => { | |
30 | try!(write!(f, "[")); | |
31 | for (i, v) in a.iter().enumerate() { | |
32 | if i != 0 { try!(write!(f, ", ")); } | |
33 | try!(write!(f, "{}", v)); | |
34 | } | |
35 | write!(f, "]") | |
36 | } | |
37 | } | |
38 | } | |
39 | } | |
40 | ||
41 | fn write_str(f: &mut fmt::Formatter, s: &str) -> fmt::Result { | |
42 | try!(write!(f, "\"")); | |
43 | for ch in s.chars() { | |
44 | match ch { | |
45 | '\u{8}' => try!(write!(f, "\\b")), | |
46 | '\u{9}' => try!(write!(f, "\\t")), | |
47 | '\u{a}' => try!(write!(f, "\\n")), | |
48 | '\u{c}' => try!(write!(f, "\\f")), | |
49 | '\u{d}' => try!(write!(f, "\\r")), | |
50 | '\u{22}' => try!(write!(f, "\\\"")), | |
51 | '\u{5c}' => try!(write!(f, "\\\\")), | |
8bb4bdeb XL |
52 | c if c < '\u{1f}' => { |
53 | try!(write!(f, "\\u{:04}", ch as u32)) | |
54 | } | |
476ff2be SL |
55 | ch => try!(write!(f, "{}", ch)), |
56 | } | |
57 | } | |
58 | write!(f, "\"") | |
59 | } | |
60 | ||
61 | impl<'a, 'b> Printer<'a, 'b> { | |
62 | fn print(&mut self, table: &'a TomlTable) -> fmt::Result { | |
8bb4bdeb | 63 | let mut space_out_first = false; |
476ff2be SL |
64 | for (k, v) in table.iter() { |
65 | match *v { | |
66 | Table(..) => continue, | |
67 | Array(ref a) => { | |
68 | if let Some(&Table(..)) = a.first() { | |
69 | continue; | |
70 | } | |
71 | } | |
72 | _ => {} | |
73 | } | |
8bb4bdeb | 74 | space_out_first = true; |
476ff2be SL |
75 | try!(writeln!(self.output, "{} = {}", Key(&[k]), v)); |
76 | } | |
8bb4bdeb | 77 | for (i, (k, v)) in table.iter().enumerate() { |
476ff2be SL |
78 | match *v { |
79 | Table(ref inner) => { | |
80 | self.stack.push(k); | |
8bb4bdeb XL |
81 | if space_out_first || i != 0 { |
82 | try!(write!(self.output, "\n")); | |
83 | } | |
84 | try!(writeln!(self.output, "[{}]", Key(&self.stack))); | |
476ff2be SL |
85 | try!(self.print(inner)); |
86 | self.stack.pop(); | |
87 | } | |
88 | Array(ref inner) => { | |
89 | match inner.first() { | |
90 | Some(&Table(..)) => {} | |
91 | _ => continue | |
92 | } | |
93 | self.stack.push(k); | |
8bb4bdeb XL |
94 | for (j, inner) in inner.iter().enumerate() { |
95 | if space_out_first || i != 0 || j != 0 { | |
96 | try!(write!(self.output, "\n")); | |
97 | } | |
98 | try!(writeln!(self.output, "[[{}]]", Key(&self.stack))); | |
476ff2be SL |
99 | match *inner { |
100 | Table(ref inner) => try!(self.print(inner)), | |
101 | _ => panic!("non-heterogeneous toml array"), | |
102 | } | |
103 | } | |
104 | self.stack.pop(); | |
105 | } | |
106 | _ => {}, | |
107 | } | |
108 | } | |
109 | Ok(()) | |
110 | } | |
111 | } | |
112 | ||
113 | impl<'a> fmt::Display for Key<'a> { | |
114 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
115 | for (i, part) in self.0.iter().enumerate() { | |
116 | if i != 0 { try!(write!(f, ".")); } | |
117 | let ok = part.chars().all(|c| { | |
118 | match c { | |
119 | 'a' ... 'z' | | |
120 | 'A' ... 'Z' | | |
121 | '0' ... '9' | | |
122 | '-' | '_' => true, | |
123 | _ => false, | |
124 | } | |
125 | }); | |
126 | if ok { | |
127 | try!(write!(f, "{}", part)); | |
128 | } else { | |
129 | try!(write_str(f, part)); | |
130 | } | |
131 | } | |
132 | Ok(()) | |
133 | } | |
134 | } |