use std::io;
use cbor2::de::Deserializer;
use cbor2::value::Value as CborValue;
pub fn import_from_reader<R: io::Read, W: io::Write>(
input_format: &str,
mut reader: R,
writer: &mut W,
) -> anyhow::Result<()> {
match input_format {
"json" => {
for v in serde_json::de::Deserializer::from_reader(reader).into_iter::<serde_json::Value>() {
let v = v?;
cbor2::to_writer(&v, &mut *writer)?;
}
}
"yaml" => {
let result: serde_yaml::Value = serde_yaml::from_reader(reader)?;
cbor2::to_writer(&result, writer)?;
}
"toml" => {
let mut s = String::new();
reader.read_to_string(&mut s)?;
let result: toml::Value = toml::de::from_str(&s)?;
cbor2::to_writer(&result, writer)?;
}
_ => {
for v in Deserializer::from_reader(reader).into_iter::<CborValue>() {
let v = v?;
cbor2::to_writer(&v, &mut *writer)?;
}
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_import_array() {
let cases = [
("json", &b"[1,2]"[..], vec![0x82, 0x01, 0x02]),
("yaml", &b"- 1\n- 2\n"[..], vec![0x82, 0x01, 0x02]),
("cbor", &b"\x82\x01\x02"[..], vec![0x82, 0x01, 0x02]),
];
for (format, input, expected) in cases {
let mut output = Vec::new();
import_from_reader(format, input, &mut output).unwrap();
assert_eq!(output, expected, "format: {format}");
}
}
#[test]
fn test_import_map_from_toml() {
let input = b"foo = 1\nbar = 2\n";
let mut output = Vec::new();
import_from_reader("toml", &input[..], &mut output).unwrap();
assert_eq!(output, vec![0xa2, 0x63, 0x66, 0x6f, 0x6f, 0x01, 0x63, 0x62, 0x61, 0x72, 0x02]);
}
#[test]
fn test_import_invalid_json() {
let input = b"not json";
let mut output = Vec::new();
let err = import_from_reader("json", &input[..], &mut output).unwrap_err();
assert!(!err.to_string().is_empty(), "error should be non-empty: {err}");
}
}