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