use std::process;
use carbonintensity::{get_intensities, get_intensity, ApiError, Target};
use chrono::NaiveDateTime;
use clap::Parser;
use std::io::Write;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
#[clap(short, long)]
pub start_date: Option<String>,
#[clap(short, long)]
pub end_date: Option<String>,
#[clap()]
#[arg(default_value_t=Target::National)]
pub target: Target,
}
#[tokio::main]
async fn main() {
let args = Args::parse();
let target: Target = args.target;
if let Some(start_date) = &args.start_date {
let end_date: Option<&str> = args.end_date.as_deref();
let result = get_intensities(&target, start_date, &end_date).await;
handle_results(result);
} else {
let result = get_intensity(&target).await;
handle_result(result, &target);
}
}
#[allow(clippy::explicit_write)]
fn handle_results(result: Result<Vec<(NaiveDateTime, i32)>, ApiError>) {
if let Ok(results) = result {
for (time, value) in results {
writeln!(std::io::stdout(), "{}, {}", time, value).unwrap_or_default();
}
} else {
eprintln!("{}", result.unwrap_err());
process::exit(1);
}
}
#[allow(clippy::explicit_write)]
fn handle_result(result: Result<i32, ApiError>, target: &Target) {
if result.is_ok() {
writeln!(
std::io::stdout(),
"Carbon intensity for {}: {:?}",
target,
result.unwrap()
)
.unwrap_or_default();
} else {
eprintln!("{}", result.unwrap_err());
process::exit(1);
}
}
#[cfg(test)]
mod tests {
use clap::Parser;
use carbonintensity::Region;
use crate::{Args, Target};
fn parsed_args(args: Vec<&str>) -> Result<Args, clap::Error> {
let args = ["carbonintensity-api"].iter().chain(args.iter());
Args::try_parse_from(args)
}
#[test]
fn cli_valid_arguments() {
let args: Args = parsed_args(vec!["bs7"]).unwrap();
assert_eq!(args.target, Target::Postcode("bs7".to_string()));
let args = parsed_args(vec!["13"]).unwrap();
assert_eq!(args.target, Target::Region(Region::London));
let args = parsed_args(vec!["--start-date", "2024-05-06", "BS7"]).unwrap();
assert_eq!(args.start_date, Some("2024-05-06".to_string()));
assert_eq!(args.target, Target::Postcode("BS7".to_string()));
let args = parsed_args(vec!["--start-date", "2024-05-06", "16"]).unwrap();
assert_eq!(args.start_date, Some("2024-05-06".to_string()));
assert_eq!(args.target, Target::Region(Region::Scotland));
let args = parsed_args(vec![
"--start-date",
"2024-05-06",
"--end-date",
"2024-07-08",
"BS7",
])
.unwrap();
assert_eq!(args.start_date, Some("2024-05-06".to_string()));
assert_eq!(args.end_date, Some("2024-07-08".to_string()));
assert_eq!(args.target, Target::Postcode("BS7".to_string()));
parsed_args(vec!["-s 2024-05-06", "-e 2024-05-06", "BS7"]).unwrap();
parsed_args(vec!["-s 2024-05-06", "BS7"]).unwrap();
parsed_args(vec!["-e 2024-05-06", "BS7"]).unwrap();
}
}