diff options
author | stuebinm | 2022-02-09 02:51:59 +0100 |
---|---|---|
committer | stuebinm | 2022-02-09 02:51:59 +0100 |
commit | cd13c85c69cf761b2da84ad91af64d23a3568aa5 (patch) | |
tree | 4cbdbf6f348508ad7f70aa11450dccc8148ae0cb /src/onboard/mod.rs | |
parent | cf88935b5245daea51d2b513709b61a0e43483d6 (diff) |
existential types in rust are weird
… lots and lots of traits …
Diffstat (limited to '')
-rw-r--r-- | src/onboard/mod.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/onboard/mod.rs b/src/onboard/mod.rs new file mode 100644 index 0000000..56bd144 --- /dev/null +++ b/src/onboard/mod.rs @@ -0,0 +1,76 @@ +use crate::traits::IsStation; +use crate::travelynx::TrainRef; +use serde::de::DeserializeOwned; + +pub mod iceportal; +pub mod zugportal; + +pub fn choose_api(name: &str) -> &dyn OnBoardAPI { + match name { + "iceportal" => &iceportal::Iceportal {} as &dyn OnBoardAPI, + "zugportal" => &zugportal::Zugportal {} as &dyn OnBoardAPI, + _ => panic!("no such API known") + } +} + +pub trait OnBoardAPI { + fn apiurl(&self) -> &'static str; + + fn request( + &self, + debug: bool + ) -> Result<Box<dyn OnBoardInfo>, serde_json::Error>; +} + +pub fn request<Api, I>( + api: &Api, + debug: bool +) -> Result<Box<dyn OnBoardInfo>, serde_json::Error> +where + Api: OnBoardAPI, + I: OnBoardInfo + DeserializeOwned + 'static +{ + let url: &'static str = api.apiurl(); + match get_request::<I>(url) { + Ok(resp) => Ok(Box::new(resp)), + Err((err, resp)) => { + if debug { + eprintln!("{:?}\n\nError was:{:?}", resp, err); + } + Err(err) + } + } +} + +pub trait OnBoardInfo { + fn guess_last_station(&self) -> Option<&dyn IsStation>; + + fn get_train_ref(&self) -> TrainRef; + + fn stops<'a>( + &'a self + ) -> Box<dyn std::iter::Iterator<Item = &'a dyn IsStation> + 'a>; +} + +fn get_request<R>(uri: &str) -> Result<R, (serde_json::Error, String)> +where + R: serde::de::DeserializeOwned +{ + let resp: String = ureq::get(uri) + .call() + .unwrap_or_else(|err| exit_err(&err.to_string(), "get request failed")) + .into_string() + .unwrap_or_else(|err| { + exit_err(&err.to_string(), "get request response failed") + }); + + match serde_json::from_str::<R>(&resp) { + Ok(obj) => Ok(obj), + Err(err) => Err((err, resp)) + } +} + +fn exit_err(msg: &str, scope: &str) -> ! { + eprintln!("{}: {}", scope, msg); + std::process::exit(1) +} |