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 guess::Report {
91 unexpected_fields,
92 version,
93 } = report;
94
95 Outcome::Report {
96 object_kind,
97 unexpected_fields,
98 version: version.into_version(),
99 }
100 } else {
101 let version = cdr::parse(&json)?;
102 Outcome::Version {
103 object_kind,
104 version: version.into_version(),
105 }
106 }
107 }
108 ObjectKind::Tariff => {
109 if validate {
110 let report = tariff::parse_and_report(&json)?;
111 let guess::Report {
112 unexpected_fields,
113 version,
114 } = report;
115
116 Outcome::Report {
117 object_kind,
118 unexpected_fields,
119 version: version.into_version(),
120 }
121 } else {
122 let version = tariff::parse(&json)?;
123 Outcome::Version {
124 object_kind,
125 version: version.into_version(),
126 }
127 }
128 }
129 };
130
131 match outcome {
132 Outcome::Version {
133 object_kind,
134 version,
135 } => print_version(object_kind, &version),
136 Outcome::Report {
137 object_kind,
138 unexpected_fields,
139 version,
140 } => {
141 print::unexpected_fields(object_kind, &unexpected_fields);
142 print_version(object_kind, &version);
143 }
144 }
145
146 Ok(())
147 }
148}
149
150fn print_version(object_kind: ObjectKind, version: &guess::Version<ocpi_tariffs::Version, ()>) {
151 match version {
152 guess::Version::Uncertain(()) => {
153 eprintln!(
154 "Unable to guess the version of the given {} JSON",
155 style(object_kind).green()
156 );
157 }
158 guess::Version::Certain(version) => {
159 println!("{version}");
160 }
161 }
162}