1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
pub use crate::enums::*;
use crate::serde_helpers::*;
use chrono::{Datelike, NaiveDate, Weekday};
use rgb::RGB8;

use std::fmt;
use std::sync::Arc;

/// Objects that have an identifier implement this trait
///
/// Those identifier are technical and should not be shown to travellers
pub trait Id {
    /// Identifier of the object
    fn id(&self) -> &str;
}

impl<T: Id> Id for Arc<T> {
    fn id(&self) -> &str {
        self.as_ref().id()
    }
}

/// Trait to introspect what is the object’s type (stop, route…)
pub trait Type {
    /// What is the type of the object
    fn object_type(&self) -> ObjectType;
}

impl<T: Type> Type for Arc<T> {
    fn object_type(&self) -> ObjectType {
        self.as_ref().object_type()
    }
}

/// A calender describes on which days the vehicle runs. See <https://gtfs.org/reference/static/#calendartxt>
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Calendar {
    /// Unique technical identifier (not for the traveller) of this calendar
    #[serde(rename = "service_id")]
    pub id: String,
    /// Does the service run on mondays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub monday: bool,
    /// Does the service run on tuesdays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub tuesday: bool,
    /// Does the service run on wednesdays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub wednesday: bool,
    /// Does the service run on thursdays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub thursday: bool,
    /// Does the service run on fridays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub friday: bool,
    /// Does the service run on saturdays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub saturday: bool,
    /// Does the service run on sundays
    #[serde(
        deserialize_with = "deserialize_bool",
        serialize_with = "serialize_bool"
    )]
    pub sunday: bool,
    /// Start service day for the service interval
    #[serde(
        deserialize_with = "deserialize_date",
        serialize_with = "serialize_date"
    )]
    pub start_date: NaiveDate,
    /// End service day for the service interval. This service day is included in the interval
    #[serde(
        deserialize_with = "deserialize_date",
        serialize_with = "serialize_date"
    )]
    pub end_date: NaiveDate,
}

impl Type for Calendar {
    fn object_type(&self) -> ObjectType {
        ObjectType::Calendar
    }
}

impl Id for Calendar {
    fn id(&self) -> &str {
        &self.id
    }
}

impl fmt::Display for Calendar {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}—{}", self.start_date, self.end_date)
    }
}

impl Calendar {
    /// Returns true if there is a service running on that day
    pub fn valid_weekday(&self, date: NaiveDate) -> bool {
        match date.weekday() {
            Weekday::Mon => self.monday,
            Weekday::Tue => self.tuesday,
            Weekday::Wed => self.wednesday,
            Weekday::Thu => self.thursday,
            Weekday::Fri => self.friday,
            Weekday::Sat => self.saturday,
            Weekday::Sun => self.sunday,
        }
    }
}

/// Defines a specific date that can be added or removed from a [Calendar]. See <https://gtfs.org/reference/static/#calendar_datestxt>
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CalendarDate {
    /// Identifier of the service that is modified at this date
    pub service_id: String,
    #[serde(
        deserialize_with = "deserialize_date",
        serialize_with = "serialize_date"
    )]
    /// Date where the service will be added or deleted
    pub date: NaiveDate,
    /// Is the service added or deleted
    pub exception_type: Exception,
}

