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: Args,
}
#[derive(clap::Args)]
pub struct Args {
#[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"),
}
}
}
enum Outcome<'buf> {
Version {
object_kind: ObjectKind,
version: guess::Version<ocpi_tariffs::Version, ()>,
},
Report {
object_kind: ObjectKind,
unexpected_fields: json::UnexpectedFields<'buf>,
version: guess::Version<ocpi_tariffs::Version, ()>,
},
}
impl Command {
pub fn run(self) -> Result<(), Error> {
let Self {
args:
Args {
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::Report {
object_kind,
unexpected_fields,
version: version.into_version(),
}
} else {
let version = cdr::parse(&json)?;
Outcome::Version {
object_kind,
version: version.into_version(),
}
}
}
ObjectKind::Tariff => {
if validate {
let report = tariff::parse_and_report(&json)?;
let guess::Report {
unexpected_fields,
version,
} = report;
Outcome::Report {
object_kind,
unexpected_fields,
version: version.into_version(),
}
} else {
let version = tariff::parse(&json)?;
Outcome::Version {
object_kind,
version: version.into_version(),
}
}
}
};
match outcome {
Outcome::Version {
object_kind,
version,
} => print_version(object_kind, &version),
Outcome::Report {
object_kind,
unexpected_fields,
version,
} => {
print::unexpected_fields(object_kind, &unexpected_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}");
}
}
}