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, serde_json::Error>; } pub fn request( api: &Api, debug: bool ) -> Result, serde_json::Error> where Api: OnBoardAPI, I: OnBoardInfo + DeserializeOwned + 'static { let url: &'static str = api.apiurl(); match get_request::(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 + 'a>; } fn get_request(uri: &str) -> Result 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::(&resp) { Ok(obj) => Ok(obj), Err(err) => Err((err, resp)) } } fn exit_err(msg: &str, scope: &str) -> ! { eprintln!("{}: {}", scope, msg); std::process::exit(1) }