use std::{collections::HashMap, fmt};
use chrono::{DateTime, FixedOffset};
use serde::{de, Deserialize};
pub type TrainResponse = HashMap<String, Vec<Train>>;
#[derive(Debug, Clone)]
pub(crate) struct TrainResponseWrapper(
pub(crate) TrainResponse,
);
impl<'de> Deserialize<'de> for TrainResponseWrapper {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_any(TrainResponseWrapperVisitor)
}
}
struct TrainResponseWrapperVisitor;
impl<'de> de::Visitor<'de> for TrainResponseWrapperVisitor {
type Value = TrainResponseWrapper;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a HashMap or an empty array")
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
Ok(TrainResponseWrapper(Deserialize::deserialize(
de::value::MapAccessDeserializer::new(map),
)?))
}
fn visit_seq<A>(self, _seq: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
Ok(TrainResponseWrapper(HashMap::new()))
}
}
#[derive(Debug, Deserialize, Clone)]
pub struct Train {
#[serde(rename = "routeName")]
pub route_name: String,
#[serde(rename = "trainNum")]
pub train_num: String,
#[serde(rename = "trainID")]
pub train_id: String,
pub lat: f64,
pub lon: f64,
#[serde(rename = "trainTimely")]
pub train_timely: String,
pub stations: Vec<TrainStation>,
pub heading: Heading,
#[serde(rename = "eventCode")]
pub event_code: String,
#[serde(rename = "eventTZ")]
pub event_tz: Option<String>,
#[serde(rename = "eventName")]
pub event_name: Option<String>,
#[serde(rename = "origCode")]
pub origin_code: String,
#[serde(rename = "originTZ")]
pub origin_tz: String,
#[serde(rename = "origName")]
pub origin_name: String,
#[serde(rename = "destCode")]
pub destination_code: String,
#[serde(rename = "destTZ")]
pub destination_tz: String,
#[serde(rename = "destName")]
pub destination_name: String,
#[serde(rename = "trainState")]
pub train_state: TrainState,
pub velocity: f32,
#[serde(rename = "statusMsg")]
pub status_message: String,
#[serde(rename = "createdAt")]
pub created_at: DateTime<FixedOffset>,
#[serde(rename = "updatedAt")]
pub updated_at: DateTime<FixedOffset>,
#[serde(rename = "lastValTS")]
pub last_value: DateTime<FixedOffset>,
#[serde(rename = "objectID")]
pub object_id: u32,
}
#[derive(Debug, Deserialize, Clone)]
pub struct TrainStation {
pub name: String,
pub code: String,
pub tz: String,
pub bus: bool,
#[serde(rename = "schArr")]
pub schedule_arrival: DateTime<FixedOffset>,
#[serde(rename = "schDep")]
pub schedule_departure: DateTime<FixedOffset>,
#[serde(rename = "arr", default)]
pub arrival: Option<DateTime<FixedOffset>>,
#[serde(rename = "dep", default)]
pub departure: Option<DateTime<FixedOffset>>,
#[serde(rename = "arrCmnt")]
pub arrival_comment: String,
#[serde(rename = "depCmnt")]
pub departure_comment: String,
pub status: TrainStatus,
}
#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)]
pub enum Heading {
N,
NE,
E,
SE,
S,
SW,
W,
NW,
}
#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)]
pub enum TrainStatus {
Enroute,
Station,
Departed,
Unknown,
}
#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)]
pub enum TrainState {
Predeparture,
Active,
Completed,
}
pub type StationResponse = HashMap<String, Station>;
#[derive(Debug, Clone)]
pub(crate) struct StationResponseWrapper(
pub(crate) HashMap<String, Station>,
);
impl<'de> Deserialize<'de> for StationResponseWrapper {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_any(StationResponseWrapperVisitor)
}
}
struct StationResponseWrapperVisitor;
impl<'de> de::Visitor<'de> for StationResponseWrapperVisitor {
type Value = StationResponseWrapper;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a HashMap or an empty array")
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
Ok(StationResponseWrapper(Deserialize::deserialize(
de::value::MapAccessDeserializer::new(map),
)?))
}
fn visit_seq<A>(self, _seq: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
Ok(StationResponseWrapper(HashMap::new()))
}
}
#[derive(Debug, Deserialize, Clone)]
pub struct Station {
#[serde(default)]
pub name: String,
pub code: String,
#[serde(default)]
pub tz: String,
pub lat: f64,
pub lon: f64,
pub address1: String,
pub address2: String,
pub city: String,
pub state: String,
pub zip: u32,
pub trains: Vec<String>,
}