1use std::io;
2
3use cbor2::de::Deserializer;
4use cbor2::value::Value as CborValue;
5use anyhow::Context;
6
7pub fn export_from_reader<R: io::Read, W: io::Write>(
34 format: &str,
35 delimiter: &str,
36 pretty: bool,
37 reader: R,
38 writer: &mut W,
39) -> anyhow::Result<()> {
40 let mut first = true;
41 for v in Deserializer::from_reader(reader).into_iter::<CborValue>() {
42 let v = v?;
43 if !first {
44 writer.write_all(delimiter.as_bytes())?;
45 }
46 first = false;
47
48 if format == "json" {
49 if pretty {
50 serde_json::to_writer_pretty(&mut *writer, &v).context("failed to serialize JSON")?;
51 } else {
52 serde_json::to_writer(&mut *writer, &v).context("failed to serialize JSON")?;
53 }
54 } else if format == "yaml" {
55 serde_yaml::to_writer(&mut *writer, &v).context("failed to serialize YAML")?;
56 } else if format == "toml" {
57 let s = toml::ser::to_string(&v).context("failed to serialize TOML")?;
58 writer.write_all(s.as_bytes())?;
59 } else {
60 cbor2::to_writer(&v, &mut *writer).context("failed to serialize CBOR")?;
61 }
62 }
63 Ok(())
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_export_array() {
72 let cbor = [0x82, 0x01, 0x02];
73 let cases: [(&str, bool, &[u8]); 2] = [
74 ("json", false, b"[1,2]"),
75 ("yaml", false, b"- 1\n- 2\n"),
76 ];
77 for (format, pretty, expected) in cases {
78 let mut output = Vec::new();
79 export_from_reader(format, "\n", pretty, &cbor[..], &mut output).unwrap();
80 assert_eq!(output, expected, "format: {format}");
81 }
82 }
83
84 #[test]
85 fn test_export_cbor() {
86 let input = [0x82, 0x01, 0x02];
87 let mut output = Vec::new();
88 export_from_reader("cbor", "\n", false, &input[..], &mut output).unwrap();
89 assert_eq!(output, b"\x82\x01\x02" as &[u8]);
90 }
91
92 #[test]
93 fn test_export_sequence() {
94 let input = [0xa1, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61];
96 let mut output = Vec::new();
97 export_from_reader("json", "\n", false, &input[..], &mut output).unwrap();
98 assert_eq!(output, b"{\"a\":\"a\"}\n\"a\"" as &[u8]);
99 }
100
101 #[test]
102 fn test_export_pretty_json() {
103 let cbor = [0x82, 0x01, 0x02];
104 let mut compact = Vec::new();
105 export_from_reader("json", "\n", false, &cbor[..], &mut compact).unwrap();
106
107 let mut pretty = Vec::new();
108 export_from_reader("json", "\n", true, &cbor[..], &mut pretty).unwrap();
109
110 assert_eq!(compact, b"[1,2]");
111 assert_ne!(pretty, compact);
112 assert!(pretty.windows(2).any(|w| w == b"\n "));
113 }
114}