/// A physical stop, station or area. See <https://gtfs.org/reference/static/#stopstxt>
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Stop {
    /// Unique technical identifier (not for the traveller) of the stop
    #[serde(rename = "stop_id")]
    pub id: String,
    /// Short text or a number that identifies the location for riders
    #[serde(rename = "stop_code")]
    pub code: Option<String>,
    ///Name of the location. Use a name that people will understand in the local and tourist vernacular
    #[serde(rename = "stop_name")]
    pub name: Option<String>,
    /// Description of the location that provides useful, quality information
    #[serde(default, rename = "stop_desc")]
    pub description: Option<String>,
    /// Type of the location
    #[serde(default)]
    pub location_type: LocationType,
    /// Defines hierarchy between the different locations
    pub parent_station: Option<String>,
    /// Identifies the fare zone for a stop
    pub zone_id: Option<String>,
    /// URL of a web page about the location
    #[serde(rename = "stop_url")]
    pub url: Option<String>,
    /// Longitude of the stop
    #[serde(deserialize_with = "de_with_optional_float")]
    #[serde(serialize_with = "serialize_float_as_str")]
    #[serde(rename = "stop_lon", default)]
    pub longitude: Option<f64>,
    /// Latitude of the stop
    #[serde(deserialize_with = "de_with_optional_float")]
    #[serde(serialize_with = "serialize_float_as_str")]
    #[serde(rename = "stop_lat", default)]
    pub latitude: Option<f64>,
    /// Timezone of the location
    #[serde(rename = "stop_timezone")]
    pub timezone: Option<String>,
    /// Indicates whether wheelchair boardings are possible from the location
    #[serde(deserialize_with = "de_with_empty_default", default)]
    pub wheelchair_boarding: Availability,
    /// Level of the location. The same level can be used by multiple unlinked stations
    pub level_id: Option<String>,
    /// Platform identifier for a platform stop (a stop belonging to a station)
    pub platform_code: Option<String>,
    /// Transfers from this Stop
    #[serde(skip)]
    pub transfers: Vec<StopTransfer>,
    /// Pathways from this stop
    #[serde(skip)]
    pub pathways: Vec<Pathway>,
    /// Text to speech readable version of the stop_name
    #[serde(rename = "tts_stop_name")]
    pub tts_name: Option<String>,
}

impl Type for Stop {
    fn object_type(&self) -> ObjectType {
        ObjectType::Stop
    }
}

impl Id for Stop {
    fn id(&self) -> &str {
        &self.id
    }
}

impl fmt::Display for Stop {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name.as_ref().unwrap_or(&String::from("")))
    }
}

/// A [StopTime] where the relations with [Trip] and [Stop] have not been tested
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RawStopTime {
    /// [Trip] to which this stop time belongs to
    pub trip_id: String,
    /// Arrival time of the stop time.
    /// It's an option since the intermediate stops can have have no arrival
    /// and this arrival needs to be interpolated
    #[serde(
        deserialize_with = "deserialize_optional_time",
        serialize_with = "serialize_optional_time"
    )]
    pub arrival_time: Option<u32>,
    /// Departure time of the stop time.
    /// It's an option since the intermediate stops can have have no departure
    /// and this departure needs to be interpolated
    #[serde(
        deserialize_with = "deserialize_optional_time",
        serialize_with = "serialize_optional_time"
    )]
    pub departure_time: Option<u32>,
    /// Identifier of the [Stop] where the vehicle stops
    pub stop_id: String,
    /// Order of stops for a particular trip. The values must increase along the trip but do not need to be consecutive
    pub stop_sequence: u16,
    /// Text that appears on signage identifying the trip's destination to riders
    pub stop_headsign: Option<String>,
    /// Indicates pickup method
    #[serde(default)]
    pub pickup_type: PickupDropOffType,
    /// Indicates drop off method
    #[serde(default)]
    pub drop_off_type: PickupDropOffType,
    /// Indicates whether a rider can board the transit vehicle anywhere along the vehicle’s travel path
    #[serde(default)]
    pub continuous_pickup: ContinuousPickupDropOff,
    /// Indicates whether a rider can alight from the transit vehicle at any point along the vehicle’s travel path
    #[serde(default)]
    pub continuous_drop_off: ContinuousPickupDropOff,
    /// 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
    pub shape_dist_traveled: Option<f32>,
    /// 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
    #[serde(default)]
    pub timepoint: TimepointType,
}

