use std::path::Path;
use nom::{IResult, Parser, character::char};
use rustc_hash::FxHashMap;
use crate::{
error::{HResult, HrdfError},
models::Direction,
parsing::{
error::PResult,
helpers::{direction_parser, read_lines, string_till_eol_parser},
},
storage::ResourceStorage,
};
type DirectionAndTypeConverter = (ResourceStorage<Direction>, FxHashMap<String, i32>);
fn parse_direction_row(input: &str) -> IResult<&str, (String, i32, String)> {
let (res, ((prefix, id), _, name)) =
(direction_parser, char(' '), string_till_eol_parser).parse(input)?;
Ok((res, (prefix, id, name)))
}
fn parse_line(
line: &str,
pk_type_converter: &mut FxHashMap<String, i32>,
) -> PResult<(i32, Direction)> {
let (_, (prefix, id, name)) = parse_direction_row(line)?;
let legacy_id = format!("{prefix}{id}");
if let Some(previous) = pk_type_converter.insert(legacy_id.clone(), id) {
log::warn!(
"Warning: previous id {previous} for {legacy_id}. The legacy_id, {legacy_id} is not unique."
);
}
Ok((id, Direction::new(id, name)))
}
pub fn parse(path: &Path) -> HResult<DirectionAndTypeConverter> {
log::info!("Parsing RICHTUNG...");
let file = path.join("RICHTUNG");
let lines = read_lines(&file, 0)?;
let mut pk_type_converter = FxHashMap::default();
let directions = lines
.into_iter()
.enumerate()
.filter(|(_, line)| !line.trim().is_empty())
.map(|(line_number, line)| {
parse_line(&line, &mut pk_type_converter).map_err(|e| HrdfError::Parsing {
error: e,
file: String::from(file.to_string_lossy()),
line,
line_number,
})
})
.collect::<HResult<FxHashMap<i32, Direction>>>()?;
Ok((ResourceStorage::new(directions), pk_type_converter))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parsing::tests::get_json_values;
use pretty_assertions::assert_eq;
#[test]
fn row_parser_v207() {
let input = "R000008 Winterthur";
let (_, (prefix, id, name)) = parse_direction_row(input).unwrap();
assert_eq!("R", prefix);
assert_eq!(8, id);
assert_eq!("Winterthur", name);
let input = "R000192 Saas-Fee, Parkhaus";
let (_, (prefix, id, name)) = parse_direction_row(input).unwrap();
assert_eq!("R", prefix);
assert_eq!(192, id);
assert_eq!("Saas-Fee, Parkhaus", name);
let input = "R002609 Hégenheim - Collège des Trois Pays";
let (_, (prefix, id, name)) = parse_direction_row(input).unwrap();
assert_eq!("R", prefix);
assert_eq!(2609, id);
assert_eq!("Hégenheim - Collège des Trois Pays", name);
}
#[test]
fn type_converter_v207() {
let rows = vec![
"R000008 Winterthur".to_string(),
"R000192 Saas-Fee, Parkhaus".to_string(),
"R002609 Hégenheim - Collège des Trois Pays".to_string(),
];
let mut pk_type_converter = FxHashMap::default();
let directions = rows
.into_iter()
.filter(|line| !line.trim().is_empty())
.map(|line| parse_line(&line, &mut pk_type_converter))
.collect::<PResult<FxHashMap<i32, Direction>>>()
.unwrap();
assert_eq!(*pk_type_converter.get("R8").unwrap(), 8);
assert_eq!(*pk_type_converter.get("R192").unwrap(), 192);
assert_eq!(*pk_type_converter.get("R2609").unwrap(), 2609);
let attribute = directions.get(&8).unwrap();
let reference = r#"
{
"id":8,
"name":"Winterthur"
}"#;
let (attribute, reference) = get_json_values(attribute, reference).unwrap();
assert_eq!(attribute, reference);
let attribute = directions.get(&192).unwrap();
let reference = r#"
{
"id":192,
"name":"Saas-Fee, Parkhaus"
}"#;
let (attribute, reference) = get_json_values(attribute, reference).unwrap();
assert_eq!(attribute, reference);
let attribute = directions.get(&2609).unwrap();
let reference = r#"
{
"id":2609,
"name":"Hégenheim - Collège des Trois Pays"
}"#;
let (attribute, reference) = get_json_values(attribute, reference).unwrap();
assert_eq!(attribute, reference);
}
}