Skip to content

Commit

Permalink
Update debug helpers and add list builder
Browse files Browse the repository at this point in the history
The collections debug helpers no longer prefix output with the
collection name, in line with the current conventions for Debug
implementations. Implementations that want to preserve the current
behavior can simply add a `try!(write!(fmt, "TypeName "));` at the
beginning of the `fmt` method.

[breaking-change]
  • Loading branch information
sfackler committed Mar 28, 2015
1 parent 3e7385a commit 4037f2a
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 129 deletions.
11 changes: 4 additions & 7 deletions src/libcollections/btree/map.rs
Expand Up @@ -904,14 +904,11 @@ impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));

for (i, (k, v)) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{:?}: {:?}", *k, *v));
let mut builder = f.debug_map();
for (k, v) in self {
builder = builder.entry(k, v);
}

write!(f, "}}")
builder.finish()
}
}

Expand Down
11 changes: 4 additions & 7 deletions src/libcollections/btree/set.rs
Expand Up @@ -628,14 +628,11 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Debug> Debug for BTreeSet<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));

for (i, x) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{:?}", *x));
let mut builder = f.debug_set();
for x in self {
builder = builder.entry(x);
}

write!(f, "}}")
builder.finish()
}
}

Expand Down
1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Expand Up @@ -40,6 +40,7 @@
#![feature(str_char)]
#![feature(convert)]
#![feature(slice_patterns)]
#![feature(debug_builders)]
#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))]
#![cfg_attr(test, allow(deprecated))] // rand

Expand Down
11 changes: 4 additions & 7 deletions src/libcollections/linked_list.rs
Expand Up @@ -927,14 +927,11 @@ impl<A: Clone> Clone for LinkedList<A> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "["));

for (i, e) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{:?}", *e));
let mut builder = f.debug_list();
for e in self {
builder = builder.entry(e);
}

write!(f, "]")
builder.finish()
}
}

Expand Down
138 changes: 85 additions & 53 deletions src/libcore/fmt/builders.rs
Expand Up @@ -177,64 +177,107 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
}
}

struct DebugInner<'a, 'b: 'a> {
fmt: &'a mut fmt::Formatter<'b>,
result: fmt::Result,
has_fields: bool,
}

impl<'a, 'b: 'a> DebugInner<'a, 'b> {
fn entry(&mut self, entry: &fmt::Debug) {
self.result = self.result.and_then(|_| {
if self.is_pretty() {
let mut writer = PadAdapter::new(self.fmt);
let prefix = if self.has_fields { "," } else { "" };
fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
} else {
let prefix = if self.has_fields { ", " } else { "" };
write!(self.fmt, "{}{:?}", prefix, entry)
}
});

self.has_fields = true;
}

pub fn finish(&mut self) {
let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" };
self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
}

fn is_pretty(&self) -> bool {
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
}
}

/// A struct to help with `fmt::Debug` implementations.
///
/// Constructed by the `Formatter::debug_set` method.
#[must_use]
pub struct DebugSet<'a, 'b: 'a> {
fmt: &'a mut fmt::Formatter<'b>,
result: fmt::Result,
has_fields: bool,
inner: DebugInner<'a, 'b>,
}

pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugSet<'a, 'b> {
let result = write!(fmt, "{} {{", name);
pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
let result = write!(fmt, "{{");
DebugSet {
fmt: fmt,
result: result,
has_fields: false,
inner: DebugInner {
fmt: fmt,
result: result,
has_fields: false,
}
}
}

impl<'a, 'b: 'a> DebugSet<'a, 'b> {
/// Adds a new entry to the set output.
#[unstable(feature = "debug_builders", reason = "method was just created")]
pub fn entry(mut self, entry: &fmt::Debug) -> DebugSet<'a, 'b> {
self.result = self.result.and_then(|_| {
let prefix = if self.has_fields {
","
} else {
""
};

if self.is_pretty() {
let mut writer = PadAdapter::new(self.fmt);
fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
} else {
write!(self.fmt, "{} {:?}", prefix, entry)
}
});

self.has_fields = true;
self.inner.entry(entry);
self
}

/// Consumes the `DebugSet`, finishing output and returning any error
/// encountered.
#[unstable(feature = "debug_builders", reason = "method was just created")]
pub fn finish(self) -> fmt::Result {
self.result.and_then(|_| {
let end = match (self.has_fields, self.is_pretty()) {
(false, _) => "}",
(true, false) => " }",
(true, true) => "\n}",
};
self.fmt.write_str(end)
})
pub fn finish(mut self) -> fmt::Result {
self.inner.finish();
self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
}
}

fn is_pretty(&self) -> bool {
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
/// A struct to help with `fmt::Debug` implementations.
///
/// Constructed by the `Formatter::debug_list` method.
#[must_use]
pub struct DebugList<'a, 'b: 'a> {
inner: DebugInner<'a, 'b>,
}

pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
let result = write!(fmt, "[");
DebugList {
inner: DebugInner {
fmt: fmt,
result: result,
has_fields: false,
}
}
}

impl<'a, 'b: 'a> DebugList<'a, 'b> {
/// Adds a new entry to the set output.
#[unstable(feature = "debug_builders", reason = "method was just created")]
pub fn entry(mut self, entry: &fmt::Debug) -> DebugList<'a, 'b> {
self.inner.entry(entry);
self
}

/// Consumes the `DebugSet`, finishing output and returning any error
/// encountered.
#[unstable(feature = "debug_builders", reason = "method was just created")]
pub fn finish(mut self) -> fmt::Result {
self.inner.finish();
self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
}
}

