use std::io;
use cbor2::de::Deserializer;
use cbor2::value::Value as CborValue;
use anyhow::Context;
pub fn export_from_reader<R: io::Read, W: io::Write>(
format: &str,
delimiter: &str,
pretty: bool,
reader: R,
writer: &mut W,
) -> anyhow::Result<()> {
let mut first = true;
for v in Deserializer::from_reader(reader).into_iter::<CborValue>() {
let v = v?;
if !first {
writer.write_all(delimiter.as_bytes())?;
}
first = false;
if format == "json" {
if pretty {
serde_json::to_writer_pretty(&mut *writer, &v).context("failed to serialize JSON")?;
} else {
serde_json::to_writer(&mut *writer, &v).context("failed to serialize JSON")?;
}
} else if format == "yaml" {
serde_yaml::to_writer(&mut *writer, &v).context("failed to serialize YAML")?;
} else if format == "toml" {
let s = toml::ser::to_string(&v).context("failed to serialize TOML")?;
writer.write_all(s.as_bytes())?;
} else {
cbor2::to_writer(&v, &mut *writer).context("failed to serialize CBOR")?;
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_export_array() {
let cbor = [0x82, 0x01, 0x02];
let cases: [(&str, bool, &[u8]); 2] = [
("json", false, b"[1,2]"),
("yaml", false, b"- 1\n- 2\n"),
];
for (format, pretty, expected) in cases {
let mut output = Vec::new();
export_from_reader(format, "\n", pretty, &cbor[..], &mut output).unwrap();
assert_eq!(output, expected, "format: {format}");
}
}
#[test]
fn test_export_cbor() {
let input = [0x82, 0x01, 0x02];
let mut output = Vec::new();
export_from_reader("cbor", "\n", false, &input[..], &mut output).unwrap();
assert_eq!(output, b"\x82\x01\x02" as &[u8]);
}
#[test]
fn test_export_sequence() {
let input = [0xa1, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61];
let mut output = Vec::new();
export_from_reader("json", "\n", false, &input[..], &mut output).unwrap();
assert_eq!(output, b"{\"a\":\"a\"}\n\"a\"" as &[u8]);
}
#[test]
fn test_export_pretty_json() {
let cbor = [0x82, 0x01, 0x02];
let mut compact = Vec::new();
export_from_reader("json", "\n", false, &cbor[..], &mut compact).unwrap();
let mut pretty = Vec::new();
export_from_reader("json", "\n", true, &cbor[..], &mut pretty).unwrap();
assert_eq!(compact, b"[1,2]");
assert_ne!(pretty, compact);
assert!(pretty.windows(2).any(|w| w == b"\n "));
}
}