valhalla_client/costing/
transit.rs1use serde::Serialize;
3
4#[serde_with::skip_serializing_none]
5#[derive(Serialize, Debug, Clone, Default, PartialEq)]
6pub(crate) struct TransitCostingOptionsInner {
7 use_bus: Option<f32>,
8 use_rail: Option<f32>,
9 use_transfers: Option<f32>,
10 filters: Option<Filters>,
11}
12
13#[derive(Serialize, Debug, Clone, Default, PartialEq)]
14pub struct TransitCostingOptions {
16 pub(crate) transit: TransitCostingOptionsInner,
17}
18impl TransitCostingOptions {
19 #[must_use]
20 pub fn builder() -> Self {
22 Self::default()
23 }
24 pub fn use_bus(mut self, use_bus: f32) -> Self {
30 self.transit.use_bus = Some(use_bus);
31 self
32 }
33 pub fn use_rail(mut self, use_rail: f32) -> Self {
39 self.transit.use_rail = Some(use_rail);
40 self
41 }
42 pub fn use_transfers(mut self, use_transfers: f32) -> Self {
48 self.transit.use_transfers = Some(use_transfers);
49 self
50 }
51 #[doc(hidden)] pub fn filter_stops<S>(mut self, ids: impl IntoIterator<Item = S>, action: Action) -> Self
65 where
66 S: Into<String>,
67 {
68 let new_filter = Filter {
69 ids: ids.into_iter().map(Into::into).collect(),
70 action,
71 };
72 if let Some(ref mut filters) = self.transit.filters {
73 filters.stops = Some(new_filter);
74 } else {
75 self.transit.filters = Some(Filters {
76 stops: Some(new_filter),
77 ..Default::default()
78 });
79 }
80 self
81 }
82 pub fn filter_routes<S>(mut self, ids: impl IntoIterator<Item = S>, action: Action) -> Self
95 where
96 S: Into<String>,
97 {
98 let new_filter = Filter {
99 ids: ids.into_iter().map(Into::into).collect(),
100 action,
101 };
102 if let Some(ref mut filters) = self.transit.filters {
103 filters.routes = Some(new_filter);
104 } else {
105 self.transit.filters = Some(Filters {
106 routes: Some(new_filter),
107 ..Default::default()
108 });
109 }
110 self
111 }
112 pub fn filter_operators<S>(mut self, ids: impl IntoIterator<Item = S>, action: Action) -> Self
125 where
126 S: Into<String>,
127 {
128 let new_filter = Filter {
129 ids: ids.into_iter().map(Into::into).collect(),
130 action,
131 };
132 if let Some(ref mut filters) = self.transit.filters {
133 filters.operators = Some(new_filter);
134 } else {
135 self.transit.filters = Some(Filters {
136 operators: Some(new_filter),
137 ..Default::default()
138 });
139 }
140 self
141 }
142}
143
144#[derive(Serialize, Debug, Clone, Copy, Default, PartialEq, Eq)]
145pub enum Action {
147 #[default]
149 Include,
150 Exclude,
152}
153
154#[serde_with::skip_serializing_none]
155#[derive(Serialize, Debug, Clone, Default, PartialEq)]
156struct Filters {
157 routes: Option<Filter>,
158 operators: Option<Filter>,
159 stops: Option<Filter>,
160}
161
162#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq)]
163struct Filter {
164 ids: Vec<String>,
165 action: Action,
166}
167
168#[cfg(test)]
169mod test {
170 use super::*;
171 #[test]
172 fn serialisation() {
173 assert_eq!(
174 serde_json::to_value(TransitCostingOptions::default()).unwrap(),
175 serde_json::json!({"transit":{}})
176 );
177 }
178
179 #[test]
180 fn builder_returns_default() {
181 assert_eq!(
182 TransitCostingOptions::builder(),
183 TransitCostingOptions::default()
184 );
185 }
186
187 #[test]
188 fn use_bus_sets_value() {
189 let opts = TransitCostingOptions::builder().use_bus(0.8);
190 assert_eq!(opts.transit.use_bus, Some(0.8));
191 }
192
193 #[test]
194 fn use_rail_sets_value() {
195 let opts = TransitCostingOptions::builder().use_rail(0.9);
196 assert_eq!(opts.transit.use_rail, Some(0.9));
197 }
198
199 #[test]
200 fn use_transfers_sets_value() {
201 let opts = TransitCostingOptions::builder().use_transfers(0.5);
202 assert_eq!(opts.transit.use_transfers, Some(0.5));
203 }
204
205 #[test]
206 fn filter_routes_sets_value() {
207 let opts = TransitCostingOptions::builder()
208 .filter_routes(vec!["NYC_AUR", "NYC_BX"], Action::Include);
209 assert!(opts.transit.filters.is_some());
210 let filters = opts.transit.filters.unwrap();
211 assert!(filters.routes.is_some());
212 let route_filter = filters.routes.unwrap();
213 assert_eq!(route_filter.ids, vec!["NYC_AUR", "NYC_BX"]);
214 assert_eq!(route_filter.action, Action::Include);
215 }
216
217 #[test]
218 fn filter_operators_sets_value() {
219 let opts =
220 TransitCostingOptions::builder().filter_operators(vec!["NYC_MTA"], Action::Exclude);
221 assert!(opts.transit.filters.is_some());
222 let filters = opts.transit.filters.unwrap();
223 assert!(filters.operators.is_some());
224 let op_filter = filters.operators.unwrap();
225 assert_eq!(op_filter.ids, vec!["NYC_MTA"]);
226 assert_eq!(op_filter.action, Action::Exclude);
227 }
228
229 #[test]
230 fn chaining_works() {
231 let opts = TransitCostingOptions::builder()
232 .use_bus(0.7)
233 .use_rail(0.9)
234 .use_transfers(0.4);
235 assert_eq!(opts.transit.use_bus, Some(0.7));
236 assert_eq!(opts.transit.use_rail, Some(0.9));
237 assert_eq!(opts.transit.use_transfers, Some(0.4));
238 }
239}