use std::collections::{HashMap, HashSet}; use gtfs_structures::{Agency, Calendar, CalendarDate, RawStopTime, RawTrip, Route, Stop}; use log::error; use serde::{Serialize, Deserialize}; use serde_json::value; use zip::result::ZipError; #[derive(Debug)] pub struct Error { pub(crate) _message: String, } impl From for Error { fn from(value: std::io::Error) -> Self { return Error { _message: value.to_string() } } } impl From for Error { fn from(value: reqwest::Error) -> Self { return Error { _message: value.to_string() } } } impl From for Error { fn from(value: ZipError) -> Self { return Error { _message: value.to_string() } } } impl From for Error { fn from(value: serde_json::Error) -> Self { return Error { _message: value.to_string() } } } // This is to store the preferences for the GTFS(-R) side of the code. #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct Preferences { #[serde(rename = "routes")] pub route_numbers: HashSet, #[serde(rename = "stops")] pub stop_codes: HashSet, #[serde(rename = "data-folder")] pub data_folder: String, #[serde(rename = "gtfs-url")] pub gtfs_url: String, #[serde(rename = "realtime-url")] pub realtime_url: String, #[serde(rename = "realtime-api-key")] pub realtime_api_key: String, #[serde(rename = "refresh-seconds")] pub refresh_seconds: u64, } // Utility functions impl Preferences { pub fn gtfs_file_name(&self) -> Result { let file_name_part = self.gtfs_url.split("/").last(); if file_name_part.is_none() { error!("The config for gtfs-url is not a valid URL: {}", self.gtfs_url); return Err(Error {_message: String::from("Failed to refresh GTFS data")}); } return Ok(String::from(file_name_part.unwrap())); } pub fn gtfs_file_path(&self) -> Result { return Ok(format!("{}/{}", self.data_folder, self.gtfs_file_name()?)); } } // The main GTFS struct. This is similar to (but not exactly) gtfs-structures::Gtfs because we don't need everything #[derive(Debug)] pub struct Gtfs<'a> { /// A copy of the preferences struct pub(crate) preferences: &'a Preferences, /// All agencies. They can not be read by `agency_id`, as it is not a required field pub(crate) agencies: Vec, /// All Calendar by `service_id` pub(crate) calendar: HashMap, /// All calendar dates grouped by service_id pub(crate) calendar_dates: HashMap>, /// All routes by `route_id` pub(crate) routes: HashMap, /// All stop by `stop_id`. pub(crate) stops: HashMap, /// All trips by trip_id pub(crate) trips: HashMap, /// Stop times for the chosen stops and the chosen routes pub(crate) stop_times: HashMap<(String, u32), RawStopTime>, } #[derive(Debug)] pub struct Arrival<'a> { pub departure_time: u32, pub route: &'a Route, pub stop: &'a Stop, pub stop_time: &'a RawStopTime, pub trip: &'a RawTrip, }