]>
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> { | |
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 | 33 | impl 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 |
92 | pub struct DebugStruct<'a, 'b: 'a> { |
93 | fmt: &'a mut fmt::Formatter<'b>, | |
94 | result: fmt::Result, | |
95 | has_fields: bool, | |
96 | } | |
97 | ||
dfeec247 XL |
98 | pub(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 | ||
106 | impl<'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 |
281 | pub 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 |
288 | pub(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 | ||
296 | impl<'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 | ||
385 | struct DebugInner<'a, 'b: 'a> { | |
386 | fmt: &'a mut fmt::Formatter<'b>, | |
387 | result: fmt::Result, | |
388 | has_fields: bool, | |
389 | } | |
390 | ||
391 | impl<'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 |
447 | pub struct DebugSet<'a, 'b: 'a> { |
448 | inner: DebugInner<'a, 'b>, | |
449 | } | |
450 | ||
e1599b0c | 451 | pub(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 | ||
456 | impl<'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 |
577 | pub struct DebugList<'a, 'b: 'a> { |
578 | inner: DebugInner<'a, 'b>, | |
579 | } | |
580 | ||
e1599b0c | 581 | pub(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 | ||
586 | impl<'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 |
707 | pub 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 | 716 | pub(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 | ||
721 | impl<'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 | } |