add response structs

This commit is contained in:
Dr. Matthias Ratajczak
2022-12-22 15:15:03 +01:00
parent 236ea12e95
commit daed8fee58
4 changed files with 313 additions and 4 deletions
+99
View File
@@ -0,0 +1,99 @@
#![allow(dead_code)]
use std::fmt::Debug;
use anyhow::Result;
use chrono::{DateTime, Local, TimeZone, Utc};
use serde::{de, Deserialize, Deserializer};
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Departure {
id: String,
dl_id: String,
line_name: String,
direction: String,
platform: Platform,
mot: String,
#[serde(default, deserialize_with = "deserialize_realtime")]
real_time: Option<DateTime<Local>>,
#[serde(deserialize_with = "deserialize_timestamp")]
scheduled_time: DateTime<Local>,
state: Option<String>,
route_changes: Vec<RouteChange>,
diva: Diva,
cancel_reasons: Vec<CancelReason>,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Platform {
name: String,
#[serde(rename = "Type")]
type_: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct RouteChange {
// fields omitted
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Diva {
number: String,
network: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct CancelReason {
// fields omitted
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Response {
name: String,
status: Status,
place: String,
expiration_time: String,
departures: Vec<Departure>,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Status {
code: String,
}
/// Deserialize a timestamp in the form of '/Date(1671713820000-0000)/'
fn deserialize_timestamp<'de, D>(deserializer: D) -> Result<DateTime<Local>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let timestamp: i64 = s
.trim_start_matches("/Date(")
.trim_end_matches(")/")
.split('-')
.next()
.ok_or_else(|| de::Error::custom("Invalid timestamp format"))?
.parse()
.map_err(de::Error::custom)?;
let result = Utc.timestamp_millis_opt(timestamp).unwrap();
let local_tz = chrono::offset::Local::now().timezone();
Ok(result.with_timezone(&local_tz))
}
fn deserialize_realtime<'de, D>(deserializer: D) -> Result<Option<DateTime<Local>>, D::Error>
where
D: Deserializer<'de>,
{
match deserialize_timestamp(deserializer) {
Ok(inner) => Ok(Some(inner)),
Err(_) => Ok(None),
}
}