use crate::error::ParseError;
use crate::parser::namespace_detector::{NamespaceContext, NamespaceDetector};
use crate::parser::ParseOptions;
use crate::transform::{flatten::Flattener, graph::GraphBuilder};
use ddex_core::models::flat::ParsedERNMessage;
use ddex_core::models::graph::ERNMessage;
use ddex_core::models::versions::ERNVersion;
use std::io::{BufRead, Seek, SeekFrom};
use std::time::Instant;
pub fn parse_dom<R: BufRead + Seek>(
mut reader: R,
version: ERNVersion,
options: ParseOptions,
security_config: &crate::parser::security::SecurityConfig,
) -> Result<ParsedERNMessage, ParseError> {
let start = Instant::now();
if !options.allow_blocking && options.timeout_ms > 0 {
}
let mut namespace_detector = NamespaceDetector::new();
let namespace_result =
namespace_detector.detect_from_xml_with_security(&mut reader, security_config)?;
let namespace_context = NamespaceContext::from_detection_result(namespace_result);
reader.seek(SeekFrom::Start(0))?;
let graph_builder = GraphBuilder::new(version);
let graph = graph_builder.build_from_xml_with_context_and_security(
reader,
namespace_context,
security_config,
)?;
let graph = if options.resolve_references {
resolve_references(graph)?
} else {
graph
};
let flat = Flattener::flatten(graph.clone());
let elapsed = start.elapsed();
if elapsed.as_millis() > options.timeout_ms as u128 {
return Err(ParseError::Timeout {
message: format!("Parsing timeout after {} seconds", elapsed.as_secs()),
});
}
Ok(ParsedERNMessage {
graph,
flat: flat?,
extensions: None,
})
}
fn resolve_references(message: ERNMessage) -> Result<ERNMessage, ParseError> {
use crate::transform::resolve::ReferenceResolver;
let mut resolver = ReferenceResolver::new();
resolver.build_maps(&message);
let unresolved = resolver.validate_references(&message);
if !unresolved.is_empty() {
for uref in unresolved {
tracing::warn!(
"Unresolved reference: {} -> {} at {}",
uref.reference_type,
uref.reference_value,
uref.location
);
}
}
Ok(message)
}