/// The moment where a vehicle, running on [Trip] stops at a [Stop]. See <https://gtfs.org/reference/static/#stopstxt>
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct StopTime {
    /// Arrival time of the stop time.
    /// It's an option since the intermediate stops can have have no arrival
    /// and this arrival needs to be interpolated
    pub arrival_time: Option<u32>,
    /// [Stop] where the vehicle stops
    pub stop: Arc<Stop>,
    /// Departure time of the stop time.
    /// It's an option since the intermediate stops can have have no departure
    /// and this departure needs to be interpolated
    pub departure_time: Option<u32>,
    /// Indicates pickup method
    pub pickup_type: PickupDropOffType,
    /// Indicates drop off method
    pub drop_off_type: PickupDropOffType,
    /// Order of stops for a particular trip. The values must increase along the trip but do not need to be consecutive
    pub stop_sequence: u16,
    /// Text that appears on signage identifying the trip's destination to riders
    pub stop_headsign: Option<String>,
    /// Indicates whether a rider can board the transit vehicle anywhere along the vehicle’s travel path
    pub continuous_pickup: ContinuousPickupDropOff,
    /// Indicates whether a rider can alight from the transit vehicle at any point along the vehicle’s travel path
    pub continuous_drop_off: ContinuousPickupDropOff,
    /// 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
    pub shape_dist_traveled: Option<f32>,
    /// 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
    pub timepoint: TimepointType,
}

impl StopTime {
    /// Creates [StopTime] by linking a [RawStopTime::stop_id] to the actual [Stop]
    pub fn from(stop_time_gtfs: RawStopTime, stop: Arc<Stop>) -> Self {
        Self {
            arrival_time: stop_time_gtfs.arrival_time,
            departure_time: stop_time_gtfs.departure_time,
            stop,
            pickup_type: stop_time_gtfs.pickup_type,
            drop_off_type: stop_time_gtfs.drop_off_type,
            stop_sequence: stop_time_gtfs.stop_sequence,
            stop_headsign: stop_time_gtfs.stop_headsign,
            continuous_pickup: stop_time_gtfs.continuous_pickup,
            continuous_drop_off: stop_time_gtfs.continuous_drop_off,
            shape_dist_traveled: stop_time_gtfs.shape_dist_traveled,
            timepoint: stop_time_gtfs.timepoint,
        }
    }
}

/// A route is a commercial line (there can be various stop sequences for a same line). See <https://gtfs.org/reference/static/#routestxt>
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Route {
    /// Unique technical (not for the traveller) identifier for the route
    #[serde(rename = "route_id")]
    pub id: String,
    /// 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
    #[serde(rename = "route_short_name", default)]
    pub short_name: Option<String>,
    /// 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
    #[serde(rename = "route_long_name", default)]
    pub long_name: Option<String>,
    /// Description of a route that provides useful, quality information
    #[serde(rename = "route_desc")]
    pub desc: Option<String>,
    /// Indicates the type of transportation used on a route
    pub route_type: RouteType,
    /// URL of a web page about the particular route
    #[serde(rename = "route_url")]
    pub url: Option<String>,
    /// Agency for the specified route
    pub agency_id: Option<String>,
    /// Orders the routes in a way which is ideal for presentation to customers. Routes with smaller route_sort_order values should be displayed first.
    #[serde(rename = "route_sort_order")]
    pub order: Option<u32>,
    /// Route color designation that matches public facing material
    #[serde(
        deserialize_with = "deserialize_route_color",
        serialize_with = "serialize_color",
        rename = "route_color",
        default = "default_route_color"
    )]
    pub color: RGB8,
    /// Legible color to use for text drawn against a background of [Route::route_color]
    #[serde(
        deserialize_with = "deserialize_route_text_color",
        serialize_with = "serialize_color",
        rename = "route_text_color",
        default
    )]
    pub text_color: RGB8,
    /// Indicates whether a rider can board the transit vehicle anywhere along the vehicle’s travel path
    #[serde(default)]
    pub continuous_pickup: ContinuousPickupDropOff,
    /// Indicates whether a rider can alight from the transit vehicle at any point along the vehicle’s travel path
    #[serde(default)]
    pub continuous_drop_off: ContinuousPickupDropOff,
}

impl Type for Route {
    fn object_type(&self) -> ObjectType {
        ObjectType::Route
    }
}

