use crate::uslm::parser::ParseError;
use crate::uslm::{USLMElement, parser::parse};
use rayon::prelude::*;
use std::fs;
use std::path::{Path, PathBuf};
pub use crate::io::{load_xml_file, read_json_file, write_json_file};
pub use crate::date::date_str_to_date;
type Result<T> = std::result::Result<T, ParseError>;
pub fn parse_uslm_xml(xml_path: &str, date: &str) -> Result<USLMElement> {
parse(xml_path, date)
}
pub fn parse_uslm_to_json(xml_path: &str, date: &str, json_path: &str) -> Result<()> {
let element = parse_uslm_xml(xml_path, date)?;
write_json_file(&element, json_path)?;
Ok(())
}
pub fn parse_uslm_directory(input_dir: &str, date: &str) -> Result<Vec<USLMElement>> {
let dir_path = Path::new(input_dir);
let xml_files: Vec<PathBuf> = fs::read_dir(dir_path)
.map_err(ParseError::Io)?
.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
if path.extension()? == "xml" {
Some(path)
} else {
None
}
})
.collect();
let results: Vec<Result<USLMElement>> = xml_files
.par_iter()
.map(|path| {
let path_str = path.to_str().ok_or_else(|| {
ParseError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Invalid path encoding",
))
})?;
parse_uslm_xml(path_str, date)
})
.collect();
let mut elements = Vec::new();
let mut errors = Vec::new();
for result in results {
match result {
Ok(element) => elements.push(element),
Err(e) => errors.push(e),
}
}
if !errors.is_empty() {
let error_msg = format!("Failed to parse {} files", errors.len());
return Err(ParseError::UnableToParseElement(error_msg));
}
Ok(elements)
}
pub fn parse_uslm_directory_to_json(input_dir: &str, date: &str, output_dir: &str) -> Result<()> {
let dir_path = Path::new(input_dir);
let out_path = Path::new(output_dir);
fs::create_dir_all(out_path)?;
let xml_files: Vec<PathBuf> = fs::read_dir(dir_path)
.map_err(ParseError::Io)?
.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
if path.extension()? == "xml" {
Some(path)
} else {
None
}
})
.collect();
let results: Vec<Result<()>> = xml_files
.par_iter()
.map(|path| {
let path_str = path.to_str().ok_or_else(|| {
ParseError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Invalid path encoding",
))
})?;
let file_stem = path.file_stem().and_then(|s| s.to_str()).ok_or_else(|| {
ParseError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Invalid filename",
))
})?;
let output_path = out_path.join(format!("{}.json", file_stem));
let output_str = output_path.to_str().ok_or_else(|| {
ParseError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Invalid output path encoding",
))
})?;
parse_uslm_to_json(path_str, date, output_str)
})
.collect();
let errors: Vec<ParseError> = results.into_iter().filter_map(|r| r.err()).collect();
if !errors.is_empty() {
let error_msg = format!("Failed to process {} files", errors.len());
return Err(ParseError::UnableToParseElement(error_msg));
}
Ok(())
}