valhalla_client/
matrix.rs

1use crate::costing;
2use crate::shapes::ShapeFormat;
3pub use crate::DateTime;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7#[serde_with::skip_serializing_none]
8#[derive(Serialize, Default, Debug)]
9pub struct Manifest {
10    pub(crate) targets: Vec<Location>,
11    pub(crate) sources: Vec<Location>,
12    #[serde(flatten)]
13    costing: costing::Costing,
14    id: Option<String>,
15    matrix_locations: Option<u32>,
16    date_time: Option<DateTime>,
17    verbose: Option<bool>,
18    shape_format: Option<ShapeFormat>,
19}
20impl Manifest {
21    pub fn builder() -> Self {
22        Default::default()
23    }
24    /// Sets the source and targets of the matrix
25    pub fn sources_to_targets(
26        mut self,
27        sources: impl IntoIterator<Item = Location>,
28        targets: impl IntoIterator<Item = Location>,
29    ) -> Self {
30        self.sources = sources.into_iter().collect();
31        self.targets = targets.into_iter().collect();
32        self
33    }
34    /// Configures the costing model
35    ///
36    /// Valhalla's routing service uses dynamic, run-time costing to generate the route path.
37    /// Can be configured with different settings depending on the costing model used.
38    ///
39    /// **Note:** multimodal costing is not supported for the time-distance matrix service at this time.
40    ///
41    /// Default: [`costing::Costing::Auto`]
42    pub fn costing(mut self, costing: costing::Costing) -> Self {
43        self.costing = costing;
44        self
45    }
46    /// Name your route request.
47    ///
48    /// If id is specified, the naming will be sent through to the response.
49    pub fn id(mut self, id: impl ToString) -> Self {
50        self.id = Some(id.to_string());
51        self
52    }
53    /// Sets the minimum number of locations that need to be found satisfying the request
54    ///
55    /// Allows a partial result to be returned.
56    ///
57    /// This is basically equivalent to:
58    /// > "find the closest or best N locations out of the full location set"
59    pub fn minimum_matrix_locations_count(mut self, count: u32) -> Self {
60        self.matrix_locations = Some(count);
61        self
62    }
63    /// Shortcut for configuring the arrival/departure date_time settings globally
64    /// instead of specifying it for each source/target.
65    ///
66    /// See [`Location::date_time`] if you want a more granular API.
67    /// Valhalla will translate this to setting the value on all `source` locations when
68    /// [`DateTime::from_current_departure_time`] or [`DateTime::from_departure_time`] is used and
69    /// on all `target` locations when [`DateTime::from_arrival_time`].
70    ///
71    /// **Note:**
72    /// There are important limitations to time awareness.
73    /// Due to algorithmic complexity, we disallow time-dependence for certain combinations
74    /// of date_time on locations:
75    /// - when there are more sources than `target`s:
76    ///   - [`Location::date_time`] on any `source`
77    ///   - using [`Self::date_time`] with [`DateTime::from_current_departure_time`] and [`DateTime::from_departure_time`]
78    /// - when there's more or equal amount of `target`s than/as `source`s
79    ///   - [`Location::date_time`] on any `target`
80    ///   - [`DateTime::from_arrival_time`]
81    pub fn date_time(mut self, date_time: DateTime) -> Self {
82        self.date_time = Some(date_time);
83        self
84    }
85    /// Modifies the verbosity of the output:
86    /// - `true` will output a flat list of objects for distances & durations explicitly specifying
87    ///   the `source` & `target` indices.
88    /// - `false` will return more compact, nested row-major distances & durations arrays and
89    ///   not echo `sources` and `targets`
90    ///
91    /// Default: `true`
92    pub fn verbose_output(mut self, verbose: bool) -> Self {
93        self.verbose = Some(verbose);
94        self
95    }
96    /// Specifies the [`ShapeFormat`] for the path shape of each connection.
97    pub fn shape_format(mut self, shape_format: ShapeFormat) -> Self {
98        self.shape_format = Some(shape_format);
99        self
100    }
101}
102
103#[serde_with::skip_serializing_none]
104#[derive(Serialize, Default, Clone, Copy, PartialEq, Debug)]
105pub struct Location {
106    lat: f32,
107    lon: f32,
108    #[serde(serialize_with = "super::serialize_naive_date_time_opt")]
109    date_time: Option<chrono::NaiveDateTime>,
110}
111impl From<super::Coordinate> for Location {
112    fn from((longitude, latitude): super::Coordinate) -> Self {
113        Self {
114            lat: latitude,
115            lon: longitude,
116            date_time: None,
117        }
118    }
119}
120impl Location {
121    /// Creates a new location from a longitude/latitude
122    pub fn new(longitude: f32, latitude: f32) -> Self {
123        Self::from((longitude, latitude))
124    }
125    /// Expected date/time for the user to be at the location in the local time zone of departure or arrival.
126    ///
127    /// Offers more granularity over setting time than the global [`Manifest::date_time`].
128    ///
129    /// **Note:**
130    /// This behaves differently for the matrix in comparison to the route API:
131    /// - If set on the sources and there's more targets than sources,
132    ///   it will behave like a *"Specified departure time"* on the sources.
133    /// - If set on the targets and there's less targets than sources,
134    ///   it will behave like a *"Specified arrival time"* on the targets.
135    ///
136    /// **Note:**
137    /// There are important limitations to time awareness.
138    /// Due to algorithmic complexity, we disallow time-dependence for certain combinations
139    /// of date_time on locations:
140    /// - when there are more sources than `target`s:
141    ///   - [`Location::date_time`] on any `source`
142    ///   - using [`Self::date_time`] with [`DateTime::from_current_departure_time`] and [`DateTime::from_departure_time`]
143    /// - when there's more or equal amount of `target`s than/as `source`s
144    ///   - [`Location::date_time`] on any `target`
145    ///   - [`DateTime::from_arrival_time`]
146    pub fn date_time(mut self, date_time: chrono::NaiveDateTime) -> Self {
147        self.date_time = Some(date_time);
148        self
149    }
150}
151
152/// [`Location`] which was configured in the input
153///
154/// Present only in `verbose` mode. Verbosity can be set via [`Manifest::verbose_output`]
155#[derive(Deserialize, Default, Clone, Copy, PartialEq, Debug)]
156pub struct VerboseLocation {
157    /// Latitude as defined in [`super::Coordinate`]
158    pub lat: f32,
159    /// Longitude as defined in [`super::Coordinate`]
160    pub lon: f32,
161    /// time configured via [`Location::date_time`]
162    pub date_time: Option<chrono::NaiveDateTime>,
163}
164
165impl From<Location> for VerboseLocation {
166    fn from(value: Location) -> Self {
167        Self {
168            lat: value.lat,
169            lon: value.lon,
170            date_time: value.date_time,
171        }
172    }
173}
174
175impl From<VerboseLocation> for Location {
176    fn from(value: VerboseLocation) -> Self {
177        Self {
178            lat: value.lat,
179            lon: value.lon,
180            date_time: value.date_time,
181        }
182    }
183}
184
185#[derive(Deserialize, Debug, Clone)]
186#[serde(untagged)]
187pub enum Response {
188    /// Returned in `verbose` mode.
189    ///
190    /// Verbosity can be set via [`Manifest::verbose_output`]
191    Verbose(VerboseResponse),
192    /// Returned in non-`verbose` mode.
193    ///
194    /// Verbosity can be set via [`Manifest::verbose_output`]
195    Concise(ConciseResponse),
196}
197#[derive(Deserialize, Debug, Clone)]
198pub struct VerboseResponse {
199    /// Name of the route request.
200    ///
201    /// If id is specified via [`Manifest::id`] the naming will be sent through to the response.
202    pub id: Option<String>,
203    /// Algorithm used
204    pub algorithm: String,
205    /// Distance units for output.
206    ///
207    /// Possible unit types are miles via [`super::Units::Imperial`] and kilometers via [`super::Units::Metric`].
208    ///
209    /// Default: [`super::Units::Metric`]
210    pub units: super::Units,
211    /// This array may contain warning objects informing about deprecated request parameters, clamped values etc.
212    #[serde(default = "Vec::new")]
213    pub warnings: Vec<Value>,
214    /// The sources of the matrix
215    pub sources: Vec<VerboseLocation>,
216    /// The targets of the matrix
217    pub targets: Vec<VerboseLocation>,
218    /// A flat list of objects for distances & durations explicitly specifying the `source` & `target` indices.
219    ///
220    /// The arrays rows are:
221    /// - time and distance from the first source location to all target locations,
222    /// - time and distance from the second source location to all target locations,
223    /// - etc.
224    pub sources_to_targets: Vec<Vec<VerboseSourceToTarget>>,
225}
226#[derive(Deserialize, Debug, Clone)]
227pub struct ConciseResponse {
228    /// Name of the route request.
229    ///
230    /// If id is specified via [`Manifest::id`] the naming will be sent through to the response.
231    pub id: Option<String>,
232    /// Algorithm used
233    pub algorithm: String,
234    /// Distance units for output.
235    ///
236    /// Possible unit types are miles via [`super::Units::Imperial`] and kilometers via [`super::Units::Metric`].
237    ///
238    /// Default: [`super::Units::Metric`]
239    pub units: super::Units,
240    /// This array may contain warning objects informing about deprecated request parameters, clamped values etc.
241    #[serde(default = "Vec::new")]
242    pub warnings: Vec<Value>,
243    /// More compact, nested row-major distances & durations
244    ///
245    /// The arrays rows are:
246    /// - time and distance from the first source location to all target locations,
247    /// - time and distance from the second source location to all target locations,
248    /// - etc.
249    pub sources_to_targets: ConciseSourceToTargets,
250}
251
252#[derive(Deserialize, Debug, Clone)]
253pub struct ConciseSourceToTargets {
254    /// The computed time between each set of points.
255    ///
256    /// Time will always be `0` for
257    /// - the first element of the time-distance array for one_to_many,
258    /// - the last element in a many_to_one, and
259    /// - the first and last elements of a many_to_many
260    pub durations: Vec<Vec<u32>>,
261    /// The computed distance between each set of points.
262    ///
263    /// Distance will always be `0.00` for
264    /// - the first element of the time-distance array for one_to_many,
265    /// - the last element in a many_to_one, and
266    /// - the first and last elements of a many_to_many.
267    pub distances: Vec<Vec<f32>>,
268}
269
270#[derive(Deserialize, Debug, Clone)]
271pub struct VerboseSourceToTarget {
272    /// The computed distance between each set of points.
273    ///
274    /// Distance will always be `0.00` for
275    /// - the first element of the time-distance array for one_to_many,
276    /// - the last element in a many_to_one, and
277    /// - the first and last elements of a many_to_many.
278    pub distance: f32,
279    /// The computed time between each set of points.
280    ///
281    /// Time will always be `0` for
282    /// - the first element of the time-distance array for one_to_many,
283    /// - the last element in a many_to_one, and
284    /// - the first and last elements of a many_to_many
285    pub time: u32,
286    /// The destination index into the locations array
287    pub from_index: usize,
288    /// The origin index into the locations array
289    pub to_index: usize,
290    /// Timezone of when a user will arrive at this location or has to depart from the start point.
291    ///
292    /// For information how to differentiate between departure/arrival time, please see [`Manifest::date_time`] or [`Location::date_time`].
293    ///
294    /// This field is included only if:
295    /// - valhalla is build with timezone support,
296    /// - the time is below the settings `max_timedep_distance_matrix` or `max_timedep_distance`
297    /// - departure/arrival time is unspecified via [`Manifest::date_time`] or [`Location::date_time`]
298    ///
299    /// Example: `"Europe/Berlin"`
300    pub time_zone_name: Option<String>,
301    /// Timezone of when a user will arrive at this location or has to depart from the start point.
302    ///
303    /// For information how to differentiate between departure/arrival time, please see [`Manifest::date_time`] or [`Location::date_time`].
304    ///
305    /// This field is included only if:
306    /// - valhalla is build with timezone support,
307    /// - the time is below the settings `max_timedep_distance_matrix` or `max_timedep_distance`
308    /// - departure/arrival time is unspecified via [`Manifest::date_time`] or [`Location::date_time`]
309    ///
310    /// Example: `"+01:00"`
311    pub time_zone_offset: Option<String>,
312    /// When a user will arrive at this location or has to depart from the start point.
313    ///
314    /// For information how to differentiate between departure/arrival time, please see [`Manifest::date_time`] or [`Location::date_time`].
315    ///
316    /// This field is included only if:
317    /// - the time is below the settings `max_timedep_distance_matrix` or `max_timedep_distance`
318    /// - departure/arrival time is unspecified via [`Manifest::date_time`] or [`Location::date_time`]
319    ///
320    /// Example: `"2024-11-07T15:26"`
321    pub date_time: Option<chrono::NaiveDateTime>,
322}