Implement parsing of flatbuffer response
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
pub fn approx_equal(a: f64, b: f64, dp: u8) -> bool {
|
||||
let p = 10f64.powi(-(dp as i32));
|
||||
pub fn approx_equal(a: f32, b: f32, dp: u8) -> bool {
|
||||
let p = 10f32.powi(-(dp as i32));
|
||||
(a - b).abs() < p
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
||||
pub struct Location {
|
||||
// Note: The order is important since we derive Deserialize
|
||||
pub longitude: f32,
|
||||
pub latitude: f32,
|
||||
}
|
||||
+22
-1
@@ -1,12 +1,33 @@
|
||||
#![allow(clippy::derivable_impls, clippy::all)]
|
||||
extern crate flatbuffers;
|
||||
|
||||
pub mod cli_arguments;
|
||||
pub mod dot_writer;
|
||||
pub mod f64_utils;
|
||||
pub mod file_util;
|
||||
pub mod hash_util;
|
||||
pub mod lexicographic_file_walker;
|
||||
pub mod location;
|
||||
pub mod nearest_response;
|
||||
pub mod osm;
|
||||
pub mod osm_db;
|
||||
pub mod osrm_world;
|
||||
pub mod scenario_id;
|
||||
pub mod task_starter;
|
||||
pub mod task_starter;
|
||||
|
||||
// flatbuffer
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/position_generated.rs"]
|
||||
pub mod position_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/waypoint_generated.rs"]
|
||||
pub mod waypoint_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/table_generated.rs"]
|
||||
pub mod table_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/route_generated.rs"]
|
||||
pub mod route_flatbuffers;
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[path = "../../target/flatbuffers/fbresult_generated.rs"]
|
||||
pub mod fbresult_flatbuffers;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use geo_types::{point, Point};
|
||||
use crate::common::fbresult_flatbuffers::osrm::engine::api::fbresult::FBResult;
|
||||
use super::location::Location;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Waypoint {
|
||||
pub hint: String,
|
||||
pub nodes: Vec<u64>,
|
||||
pub distance: f64,
|
||||
pub distance: f32,
|
||||
pub name: String,
|
||||
location: [f64; 2],
|
||||
location: Location,
|
||||
}
|
||||
|
||||
impl Waypoint {
|
||||
pub fn location(&self) -> Point {
|
||||
point!(self.location)
|
||||
pub fn location(&self) -> &Location {
|
||||
&self.location
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,3 +23,65 @@ pub struct NearestResponse {
|
||||
pub waypoints: Vec<Waypoint>,
|
||||
pub data_version: Option<String>,
|
||||
}
|
||||
|
||||
impl NearestResponse {
|
||||
pub fn from_json_reader(reader: impl std::io::Read) -> Self {
|
||||
let response = match serde_json::from_reader::<_, NearestResponse>(reader) {
|
||||
Ok(response) => response,
|
||||
Err(e) => panic!("parsing error {e}"),
|
||||
};
|
||||
response
|
||||
}
|
||||
|
||||
pub fn from_flatbuffer(mut reader: impl std::io::Read) -> Self {
|
||||
let mut buffer = Vec::new();
|
||||
if let Err(e) = reader.read_to_end(&mut buffer) {
|
||||
panic!("cannot read from strem: {e}");
|
||||
};
|
||||
let decoded: Result<FBResult, flatbuffers::InvalidFlatbuffer> =
|
||||
flatbuffers::root::<FBResult>(&buffer);
|
||||
let decoded: FBResult = match decoded {
|
||||
Ok(d) => d,
|
||||
Err(e) => panic!("Error during parsing: {e} {:?}", buffer),
|
||||
};
|
||||
let code = match decoded.code() {
|
||||
Some(e) => e.message().expect("code exists but is not unwrappable"),
|
||||
None => "",
|
||||
};
|
||||
let data_version = match decoded.data_version() {
|
||||
Some(s) => s,
|
||||
None => "",
|
||||
};
|
||||
|
||||
let waypoints = decoded
|
||||
.waypoints()
|
||||
.expect("waypoints should be at least an empty list")
|
||||
.iter()
|
||||
.map(|wp| {
|
||||
let hint = wp.hint().expect("hint is missing").to_string();
|
||||
let location = wp.location().expect("waypoint must have a location");
|
||||
let location = Location {
|
||||
latitude: location.latitude(),
|
||||
longitude: location.longitude(),
|
||||
};
|
||||
let nodes = wp.nodes().expect("waypoint mus have nodes");
|
||||
let nodes = vec![nodes.first(), nodes.second()];
|
||||
let distance = wp.distance();
|
||||
|
||||
Waypoint {
|
||||
hint,
|
||||
nodes,
|
||||
distance,
|
||||
name: "".into(),
|
||||
location,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
code: code.into(),
|
||||
waypoints,
|
||||
data_version: Some(data_version.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -2,6 +2,8 @@ use std::collections::HashMap;
|
||||
|
||||
use xml_builder::XMLElement;
|
||||
|
||||
use super::location::Location;
|
||||
|
||||
static OSM_USER: &str = "osrm";
|
||||
static OSM_TIMESTAMP: &str = "2000-01-01T00:00:00Z";
|
||||
static OSM_UID: &str = "1";
|
||||
@@ -9,8 +11,7 @@ static OSM_UID: &str = "1";
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct OSMNode {
|
||||
pub id: u64,
|
||||
pub lat: f64,
|
||||
pub lon: f64,
|
||||
pub location: Location,
|
||||
pub tags: HashMap<String, String>,
|
||||
}
|
||||
|
||||
@@ -34,8 +35,8 @@ impl OSMNode {
|
||||
node.add_attribute("uid", OSM_UID);
|
||||
node.add_attribute("user", OSM_USER);
|
||||
node.add_attribute("timestamp", OSM_TIMESTAMP);
|
||||
node.add_attribute("lon", &format!("{:?}", self.lon));
|
||||
node.add_attribute("lat", &format!("{:?}", self.lat));
|
||||
node.add_attribute("lon", &format!("{:?}", self.location.longitude));
|
||||
node.add_attribute("lat", &format!("{:?}", self.location.latitude));
|
||||
|
||||
if !self.tags.is_empty() {
|
||||
for (key, value) in &self.tags {
|
||||
@@ -81,8 +82,8 @@ impl OSMWay {
|
||||
let mut nd = XMLElement::new("nd");
|
||||
nd.add_attribute("ref", &node.id.to_string());
|
||||
if self.add_locations {
|
||||
nd.add_attribute("lon", &format!("{:?}", node.lon));
|
||||
nd.add_attribute("lat", &format!("{:?}", node.lat));
|
||||
nd.add_attribute("lon", &format!("{:?}", node.location.longitude));
|
||||
nd.add_attribute("lat", &format!("{:?}", node.location.latitude));
|
||||
}
|
||||
way.add_child(nd).unwrap();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::Point;
|
||||
use crate::Location;
|
||||
use cucumber::World;
|
||||
use log::debug;
|
||||
use std::{
|
||||
@@ -18,11 +18,13 @@ pub struct OSRMWorld {
|
||||
pub osm_id: u64,
|
||||
pub profile: String,
|
||||
|
||||
pub known_osm_nodes: HashMap<char, Point>,
|
||||
pub known_locations: HashMap<char, Point>,
|
||||
pub known_osm_nodes: HashMap<char, Location>,
|
||||
pub known_locations: HashMap<char, Location>,
|
||||
|
||||
pub osm_db: OSMDb,
|
||||
pub extraction_parameters: Vec<String>,
|
||||
|
||||
pub request_with_flatbuffers: bool,
|
||||
}
|
||||
|
||||
impl OSRMWorld {
|
||||
@@ -78,7 +80,7 @@ impl OSRMWorld {
|
||||
self.osm_id
|
||||
}
|
||||
|
||||
pub fn add_osm_node(&mut self, name: char, location: Point, id: Option<u64>) {
|
||||
pub fn add_osm_node(&mut self, name: char, location: Location, id: Option<u64>) {
|
||||
if self.known_osm_nodes.contains_key(&name) {
|
||||
panic!("duplicate node: {name}");
|
||||
}
|
||||
@@ -88,8 +90,7 @@ impl OSRMWorld {
|
||||
};
|
||||
let node = OSMNode {
|
||||
id,
|
||||
lat: location.y(),
|
||||
lon: location.x(),
|
||||
location,
|
||||
tags: HashMap::from([("name".to_string(), name.to_string())]),
|
||||
};
|
||||
|
||||
@@ -97,7 +98,7 @@ impl OSRMWorld {
|
||||
self.osm_db.add_node(node);
|
||||
}
|
||||
|
||||
pub fn get_location(&self, name: char) -> Point {
|
||||
pub fn get_location(&self, name: char) -> Location {
|
||||
*match name {
|
||||
// TODO: move lookup to world
|
||||
'0'..='9' => self
|
||||
@@ -112,7 +113,7 @@ impl OSRMWorld {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_location(&mut self, name: char, location: Point) {
|
||||
pub fn add_location(&mut self, name: char, location: Location) {
|
||||
if self.known_locations.contains_key(&name) {
|
||||
panic!("duplicate location: {name}")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user