numbat-exchange-rates-0.4.0/.cargo_vcs_info.json0000644000000001630000000000100152170ustar { "git": { "sha1": "bbb855bc9bf1f01c8d99861f5b828043e21f799a" }, "path_in_vcs": "numbat-exchange-rates" }numbat-exchange-rates-0.4.0/Cargo.toml0000644000000017010000000000100132140ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.70" name = "numbat-exchange-rates" version = "0.4.0" authors = ["David Peter "] description = "A library to fetch and parse currency exchange rates from the ECB" homepage = "https://numbat.dev/" license = "MIT OR Apache-2.0" repository = "https://github.com/sharkdp/numbat" [dependencies.attohttpc] version = "0.26.0" features = ["tls-rustls-webpki-roots"] default-features = false [dependencies.quick-xml] version = "0.31.0" numbat-exchange-rates-0.4.0/Cargo.toml.orig000064400000000000000000000007361046102023000167040ustar 00000000000000[package] name = "numbat-exchange-rates" description = "A library to fetch and parse currency exchange rates from the ECB" authors = ["David Peter "] homepage = "https://numbat.dev/" repository = "https://github.com/sharkdp/numbat" version = "0.4.0" edition = "2021" license = "MIT OR Apache-2.0" rust-version = "1.70" [dependencies] attohttpc = { version = "0.26.0", default-features = false, features = ["tls-rustls-webpki-roots"] } quick-xml = "0.31.0" numbat-exchange-rates-0.4.0/src/lib.rs000064400000000000000000000026451046102023000157210ustar 00000000000000use std::collections::HashMap; use quick_xml::events::Event; use quick_xml::reader::Reader; pub type ExchangeRates = HashMap; pub fn parse_exchange_rates(xml_content: &str) -> Option { let mut rates = ExchangeRates::default(); let mut reader = Reader::from_str(&xml_content); loop { match reader.read_event().ok()? { Event::Eof => break, Event::Empty(e) => { if e.local_name().as_ref() != b"Cube" { continue; } let currency = &e .try_get_attribute("currency") .ok()?? .unescape_value() .ok()?; let rate = &e.try_get_attribute("rate").ok()??.unescape_value().ok()?; let rate = rate.parse().ok()?; rates.insert(currency.to_string(), rate); } _ => {} } } Some(rates) } const ECB_XML_URL: &str = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; fn fetch_ecb_xml() -> Option { attohttpc::get(ECB_XML_URL).send().ok()?.text().ok() } pub fn fetch_exchange_rates() -> Option { let xml_content = fetch_ecb_xml()?; parse_exchange_rates(&xml_content) } #[cfg(test)] mod tests { use super::*; #[test] fn fetch_exchange_rates_works() { fetch_exchange_rates(); } }