1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Error types for the undoc library.
use std::io;
use thiserror::Error;
/// Result type alias for undoc operations.
pub type Result<T> = std::result::Result<T, Error>;
/// Errors that can occur during document processing.
#[derive(Error, Debug)]
pub enum Error {
/// I/O error during file operations.
#[error("I/O error: {0}")]
Io(#[from] io::Error),
/// The file format could not be determined.
#[error("Unknown file format")]
UnknownFormat,
/// The file format is recognized but not supported.
#[error("Unsupported format: {0}")]
UnsupportedFormat(String),
/// Error reading ZIP archive.
#[error("ZIP archive error: {0}")]
ZipArchive(String),
/// Error parsing XML content.
#[error("XML parse error in {location}: {message}")]
XmlParseWithContext {
/// The error message
message: String,
/// Location context (file path, element name, etc.)
location: String,
},
/// Error parsing XML content (legacy, no context).
#[error("XML parse error: {0}")]
XmlParse(String),
/// Invalid or malformed data in the document.
#[error("Invalid data: {0}")]
InvalidData(String),
/// A required document component is missing.
#[error("Missing component: {0}")]
MissingComponent(String),
/// Error during text encoding conversion.
#[error("Encoding error: {0}")]
Encoding(String),
/// A referenced style was not found.
#[error("Style not found: {0}")]
StyleNotFound(String),
/// A referenced resource was not found.
#[error("Resource not found: {0}")]
ResourceNotFound(String),
/// The document is encrypted and cannot be processed.
#[error("Document is encrypted")]
Encrypted,
/// Error during rendering.
#[error("Render error: {0}")]
Render(String),
}
impl From<zip::result::ZipError> for Error {
fn from(err: zip::result::ZipError) -> Self {
Error::ZipArchive(err.to_string())
}
}
impl From<quick_xml::Error> for Error {
fn from(err: quick_xml::Error) -> Self {
Error::XmlParse(err.to_string())
}
}
impl Error {
/// Create an XML parse error with context information.
///
/// # Arguments
/// * `message` - The error message
/// * `location` - Context such as file path or element being parsed
///
/// # Example
/// ```ignore
/// Error::xml_parse_with_context("Invalid element", "word/document.xml")
/// ```
pub fn xml_parse_with_context(message: impl Into<String>, location: impl Into<String>) -> Self {
Error::XmlParseWithContext {
message: message.into(),
location: location.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = Error::UnknownFormat;
assert_eq!(err.to_string(), "Unknown file format");
let err = Error::UnsupportedFormat("legacy .doc".to_string());
assert_eq!(err.to_string(), "Unsupported format: legacy .doc");
}
#[test]
fn test_error_from_io() {
let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
let err: Error = io_err.into();
assert!(matches!(err, Error::Io(_)));
}
}