Tradaf/src/lib.rs
2022-09-20 23:03:15 +02:00

183 lines
6.1 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(Debug, 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 {
//Bson,
//Cbor,
Json,
Json5,
Pickle,
Ron,
//Toml
Yaml,
}
#[derive(Copy, Clone, Debug, ValueEnum)]
pub enum Output {
//Bson,
//Cbor,
Json,
//Json5, // NOTE: The crate is not notted "(deserialization only)" on the [serde listing](https://serde.rs/#data-formats) but it does not expose a serializer
Pickle,
Ron,
//Toml,
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::Bson => {
use bson::Deserializer;
let mut deserializer = bson::from_reader(input).unwrap(); // FIXME: need which type annotation?
ser(opt, &mut deserializer, output);
}
*/
Input::Json => {
use serde_json::Deserializer;
// NOTE: Apparently serde_json do not implement `Deserializer` on const?
let mut deserializer = Deserializer::from_reader(input);
ser(opt, &mut deserializer, output);
}
Input::Json5 => {
use json5::Deserializer;
// NOTE: Apparently Json5 do not implement `Deserializer` on const?
// NOTE: Apparently Json5 do not implement `Deserializer::from_reader` but it can serialise into a writter…
let mut buf = String::new();
let _buf_size = input.read_to_string(&mut buf).unwrap();
let mut deserializer = Deserializer::from_str(&buf).unwrap();
ser(opt, &mut deserializer, output);
}
Input::Pickle => {
use serde_pickle::Deserializer;
// NOTE: Apparently serde_pickle do not implement `Deserializer` on const?
let mut deserializer = Deserializer::new(input, serde_pickle::DeOptions::new());
ser(opt, &mut deserializer, output);
}
Input::Ron => {
use ron::Deserializer;
// 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 = Deserializer::from_bytes(&buf).unwrap();
ser(opt, &mut deserializer, output);
}
Input::Yaml => {
use serde_yaml::Deserializer;
let deserializer = 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::Bson => {
use bson::Serializer;
let options = bson::SerializerOptions::builder();
let options = if opt.pretty {
options.human_readable(true)
} else {
options.human_readable(false)
};
let serializer = Serializer::new_with_options(options.build()); // FIXME: why no way to tell the serializer were we want the output?
serde_transcode::transcode(deserializer, serializer).unwrap();
}
*/
Output::Json => {
use serde_json::Serializer;
if opt.pretty {
let formatter = serde_json::ser::PrettyFormatter::with_indent(b"\t");
let serializer = &mut Serializer::with_formatter(output, formatter);
serde_transcode::transcode(deserializer, serializer).unwrap();
} else {
let serializer = &mut Serializer::new(output);
serde_transcode::transcode(deserializer, serializer).unwrap();
};
// NOTE: serde_jsons PrettyFormatter and CompactFormatter are incompatibles…
// serde_transcode::transcode(deserializer, serializer).unwrap();
}
Output::Pickle => {
use serde_pickle::Serializer;
let serializer = &mut Serializer::new(output, serde_pickle::SerOptions::new());
serde_transcode::transcode(deserializer, serializer).unwrap();
}
Output::Ron => {
use ron::Serializer;
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 Serializer::new(output, pretty_config).unwrap();
serde_transcode::transcode(deserializer, serializer).unwrap();
}
Output::Yaml => {
use serde_yaml::Serializer;
let serializer = &mut Serializer::new(output);
serde_transcode::transcode(deserializer, serializer).unwrap();
}
};
}