google_maps2/directions/request/avoid.rs
1//! Contains the `Avoid` enum and its associated traits. It is used to route
2//! around features such as ferries, highways, and tolls.
3
4use crate::directions::error::Error as DirectionsError;
5use crate::error::Error as GoogleMapsError;
6use phf::phf_map;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9// -----------------------------------------------------------------------------
10
11/// Used to specify features that calculated routes should
12/// [avoid](https://developers.google.com/maps/documentation/directions/intro#Restrictions).
13///
14/// Directions may be calculated that adhere to certain restrictions.
15/// Restrictions are indicated by use of the `avoid` parameter, and an argument to
16/// that parameter indicating the restriction to avoid. The following
17/// restrictions are supported:
18///
19/// * Tolls
20/// * Highways
21/// * Ferries
22///
23/// It's possible to request a route that avoids any combination of tolls,
24/// highways and ferries by passing both restrictions to the avoid parameter.
25/// For example: `avoid=tolls|highways|ferries`.
26///
27/// Note: the addition of restrictions does not preclude routes that include the
28/// restricted feature; it simply biases the result to more favorable routes.
29
30#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
31#[repr(u8)]
32pub enum Avoid {
33 /// Indicates that the calculated route should avoid ferries.
34 Ferries = 0,
35 /// Indicates that the calculated route should avoid highways.
36 Highways = 1,
37 /// Indicates that the calculated route should avoid indoor steps for
38 /// walking and transit directions. Only requests that include an API key or
39 /// a Google Maps Platform Premium Plan client ID will receive indoor steps
40 /// by default.
41 Indoor = 2,
42 /// Indicates that the calculated route should avoid toll roads/bridges.
43 #[default]
44 Tolls = 3,
45} // enum
46
47// -----------------------------------------------------------------------------
48
49impl<'de> Deserialize<'de> for Avoid {
50 /// Manual implementation of `Deserialize` for `serde`. This will take
51 /// advantage of the `phf`-powered `TryFrom` implementation for this type.
52 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
53 let string = String::deserialize(deserializer)?;
54 match Self::try_from(string.as_str()) {
55 Ok(variant) => Ok(variant),
56 Err(error) => Err(serde::de::Error::custom(error.to_string())),
57 } // match
58 } // fn
59} // impl
60
61// -----------------------------------------------------------------------------
62
63impl Serialize for Avoid {
64 /// Manual implementation of `Serialize` for `serde`.
65 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
66 where
67 S: Serializer,
68 {
69 serializer.serialize_str(std::convert::Into::<&str>::into(self))
70 } // fn
71} // impl
72
73// -----------------------------------------------------------------------------
74
75impl std::convert::From<&Avoid> for &str {
76 /// Converts an `Avoid` enum to a `String` that contains a
77 /// [restrictions](https://developers.google.com/maps/documentation/directions/intro#Restrictions)
78 /// code.
79 fn from(avoid: &Avoid) -> Self {
80 match avoid {
81 Avoid::Ferries => "ferries",
82 Avoid::Highways => "highways",
83 Avoid::Indoor => "indoor",
84 Avoid::Tolls => "tolls",
85 } // match
86 } // fn
87} // impl
88
89// -----------------------------------------------------------------------------
90
91impl std::fmt::Display for Avoid {
92 /// Converts an `Avoid` enum to a `String` that contains a
93 /// [restrictions](https://developers.google.com/maps/documentation/directions/intro#Restrictions)
94 /// code.
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(f, "{}", std::convert::Into::<&str>::into(self))
97 } // fmt
98} // impl
99
100// -----------------------------------------------------------------------------
101
102impl std::convert::From<&Self> for Avoid {
103 /// Converts a borrowed `&Avoid` enum into an owned `Avoid` enum by cloning
104 /// it.
105 fn from(avoid: &Self) -> Self {
106 avoid.clone()
107 } // fn
108} // impl
109
110// -----------------------------------------------------------------------------
111
112impl std::convert::From<&Avoid> for String {
113 /// Converts an `Avoid` enum to a `String` that contains a
114 /// [restrictions](https://developers.google.com/maps/documentation/directions/intro#Restrictions)
115 /// code.
116 fn from(avoid: &Avoid) -> Self {
117 std::convert::Into::<&str>::into(avoid).to_string()
118 } // fn
119} // impl
120
121// -----------------------------------------------------------------------------
122
123static RESTRICTIONS_BY_CODE: phf::Map<&'static str, Avoid> = phf_map! {
124 "ferries" => Avoid::Ferries,
125 "highways" => Avoid::Highways,
126 "indoor" => Avoid::Indoor,
127 "tolls" => Avoid::Tolls,
128};
129
130// -----------------------------------------------------------------------------
131
132impl std::convert::TryFrom<&str> for Avoid {
133 // Error definitions are contained in the
134 // `google_maps\src\directions\error.rs` module.
135 type Error = GoogleMapsError;
136 /// Gets an `Avoid` enum from a `String` that contains a valid
137 /// [restrictions](https://developers.google.com/maps/documentation/directions/intro#Restrictions)
138 /// code.
139 fn try_from(restriction_code: &str) -> Result<Self, Self::Error> {
140 Ok(RESTRICTIONS_BY_CODE
141 .get(restriction_code)
142 .cloned()
143 .ok_or_else(|| DirectionsError::InvalidAvoidCode(restriction_code.to_string()))?)
144 } // fn
145} // impl
146
147// -----------------------------------------------------------------------------
148
149impl std::str::FromStr for Avoid {
150 // Error definitions are contained in the
151 // `google_maps\src\directions\error.rs` module.
152 type Err = GoogleMapsError;
153 /// Gets an `Avoid` enum from a `String` that contains a valid
154 /// [restrictions](https://developers.google.com/maps/documentation/directions/intro#Restrictions)
155 /// code.
156 fn from_str(restriction_code: &str) -> Result<Self, Self::Err> {
157 Ok(RESTRICTIONS_BY_CODE
158 .get(restriction_code)
159 .cloned()
160 .ok_or_else(|| DirectionsError::InvalidAvoidCode(restriction_code.to_string()))?)
161 } // fn
162} // impl
163
164// -----------------------------------------------------------------------------
165
166impl Avoid {
167 /// Formats a `Avoid` enum into a string that is presentable to the end
168 /// user.
169 #[must_use]
170 pub const fn display(&self) -> &str {
171 match self {
172 Self::Ferries => "Ferries",
173 Self::Highways => "Highways",
174 Self::Indoor => "Indoor",
175 Self::Tolls => "Tolls",
176 } // match
177 } // fn
178} // impl