gistools/readers/gtfs/schedule/fare_leg_rules.rs
1use crate::readers::csv::parse_csv_as_record;
2use alloc::{string::String, vec::Vec};
3use s2json::MValueCompatible;
4
5/// # Fare Leg Rules
6///
7/// **Optional**
8/// Defines more granular fare rules for individual legs of travel (GTFS-Fares V2).
9///
10/// Use these rules by filtering on:
11/// - `network_id`
12/// - `from_area_id`
13/// - `to_area_id`
14/// - `from_timeframe_group_id`
15/// - `to_timeframe_group_id`
16///
17/// Multiple matching strategies exist depending on the presence or absence of `rule_priority`:
18/// - If `rule_priority` does **not** exist, empty fields represent an **inverse** match against
19/// all possible values **except** those otherwise specified.
20/// - If `rule_priority` **does** exist, empty fields mean the field does not affect matching.
21///
22/// For matching an “effective fare leg” that spans multiple legs, see the specification for
23/// rules on using the first vs. last leg’s departure/arrival areas and timeframes.
24#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
25pub struct GTFSFareLegRule {
26 /// **Optional**
27 /// Identifies a group of entries in fare_leg_rules.txt that can be referenced
28 /// in `fare_transfer_rules.from_leg_group_id` or `fare_transfer_rules.to_leg_group_id`.
29 pub leg_group_id: Option<String>,
30 /// **Optional**
31 /// Identifies a route network (`routes.network_id` or `networks.network_id`) this rule applies to.
32 /// - If `rule_priority` is omitted and no matching `network_id`, empty matches “all but listed”.
33 /// - If `rule_priority` exists, empty means network does not affect matching.
34 pub network_id: Option<String>,
35 /// **Optional**
36 /// Identifies a departure area (`areas.area_id`) for this fare leg rule.
37 /// - If `rule_priority` is omitted and no matching `from_area_id`, empty matches “all but listed”.
38 /// - If `rule_priority` exists, empty means departure area does not affect matching.
39 pub from_area_id: Option<String>,
40 /// **Optional**
41 /// Identifies an arrival area (`areas.area_id`) for this fare leg rule.
42 /// - If `rule_priority` is omitted and no matching `to_area_id`, empty matches “all but listed”.
43 /// - If `rule_priority` exists, empty means arrival area does not affect matching.
44 pub to_area_id: Option<String>,
45 /// **Optional**
46 /// References a `timeframes.timeframe_group_id` for the start of the fare leg.
47 /// An empty value means the start time does not affect matching.
48 pub from_timeframe_group_id: Option<String>,
49 /// **Optional**
50 /// References a `timeframes.timeframe_group_id` for the end of the fare leg.
51 /// An empty value means the end time does not affect matching.
52 pub to_timeframe_group_id: Option<String>,
53 /// **Required**
54 /// References a `fare_products.fare_product_id`.
55 /// The rider must possess/purchase this fare product for the described leg.
56 pub fare_product_id: String,
57 /// **Optional**
58 /// Defines the order of priority in which matching rules are applied.
59 /// - Higher priority overrides lower priority when multiple rules match.
60 /// - Empty is treated as zero.
61 pub rule_priority: i64,
62}
63impl GTFSFareLegRule {
64 /// Create a new GTFSFareLegRule
65 pub fn new(source: &str) -> Vec<GTFSFareLegRule> {
66 let mut res = Vec::new();
67 for record in parse_csv_as_record::<GTFSFareLegRule>(source, None, None) {
68 res.push(record);
69 }
70 res
71 }
72}