use std::collections::BTreeMap; use eyre::{bail, Context}; use serde::Serialize; use serde_json::{Map, Value}; #[derive(Default)] pub struct Output { elements: BTreeMap<&'static str, Value>, } impl Output { pub fn write(&mut self, key: &'static str, v: &impl Serialize) -> eyre::Result<()> { let v = serde_json::to_value(v).wrap_err("failed to serialize output")?; if self.elements.insert(key, v).is_some() { bail!("duplicated output key {key:?}"); } Ok(()) } pub fn write_append(&mut self, key: &'static str, v: &impl Serialize) -> eyre::Result<()> { let Value::Object(mut v) = serde_json::to_value(v).wrap_err("failed to serialize output")? else { bail!("tried to append non-object"); }; let Value::Object(entry) = self.elements.entry(key).or_insert(Map::new().into()) else { bail!("tried to append to non-object"); }; entry.append(&mut v); Ok(()) } } impl Drop for Output { fn drop(&mut self) { let out = serde_json::to_string_pretty(&self.elements).expect("can serialize output as json"); println!("{out}",); } }