use clap::{Parser, ValueEnum};
use jst::{Context, ResolveMethod};
use serde_json::Value;
use std::fs::File;
use std::io::{self, BufReader};
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum Type {
#[default]
Avro,
Bigquery,
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum Resolve {
#[default]
Cast,
Panic,
Drop,
}
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
file: Option<String>,
#[arg(short, long = "type", value_enum, default_value_t = Type::Avro, value_name = "TYPE")]
typ: Type,
#[arg(short, long, value_enum, default_value_t = Resolve::Cast)]
resolve: Resolve,
#[arg(short = 'c', long)]
normalize_case: bool,
#[arg(short = 'n', long)]
force_nullable: bool,
#[arg(long)]
tuple_struct: bool,
#[arg(short = 'w', long)]
allow_maps_without_value: bool,
}
fn main() {
env_logger::init();
let args = Args::parse();
let reader: Box<dyn io::Read> = match &args.file {
Some(path) if path == "-" => Box::new(io::stdin()),
Some(path) => {
let file = File::open(path).unwrap();
Box::new(BufReader::new(file))
}
None => Box::new(io::stdin()),
};
let data: Value = serde_json::from_reader(reader).unwrap();
let context = Context {
resolve_method: match args.resolve {
Resolve::Cast => ResolveMethod::Cast,
Resolve::Panic => ResolveMethod::Panic,
Resolve::Drop => ResolveMethod::Drop,
},
normalize_case: args.normalize_case,
force_nullable: args.force_nullable,
tuple_struct: args.tuple_struct,
allow_maps_without_value: args.allow_maps_without_value,
json_object_path_regex: None,
};
let output = match args.typ {
Type::Avro => jst::convert_avro(&data, context),
Type::Bigquery => jst::convert_bigquery(&data, context),
};
let pretty = serde_json::to_string_pretty(&output).unwrap();
println!("{}", pretty);
}