ocpi_tariffs_cli/
guess_version.rs1use std::{
2 fmt, fs,
3 io::{self, Read as _},
4 path::PathBuf,
5};
6
7use console::style;
8use ocpi_tariffs::{cdr, guess, json, tariff};
9use tracing::debug;
10
11use crate::{opts::DEFAULT_STDIO_BUF_SIZE, print, Error, ObjectKind};
12
13#[derive(clap::Parser)]
14pub struct Command {
15 #[command(flatten)]
16 args: Args,
17}
18
19#[derive(clap::Args)]
20pub struct Args {
21 #[arg(short = 't', long = "type")]
23 kind: ObjectKind,
24
25 #[arg(short = 'f', long)]
27 file: Option<PathBuf>,
28
29 #[arg(long)]
31 validate: bool,
32}
33
34impl fmt::Display for ObjectKind {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 ObjectKind::Cdr => f.write_str("CDR"),
38 ObjectKind::Tariff => f.write_str("tariff"),
39 }
40 }
41}
42
43enum Outcome<'buf> {
44 Version {
45 object_kind: ObjectKind,
46
47 version: guess::Version<ocpi_tariffs::Version, ()>,
48 },
49 Report {
50 object_kind: ObjectKind,
51
52 unexpected_fields: json::UnexpectedFields<'buf>,
56
57 version: guess::Version<ocpi_tariffs::Version, ()>,
58 },
59}
60
61impl Command {
62 pub fn run(self) -> Result<(), Error> {
63 let Self {
64 args:
65 Args {
66 kind: object_kind,
67 file: path,
68 validate,
69 },
70 } = self;
71
72 let json = if let Some(path) = path {
73 debug!("Loading {object_kind} from file");
74 let json = fs::read_to_string(&*path).map_err(|e| Error::file(path, e))?;
75 debug!(bytes_read = json.len(), "{object_kind} read from file");
76 json
77 } else {
78 debug!("Loading {object_kind} from stdin");
79 let mut stdin = io::stdin().lock();
80 let mut json = String::with_capacity(DEFAULT_STDIO_BUF_SIZE);
81 let bytes_read = stdin.read_to_string(&mut json).map_err(Error::stdin)?;
82 debug!(bytes_read, "{object_kind} read from stdin");
83 json
84 };
85
86 let outcome = match object_kind {
87 ObjectKind::Cdr => {
88 if validate {
89 let report = cdr::parse_and_report(&json)?;
90 let (version, unexpected_fields) = report.into_parts();
91
92 Outcome::Report {
93 object_kind,
94 unexpected_fields,
95 version: version.into_version(),
96 }
97 } else {
98 let version = cdr::parse(&json)?;
99 Outcome::Version {
100 object_kind,
101 version: version.into_version(),
102 }
103 }
104 }
105 ObjectKind::Tariff => {
106 if validate {
107 let report = tariff::parse_and_report(&json)?;
108 let (version, unexpected_fields) = report.into_parts();
109
110 Outcome::Report {
111 object_kind,
112 unexpected_fields,
113 version: version.into_version(),
114 }
115 } else {
116 let version = tariff::parse(&json)?;
117 Outcome::Version {
118 object_kind,
119 version: version.into_version(),
120 }
121 }
122 }
123 };
124
125 match outcome {
126 Outcome::Version {
127 object_kind,
128 version,
129 } => print_version(object_kind, &version),
130 Outcome::Report {
131 object_kind,
132 unexpected_fields,
133 version,
134 } => {
135 print::unexpected_fields(object_kind, &unexpected_fields);
136 print_version(object_kind, &version);
137 }
138 }
139
140 Ok(())
141 }
142}
143
144fn print_version(object_kind: ObjectKind, version: &guess::Version<ocpi_tariffs::Version, ()>) {
145 match version {
146 guess::Version::Uncertain(()) => {
147 eprintln!(
148 "Unable to guess the version of the given {} JSON",
149 style(object_kind).green()
150 );
151 }
152 guess::Version::Certain(version) => {
153 println!("{version}");
154 }
155 }
156}