ddex_parser/parser/
detector.rs1use crate::error::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(format!("Invalid XML attribute: {}", e)));
43 }
44 }
45 }
46 break; }
48 Ok(Event::Eof) => {
49 break;
50 }
51 Ok(_) => {} Err(e) => {
53 return Err(ParseError::XmlError(format!("XML parsing error: {}", e)));
54 }
55 }
56 buf.clear();
57 }
58
59 if !found_root {
61 return Err(ParseError::XmlError("No root element found - invalid XML".to_string()));
62 }
63
64 for uri in &namespace_uris {
66 if uri.contains("http://ddex.net/xml/ern/382") {
67 return Ok(ERNVersion::V3_8_2);
68 } else if uri.contains("http://ddex.net/xml/ern/42") {
69 return Ok(ERNVersion::V4_2);
70 } else if uri.contains("http://ddex.net/xml/ern/43") {
71 return Ok(ERNVersion::V4_3);
72 }
73 }
74
75 Err(ParseError::XmlError("No DDEX ERN namespace found - not a valid DDEX document".to_string()))
77 }
78}