Tradaf/src/lib.rs

114 lines
3.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use clap::{Parser, ValueEnum};
use serde::de::Deserializer;
use std::io::{Read, Write};
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
pub struct Opt {
/// Input type
#[clap(value_enum, ignore_case = true)]
pub input: Input,
/// Output type
#[clap(value_enum, ignore_case = true)]
pub output: Output,
/// For data format compatible, a default pretty format is output instead of a minified one
/// Output a pretty formated data instead of minified, only for format compatible
#[clap(long, short)]
pub pretty: bool,
/// Do not output a newline at the end of the stream
#[clap(long, short)]
pub no_newline: bool,
}
#[derive(Copy, Clone, Debug, ValueEnum)]
pub enum Input {
Json,
Ron,
Yaml,
}
#[derive(Copy, Clone, Debug, ValueEnum)]
pub enum Output {
Json,
Ron,
Yaml,
}
pub fn transcode(opt: Opt, input: &mut dyn Read, output: &mut dyn Write) {
// A JSON deserializer. You can use any Serde Deserializer here.
de(&opt, input, output);
// TODO: I would love to be able to have `de` and `ser` return the correct
// (de)serializer and then call `serde_transcode::transcode(deserializer, serializer)`
// here once for all. This will be a clearer separation of function,
// but it may need `erased_serde` that I did not made it work with `serde_transcode`.
if !opt.no_newline {
output.write_all(b"\n").expect(
"We already wrote the whole serialized struct, a new line at the end should be OK",
);
}
}
fn de(opt: &Opt, input: &mut dyn Read, output: &mut dyn Write) {
match opt.input {
Input::Json => {
// NOTE: Apparently serde_json do not implement `Deserializer` on const?
let mut deserializer = serde_json::Deserializer::from_reader(input);
ser(opt, &mut deserializer, output);
}
Input::Ron => {
// NOTE: Apparently ron do not implement `Deserializer` on const?
// NOTE: Apparently ron do not implement `Deserializer::from_reader` but it can serialise into a writter…
let mut buf = vec![];
let _buf_size = input.read_to_end(&mut buf).unwrap();
let mut deserializer = ron::Deserializer::from_bytes(&buf).unwrap();
ser(opt, &mut deserializer, output);
}
Input::Yaml => {
let deserializer = serde_yaml::Deserializer::from_reader(input);
ser(opt, deserializer, output);
}
};
}
fn ser<'de, D>(opt: &Opt, deserializer: D, output: &mut dyn Write)
where
D: Deserializer<'de>,
{
match opt.output {
Output::Json => {
if opt.pretty {
let formatter = serde_json::ser::PrettyFormatter::with_indent(b"\t");
let serializer = &mut serde_json::Serializer::with_formatter(output, formatter);
serde_transcode::transcode(deserializer, serializer).unwrap();
} else {
let serializer = &mut serde_json::Serializer::new(output);
serde_transcode::transcode(deserializer, serializer).unwrap();
};
// NOTE: serde_jsons PrettyFormatter and CompactFormatter are incompatibles…
// serde_transcode::transcode(deserializer, serializer).unwrap();
}
Output::Ron => {
let mut pretty_config = None;
if opt.pretty {
let pretty = ron::ser::PrettyConfig::new().indentor("\t".to_owned());
pretty_config = Some(pretty);
}
let serializer = &mut ron::Serializer::new(output, pretty_config).unwrap();
serde_transcode::transcode(deserializer, serializer).unwrap();
}
Output::Yaml => {
let serializer = &mut serde_yaml::Serializer::new(output);
serde_transcode::transcode(deserializer, serializer).unwrap();
}
};
}