diff --git a/src/bson.rs b/src/bson.rs index 01ce1bb3..9c732c50 100644 --- a/src/bson.rs +++ b/src/bson.rs @@ -134,19 +134,48 @@ impl Display for Bson { Bson::Array(ref vec) => { fmt.write_str("[")?; + let indent = fmt.width().unwrap_or(2); + let indent_str = " ".repeat(indent); + let mut first = true; for bson in vec { if !first { fmt.write_str(", ")?; } - - write!(fmt, "{}", bson)?; + if fmt.alternate() { + write!(fmt, "\n{indent_str}")?; + match bson { + Bson::Array(_arr) => { + let new_indent = indent + 2; + write!(fmt, "{bson:#new_indent$}")?; + } + Bson::Document(ref doc) => { + let new_indent = indent + 2; + write!(fmt, "{doc:#new_indent$}")?; + } + _ => { + write!(fmt, "{}", bson)?; + } + } + } else { + write!(fmt, "{}", bson)?; + } first = false; } - - fmt.write_str("]") + if fmt.alternate() && !vec.is_empty() { + let closing_bracket_indent_str = " ".repeat(indent - 2); + write!(fmt, "\n{closing_bracket_indent_str}]") + } else { + fmt.write_str("]") + } + } + Bson::Document(ref doc) => { + if fmt.alternate() { + write!(fmt, "{doc:#}") + } else { + write!(fmt, "{doc}") + } } - Bson::Document(ref doc) => write!(fmt, "{}", doc), Bson::Boolean(b) => write!(fmt, "{}", b), Bson::Null => write!(fmt, "null"), Bson::RegularExpression(ref x) => write!(fmt, "{}", x), diff --git a/src/document.rs b/src/document.rs index 3a5f189f..18b57851 100644 --- a/src/document.rs +++ b/src/document.rs @@ -80,21 +80,54 @@ impl Hash for Document { impl Display for Document { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - fmt.write_str("{")?; + let indent = fmt.width().unwrap_or(2); + let indent_str = " ".repeat(indent); + + write!(fmt, "{{")?; + if fmt.alternate() && !self.inner.is_empty() { + fmt.write_str("\n")?; + } let mut first = true; for (k, v) in self { - if first { - first = false; - fmt.write_str(" ")?; - } else { - fmt.write_str(", ")?; + if !fmt.alternate() { + if first { + first = false; + write!(fmt, " ")?; + } else { + fmt.write_str(", ")?; + } + write!(fmt, "\"{}\": {}", k, v)?; } - write!(fmt, "\"{}\": {}", k, v)?; + if fmt.alternate() { + if first { + first = false; + } else { + fmt.write_str(",\n")?; + } + match v { + Bson::Document(ref doc) => { + let new_indent = indent + 2; + write!(fmt, "{indent_str}\"{}\": {doc:#new_indent$}", k)?; + } + Bson::Array(_arr) => { + let new_indent = indent + 2; + write!(fmt, "{indent_str}\"{}\": {v:#new_indent$}", k)?; + } + _ => { + write!(fmt, "{indent_str}\"{}\": {}", k, v)?; + } + } + } } - write!(fmt, "{}}}", if !first { " " } else { "" }) + let closing_bracket_indent_str = " ".repeat(indent - 2); + if fmt.alternate() && !self.inner.is_empty() { + write!(fmt, "\n{closing_bracket_indent_str}}}") + } else { + write!(fmt, "{}}}", if !first { " " } else { "" }) + } } } diff --git a/src/tests/modules/document.rs b/src/tests/modules/document.rs index 85fc62ff..e8be3199 100644 --- a/src/tests/modules/document.rs +++ b/src/tests/modules/document.rs @@ -245,3 +245,128 @@ fn extend() { }, ); } + +#[test] +fn test_display_empty_doc() { + let empty_expectation = "{}"; + let doc = doc! {}; + let doc_display = format!("{doc}"); + assert_eq!(empty_expectation, doc_display); + + let doc_display_pretty = format!("{doc:#}"); + assert_eq!(empty_expectation, doc_display_pretty); +} + +#[test] +fn test_display_doc() { + let doc = doc! { + "hello": "world" + }; + + let doc_display_expectation = "{ \"hello\": \"world\" }"; + assert_eq!(doc_display_expectation, format!("{doc}")); + + let doc_display_pretty_expectation = r#"{ + "hello": "world" +}"#; + assert_eq!(doc_display_pretty_expectation, format!("{doc:#}")); +} + +#[test] +fn test_display_nested_doc() { + let doc = doc! { + "hello": { + "hello": 2 + } + }; + + let doc_display_expectation = "{ \"hello\": { \"hello\": 2 } }"; + assert_eq!(doc_display_expectation, format!("{doc}")); + + let doc_display_pretty_expectation = r#"{ + "hello": { + "hello": 2 + } +}"#; + let formatted = format!("{doc:#}"); + assert_eq!(doc_display_pretty_expectation, formatted); +} + +#[test] +fn test_display_doc_with_array() { + let doc = doc! { + "hello": [1, 2, 3] + }; + + let doc_display_expectation = "{ \"hello\": [1, 2, 3] }"; + assert_eq!(doc_display_expectation, format!("{doc}")); + + let doc_display_pretty_expectation = r#"{ + "hello": [ + 1, + 2, + 3 + ] +}"#; + let formatted = format!("{doc:#}"); + assert_eq!(doc_display_pretty_expectation, formatted); + + let nested_array_doc = doc! { + "a": [1, [1, 2]] + }; + + let expectation = r#"{ + "a": [ + 1, + [ + 1, + 2 + ] + ] +}"#; + assert_eq!(expectation, format!("{nested_array_doc:#}")); +} + +#[test] +fn test_pretty_printing() { + let d = doc! { "hello": "world!", "world": "hello", "key": "val" }; + let expected = r#"{ "hello": "world!", "world": "hello", "key": "val" }"#; + let formatted = format!("{d}"); + assert_eq!( + expected, formatted, + "expected:\n{expected}\ngot:\n{formatted}" + ); + + let d = doc! { "hello": "world!", "nested": { "key": "val", "double": { "a": "thing" } } }; + let expected = r#"{ + "hello": "world!", + "nested": { + "key": "val", + "double": { + "a": "thing" + } + } +}"#; + let formatted = format!("{d:#}"); + assert_eq!( + expected, formatted, + "expected:\n{expected}\ngot:\n{formatted}" + ); + + let d = + doc! { "hello": "world!", "nested": { "key": "val", "double": { "a": [1, 2], "c": "d"} } }; + let expected = r#"{ + "hello": "world!", + "nested": { + "key": "val", + "double": { + "a": [ + 1, + 2 + ], + "c": "d" + } + } +}"#; + assert_eq!(expected, format!("{d:#}")); +}