]> git.proxmox.com Git - rustc.git/blob - src/vendor/toml/src/display.rs
6891530beeb4e651a8433772ebc97baf8642b954
[rustc.git] / src / vendor / toml / src / display.rs
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, "\\\\")),
52 ch => try!(write!(f, "{}", ch)),
53 }
54 }
55 write!(f, "\"")
56 }
57
58 impl<'a, 'b> Printer<'a, 'b> {
59 fn print(&mut self, table: &'a TomlTable) -> fmt::Result {
60 for (k, v) in table.iter() {
61 match *v {
62 Table(..) => continue,
63 Array(ref a) => {
64 if let Some(&Table(..)) = a.first() {
65 continue;
66 }
67 }
68 _ => {}
69 }
70 try!(writeln!(self.output, "{} = {}", Key(&[k]), v));
71 }
72 for (k, v) in table.iter() {
73 match *v {
74 Table(ref inner) => {
75 self.stack.push(k);
76 try!(writeln!(self.output, "\n[{}]", Key(&self.stack)));
77 try!(self.print(inner));
78 self.stack.pop();
79 }
80 Array(ref inner) => {
81 match inner.first() {
82 Some(&Table(..)) => {}
83 _ => continue
84 }
85 self.stack.push(k);
86 for inner in inner.iter() {
87 try!(writeln!(self.output, "\n[[{}]]", Key(&self.stack)));
88 match *inner {
89 Table(ref inner) => try!(self.print(inner)),
90 _ => panic!("non-heterogeneous toml array"),
91 }
92 }
93 self.stack.pop();
94 }
95 _ => {},
96 }
97 }
98 Ok(())
99 }
100 }
101
102 impl<'a> fmt::Display for Key<'a> {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 for (i, part) in self.0.iter().enumerate() {
105 if i != 0 { try!(write!(f, ".")); }
106 let ok = part.chars().all(|c| {
107 match c {
108 'a' ... 'z' |
109 'A' ... 'Z' |
110 '0' ... '9' |
111 '-' | '_' => true,
112 _ => false,
113 }
114 });
115 if ok {
116 try!(write!(f, "{}", part));
117 } else {
118 try!(write_str(f, part));
119 }
120 }
121 Ok(())
122 }
123 }
124
125 #[cfg(test)]
126 #[allow(warnings)]
127 mod tests {
128 use Value;
129 use Value::{String, Integer, Float, Boolean, Datetime, Array, Table};
130 use std::collections::BTreeMap;
131
132 macro_rules! map( ($($k:expr => $v:expr),*) => ({
133 let mut _m = BTreeMap::new();
134 $(_m.insert($k.to_string(), $v);)*
135 _m
136 }) );
137
138 #[test]
139 fn simple_show() {
140 assert_eq!(String("foo".to_string()).to_string(),
141 "\"foo\"");
142 assert_eq!(Integer(10).to_string(),
143 "10");
144 assert_eq!(Float(10.0).to_string(),
145 "10.0");
146 assert_eq!(Float(2.4).to_string(),
147 "2.4");
148 assert_eq!(Boolean(true).to_string(),
149 "true");
150 assert_eq!(Datetime("test".to_string()).to_string(),
151 "test");
152 assert_eq!(Array(vec![]).to_string(),
153 "[]");
154 assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string(),
155 "[1, 2]");
156 }
157
158 #[test]
159 fn table() {
160 assert_eq!(Table(map! { }).to_string(),
161 "");
162 assert_eq!(Table(map! { "test" => Integer(2) }).to_string(),
163 "test = 2\n");
164 assert_eq!(Table(map! {
165 "test" => Integer(2),
166 "test2" => Table(map! {
167 "test" => String("wut".to_string())
168 })
169 }).to_string(),
170 "test = 2\n\
171 \n\
172 [test2]\n\
173 test = \"wut\"\n");
174 assert_eq!(Table(map! {
175 "test" => Integer(2),
176 "test2" => Table(map! {
177 "test" => String("wut".to_string())
178 })
179 }).to_string(),
180 "test = 2\n\
181 \n\
182 [test2]\n\
183 test = \"wut\"\n");
184 assert_eq!(Table(map! {
185 "test" => Integer(2),
186 "test2" => Array(vec![Table(map! {
187 "test" => String("wut".to_string())
188 })])
189 }).to_string(),
190 "test = 2\n\
191 \n\
192 [[test2]]\n\
193 test = \"wut\"\n");
194 assert_eq!(Table(map! {
195 "foo.bar" => Integer(2),
196 "foo\"bar" => Integer(2)
197 }).to_string(),
198 "\"foo\\\"bar\" = 2\n\
199 \"foo.bar\" = 2\n");
200 }
201 }