use std::{fmt, path::PathBuf};
use console::style;
use ocpi_tariffs::{cdr, guess, json, tariff};
use crate::{load_object_file, load_object_from_stdin, print, Error, ObjectKind};
#[derive(clap::Parser)]
pub struct Command {
#[command(flatten)]
args: Arguments,
}
#[derive(clap::Args)]
struct Arguments {
#[arg(short = 't', long = "type")]
kind: ObjectKind,
#[arg(short = 'f', long)]
file: Option<PathBuf>,
#[arg(long)]
validate: bool,
}
impl fmt::Display for ObjectKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ObjectKind::Cdr => f.write_str("CDR"),
ObjectKind::Tariff => f.write_str("tariff"),
}
}
}
struct Outcome<'buf> {
object_kind: ObjectKind,
version: guess::Version<ocpi_tariffs::Version, ()>,
unexpected_fields: Option<json::UnexpectedFields<'buf>>,
}
impl Command {
pub fn run(self) -> Result<(), Error> {
let Self {
args:
Arguments {
kind: object_kind,
file: path,
validate,
},
} = self;
let json = if let Some(path) = path.as_deref() {
load_object_file(path, object_kind)?
} else {
load_object_from_stdin(object_kind)?
};
let outcome = match object_kind {
ObjectKind::Cdr => {
if validate {
let report = cdr::parse_and_report(&json)?;
let guess::Report {
unexpected_fields,
version,
} = report;
Outcome {
object_kind,
unexpected_fields: Some(unexpected_fields),
version: version.into_version(),
}
} else {
let version = cdr::parse(&json)?;
Outcome {
object_kind,
unexpected_fields: None,
version: version.into_version(),
}
}
}
ObjectKind::Tariff => {
if validate {
let report = tariff::parse_and_report(&json)?;
let guess::Report {
unexpected_fields,
version,
} = report;
Outcome {
object_kind,
unexpected_fields: Some(unexpected_fields),
version: version.into_version(),
}
} else {
let version = tariff::parse(&json)?;
Outcome {
object_kind,
unexpected_fields: None,
version: version.into_version(),
}
}
}
};
let Outcome {
object_kind,
unexpected_fields,
version,
} = outcome;
if let Some(fields) = unexpected_fields {
print::unexpected_fields(object_kind, &fields);
}
print_version(object_kind, &version);
Ok(())
}
}
fn print_version(object_kind: ObjectKind, version: &guess::Version<ocpi_tariffs::Version, ()>) {
match version {
guess::Version::Uncertain(()) => {
eprintln!(
"Unable to guess the version of the given {} JSON",
style(object_kind).green()
);
}
guess::Version::Certain(version) => {
println!("{version}");
}
}
}