1use ddex_core::models;
3pub mod error;
6pub mod parser;
7pub mod transform;
8
9pub use ddex_core::models::versions::ERNVersion;
11
12use serde::{Deserialize, Serialize};
13use parser::security::SecurityConfig;
14
15#[derive(Debug, Clone)]
17pub struct DDEXParser {
18 config: SecurityConfig,
19}
20
21impl Default for DDEXParser {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl DDEXParser {
28 pub fn new() -> Self {
30 Self {
31 config: SecurityConfig::default(),
32 }
33 }
34
35 pub fn with_config(config: SecurityConfig) -> Self {
37 Self { config }
38 }
39
40 pub fn parse<R: std::io::BufRead + std::io::Seek>(
42 &self,
43 reader: R,
44 ) -> Result<ddex_core::models::flat::ParsedERNMessage, error::ParseError> {
45 self.parse_with_options(reader, Default::default())
46 }
47
48 pub fn parse_with_options<R: std::io::BufRead + std::io::Seek>(
50 &self,
51 reader: R,
52 options: parser::ParseOptions,
53 ) -> Result<ddex_core::models::flat::ParsedERNMessage, error::ParseError> {
54 if !self.config.disable_external_entities {
56 return Err(error::ParseError::SecurityViolation {
57 message: "External entities are disabled".to_string(),
58 });
59 }
60
61 parser::parse(reader, options)
62 }
63
64 pub fn stream<R: std::io::BufRead>(
66 &self,
67 reader: R,
68 ) -> StreamIterator<R> {
69 let version = ddex_core::models::versions::ERNVersion::V4_3;
72
73 StreamIterator {
74 parser: parser::stream::StreamingParser::new(reader, version),
75 config: self.config.clone(),
76 }
77 }
78
79 pub fn detect_version<R: std::io::BufRead>(
81 &self,
82 reader: R,
83 ) -> Result<ddex_core::models::versions::ERNVersion, error::ParseError> {
84 parser::detector::VersionDetector::detect(reader)
85 }
86
87 pub fn sanity_check<R: std::io::BufRead>(
89 &self,
90 _reader: R,
91 ) -> Result<SanityCheckResult, error::ParseError> {
92 Ok(SanityCheckResult {
94 is_valid: true,
95 version: ddex_core::models::versions::ERNVersion::V4_3,
96 errors: Vec::new(),
97 warnings: Vec::new(),
98 })
99 }
100}
101
102pub struct StreamIterator<R: std::io::BufRead> {
104 parser: parser::stream::StreamingParser<R>,
105 #[allow(dead_code)] config: SecurityConfig,
107}
108
109impl<R: std::io::BufRead> Iterator for StreamIterator<R> {
110 type Item = Result<models::graph::Release, error::ParseError>;
111
112 fn next(&mut self) -> Option<Self::Item> {
113 self.parser.stream_releases().next()
114 }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct SanityCheckResult {
120 pub is_valid: bool,
121 pub version: ddex_core::models::versions::ERNVersion,
122 pub errors: Vec<String>,
123 pub warnings: Vec<String>,
124}
125
126#[cfg(feature = "bench")]
128pub mod bench_report;
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_parser_creation() {
136 let parser = DDEXParser::new();
137 assert!(parser.config.disable_external_entities);
138 }
139}