ddex_parser/parser/
detector.rs1use crate::error::{ErrorLocation, ParseError};
2use ddex_core::models::versions::ERNVersion;
3use quick_xml::{events::Event, Reader};
4use std::io::BufRead;
5pub struct VersionDetector;
8
9impl VersionDetector {
10 pub fn detect<R: std::io::Read>(reader: R) -> crate::error::Result<ERNVersion> {
11 let mut buf_reader = std::io::BufReader::new(reader);
12 Self::detect_from_bufread(&mut buf_reader)
13 }
14
15 pub fn detect_from_bufread<R: BufRead>(reader: R) -> crate::error::Result<ERNVersion> {
16 let mut xml_reader = Reader::from_reader(reader);
17 xml_reader.config_mut().trim_text(true);
18
19 let mut buf = Vec::new();
20 let mut found_root = false;
21 let mut namespace_uris = Vec::new();
22
23 loop {
25 match xml_reader.read_event_into(&mut buf) {
26 Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e)) => {
27 found_root = true;
28
29 for attr in e.attributes() {
31 match attr {
32 Ok(attr) => {
33 let key = std::str::from_utf8(attr.key.as_ref()).unwrap_or("");
34 let value = std::str::from_utf8(&attr.value).unwrap_or("");
35
36 if key == "xmlns" || key.starts_with("xmlns:") {
38 namespace_uris.push(value.to_string());
39 }
40 }
41 Err(e) => {
42 return Err(ParseError::XmlError {
43 message: format!("Invalid XML attribute: {}", e),
44 location: ErrorLocation::default(),
45 });
46 }
47 }
48 }
49 break; }
51 Ok(Event::Eof) => {
52 break;
53 }
54 Ok(_) => {} Err(e) => {
56 return Err(ParseError::XmlError {
57 message: format!("XML parsing error: {}", e),
58 location: ErrorLocation::default(),
59 });
60 }
61 }
62 buf.clear();
63 }
64
65 if !found_root {
67 return Err(ParseError::XmlError {
68 message: "No root element found - invalid XML".to_string(),
69 location: ErrorLocation::default(),
70 });
71 }
72
73 for uri in &namespace_uris {
75 if uri.contains("http://ddex.net/xml/ern/382") {
76 return Ok(ERNVersion::V3_8_2);
77 } else if uri.contains("http://ddex.net/xml/ern/42") {
78 return Ok(ERNVersion::V4_2);
79 } else if uri.contains("http://ddex.net/xml/ern/43") {
80 return Ok(ERNVersion::V4_3);
81 }
82 }
83
84 Err(ParseError::XmlError {
86 message: "No DDEX ERN namespace found - not a valid DDEX document".to_string(),
87 location: ErrorLocation::default(),
88 })
89 }
90}