Skip to content

Update debug helpers and use it for stdlib collections #23810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -904,14 +904,7 @@ 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));
}

write!(f, "}}")
self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish()
}
}

Expand Down
9 changes: 1 addition & 8 deletions src/libcollections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,14 +628,7 @@ 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));
}

write!(f, "}}")
self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish()
}
}

Expand Down
1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
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
9 changes: 1 addition & 8 deletions src/libcollections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,14 +927,7 @@ 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));
}

write!(f, "]")
self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish()
}
}

Expand Down
138 changes: 85 additions & 53 deletions src/libcore/fmt/builders.rs
Original file line number Diff line number Diff line change
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
77 changes: 40 additions & 37 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
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,38 @@ 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 {
/// self.0.iter().fold(fmt.debug_list(), |b, e| b.entry(e)).finish()
/// }
/// }
///
/// // prints "[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,21 +718,17 @@ 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");
/// for i in &self.0 {
/// builder = builder.entry(i);
/// }
/// builder.finish()
/// self.0.iter().fold(fmt.debug_set(), |b, e| b.entry(e)).finish()
/// }
/// }
///
/// // prints "Foo { 10, 11 }"
/// // prints "{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,21 +744,17 @@ 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");
/// for &(ref key, ref value) in &self.0 {
/// builder = builder.entry(key, value);
/// }
/// builder.finish()
/// self.0.iter().fold(fmt.debug_map(), |b, &(ref k, ref v)| b.entry(k, v)).finish()
/// }
/// }
///
/// // prints "Foo { "A": 10, "B": 11 }"
/// // prints "{"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 Expand Up @@ -987,22 +1005,7 @@ impl<'a> Debug for &'a (any::Any+'a) {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Debug> Debug for [T] {
fn fmt(&self, f: &mut Formatter) -> Result {
if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
try!(write!(f, "["));
}
let mut is_first = true;
for x in self {
if is_first {
is_first = false;
} else {
try!(write!(f, ", "));
}
try!(write!(f, "{:?}", *x))
}
if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
try!(write!(f, "]"));
}
Ok(())
self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish()
}
}

Expand Down
Loading