1use ddex_core::error::DDEXError;
4use ddex_core::ffi::{FFIError, FFIErrorSeverity, FFIErrorCategory};
5use thiserror::Error;
6
7pub use ddex_core::error::ErrorLocation;
9
10pub type Result<T> = std::result::Result<T, ParseError>;
12
13#[derive(Debug, Error)]
15pub enum ParseError {
16 #[error("XML parsing error: {message}")]
17 XmlError {
18 message: String,
19 location: ErrorLocation,
20 },
21
22 #[error("Unsupported DDEX version: {version}")]
23 UnsupportedVersion {
24 version: String,
25 },
26
27 #[error("Security violation: {message}")]
28 SecurityViolation {
29 message: String,
30 },
31
32 #[error("Parse timeout after {seconds} seconds")]
33 Timeout {
34 seconds: u64,
35 },
36
37 #[error("Core error: {0}")]
38 Core(#[from] DDEXError),
39
40 #[error("IO error: {0}")]
41 Io(#[from] std::io::Error),
42}
43
44impl From<ParseError> for FFIError {
45 fn from(err: ParseError) -> Self {
46 match err {
47 ParseError::Core(core_err) => core_err.into(),
48 ParseError::XmlError { message, location } => FFIError {
49 code: "PARSE_XML_ERROR".to_string(),
50 message,
51 location: Some(ddex_core::ffi::FFIErrorLocation {
52 line: location.line,
53 column: location.column,
54 path: location.path,
55 }),
56 severity: FFIErrorSeverity::Error,
57 hint: Some("Check XML syntax".to_string()),
58 category: FFIErrorCategory::XmlParsing,
59 },
60 ParseError::UnsupportedVersion { version } => FFIError {
61 code: "UNSUPPORTED_VERSION".to_string(),
62 message: format!("Unsupported DDEX version: {}", version),
63 location: None,
64 severity: FFIErrorSeverity::Error,
65 hint: Some("Use ERN 3.8.2, 4.2, or 4.3".to_string()),
66 category: FFIErrorCategory::Version,
67 },
68 ParseError::SecurityViolation { message } => FFIError {
69 code: "SECURITY_VIOLATION".to_string(),
70 message,
71 location: None,
72 severity: FFIErrorSeverity::Error,
73 hint: Some("Check for XXE or entity expansion attacks".to_string()),
74 category: FFIErrorCategory::Validation,
75 },
76 ParseError::Timeout { seconds } => FFIError {
77 code: "PARSE_TIMEOUT".to_string(),
78 message: format!("Parse timeout after {} seconds", seconds),
79 location: None,
80 severity: FFIErrorSeverity::Error,
81 hint: Some("File may be too large or complex".to_string()),
82 category: FFIErrorCategory::Io,
83 },
84 ParseError::Io(io_err) => FFIError {
85 code: "IO_ERROR".to_string(),
86 message: io_err.to_string(),
87 location: None,
88 severity: FFIErrorSeverity::Error,
89 hint: None,
90 category: FFIErrorCategory::Io,
91 },
92 }
93 }
94}