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