1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
use crate::{Debug, Formatter, INDENT};
/// A struct to help with [`Debug`](Debug) implementations.
///
/// This is useful when you wish to output a formatted tuple as a part of your
/// [`Debug::fmt`] implementation.
///
/// This can be constructed by the [`Formatter::debug_tuple`] method.
///
/// # Examples
///
/// ```
/// use debug3::{Debug, Formatter};
///
/// struct Foo(i32, String);
///
/// impl Debug for Foo {
/// fn fmt(&self, fmt: &mut Formatter) {
/// fmt.debug_tuple("Foo")
/// .field(&self.0)
/// .field(&self.1)
/// .finish()
/// }
/// }
///
/// assert_eq!(
/// debug3::pprint(Foo(10, "Hello World".to_string())),
/// "Foo(10, \"Hello World\")",
/// );
/// ```
#[must_use = "must eventually call `finish()` on Debug builders"]
pub struct DebugTuple<'a> {
fmt: &'a mut Formatter,
fields: usize,
empty_name: bool,
}
pub(crate) fn new<'a>(fmt: &'a mut Formatter, name: &str) -> DebugTuple<'a> {
// fmt.write_str(name);
fmt.word_s(name);
DebugTuple {
fmt,
fields: 0,
empty_name: name.is_empty(),
}
}
impl<'a> DebugTuple<'a> {
/// Adds a new field to the generated tuple struct output.
///
/// # Examples
///
/// ```
/// use debug3::{Debug, Formatter};
///
/// struct Foo(i32, String);
///
/// impl Debug for Foo {
/// fn fmt(&self, fmt: &mut Formatter) {
/// fmt.debug_tuple("Foo")
/// .field(&self.0) // We add the first field.
/// .field(&self.1) // We add the second field.
/// .finish() // We're good to go!
/// }
/// }
///
/// assert_eq!(
/// debug3::pprint(Foo(10, "Hello World".to_string())),
/// "Foo(10, \"Hello World\")",
/// );
/// ```
pub fn field(&mut self, value: &dyn Debug) -> &mut Self {
if self.fields == 0 {
self.fmt.word("(");
self.fmt.cbox(INDENT);
self.fmt.zerobreak();
} else {
self.fmt.trailing_comma(false);
}
value.fmt(self.fmt);
self.fields += 1;
self
}
/// Finishes output and returns any error encountered.
///
/// # Examples
///
/// ```
/// use debug3::{Debug, Formatter};
///
/// struct Foo(i32, String);
///
/// impl Debug for Foo {
/// fn fmt(&self, fmt: &mut Formatter) {
/// fmt.debug_tuple("Foo")
/// .field(&self.0)
/// .field(&self.1)
/// .finish() // You need to call it to "finish" the
/// // tuple formatting.
/// }
/// }
///
/// assert_eq!(
/// debug3::pprint(Foo(10, "Hello World".to_string())),
/// "Foo(10, \"Hello World\")",
/// );
/// ```
pub fn finish(&mut self) {
if self.fields > 0 {
// Handle Closing Comma for tuple of 1,
if self.fields == 1 && self.empty_name {
self.fmt.word(",");
self.fmt.zerobreak();
} else {
self.fmt.trailing_comma(true);
}
self.fmt.offset(-INDENT);
self.fmt.end();
self.fmt.word(")");
} else if self.empty_name {
self.fmt.word("()");
}
}
}