use std::io::{BufRead, BufReader, Read, Write};
use clap::{Args, Parser};
use clio::{Input, Output};
use jslt::Jslt;
#[derive(Args, Debug)]
#[group(required = true, multiple = false)]
struct SchemaOpts {
#[clap(long, short, conflicts_with = "schema_path")]
schema: Option<String>,
#[clap(long, short = 'f', conflicts_with = "schema")]
schema_path: Option<Input>,
}
#[derive(Debug, Parser)]
#[command(version, about, styles = jslt::_binary::get_clap_styles())]
struct Opts {
#[clap(flatten)]
schema: SchemaOpts,
#[clap(long, conflicts_with = "input")]
text: Option<String>,
#[clap(long, short, conflicts_with = "text")]
multiline: bool,
#[clap(value_parser, default_value = "-", conflicts_with = "text")]
input: Input,
#[clap(long, short)]
pretty: bool,
#[clap(long, short, value_parser, default_value = "-")]
output: Output,
}
impl SchemaOpts {
fn into_schema(self) -> std::io::Result<String> {
match (self.schema_path, self.schema) {
(Some(mut schema_path), None) => {
let mut output = String::new();
schema_path.read_to_string(&mut output)?;
Ok(output)
}
(None, Some(schema)) => Ok(schema),
_ => unreachable!(),
}
}
}
fn entrypoint(mut opts: Opts) -> Result<(), Box<dyn std::error::Error>> {
let schema = opts.schema.into_schema()?;
let jslt: Jslt = schema.parse()?;
if opts.multiline {
for line in BufReader::new(opts.input).lines().take_while(Result::is_ok) {
let value = serde_json::from_str(&line.expect("line should be filtered to only success"))?;
let value = jslt.transform_value(&value)?;
if opts.pretty {
writeln!(opts.output, "{}", serde_json::to_string_pretty(&value)?)?;
} else {
writeln!(opts.output, "{value}")?;
}
}
} else {
let value = match opts.text {
Some(text) => serde_json::from_str(&text)?,
None => serde_json::from_reader(opts.input)?,
};
let value = jslt.transform_value(&value)?;
if opts.pretty {
writeln!(opts.output, "{}", serde_json::to_string_pretty(&value)?)?;
} else {
writeln!(opts.output, "{value}")?;
}
}
Ok(())
}
fn main() {
let opts = Opts::parse();
if let Err(err) = entrypoint(opts) {
eprintln!("{err}");
}
}