]> git.lizzy.rs Git - rust.git/blob - src/libcore/fmt/builders.rs
Auto merge of #28621 - tshepang:move-safety, r=steveklabnik
[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     pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
185         &mut self.fmt
186     }
187 }
188
189 struct DebugInner<'a, 'b: 'a> {
190     fmt: &'a mut fmt::Formatter<'b>,
191     result: fmt::Result,
192     has_fields: bool,
193 }
194
195 impl<'a, 'b: 'a> DebugInner<'a, 'b> {
196     fn entry(&mut self, entry: &fmt::Debug) {
197         self.result = self.result.and_then(|_| {
198             if self.is_pretty() {
199                 let mut writer = PadAdapter::new(self.fmt);
200                 let prefix = if self.has_fields {
201                     ","
202                 } else {
203                     ""
204                 };
205                 fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
206             } else {
207                 let prefix = if self.has_fields {
208                     ", "
209                 } else {
210                     ""
211                 };
212                 write!(self.fmt, "{}{:?}", prefix, entry)
213             }
214         });
215
216         self.has_fields = true;
217     }
218
219     pub fn finish(&mut self) {
220         let prefix = if self.is_pretty() && self.has_fields {
221             "\n"
222         } else {
223             ""
224         };
225         self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
226     }
227
228     fn is_pretty(&self) -> bool {
229         self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
230     }
231 }
232
233 /// A struct to help with `fmt::Debug` implementations.
234 ///
235 /// Constructed by the `Formatter::debug_set` method.
236 #[must_use]
237 #[stable(feature = "debug_builders", since = "1.2.0")]
238 pub struct DebugSet<'a, 'b: 'a> {
239     inner: DebugInner<'a, 'b>,
240 }
241
242 pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
243     let result = write!(fmt, "{{");
244     DebugSet {
245         inner: DebugInner {
246             fmt: fmt,
247             result: result,
248             has_fields: false,
249         },
250     }
251 }
252
253 impl<'a, 'b: 'a> DebugSet<'a, 'b> {
254     /// Adds a new entry to the set output.
255     #[stable(feature = "debug_builders", since = "1.2.0")]
256     pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugSet<'a, 'b> {
257         self.inner.entry(entry);
258         self
259     }
260
261     /// Adds the contents of an iterator of entries to the set output.
262     #[stable(feature = "debug_builders", since = "1.2.0")]
263     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugSet<'a, 'b>
264         where D: fmt::Debug,
265               I: IntoIterator<Item = D>
266     {
267         for entry in entries {
268             self.entry(&entry);
269         }
270         self
271     }
272
273     /// Finishes output and returns any error encountered.
274     #[stable(feature = "debug_builders", since = "1.2.0")]
275     pub fn finish(&mut self) -> fmt::Result {
276         self.inner.finish();
277         self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
278     }
279 }
280
281 /// A struct to help with `fmt::Debug` implementations.
282 ///
283 /// Constructed by the `Formatter::debug_list` method.
284 #[must_use]
285 #[stable(feature = "debug_builders", since = "1.2.0")]
286 pub struct DebugList<'a, 'b: 'a> {
287     inner: DebugInner<'a, 'b>,
288 }
289
290 pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
291     let result = write!(fmt, "[");
292     DebugList {
293         inner: DebugInner {
294             fmt: fmt,
295             result: result,
296             has_fields: false,
297         },
298     }
299 }
300
301 impl<'a, 'b: 'a> DebugList<'a, 'b> {
302     /// Adds a new entry to the list output.
303     #[stable(feature = "debug_builders", since = "1.2.0")]
304     pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugList<'a, 'b> {
305         self.inner.entry(entry);
306         self
307     }
308
309     /// Adds the contents of an iterator of entries to the list output.
310     #[stable(feature = "debug_builders", since = "1.2.0")]
311     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugList<'a, 'b>
312         where D: fmt::Debug,
313               I: IntoIterator<Item = D>
314     {
315         for entry in entries {
316             self.entry(&entry);
317         }
318         self
319     }
320
321     /// Finishes output and returns any error encountered.
322     #[stable(feature = "debug_builders", since = "1.2.0")]
323     pub fn finish(&mut self) -> fmt::Result {
324         self.inner.finish();
325         self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
326     }
327 }
328
329 /// A struct to help with `fmt::Debug` implementations.
330 ///
331 /// Constructed by the `Formatter::debug_map` method.
332 #[must_use]
333 #[stable(feature = "debug_builders", since = "1.2.0")]
334 pub struct DebugMap<'a, 'b: 'a> {
335     fmt: &'a mut fmt::Formatter<'b>,
336     result: fmt::Result,
337     has_fields: bool,
338 }
339
340 pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
341     let result = write!(fmt, "{{");
342     DebugMap {
343         fmt: fmt,
344         result: result,
345         has_fields: false,
346     }
347 }
348
349 impl<'a, 'b: 'a> DebugMap<'a, 'b> {
350     /// Adds a new entry to the map output.
351     #[stable(feature = "debug_builders", since = "1.2.0")]
352     pub fn entry(&mut self, key: &fmt::Debug, value: &fmt::Debug) -> &mut DebugMap<'a, 'b> {
353         self.result = self.result.and_then(|_| {
354             if self.is_pretty() {
355                 let mut writer = PadAdapter::new(self.fmt);
356                 let prefix = if self.has_fields {
357                     ","
358                 } else {
359                     ""
360                 };
361                 fmt::write(&mut writer,
362                            format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
363             } else {
364                 let prefix = if self.has_fields {
365                     ", "
366                 } else {
367                     ""
368                 };
369                 write!(self.fmt, "{}{:?}: {:?}", prefix, key, value)
370             }
371         });
372
373         self.has_fields = true;
374         self
375     }
376
377     /// Adds the contents of an iterator of entries to the map output.
378     #[stable(feature = "debug_builders", since = "1.2.0")]
379     pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
380         where K: fmt::Debug,
381               V: fmt::Debug,
382               I: IntoIterator<Item = (K, V)>
383     {
384         for (k, v) in entries {
385             self.entry(&k, &v);
386         }
387         self
388     }
389
390     /// Finishes output and returns any error encountered.
391     #[stable(feature = "debug_builders", since = "1.2.0")]
392     pub fn finish(&mut self) -> fmt::Result {
393         let prefix = if self.is_pretty() && self.has_fields {
394             "\n"
395         } else {
396             ""
397         };
398         self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
399     }
400
401     fn is_pretty(&self) -> bool {
402         self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
403     }
404 }