diff --git a/Cargo.lock b/Cargo.lock index 74bcadc..8667961 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1236,21 +1236,9 @@ dependencies = [ "mio", "pin-project-lite", "socket2", - "tokio-macros", "windows-sys 0.61.2", ] -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tokio-native-tls" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 168b50b..bb19b10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,4 +34,4 @@ reqwest = "0.12" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" smol_str = { version = "0.3", features = ["serde"] } -tokio = { version = "1.48", features = ["macros"] } +tokio = "1.48" diff --git a/src/caching/cache.rs b/src/caching/cache.rs index c28bfba..3698659 100644 --- a/src/caching/cache.rs +++ b/src/caching/cache.rs @@ -3,8 +3,8 @@ use std::io::{BufReader, BufWriter}; use std::path::{Path, PathBuf}; use super::CacheLine; -use crate::os::Os; use crate::View; +use crate::os::Os; #[derive(Debug)] pub struct Cache { diff --git a/src/caching/cache_line.rs b/src/caching/cache_line.rs index 69f20e9..5df39db 100644 --- a/src/caching/cache_line.rs +++ b/src/caching/cache_line.rs @@ -4,8 +4,8 @@ use chrono::serde::ts_seconds; use chrono::{DateTime, Datelike, FixedOffset, Local, NaiveDate, TimeDelta, Utc, Weekday}; use serde::{Deserialize, Serialize}; -use crate::models::ExchangeRateResult; use crate::Hollidays; +use crate::models::ExchangeRateResult; const CET: FixedOffset = unsafe { FixedOffset::east_opt(3600).unwrap_unchecked() }; diff --git a/src/main.rs b/src/main.rs index 3f6fc8b..c327bf1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use clap::Parser as _; use ecb_rates::caching::{Cache, CacheLine}; use ecb_rates::HeaderDescription; @@ -17,22 +18,40 @@ async fn get_and_parse(url: impl IntoUrl) -> anyhow::Result ExitCode { - let mut cli = Cli::parse(); +fn main() -> ExitCode { + let cli = Cli::parse(); + + let runtime = match tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + { + Ok(runtime) => runtime, + Err(e) => { + eprintln!("Failed to initialize asynchronous runtime: {:?}", e); + return ExitCode::FAILURE; + } + }; + + match runtime.block_on(async_main(cli)) { + Ok(_) => ExitCode::SUCCESS, + Err(e) => { + eprintln!("Fatal: {:?}", e); + ExitCode::FAILURE + } + } +} + +async fn async_main(mut cli: Cli) -> anyhow::Result<()> { if cli.force_color { colored::control::set_override(true); } let mut header_description = HeaderDescription::new(); let use_cache = !cli.no_cache; - let view = match cli.show_days.to_view() { - Some(v) => v, - None => { - eprintln!("It doesn't make any sence to fetch 0 days right?"); - return ExitCode::SUCCESS; - } - }; + let view = cli + .show_days + .to_view() + .context("It doesn't make any sence to fetch 0 days right?")?; let mut cache = if use_cache { Cache::load(&view) } else { None }; let cache_ok = cache.as_ref().map_or_else( || false, @@ -48,14 +67,9 @@ async fn main() -> ExitCode { .exchange_rate_results .clone() } else { - let parsed = match get_and_parse(view.to_ecb_url()).await { - Ok(k) => k, - Err(e) => { - eprintln!("Failed to get/parse data from ECB: {}", e); - return ExitCode::FAILURE; - } - }; - + let parsed = get_and_parse(view.to_ecb_url()) + .await + .context("Failed to get/parse data from ECB")?; if !cache_ok { let not_equal_cache = cache.as_ref().map_or_else( || true, @@ -66,14 +80,11 @@ async fn main() -> ExitCode { }, ); - if not_equal_cache - && let Some(cache_safe) = cache.as_mut() { - let cache_line = CacheLine::new(parsed.clone()); - cache_safe.set_cache_line(cache_line); - if let Err(e) = cache_safe.save() { - eprintln!("Failed to save to cache with: {:?}", e); - } - } + if not_equal_cache && let Some(cache_safe) = cache.as_mut() { + let cache_line = CacheLine::new(parsed.clone()); + cache_safe.set_cache_line(cache_line); + cache_safe.save()?; + } } parsed }; @@ -81,11 +92,8 @@ async fn main() -> ExitCode { cli.perspective = cli.perspective.map(|s| s.to_uppercase_smolstr()); if let Some(currency) = cli.perspective.as_ref() { header_description.replace_eur(currency); - let error_occured = change_perspective(&mut parsed, currency).is_none(); - if error_occured { - eprintln!("The currency wasn't in the data from the ECB!"); - return ExitCode::FAILURE; - } + change_perspective(&mut parsed, currency) + .context("The currency wasn't in the data from the ECB!")?; } if cli.should_invert { @@ -160,5 +168,5 @@ async fn main() -> ExitCode { }; println!("{}", &output); - ExitCode::SUCCESS + Ok(()) } diff --git a/src/parsing.rs b/src/parsing.rs index 2e0e361..2ed0bab 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; -use quick_xml::events::Event; use quick_xml::Reader; +use quick_xml::events::Event; use smol_str::SmolStr; use crate::models::ExchangeRateResult; @@ -68,11 +68,10 @@ pub fn parse(xml: &str) -> anyhow::Result> { *inside_cube_time = true; } - if *inside_cube_time - && let (Some(c), Some(r_str)) = (currency_attr, rate_attr) { - let r = r_str.parse::()?; - current_rates.insert(c, r); - } + if *inside_cube_time && let (Some(c), Some(r_str)) = (currency_attr, rate_attr) { + let r = r_str.parse::()?; + current_rates.insert(c, r); + } Ok(()) } diff --git a/src/table/table_owned.rs b/src/table/table_owned.rs index 0f0abd7..6a01328 100644 --- a/src/table/table_owned.rs +++ b/src/table/table_owned.rs @@ -2,9 +2,9 @@ use std::fmt::Display; use smol_str::SmolStr; +use crate::DEFAULT_WIDTH; use crate::cli::SortBy; use crate::models::ExchangeRateResult; -use crate::DEFAULT_WIDTH; use super::table_display::helper_table_print; use super::{TableGet, TableTrait}; diff --git a/src/table/table_ref.rs b/src/table/table_ref.rs index 7f49ac8..118e4a3 100644 --- a/src/table/table_ref.rs +++ b/src/table/table_ref.rs @@ -1,13 +1,13 @@ use std::fmt::Display; +use crate::DEFAULT_WIDTH; use crate::cli::SortBy; use crate::models::ExchangeRateResult; -use crate::DEFAULT_WIDTH; +use super::Table; use super::table_display::helper_table_print; use super::table_getter::TableGet; use super::table_trait::TableTrait; -use super::Table; pub struct TableRef<'a> { header: Option<&'a str>,