ddex_parser/parser/
dom.rs1use crate::error::ParseError;
5use crate::parser::namespace_detector::{NamespaceContext, NamespaceDetector};
6use crate::parser::ParseOptions;
7use crate::transform::{flatten::Flattener, graph::GraphBuilder};
8use ddex_core::models::flat::ParsedERNMessage;
9use ddex_core::models::graph::ERNMessage;
10use ddex_core::models::versions::ERNVersion;
11use std::io::{BufRead, Seek, SeekFrom};
12use std::time::Instant;
13
14pub fn parse_dom<R: BufRead + Seek>(
16 mut reader: R,
17 version: ERNVersion,
18 options: ParseOptions,
19 security_config: &crate::parser::security::SecurityConfig,
20) -> Result<ParsedERNMessage, ParseError> {
21 let start = Instant::now();
22
23 if !options.allow_blocking && options.timeout_ms > 0 {
25 }
27
28 let mut namespace_detector = NamespaceDetector::new();
30 let namespace_result =
31 namespace_detector.detect_from_xml_with_security(&mut reader, security_config)?;
32 let namespace_context = NamespaceContext::from_detection_result(namespace_result);
33
34 reader.seek(SeekFrom::Start(0))?;
36
37 let graph_builder = GraphBuilder::new(version);
39 let graph = graph_builder.build_from_xml_with_context_and_security(
40 reader,
41 namespace_context,
42 security_config,
43 )?;
44
45 let graph = if options.resolve_references {
47 resolve_references(graph)?
48 } else {
49 graph
50 };
51
52 let flat = Flattener::flatten(graph.clone());
54
55 let elapsed = start.elapsed();
57 if elapsed.as_millis() > options.timeout_ms as u128 {
58 return Err(ParseError::Timeout {
59 seconds: elapsed.as_secs(),
60 });
61 }
62
63 Ok(ParsedERNMessage {
64 graph,
65 flat,
66 extensions: None,
67 })
68}
69
70fn resolve_references(message: ERNMessage) -> Result<ERNMessage, ParseError> {
71 use crate::transform::resolve::ReferenceResolver;
72
73 let mut resolver = ReferenceResolver::new();
74 resolver.build_maps(&message);
75
76 let unresolved = resolver.validate_references(&message);
78 if !unresolved.is_empty() {
79 for uref in unresolved {
81 tracing::warn!(
82 "Unresolved reference: {} -> {} at {}",
83 uref.reference_type,
84 uref.reference_value,
85 uref.location
86 );
87 }
88 }
89
90 Ok(message)
91}