use std::io;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("Unknown file format")]
UnknownFormat,
#[error("Unsupported format: {0}")]
UnsupportedFormat(String),
#[error("ZIP archive error: {0}")]
ZipArchive(String),
#[error("XML parse error in {location}: {message}")]
XmlParseWithContext {
message: String,
location: String,
},
#[error("XML parse error: {0}")]
XmlParse(String),
#[error("Invalid data: {0}")]
InvalidData(String),
#[error("Missing component: {0}")]
MissingComponent(String),
#[error("Encoding error: {0}")]
Encoding(String),
#[error("Style not found: {0}")]
StyleNotFound(String),
#[error("Resource not found: {0}")]
ResourceNotFound(String),
#[error("Document is encrypted")]
Encrypted,
#[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 From<quick_xml::DeError> for Error {
fn from(err: quick_xml::DeError) -> Self {
Error::XmlParse(err.to_string())
}
}
impl Error {
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(_)));
}
}