use crate::__private::SerializeExpectOp;
use crate::internals::pretty_formatter::PrettyDisplay;
use serde_json::Map;
use serde_json::Value;
use std::fmt::Arguments;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;
use std::ops::Deref;
use std::ops::DerefMut;
const INDENTATION_SIZE: usize = 4;
pub struct PrettyFormatter<'a, 'b> {
indentation: usize,
formatter: &'a mut Formatter<'b>,
}
impl<'a, 'b> PrettyFormatter<'a, 'b> {
pub fn new(formatter: &'a mut Formatter<'b>) -> Self {
Self {
indentation: INDENTATION_SIZE,
formatter,
}
}
pub fn write_fmt(&mut self, arguments: Arguments<'_>) -> FmtResult {
self.formatter.write_fmt(arguments)
}
pub fn write_fmt_array<V>(&mut self, items: &[V]) -> FmtResult
where
V: PrettyDisplay,
{
write!(self.formatter, "[")?;
for (i, item) in items.iter().enumerate() {
if item.is_indenting() {
self.increment_indentation();
if i == 0 {
self.write_indentation()?;
} else {
for _ in 0..INDENTATION_SIZE {
write!(self.formatter, " ")?;
}
}
}
item.pretty_fmt(self)?;
if i < items.len() - 1 {
write!(self.formatter, ",")?;
if items.get(i + 1).is_some_and(|v| !v.is_indenting()) {
write!(self.formatter, " ")?;
}
}
if item.is_indenting() {
self.decrement_indentation();
self.write_indentation()?;
}
}
write!(self.formatter, "]")?;
Ok(())
}
pub fn write_fmt_object(&mut self, object: &Map<String, Value>) -> FmtResult {
if let Some(expect_op) = SerializeExpectOp::maybe_parse_from_obj(object) {
return write!(self.formatter, "expect::{}()", expect_op.name());
}
write!(self.formatter, "{{")?;
self.increment_indentation();
let mut is_empty = true;
for (i, (key, value)) in object.iter().enumerate() {
is_empty = false;
if i > 0 {
write!(self.formatter, ",")?;
}
self.write_indentation()?;
write!(self.formatter, r#""{key}": "#)?;
value.pretty_fmt(self)?;
}
self.decrement_indentation();
if !is_empty {
self.write_indentation()?;
}
write!(self.formatter, "}}")?;
Ok(())
}
pub fn increment_indentation(&mut self) {
self.indentation += INDENTATION_SIZE;
}
pub fn decrement_indentation(&mut self) {
self.indentation -= INDENTATION_SIZE;
}
pub fn write_indentation(&mut self) -> FmtResult {
writeln!(self.formatter)?;
for _ in 0..self.indentation {
write!(self.formatter, " ")?;
}
Ok(())
}
}
impl<'b> Deref for PrettyFormatter<'_, 'b> {
type Target = Formatter<'b>;
fn deref(&self) -> &Self::Target {
self.formatter
}
}
impl DerefMut for PrettyFormatter<'_, '_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.formatter
}
}
#[cfg(test)]
mod test_write_fmt_object {
use crate::expect;
use crate::internals::objects::ValueObject;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn it_should_format_object_with_one_key_value_pair() {
let object = ValueObject::from(json!({ "key": "value" }));
let output = format!("{object}");
assert_eq!(
output,
r#"{
"key": "value"
}"#
);
}
#[test]
fn it_should_format_object_holding_an_expect_operation() {
let object = ValueObject::from(json!({ "key": expect::string().contains("aaa") }));
let output = format!("{object}");
assert_eq!(
output,
r#"{
"key": expect::string()
}"#
);
}
}