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}