ddex_core/
error.rs

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