use std::fmt::{self, Display, Formatter};
use amplify::hex::ToHex;
use super::StrictVal;
use crate::value::EnumTag;
impl StrictVal {
fn needs_braces(&self) -> bool {
matches!(
self,
StrictVal::Number(_) | StrictVal::String(_) | StrictVal::Enum(_) | StrictVal::Union(..)
)
}
}
impl Display for StrictVal {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
StrictVal::Unit => f.write_str("()"),
StrictVal::Number(n) => Display::fmt(n, f),
StrictVal::String(s) => write!(f, r#""{s}""#),
StrictVal::Bytes(blob) => write!(f, "0x{}", blob.to_hex()),
StrictVal::Tuple(fields) => {
let mut iter = fields.iter();
let last = iter.next_back();
f.write_str("(")?;
for field in iter {
Display::fmt(field, f)?;
f.write_str(", ")?;
}
if let Some(field) = last {
Display::fmt(field, f)?;
}
f.write_str(")")
}
StrictVal::Struct(fields) => {
let mut iter = fields.iter();
let last = iter.next_back();
f.write_str("(")?;
for (fname, fval) in iter {
write!(f, "{fname}=")?;
Display::fmt(fval, f)?;
f.write_str(", ")?;
}
if let Some((fname, fval)) = last {
write!(f, "{fname}=")?;
Display::fmt(fval, f)?;
}
f.write_str(")")
}
StrictVal::Enum(tag) => Display::fmt(tag, f),
StrictVal::Union(tag, val)
if (*tag == EnumTag::Ord(0) || *tag == EnumTag::Name(vname!("none")))
&& **val == StrictVal::Unit =>
{
f.write_str("~")
}
StrictVal::Union(tag, val) => {
Display::fmt(tag, f)?;
if val.needs_braces() {
f.write_str("(")?;
}
Display::fmt(val, f)?;
if val.needs_braces() {
f.write_str("(")?;
}
Ok(())
}
StrictVal::List(items) => {
let mut iter = items.iter();
let last = iter.next_back();
f.write_str("[")?;
for item in iter {
Display::fmt(item, f)?;
f.write_str(", ")?;
}
if let Some(item) = last {
Display::fmt(item, f)?;
}
f.write_str("]")
}
StrictVal::Set(items) => {
let mut iter = items.iter();
let last = iter.next_back();
f.write_str("{")?;
for item in iter {
Display::fmt(item, f)?;
f.write_str(", ")?;
}
if let Some(item) = last {
Display::fmt(item, f)?;
}
f.write_str("}")
}
StrictVal::Map(items) => {
let mut iter = items.iter();
let last = iter.next_back();
f.write_str("{")?;
for (fname, fval) in iter {
write!(f, "{fname} -> ")?;
Display::fmt(fval, f)?;
f.write_str(", ")?;
}
if let Some((fname, fval)) = last {
write!(f, "{fname} -> ")?;
Display::fmt(fval, f)?;
}
f.write_str("}")
}
}
}
}
#[cfg(test)]
mod test {
#[test]
fn serialize() {
let strct = svstruct!(name => "Some name", ticker => "TICK", precision => svenum!(8));
assert_eq!(format!("{strct}"), r#"(name="Some name", ticker="TICK", precision=8)"#)
}
}