use std::fmt::{self, Display, Write};
const INDENT: &str = " ";
fn subwriter<T: Display>(indent: &'static str, f: &mut fmt::Formatter, v: &T) -> fmt::Result {
if f.alternate() {
write!(indenter::indented(f).with_str(indent), "{:#}", v)
} else {
Display::fmt(v, f)
}
}
pub fn display_container<T: Display, Iter: ExactSizeIterator<Item = T>>(
f: &mut fmt::Formatter,
prefix: &str,
suffix: &str,
items: Iter,
) -> fmt::Result {
let (separator, outer, indent) = match (f.alternate(), items.len()) {
(false, _) => (", ", "", ""),
(true, 0) => ("", "", ""),
(true, 1) => ("", " ", ""),
_ => (",\n", "\n", INDENT),
};
f.write_str(prefix)?;
f.write_str(outer)?;
for (i, value) in items.into_iter().enumerate() {
if i != 0 {
f.write_str(separator)?;
}
subwriter(indent, f, &value)?;
}
f.write_str(outer)?;
f.write_str(suffix)
}
pub fn display_keyed_container<K: Display, V: Display, Iter: ExactSizeIterator<Item = (K, V)>>(
f: &mut fmt::Formatter,
prefix: &str,
suffix: &str,
separator: &str,
items: Iter,
) -> fmt::Result {
struct Wrapper<'a, K: Display, V: Display>(K, V, &'a str);
impl<'a, K: Display, V: Display> fmt::Display for Wrapper<'a, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)?;
f.write_str(self.2)?;
fmt::Display::fmt(&self.1, f)
}
}
display_container(
f,
prefix,
suffix,
items.map(|(k, v)| Wrapper(k, v, separator)),
)
}
#[cfg(test)]
mod tests {
use std::fmt;
use indexmap::{indexmap, IndexMap};
use indoc::indoc;
use super::*;
#[test]
fn test_container() {
struct Wrapped(Vec<u32>);
impl fmt::Display for Wrapped {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
display_container(f, "prefix[", "]", self.0.iter())
}
}
assert_eq!("prefix[]", format!("{:}", Wrapped(vec![])));
assert_eq!("prefix[1]", format!("{:}", Wrapped(vec![1])));
assert_eq!("prefix[1, 2]", format!("{:}", Wrapped(vec![1, 2])));
assert_eq!("prefix[1, 2, 3]", format!("{:}", Wrapped(vec![1, 2, 3])));
assert_eq!("prefix[]", format!("{:#}", Wrapped(vec![])));
assert_eq!("prefix[ 1 ]", format!("{:#}", Wrapped(vec![1])));
assert_eq!(
indoc!(
"prefix[
1,
2
]"
),
format!("{:#}", Wrapped(vec![1, 2])),
);
assert_eq!(
indoc!(
"prefix[
1,
2,
3
]"
),
format!("{:#}", Wrapped(vec![1, 2, 3])),
);
}
#[test]
fn test_keyed_container() {
struct Wrapped(IndexMap<u32, &'static str>);
impl fmt::Display for Wrapped {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
display_keyed_container(
f,
"prefix[",
"]",
": ",
self.0.iter().map(|(k, v)| (k, format!("\"{}\"", v))),
)
}
}
assert_eq!("prefix[]", format!("{:}", Wrapped(indexmap! {})));
assert_eq!(
"prefix[1: \"1\"]",
format!("{:}", Wrapped(indexmap! {1 => "1"}))
);
assert_eq!(
"prefix[1: \"1\", 2: \"2\"]",
format!("{:}", Wrapped(indexmap! {1 => "1", 2 => "2"})),
);
assert_eq!(
"prefix[1: \"1\", 2: \"2\", 3: \"3\"]",
format!("{:}", Wrapped(indexmap! {1 => "1", 2 => "2", 3 => "3"})),
);
assert_eq!("prefix[]", format!("{:#}", Wrapped(indexmap! {})));
assert_eq!(
"prefix[ 1: \"1\" ]",
format!("{:#}", Wrapped(indexmap! {1 => "1"}))
);
assert_eq!(
indoc!(
"prefix[
1: \"1\",
2: \"2\"
]"
),
format!("{:#}", Wrapped(indexmap! {1 => "1", 2 => "2"})),
);
assert_eq!(
indoc!(
"prefix[
1: \"1\",
2: \"2\",
3: \"3\"
]"
),
format!("{:#}", Wrapped(indexmap! {1 => "1", 2 => "2", 3 => "3"})),
);
}
}