ddex_core/
error.rs

1//! Shared error types for DDEX Suite
2
3use thiserror::Error;
4use serde::{Serialize, Deserialize};
5
6/// Common error types used across parser and builder
7#[derive(Debug, Error, Clone, Serialize, Deserialize)]
8pub enum DDEXError {
9    #[error("XML parsing error: {message}")]
10    XmlError {
11        message: String,
12        location: ErrorLocation,
13    },
14
15    #[error("Validation error: {message}")]
16    ValidationError {
17        message: String,
18        field: Option<String>,
19    },
20
21    #[error("Reference error: {message}")]
22    ReferenceError {
23        message: String,
24        reference: String,
25    },
26
27    #[error("Version mismatch: expected {expected}, found {found}")]
28    VersionMismatch {
29        expected: String,
30        found: String,
31    },
32
33    #[error("IO error: {message}")]
34    IoError {
35        message: String,
36    },
37}
38
39/// Location information for errors
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct ErrorLocation {
42    pub line: usize,
43    pub column: usize,
44    pub byte_offset: Option<usize>,
45    pub path: String,
46}
47
48impl Default for ErrorLocation {
49    fn default() -> Self {
50        Self {
51            line: 0,
52            column: 0,
53            byte_offset: None,
54            path: "unknown".to_string(),
55        }
56    }
57}
58
59/// FFI-friendly error representation
60pub mod ffi {
61    use super::*;
62    use crate::ffi::{FFIError, FFIErrorSeverity, FFIErrorCategory, FFIErrorLocation};
63    
64    /// Convert from DDEXError to FFIError
65    impl From<DDEXError> for FFIError {
66        fn from(err: DDEXError) -> Self {
67            match err {
68                DDEXError::XmlError { message, location } => FFIError {
69                    code: "XML_PARSE_ERROR".to_string(),
70                    message,
71                    location: Some(FFIErrorLocation {
72                        line: location.line,
73                        column: location.column,
74                        path: location.path,
75                    }),
76                    severity: FFIErrorSeverity::Error,
77                    hint: Some("Check XML syntax".to_string()),
78                    category: FFIErrorCategory::XmlParsing,
79                },
80                DDEXError::ValidationError { message, field } => FFIError {
81                    code: "VALIDATION_ERROR".to_string(),
82                    message: message.clone(),
83                    location: field.map(|f| FFIErrorLocation {
84                        line: 0,
85                        column: 0,
86                        path: f,
87                    }),
88                    severity: FFIErrorSeverity::Error,
89                    hint: Some("Check field requirements".to_string()),
90                    category: FFIErrorCategory::Validation,
91                },
92                DDEXError::ReferenceError { message, reference } => FFIError {
93                    code: "REFERENCE_ERROR".to_string(),
94                    message,
95                    location: Some(FFIErrorLocation {
96                        line: 0,
97                        column: 0,
98                        path: reference,
99                    }),
100                    severity: FFIErrorSeverity::Error,
101                    hint: Some("Verify reference exists".to_string()),
102                    category: FFIErrorCategory::Reference,
103                },
104                DDEXError::VersionMismatch { expected, found } => FFIError {
105                    code: "VERSION_MISMATCH".to_string(),
106                    message: format!("Expected version {}, found {}", expected, found),
107                    location: None,
108                    severity: FFIErrorSeverity::Error,
109                    hint: Some("Use correct DDEX version".to_string()),
110                    category: FFIErrorCategory::Version,
111                },
112                DDEXError::IoError { message } => FFIError {
113                    code: "IO_ERROR".to_string(),
114                    message,
115                    location: None,
116                    severity: FFIErrorSeverity::Error,
117                    hint: None,
118                    category: FFIErrorCategory::Io,
119                },
120            }
121        }
122    }
123}