Expand All @@ -248,8 +291,8 @@ pub struct DebugMap<'a, 'b: 'a> {
has_fields: bool,
}

pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugMap<'a, 'b> {
let result = write!(fmt, "{} {{", name);
pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
let result = write!(fmt, "{{");
DebugMap {
fmt: fmt,
result: result,
Expand All @@ -262,37 +305,26 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
#[unstable(feature = "debug_builders", reason = "method was just created")]
pub fn entry(mut self, key: &fmt::Debug, value: &fmt::Debug) -> DebugMap<'a, 'b> {
self.result = self.result.and_then(|_| {
let prefix = if self.has_fields {
","
} else {
""
};

if self.is_pretty() {
let mut writer = PadAdapter::new(self.fmt);
let prefix = if self.has_fields { "," } else { "" };
fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
} else {
write!(self.fmt, "{} {:?}: {:?}", prefix, key, value)
let prefix = if self.has_fields { ", " } else { "" };
write!(self.fmt, "{}{:?}: {:?}", prefix, key, value)
}
});

self.has_fields = true;

self
}

/// Consumes the `DebugMap`, finishing output and returning any error
/// encountered.
#[unstable(feature = "debug_builders", reason = "method was just created")]
pub fn finish(self) -> fmt::Result {
self.result.and_then(|_| {
let end = match (self.has_fields, self.is_pretty()) {
(false, _) => "}",
(true, false) => " }",
(true, true) => "\n}",
};
self.fmt.write_str(end)
})
let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" };
self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
}

fn is_pretty(&self) -> bool {
Expand Down
52 changes: 41 additions & 11 deletions src/libcore/fmt/mod.rs
Expand Up @@ -32,7 +32,7 @@ pub use self::num::radix;
pub use self::num::Radix;
pub use self::num::RadixFmt;

pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugMap};
pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap};

mod num;
mod float;
Expand Down Expand Up @@ -644,7 +644,7 @@ impl<'a> Formatter<'a> {
/// // prints "Foo { bar: 10, baz: "Hello World" }"
/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
/// ```
#[unstable(feature = "core", reason = "method was just created")]
#[unstable(feature = "debug_builders", reason = "method was just created")]
#[inline]
pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {
builders::debug_struct_new(self, name)
Expand Down Expand Up @@ -673,12 +673,42 @@ impl<'a> Formatter<'a> {
/// // prints "Foo(10, "Hello World")"
/// println!("{:?}", Foo(10, "Hello World".to_string()));
/// ```
#[unstable(feature = "core", reason = "method was just created")]
#[unstable(feature = "debug_builders", reason = "method was just created")]
#[inline]
pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {
builders::debug_tuple_new(self, name)
}

/// Creates a `DebugList` builder designed to assist with creation of
/// `fmt::Debug` implementations for list-like structures.
///
/// # Examples
///
/// ```rust
/// # #![feature(debug_builders, core)]
/// use std::fmt;
///
/// struct Foo(Vec<i32>);
///
/// impl fmt::Debug for Foo {
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
/// let mut builder = fmt.debug_list();
/// for i in &self.0 {
/// builder = builder.entry(i);
/// }
/// builder.finish()
/// }
/// }
///
/// // prints "Foo { 10, 11 }"
/// println!("{:?}", Foo(vec![10, 11]));
/// ```
#[unstable(feature = "debug_builders", reason = "method was just created")]
#[inline]
pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> {
builders::debug_list_new(self)
}

/// Creates a `DebugSet` builder designed to assist with creation of
/// `fmt::Debug` implementations for set-like structures.
///
Expand All @@ -692,7 +722,7 @@ impl<'a> Formatter<'a> {
///
/// impl fmt::Debug for Foo {
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
/// let mut builder = fmt.debug_set("Foo");
/// let mut builder = fmt.debug_set();
/// for i in &self.0 {
/// builder = builder.entry(i);
/// }
Expand All @@ -703,10 +733,10 @@ impl<'a> Formatter<'a> {
/// // prints "Foo { 10, 11 }"
/// println!("{:?}", Foo(vec![10, 11]));
/// ```
#[unstable(feature = "core", reason = "method was just created")]
#[unstable(feature = "debug_builders", reason = "method was just created")]
#[inline]
pub fn debug_set<'b>(&'b mut self, name: &str) -> DebugSet<'b, 'a> {
builders::debug_set_new(self, name)
pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> {
builders::debug_set_new(self)
}

/// Creates a `DebugMap` builder designed to assist with creation of
Expand All @@ -722,7 +752,7 @@ impl<'a> Formatter<'a> {
///
/// impl fmt::Debug for Foo {
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
/// let mut builder = fmt.debug_map("Foo");
/// let mut builder = fmt.debug_map();
/// for &(ref key, ref value) in &self.0 {
/// builder = builder.entry(key, value);
/// }
Expand All @@ -733,10 +763,10 @@ impl<'a> Formatter<'a> {
/// // prints "Foo { "A": 10, "B": 11 }"
/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)]));
/// ```
#[unstable(feature = "core", reason = "method was just created")]
#[unstable(feature = "debug_builders", reason = "method was just created")]
#[inline]
pub fn debug_map<'b>(&'b mut self, name: &str) -> DebugMap<'b, 'a> {
builders::debug_map_new(self, name)
pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> {
builders::debug_map_new(self)
}
}

Expand Down

0 comments on commit 4037f2a

Please sign in to comment.