Skip to content

Instantly share code, notes, and snippets.

@sfackler
Created January 21, 2015 07:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfackler/6d6610c5d9e271146d11 to your computer and use it in GitHub Desktop.
Save sfackler/6d6610c5d9e271146d11 to your computer and use it in GitHub Desktop.
#![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