gistools/readers/gtfs/realtime/trip/
modifications.rs

1#![cfg_attr(feature = "nightly", coverage(off))]
2// NOTE: I can't find data that actually uses this and most modules don't support so.
3// This is an experimental module, exists incase the GTFS-Realtime spec changes to include it
4
5use crate::util::Date;
6use alloc::{string::String, vec::Vec};
7use pbf::{ProtoRead, Protobuf};
8
9/// NOTE: This field is still experimental, and subject to change. It may be formally adopted in
10/// the future.
11#[derive(Debug, Default, Clone, PartialEq)]
12pub struct GTFSRealtimeTripModifications {
13    /// A list of selected trips affected by this TripModifications.
14    pub selected_trips: Vec<GTFSRealtimeSelectedTrips>, // 1 [repeated message]
15    /// A list of start times in the real-time trip descriptor for the trip_id defined in trip_ids.
16    /// Useful to target multiple departures of a trip_id in a frequency-based trip.
17    pub start_times: Vec<String>, // 2 [repeated string]
18    /// Dates on which the modifications occurs, in the YYYYMMDD format. Producers SHOULD only
19    /// transmit detours occurring within the next week.
20    /// The dates provided should not be used as user-facing information, if a user-facing start and
21    /// end date needs to be provided, they can be provided in the linked service alert with `service_alert_id`
22    pub service_dates: Vec<String>, // 3 [repeated string]
23    /// A list of modifications to apply to the affected trips.
24    pub modifications: Vec<GTFSRealtimeModification>, // 4 [repeated message]
25}
26/// Read in the contents of the GTFSRealtimeTripModifications
27impl ProtoRead for GTFSRealtimeTripModifications {
28    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
29        match tag {
30            1 => {
31                let mut selected_trip = GTFSRealtimeSelectedTrips::default();
32                pb.read_message(&mut selected_trip);
33                self.selected_trips.push(selected_trip);
34            }
35            2 => self.start_times.push(pb.read_string()),
36            3 => self.service_dates.push(pb.read_string()),
37            4 => {
38                let mut modification = GTFSRealtimeModification::default();
39                pb.read_message(&mut modification);
40                self.modifications.push(modification);
41            }
42            _ => panic!("unknown tag {}", tag),
43        }
44    }
45}
46
47/// A `Modification` message replaces a span of n stop times from each affected trip starting at
48/// `start_stop_selector`.
49#[derive(Debug, Default, Clone, PartialEq)]
50pub struct GTFSRealtimeModification {
51    /// The stop selector of the first stop_time of the original trip that is to be affected by this modification.
52    /// Used in conjuction with `end_stop_selector`.
53    /// `start_stop_selector` is required and is used to define the reference stop used with `travel_time_to_stop`.
54    pub start_stop_selector: Option<GTFSRealtimeStopSelector>, // 1 [message]
55    /// The stop selector of the last stop of the original trip that is to be affected by this modification.
56    /// The selection is inclusive, so if only one stop_time is replaced by that modification, `start_stop_selector`
57    /// and `end_stop_selector` must be equivalent.
58    /// If no stop_time is replaced, `end_stop_selector` must not be provided. It's otherwise required.
59    pub end_stop_selector: Option<GTFSRealtimeStopSelector>, // 2 [message]
60    /// The number of seconds of delay to add to all departure and arrival times following the end of this modification.
61    /// If multiple modifications apply to the same trip, the delays accumulate as the trip advances.
62    pub propagated_modification_delay: i32, // 3 [int32]
63    /// A list of replacement stops, replacing those of the original trip.
64    /// The length of the new stop times may be less, the same, or greater than the number of replaced stop times.
65    pub replacement_stops: Vec<GTFSRealtimeReplacementStop>, // 4 [repeated message]
66    /// An `id` value from the `FeedEntity` message that contains the `Alert` describing this Modification
67    /// for user-facing communication.
68    pub service_alert_id: Option<String>, // 5 [string]
69    /// This timestamp identifies the moment when the modification has last been changed.
70    /// In POSIX time (i.e., number of seconds since January 1st 1970 00:00:00 UTC).
71    pub last_modified_time: Option<Date>, // 6 [uint64]
72}
73/// Read in the contents of the GTFSRealtimeModification
74impl ProtoRead for GTFSRealtimeModification {
75    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
76        match tag {
77            1 => {
78                let mut stop_selector = GTFSRealtimeStopSelector::default();
79                pb.read_message(&mut stop_selector);
80                self.start_stop_selector = Some(stop_selector);
81            }
82            2 => {
83                let mut stop_selector = GTFSRealtimeStopSelector::default();
84                pb.read_message(&mut stop_selector);
85                self.end_stop_selector = Some(stop_selector);
86            }
87            3 => self.propagated_modification_delay = pb.read_varint(),
88            4 => {
89                let mut replacement_stop = GTFSRealtimeReplacementStop::default();
90                pb.read_message(&mut replacement_stop);
91                self.replacement_stops.push(replacement_stop);
92            }
93            5 => self.service_alert_id = Some(pb.read_string()),
94            6 => {
95                self.last_modified_time =
96                    Some(Date::from_time(pb.read_varint::<u64>() as i64 * 1000));
97            }
98            _ => panic!("unknown tag {}", tag),
99        }
100    }
101}
102
103/// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the future.
104/// Select a stop by stop sequence or by stop_id. At least one of the two values must be provided.
105#[derive(Debug, Default, Clone, PartialEq)]
106pub struct GTFSRealtimeStopSelector {
107    /// Must be the same as in stop_times.txt in the corresponding GTFS feed.
108    pub stop_sequence: Option<u32>, // 1 [uint32]
109    /// Must be the same as in stops.txt in the corresponding GTFS feed.
110    pub stop_id: Option<String>, // 2 [string]
111}
112/// Read in the contents of the GTFSRealtimeStopSelector
113impl ProtoRead for GTFSRealtimeStopSelector {
114    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
115        match tag {
116            1 => self.stop_sequence = Some(pb.read_varint()),
117            2 => self.stop_id = Some(pb.read_string()),
118            _ => panic!("unknown tag {}", tag),
119        }
120    }
121}
122
123/// Selected trips affected by TripModifications.
124#[derive(Debug, Default, Clone, PartialEq)]
125pub struct GTFSRealtimeSelectedTrips {
126    /// A list of trips affected with this replacement that all have the same new `shape_id`.
127    pub trip_ids: Vec<String>, // 1 [repeated string]
128    /// The ID of the new shape for the modified trips in this SelectedTrips.
129    /// May refer to a new shape added using a GTFS-RT Shape message, or to an existing shape defined in
130    /// the GTFS-Static feed's shapes.txt.
131    pub shape_id: Option<String>, // 2 [string]
132}
133/// Read in the contents of the GTFSRealtimeSelectedTrips
134impl ProtoRead for GTFSRealtimeSelectedTrips {
135    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
136        match tag {
137            1 => self.trip_ids.push(pb.read_string()),
138            2 => self.shape_id = Some(pb.read_string()),
139            _ => panic!("unknown tag {}", tag),
140        }
141    }
142}
143
144/// NOTE: This field is still experimental, and subject to change. It may be formally adopted in the
145/// future.
146#[derive(Debug, Default, Clone, PartialEq)]
147pub struct GTFSRealtimeReplacementStop {
148    /// The difference in seconds between the arrival time at this stop and the arrival time at the reference
149    /// stop. The reference stop is the stop prior to start_stop_selector. If the modification begins
150    /// at the first stop of the trip, then the first stop of the trip is the reference stop.
151    /// This value MUST be monotonically increasing and may only be a negative number if the first
152    /// stop of the original trip is the reference stop.
153    pub travel_time_to_stop: Option<i32>, // 1 [int32]
154    /// The replacement stop ID which will now be visited by the trip. May refer to a new stop added
155    /// using a GTFS-RT Stop message, or to an existing stop defined in the GTFS-Static feed's stops.txt.
156    /// The stop MUST have location_type=0 (routable stops).
157    pub stop_id: Option<String>, // 2 [string]
158}
159/// Read in the contents of the GTFSRealtimeReplacementStop
160impl ProtoRead for GTFSRealtimeReplacementStop {
161    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
162        match tag {
163            1 => self.travel_time_to_stop = Some(pb.read_varint()),
164            2 => self.stop_id = Some(pb.read_string()),
165            _ => panic!("unknown tag {}", tag),
166        }
167    }
168}