pub mod fmi;
pub mod pbf;
use crate::{
configs::parser::{self, EdgeCategory, NodeCategory},
defaults::capacity,
io::{MapFileExt, SupportingFileExts, SupportingMapFileExts},
network::{EdgeBuilder, Graph, GraphBuilder, NodeBuilder},
};
use log::{info, warn};
use std::path::Path;
pub struct Parser;
impl Parser {
pub fn parse(cfg: parser::Config) -> Result<GraphBuilder, String> {
match Parser::from_path(&cfg.map_file)? {
MapFileExt::PBF => pbf::Parser::new().parse(cfg),
MapFileExt::FMI => fmi::Parser::new().parse(cfg),
}
}
pub fn parse_and_finalize(cfg: parser::Config) -> Result<Graph, String> {
match Parser::from_path(&cfg.map_file)? {
MapFileExt::PBF => pbf::Parser::new().parse_and_finalize(cfg),
MapFileExt::FMI => fmi::Parser::new().parse_and_finalize(cfg),
}
}
}
impl SupportingMapFileExts for Parser {}
impl SupportingFileExts for Parser {
fn supported_exts<'a>() -> &'a [&'a str] {
&["pbf", "fmi"]
}
}
trait Parsing {
fn preprocess(&mut self, cfg: &parser::Config) -> Result<(), String> {
check_parser_config(cfg)
}
fn parse(&mut self, cfg: parser::Config) -> Result<GraphBuilder, String> {
let mut builder = GraphBuilder::new(cfg);
info!("START Process given file");
self.preprocess(builder.cfg())?;
self.parse_ways(&mut builder)?;
let mut builder = builder.next();
self.parse_nodes(&mut builder)?;
let builder = builder.next();
info!("FINISHED");
builder
}
fn parse_ways(&self, builder: &mut EdgeBuilder) -> Result<(), String>;
fn parse_nodes(&self, builder: &mut NodeBuilder) -> Result<(), String>;
fn parse_and_finalize(&mut self, cfg: parser::Config) -> Result<Graph, String> {
let path = Path::new(&cfg.map_file);
info!("START Parse from given path {}", path.display());
let result = self.parse(cfg)?.finalize();
info!("FINISHED");
result
}
}
fn check_parser_config(cfg: &parser::Config) -> Result<(), String> {
if !cfg.nodes.categories().contains(&NodeCategory::NodeId) {
return Err(String::from(
"The provided config-file doesn't contain a NodeId, but needs to.",
));
}
if !cfg.nodes.categories().contains(&NodeCategory::Latitude) {
return Err(String::from(
"The provided config-file doesn't contain a latitude, but needs to.",
));
}
if !cfg.nodes.categories().contains(&NodeCategory::Longitude) {
return Err(String::from(
"The provided config-file doesn't contain a longitude, but needs to.",
));
}
if cfg.edges.dim() > capacity::SMALL_VEC_INLINE_SIZE {
return Err(format!(
"The provided config-file has more metrics for the graph ({}) \
than the parser has been compiled to ({}).",
cfg.edges.dim(),
capacity::SMALL_VEC_INLINE_SIZE
));
}
let count = cfg
.edges
.edge_categories()
.iter()
.filter(|category| category == &&EdgeCategory::ShortcutEdgeIdx)
.count();
if count > 0 && count != 2 {
return Err(format!(
"The config-file has a different number than 0 or 2 of edge-category '{}'",
EdgeCategory::ShortcutEdgeIdx
));
}
if cfg.edges.dim() < capacity::SMALL_VEC_INLINE_SIZE {
warn!(
"The provided config-file has less metrics for the graph ({}) \
than the parser has been compiled to ({}). \
Compiling accordingly saves memory.",
cfg.edges.dim(),
capacity::SMALL_VEC_INLINE_SIZE
);
}
Ok(())
}