impl Id for Route {
    fn id(&self) -> &str {
        &self.id
    }
}

impl fmt::Display for Route {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(long_name) = self.long_name.as_ref() {
            write!(f, "{}", long_name)
        } else if let Some(short_name) = self.short_name.as_ref() {
            write!(f, "{}", short_name)
        } else {
            write!(f, "{}", self.id)
        }
    }
}

/// Raw structure to hold translations as defined in the GTFS file. See <https://gtfs.org/schedule/reference/#translationstxt>
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RawTranslation {
    /// To which table does the translation apply
    pub table_name: String,
    /// To which field does the translation apply
    pub field_name: String,
    /// Language of the translation
    pub language: String,
    /// Translated value
    pub translation: String,
    /// The record identifier to translate. For stop_times, it’s the trip_id
    pub record_id: Option<String>,
    /// Only for stop_times: the stop_sequence
    pub record_sub_id: Option<String>,
    /// Translate all values that match exactly, instead of specifying individual records
    pub field_value: Option<String>,
}

/// A [Trip] where the relationships with other objects have not been checked
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RawTrip {
    /// Unique technical (not for the traveller) identifier for the Trip
    #[serde(rename = "trip_id")]
    pub id: String,
    /// References the [Calendar] on which this trip runs
    pub service_id: String,
    /// References along which [Route] this trip runs
    pub route_id: String,
    /// Shape of the trip
    pub shape_id: Option<String>,
    /// Text that appears on signage identifying the trip's destination to riders
    pub trip_headsign: Option<String>,
    /// Public facing text used to identify the trip to riders, for instance, to identify train numbers for commuter rail trips
    pub trip_short_name: Option<String>,
    /// 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
    pub direction_id: Option<DirectionType>,
    /// 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
    pub block_id: Option<String>,
    /// Indicates wheelchair accessibility
    #[serde(default)]
    pub wheelchair_accessible: Availability,
    /// Indicates whether bikes are allowed
    #[serde(default)]
    pub bikes_allowed: BikesAllowedType,
}

impl Type for RawTrip {
    fn object_type(&self) -> ObjectType {
        ObjectType::Trip
    }
}

impl Id for RawTrip {
    fn id(&self) -> &str {
        &self.id
    }
}

impl fmt::Display for RawTrip {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "route id: {}, service id: {}",
            self.route_id, self.service_id
        )
    }
}

/// A Trip is a vehicle that follows a sequence of [StopTime] on certain days. See <https://gtfs.org/reference/static/#tripstxt>
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Trip {
    /// Unique technical identifier (not for the traveller) for the Trip
    pub id: String,
    /// References the [Calendar] on which this trip runs
    pub service_id: String,
    /// References along which [Route] this trip runs
    pub route_id: String,
    /// All the [StopTime] that define the trip
    pub stop_times: Vec<StopTime>,
    /// Unique technical (not for the traveller) identifier for the Shape
    pub shape_id: Option<String>,
    /// Text that appears on signage identifying the trip's destination to riders
    pub trip_headsign: Option<String>,
    /// Public facing text used to identify the trip to riders, for instance, to identify train numbers for commuter rail trips
    pub trip_short_name: Option<String>,
    /// 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
    pub direction_id: Option<DirectionType>,
    /// 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
    pub block_id: Option<String>,
    /// Indicates wheelchair accessibility
    pub wheelchair_accessible: Availability,
    /// Indicates whether bikes are allowed
    pub bikes_allowed: BikesAllowedType,
    /// During which periods the trip runs by frequency and not by fixed timetable
    pub frequencies: Vec<Frequency>,
}

impl Type for Trip {
    fn object_type(&self) -> ObjectType {
        ObjectType::Trip
    }
}

impl Id for Trip {
    fn id(&self) -> &str {
        &self.id
    }
}

impl fmt::Display for Trip {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "route id: {}, service id: {}",
            self.route_id, self.service_id
        )
    }
}

