use corn::{parse, Value};
use corn_cli::error::{print_err, Error, ExitCode};
use std::io::Read;
use std::process::exit;
use std::{fs, io};
use crate::Error::Corn;
use clap::{Parser, ValueEnum};
use colored::Colorize;
#[derive(ValueEnum, Clone, Copy, Debug)]
enum OutputType {
Json,
Yaml,
Toml,
}
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
input: Option<String>,
#[clap(long = "type", short = 't', value_enum)]
output_type: Option<OutputType>,
}
fn get_input(input: Option<&String>) -> io::Result<String> {
if let Some(input) = input {
fs::read_to_string(input)
} else {
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer)?;
Ok(buffer)
}
}
fn main() {
let args = Args::parse();
let unparsed_file = get_input(args.input.as_ref());
match unparsed_file {
Ok(unparsed_file) => {
let output_type = get_output_type(args.output_type);
match parse(&unparsed_file) {
Ok(config) => match serialize(&config, output_type) {
Ok(serialized) => println!("{serialized}"),
Err(err) => handle_err(&err),
},
Err(err) => handle_err(&Corn(err)),
};
}
Err(err) => {
print_err(
&err.to_string(),
Some(format!(
"while attempting to read `{}`",
args.input.unwrap_or_else(|| "stdin".to_string()).bold()
)),
);
let error = Error::ReadingFile(err);
exit(error.get_exit_code());
}
}
}
fn get_output_type(arg: Option<OutputType>) -> OutputType {
if let Some(output_type) = arg {
return output_type;
}
OutputType::Json
}
fn serialize(config: &Value, output_type: OutputType) -> Result<String, Error> {
match output_type {
OutputType::Json => serde_json::to_string_pretty(&config).map_err(Error::from),
OutputType::Yaml => serde_yaml::to_string(&config).map_err(Error::from),
OutputType::Toml => toml_edit::ser::to_string_pretty(&config).map_err(Error::from),
}
}
fn handle_err(error: &Error) {
let code = error.get_exit_code();
let code_formatted = format!("[E{code:0>4}]").red().bold();
eprintln!("{code_formatted} {error}");
exit(code);
}