ddex_parser/parser/
mod.rs

1// core/src/parser/mod.rs
2//! Parser module
3
4pub mod detector;
5pub mod security;
6pub mod stream;
7pub mod mode;
8pub mod dom;
9pub mod extension_capture;
10pub mod namespace_detector;
11pub mod attribute_extractor;
12
13#[cfg(test)]
14mod tests;
15
16use crate::error::ParseError;
17use ddex_core::models::flat::ParsedERNMessage;
18use std::io::BufRead;
19
20/// Main parser options
21#[derive(Debug, Clone)]
22pub struct ParseOptions {
23    pub mode: mode::ParseMode,
24    pub auto_threshold: u64,
25    pub resolve_references: bool,
26    pub include_raw: bool,
27    pub max_memory: usize,
28    pub timeout_ms: u64,
29    pub allow_blocking: bool,
30    pub include_raw_extensions: bool,
31    pub include_comments: bool,
32    pub preserve_unknown_elements: bool,
33    pub chunk_size: usize,
34}
35
36impl Default for ParseOptions {
37    fn default() -> Self {
38        Self {
39            mode: mode::ParseMode::Auto,
40            auto_threshold: 10 * 1024 * 1024, // 10MB
41            resolve_references: true,
42            include_raw: false,
43            max_memory: 100 * 1024 * 1024, // 100MB
44            timeout_ms: 30000, // 30 seconds
45            allow_blocking: false,
46            chunk_size: 100,
47            include_raw_extensions: false,
48            include_comments: false,
49            preserve_unknown_elements: false,
50        }
51    }
52}
53
54/// Parse DDEX XML with automatic mode selection
55pub fn parse<R: BufRead + std::io::Seek>(
56    mut reader: R,
57    options: ParseOptions,
58) -> Result<ParsedERNMessage, ParseError> {
59    // Detect version first
60    let version = detector::VersionDetector::detect(&mut reader)?;
61    reader.seek(std::io::SeekFrom::Start(0))?;
62    
63    // Select parsing mode
64    let mode_selector = mode::ModeSelector::new(options.auto_threshold);
65    let selected_mode = mode_selector.select_mode(&mut reader, options.mode)?;
66    reader.seek(std::io::SeekFrom::Start(0))?;
67    
68    match selected_mode {
69        mode::ParseMode::Dom => {
70            // Use DOM parser for smaller files
71            dom::parse_dom(reader, version, options)
72        }
73        mode::ParseMode::Stream => {
74            // Use streaming parser for larger files
75            stream::parse_streaming(reader, version, options)
76        }
77        mode::ParseMode::Auto => unreachable!(), // Already resolved
78    }
79}
80
81pub mod version_ext;
82
83impl ParseOptions {
84    pub fn with_extensions() -> Self {
85        Self {
86            include_raw_extensions: true,
87            include_comments: true,
88            preserve_unknown_elements: true,
89            ..Default::default()
90        }
91    }
92    
93    pub fn for_round_trip() -> Self {
94        Self {
95            include_raw_extensions: true,
96            include_comments: true,
97            preserve_unknown_elements: true,
98            resolve_references: false,
99            ..Default::default()
100        }
101    }
102}