/// General informations about the agency running the network. See <https://gtfs.org/reference/static/#agencytxt>
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct Agency {
    /// Unique technical (not for the traveller) identifier for the Agency
    #[serde(rename = "agency_id")]
    pub id: Option<String>,
    ///Full name of the transit agency
    #[serde(rename = "agency_name")]
    pub name: String,
    /// Full url of the transit agency.
    #[serde(rename = "agency_url")]
    pub url: String,
    /// Timezone where the transit agency is located
    #[serde(rename = "agency_timezone")]
    pub timezone: String,
    /// Primary language used by this transit agency
    #[serde(rename = "agency_lang")]
    pub lang: Option<String>,
    /// A voice telephone number for the specified agency
    #[serde(rename = "agency_phone")]
    pub phone: Option<String>,
    /// URL of a web page that allows a rider to purchase tickets or other fare instruments for that agency online
    #[serde(rename = "agency_fare_url")]
    pub fare_url: Option<String>,
    /// Email address actively monitored by the agency’s customer service department
    #[serde(rename = "agency_email")]
    pub email: Option<String>,
}

impl Type for Agency {
    fn object_type(&self) -> ObjectType {
        ObjectType::Agency
    }
}

impl Id for Agency {
    fn id(&self) -> &str {
        match &self.id {
            None => "",
            Some(id) => id,
        }
    }
}

impl fmt::Display for Agency {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name)
    }
}

/// A single geographical point decribing the shape of a [Trip]. See <https://gtfs.org/reference/static/#shapestxt>
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct Shape {
    /// Unique technical (not for the traveller) identifier for the Shape
    #[serde(rename = "shape_id")]
    pub id: String,
    #[serde(rename = "shape_pt_lat", default)]
    /// Latitude of a shape point
    pub latitude: f64,
    /// Longitude of a shape point
    #[serde(rename = "shape_pt_lon", default)]
    pub longitude: f64,
    /// Sequence in which the shape points connect to form the shape. Values increase along the trip but do not need to be consecutive.
    #[serde(rename = "shape_pt_sequence")]
    pub sequence: usize,
    /// 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
    #[serde(rename = "shape_dist_traveled")]
    pub dist_traveled: Option<f32>,
}

impl Type for Shape {
    fn object_type(&self) -> ObjectType {
        ObjectType::Shape
    }
}

impl Id for Shape {
    fn id(&self) -> &str {
        &self.id
    }
}

/// Defines one possible fare. See <https://gtfs.org/reference/static/#fare_attributestxt>
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct FareAttribute {
    /// Unique technical (not for the traveller) identifier for the FareAttribute
    #[serde(rename = "fare_id")]
    pub id: String,
    /// Fare price, in the unit specified by [FareAttribute::currency]
    pub price: String,
    /// Currency used to pay the fare.
    #[serde(rename = "currency_type")]
    pub currency: String,
    ///Indicates when the fare must be paid
    pub payment_method: PaymentMethod,
    /// Indicates the number of transfers permitted on this fare
    pub transfers: Transfers,
    /// Identifies the relevant agency for a fare
    pub agency_id: Option<String>,
    /// Length of time in seconds before a transfer expires
    pub transfer_duration: Option<usize>,
}

impl Id for FareAttribute {
    fn id(&self) -> &str {
        &self.id
    }
}

impl Type for FareAttribute {
    fn object_type(&self) -> ObjectType {
        ObjectType::Fare
    }
}

/// Defines one possible fare. See <https://gtfs.org/schedule/reference/#fare_rulestxt>
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct FareRule {
    /// ID of the referenced FareAttribute.
    pub fare_id: String,
    /// ID of a [Route] associated with the fare class
    pub route_id: Option<String>,
    /// Identifies an origin zone. References a [Stop].zone_id
    pub origin_id: Option<String>,
    /// Identifies an destination zone. References a [Stop].zone_id
    pub destination_id: Option<String>,
    /// Identifies the zones that a rider will enter while using a given fare class. References a [Stop].zone_id
    pub contains_id: Option<String>,
}

