1use std::convert::TryInto;
4
5use serde::{Deserialize, Serialize};
6use serde_repr::{Deserialize_repr, Serialize_repr};
7
8#[derive(Debug, Serialize, Deserialize, Clone)]
9pub struct Entity {
10 pub id: String,
11 pub trip_update: Option<TripUpdate>,
12 pub vehicle: Option<VehiclePosition>,
13 #[serde(default)]
14 pub is_deleted: bool,
15 }
17
18#[derive(Debug, Serialize, Deserialize, Clone)]
19pub struct TripUpdate {
20 pub trip: TripDescriptor,
21 pub vehicle: Option<VehicleDescriptor>,
22 pub stop_time_update: Option<StopTimeUpdate>,
23 pub timestamp: Option<u64>,
24 pub delay: Option<i32>,
25}
26
27#[derive(Debug, Serialize, Deserialize, Clone)]
28pub struct StopTimeUpdate {
29 pub stop_sequence: Option<u32>,
30 pub stop_id: Option<String>,
31 pub arrival: Option<StopTimeEvent>,
32 pub departure: Option<StopTimeEvent>,
33 #[serde(default)]
34 pub schedule_relationship: ScheduleRelationship,
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone)]
38pub struct StopTimeEvent {
39 pub delay: Option<i32>,
40 pub time: Option<i64>,
41 pub uncertainty: Option<i32>,
42}
43
44#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, Copy)]
45#[repr(u8)]
46pub enum ScheduleRelationship {
47 Scheduled = 0,
48 Skipped = 1,
49 NoData = 2,
50}
51
52impl Default for ScheduleRelationship {
53 fn default() -> Self {
54 Self::Scheduled
55 }
56}
57
58#[derive(Debug, Serialize, Deserialize, Clone)]
59pub struct VehiclePosition {
60 pub trip: Option<TripDescriptor>,
61 pub vehicle: Option<VehicleDescriptor>,
62 pub position: Option<Position>,
63 pub current_stop_sequence: Option<u32>,
64 pub stop_id: Option<String>,
65 #[serde(default)]
66 pub current_status: VehicleStopStatus,
67 pub timestamp: Option<u64>,
68 pub congestion_level: Option<CongestionLevel>,
69 pub occupancy_status: Option<OccupancyStatus>,
70}
71
72#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, Copy)]
73#[repr(u8)]
74pub enum VehicleStopStatus {
75 IncomingAt = 0,
78
79 StoppedAt = 1,
81
82 InTransitTo = 2,
84}
85
86impl Default for VehicleStopStatus {
87 fn default() -> Self {
88 Self::InTransitTo
89 }
90}
91
92#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, Copy)]
93#[repr(u8)]
94pub enum CongestionLevel {
95 UnknownCongestionLevel = 0,
96 RunningSmoothly = 1,
97 StopAndGo = 2,
98 Congestion = 3,
99 SevereCongestion = 4,
100}
101
102#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, Copy)]
103#[repr(u8)]
104pub enum OccupancyStatus {
105 Empty = 0,
106 ManySeatsAvailable = 1,
107 FewSeatsAvailable = 2,
108 StandingRoomOnly = 3,
109 CrushedStandingRoomOnly = 4,
110 Full = 5,
111 NotAcceptingPassengers = 6,
112}
113
114#[derive(Debug, Serialize, Deserialize, Clone)]
115pub struct Position {
116 pub latitude: f32,
117 pub longitude: f32,
118 #[serde(default)]
119 #[serde(deserialize_with = "deserialize_bearing")]
120 pub bearing: Option<f32>,
121 pub odometer: Option<f64>,
122 pub speed: Option<f32>,
123}
124
125#[derive(Debug, Serialize, Deserialize, Clone)]
126pub struct TripDescriptor {
127 pub trip_id: Option<String>,
128 pub route_id: Option<String>,
129 pub direction_id: Option<u32>,
130 pub start_time: Option<String>,
131 pub start_date: Option<String>,
132 pub schedule_relationship: Option<ScheduleRelationshipTripDescriptor>,
133}
134
135#[derive(Debug, Serialize_repr, Deserialize_repr, Clone, Copy)]
136#[repr(u8)]
137pub enum ScheduleRelationshipTripDescriptor {
138 Scheduled = 0,
139 Added = 1,
140 Unscheduled = 2,
141 Cancelled = 3,
142}
143
144#[derive(Debug, Serialize, Deserialize, Clone)]
145pub struct VehicleDescriptor {
146 pub id: Option<String>,
147 pub label: Option<String>,
148 pub license_plate: Option<String>,
149}
150
151impl Entity {
152 pub fn trip_id(&self) -> Option<String> {
154 Self::substr_to_char(self.trip_update.as_ref()?.trip.trip_id.as_ref()?, '-')
155 }
156
157 pub fn route_id(&self) -> Option<String> {
159 Self::substr_to_char(self.trip_update.as_ref()?.trip.route_id.as_ref()?, '-')
160 }
161
162 pub fn stop_id(&self) -> Option<String> {
164 Self::substr_to_char(
165 self.trip_update
166 .as_ref()?
167 .stop_time_update
168 .as_ref()?
169 .stop_id
170 .as_ref()?,
171 '-',
172 )
173 }
174
175 #[inline]
176 fn substr_to_char<T: AsRef<str>>(str: T, c: char) -> Option<String> {
177 let str = str.as_ref();
178 Some(str.chars().take(str.find(c)?).collect())
179 }
180}
181
182pub fn deserialize_bearing<'de, D>(deserializer: D) -> std::result::Result<Option<f32>, D::Error>
186where
187 D: serde::Deserializer<'de>,
188{
189 struct Bearing;
190
191 impl<'de> serde::de::Visitor<'de> for Bearing {
192 type Value = f32;
193
194 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
195 formatter.write_str("float, integer or string")
196 }
197
198 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
199 where
200 E: serde::de::Error,
201 {
202 v.parse().map_err(serde::de::Error::custom)
203 }
204
205 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
206 where
207 E: serde::de::Error,
208 {
209 self.visit_str(&v)
210 }
211
212 fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
213 where
214 E: serde::de::Error,
215 {
216 Ok(v)
217 }
218
219 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
220 where
221 E: serde::de::Error,
222 {
223 let v: i16 = v.try_into().map_err(serde::de::Error::custom)?;
224 Ok(v.into())
225 }
226 }
227
228 Ok(deserializer.deserialize_any(Bearing).ok())
229}