1use crate::bounding_box::BoundingBox;
4use crate::coordinate::GeographicCoordinate;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub enum TransportationMode {
11 Automobile,
13 Bicycle,
15 Pedestrian,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
21#[serde(rename_all = "snake_case")]
22pub enum UnitSystem {
23 Metric,
25 Imperial,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
31pub struct AvoidOptions {
32 pub toll_roads: bool,
34 pub limited_access_highways: bool,
36 pub ferries: bool,
38 pub unpaved_roads: bool,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
50#[serde(rename_all = "snake_case")]
51pub enum RouteStrategy {
52 #[default]
54 Fastest,
55 Shortest,
57}
58
59#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61pub struct RouteOptions {
62 pub transportation_mode: TransportationMode,
64 pub route_strategy: RouteStrategy,
66 pub unit_system: UnitSystem,
68 pub avoid_options: AvoidOptions,
70 pub departure_timestamp_seconds: Option<u64>,
73}
74
75impl Default for RouteOptions {
76 fn default() -> Self {
77 Self {
78 transportation_mode: TransportationMode::Automobile,
79 route_strategy: RouteStrategy::Fastest,
80 unit_system: UnitSystem::Metric,
81 avoid_options: AvoidOptions::default(),
82 departure_timestamp_seconds: None,
83 }
84 }
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
89#[serde(rename_all = "snake_case")]
90pub enum TurnDirection {
91 Straight,
93 SharpLeft,
95 Left,
97 SlightLeft,
99 SlightRight,
101 Right,
103 SharpRight,
105 UTurn,
107 LeavingRoad,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
119pub enum ManeuverType {
120 Departure,
122 Arrival,
124 Continue,
126 Turn(TurnDirection),
128 Merge,
130 OnRamp,
132 OffRamp,
134 Fork,
136 Roundabout(u8),
138 Ferry,
140}
141
142const TURN_STABLE_LABEL_PREFIX: &str = "turn";
144const ROUNDABOUT_STABLE_LABEL_PREFIX: &str = "roundabout";
146const STABLE_LABEL_PARAMETER_SEPARATOR: char = '-';
148const STABLE_LABEL_ROUNDABOUT_MINIMUM_EXIT_INDEX: u8 = 1;
150const STABLE_LABEL_SERDE_EXPECTATION: &str = "a stable maneuver label such as \
152 \"departure\", \"turn-left\" or \"roundabout-2\"";
153
154fn turn_direction_label_segment(turn_direction: TurnDirection) -> &'static str {
157 match turn_direction {
158 TurnDirection::Straight => "straight",
159 TurnDirection::SharpLeft => "sharp-left",
160 TurnDirection::Left => "left",
161 TurnDirection::SlightLeft => "slight-left",
162 TurnDirection::SlightRight => "slight-right",
163 TurnDirection::Right => "right",
164 TurnDirection::SharpRight => "sharp-right",
165 TurnDirection::UTurn => "u-turn",
166 TurnDirection::LeavingRoad => "leaving-road",
167 }
168}
169
170fn turn_direction_from_label_segment(label_segment: &str) -> Option<TurnDirection> {
173 Some(match label_segment {
174 "straight" => TurnDirection::Straight,
175 "sharp-left" => TurnDirection::SharpLeft,
176 "left" => TurnDirection::Left,
177 "slight-left" => TurnDirection::SlightLeft,
178 "slight-right" => TurnDirection::SlightRight,
179 "right" => TurnDirection::Right,
180 "sharp-right" => TurnDirection::SharpRight,
181 "u-turn" => TurnDirection::UTurn,
182 "leaving-road" => TurnDirection::LeavingRoad,
183 _ => return None,
184 })
185}
186
187impl ManeuverType {
188 pub fn stable_label(&self) -> String {
193 match self {
194 Self::Departure => "departure".to_string(),
195 Self::Arrival => "arrival".to_string(),
196 Self::Continue => "continue".to_string(),
197 Self::Turn(turn_direction) => format!(
198 "{TURN_STABLE_LABEL_PREFIX}{STABLE_LABEL_PARAMETER_SEPARATOR}{}",
199 turn_direction_label_segment(*turn_direction)
200 ),
201 Self::Merge => "merge".to_string(),
202 Self::OnRamp => "on-ramp".to_string(),
203 Self::OffRamp => "off-ramp".to_string(),
204 Self::Fork => "fork".to_string(),
205 Self::Roundabout(exit_index) => format!(
206 "{ROUNDABOUT_STABLE_LABEL_PREFIX}{STABLE_LABEL_PARAMETER_SEPARATOR}{exit_index}"
207 ),
208 Self::Ferry => "ferry".to_string(),
209 }
210 }
211
212 pub fn from_stable_label(stable_label: &str) -> Option<Self> {
215 match stable_label {
216 "departure" => Some(Self::Departure),
217 "arrival" => Some(Self::Arrival),
218 "continue" => Some(Self::Continue),
219 "merge" => Some(Self::Merge),
220 "on-ramp" => Some(Self::OnRamp),
221 "off-ramp" => Some(Self::OffRamp),
222 "fork" => Some(Self::Fork),
223 "ferry" => Some(Self::Ferry),
224 _ => parameterized_from_stable_label(stable_label),
225 }
226 }
227}
228
229fn parameterized_from_stable_label(stable_label: &str) -> Option<ManeuverType> {
233 let label_parameter = |label_prefix: &str| {
234 stable_label
235 .strip_prefix(label_prefix)
236 .and_then(|rest| rest.strip_prefix(STABLE_LABEL_PARAMETER_SEPARATOR))
237 };
238 if let Some(turn_direction) =
239 label_parameter(TURN_STABLE_LABEL_PREFIX).and_then(turn_direction_from_label_segment)
240 {
241 return Some(ManeuverType::Turn(turn_direction));
242 }
243 label_parameter(ROUNDABOUT_STABLE_LABEL_PREFIX)
244 .and_then(|exit_index_text| exit_index_text.parse::<u8>().ok())
245 .filter(|exit_index| *exit_index >= STABLE_LABEL_ROUNDABOUT_MINIMUM_EXIT_INDEX)
246 .map(ManeuverType::Roundabout)
247}
248
249impl Serialize for ManeuverType {
251 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
252 serializer.serialize_str(&self.stable_label())
253 }
254}
255
256impl<'de> Deserialize<'de> for ManeuverType {
259 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
260 struct StableLabelVisitor;
261
262 impl serde::de::Visitor<'_> for StableLabelVisitor {
263 type Value = ManeuverType;
264
265 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266 formatter.write_str(STABLE_LABEL_SERDE_EXPECTATION)
267 }
268
269 fn visit_str<E: serde::de::Error>(self, label: &str) -> Result<Self::Value, E> {
270 ManeuverType::from_stable_label(label).ok_or_else(|| {
271 E::invalid_value(
272 serde::de::Unexpected::Str(label),
273 &STABLE_LABEL_SERDE_EXPECTATION,
274 )
275 })
276 }
277 }
278
279 deserializer.deserialize_str(StableLabelVisitor)
280 }
281}
282
283#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
285pub struct LaneGuidance {
286 pub lane_index: u8,
288 pub permitted_directions: Vec<TurnDirection>,
290 pub is_recommended: bool,
292}
293
294#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
296pub struct RouteStep {
297 pub distance_meters: f64,
299 pub duration_seconds: f64,
301 pub maneuver_type: ManeuverType,
303 pub instruction_display_text: String,
305 pub instruction_speech_text: String,
307 pub shape: Vec<GeographicCoordinate>,
309 pub lane_guidances: Vec<LaneGuidance>,
311}
312
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
315pub struct RouteLeg {
316 pub distance_meters: f64,
318 pub duration_seconds: f64,
320 pub steps: Vec<RouteStep>,
322}
323
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
326pub struct RouteData {
327 pub distance_meters: f64,
329 pub duration_seconds: f64,
331 pub bounding_box: BoundingBox,
333 pub legs: Vec<RouteLeg>,
335}
336
337#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
339pub struct DistanceMatrixEntry {
340 pub origin_index: u32,
342 pub destination_index: u32,
344 pub distance_meters: f64,
346 pub duration_seconds: f64,
348}
349
350#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
352pub struct DistanceMatrix {
353 pub entries: Vec<DistanceMatrixEntry>,
355}