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