gtfs_structures/objects.rs
1pub use crate::enums::*;
2use crate::serde_helpers::*;
3use chrono::{Datelike, NaiveDate, Weekday};
4use rgb::RGB8;
5
6use std::fmt;
7use std::hash::Hash;
8use std::sync::Arc;
9
10/// Objects that have an identifier implement this trait
11///
12/// Those identifier are technical and should not be shown to travellers
13pub trait Id {
14 /// Identifier of the object
15 fn id(&self) -> &str;
16}
17
18impl<T: Id> Id for Arc<T> {
19 fn id(&self) -> &str {
20 self.as_ref().id()
21 }
22}
23
24/// Trait to introspect what is the object’s type (stop, route…)
25pub trait Type {
26 /// What is the type of the object
27 fn object_type(&self) -> ObjectType;
28}
29
30impl<T: Type> Type for Arc<T> {
31 fn object_type(&self) -> ObjectType {
32 self.as_ref().object_type()
33 }
34}
35
36/// A calender describes on which days the vehicle runs. See <https://gtfs.org/reference/static/#calendartxt>
37#[derive(Debug, Clone, Deserialize, Serialize, Hash, PartialEq, Eq)]
38pub struct Calendar {
39 /// Unique technical identifier (not for the traveller) of this calendar
40 #[serde(rename = "service_id")]
41 pub id: String,
42 /// Does the service run on mondays
43 #[serde(
44 deserialize_with = "deserialize_bool",
45 serialize_with = "serialize_bool"
46 )]
47 pub monday: bool,
48 /// Does the service run on tuesdays
49 #[serde(
50 deserialize_with = "deserialize_bool",
51 serialize_with = "serialize_bool"
52 )]
53 pub tuesday: bool,
54 /// Does the service run on wednesdays
55 #[serde(
56 deserialize_with = "deserialize_bool",
57 serialize_with = "serialize_bool"
58 )]
59 pub wednesday: bool,
60 /// Does the service run on thursdays
61 #[serde(
62 deserialize_with = "deserialize_bool",
63 serialize_with = "serialize_bool"
64 )]
65 pub thursday: bool,
66 /// Does the service run on fridays
67 #[serde(
68 deserialize_with = "deserialize_bool",
69 serialize_with = "serialize_bool"
70 )]
71 pub friday: bool,
72 /// Does the service run on saturdays
73 #[serde(
74 deserialize_with = "deserialize_bool",
75 serialize_with = "serialize_bool"
76 )]
77 pub saturday: bool,
78 /// Does the service run on sundays
79 #[serde(
80 deserialize_with = "deserialize_bool",
81 serialize_with = "serialize_bool"
82 )]
83 pub sunday: bool,
84 /// Start service day for the service interval
85 #[serde(
86 deserialize_with = "deserialize_date",
87 serialize_with = "serialize_date"
88 )]
89 pub start_date: NaiveDate,
90 /// End service day for the service interval. This service day is included in the interval
91 #[serde(
92 deserialize_with = "deserialize_date",
93 serialize_with = "serialize_date"
94 )]
95 pub end_date: NaiveDate,
96}
97
98impl Type for Calendar {
99 fn object_type(&self) -> ObjectType {
100 ObjectType::Calendar
101 }
102}
103
104impl Id for Calendar {
105 fn id(&self) -> &str {
106 &self.id
107 }
108}
109
110impl fmt::Display for Calendar {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 write!(f, "{}—{}", self.start_date, self.end_date)
113 }
114}
115
116impl Calendar {
117 /// Returns true if there is a service running on that day
118 pub fn valid_weekday(&self, date: NaiveDate) -> bool {
119 match date.weekday() {
120 Weekday::Mon => self.monday,
121 Weekday::Tue => self.tuesday,
122 Weekday::Wed => self.wednesday,
123 Weekday::Thu => self.thursday,
124 Weekday::Fri => self.friday,
125 Weekday::Sat => self.saturday,
126 Weekday::Sun => self.sunday,
127 }
128 }
129}
130
131/// Defines a specific date that can be added or removed from a [Calendar]. See <https://gtfs.org/reference/static/#calendar_datestxt>
132#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
133pub struct CalendarDate {
134 /// Identifier of the service that is modified at this date
135 pub service_id: String,
136 #[serde(
137 deserialize_with = "deserialize_date",
138 serialize_with = "serialize_date"
139 )]
140 /// Date where the service will be added or deleted
141 pub date: NaiveDate,
142 /// Is the service added or deleted
143 pub exception_type: Exception,
144}
145
146/// A physical stop, station or area. See <https://gtfs.org/reference/static/#stopstxt>
147#[derive(Debug, Serialize, Deserialize, Clone, Default)]
148pub struct Stop {
149 /// Unique technical identifier (not for the traveller) of the stop
150 #[serde(rename = "stop_id")]
151 pub id: String,
152 /// Short text or a number that identifies the location for riders
153 #[serde(rename = "stop_code")]
154 pub code: Option<String>,
155 ///Name of the location. Use a name that people will understand in the local and tourist vernacular
156 #[serde(rename = "stop_name")]
157 pub name: Option<String>,
158 /// Description of the location that provides useful, quality information
159 #[serde(default, rename = "stop_desc")]
160 pub description: Option<String>,
161 /// Type of the location
162 #[serde(default)]
163 pub location_type: LocationType,
164 /// Defines hierarchy between the different locations
165 pub parent_station: Option<String>,
166 /// Identifies the fare zone for a stop
167 pub zone_id: Option<String>,
168 /// URL of a web page about the location
169 #[serde(rename = "stop_url")]
170 pub url: Option<String>,
171 /// Longitude of the stop
172 #[serde(deserialize_with = "de_with_optional_float")]
173 #[serde(serialize_with = "serialize_float_as_str")]
174 #[serde(rename = "stop_lon", default)]
175 pub longitude: Option<f64>,
176 /// Latitude of the stop
177 #[serde(deserialize_with = "de_with_optional_float")]
178 #[serde(serialize_with = "serialize_float_as_str")]
179 #[serde(rename = "stop_lat", default)]
180 pub latitude: Option<f64>,
181 /// Timezone of the location
182 #[serde(rename = "stop_timezone")]
183 pub timezone: Option<String>,
184 /// Indicates whether wheelchair boardings are possible from the location
185 #[serde(deserialize_with = "de_with_empty_default", default)]
186 pub wheelchair_boarding: Availability,
187 /// Level of the location. The same level can be used by multiple unlinked stations
188 pub level_id: Option<String>,
189 /// Platform identifier for a platform stop (a stop belonging to a station)
190 pub platform_code: Option<String>,
191 /// Transfers from this Stop
192 #[serde(skip)]
193 pub transfers: Vec<StopTransfer>,
194 /// Pathways from this stop
195 #[serde(skip)]
196 pub pathways: Vec<Pathway>,
197 /// Text to speech readable version of the stop_name
198 #[serde(rename = "tts_stop_name")]
199 pub tts_name: Option<String>,
200}
201
202impl Type for Stop {
203 fn object_type(&self) -> ObjectType {
204 ObjectType::Stop
205 }
206}
207
208impl Id for Stop {
209 fn id(&self) -> &str {
210 &self.id
211 }
212}
213
214impl fmt::Display for Stop {
215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216 write!(f, "{}", self.name.as_ref().unwrap_or(&String::from("")))
217 }
218}
219
220/// A [StopTime] where the relations with [Trip] and [Stop] have not been tested
221#[derive(Debug, Clone, Serialize, Deserialize, Default)]
222pub struct RawStopTime {
223 /// [Trip] to which this stop time belongs to
224 pub trip_id: String,
225 /// Arrival time of the stop time.
226 /// It's an option since the intermediate stops can have have no arrival
227 /// and this arrival needs to be interpolated
228 #[serde(
229 deserialize_with = "deserialize_optional_time",
230 serialize_with = "serialize_optional_time"
231 )]
232 pub arrival_time: Option<u32>,
233 /// Departure time of the stop time.
234 /// It's an option since the intermediate stops can have have no departure
235 /// and this departure needs to be interpolated
236 #[serde(
237 deserialize_with = "deserialize_optional_time",
238 serialize_with = "serialize_optional_time"
239 )]
240 pub departure_time: Option<u32>,
241 /// Identifier of the [Stop] where the vehicle stops
242 pub stop_id: String,
243 /// Order of stops for a particular trip. The values must increase along the trip but do not need to be consecutive
244 pub stop_sequence: u32,
245 /// Text that appears on signage identifying the trip's destination to riders
246 pub stop_headsign: Option<String>,
247 /// Indicates pickup method
248 #[serde(default)]
249 pub pickup_type: PickupDropOffType,
250 /// Indicates drop off method
251 #[serde(default)]
252 pub drop_off_type: PickupDropOffType,
253 /// Indicates whether a rider can board the transit vehicle anywhere along the vehicle’s travel path
254 #[serde(default)]
255 pub continuous_pickup: ContinuousPickupDropOff,
256 /// Indicates whether a rider can alight from the transit vehicle at any point along the vehicle’s travel path
257 #[serde(default)]
258 pub continuous_drop_off: ContinuousPickupDropOff,
259 /// Actual distance traveled along the associated shape, from the first stop to the stop specified in this record. This field specifies how much of the shape to draw between any two stops during a trip
260 pub shape_dist_traveled: Option<f32>,
261 /// Indicates if arrival and departure times for a stop are strictly adhered to by the vehicle or if they are instead approximate and/or interpolated times
262 #[serde(default)]
263 pub timepoint: TimepointType,
264}
265
266/// The moment where a vehicle, running on [Trip] stops at a [Stop]. See <https://gtfs.org/reference/static/#stopstxt>
267#[derive(Clone, Debug, Default, Serialize, Deserialize)]
268pub struct StopTime {
269 /// Arrival time of the stop time.
270 /// It's an option since the intermediate stops can have have no arrival
271 /// and this arrival needs to be interpolated
272 pub arrival_time: Option<u32>,
273 /// [Stop] where the vehicle stops
274 pub stop: Arc<Stop>,
275 /// Departure time of the stop time.
276 /// It's an option since the intermediate stops can have have no departure
277 /// and this departure needs to be interpolated
278 pub departure_time: Option<u32>,
279 /// Indicates pickup method
280 pub pickup_type: PickupDropOffType,
281 /// Indicates drop off method
282 pub drop_off_type: PickupDropOffType,
283 /// Order of stops for a particular trip. The values must increase along the trip but do not need to be consecutive
284 pub stop_sequence: u32,
285 /// Text that appears on signage identifying the trip's destination to riders
286 pub stop_headsign: Option<String>,
287 /// Indicates whether a rider can board the transit vehicle anywhere along the vehicle’s travel path
288 pub continuous_pickup: ContinuousPickupDropOff,
289 /// Indicates whether a rider can alight from the transit vehicle at any point along the vehicle’s travel path
290 pub continuous_drop_off: ContinuousPickupDropOff,
291 /// Actual distance traveled along the associated shape, from the first stop to the stop specified in this record. This field specifies how much of the shape to draw between any two stops during a trip
292 pub shape_dist_traveled: Option<f32>,
293 /// Indicates if arrival and departure times for a stop are strictly adhered to by the vehicle or if they are instead approximate and/or interpolated times
294 pub timepoint: TimepointType,
295}
296
297impl StopTime {
298 /// Creates [StopTime] by linking a [RawStopTime::stop_id] to the actual [Stop]
299 pub fn from(stop_time_gtfs: RawStopTime, stop: Arc<Stop>) -> Self {
300 Self {
301 arrival_time: stop_time_gtfs.arrival_time,
302 departure_time: stop_time_gtfs.departure_time,
303 stop,
304 pickup_type: stop_time_gtfs.pickup_type,
305 drop_off_type: stop_time_gtfs.drop_off_type,
306 stop_sequence: stop_time_gtfs.stop_sequence,
307 stop_headsign: stop_time_gtfs.stop_headsign,
308 continuous_pickup: stop_time_gtfs.continuous_pickup,
309 continuous_drop_off: stop_time_gtfs.continuous_drop_off,
310 shape_dist_traveled: stop_time_gtfs.shape_dist_traveled,
311 timepoint: stop_time_gtfs.timepoint,
312 }
313 }
314}
315
316/// A route is a commercial line (there can be various stop sequences for a same line). See <https://gtfs.org/reference/static/#routestxt>
317#[derive(Debug, Clone, Serialize, Deserialize, Default)]
318pub struct Route {
319 /// Unique technical (not for the traveller) identifier for the route
320 #[serde(rename = "route_id")]
321 pub id: String,
322 /// Short name of a route. This will often be a short, abstract identifier like "32", "100X", or "Green" that riders use to identify a route, but which doesn't give any indication of what places the route serves
323 #[serde(rename = "route_short_name", default)]
324 pub short_name: Option<String>,
325 /// Full name of a route. This name is generally more descriptive than the [Route::short_name]] and often includes the route's destination or stop
326 #[serde(rename = "route_long_name", default)]
327 pub long_name: Option<String>,
328 /// Description of a route that provides useful, quality information
329 #[serde(rename = "route_desc")]
330 pub desc: Option<String>,
331 /// Indicates the type of transportation used on a route
332 pub route_type: RouteType,
333 /// URL of a web page about the particular route
334 #[serde(rename = "route_url")]
335 pub url: Option<String>,
336 /// Agency for the specified route
337 pub agency_id: Option<String>,
338 /// Orders the routes in a way which is ideal for presentation to customers. Routes with smaller route_sort_order values should be displayed first.
339 #[serde(rename = "route_sort_order")]
340 pub order: Option<u32>,
341 /// Route color designation that matches public facing material
342 #[serde(
343 deserialize_with = "deserialize_optional_color",
344 serialize_with = "serialize_optional_color",
345 rename = "route_color",
346 default
347 )]
348 pub color: Option<RGB8>,
349 /// Legible color to use for text drawn against a background of [Route::route_color]
350 #[serde(
351 deserialize_with = "deserialize_optional_color",
352 serialize_with = "serialize_optional_color",
353 rename = "route_text_color",
354 default
355 )]
356 pub text_color: Option<RGB8>,
357 /// Indicates whether a rider can board the transit vehicle anywhere along the vehicle’s travel path
358 #[serde(default)]
359 pub continuous_pickup: ContinuousPickupDropOff,
360 /// Indicates whether a rider can alight from the transit vehicle at any point along the vehicle’s travel path
361 #[serde(default)]
362 pub continuous_drop_off: ContinuousPickupDropOff,
363}
364
365impl Route {
366 /// Legible color to use for text drawn against a background of [Route::route_color]
367 /// Defaults to white (FFFFFF) when omitted or left empty.
368 pub fn text_color(&self) -> RGB8 {
369 self.text_color.unwrap_or_default()
370 }
371
372 /// Legible color to use for text drawn against a background of [Route::route_color]
373 /// Defaults to black (000000) when omitted or left empty.
374 pub fn color(&self) -> RGB8 {
375 self.color.unwrap_or_else(default_route_color)
376 }
377}
378
379impl Type for Route {
380 fn object_type(&self) -> ObjectType {
381 ObjectType::Route
382 }
383}
384
385impl Id for Route {
386 fn id(&self) -> &str {
387 &self.id
388 }
389}
390
391impl fmt::Display for Route {
392 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
393 if let Some(long_name) = self.long_name.as_ref() {
394 write!(f, "{long_name}")
395 } else if let Some(short_name) = self.short_name.as_ref() {
396 write!(f, "{short_name}")
397 } else {
398 write!(f, "{}", self.id)
399 }
400 }
401}
402
403/// Raw structure to hold translations as defined in the GTFS file. See <https://gtfs.org/schedule/reference/#translationstxt>
404#[derive(Debug, Clone, Serialize, Deserialize, Default)]
405pub struct RawTranslation {
406 /// To which table does the translation apply
407 pub table_name: String,
408 /// To which field does the translation apply
409 pub field_name: String,
410 /// Language of the translation
411 pub language: String,
412 /// Translated value
413 pub translation: String,
414 /// The record identifier to translate. For stop_times, it’s the trip_id
415 pub record_id: Option<String>,
416 /// Only for stop_times: the stop_sequence
417 pub record_sub_id: Option<String>,
418 /// Translate all values that match exactly, instead of specifying individual records
419 pub field_value: Option<String>,
420}
421
422/// A [Trip] where the relationships with other objects have not been checked
423#[derive(Debug, Clone, Serialize, Deserialize, Default)]
424pub struct RawTrip {
425 /// Unique technical (not for the traveller) identifier for the Trip
426 #[serde(rename = "trip_id")]
427 pub id: String,
428 /// References the [Calendar] on which this trip runs
429 pub service_id: String,
430 /// References along which [Route] this trip runs
431 pub route_id: String,
432 /// Shape of the trip
433 pub shape_id: Option<String>,
434 /// Text that appears on signage identifying the trip's destination to riders
435 pub trip_headsign: Option<String>,
436 /// Public facing text used to identify the trip to riders, for instance, to identify train numbers for commuter rail trips
437 pub trip_short_name: Option<String>,
438 /// Indicates the direction of travel for a trip. This field is not used in routing; it provides a way to separate trips by direction when publishing time tables
439 pub direction_id: Option<DirectionType>,
440 /// Identifies the block to which the trip belongs. A block consists of a single trip or many sequential trips made using the same vehicle, defined by shared service days and block_id. A block_id can have trips with different service days, making distinct blocks
441 pub block_id: Option<String>,
442 /// Indicates wheelchair accessibility
443 #[serde(default)]
444 pub wheelchair_accessible: Availability,
445 /// Indicates whether bikes are allowed
446 #[serde(default)]
447 pub bikes_allowed: BikesAllowedType,
448}
449
450impl Type for RawTrip {
451 fn object_type(&self) -> ObjectType {
452 ObjectType::Trip
453 }
454}
455
456impl Id for RawTrip {
457 fn id(&self) -> &str {
458 &self.id
459 }
460}
461
462impl fmt::Display for RawTrip {
463 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
464 write!(
465 f,
466 "route id: {}, service id: {}",
467 self.route_id, self.service_id
468 )
469 }
470}
471
472/// A Trip is a vehicle that follows a sequence of [StopTime] on certain days. See <https://gtfs.org/reference/static/#tripstxt>
473#[derive(Clone, Debug, Default, Serialize, Deserialize)]
474pub struct Trip {
475 /// Unique technical identifier (not for the traveller) for the Trip
476 pub id: String,
477 /// References the [Calendar] on which this trip runs
478 pub service_id: String,
479 /// References along which [Route] this trip runs
480 pub route_id: String,
481 /// All the [StopTime] that define the trip
482 pub stop_times: Vec<StopTime>,
483 /// Unique technical (not for the traveller) identifier for the Shape
484 pub shape_id: Option<String>,
485 /// Text that appears on signage identifying the trip's destination to riders
486 pub trip_headsign: Option<String>,
487 /// Public facing text used to identify the trip to riders, for instance, to identify train numbers for commuter rail trips
488 pub trip_short_name: Option<String>,
489 /// Indicates the direction of travel for a trip. This field is not used in routing; it provides a way to separate trips by direction when publishing time tables
490 pub direction_id: Option<DirectionType>,
491 /// Identifies the block to which the trip belongs. A block consists of a single trip or many sequential trips made using the same vehicle, defined by shared service days and block_id. A block_id can have trips with different service days, making distinct blocks
492 pub block_id: Option<String>,
493 /// Indicates wheelchair accessibility
494 pub wheelchair_accessible: Availability,
495 /// Indicates whether bikes are allowed
496 pub bikes_allowed: BikesAllowedType,
497 /// During which periods the trip runs by frequency and not by fixed timetable
498 pub frequencies: Vec<Frequency>,
499}
500
501impl Type for Trip {
502 fn object_type(&self) -> ObjectType {
503 ObjectType::Trip
504 }
505}
506
507impl Id for Trip {
508 fn id(&self) -> &str {
509 &self.id
510 }
511}
512
513impl fmt::Display for Trip {
514 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
515 write!(
516 f,
517 "route id: {}, service id: {}",
518 self.route_id, self.service_id
519 )
520 }
521}
522
523/// General informations about the agency running the network. See <https://gtfs.org/reference/static/#agencytxt>
524#[derive(Clone, Debug, Serialize, Deserialize, Default)]
525pub struct Agency {
526 /// Unique technical (not for the traveller) identifier for the Agency
527 #[serde(rename = "agency_id")]
528 pub id: Option<String>,
529 ///Full name of the transit agency
530 #[serde(rename = "agency_name")]
531 pub name: String,
532 /// Full url of the transit agency.
533 #[serde(rename = "agency_url")]
534 pub url: String,
535 /// Timezone where the transit agency is located
536 #[serde(rename = "agency_timezone")]
537 pub timezone: String,
538 /// Primary language used by this transit agency
539 #[serde(rename = "agency_lang")]
540 pub lang: Option<String>,
541 /// A voice telephone number for the specified agency
542 #[serde(rename = "agency_phone")]
543 pub phone: Option<String>,
544 /// URL of a web page that allows a rider to purchase tickets or other fare instruments for that agency online
545 #[serde(rename = "agency_fare_url")]
546 pub fare_url: Option<String>,
547 /// Email address actively monitored by the agency’s customer service department
548 #[serde(rename = "agency_email")]
549 pub email: Option<String>,
550}
551
552impl Type for Agency {
553 fn object_type(&self) -> ObjectType {
554 ObjectType::Agency
555 }
556}
557
558impl Id for Agency {
559 fn id(&self) -> &str {
560 match &self.id {
561 None => "",
562 Some(id) => id,
563 }
564 }
565}
566
567impl fmt::Display for Agency {
568 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
569 write!(f, "{}", self.name)
570 }
571}
572
573/// A single geographical point decribing the shape of a [Trip]. See <https://gtfs.org/reference/static/#shapestxt>
574#[derive(Clone, Debug, Serialize, Deserialize, Default)]
575pub struct Shape {
576 /// Unique technical (not for the traveller) identifier for the Shape
577 #[serde(rename = "shape_id")]
578 pub id: String,
579 #[serde(rename = "shape_pt_lat", default)]
580 /// Latitude of a shape point
581 pub latitude: f64,
582 /// Longitude of a shape point
583 #[serde(rename = "shape_pt_lon", default)]
584 pub longitude: f64,
585 /// Sequence in which the shape points connect to form the shape. Values increase along the trip but do not need to be consecutive.
586 #[serde(rename = "shape_pt_sequence")]
587 pub sequence: usize,
588 /// Actual distance traveled along the shape from the first shape point to the point specified in this record. Used by trip planners to show the correct portion of the shape on a map
589 #[serde(rename = "shape_dist_traveled")]
590 pub dist_traveled: Option<f32>,
591}
592
593impl Type for Shape {
594 fn object_type(&self) -> ObjectType {
595 ObjectType::Shape
596 }
597}
598
599impl Id for Shape {
600 fn id(&self) -> &str {
601 &self.id
602 }
603}
604
605/// Defines one possible fare. See <https://gtfs.org/reference/static/#fare_attributestxt>
606#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
607pub struct FareAttribute {
608 /// Unique technical (not for the traveller) identifier for the FareAttribute
609 #[serde(rename = "fare_id")]
610 pub id: String,
611 /// Fare price, in the unit specified by [FareAttribute::currency]
612 pub price: String,
613 /// Currency used to pay the fare.
614 #[serde(rename = "currency_type")]
615 pub currency: String,
616 ///Indicates when the fare must be paid
617 pub payment_method: PaymentMethod,
618 /// Indicates the number of transfers permitted on this fare
619 pub transfers: Transfers,
620 /// Identifies the relevant agency for a fare
621 pub agency_id: Option<String>,
622 /// Length of time in seconds before a transfer expires
623 pub transfer_duration: Option<usize>,
624}
625
626impl Id for FareAttribute {
627 fn id(&self) -> &str {
628 &self.id
629 }
630}
631
632impl Type for FareAttribute {
633 fn object_type(&self) -> ObjectType {
634 ObjectType::Fare
635 }
636}
637
638/// Used to describe the range of fares available for purchase by riders or taken into account
639/// when computing the total fare for journeys with multiple legs, such as transfer costs.
640/// https://gtfs.org/documentation/schedule/reference/#fare_productstxt
641#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
642pub struct FareProduct {
643 /// Identifies a fare product or set of fare products.
644 #[serde(rename = "fare_product_id")]
645 pub id: String,
646 /// The name of the fare product as displayed to riders.
647 #[serde(rename = "fare_product_name")]
648 pub name: Option<String>,
649 /// Identifies a rider category eligible for the fare product.
650 pub rider_category_id: Option<String>,
651 /// Identifies a fare media that can be employed to use the fare product during the trip.
652 pub fare_media_id: Option<String>,
653 /// The cost of the fare product. May be negative to represent transfer discounts. May be zero to represent a fare product that is free.
654 pub amount: String,
655 /// The currency of the cost of the fare product.
656 pub currency: String,
657}
658
659impl Id for FareProduct {
660 fn id(&self) -> &str {
661 &self.id
662 }
663}
664
665impl Type for FareProduct {
666 fn object_type(&self) -> ObjectType {
667 ObjectType::Fare
668 }
669}
670
671/// To describe the different fare media that can be employed to use fare products.
672/// Fare media are physical or virtual holders used for the representation and/or validation of a fare product.
673/// https://gtfs.org/documentation/schedule/reference/#fare_mediatxt
674#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
675pub struct FareMedia {
676 /// Identifies a fare media.
677 #[serde(rename = "fare_media_id")]
678 pub id: String,
679 /// The name of the fare media.
680 #[serde(rename = "fare_media_name")]
681 pub name: Option<String>,
682 /// The type of fare media
683 #[serde(rename = "fare_media_type")]
684 pub media_type: FareMediaType,
685}
686
687impl Id for FareMedia {
688 fn id(&self) -> &str {
689 &self.id
690 }
691}
692
693impl Type for FareMedia {
694 fn object_type(&self) -> ObjectType {
695 ObjectType::Fare
696 }
697}
698
699/// Defines categories of riders (e.g. elderly, student).
700/// https://gtfs.org/documentation/schedule/reference/#rider_categoriestxt
701#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
702pub struct RiderCategory {
703 /// Identifies a rider category.
704 #[serde(rename = "rider_category_id")]
705 pub id: String,
706 /// Rider category name as displayed to the rider.
707 #[serde(rename = "rider_category_name")]
708 pub name: String,
709 /// is_default_fare_category
710 pub is_default_fare_category: DefaultFareCategory,
711 /// URL of a web page, usually from the operating agency, that provides
712 /// detailed information about a specific rider category and/or describes its eligibility criteria.
713 pub eligibility_url: Option<String>,
714}
715
716impl Id for RiderCategory {
717 fn id(&self) -> &str {
718 &self.id
719 }
720}
721
722impl Type for RiderCategory {
723 fn object_type(&self) -> ObjectType {
724 ObjectType::Fare
725 }
726}
727
728/// Defines one possible fare. See <https://gtfs.org/schedule/reference/#fare_rulestxt>
729#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
730pub struct FareRule {
731 /// ID of the referenced FareAttribute.
732 pub fare_id: String,
733 /// ID of a [Route] associated with the fare class
734 pub route_id: Option<String>,
735 /// Identifies an origin zone. References a [Stop].zone_id
736 pub origin_id: Option<String>,
737 /// Identifies an destination zone. References a [Stop].zone_id
738 pub destination_id: Option<String>,
739 /// Identifies the zones that a rider will enter while using a given fare class. References a [Stop].zone_id
740 pub contains_id: Option<String>,
741}
742
743/// A [Frequency] before being merged into the corresponding [Trip]
744#[derive(Clone, Debug, Serialize, Deserialize, Default)]
745pub struct RawFrequency {
746 /// References the [Trip] that uses frequency
747 pub trip_id: String,
748 /// Time at which the first vehicle departs from the first stop of the trip
749 #[serde(
750 deserialize_with = "deserialize_time",
751 serialize_with = "serialize_time"
752 )]
753 pub start_time: u32,
754 /// Time at which service changes to a different headway (or ceases) at the first stop in the trip
755 #[serde(
756 deserialize_with = "deserialize_time",
757 serialize_with = "serialize_time"
758 )]
759 pub end_time: u32,
760 /// Time, in seconds, between departures from the same stop (headway) for the trip, during the time interval specified by start_time and end_time
761 pub headway_secs: u32,
762 /// Indicates the type of service for a trip
763 pub exact_times: Option<ExactTimes>,
764}
765
766/// Timetables can be defined by the frequency of their vehicles. See <<https://gtfs.org/reference/static/#frequenciestxt>>
767#[derive(Clone, Debug, Default, Deserialize, Serialize)]
768pub struct Frequency {
769 /// Time at which the first vehicle departs from the first stop of the trip
770 pub start_time: u32,
771 /// Time at which service changes to a different headway (or ceases) at the first stop in the trip
772 pub end_time: u32,
773 /// Time, in seconds, between departures from the same stop (headway) for the trip, during the time interval specified by start_time and end_time
774 pub headway_secs: u32,
775 /// Indicates the type of service for a trip
776 pub exact_times: Option<ExactTimes>,
777}
778
779impl Frequency {
780 /// Converts from a [RawFrequency] to a [Frequency]
781 pub fn from(frequency: &RawFrequency) -> Self {
782 Self {
783 start_time: frequency.start_time,
784 end_time: frequency.end_time,
785 headway_secs: frequency.headway_secs,
786 exact_times: frequency.exact_times,
787 }
788 }
789}
790
791/// Transfer information between stops before merged into [Stop]
792#[derive(Clone, Debug, Serialize, Deserialize, Default)]
793pub struct RawTransfer {
794 /// Stop from which to leave
795 pub from_stop_id: String,
796 /// Stop which to transfer to
797 pub to_stop_id: String,
798 /// Type of the transfer
799 pub transfer_type: TransferType,
800 /// Minimum time needed to make the transfer in seconds
801 pub min_transfer_time: Option<u32>,
802}
803
804#[derive(Clone, Debug, Default, Deserialize, Serialize)]
805/// Transfer information between stops
806pub struct StopTransfer {
807 /// Stop which to transfer to
808 pub to_stop_id: String,
809 /// Type of the transfer
810 pub transfer_type: TransferType,
811 /// Minimum time needed to make the transfer in seconds
812 pub min_transfer_time: Option<u32>,
813}
814
815impl From<RawTransfer> for StopTransfer {
816 /// Converts from a [RawTransfer] to a [StopTransfer]
817 fn from(transfer: RawTransfer) -> Self {
818 Self {
819 to_stop_id: transfer.to_stop_id,
820 transfer_type: transfer.transfer_type,
821 min_transfer_time: transfer.min_transfer_time,
822 }
823 }
824}
825
826/// Meta-data about the feed. See <https://gtfs.org/reference/static/#feed_infotxt>
827#[derive(Clone, Debug, Serialize, Deserialize)]
828pub struct FeedInfo {
829 /// Full name of the organization that publishes the dataset.
830 #[serde(rename = "feed_publisher_name")]
831 pub name: String,
832 /// URL of the dataset publishing organization's website
833 #[serde(rename = "feed_publisher_url")]
834 pub url: String,
835 /// Default language used for the text in this dataset
836 #[serde(rename = "feed_lang")]
837 pub lang: String,
838 /// Defines the language that should be used when the data consumer doesn’t know the language of the rider
839 pub default_lang: Option<String>,
840 /// The dataset provides complete and reliable schedule information for service in the period from this date
841 #[serde(
842 deserialize_with = "deserialize_option_date",
843 serialize_with = "serialize_option_date",
844 rename = "feed_start_date",
845 default
846 )]
847 pub start_date: Option<NaiveDate>,
848 ///The dataset provides complete and reliable schedule information for service in the period until this date
849 #[serde(
850 deserialize_with = "deserialize_option_date",
851 serialize_with = "serialize_option_date",
852 rename = "feed_end_date",
853 default
854 )]
855 pub end_date: Option<NaiveDate>,
856 /// String that indicates the current version of their GTFS dataset
857 #[serde(rename = "feed_version")]
858 pub version: Option<String>,
859 /// Email address for communication regarding the GTFS dataset and data publishing practices
860 #[serde(rename = "feed_contact_email")]
861 pub contact_email: Option<String>,
862 /// URL for contact information, a web-form, support desk, or other tools for communication regarding the GTFS dataset and data publishing practices
863 #[serde(rename = "feed_contact_url")]
864 pub contact_url: Option<String>,
865}
866
867impl fmt::Display for FeedInfo {
868 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
869 write!(f, "{}", self.name)
870 }
871}
872
873/// A graph representation to describe subway or train, with nodes (the locations) and edges (the pathways).
874#[derive(Clone, Debug, Serialize, Deserialize, Default)]
875pub struct RawPathway {
876 /// Uniquely identifies the pathway
877 #[serde(rename = "pathway_id")]
878 pub id: String,
879 /// Location at which the pathway begins
880 pub from_stop_id: String,
881 /// Location at which the pathway ends
882 pub to_stop_id: String,
883 /// Type of pathway between the specified (from_stop_id, to_stop_id) pair
884 #[serde(rename = "pathway_mode")]
885 pub mode: PathwayMode,
886 /// Indicates in which direction the pathway can be used
887 pub is_bidirectional: PathwayDirectionType,
888 /// Horizontal length in meters of the pathway from the origin location to the destination location
889 pub length: Option<f32>,
890 /// Average time in seconds needed to walk through the pathway from the origin location to the destination location
891 pub traversal_time: Option<u32>,
892 /// Number of stairs of the pathway
893 pub stair_count: Option<i32>,
894 /// Maximum slope ratio of the pathway
895 pub max_slope: Option<f32>,
896 /// Minimum width of the pathway in meters
897 pub min_width: Option<f32>,
898 /// String of text from physical signage visible to transit riders
899 pub signposted_as: Option<String>,
900 /// Same than the signposted_as field, but when the pathways is used backward
901 pub reversed_signposted_as: Option<String>,
902}
903
904impl Id for RawPathway {
905 fn id(&self) -> &str {
906 &self.id
907 }
908}
909
910impl Type for RawPathway {
911 fn object_type(&self) -> ObjectType {
912 ObjectType::Pathway
913 }
914}
915
916/// Pathway going from a stop to another.
917#[derive(Debug, Clone, Default, Serialize, Deserialize)]
918pub struct Pathway {
919 /// Uniquely identifies the pathway
920 pub id: String,
921 /// Location at which the pathway ends
922 pub to_stop_id: String,
923 /// Type of pathway between the specified (from_stop_id, to_stop_id) pair
924 pub mode: PathwayMode,
925 /// Indicates in which direction the pathway can be used
926 pub is_bidirectional: PathwayDirectionType,
927 /// Horizontal length in meters of the pathway from the origin location to the destination location
928 pub length: Option<f32>,
929 /// Average time in seconds needed to walk through the pathway from the origin location to the destination location
930 pub traversal_time: Option<u32>,
931 /// Number of stairs of the pathway
932 pub stair_count: Option<i32>,
933 /// Maximum slope ratio of the pathway
934 pub max_slope: Option<f32>,
935 /// Minimum width of the pathway in meters
936 pub min_width: Option<f32>,
937 /// String of text from physical signage visible to transit riders
938 pub signposted_as: Option<String>,
939 /// Same than the signposted_as field, but when the pathways is used backward
940 pub reversed_signposted_as: Option<String>,
941}
942
943impl Id for Pathway {
944 fn id(&self) -> &str {
945 &self.id
946 }
947}
948
949impl Type for Pathway {
950 fn object_type(&self) -> ObjectType {
951 ObjectType::Pathway
952 }
953}
954
955impl From<RawPathway> for Pathway {
956 /// Converts from a [RawPathway] to a [Pathway]
957 fn from(raw: RawPathway) -> Self {
958 Self {
959 id: raw.id,
960 to_stop_id: raw.to_stop_id,
961 mode: raw.mode,
962 is_bidirectional: raw.is_bidirectional,
963 length: raw.length,
964 max_slope: raw.max_slope,
965 min_width: raw.min_width,
966 reversed_signposted_as: raw.reversed_signposted_as,
967 signposted_as: raw.signposted_as,
968 stair_count: raw.stair_count,
969 traversal_time: raw.traversal_time,
970 }
971 }
972}
973
974/// Format of the data
975#[derive(Clone, Debug, Serialize, PartialEq)]
976pub enum SourceFormat {
977 /// `Directory` means the data comes from a directory
978 Directory,
979 /// `Zip` means the data were read from a zip
980 Zip,
981}