use super::*;
pub(super) fn write(
mut buf: String,
node: Node,
fmts: &[Fmt],
col: usize,
inline_field_id: bool,
map: NamedIter,
) -> String {
let fmt = fmts.get(node.index()).unwrap();
let id = node.kserd().id();
let prefix = |mut buf| {
maybe_write_nonprim_ident(&mut buf, fmt.id, id);
buf.push('(');
buf
};
let suffix = |mut buf: String| {
buf.push(')');
buf
};
let write_node_with_field_mapping = |mut buf: String, name, value, col| {
let buf_lo = buf.len();
write!(buf, "{}{} ", name, FIELDS_ASSIGNER).ok();
let buf_hi = buf.len();
let name_indent = buf[buf_lo..buf_hi].chars().count();
let c = col + name_indent;
buf = write_node(buf, value, fmts, c); buf.push('\n');
buf
};
match fmt.line {
Repr::Inline => {
delim_writer(buf, prefix, suffix, |mut buf| {
let rm_trailing = !map.is_empty();
for (name, v) in map {
write!(buf, "{}{} ", name, FIELDS_ASSIGNER).ok();
buf = write_node(buf, v, fmts, col); buf.push_str(FIELDS_SEPARATOR);
}
if rm_trailing {
FIELDS_SEPARATOR.chars().for_each(|_| {
buf.pop();
});
}
buf
})
}
Repr::Concise => delim_writer(buf, prefix, suffix, |mut buf| {
buf.push('\n');
let c = col + INDENT;
for (name, v) in map {
write_indent(&mut buf, c);
buf = write_node_with_field_mapping(buf, name, v, c);
}
write_indent(&mut buf, col);
buf
}),
Repr::Verbose => {
if fmt.id && inline_field_id {
if let Some(id) = id {
write_indent(&mut buf, col);
buf.push(':');
buf.push_str(id);
buf.push('\n');
}
}
for (name, v) in map {
let vfmt = fmts.get(v.index()).unwrap();
let (vrepr, val) = (vfmt.line, v.value());
buf = match (vrepr, val) {
(Repr::Verbose, NodeValue::Cntr(map)) => {
buf.push('\n');
write_indent(&mut buf, col);
buf.push('[');
buf.push_str(name);
if vfmt.id {
if let Some(id) = v.kserd().id() {
buf.push(':');
buf.push_str(id);
}
}
buf.push_str("]\n");
cntr::write(buf, v, fmts, col + INDENT, false, map)
}
(Repr::Verbose, NodeValue::Seq(seq)) => {
buf.push('\n');
buf = seqs::write(buf, v, fmts, col, seq, Some(name));
buf.pop(); buf
}
(Repr::Verbose, NodeValue::Map(map)) => {
buf.push('\n');
maps::write(buf, v, fmts, col, map, Some(name))
}
_ => {
write_indent(&mut buf, col);
write_node_with_field_mapping(buf, name, v, col)
}
};
}
buf
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(clippy::all)]
fn cntr_fmting() {
let kserd = Kserd::with_id(
"Struct",
Value::new_cntr(vec![
("a", Kserd::new_num(101)),
(
"b",
Kserd::new(Value::Tuple(vec![Kserd::new_num(0), Kserd::new_num(10101)])),
),
(
"c",
Kserd::new(Value::Seq(vec![Kserd::new_num(111), Kserd::new_num(3.14)])),
),
])
.unwrap(),
)
.unwrap();
let mut config = FormattingConfig {
width_limit: None,
..Default::default()
};
let s = kserd.as_str_with_config(config);
println!("{}", s);
assert_eq!(&s, "Struct (a = 101, b = (0, 10101), c = [111, 3.14])");
config.width_limit = Some(20);
let s = kserd.as_str_with_config(config);
println!("{}", s);
assert_eq!(
&s,
"Struct (
a = 101
b = (0, 10101)
c = [111, 3.14]
)"
);
config.width_limit = Some(0);
let s = kserd.as_str_with_config(config);
println!("{}", s);
assert_eq!(
&s,
":Struct
a = 101
b = (
0
10101
)
[[c]]
111
[[c]]
3.14
"
);
}
#[test]
fn field_structs() {
let kserd =
Kserd::new_cntr(vec![("a", Kserd::new_num(1)), ("b", Kserd::new_num(2))]).unwrap();
let mut fmtr = Formatter::new(&kserd);
fmtr.verbose(0).unwrap();
fmtr.id(1, false).unwrap();
fmtr.id(2, false).unwrap();
let s = fmtr.write_string(String::new());
println!("{}", s);
assert_eq!(&s, "a = 1\nb = 2\n");
}
#[test]
fn nested_cntrs() {
let kserd = Kserd::new_cntr(vec![(
"un",
Kserd::new_cntr(vec![(
"dos",
Kserd::new_cntr(vec![(
"treis",
Kserd::new_cntr(vec![("quattro", Kserd::new_unit())]).unwrap(),
)])
.unwrap(),
)])
.unwrap(),
)])
.unwrap();
let s = kserd.as_str_with_config(FormattingConfig {
width_limit: Some(0),
..Default::default()
});
println!("{}", s);
assert_eq!(
&s,
"
[un]
[dos]
[treis]
quattro = ()
"
);
}
#[test]
fn empty_cntr() {
let kserd = Kserd::with_id(
"something",
Value::new_cntr(Vec::<(&str, _)>::new()).unwrap(),
)
.unwrap();
let mut fmtr = Formatter::new(&kserd);
fmtr.id(0, true).unwrap();
assert!(fmtr.verbose(0).is_err()); assert!(fmtr.concise(0).is_err());
fmtr.inline(0).unwrap(); assert_eq!(&fmtr.write_string(String::new()), "something ()");
fmtr.id(0, false).unwrap();
fmtr.inline(0).unwrap(); assert_eq!(&fmtr.write_string(String::new()), "()");
}
}