mirror of
https://github.com/tiffany352/rink-rs
synced 2024-11-10 05:34:14 +00:00
Download and keep updated currency conversions
This commit is contained in:
parent
19214ae156
commit
471d70c3a8
4 changed files with 95 additions and 2 deletions
|
@ -10,11 +10,12 @@ license = "MPL-2.0"
|
|||
keywords = ["unit", "math", "conversion", "cli", "tool"]
|
||||
|
||||
[features]
|
||||
default = ["linefeed", "chrono-humanize", "gpl"]
|
||||
default = ["linefeed", "chrono-humanize", "gpl", "currency"]
|
||||
ircbot = ["irc", "glob"]
|
||||
web = ["hyper", "url", "sandbox"]
|
||||
sandbox = ["libc", "ipc-channel"]
|
||||
gpl = []
|
||||
currency = ["hyper", "xml-rs"]
|
||||
|
||||
[dependencies]
|
||||
rust-gmp = "0.3.2"
|
||||
|
@ -28,6 +29,7 @@ hyper = { version = "0.9.10", optional = true }
|
|||
url = { version = "1.2.0", optional = true }
|
||||
libc = { version = "0.2.14", optional = true }
|
||||
ipc-channel = { version = "0.5.1", optional = true }
|
||||
xml-rs = { version = "0.3.4", optional = true }
|
||||
|
||||
[[bin]]
|
||||
name = "rink"
|
||||
|
|
|
@ -531,6 +531,7 @@ specific_volume ? volume / mass
|
|||
spin ? mass area / time
|
||||
surface_tension ? energy / area
|
||||
fuel_efficiency ? area^-1
|
||||
specific_energy ? energy / mass
|
||||
|
||||
|
||||
#
|
||||
|
@ -4886,7 +4887,7 @@ Ci curie # emitted by the amount of radon that is
|
|||
# in equilibrium with 1 gram of radium.
|
||||
rutherford 1e6 Bq #
|
||||
|
||||
radiation_dose ? gray
|
||||
radiation_dose gray
|
||||
gray J/kg # Absorbed dose of radiation
|
||||
Gy gray #
|
||||
rad 1e-2 Gy # From Radiation Absorbed Dose
|
||||
|
|
64
src/currency.rs
Normal file
64
src/currency.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use std::fs::File;
|
||||
use std::time::{SystemTime, Duration};
|
||||
use std::fmt::Display;
|
||||
use hyper::Client;
|
||||
use hyper::status::StatusCode;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::fs::create_dir_all;
|
||||
|
||||
static URL: &'static str = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
|
||||
|
||||
pub type Parsed = Vec<(String, f64)>;
|
||||
|
||||
pub fn parse(_f: File) -> Parsed {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn path() -> Result<PathBuf, String> {
|
||||
let mut path = try!(::config_dir());
|
||||
path.push("rink/currency.xml");
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn download() -> Result<(), String> {
|
||||
try!(create_dir_all(try!(path()).parent().unwrap()).map_err(|x| format!("{}", x)));
|
||||
let mut f = try!(File::create(try!(path())).map_err(|x| format!("{}", x)));
|
||||
|
||||
let client = Client::new();
|
||||
let mut res = try!(client.get(URL).send().map_err(|x| format!("{}", x)));
|
||||
if res.status != StatusCode::Ok {
|
||||
return Err(format!("Request failed with status code {}", res.status))
|
||||
}
|
||||
let mut buf = vec![0; 8192];
|
||||
loop {
|
||||
match res.read(&mut buf) {
|
||||
Ok(0) => break,
|
||||
Ok(n) => {
|
||||
try!(f.write(&buf[..n]).map_err(|x| format!("{}", x)));
|
||||
},
|
||||
Err(e) => return Err(format!("{}", e))
|
||||
}
|
||||
}
|
||||
try!(f.sync_all().map_err(|x| format!("{}", x)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open() -> Result<Parsed, String> {
|
||||
fn ts<T:Display>(x: T) -> String {
|
||||
format!("{}", x)
|
||||
}
|
||||
let f = try!(File::open(try!(path())).map_err(ts));
|
||||
let stats = try!(f.metadata().map_err(ts));
|
||||
let mtime = try!(stats.modified().map_err(ts));
|
||||
let now = SystemTime::now();
|
||||
let elapsed = try!(now.duration_since(mtime).map_err(ts));
|
||||
if elapsed > Duration::from_secs(23*60*60) {
|
||||
return Err(format!("File is out of date"))
|
||||
}
|
||||
Ok(parse(f))
|
||||
}
|
||||
|
||||
pub fn load() -> Result<Parsed, String> {
|
||||
open().or_else(|_| download().and_then(|()| open()))
|
||||
}
|
26
src/lib.rs
26
src/lib.rs
|
@ -39,6 +39,10 @@ extern crate chrono_humanize;
|
|||
extern crate libc;
|
||||
#[cfg(feature = "sandbox")]
|
||||
extern crate ipc_channel;
|
||||
#[cfg(feature = "currency")]
|
||||
extern crate hyper;
|
||||
#[cfg(feature = "currency")]
|
||||
extern crate xml;
|
||||
|
||||
pub mod text_query;
|
||||
pub mod eval;
|
||||
|
@ -49,6 +53,8 @@ pub mod gnu_units;
|
|||
pub mod ast;
|
||||
pub mod value;
|
||||
pub mod reply;
|
||||
#[cfg(feature = "currency")]
|
||||
pub mod currency;
|
||||
|
||||
pub use number::Number;
|
||||
pub use eval::Context;
|
||||
|
@ -93,6 +99,20 @@ fn config_dir() -> Result<PathBuf, String> {
|
|||
.map(|mut x: PathBuf| { x.push("Library/Application Support"); x})
|
||||
}
|
||||
|
||||
#[cfg(feature = "currency")]
|
||||
fn load_currency() -> Option<Result<ast::Defs, String>> {
|
||||
let res = match currency::load() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Some(Err(e))
|
||||
};
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "currency"))]
|
||||
fn load_currency() -> Option<Result<ast::Defs, String>> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpl")]
|
||||
static DEFAULT_FILE: Option<&'static str> = Some(include_str!("../definitions.units"));
|
||||
#[cfg(not(feature = "gpl"))]
|
||||
|
@ -138,10 +158,16 @@ pub fn load() -> Result<Context, String> {
|
|||
let mut iter = gnu_units::TokenIterator::new(&*units).peekable();
|
||||
let units = gnu_units::parse(&mut iter);
|
||||
let dates = date::parse_datefile(&*dates);
|
||||
let currency = load_currency();
|
||||
|
||||
let mut ctx = eval::Context::new();
|
||||
ctx.load(units);
|
||||
ctx.load_dates(dates);
|
||||
match currency {
|
||||
Some(Ok(currency)) => ctx.load(currency),
|
||||
Some(Err(e)) => println!("Failed to load currency data: {}", e),
|
||||
None => (),
|
||||
}
|
||||
Ok(ctx)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue