]> git.lizzy.rs Git - rust.git/blob - src/libcore/fmt/builders.rs
Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix
[rust.git] / src / libcore / fmt / builders.rs
1 use fmt;
2
3 struct PadAdapter<'a> {
4     buf: &'a mut (dyn fmt::Write + 'a),
5     on_newline: bool,
6 }
7
8 impl<'a> PadAdapter<'a> {
9     fn wrap<'b, 'c: 'a+'b>(fmt: &'c mut fmt::Formatter, slot: &'b mut Option<Self>)
10                         -> fmt::Formatter<'b> {
11         fmt.wrap_buf(move |buf| {
12             *slot = Some(PadAdapter {
13                 buf,
14                 on_newline: false,
15             });
16             slot.as_mut().unwrap()
17         })
18     }
19 }
20
21 impl fmt::Write for PadAdapter<'_> {
22     fn write_str(&mut self, mut s: &str) -> fmt::Result {
23         while !s.is_empty() {
24             if self.on_newline {
25                 self.buf.write_str("    ")?;
26             }
27
28             let split = match s.find('\n') {
29                 Some(pos) => {
30                     self.on_newline = true;
31                     pos + 1
32                 }
33                 None => {
34                     self.on_newline = false;
35                     s.len()
36                 }
37             };
38             self.buf.write_str(&s[..split])?;
39             s = &s[split..];
40         }
41
42         Ok(())
43     }
44 }
45
46 /// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
47 ///
48 /// This is useful when you wish to output a formatted struct as a part of your
49 /// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
50 ///
51 /// This can be constructed by the
52 /// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
53 /// method.
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use std::fmt;
59 ///
60 /// struct Foo {
61 ///     bar: i32,
62 ///     baz: String,
63 /// }
64 ///
65 /// impl fmt::Debug for Foo {
66 ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
67 ///         fmt.debug_struct("Foo")
68 ///            .field("bar", &self.bar)
69 ///            .field("baz", &self.baz)
70 ///            .finish()
71 ///     }
72 /// }
73 ///
74 /// // prints "Foo { bar: 10, baz: "Hello World" }"
75 /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
76 /// ```
77 #[must_use = "must eventually call `finish()` on Debug builders"]
78 #[allow(missing_debug_implementations)]
79 #[stable(feature = "debug_builders", since = "1.2.0")]
80 pub struct DebugStruct<'a, 'b: 'a> {
81     fmt: &'a mut fmt::Formatter<'b>,
82     result: fmt::Result,
83     has_fields: bool,
84 }
85
86 pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
87                                 name: &str)
88                                 -> DebugStruct<'a, 'b> {
89     let result = fmt.write_str(name);
90     DebugStruct {
91         fmt,
92         result,
93         has_fields: false,
94     }
95 }
96
97 impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
98     /// Adds a new field to the generated struct output.
99     #[stable(feature = "debug_builders", since = "1.2.0")]
100     pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut DebugStruct<'a, 'b> {
101         self.result = self.result.and_then(|_| {
102             let prefix = if self.has_fields {
103                 ","
104             } else {
105                 " {"
106             };
107
108             if self.is_pretty() {
109                 let mut slot = None;
110                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
111                 writer.write_str(prefix)?;
112                 writer.write_str("\n")?;
113                 writer.write_str(name)?;
114                 writer.write_str(": ")?;
115                 value.fmt(&mut writer)
116             } else {
117                 write!(self.fmt, "{} {}: ", prefix, name)?;
118                 value.fmt(self.fmt)
119             }
120         });
121
122         self.has_fields = true;
123         self
124     }
125
126     /// Finishes output and returns any error encountered.
127     #[stable(feature = "debug_builders", since = "1.2.0")]
128     pub fn finish(&mut self) -> fmt::Result {
129         if self.has_fields {
130             self.result = self.result.and_then(|_| {
131                 if self.is_pretty() {
132                     self.fmt.write_str("\n}")
133                 } else {
134                     self.fmt.write_str(" }")
135                 }
136             });
137         }
138         self.result
139     }
140
141     fn is_pretty(&self) -> bool {
142         self.fmt.alternate()
143     }
144 }
145
146 /// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
147 ///
148 /// This is useful when you wish to output a formatted tuple as a part of your
149 /// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
150 ///
151 /// This can be constructed by the
152 /// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
153 /// method.
154 ///
155 /// # Examples
156 ///
157 /// ```
158 /// use std::fmt;
159 ///
160 /// struct Foo(i32, String);
161 ///
162 /// impl fmt::Debug for Foo {
163 ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
164 ///         fmt.debug_tuple("Foo")
165 ///            .field(&self.0)
166 ///            .field(&self.1)
167 ///            .finish()
168 ///     }
169 /// }
170 ///
171 /// // prints "Foo(10, "Hello World")"
172 /// println!("{:?}", Foo(10, "Hello World".to_string()));
173 /// ```
174 #[must_use = "must eventually call `finish()` on Debug builders"]
175 #[allow(missing_debug_implementations)]
176 #[stable(feature = "debug_builders", since = "1.2.0")]
177 pub struct DebugTuple<'a, 'b: 'a> {
178     fmt: &'a mut fmt::Formatter<'b>,
179     result: fmt::Result,
180     fields: usize,
181     empty_name: bool,
182 }
183
184 pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
185     let result = fmt.write_str(name);
186     DebugTuple {
187         fmt,
188         result,
189         fields: 0,
190         empty_name: name.is_empty(),
191     }
192 }
193
194 impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
195     /// Adds a new field to the generated tuple struct output.
196     #[stable(feature = "debug_builders", since = "1.2.0")]
197     pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut DebugTuple<'a, 'b> {
198         self.result = self.result.and_then(|_| {
199             let (prefix, space) = if self.fields > 0 {
200                 (",", " ")
201             } else {
202                 ("(", "")
203             };
204
205             if self.is_pretty() {
206                 let mut slot = None;
207                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
208                 writer.write_str(prefix)?;
209                 writer.write_str("\n")?;
210                 value.fmt(&mut writer)
211             } else {
212                 self.fmt.write_str(prefix)?;
213                 self.fmt.write_str(space)?;
214                 value.fmt(self.fmt)
215             }
216         });
217
218         self.fields += 1;
219         self
220     }
221
222     /// Finishes output and returns any error encountered.
223     #[stable(feature = "debug_builders", since = "1.2.0")]
224     pub fn finish(&mut self) -> fmt::Result {
225         if self.fields > 0 {
226             self.result = self.result.and_then(|_| {
227                 if self.is_pretty() {
228                     self.fmt.write_str("\n")?;
229                 }
230                 if self.fields == 1 && self.empty_name {
231                     self.fmt.write_str(",")?;
232                 }
233                 self.fmt.write_str(")")
234             });
235         }
236         self.result
237     }
238
239     fn is_pretty(&self) -> bool {
240         self.fmt.alternate()
241     }
242 }
243
244 struct DebugInner<'a, 'b: 'a> {
245     fmt: &'a mut fmt::Formatter<'b>,
246     result: fmt::Result,
247     has_fields: bool,
248 }
249
250 impl<'a, 'b: 'a> DebugInner<'a, 'b> {
251     fn entry(&mut self, entry: &dyn fmt::Debug) {
252         self.result = self.result.and_then(|_| {
253             if self.is_pretty() {
254                 let mut slot = None;
255                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
256                 writer.write_str(if self.has_fields {
257                     ",\n"
258                 } else {
259                     "\n"
260                 })?;
261                 entry.fmt(&mut writer)
262             } else {
263                 if self.has_fields {
264                     self.fmt.write_str(", ")?
265                 }
266                 entry.fmt(self.fmt)
267             }
268         });
269
270         self.has_fields = true;
271     }
272
273     pub fn finish(&mut self) {
274         let prefix = if self.is_pretty() && self.has_fields {
275             "\n"
276         } else {
277             ""
278         };
279         self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
280     }
281
282     fn is_pretty(&self) -> bool {
283         self.fmt.alternate()
284     }
285 }
286
287 /// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
288 ///
289 /// This is useful when you wish to output a formatted set of items as a part
290 /// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
291 ///
292 /// This can be constructed by the
293 /// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
294 /// method.
295 ///
296 /// # Examples
297 ///
298 /// ```
299 /// use std::fmt;
300 ///
301 /// struct Foo(Vec<i32>);
302 ///
303 /// impl fmt::Debug for Foo {
304 ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
305 ///         fmt.debug_set().entries(self.0.iter()).finish()
306 ///     }
307 /// }
308 ///
309 /// // prints "{10, 11}"
310 /// println!("{:?}", Foo(vec![10, 11]));
311 /// ```
312 #[must_use = "must eventually call `finish()` on Debug builders"]
313 #[allow(missing_debug_implementations)]
314 #[stable(feature = "debug_builders", since = "1.2.0")]
315 pub struct DebugSet<'a, 'b: 'a> {
316     inner: DebugInner<'a, 'b>,
317 }
318
319 pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
320     let result = write!(fmt, "{{");
321     DebugSet {
322         inner: DebugInner {
323             fmt,
324             result,
325             has_fields: false,
326         },
327     }
328 }
329
330 impl<'a, 'b: 'a> DebugSet<'a, 'b> {
331     /// Adds a new entry to the set output.
332     #[stable(feature = "debug_builders", since = "1.2.0")]
333     pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugSet<'a, 'b> {
334         self.inner.entry(entry);
335         self
336     }
337
338     /// Adds the contents of an iterator of entries to the set output.
339     #[stable(feature = "debug_builders", since = "1.2.0")]
340     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugSet<'a, 'b>
341         where D: fmt::Debug,
342               I: IntoIterator<Item = D>
343     {
344         for entry in entries {
345             self.entry(&entry);
346         }
347         self
348     }
349
350     /// Finishes output and returns any error encountered.
351     #[stable(feature = "debug_builders", since = "1.2.0")]
352     pub fn finish(&mut self) -> fmt::Result {
353         self.inner.finish();
354         self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
355     }
356 }
357
358 /// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
359 ///
360 /// This is useful when you wish to output a formatted list of items as a part
361 /// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
362 ///
363 /// This can be constructed by the
364 /// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
365 /// method.
366 ///
367 /// # Examples
368 ///
369 /// ```
370 /// use std::fmt;
371 ///
372 /// struct Foo(Vec<i32>);
373 ///
374 /// impl fmt::Debug for Foo {
375 ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
376 ///         fmt.debug_list().entries(self.0.iter()).finish()
377 ///     }
378 /// }
379 ///
380 /// // prints "[10, 11]"
381 /// println!("{:?}", Foo(vec![10, 11]));
382 /// ```
383 #[must_use = "must eventually call `finish()` on Debug builders"]
384 #[allow(missing_debug_implementations)]
385 #[stable(feature = "debug_builders", since = "1.2.0")]
386 pub struct DebugList<'a, 'b: 'a> {
387     inner: DebugInner<'a, 'b>,
388 }
389
390 pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
391     let result = write!(fmt, "[");
392     DebugList {
393         inner: DebugInner {
394             fmt,
395             result,
396             has_fields: false,
397         },
398     }
399 }
400
401 impl<'a, 'b: 'a> DebugList<'a, 'b> {
402     /// Adds a new entry to the list output.
403     #[stable(feature = "debug_builders", since = "1.2.0")]
404     pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugList<'a, 'b> {
405         self.inner.entry(entry);
406         self
407     }
408
409     /// Adds the contents of an iterator of entries to the list output.
410     #[stable(feature = "debug_builders", since = "1.2.0")]
411     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugList<'a, 'b>
412         where D: fmt::Debug,
413               I: IntoIterator<Item = D>
414     {
415         for entry in entries {
416             self.entry(&entry);
417         }
418         self
419     }
420
421     /// Finishes output and returns any error encountered.
422     #[stable(feature = "debug_builders", since = "1.2.0")]
423     pub fn finish(&mut self) -> fmt::Result {
424         self.inner.finish();
425         self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
426     }
427 }
428
429 /// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
430 ///
431 /// This is useful when you wish to output a formatted map as a part of your
432 /// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
433 ///
434 /// This can be constructed by the
435 /// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
436 /// method.
437 ///
438 /// # Examples
439 ///
440 /// ```
441 /// use std::fmt;
442 ///
443 /// struct Foo(Vec<(String, i32)>);
444 ///
445 /// impl fmt::Debug for Foo {
446 ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
447 ///         fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()
448 ///     }
449 /// }
450 ///
451 /// // prints "{"A": 10, "B": 11}"
452 /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)]));
453 /// ```
454 #[must_use = "must eventually call `finish()` on Debug builders"]
455 #[allow(missing_debug_implementations)]
456 #[stable(feature = "debug_builders", since = "1.2.0")]
457 pub struct DebugMap<'a, 'b: 'a> {
458     fmt: &'a mut fmt::Formatter<'b>,
459     result: fmt::Result,
460     has_fields: bool,
461 }
462
463 pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
464     let result = write!(fmt, "{{");
465     DebugMap {
466         fmt,
467         result,
468         has_fields: false,
469     }
470 }
471
472 impl<'a, 'b: 'a> DebugMap<'a, 'b> {
473     /// Adds a new entry to the map output.
474     #[stable(feature = "debug_builders", since = "1.2.0")]
475     pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
476         self.result = self.result.and_then(|_| {
477             if self.is_pretty() {
478                 let mut slot = None;
479                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
480                 writer.write_str(if self.has_fields {
481                     ",\n"
482                 } else {
483                     "\n"
484                 })?;
485                 key.fmt(&mut writer)?;
486                 writer.write_str(": ")?;
487                 value.fmt(&mut writer)
488             } else {
489                 if self.has_fields {
490                     self.fmt.write_str(", ")?
491                 }
492                 key.fmt(self.fmt)?;
493                 self.fmt.write_str(": ")?;
494                 value.fmt(self.fmt)
495             }
496         });
497
498         self.has_fields = true;
499         self
500     }
501
502     /// Adds the contents of an iterator of entries to the map output.
503     #[stable(feature = "debug_builders", since = "1.2.0")]
504     pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
505         where K: fmt::Debug,
506               V: fmt::Debug,
507               I: IntoIterator<Item = (K, V)>
508     {
509         for (k, v) in entries {
510             self.entry(&k, &v);
511         }
512         self
513     }
514
515     /// Finishes output and returns any error encountered.
516     #[stable(feature = "debug_builders", since = "1.2.0")]
517     pub fn finish(&mut self) -> fmt::Result {
518         let prefix = if self.is_pretty() && self.has_fields {
519             "\n"
520         } else {
521             ""
522         };
523         self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
524     }
525
526     fn is_pretty(&self) -> bool {
527         self.fmt.alternate()
528     }
529 }