/// A [Frequency] before being merged into the corresponding [Trip]
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct RawFrequency {
    /// References the [Trip] that uses frequency
    pub trip_id: String,
    /// Time at which the first vehicle departs from the first stop of the trip
    #[serde(
        deserialize_with = "deserialize_time",
        serialize_with = "serialize_time"
    )]
    pub start_time: u32,
    /// Time at which service changes to a different headway (or ceases) at the first stop in the trip
    #[serde(
        deserialize_with = "deserialize_time",
        serialize_with = "serialize_time"
    )]
    pub end_time: u32,
    /// Time, in seconds, between departures from the same stop (headway) for the trip, during the time interval specified by start_time and end_time
    pub headway_secs: u32,
    /// Indicates the type of service for a trip
    pub exact_times: Option<ExactTimes>,
}

/// Timetables can be defined by the frequency of their vehicles. See <<https://gtfs.org/reference/static/#frequenciestxt>>
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Frequency {
    /// Time at which the first vehicle departs from the first stop of the trip
    pub start_time: u32,
    /// Time at which service changes to a different headway (or ceases) at the first stop in the trip
    pub end_time: u32,
    /// Time, in seconds, between departures from the same stop (headway) for the trip, during the time interval specified by start_time and end_time
    pub headway_secs: u32,
    /// Indicates the type of service for a trip
    pub exact_times: Option<ExactTimes>,
}

impl Frequency {
    /// Converts from a [RawFrequency] to a [Frequency]
    pub fn from(frequency: &RawFrequency) -> Self {
        Self {
            start_time: frequency.start_time,
            end_time: frequency.end_time,
            headway_secs: frequency.headway_secs,
            exact_times: frequency.exact_times,
        }
    }
}

/// Transfer information between stops before merged into [Stop]
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct RawTransfer {
    /// Stop from which to leave
    pub from_stop_id: String,
    /// Stop which to transfer to
    pub to_stop_id: String,
    /// Type of the transfer
    pub transfer_type: TransferType,
    /// Minimum time needed to make the transfer in seconds
    pub min_transfer_time: Option<u32>,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
/// Transfer information between stops
pub struct StopTransfer {
    /// Stop which to transfer to
    pub to_stop_id: String,
    /// Type of the transfer
    pub transfer_type: TransferType,
    /// Minimum time needed to make the transfer in seconds
    pub min_transfer_time: Option<u32>,
}

impl From<RawTransfer> for StopTransfer {
    /// Converts from a [RawTransfer] to a [StopTransfer]
    fn from(transfer: RawTransfer) -> Self {
        Self {
            to_stop_id: transfer.to_stop_id,
            transfer_type: transfer.transfer_type,
            min_transfer_time: transfer.min_transfer_time,
        }
    }
}

/// Meta-data about the feed. See <https://gtfs.org/reference/static/#feed_infotxt>
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FeedInfo {
    /// Full name of the organization that publishes the dataset.
    #[serde(rename = "feed_publisher_name")]
    pub name: String,
    /// URL of the dataset publishing organization's website
    #[serde(rename = "feed_publisher_url")]
    pub url: String,
    /// Default language used for the text in this dataset
    #[serde(rename = "feed_lang")]
    pub lang: String,
    /// Defines the language that should be used when the data consumer doesn’t know the language of the rider
    pub default_lang: Option<String>,
    /// The dataset provides complete and reliable schedule information for service in the period from this date
    #[serde(
        deserialize_with = "deserialize_option_date",
        serialize_with = "serialize_option_date",
        rename = "feed_start_date",
        default
    )]
    pub start_date: Option<NaiveDate>,
    ///The dataset provides complete and reliable schedule information for service in the period until this date
    #[serde(
        deserialize_with = "deserialize_option_date",
        serialize_with = "serialize_option_date",
        rename = "feed_end_date",
        default
    )]
    pub end_date: Option<NaiveDate>,
    /// String that indicates the current version of their GTFS dataset
    #[serde(rename = "feed_version")]
    pub version: Option<String>,
    /// Email address for communication regarding the GTFS dataset and data publishing practices
    #[serde(rename = "feed_contact_email")]
    pub contact_email: Option<String>,
    /// URL for contact information, a web-form, support desk, or other tools for communication regarding the GTFS dataset and data publishing practices
    #[serde(rename = "feed_contact_url")]
    pub contact_url: Option<String>,
}

