Skip to main content

google_maps/directions/request/location/
mod.rs

1//! Contains the `Location` enum and its associated traits. It is used to
2//! specify origin and destination locations in the form of a text address,
3//! latitude/longitude pair, or Google Place ID.
4
5#[cfg(feature = "geo")]
6mod geo;
7
8// -----------------------------------------------------------------------------
9
10use crate::types::LatLng;
11use crate::GoogleMapsError;
12use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
13use rust_decimal::Decimal;
14
15// -----------------------------------------------------------------------------
16//
17/// Used to specify the address, latitude/longitude, or place ID for the origin
18/// and destination.
19#[cfg(not(feature = "geo"))]
20#[derive(
21    Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize,
22)]
23pub enum Location {
24    /// If you pass an address, the Directions service geocodes the string and
25    /// converts it to a latitude/longitude coordinate to calculate directions.
26    /// This coordinate may be different from that returned by the Geocoding
27    /// API, for example a building entrance rather than its center.
28    Address(String),
29    /// If you pass coordinates, they are used unchanged to calculate
30    /// directions.
31    LatLng(LatLng),
32    /// The place ID may only be specified if the request includes an API key or
33    /// a Google Maps Platform Premium Plan client ID. You can retrieve place
34    /// IDs from the Geocoding API and the Places API (including Place
35    /// Autocomplete). For an example using place IDs from Place Autocomplete,
36    /// see [Place Autocomplete and Directions](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-directions).
37    /// For more about place IDs, see the [Place ID overview](https://developers.google.com/places/place-id).
38    PlaceId(String),
39} // enum
40
41// -----------------------------------------------------------------------------
42
43impl std::convert::From<&Self> for Location {
44    /// Converts a borrowed `&Locations` enum into an owned `Location` enum by
45    /// cloning it.
46    fn from(location: &Self) -> Self {
47        location.clone()
48    } // fn
49} // impl
50
51// -----------------------------------------------------------------------------
52
53#[cfg(not(feature = "geo"))]
54impl std::convert::From<&Location> for String {
55    /// Converts a `Location` enum to a `String` that contains a URL-encoded
56    /// [location](https://developers.google.com/maps/documentation/directions/intro#required-parameters)
57    /// value.
58    fn from(location: &Location) -> Self {
59        match location {
60            Location::Address(address) => {
61                utf8_percent_encode(address, NON_ALPHANUMERIC).to_string()
62            }
63
64            Location::LatLng(latlng) => {
65                utf8_percent_encode(&Self::from(latlng), NON_ALPHANUMERIC).to_string()
66            }
67
68            Location::PlaceId(place_id) => {
69                utf8_percent_encode(&format!("place_id:{place_id}"), NON_ALPHANUMERIC).to_string()
70            }
71        } // match
72    } // fn
73} // impl
74
75// -----------------------------------------------------------------------------
76//
77/// Used to specify the address, latitude/longitude, or place ID for the origin
78/// and destination.
79#[cfg(feature = "geo")]
80#[derive(Clone, Debug, PartialEq)]
81pub enum Location {
82    /// If you pass an address, the Directions service geocodes the string and
83    /// converts it to a latitude/longitude coordinate to calculate directions.
84    /// This coordinate may be different from that returned by the Geocoding
85    /// API, for example a building entrance rather than its center.
86    Address(String),
87    /// If you pass coordinates, they are used unchanged to calculate
88    /// directions.
89    LatLng(LatLng),
90    /// The place ID may only be specified if the request includes an API key or
91    /// a Google Maps Platform Premium Plan client ID. You can retrieve place
92    /// IDs from the Geocoding API and the Places API (including Place
93    /// Autocomplete). For an example using place IDs from Place Autocomplete,
94    /// see [Place Autocomplete and Directions](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-directions).
95    /// For more about place IDs, see the [Place ID overview](https://developers.google.com/places/place-id).
96    PlaceId(String),
97    /// If you pass coordinates, they are used unchanged to calculate
98    /// directions. This variant supports the
99    /// [geo](https://crates.io/crates/geo) crate's
100    /// [Coord](https://docs.rs/geo/latest/geo/geometry/struct.Coord.html) type.
101    Coord(geo_types::geometry::Coord),
102    /// If you pass a point, it is used unchanged to calculate directions. This
103    /// variant supports the [geo](https://crates.io/crates/geo) crate's
104    /// [Point](https://docs.rs/geo/latest/geo/geometry/struct.Point.html) type.
105    Point(geo_types::geometry::Point),
106} // enum
107
108// -----------------------------------------------------------------------------
109
110#[cfg(feature = "geo")]
111impl std::convert::From<&Location> for String {
112    /// Converts a `Location` enum to a `String` that contains a URL-encoded
113    /// [location](https://developers.google.com/maps/documentation/directions/intro#required-parameters)
114    /// value.
115    fn from(location: &Location) -> Self {
116        match location {
117            Location::Address(address) => {
118                utf8_percent_encode(address, NON_ALPHANUMERIC).to_string()
119            }
120
121            Location::LatLng(latlng) => {
122                utf8_percent_encode(&Self::from(latlng), NON_ALPHANUMERIC).to_string()
123            }
124
125            Location::PlaceId(place_id) => {
126                utf8_percent_encode(&format!("place_id:{place_id}"), NON_ALPHANUMERIC).to_string()
127            }
128
129            Location::Coord(coordinate) => utf8_percent_encode(
130                &format!(
131                    "{latitude},{longitude}",
132                    latitude = coordinate.y,
133                    longitude = coordinate.x,
134                ),
135                NON_ALPHANUMERIC,
136            )
137            .to_string(),
138
139            Location::Point(point) => utf8_percent_encode(
140                &format!(
141                    "{latitude},{longitude}",
142                    latitude = point.y(),
143                    longitude = point.x()
144                ),
145                NON_ALPHANUMERIC,
146            )
147            .to_string(),
148        } // match
149    } // fn
150} // impl
151
152// -----------------------------------------------------------------------------
153
154impl Location {
155    /// If you pass an address, the Directions service geocodes the string and
156    /// converts it to a latitude/longitude coordinate to calculate directions.
157    /// This coordinate may be different from that returned by the Geocoding
158    /// API, for example a building entrance rather than its center.
159    pub fn from_address(address: impl Into<String>) -> Self {
160        Self::Address(address.into())
161    } // fn
162} // impl
163
164// -----------------------------------------------------------------------------
165
166impl Location {
167    /// The place ID may only be specified if the request includes an API key or
168    /// a Google Maps Platform Premium Plan client ID. You can retrieve place
169    /// IDs from the Geocoding API and the Places API (including Place
170    /// Autocomplete). For an example using place IDs from Place Autocomplete,
171    /// see [Place Autocomplete and Directions](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-directions).
172    /// For more about place IDs, see the [Place ID overview](https://developers.google.com/places/place-id).
173    pub fn from_place_id(place_id: impl Into<String>) -> Self {
174        Self::PlaceId(place_id.into())
175    } // fn
176} // impl
177
178// -----------------------------------------------------------------------------
179
180impl Location {
181    /// Takes individual latitude & longitude `Decimal` coordinates and
182    /// converts them into a `Location` structure. If either the latitude
183    /// (-90.0 to +90.0) or longitude (-180.0 to +180.0) are out of range, this
184    /// function will return an error.
185    pub fn try_from_dec(latitude: Decimal, longitude: Decimal) -> Result<Self, GoogleMapsError> {
186        let latlng = LatLng::try_from_dec(latitude, longitude)?;
187        Ok(Self::LatLng(latlng))
188    } // fn
189} // impl
190
191// -----------------------------------------------------------------------------
192
193impl Location {
194    /// Takes individual latitude & longitude `f32` coordinates and
195    /// converts them into a `Location` structure. If either the latitude
196    /// (-90.0 to +90.0) or longitude (-180.0 to +180.0) are out of range, this
197    /// function will return an error.
198    pub fn try_from_f32(latitude: f32, longitude: f32) -> Result<Self, GoogleMapsError> {
199        let latlng = LatLng::try_from_f32(latitude, longitude)?;
200        Ok(Self::LatLng(latlng))
201    } // fn
202} // impl
203
204// -----------------------------------------------------------------------------
205
206impl Location {
207    /// Takes individual latitude & longitude `f64` coordinates and
208    /// converts them into a `Location` structure. If either the latitude
209    /// (-90.0 to +90.0) or longitude (-180.0 to +180.0) are out of range, this
210    /// function will return an error.
211    pub fn try_from_f64(latitude: f64, longitude: f64) -> Result<Self, GoogleMapsError> {
212        let latlng = LatLng::try_from_f64(latitude, longitude)?;
213        Ok(Self::LatLng(latlng))
214    } // fn
215} // impl
216
217// -----------------------------------------------------------------------------
218
219impl From<LatLng> for Location {
220    /// Converts an owned `LatLng` coordinates type into a `Location` type.
221     fn from(latlng: LatLng) -> Self {
222        Self::LatLng(latlng)
223    } // fn
224} // impl
225
226// -----------------------------------------------------------------------------
227
228impl From<&LatLng> for Location {
229    /// Converts a borrowed `&LatLng` coordinates type into a `Location` type.
230     fn from(latlng: &LatLng) -> Self {
231        Self::LatLng(*latlng)
232    } // fn
233} // impl