Created
January 21, 2015 07:58
-
-
Save sfackler/6d6610c5d9e271146d11 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(unstable)] | |
use std::fmt; | |
use std::fmt::rt::Flag; | |
struct PadAdapter<'a, 'b: 'a> { | |
fmt: &'a mut fmt::Formatter<'b>, | |
on_newline: bool, | |
} | |
impl<'a, 'b: 'a> PadAdapter<'a, 'b> { | |
fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> { | |
PadAdapter { | |
fmt: fmt, | |
on_newline: false, | |
} | |
} | |
} | |
impl<'a, 'b: 'a> fmt::Writer for PadAdapter<'a, 'b> { | |
fn write_str(&mut self, mut s: &str) -> fmt::Result { | |
while !s.is_empty() { | |
if self.on_newline { | |
try!(self.fmt.write_str(" ")); | |
} | |
let split = match s.find('\n') { | |
Some(pos) => { | |
self.on_newline = true; | |
pos + 1 | |
} | |
None => { | |
self.on_newline = false; | |
s.len() | |
} | |
}; | |
try!(self.fmt.write_str(&s[..split])); | |
s = &s[split..]; | |
} | |
Ok(()) | |
} | |
} | |
#[must_use] | |
pub struct ShowStruct<'a, 'b: 'a> { | |
fmt: &'a mut fmt::Formatter<'b>, | |
result: fmt::Result, | |
has_fields: bool, | |
} | |
impl<'a, 'b: 'a> ShowStruct<'a, 'b> { | |
pub fn new(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> ShowStruct<'a, 'b> { | |
let result = fmt.write_str(name); | |
ShowStruct { | |
fmt: fmt, | |
result: result, | |
has_fields: false, | |
} | |
} | |
pub fn field<S>(mut self, name: &str, value: &S) -> ShowStruct<'a, 'b> | |
where S: fmt::Show { | |
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, name, value)) | |
} else { | |
write!(self.fmt, "{} {}: {:?}", prefix, name, value) | |
} | |
}); | |
self.has_fields = true; | |
self | |
} | |
pub fn finish(mut self) -> fmt::Result { | |
if self.has_fields { | |
self.result = self.result.and_then(|_| { | |
if self.is_pretty() { | |
self.fmt.write_str("\n}") | |
} else { | |
self.fmt.write_str(" }") | |
} | |
}); | |
} | |
self.result | |
} | |
fn is_pretty(&self) -> bool { | |
self.fmt.flags() & (1 << (Flag::FlagAlternate as usize)) != 0 | |
} | |
} | |
#[must_use] | |
pub struct ShowTuple<'a, 'b: 'a> { | |
fmt: &'a mut fmt::Formatter<'b>, | |
result: fmt::Result, | |
has_fields: bool, | |
} | |
impl<'a, 'b: 'a> ShowTuple<'a, 'b> { | |
pub fn new(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> ShowTuple<'a, 'b> { | |
let result = fmt.write_str(name); | |
ShowTuple { | |
fmt: fmt, | |
result: result, | |
has_fields: false, | |
} | |
} | |
pub fn field<S>(mut self, value: &S) -> ShowTuple<'a, 'b> where S: fmt::Show { | |
self.result = self.result.and_then(|_| { | |
let (prefix, space) = if self.has_fields { | |
(",", " ") | |
} else { | |
("(", "") | |
}; | |
if self.is_pretty() { | |
let mut writer = PadAdapter::new(self.fmt); | |
fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, value)) | |
} else { | |
write!(self.fmt, "{}{}{:?}", prefix, space, value) | |
} | |
}); | |
self.has_fields = true; | |
self | |
} | |
pub fn finish(mut self) -> fmt::Result { | |
if self.has_fields { | |
self.result = self.result.and_then(|_| { | |
if self.is_pretty() { | |
self.fmt.write_str("\n)") | |
} else { | |
self.fmt.write_str(")") | |
} | |
}); | |
} | |
self.result | |
} | |
fn is_pretty(&self) -> bool { | |
self.fmt.flags() & (1 << (Flag::FlagAlternate as usize)) != 0 | |
} | |
} | |
#[must_use] | |
pub struct ShowSet<'a, 'b: 'a> { | |
fmt: &'a mut fmt::Formatter<'b>, | |
result: fmt::Result, | |
has_fields: bool, | |
} | |
impl<'a, 'b: 'a> ShowSet<'a, 'b> { | |
pub fn new(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> ShowSet<'a, 'b> { | |
let result = write!(fmt, "{} {{", name); | |
ShowSet { | |
fmt: fmt, | |
result: result, | |
has_fields: false, | |
} | |
} | |
pub fn entry<S>(mut self, entry: &S) -> ShowSet<'a, 'b> where S: fmt::Show { | |
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 | |
} | |
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) | |
}) | |
} | |
fn is_pretty(&self) -> bool { | |
self.fmt.flags() & (1 << (Flag::FlagAlternate as usize)) != 0 | |
} | |
} | |
#[must_use] | |
pub struct ShowMap<'a, 'b: 'a> { | |
fmt: &'a mut fmt::Formatter<'b>, | |
result: fmt::Result, | |
has_fields: bool, | |
} | |
impl<'a, 'b: 'a> ShowMap<'a, 'b> { | |
pub fn new(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> ShowMap<'a, 'b> { | |
let result = write!(fmt, "{} {{", name); | |
ShowMap { | |
fmt: fmt, | |
result: result, | |
has_fields: false, | |
} | |
} | |
pub fn entry<K, V>(mut self, key: &K, value: &V) -> ShowMap<'a, 'b> | |
where K: fmt::Show, V: fmt::Show { | |
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, key, value)) | |
} else { | |
write!(self.fmt, "{} {:?}: {:?}", prefix, key, value) | |
} | |
}); | |
self.has_fields = true; | |
self | |
} | |
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) | |
}) | |
} | |
fn is_pretty(&self) -> bool { | |
self.fmt.flags() & (1 << (Flag::FlagAlternate as usize)) != 0 | |
} | |
} | |
#[cfg(test)] | |
mod show_struct { | |
use std::fmt; | |
use super::ShowStruct; | |
#[test] | |
fn test_empty() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowStruct::new(fmt, "Foo").finish() | |
} | |
} | |
assert_eq!("Foo", format!("{:?}", Foo)); | |
assert_eq!("Foo", format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_single() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowStruct::new(fmt, "Foo") | |
.field("bar", &true) | |
.finish() | |
} | |
} | |
assert_eq!("Foo { bar: true }", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo { | |
bar: true | |
}", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_multiple() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowStruct::new(fmt, "Foo") | |
.field("bar", &true) | |
.field("baz", &format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo { | |
bar: true, | |
baz: 10/20 | |
}", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_nested() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowStruct::new(fmt, "Foo") | |
.field("bar", &true) | |
.field("baz", &format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
struct Bar; | |
impl fmt::Show for Bar { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowStruct::new(fmt, "Bar") | |
.field("foo", &Foo) | |
.field("hello", &"world") | |
.finish() | |
} | |
} | |
assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }", | |
format!("{:?}", Bar)); | |
assert_eq!( | |
"Bar { | |
foo: Foo { | |
bar: true, | |
baz: 10/20 | |
}, | |
hello: \"world\" | |
}", | |
format!("{:#?}", Bar)); | |
} | |
} | |
#[cfg(test)] | |
mod show_tuple { | |
use std::fmt; | |
use super::ShowTuple; | |
#[test] | |
fn test_empty() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowTuple::new(fmt, "Foo").finish() | |
} | |
} | |
assert_eq!("Foo", format!("{:?}", Foo)); | |
assert_eq!("Foo", format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_single() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowTuple::new(fmt, "Foo") | |
.field(&true) | |
.finish() | |
} | |
} | |
assert_eq!("Foo(true)", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo( | |
true | |
)", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_multiple() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowTuple::new(fmt, "Foo") | |
.field(&true) | |
.field(&format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo( | |
true, | |
10/20 | |
)", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_nested() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowTuple::new(fmt, "Foo") | |
.field(&true) | |
.field(&format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
struct Bar; | |
impl fmt::Show for Bar { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowTuple::new(fmt, "Bar") | |
.field(&Foo) | |
.field(&"world") | |
.finish() | |
} | |
} | |
assert_eq!("Bar(Foo(true, 10/20), \"world\")", | |
format!("{:?}", Bar)); | |
assert_eq!( | |
"Bar( | |
Foo( | |
true, | |
10/20 | |
), | |
\"world\" | |
)", | |
format!("{:#?}", Bar)); | |
} | |
} | |
#[cfg(test)] | |
mod show_map { | |
use std::fmt; | |
use super::ShowMap; | |
#[test] | |
fn test_empty() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowMap::new(fmt, "Foo").finish() | |
} | |
} | |
assert_eq!("Foo {}", format!("{:?}", Foo)); | |
assert_eq!("Foo {}", format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_single() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowMap::new(fmt, "Foo") | |
.entry(&"bar", &true) | |
.finish() | |
} | |
} | |
assert_eq!("Foo { \"bar\": true }", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo { | |
\"bar\": true | |
}", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_multiple() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowMap::new(fmt, "Foo") | |
.entry(&"bar", &true) | |
.entry(&10i32, &format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
assert_eq!("Foo { \"bar\": true, 10i32: 10/20 }", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo { | |
\"bar\": true, | |
10i32: 10/20 | |
}", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_nested() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowMap::new(fmt, "Foo") | |
.entry(&"bar", &true) | |
.entry(&10i32, &format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
struct Bar; | |
impl fmt::Show for Bar { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowMap::new(fmt, "Bar") | |
.entry(&"foo", &Foo) | |
.entry(&Foo, &"world") | |
.finish() | |
} | |
} | |
assert_eq!("Bar { \"foo\": Foo { \"bar\": true, 10i32: 10/20 }, \ | |
Foo { \"bar\": true, 10i32: 10/20 }: \"world\" }", | |
format!("{:?}", Bar)); | |
assert_eq!( | |
"Bar { | |
\"foo\": Foo { | |
\"bar\": true, | |
10i32: 10/20 | |
}, | |
Foo { | |
\"bar\": true, | |
10i32: 10/20 | |
}: \"world\" | |
}", | |
format!("{:#?}", Bar)); | |
} | |
} | |
#[cfg(test)] | |
mod show_set { | |
use std::fmt; | |
use super::ShowSet; | |
#[test] | |
fn test_empty() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowSet::new(fmt, "Foo").finish() | |
} | |
} | |
assert_eq!("Foo {}", format!("{:?}", Foo)); | |
assert_eq!("Foo {}", format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_single() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowSet::new(fmt, "Foo") | |
.entry(&true) | |
.finish() | |
} | |
} | |
assert_eq!("Foo { true }", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo { | |
true | |
}", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_multiple() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowSet::new(fmt, "Foo") | |
.entry(&true) | |
.entry(&format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
assert_eq!("Foo { true, 10/20 }", format!("{:?}", Foo)); | |
assert_eq!( | |
"Foo { | |
true, | |
10/20 | |
}", | |
format!("{:#?}", Foo)); | |
} | |
#[test] | |
fn test_nested() { | |
struct Foo; | |
impl fmt::Show for Foo { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowSet::new(fmt, "Foo") | |
.entry(&true) | |
.entry(&format_args!("{}/{}", 10i32, 20i32)) | |
.finish() | |
} | |
} | |
struct Bar; | |
impl fmt::Show for Bar { | |
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
ShowSet::new(fmt, "Bar") | |
.entry(&Foo) | |
.entry(&"world") | |
.finish() | |
} | |
} | |
assert_eq!("Bar { Foo { true, 10/20 }, \"world\" }", | |
format!("{:?}", Bar)); | |
assert_eq!( | |
"Bar { | |
Foo { | |
true, | |
10/20 | |
}, | |
\"world\" | |
}", | |
format!("{:#?}", Bar)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment