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