use std::error::Error as StdError;
use std::fs::File;
use std::io::prelude::*;
use clap::{Parser, ValueEnum};
use env_logger::Builder as LoggerBuilder;
use schematools::Client;
use serde_json::Value;
pub mod chain;
#[cfg(feature = "codegen")]
pub mod codegen;
pub mod process;
pub mod registry;
pub mod validate;
use crate::error::Error;
use schematools::schema::Schema;
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, ValueEnum)]
enum OutputValues {
Json,
Yaml,
}
pub trait GetSchemaCommand {
fn get_schema(&self, client: &Client) -> Result<Schema, Error>;
}
fn get_options<T>(
s: &str,
) -> Result<(T, serde_json::Value), Box<dyn StdError + Send + Sync + 'static>>
where
T: std::str::FromStr,
T::Err: StdError + Send + Sync + 'static,
{
if s.contains("=~") {
let pos = s.find("=~").unwrap();
Ok((s[..pos].parse()?, serde_json::from_str(&s[pos + 2..])?))
} else {
let pos = s
.find('=')
.ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?;
Ok((s[..pos].parse()?, serde_json::to_value(&s[pos + 1..])?))
}
}
#[derive(Clone, Debug, Parser)]
pub struct Verbosity {
#[clap(
long,
short,
action = clap::ArgAction::Count
)]
verbose: u8,
}
impl Verbosity {
pub fn start(self: &Verbosity) -> Result<(), Error> {
LoggerBuilder::new()
.filter(Some("globset"), log::LevelFilter::Error)
.filter(
None,
match self.verbose {
4 => log::LevelFilter::Trace,
3 => log::LevelFilter::Debug,
2 => log::LevelFilter::Info,
1 => log::LevelFilter::Warn,
0 => log::LevelFilter::Error,
_ => log::LevelFilter::Trace,
},
)
.format_timestamp_nanos()
.try_init()
.map_err(|e| Error::LoggerStart(e.to_string()))?;
Ok(())
}
}
#[derive(Clone, Debug, Parser)]
pub(crate) struct Output {
#[arg(value_enum, short, long, default_value = "json")]
output: String,
#[clap(long)]
to_file: Option<String>,
}
impl Output {
pub fn show(self: &Output, value: &Value) {
let result = match self.output.as_str() {
"json" => serde_json::to_string_pretty(value).unwrap(),
"yaml" => yaml_serde::to_string(value).unwrap(),
_ => panic!("Output format not supported"),
};
match &self.to_file {
Some(filename) => {
let mut file = File::create(filename).unwrap();
file.write_all(result.as_bytes())
.expect("Can't save file on disk");
}
None => {
println!("{result}");
}
};
}
}