Tradaf/src/lib.rs

369 lines
12 KiB
Rust
Raw Permalink 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::{
convert::TryFrom,
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,
#[clap(long, short = 'F', required_if_eq_any(&[("input", "d-bus"), ("input", "g-variant")]))]
pub format_in: Option<String>,
#[clap(long, short = 'f', required_if_eq_any(&[("output", "d-bus"), ("output", "g-variant")]))]
pub format_out: Option<String>,
/// 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 {
Bencode,
//Bson,
//Cbor,
DBus,
//DynamoDB,
//FlexBuffer,
GVariant,
Json,
Json5,
//SExpression,
Pickle,
//Qs, // NOTE: The crate is not noted "(serialization only)" on the [serde listing](https://serde.rs/#data-formats) but it does not expose a `Deserializer`
//Rmp, // NOTE: It appears that we are forced to deserialize into a concrete type
Ron,
//Toml
Yaml,
}
#[derive(Copy, Clone, Debug, ValueEnum)]
pub enum Output {
//Bencode,
//Bson,
//Cbor,
DBus,
//DynamoDB,
//FlexBuffer,
GVariant,
Json,
//Json5, // NOTE: The crate is not noted "(deserialization only)" on the [serde listing](https://serde.rs/#data-formats) but it does not expose a `Serializer`
//SExpression,
Pickle,
Qs,
Rmp,
Ron,
//Toml,
Yaml,
}
pub fn transcode(opt: Opt, input: &mut dyn Read, output: &mut dyn Write) {
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::Bencode => {
use bendy::serde::Deserializer;
let mut buf = vec![];
let _buf_size = input.read_to_end(&mut buf).unwrap();
let mut deserializer = Deserializer::from_bytes(&buf);
ser(opt, &mut deserializer, output);
}
/*
Input::Bson => {
use bson::Deserializer;
let deserializer = bson::from_reader(input).unwrap(); // FIXME: can we skip the type annotation?
ser(opt, deserializer, output);
}
*/
Input::DBus => {
use zvariant::dbus::Deserializer;
use zvariant::EncodingContext;
use zvariant::Signature;
use byteorder::LE;
let sig = opt.format_in.clone().unwrap();
let mut buf = String::new();
let _buf_size = input.read_to_string(&mut buf).unwrap();
let mut deserializer = Deserializer::new(
buf.as_bytes(),
None,
&Signature::try_from(sig).unwrap(),
EncodingContext::<LE>::new_dbus(0),
);
ser(opt, &mut deserializer, output);
}
/*
Input::DynamoDB => {
use serde_dynamo::Deserializer;
let deserializer = Deserializer::from(input); // from_reader(input);
ser(opt, deserializer, output);
}
*/
/*
Input::FlexBuffer => {
use serde_yaml::Deserializer;
let deserializer = Deserializer::from_reader(input);
ser(opt, deserializer, output);
}
*/
Input::GVariant => {
use zvariant::gvariant::Deserializer;
use zvariant::EncodingContext;
use zvariant::Signature;
use byteorder::LE;
let sig = opt.format_in.clone().unwrap();
let mut buf = String::new();
let _buf_size = input.read_to_string(&mut buf).unwrap();
let mut deserializer = Deserializer::new(
buf.as_bytes(),
None,
&Signature::try_from(sig).unwrap(),
EncodingContext::<LE>::new_dbus(0),
);
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::SExpression => {
use serde_lexpr as Deserializer;
let deserializer = Deserializer::from_reader(input).unwrap(); // FIXME: can we skip the type annotation?
ser(opt, 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::Bencode => {
use bendy::serde::Serializer;
let serializer = &mut Serializer::new(/*output*/);
serde_transcode::transcode(deserializer, serializer).unwrap();
serializer.into_bytes();
}
*/
/*
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::DBus => {
use zvariant::dbus::Serializer;
use zvariant::EncodingContext;
use zvariant::Signature;
use byteorder::LE;
let sig = opt.format_out.clone().unwrap();
let mut out = std::io::Cursor::new(vec![]);
let mut fs = vec![];
let serializer = &mut Serializer::new(
&Signature::try_from(sig).unwrap(),
&mut out,
&mut fs, //None,
EncodingContext::<LE>::new_dbus(0),
);
//let mut buf = String::new();
// let _buf_size = output.read_to_string(&mut buf).unwrap();
// let mut deserializer = Deserializer::new();
serde_transcode::transcode(deserializer, serializer).unwrap();
}
/*
Output::DynamoDB => {
use serde_dynamo::Serializer;
let serializer = &mut Serializer::new(output);
serde_transcode::transcode(deserializer, serializer).unwrap();
}
*/
/*
Output::FlexBuffer => {
use flexbuffers::FlexbufferSerializer as Serializer;
let serializer = &mut Serializer::new(/*output*/);
// serde_transcode::transcode(deserializer, serializer).unwrap();
let r = flexbuffers::Reader::get_root(serializer.view()).unwrap();
println!("{}", r);
}
*/
Output::GVariant => {
use zvariant::gvariant::Serializer;
use zvariant::EncodingContext;
use zvariant::Signature;
use byteorder::LE;
let sig = opt.format_out.clone().unwrap();
let mut out = std::io::Cursor::new(vec![]);
let mut fs = vec![];
let serializer = &mut Serializer::new(
&Signature::try_from(sig).unwrap(),
&mut out,
&mut fs, //None,
EncodingContext::<LE>::new_dbus(0),
);
//let mut buf = String::new();
// let _buf_size = output.read_to_string(&mut buf).unwrap();
// let mut deserializer = Deserializer::new();
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::SExpression => {
use serde_lexpr::to_writer as Serializer;
let serializer = Serializer::new(output); // FIXME: There is a `to_writer` but the Serializer is not exposed directly.
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::Qs => {
use serde_qs::Serializer;
let serializer = &mut Serializer::new(output);
serde_transcode::transcode(deserializer, serializer).unwrap();
}
Output::Rmp => {
use rmp_serde::Serializer;
let serializer = &mut Serializer::new(output);
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();
}
};
}