impl fmt::Display for FeedInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name)
    }
}

/// A graph representation to describe subway or train, with nodes (the locations) and edges (the pathways).
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct RawPathway {
    /// Uniquely identifies the pathway
    #[serde(rename = "pathway_id")]
    pub id: String,
    /// Location at which the pathway begins
    pub from_stop_id: String,
    /// Location at which the pathway ends
    pub to_stop_id: String,
    /// Type of pathway between the specified (from_stop_id, to_stop_id) pair
    #[serde(rename = "pathway_mode")]
    pub mode: PathwayMode,
    /// Indicates in which direction the pathway can be used
    pub is_bidirectional: PathwayDirectionType,
    /// Horizontal length in meters of the pathway from the origin location to the destination location
    pub length: Option<f32>,
    /// Average time in seconds needed to walk through the pathway from the origin location to the destination location
    pub traversal_time: Option<u32>,
    /// Number of stairs of the pathway
    pub stair_count: Option<i32>,
    /// Maximum slope ratio of the pathway
    pub max_slope: Option<f32>,
    /// Minimum width of the pathway in meters
    pub min_width: Option<f32>,
    /// String of text from physical signage visible to transit riders
    pub signposted_as: Option<String>,
    /// Same than the signposted_as field, but when the pathways is used backward
    pub reversed_signposted_as: Option<String>,
}

impl Id for RawPathway {
    fn id(&self) -> &str {
        &self.id
    }
}

impl Type for RawPathway {
    fn object_type(&self) -> ObjectType {
        ObjectType::Pathway
    }
}

/// Pathway going from a stop to another.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Pathway {
    /// Uniquely identifies the pathway
    pub id: String,
    /// Location at which the pathway ends
    pub to_stop_id: String,
    /// Type of pathway between the specified (from_stop_id, to_stop_id) pair
    pub mode: PathwayMode,
    /// Indicates in which direction the pathway can be used
    pub is_bidirectional: PathwayDirectionType,
    /// Horizontal length in meters of the pathway from the origin location to the destination location
    pub length: Option<f32>,
    /// Average time in seconds needed to walk through the pathway from the origin location to the destination location
    pub traversal_time: Option<u32>,
    /// Number of stairs of the pathway
    pub stair_count: Option<i32>,
    /// Maximum slope ratio of the pathway
    pub max_slope: Option<f32>,
    /// Minimum width of the pathway in meters
    pub min_width: Option<f32>,
    /// String of text from physical signage visible to transit riders
    pub signposted_as: Option<String>,
    /// Same than the signposted_as field, but when the pathways is used backward
    pub reversed_signposted_as: Option<String>,
}

impl Id for Pathway {
    fn id(&self) -> &str {
        &self.id
    }
}

impl Type for Pathway {
    fn object_type(&self) -> ObjectType {
        ObjectType::Pathway
    }
}

impl From<RawPathway> for Pathway {
    /// Converts from a [RawPathway] to a [Pathway]
    fn from(raw: RawPathway) -> Self {
        Self {
            id: raw.id,
            to_stop_id: raw.to_stop_id,
            mode: raw.mode,
            is_bidirectional: raw.is_bidirectional,
            length: raw.length,
            max_slope: raw.max_slope,
            min_width: raw.min_width,
            reversed_signposted_as: raw.reversed_signposted_as,
            signposted_as: raw.signposted_as,
            stair_count: raw.stair_count,
            traversal_time: raw.traversal_time,
        }
    }
}

/// Format of the data
#[derive(Clone, Debug, Serialize, PartialEq)]
pub enum SourceFormat {
    /// `Directory` means the data comes from a directory
    Directory,
    /// `Zip` means the data were read from a zip
    Zip,
}