gistools/readers/gtfs/realtime/
entity.rs

1use crate::readers::{
2    GTFSRealtimeAlert, GTFSRealtimeShape, GTFSRealtimeStop, GTFSRealtimeTripDescriptor,
3    GTFSRealtimeTripModifications, GTFSRealtimeTripUpdate, GTFSRealtimeVehiclePosition,
4};
5use alloc::string::String;
6use pbf::{ProtoRead, Protobuf};
7
8/// The type of a GTFSRealtimeEntity message
9#[derive(Debug, Clone, PartialEq)]
10pub enum GTFSRealtimeEntityMessage {
11    /// A Trip Update message
12    TripUpdate(GTFSRealtimeTripUpdate),
13    /// A Vehicle Position message
14    VehiclePosition(GTFSRealtimeVehiclePosition),
15    /// An Alert message
16    Alert(GTFSRealtimeAlert),
17    /// A Shape message
18    Shape(GTFSRealtimeShape),
19    /// A Stop message
20    Stop(GTFSRealtimeStop),
21    /// A Trip Modifications message
22    TripModifications(GTFSRealtimeTripModifications),
23    /// A Deleted message
24    Deleted,
25}
26impl From<&GTFSRealtimeEntity> for GTFSRealtimeEntityMessage {
27    fn from(entity: &GTFSRealtimeEntity) -> Self {
28        if entity.is_deleted {
29            GTFSRealtimeEntityMessage::Deleted
30        } else if entity.trip_update.is_some() {
31            GTFSRealtimeEntityMessage::TripUpdate(entity.trip_update.as_ref().unwrap().clone())
32        } else if entity.vehicle_position.is_some() {
33            GTFSRealtimeEntityMessage::VehiclePosition(
34                entity.vehicle_position.as_ref().unwrap().clone(),
35            )
36        } else if entity.alert.is_some() {
37            GTFSRealtimeEntityMessage::Alert(entity.alert.as_ref().unwrap().clone())
38        } else if entity.shape.is_some() {
39            GTFSRealtimeEntityMessage::Shape(entity.shape.as_ref().unwrap().clone())
40        } else if entity.stop.is_some() {
41            GTFSRealtimeEntityMessage::Stop(entity.stop.as_ref().unwrap().clone())
42        } else if entity.trip_modifications.is_some() {
43            GTFSRealtimeEntityMessage::TripModifications(
44                entity.trip_modifications.as_ref().unwrap().clone(),
45            )
46        } else {
47            GTFSRealtimeEntityMessage::Deleted
48        }
49    }
50}
51
52/// A definition (or update) of an entity in the transit feed.
53/// May be a TripUpdate, VehiclePosition, Alert, Shape, Stop, and/or TripModifications.
54/// At least one of the above must be present (unless the entity is being deleted).
55#[derive(Debug, Default, Clone, PartialEq)]
56pub struct GTFSRealtimeEntity {
57    /// The ids are used only to provide incrementality support. The id should be
58    /// unique within a FeedMessage. Consequent FeedMessages may contain
59    /// FeedEntities with the same id. In case of a DIFFERENTIAL update the new
60    /// FeedEntity with some id will replace the old FeedEntity with the same id
61    /// (or delete it - see is_deleted below).
62    /// The actual GTFS entities (e.g. stations, routes, trips) referenced by the
63    /// feed must be specified by explicit selectors (see EntitySelector below for
64    /// more info).
65    pub id: String, // 1 [string]
66    /// Whether this entity is to be deleted. Relevant only for incremental fetches
67    pub is_deleted: bool, // 2 [bool]
68    /// Trip update
69    pub trip_update: Option<GTFSRealtimeTripUpdate>, // 3
70    /// Realtime positioning information for a given vehicle.
71    pub vehicle_position: Option<GTFSRealtimeVehiclePosition>, // 4
72    /// An alert
73    pub alert: Option<GTFSRealtimeAlert>, // 5
74    /// Describes the physical path that a vehicle takes when it's not part of the (CSV) GTFS,
75    /// such as for a detour. Shapes belong to Trips, and consist of a sequence of shape points.
76    /// Tracing the points in order provides the path of the vehicle.  Shapes do not need to intercept
77    /// the location of Stops exactly, but all Stops on a trip should lie within a small distance of
78    /// the shape for that trip, i.e. close to straight line segments connecting the shape points
79    /// NOTE: This message is still experimental, and subject to change. It may be formally adopted in the future.
80    pub shape: Option<GTFSRealtimeShape>, // 6
81    /// Describes a stop
82    pub stop: Option<GTFSRealtimeStop>, // 7
83    /// Trip modifications
84    pub trip_modifications: Option<GTFSRealtimeTripModifications>, // 8
85}
86/// Read in the contents of the GTFSRealtimeEntity
87impl ProtoRead for GTFSRealtimeEntity {
88    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
89        match tag {
90            1 => self.id = pb.read_string(),
91            2 => self.is_deleted = pb.read_varint(),
92            3 => {
93                let mut trip_update = GTFSRealtimeTripUpdate::default();
94                pb.read_message(&mut trip_update);
95                self.trip_update = Some(trip_update);
96            }
97            4 => {
98                let mut vehicle_position = GTFSRealtimeVehiclePosition::default();
99                pb.read_message(&mut vehicle_position);
100                self.vehicle_position = Some(vehicle_position);
101            }
102            5 => {
103                let mut alert = GTFSRealtimeAlert::default();
104                pb.read_message(&mut alert);
105                self.alert = Some(alert);
106            }
107            // These are not yet implemented
108            // 6 => {
109            //     let mut shape = GTFSRealtimeShape::default();
110            //     pb.read_message(&mut shape);
111            //     self.shape = Some(shape);
112            // }
113            // 7 => {
114            //     let mut stop = GTFSRealtimeStop::default();
115            //     pb.read_message(&mut stop);
116            //     self.stop = Some(stop);
117            // }
118            // 8 => {
119            //     let mut trip_modifications = GTFSRealtimeTripModifications::default();
120            //     pb.read_message(&mut trip_modifications);
121            //     self.trip_modifications = Some(trip_modifications);
122            // }
123            _ => panic!("unknown tag {}", tag),
124        }
125    }
126}
127
128/// A selector for an entity in a GTFS feed.
129/// The values of the fields should correspond to the appropriate fields in the
130/// GTFS feed.
131/// At least one specifier must be given. If several are given, then the
132/// matching has to apply to all the given specifiers.
133#[derive(Debug, Default, Clone, PartialEq)]
134pub struct GTFSRealtimeEntitySelector {
135    /// Corresponds to agency_id in GTFS
136    pub agency_id: Option<String>, // 1 [string]
137    /// Corresponds to route_id in GTFS
138    pub route_id: Option<String>, // 2 [string]
139    /// corresponds to route_type in GTFS.
140    /// For example, 0 means "any route type".
141    pub route_type: Option<i32>, // 3 [int32]
142    /// Corresponds to trip_id in GTFS
143    pub trip: Option<GTFSRealtimeTripDescriptor>, // 4 [message]
144    /// Corresponds to stop_id in GTFS stops.txt
145    pub stop_id: Option<String>, // 5 [string]
146    /// Corresponds to trip direction_id in GTFS trips.txt. If provided the
147    /// route_id must also be provided.
148    pub direction_id: Option<u32>, // 6 [uint32]
149}
150/// Read in the contents of the GTFSRealtimeEntitySelector
151impl ProtoRead for GTFSRealtimeEntitySelector {
152    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
153        match tag {
154            1 => self.agency_id = Some(pb.read_string()),
155            2 => self.route_id = Some(pb.read_string()),
156            3 => self.route_type = Some(pb.read_s_varint()),
157            4 => {
158                let mut trip = GTFSRealtimeTripDescriptor::default();
159                pb.read_message(&mut trip);
160                self.trip = Some(trip);
161            }
162            5 => self.stop_id = Some(pb.read_string()),
163            6 => self.direction_id = Some(pb.read_varint()),
164            _ => panic!("unknown tag {}", tag),
165        }
166    }
167}