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