]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | #![allow(unused_imports)] |
2 | ||
3 | use crate::fmt::{self, Debug, Formatter}; | |
c34b1796 | 4 | |
416331ca XL |
5 | struct PadAdapter<'buf, 'state> { |
6 | buf: &'buf mut (dyn fmt::Write + 'buf), | |
7 | state: &'state mut PadAdapterState, | |
8 | } | |
9 | ||
10 | struct PadAdapterState { | |
c34b1796 AL |
11 | on_newline: bool, |
12 | } | |
13 | ||
416331ca XL |
14 | impl Default for PadAdapterState { |
15 | fn default() -> Self { | |
dfeec247 | 16 | PadAdapterState { on_newline: true } |
416331ca XL |
17 | } |
18 | } | |
19 | ||
20 | impl<'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 | 30 | impl 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 |
89 | pub struct DebugStruct<'a, 'b: 'a> { |
90 | fmt: &'a mut fmt::Formatter<'b>, | |
91 | result: fmt::Result, | |
92 | has_fields: bool, | |
93 | } | |
94 | ||
dfeec247 XL |
95 | pub(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 | ||
103 | impl<'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 |
278 | pub 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 |
285 | pub(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 | ||
293 | impl<'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 | ||
382 | struct DebugInner<'a, 'b: 'a> { | |
383 | fmt: &'a mut fmt::Formatter<'b>, | |
384 | result: fmt::Result, | |
385 | has_fields: bool, | |
386 | } | |
387 | ||
388 | impl<'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 |
444 | pub struct DebugSet<'a, 'b: 'a> { |
445 | inner: DebugInner<'a, 'b>, | |
446 | } | |
447 | ||
e1599b0c | 448 | pub(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 | ||
453 | impl<'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 |
574 | pub struct DebugList<'a, 'b: 'a> { |
575 | inner: DebugInner<'a, 'b>, | |
576 | } | |
577 | ||
e1599b0c | 578 | pub(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 | ||
583 | impl<'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 |
704 | pub 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 | 713 | pub(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 | ||
718 | impl<'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 | } |