]> git.proxmox.com Git - rustc.git/blame - library/core/src/fmt/builders.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / library / core / src / fmt / builders.rs
CommitLineData
29967ef6
XL
1#![allow(unused_imports)]
2
3use crate::fmt::{self, Debug, Formatter};
c34b1796 4
416331ca
XL
5struct PadAdapter<'buf, 'state> {
6 buf: &'buf mut (dyn fmt::Write + 'buf),
7 state: &'state mut PadAdapterState,
8}
9
10struct PadAdapterState {
c34b1796
AL
11 on_newline: bool,
12}
13
416331ca
XL
14impl Default for PadAdapterState {
15 fn default() -> Self {
dfeec247 16 PadAdapterState { on_newline: true }
416331ca
XL
17 }
18}
19
20impl<'buf, 'state> PadAdapter<'buf, 'state> {
dfeec247
XL
21 fn wrap<'slot, 'fmt: 'buf + 'slot>(
22 fmt: &'fmt mut fmt::Formatter<'_>,
23 slot: &'slot mut Option<Self>,
24 state: &'state mut PadAdapterState,
25 ) -> fmt::Formatter<'slot> {
94222f64 26 fmt.wrap_buf(move |buf| slot.insert(PadAdapter { buf, state }))
c34b1796
AL
27 }
28}
29
416331ca 30impl fmt::Write for PadAdapter<'_, '_> {
c34b1796
AL
31 fn write_str(&mut self, mut s: &str) -> fmt::Result {
32 while !s.is_empty() {
416331ca 33 if self.state.on_newline {
ff7c6d11 34 self.buf.write_str(" ")?;
c34b1796
AL
35 }
36
37 let split = match s.find('\n') {
38 Some(pos) => {
416331ca 39 self.state.on_newline = true;
c34b1796
AL
40 pos + 1
41 }
42 None => {
416331ca 43 self.state.on_newline = false;
c34b1796
AL
44 s.len()
45 }
46 };
ff7c6d11 47 self.buf.write_str(&s[..split])?;
c34b1796
AL
48 s = &s[split..];
49 }
50
51 Ok(())
52 }
53}
54
29967ef6 55/// A struct to help with [`fmt::Debug`](Debug) implementations.
c34b1796 56///
041b39d2 57/// This is useful when you wish to output a formatted struct as a part of your
29967ef6 58/// [`Debug::fmt`] implementation.
041b39d2 59///
29967ef6 60/// This can be constructed by the [`Formatter::debug_struct`] method.
041b39d2 61///
3b2f2976 62/// # Examples
041b39d2
XL
63///
64/// ```
65/// use std::fmt;
66///
67/// struct Foo {
68/// bar: i32,
69/// baz: String,
70/// }
71///
72/// impl fmt::Debug for Foo {
73/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
74/// fmt.debug_struct("Foo")
75/// .field("bar", &self.bar)
76/// .field("baz", &self.baz)
77/// .finish()
78/// }
79/// }
80///
9fa01778
XL
81/// assert_eq!(
82/// format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }),
83/// "Foo { bar: 10, baz: \"Hello World\" }",
84/// );
041b39d2 85/// ```
94b46f34 86#[must_use = "must eventually call `finish()` on Debug builders"]
54a0048b 87#[allow(missing_debug_implementations)]
62682a34 88#[stable(feature = "debug_builders", since = "1.2.0")]
c34b1796
AL
89pub struct DebugStruct<'a, 'b: 'a> {
90 fmt: &'a mut fmt::Formatter<'b>,
91 result: fmt::Result,
92 has_fields: bool,
93}
94
dfeec247
XL
95pub(super) fn debug_struct_new<'a, 'b>(
96 fmt: &'a mut fmt::Formatter<'b>,
97 name: &str,
98) -> DebugStruct<'a, 'b> {
c34b1796 99 let result = fmt.write_str(name);
dfeec247 100 DebugStruct { fmt, result, has_fields: false }
c34b1796
AL
101}
102
103impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
104 /// Adds a new field to the generated struct output.
9fa01778
XL
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use std::fmt;
110 ///
111 /// struct Bar {
112 /// bar: i32,
113 /// another: String,
114 /// }
115 ///
116 /// impl fmt::Debug for Bar {
117 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
118 /// fmt.debug_struct("Bar")
119 /// .field("bar", &self.bar) // We add `bar` field.
120 /// .field("another", &self.another) // We add `another` field.
121 /// // We even add a field which doesn't exist (because why not?).
122 /// .field("not_existing_field", &1)
123 /// .finish() // We're good to go!
124 /// }
125 /// }
126 ///
127 /// assert_eq!(
128 /// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }),
129 /// "Bar { bar: 10, another: \"Hello World\", not_existing_field: 1 }",
130 /// );
131 /// ```
62682a34 132 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247 133 pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self {
c34b1796 134 self.result = self.result.and_then(|_| {
c34b1796 135 if self.is_pretty() {
532ac7d7
XL
136 if !self.has_fields {
137 self.fmt.write_str(" {\n")?;
138 }
ff7c6d11 139 let mut slot = None;
416331ca 140 let mut state = Default::default();
ee023bcb 141 let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
ff7c6d11
XL
142 writer.write_str(name)?;
143 writer.write_str(": ")?;
532ac7d7
XL
144 value.fmt(&mut writer)?;
145 writer.write_str(",\n")
c34b1796 146 } else {
532ac7d7
XL
147 let prefix = if self.has_fields { ", " } else { " { " };
148 self.fmt.write_str(prefix)?;
149 self.fmt.write_str(name)?;
150 self.fmt.write_str(": ")?;
ff7c6d11 151 value.fmt(self.fmt)
c34b1796
AL
152 }
153 });
154
155 self.has_fields = true;
156 self
157 }
158
dfeec247
XL
159 /// Marks the struct as non-exhaustive, indicating to the reader that there are some other
160 /// fields that are not shown in the debug representation.
161 ///
162 /// # Examples
163 ///
164 /// ```
dfeec247
XL
165 /// use std::fmt;
166 ///
167 /// struct Bar {
168 /// bar: i32,
169 /// hidden: f32,
170 /// }
171 ///
172 /// impl fmt::Debug for Bar {
173 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
174 /// fmt.debug_struct("Bar")
175 /// .field("bar", &self.bar)
176 /// .finish_non_exhaustive() // Show that some other field(s) exist.
177 /// }
178 /// }
179 ///
180 /// assert_eq!(
181 /// format!("{:?}", Bar { bar: 10, hidden: 1.0 }),
182 /// "Bar { bar: 10, .. }",
183 /// );
184 /// ```
cdc7bbd5 185 #[stable(feature = "debug_non_exhaustive", since = "1.53.0")]
dfeec247
XL
186 pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
187 self.result = self.result.and_then(|_| {
cdc7bbd5
XL
188 if self.has_fields {
189 if self.is_pretty() {
190 let mut slot = None;
191 let mut state = Default::default();
ee023bcb 192 let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
cdc7bbd5
XL
193 writer.write_str("..\n")?;
194 self.fmt.write_str("}")
dfeec247 195 } else {
cdc7bbd5 196 self.fmt.write_str(", .. }")
dfeec247 197 }
dfeec247 198 } else {
cdc7bbd5 199 self.fmt.write_str(" { .. }")
dfeec247 200 }
dfeec247
XL
201 });
202 self.result
203 }
204
62682a34 205 /// Finishes output and returns any error encountered.
9fa01778
XL
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use std::fmt;
211 ///
212 /// struct Bar {
213 /// bar: i32,
214 /// baz: String,
215 /// }
216 ///
217 /// impl fmt::Debug for Bar {
218 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
219 /// fmt.debug_struct("Bar")
220 /// .field("bar", &self.bar)
221 /// .field("baz", &self.baz)
222 /// .finish() // You need to call it to "finish" the
223 /// // struct formatting.
224 /// }
225 /// }
226 ///
227 /// assert_eq!(
228 /// format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }),
229 /// "Bar { bar: 10, baz: \"Hello World\" }",
230 /// );
231 /// ```
62682a34
SL
232 #[stable(feature = "debug_builders", since = "1.2.0")]
233 pub fn finish(&mut self) -> fmt::Result {
c34b1796
AL
234 if self.has_fields {
235 self.result = self.result.and_then(|_| {
dfeec247 236 if self.is_pretty() { self.fmt.write_str("}") } else { self.fmt.write_str(" }") }
c34b1796
AL
237 });
238 }
239 self.result
240 }
241
242 fn is_pretty(&self) -> bool {
ea8adc8c 243 self.fmt.alternate()
c34b1796
AL
244 }
245}
246
29967ef6 247/// A struct to help with [`fmt::Debug`](Debug) implementations.
041b39d2
XL
248///
249/// This is useful when you wish to output a formatted tuple as a part of your
29967ef6 250/// [`Debug::fmt`] implementation.
041b39d2 251///
29967ef6 252/// This can be constructed by the [`Formatter::debug_tuple`] method.
c34b1796 253///
3b2f2976 254/// # Examples
041b39d2
XL
255///
256/// ```
257/// use std::fmt;
258///
259/// struct Foo(i32, String);
260///
261/// impl fmt::Debug for Foo {
262/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
263/// fmt.debug_tuple("Foo")
264/// .field(&self.0)
265/// .field(&self.1)
266/// .finish()
267/// }
268/// }
269///
9fa01778
XL
270/// assert_eq!(
271/// format!("{:?}", Foo(10, "Hello World".to_string())),
272/// "Foo(10, \"Hello World\")",
273/// );
041b39d2 274/// ```
94b46f34 275#[must_use = "must eventually call `finish()` on Debug builders"]
54a0048b 276#[allow(missing_debug_implementations)]
62682a34 277#[stable(feature = "debug_builders", since = "1.2.0")]
c34b1796
AL
278pub struct DebugTuple<'a, 'b: 'a> {
279 fmt: &'a mut fmt::Formatter<'b>,
280 result: fmt::Result,
54a0048b
SL
281 fields: usize,
282 empty_name: bool,
c34b1796
AL
283}
284
e1599b0c
XL
285pub(super) fn debug_tuple_new<'a, 'b>(
286 fmt: &'a mut fmt::Formatter<'b>,
287 name: &str,
288) -> DebugTuple<'a, 'b> {
c34b1796 289 let result = fmt.write_str(name);
dfeec247 290 DebugTuple { fmt, result, fields: 0, empty_name: name.is_empty() }
c34b1796
AL
291}
292
293impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
294 /// Adds a new field to the generated tuple struct output.
9fa01778
XL
295 ///
296 /// # Examples
297 ///
298 /// ```
299 /// use std::fmt;
300 ///
301 /// struct Foo(i32, String);
302 ///
303 /// impl fmt::Debug for Foo {
304 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
305 /// fmt.debug_tuple("Foo")
306 /// .field(&self.0) // We add the first field.
307 /// .field(&self.1) // We add the second field.
308 /// .finish() // We're good to go!
309 /// }
310 /// }
311 ///
312 /// assert_eq!(
313 /// format!("{:?}", Foo(10, "Hello World".to_string())),
314 /// "Foo(10, \"Hello World\")",
315 /// );
316 /// ```
62682a34 317 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247 318 pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
c34b1796 319 self.result = self.result.and_then(|_| {
c34b1796 320 if self.is_pretty() {
532ac7d7
XL
321 if self.fields == 0 {
322 self.fmt.write_str("(\n")?;
323 }
ff7c6d11 324 let mut slot = None;
416331ca 325 let mut state = Default::default();
ee023bcb 326 let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
532ac7d7
XL
327 value.fmt(&mut writer)?;
328 writer.write_str(",\n")
c34b1796 329 } else {
532ac7d7 330 let prefix = if self.fields == 0 { "(" } else { ", " };
ff7c6d11 331 self.fmt.write_str(prefix)?;
ff7c6d11 332 value.fmt(self.fmt)
c34b1796
AL
333 }
334 });
335
54a0048b 336 self.fields += 1;
c34b1796
AL
337 self
338 }
339
62682a34 340 /// Finishes output and returns any error encountered.
9fa01778
XL
341 ///
342 /// # Examples
343 ///
344 /// ```
345 /// use std::fmt;
346 ///
347 /// struct Foo(i32, String);
348 ///
349 /// impl fmt::Debug for Foo {
350 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
351 /// fmt.debug_tuple("Foo")
352 /// .field(&self.0)
353 /// .field(&self.1)
354 /// .finish() // You need to call it to "finish" the
355 /// // tuple formatting.
356 /// }
357 /// }
358 ///
359 /// assert_eq!(
360 /// format!("{:?}", Foo(10, "Hello World".to_string())),
361 /// "Foo(10, \"Hello World\")",
362 /// );
363 /// ```
62682a34
SL
364 #[stable(feature = "debug_builders", since = "1.2.0")]
365 pub fn finish(&mut self) -> fmt::Result {
54a0048b 366 if self.fields > 0 {
c34b1796 367 self.result = self.result.and_then(|_| {
532ac7d7 368 if self.fields == 1 && self.empty_name && !self.is_pretty() {
54a0048b 369 self.fmt.write_str(",")?;
c34b1796 370 }
54a0048b 371 self.fmt.write_str(")")
c34b1796
AL
372 });
373 }
374 self.result
375 }
376
377 fn is_pretty(&self) -> bool {
ea8adc8c 378 self.fmt.alternate()
c34b1796
AL
379 }
380}
381
382struct DebugInner<'a, 'b: 'a> {
383 fmt: &'a mut fmt::Formatter<'b>,
384 result: fmt::Result,
385 has_fields: bool,
386}
387
388impl<'a, 'b: 'a> DebugInner<'a, 'b> {
8faf50e0 389 fn entry(&mut self, entry: &dyn fmt::Debug) {
c34b1796
AL
390 self.result = self.result.and_then(|_| {
391 if self.is_pretty() {
532ac7d7
XL
392 if !self.has_fields {
393 self.fmt.write_str("\n")?;
394 }
ff7c6d11 395 let mut slot = None;
416331ca 396 let mut state = Default::default();
ee023bcb 397 let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
532ac7d7
XL
398 entry.fmt(&mut writer)?;
399 writer.write_str(",\n")
c34b1796 400 } else {
ff7c6d11
XL
401 if self.has_fields {
402 self.fmt.write_str(", ")?
403 }
404 entry.fmt(self.fmt)
c34b1796
AL
405 }
406 });
407
408 self.has_fields = true;
409 }
410
c34b1796 411 fn is_pretty(&self) -> bool {
ea8adc8c 412 self.fmt.alternate()
c34b1796
AL
413 }
414}
415
29967ef6 416/// A struct to help with [`fmt::Debug`](Debug) implementations.
041b39d2
XL
417///
418/// This is useful when you wish to output a formatted set of items as a part
29967ef6 419/// of your [`Debug::fmt`] implementation.
041b39d2 420///
29967ef6 421/// This can be constructed by the [`Formatter::debug_set`] method.
041b39d2 422///
3b2f2976 423/// # Examples
c34b1796 424///
041b39d2
XL
425/// ```
426/// use std::fmt;
427///
428/// struct Foo(Vec<i32>);
429///
430/// impl fmt::Debug for Foo {
431/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
432/// fmt.debug_set().entries(self.0.iter()).finish()
433/// }
434/// }
435///
9fa01778
XL
436/// assert_eq!(
437/// format!("{:?}", Foo(vec![10, 11])),
438/// "{10, 11}",
439/// );
041b39d2 440/// ```
94b46f34 441#[must_use = "must eventually call `finish()` on Debug builders"]
54a0048b 442#[allow(missing_debug_implementations)]
62682a34 443#[stable(feature = "debug_builders", since = "1.2.0")]
c34b1796
AL
444pub struct DebugSet<'a, 'b: 'a> {
445 inner: DebugInner<'a, 'b>,
446}
447
e1599b0c 448pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
532ac7d7 449 let result = fmt.write_str("{");
dfeec247 450 DebugSet { inner: DebugInner { fmt, result, has_fields: false } }
c34b1796
AL
451}
452
453impl<'a, 'b: 'a> DebugSet<'a, 'b> {
454 /// Adds a new entry to the set output.
9fa01778
XL
455 ///
456 /// # Examples
457 ///
458 /// ```
459 /// use std::fmt;
460 ///
461 /// struct Foo(Vec<i32>, Vec<u32>);
462 ///
463 /// impl fmt::Debug for Foo {
464 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
465 /// fmt.debug_set()
466 /// .entry(&self.0) // Adds the first "entry".
467 /// .entry(&self.1) // Adds the second "entry".
468 /// .finish()
469 /// }
470 /// }
471 ///
472 /// assert_eq!(
473 /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
474 /// "{[10, 11], [12, 13]}",
475 /// );
476 /// ```
62682a34 477 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247 478 pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
c34b1796
AL
479 self.inner.entry(entry);
480 self
481 }
482
62682a34 483 /// Adds the contents of an iterator of entries to the set output.
9fa01778
XL
484 ///
485 /// # Examples
486 ///
487 /// ```
488 /// use std::fmt;
489 ///
490 /// struct Foo(Vec<i32>, Vec<u32>);
491 ///
492 /// impl fmt::Debug for Foo {
493 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
494 /// fmt.debug_set()
495 /// .entries(self.0.iter()) // Adds the first "entry".
496 /// .entries(self.1.iter()) // Adds the second "entry".
497 /// .finish()
498 /// }
499 /// }
500 ///
501 /// assert_eq!(
502 /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
503 /// "{10, 11, 12, 13}",
504 /// );
505 /// ```
62682a34 506 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247
XL
507 pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
508 where
509 D: fmt::Debug,
510 I: IntoIterator<Item = D>,
b039eaaf 511 {
62682a34
SL
512 for entry in entries {
513 self.entry(&entry);
514 }
515 self
516 }
517
518 /// Finishes output and returns any error encountered.
9fa01778
XL
519 ///
520 /// # Examples
521 ///
522 /// ```
523 /// use std::fmt;
524 ///
525 /// struct Foo(Vec<i32>);
526 ///
527 /// impl fmt::Debug for Foo {
528 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
529 /// fmt.debug_set()
530 /// .entries(self.0.iter())
531 /// .finish() // Ends the struct formatting.
532 /// }
533 /// }
534 ///
535 /// assert_eq!(
536 /// format!("{:?}", Foo(vec![10, 11])),
537 /// "{10, 11}",
538 /// );
539 /// ```
62682a34
SL
540 #[stable(feature = "debug_builders", since = "1.2.0")]
541 pub fn finish(&mut self) -> fmt::Result {
c34b1796
AL
542 self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
543 }
544}
545
29967ef6 546/// A struct to help with [`fmt::Debug`](Debug) implementations.
041b39d2
XL
547///
548/// This is useful when you wish to output a formatted list of items as a part
29967ef6 549/// of your [`Debug::fmt`] implementation.
041b39d2 550///
29967ef6 551/// This can be constructed by the [`Formatter::debug_list`] method.
041b39d2 552///
3b2f2976 553/// # Examples
041b39d2
XL
554///
555/// ```
556/// use std::fmt;
557///
558/// struct Foo(Vec<i32>);
c34b1796 559///
041b39d2
XL
560/// impl fmt::Debug for Foo {
561/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
562/// fmt.debug_list().entries(self.0.iter()).finish()
563/// }
564/// }
565///
9fa01778
XL
566/// assert_eq!(
567/// format!("{:?}", Foo(vec![10, 11])),
568/// "[10, 11]",
569/// );
041b39d2 570/// ```
94b46f34 571#[must_use = "must eventually call `finish()` on Debug builders"]
54a0048b 572#[allow(missing_debug_implementations)]
62682a34 573#[stable(feature = "debug_builders", since = "1.2.0")]
c34b1796
AL
574pub struct DebugList<'a, 'b: 'a> {
575 inner: DebugInner<'a, 'b>,
576}
577
e1599b0c 578pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
532ac7d7 579 let result = fmt.write_str("[");
dfeec247 580 DebugList { inner: DebugInner { fmt, result, has_fields: false } }
c34b1796
AL
581}
582
583impl<'a, 'b: 'a> DebugList<'a, 'b> {
62682a34 584 /// Adds a new entry to the list output.
9fa01778
XL
585 ///
586 /// # Examples
587 ///
588 /// ```
589 /// use std::fmt;
590 ///
591 /// struct Foo(Vec<i32>, Vec<u32>);
592 ///
593 /// impl fmt::Debug for Foo {
594 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
595 /// fmt.debug_list()
596 /// .entry(&self.0) // We add the first "entry".
597 /// .entry(&self.1) // We add the second "entry".
598 /// .finish()
599 /// }
600 /// }
601 ///
602 /// assert_eq!(
603 /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
604 /// "[[10, 11], [12, 13]]",
605 /// );
606 /// ```
62682a34 607 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247 608 pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
c34b1796
AL
609 self.inner.entry(entry);
610 self
611 }
612
62682a34 613 /// Adds the contents of an iterator of entries to the list output.
9fa01778
XL
614 ///
615 /// # Examples
616 ///
617 /// ```
618 /// use std::fmt;
619 ///
620 /// struct Foo(Vec<i32>, Vec<u32>);
621 ///
622 /// impl fmt::Debug for Foo {
623 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
624 /// fmt.debug_list()
625 /// .entries(self.0.iter())
626 /// .entries(self.1.iter())
627 /// .finish()
628 /// }
629 /// }
630 ///
631 /// assert_eq!(
632 /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
633 /// "[10, 11, 12, 13]",
634 /// );
635 /// ```
62682a34 636 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247
XL
637 pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
638 where
639 D: fmt::Debug,
640 I: IntoIterator<Item = D>,
b039eaaf 641 {
62682a34
SL
642 for entry in entries {
643 self.entry(&entry);
644 }
645 self
646 }
647
648 /// Finishes output and returns any error encountered.
9fa01778
XL
649 ///
650 /// # Examples
651 ///
652 /// ```
653 /// use std::fmt;
654 ///
655 /// struct Foo(Vec<i32>);
656 ///
657 /// impl fmt::Debug for Foo {
658 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
659 /// fmt.debug_list()
660 /// .entries(self.0.iter())
661 /// .finish() // Ends the struct formatting.
662 /// }
663 /// }
664 ///
665 /// assert_eq!(
666 /// format!("{:?}", Foo(vec![10, 11])),
667 /// "[10, 11]",
668 /// );
669 /// ```
62682a34
SL
670 #[stable(feature = "debug_builders", since = "1.2.0")]
671 pub fn finish(&mut self) -> fmt::Result {
c34b1796
AL
672 self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
673 }
674}
675
29967ef6 676/// A struct to help with [`fmt::Debug`](Debug) implementations.
041b39d2
XL
677///
678/// This is useful when you wish to output a formatted map as a part of your
29967ef6 679/// [`Debug::fmt`] implementation.
041b39d2 680///
29967ef6 681/// This can be constructed by the [`Formatter::debug_map`] method.
041b39d2 682///
3b2f2976 683/// # Examples
041b39d2
XL
684///
685/// ```
686/// use std::fmt;
687///
688/// struct Foo(Vec<(String, i32)>);
689///
690/// impl fmt::Debug for Foo {
691/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
692/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()
693/// }
694/// }
c34b1796 695///
9fa01778
XL
696/// assert_eq!(
697/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
698/// "{\"A\": 10, \"B\": 11}",
699/// );
041b39d2 700/// ```
94b46f34 701#[must_use = "must eventually call `finish()` on Debug builders"]
54a0048b 702#[allow(missing_debug_implementations)]
62682a34 703#[stable(feature = "debug_builders", since = "1.2.0")]
c34b1796
AL
704pub struct DebugMap<'a, 'b: 'a> {
705 fmt: &'a mut fmt::Formatter<'b>,
706 result: fmt::Result,
707 has_fields: bool,
416331ca
XL
708 has_key: bool,
709 // The state of newlines is tracked between keys and values
710 state: PadAdapterState,
c34b1796
AL
711}
712
e1599b0c 713pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
532ac7d7 714 let result = fmt.write_str("{");
dfeec247 715 DebugMap { fmt, result, has_fields: false, has_key: false, state: Default::default() }
c34b1796
AL
716}
717
718impl<'a, 'b: 'a> DebugMap<'a, 'b> {
719 /// Adds a new entry to the map output.
9fa01778
XL
720 ///
721 /// # Examples
722 ///
723 /// ```
724 /// use std::fmt;
725 ///
726 /// struct Foo(Vec<(String, i32)>);
727 ///
728 /// impl fmt::Debug for Foo {
729 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
730 /// fmt.debug_map()
731 /// .entry(&"whole", &self.0) // We add the "whole" entry.
732 /// .finish()
733 /// }
734 /// }
735 ///
736 /// assert_eq!(
737 /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
738 /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
739 /// );
740 /// ```
62682a34 741 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247 742 pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut Self {
416331ca
XL
743 self.key(key).value(value)
744 }
745
746 /// Adds the key part of a new entry to the map output.
747 ///
748 /// This method, together with `value`, is an alternative to `entry` that
749 /// can be used when the complete entry isn't known upfront. Prefer the `entry`
750 /// method when it's possible to use.
751 ///
752 /// # Panics
753 ///
754 /// `key` must be called before `value` and each call to `key` must be followed
755 /// by a corresponding call to `value`. Otherwise this method will panic.
756 ///
757 /// # Examples
758 ///
759 /// ```
416331ca
XL
760 /// use std::fmt;
761 ///
762 /// struct Foo(Vec<(String, i32)>);
763 ///
764 /// impl fmt::Debug for Foo {
765 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
766 /// fmt.debug_map()
767 /// .key(&"whole").value(&self.0) // We add the "whole" entry.
768 /// .finish()
769 /// }
770 /// }
771 ///
772 /// assert_eq!(
773 /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
774 /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
775 /// );
776 /// ```
dfeec247
XL
777 #[stable(feature = "debug_map_key_value", since = "1.42.0")]
778 pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self {
c34b1796 779 self.result = self.result.and_then(|_| {
dfeec247
XL
780 assert!(
781 !self.has_key,
782 "attempted to begin a new map entry \
783 without completing the previous one"
784 );
e74abb32 785
c34b1796 786 if self.is_pretty() {
532ac7d7
XL
787 if !self.has_fields {
788 self.fmt.write_str("\n")?;
789 }
ff7c6d11 790 let mut slot = None;
416331ca 791 self.state = Default::default();
ee023bcb 792 let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
ff7c6d11
XL
793 key.fmt(&mut writer)?;
794 writer.write_str(": ")?;
c34b1796 795 } else {
ff7c6d11
XL
796 if self.has_fields {
797 self.fmt.write_str(", ")?
798 }
799 key.fmt(self.fmt)?;
800 self.fmt.write_str(": ")?;
c34b1796 801 }
416331ca
XL
802
803 self.has_key = true;
804 Ok(())
805 });
806
807 self
808 }
809
810 /// Adds the value part of a new entry to the map output.
811 ///
812 /// This method, together with `key`, is an alternative to `entry` that
813 /// can be used when the complete entry isn't known upfront. Prefer the `entry`
814 /// method when it's possible to use.
815 ///
816 /// # Panics
817 ///
818 /// `key` must be called before `value` and each call to `key` must be followed
819 /// by a corresponding call to `value`. Otherwise this method will panic.
820 ///
821 /// # Examples
822 ///
823 /// ```
416331ca
XL
824 /// use std::fmt;
825 ///
826 /// struct Foo(Vec<(String, i32)>);
827 ///
828 /// impl fmt::Debug for Foo {
829 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
830 /// fmt.debug_map()
831 /// .key(&"whole").value(&self.0) // We add the "whole" entry.
832 /// .finish()
833 /// }
834 /// }
835 ///
836 /// assert_eq!(
837 /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
838 /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
839 /// );
840 /// ```
dfeec247
XL
841 #[stable(feature = "debug_map_key_value", since = "1.42.0")]
842 pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self {
416331ca 843 self.result = self.result.and_then(|_| {
e74abb32
XL
844 assert!(self.has_key, "attempted to format a map value before its key");
845
416331ca
XL
846 if self.is_pretty() {
847 let mut slot = None;
ee023bcb 848 let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
416331ca
XL
849 value.fmt(&mut writer)?;
850 writer.write_str(",\n")?;
851 } else {
852 value.fmt(self.fmt)?;
853 }
854
855 self.has_key = false;
856 Ok(())
c34b1796
AL
857 });
858
859 self.has_fields = true;
860 self
861 }
862
62682a34 863 /// Adds the contents of an iterator of entries to the map output.
9fa01778
XL
864 ///
865 /// # Examples
866 ///
867 /// ```
868 /// use std::fmt;
869 ///
870 /// struct Foo(Vec<(String, i32)>);
871 ///
872 /// impl fmt::Debug for Foo {
873 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
874 /// fmt.debug_map()
875 /// // We map our vec so each entries' first field will become
876 /// // the "key".
877 /// .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
878 /// .finish()
879 /// }
880 /// }
881 ///
882 /// assert_eq!(
883 /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
884 /// "{\"A\": 10, \"B\": 11}",
885 /// );
886 /// ```
62682a34 887 #[stable(feature = "debug_builders", since = "1.2.0")]
dfeec247
XL
888 pub fn entries<K, V, I>(&mut self, entries: I) -> &mut Self
889 where
890 K: fmt::Debug,
891 V: fmt::Debug,
892 I: IntoIterator<Item = (K, V)>,
b039eaaf 893 {
62682a34
SL
894 for (k, v) in entries {
895 self.entry(&k, &v);
896 }
897 self
898 }
899
900 /// Finishes output and returns any error encountered.
9fa01778 901 ///
416331ca
XL
902 /// # Panics
903 ///
904 /// `key` must be called before `value` and each call to `key` must be followed
905 /// by a corresponding call to `value`. Otherwise this method will panic.
906 ///
9fa01778
XL
907 /// # Examples
908 ///
909 /// ```
910 /// use std::fmt;
911 ///
912 /// struct Foo(Vec<(String, i32)>);
913 ///
914 /// impl fmt::Debug for Foo {
915 /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
916 /// fmt.debug_map()
917 /// .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
918 /// .finish() // Ends the struct formatting.
919 /// }
920 /// }
921 ///
922 /// assert_eq!(
923 /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
924 /// "{\"A\": 10, \"B\": 11}",
925 /// );
926 /// ```
62682a34
SL
927 #[stable(feature = "debug_builders", since = "1.2.0")]
928 pub fn finish(&mut self) -> fmt::Result {
e74abb32
XL
929 self.result.and_then(|_| {
930 assert!(!self.has_key, "attempted to finish a map with a partial entry");
416331ca 931
e74abb32
XL
932 self.fmt.write_str("}")
933 })
c34b1796
AL
934 }
935
936 fn is_pretty(&self) -> bool {
ea8adc8c 937 self.fmt.alternate()
c34b1796
AL
938 }
939}