]> git.lizzy.rs Git - rust.git/blob - src/libcore/fmt/builders.rs
7c986131a52858dd357c48b0f6ec02208635878e
[rust.git] / src / libcore / fmt / builders.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use prelude::v1::*;
12 use fmt::{self, Write, FlagV1};
13
14 struct PadAdapter<'a, 'b: 'a> {
15     fmt: &'a mut fmt::Formatter<'b>,
16     on_newline: bool,
17 }
18
19 impl<'a, 'b: 'a> PadAdapter<'a, 'b> {
20     fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> {
21         PadAdapter {
22             fmt: fmt,
23             on_newline: false,
24         }
25     }
26 }
27
28 impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
29     fn write_str(&mut self, mut s: &str) -> fmt::Result {
30         while !s.is_empty() {
31             if self.on_newline {
32                 try!(self.fmt.write_str("    "));
33             }
34
35             let split = match s.find('\n') {
36                 Some(pos) => {
37                     self.on_newline = true;
38                     pos + 1
39                 }
40                 None => {
41                     self.on_newline = false;
42                     s.len()
43                 }
44             };
45             try!(self.fmt.write_str(&s[..split]));
46             s = &s[split..];
47         }
48
49         Ok(())
50     }
51 }
52
53 /// A struct to help with `fmt::Debug` implementations.
54 ///
55 /// Constructed by the `Formatter::debug_struct` method.
56 #[must_use]
57 #[stable(feature = "debug_builders", since = "1.2.0")]
58 pub struct DebugStruct<'a, 'b: 'a> {
59     fmt: &'a mut fmt::Formatter<'b>,
60     result: fmt::Result,
61     has_fields: bool,
62 }
63
64 pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
65                                 name: &str)
66                                 -> DebugStruct<'a, 'b> {
67     let result = fmt.write_str(name);
68     DebugStruct {
69         fmt: fmt,
70         result: result,
71         has_fields: false,
72     }
73 }
74
75 impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
76     /// Adds a new field to the generated struct output.
77     #[stable(feature = "debug_builders", since = "1.2.0")]
78     pub fn field(&mut self, name: &str, value: &fmt::Debug) -> &mut DebugStruct<'a, 'b> {
79         self.result = self.result.and_then(|_| {
80             let prefix = if self.has_fields {
81                 ","
82             } else {
83                 " {"
84             };
85
86             if self.is_pretty() {
87                 let mut writer = PadAdapter::new(self.fmt);
88                 fmt::write(&mut writer,
89                            format_args!("{}\n{}: {:#?}", prefix, name, value))
90             } else {
91                 write!(self.fmt, "{} {}: {:?}", prefix, name, value)
92             }
93         });
94
95         self.has_fields = true;
96         self
97     }
98
99     /// Finishes output and returns any error encountered.
100     #[stable(feature = "debug_builders", since = "1.2.0")]
101     pub fn finish(&mut self) -> fmt::Result {
102         if self.has_fields {
103             self.result = self.result.and_then(|_| {
104                 if self.is_pretty() {
105                     self.fmt.write_str("\n}")
106                 } else {
107                     self.fmt.write_str(" }")
108                 }
109             });
110         }
111         self.result
112     }
113
114     fn is_pretty(&self) -> bool {
115         self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
116     }
117 }
118
119 /// A struct to help with `fmt::Debug` implementations.
120 ///
121 /// Constructed by the `Formatter::debug_tuple` method.
122 #[must_use]
123 #[stable(feature = "debug_builders", since = "1.2.0")]
124 pub struct DebugTuple<'a, 'b: 'a> {
125     fmt: &'a mut fmt::Formatter<'b>,
126     result: fmt::Result,
127     has_fields: bool,
128 }
129
130 pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
131     let result = fmt.write_str(name);
132     DebugTuple {
133         fmt: fmt,
134         result: result,
135         has_fields: false,
136     }
137 }
138
139 impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
140     /// Adds a new field to the generated tuple struct output.
141     #[stable(feature = "debug_builders", since = "1.2.0")]
142     pub fn field(&mut self, value: &fmt::Debug) -> &mut DebugTuple<'a, 'b> {
143         self.result = self.result.and_then(|_| {
144             let (prefix, space) = if self.has_fields {
145                 (",", " ")
146             } else {
147                 ("(", "")
148             };
149
150             if self.is_pretty() {
151                 let mut writer = PadAdapter::new(self.fmt);
152                 fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, value))
153             } else {
154                 write!(self.fmt, "{}{}{:?}", prefix, space, value)
155             }
156         });
157
158         self.has_fields = true;
159         self
160     }
161
162     /// Finishes output and returns any error encountered.
163     #[stable(feature = "debug_builders", since = "1.2.0")]
164     pub fn finish(&mut self) -> fmt::Result {
165         if self.has_fields {
166             self.result = self.result.and_then(|_| {
167                 if self.is_pretty() {
168                     self.fmt.write_str("\n)")
169                 } else {
170                     self.fmt.write_str(")")
171                 }
172             });
173         }
174         self.result
175     }
176
177     fn is_pretty(&self) -> bool {
178         self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
179     }
180
181     /// Returns the wrapped `Formatter`.
182     #[unstable(feature = "debug_builder_formatter", reason = "recently added",
183                issue = "27782")]
184     #[rustc_deprecated(since = "1.7.0", reason = "will be removed")]
185     pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
186         &mut self.fmt
187     }
188 }
189
190 struct DebugInner<'a, 'b: 'a> {
191     fmt: &'a mut fmt::Formatter<'b>,
192     result: fmt::Result,
193     has_fields: bool,
194 }
195
196 impl<'a, 'b: 'a> DebugInner<'a, 'b> {
197     fn entry(&mut self, entry: &fmt::Debug) {
198         self.result = self.result.and_then(|_| {
199             if self.is_pretty() {
200                 let mut writer = PadAdapter::new(self.fmt);
201                 let prefix = if self.has_fields {
202                     ","
203                 } else {
204                     ""
205                 };
206                 fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
207             } else {
208                 let prefix = if self.has_fields {
209                     ", "
210                 } else {
211                     ""
212                 };
213                 write!(self.fmt, "{}{:?}", prefix, entry)
214             }
215         });
216
217         self.has_fields = true;
218     }
219
220     pub fn finish(&mut self) {
221         let prefix = if self.is_pretty() && self.has_fields {
222             "\n"
223         } else {
224             ""
225         };
226         self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
227     }
228
229     fn is_pretty(&self) -> bool {
230         self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
231     }
232 }
233
234 /// A struct to help with `fmt::Debug` implementations.
235 ///
236 /// Constructed by the `Formatter::debug_set` method.
237 #[must_use]
238 #[stable(feature = "debug_builders", since = "1.2.0")]
239 pub struct DebugSet<'a, 'b: 'a> {
240     inner: DebugInner<'a, 'b>,
241 }
242
243 pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
244     let result = write!(fmt, "{{");
245     DebugSet {
246         inner: DebugInner {
247             fmt: fmt,
248             result: result,
249             has_fields: false,
250         },
251     }
252 }
253
254 impl<'a, 'b: 'a> DebugSet<'a, 'b> {
255     /// Adds a new entry to the set output.
256     #[stable(feature = "debug_builders", since = "1.2.0")]
257     pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugSet<'a, 'b> {
258         self.inner.entry(entry);
259         self
260     }
261
262     /// Adds the contents of an iterator of entries to the set output.
263     #[stable(feature = "debug_builders", since = "1.2.0")]
264     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugSet<'a, 'b>
265         where D: fmt::Debug,
266               I: IntoIterator<Item = D>
267     {
268         for entry in entries {
269             self.entry(&entry);
270         }
271         self
272     }
273
274     /// Finishes output and returns any error encountered.
275     #[stable(feature = "debug_builders", since = "1.2.0")]
276     pub fn finish(&mut self) -> fmt::Result {
277         self.inner.finish();
278         self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
279     }
280 }
281
282 /// A struct to help with `fmt::Debug` implementations.
283 ///
284 /// Constructed by the `Formatter::debug_list` method.
285 #[must_use]
286 #[stable(feature = "debug_builders", since = "1.2.0")]
287 pub struct DebugList<'a, 'b: 'a> {
288     inner: DebugInner<'a, 'b>,
289 }
290
291 pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
292     let result = write!(fmt, "[");
293     DebugList {
294         inner: DebugInner {
295             fmt: fmt,
296             result: result,
297             has_fields: false,
298         },
299     }
300 }
301
302 impl<'a, 'b: 'a> DebugList<'a, 'b> {
303     /// Adds a new entry to the list output.
304     #[stable(feature = "debug_builders", since = "1.2.0")]
305     pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugList<'a, 'b> {
306         self.inner.entry(entry);
307         self
308     }
309
310     /// Adds the contents of an iterator of entries to the list output.
311     #[stable(feature = "debug_builders", since = "1.2.0")]
312     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugList<'a, 'b>
313         where D: fmt::Debug,
314               I: IntoIterator<Item = D>
315     {
316         for entry in entries {
317             self.entry(&entry);
318         }
319         self
320     }
321
322     /// Finishes output and returns any error encountered.
323     #[stable(feature = "debug_builders", since = "1.2.0")]
324     pub fn finish(&mut self) -> fmt::Result {
325         self.inner.finish();
326         self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
327     }
328 }
329
330 /// A struct to help with `fmt::Debug` implementations.
331 ///
332 /// Constructed by the `Formatter::debug_map` method.
333 #[must_use]
334 #[stable(feature = "debug_builders", since = "1.2.0")]
335 pub struct DebugMap<'a, 'b: 'a> {
336     fmt: &'a mut fmt::Formatter<'b>,
337     result: fmt::Result,
338     has_fields: bool,
339 }
340
341 pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
342     let result = write!(fmt, "{{");
343     DebugMap {
344         fmt: fmt,
345         result: result,
346         has_fields: false,
347     }
348 }
349
350 impl<'a, 'b: 'a> DebugMap<'a, 'b> {
351     /// Adds a new entry to the map output.
352     #[stable(feature = "debug_builders", since = "1.2.0")]
353     pub fn entry(&mut self, key: &fmt::Debug, value: &fmt::Debug) -> &mut DebugMap<'a, 'b> {
354         self.result = self.result.and_then(|_| {
355             if self.is_pretty() {
356                 let mut writer = PadAdapter::new(self.fmt);
357                 let prefix = if self.has_fields {
358                     ","
359                 } else {
360                     ""
361                 };
362                 fmt::write(&mut writer,
363                            format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
364             } else {
365                 let prefix = if self.has_fields {
366                     ", "
367                 } else {
368                     ""
369                 };
370                 write!(self.fmt, "{}{:?}: {:?}", prefix, key, value)
371             }
372         });
373
374         self.has_fields = true;
375         self
376     }
377
378     /// Adds the contents of an iterator of entries to the map output.
379     #[stable(feature = "debug_builders", since = "1.2.0")]
380     pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
381         where K: fmt::Debug,
382               V: fmt::Debug,
383               I: IntoIterator<Item = (K, V)>
384     {
385         for (k, v) in entries {
386             self.entry(&k, &v);
387         }
388         self
389     }
390
391     /// Finishes output and returns any error encountered.
392     #[stable(feature = "debug_builders", since = "1.2.0")]
393     pub fn finish(&mut self) -> fmt::Result {
394         let prefix = if self.is_pretty() && self.has_fields {
395             "\n"
396         } else {
397             ""
398         };
399         self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
400     }
401
402     fn is_pretty(&self) -> bool {
403         self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
404     }
405 }