hafas_rs/
types.rs

1use std::borrow::Cow;
2
3use chrono::DateTime;
4use chrono::Duration;
5use chrono::FixedOffset;
6#[cfg(feature = "polylines")]
7use geojson::FeatureCollection;
8use serde::{Deserialize, Serialize};
9
10/* Types */
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(untagged)]
14pub enum Location {
15    Address {
16        address: String,
17        latitude: f32,
18        longitude: f32,
19    },
20    Point {
21        #[serde(skip_serializing_if = "Option::is_none")]
22        id: Option<String>,
23        #[serde(skip_serializing_if = "Option::is_none")]
24        name: Option<String>,
25        #[serde(skip_serializing_if = "Option::is_none")]
26        poi: Option<bool>,
27        latitude: f32,
28        longitude: f32,
29    },
30}
31
32impl PartialEq for Location {
33    fn eq(&self, other: &Self) -> bool {
34        match (&self, other) {
35            (Location::Address {
36                address: a,
37                ..
38            }, Location::Address {
39                address: b,
40                ..
41            }) => {
42                a == b
43            }
44            (Location::Point {
45                id: Some(a),
46                ..
47            }, Location::Point {
48                id: Some(b),
49                ..
50            }) => {
51                a == b
52            }
53            (_, _) => false,
54        }
55    }
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
59#[serde(tag = "type")]
60#[serde(rename_all = "lowercase")]
61pub enum Place {
62    Stop(Stop),
63    Location(Location),
64}
65
66/*#[derive(Debug, Clone, Serialize)]
67pub struct Station {
68    pub id: u64,
69    pub name: String,
70    pub coordinates: Coordinates,
71    pub products: Products,
72}*/
73
74#[derive(Debug, Default, Clone, Serialize, Deserialize)]
75pub struct Stop {
76    pub id: String,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub name: Option<String>,
79    pub location: Option<Location>,
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub products: Option<Vec<Product>>,
82    //station: Option<Station>,
83}
84
85impl PartialEq for Stop {
86    fn eq(&self, other: &Self) -> bool {
87        self.id == other.id
88    }
89}
90
91// None means true
92// TODO: What to do with the new products for other providers?
93#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
94#[serde(rename_all = "camelCase")]
95pub struct ProductsSelection {
96    pub national_express: Option<bool>,
97    pub national: Option<bool>,
98    pub regional_exp: Option<bool>,
99    pub regional: Option<bool>,
100    pub suburban: Option<bool>,
101    pub bus: Option<bool>,
102    pub ferry: Option<bool>,
103    pub subway: Option<bool>,
104    pub tram: Option<bool>,
105    pub taxi: Option<bool>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
109#[serde(rename_all = "camelCase")]
110pub struct Product {
111    pub id: Cow<'static, str>,
112    pub mode: Mode,
113    pub bitmasks: Cow<'static, [u16]>,
114    pub name: Cow<'static, str>,
115    pub short: Cow<'static, str>,
116    // TODO: default?
117}
118
119#[derive(Serialize, Debug, Clone, Deserialize, PartialEq, Eq)]
120#[serde(rename_all = "lowercase")]
121pub enum Mode {
122    Train,
123    Bus,
124    Watercraft,
125    Taxi,
126    Walking,
127    Gondola,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
131pub enum LoyaltyCard {
132    BahnCard25Class1,
133    BahnCard25Class2,
134    BahnCard50Class1,
135    BahnCard50Class2,
136    Vorteilscard,
137    HalbtaxaboRailplus,
138    Halbtaxabo,
139    VoordeelurenaboRailplus,
140    Voordeelurenabo,
141    SHCard,
142    Generalabonnement,
143}
144
145impl LoyaltyCard {
146    /// See https://gist.github.com/juliuste/202bb04f450a79f8fa12a2ec3abcd72d
147    pub fn from_id(value: u8) -> Option<Self> {
148        match value {
149            1 => Some(LoyaltyCard::BahnCard25Class1),
150            2 => Some(LoyaltyCard::BahnCard25Class2),
151            3 => Some(LoyaltyCard::BahnCard50Class1),
152            4 => Some(LoyaltyCard::BahnCard50Class2),
153            9 => Some(LoyaltyCard::Vorteilscard),
154            10 => Some(LoyaltyCard::HalbtaxaboRailplus),
155            11 => Some(LoyaltyCard::Halbtaxabo),
156            12 => Some(LoyaltyCard::VoordeelurenaboRailplus),
157            13 => Some(LoyaltyCard::Voordeelurenabo),
158            14 => Some(LoyaltyCard::SHCard),
159            15 => Some(LoyaltyCard::Generalabonnement),
160            _ => None,
161        }
162    }
163
164    pub fn to_id(self) -> u8 {
165        match self {
166            LoyaltyCard::BahnCard25Class1 => 1,
167            LoyaltyCard::BahnCard25Class2 => 2,
168            LoyaltyCard::BahnCard50Class1 => 3,
169            LoyaltyCard::BahnCard50Class2 => 4,
170            LoyaltyCard::Vorteilscard => 9,
171            LoyaltyCard::HalbtaxaboRailplus => 10,
172            LoyaltyCard::Halbtaxabo => 11,
173            LoyaltyCard::VoordeelurenaboRailplus => 12,
174            LoyaltyCard::Voordeelurenabo => 13,
175            LoyaltyCard::SHCard => 14,
176            LoyaltyCard::Generalabonnement => 15,
177        }
178    }
179}
180
181#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
182pub enum TariffClass {
183    First,
184    Second,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
188#[serde(rename_all = "lowercase")]
189pub enum Accessibility {
190    r#None,
191    Partial,
192    Complete,
193}
194
195#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
196#[serde(rename_all = "kebab-case")]
197pub enum LoadFactor {
198    LowToMedium,
199    High,
200    VeryHigh,
201    ExceptionallyHigh,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
205#[serde(rename_all = "camelCase")]
206pub struct Line {
207    pub name: Option<String>,
208    pub fahrt_nr: Option<String>,
209    pub mode: Mode,
210    pub product: Product,
211    pub operator: Option<Operator>,
212    pub product_name: Option<String>,
213}
214
215#[derive(Debug, Serialize, Clone, Deserialize, PartialEq)]
216#[serde(rename_all = "camelCase")]
217pub struct Frequency {
218    #[serde(with = "crate::serialize::duration")]
219    pub minimum: Option<Duration>,
220    #[serde(with = "crate::serialize::duration")]
221    pub maximum: Option<Duration>,
222    pub iterations: Option<u64>,
223}
224
225#[derive(Debug, Serialize, Clone, Deserialize, PartialEq)]
226#[serde(rename_all = "camelCase")]
227pub struct Leg {
228    pub origin: Place,
229    pub destination: Place,
230    pub departure: Option<DateTime<FixedOffset>>,
231    pub planned_departure: Option<DateTime<FixedOffset>>,
232    pub departure_delay: Option<i64>,
233    pub arrival: Option<DateTime<FixedOffset>>,
234    pub planned_arrival: Option<DateTime<FixedOffset>>,
235    pub arrival_delay: Option<i64>,
236    #[serde(skip_serializing_if = "Option::is_none")]
237    pub reachable: Option<bool>,
238    pub trip_id: Option<String>,
239    pub line: Option<Line>,
240    pub direction: Option<String>,
241    //current_location,
242    pub arrival_platform: Option<String>,
243    pub planned_arrival_platform: Option<String>,
244    pub departure_platform: Option<String>,
245    pub planned_departure_platform: Option<String>,
246    pub frequency: Option<Frequency>,
247    #[serde(skip_serializing_if = "Option::is_none")]
248    pub cancelled: Option<bool>,
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub stopovers: Option<Vec<Stopover>>,
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub load_factor: Option<LoadFactor>,
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub remarks: Option<Vec<Remark>>,
255    #[cfg(feature = "polylines")]
256    #[serde(skip_serializing_if = "Option::is_none")]
257    pub polyline: Option<FeatureCollection>,
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub walking: Option<bool>,
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub transfer: Option<bool>,
262    #[serde(skip_serializing_if = "Option::is_none")]
263    pub distance: Option<u64>,
264}
265
266#[derive(Debug, Serialize, Clone, Deserialize, PartialEq)]
267#[serde(rename_all = "camelCase")]
268pub struct Stopover {
269    pub stop: Place,
270    pub departure: Option<DateTime<FixedOffset>>,
271    pub planned_departure: Option<DateTime<FixedOffset>>,
272    pub departure_delay: Option<i64>,
273    pub arrival: Option<DateTime<FixedOffset>>,
274    pub planned_arrival: Option<DateTime<FixedOffset>>,
275    pub arrival_delay: Option<i64>,
276    pub arrival_platform: Option<String>,
277    pub planned_arrival_platform: Option<String>,
278    pub departure_platform: Option<String>,
279    pub planned_departure_platform: Option<String>,
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub cancelled: Option<bool>,
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub remarks: Option<Vec<Remark>>,
284}
285
286#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
287pub struct Price {
288    pub amount: f64,
289    pub currency: String,
290}
291
292#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
293#[serde(rename_all = "camelCase")]
294pub struct Journey {
295    #[serde(skip_serializing_if = "Option::is_none")]
296    pub refresh_token: Option<String>,
297    pub legs: Vec<Leg>,
298    pub price: Option<Price>,
299    //last_updated
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
303pub struct Operator {
304    pub id: String,
305    pub name: String,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
309#[serde(rename_all = "lowercase")]
310pub enum RemarkType {
311    Hint,
312    Status,
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
316pub struct Remark {
317    pub code: String,
318    pub text: String,
319    pub r#type: RemarkType,
320    #[serde(skip_serializing_if = "Option::is_none")]
321    pub summary: Option<String>,
322    #[serde(skip_serializing_if = "Option::is_none")]
323    pub trip_id: Option<String>,
324}