summaryrefslogtreecommitdiff
path: root/src/onboard/mod.rs
diff options
context:
space:
mode:
authorstuebinm2022-02-09 02:51:59 +0100
committerstuebinm2022-02-09 02:51:59 +0100
commitcd13c85c69cf761b2da84ad91af64d23a3568aa5 (patch)
tree4cbdbf6f348508ad7f70aa11450dccc8148ae0cb /src/onboard/mod.rs
parentcf88935b5245daea51d2b513709b61a0e43483d6 (diff)
existential types in rust are weird
… lots and lots of traits …
Diffstat (limited to '')
-rw-r--r--src/onboard/mod.rs76
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)
+}