use std::fmt;
use std::io;
#[derive(Debug)]
pub enum PdfError {
Io(io::Error),
SyntaxError {
position: usize,
message: String,
},
InvalidStructure(String),
EncryptionError(String),
PasswordRequired,
InvalidPassword,
NonCompliant {
standard: String,
reason: String,
},
UnsupportedFeature(String),
TypeError {
expected: String,
found: String,
},
ResourceNotFound(String),
InvalidResource(String),
ParseError(String),
InvalidReference(String),
InvalidFont(String),
InvalidImage(String),
InvalidAnnotation(String),
InvalidFormField(String),
InvalidPage(String),
XRefError(String),
CompressionError(String),
EncodingError(String),
OcrError(String),
Other(String),
}
impl fmt::Display for PdfError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PdfError::Io(err) => write!(f, "I/O error: {}", err),
PdfError::SyntaxError { position, message } => {
write!(f, "Syntax error at position {}: {}", position, message)
}
PdfError::InvalidStructure(msg) => write!(f, "Invalid PDF structure: {}", msg),
PdfError::EncryptionError(msg) => write!(f, "Encryption error: {}", msg),
PdfError::PasswordRequired => write!(f, "Password required to open this document"),
PdfError::InvalidPassword => write!(f, "Invalid password provided"),
PdfError::NonCompliant { standard, reason } => {
write!(f, "Not compliant with {}: {}", standard, reason)
}
PdfError::UnsupportedFeature(msg) => write!(f, "Unsupported feature: {}", msg),
PdfError::TypeError { expected, found } => {
write!(f, "Type error: expected {}, found {}", expected, found)
}
PdfError::ResourceNotFound(msg) => write!(f, "Resource not found: {}", msg),
PdfError::InvalidResource(msg) => write!(f, "Invalid resource: {}", msg),
PdfError::ParseError(msg) => write!(f, "Parse error: {}", msg),
PdfError::InvalidReference(msg) => write!(f, "Invalid reference: {}", msg),
PdfError::InvalidFont(msg) => write!(f, "Invalid font: {}", msg),
PdfError::InvalidImage(msg) => write!(f, "Invalid image: {}", msg),
PdfError::InvalidAnnotation(msg) => write!(f, "Invalid annotation: {}", msg),
PdfError::InvalidFormField(msg) => write!(f, "Invalid form field: {}", msg),
PdfError::InvalidPage(msg) => write!(f, "Invalid page: {}", msg),
PdfError::XRefError(msg) => write!(f, "Cross-reference error: {}", msg),
PdfError::CompressionError(msg) => write!(f, "Compression error: {}", msg),
PdfError::EncodingError(msg) => write!(f, "Encoding error: {}", msg),
PdfError::OcrError(msg) => write!(f, "OCR error: {}", msg),
PdfError::Other(msg) => write!(f, "Error: {}", msg),
}
}
}
impl std::error::Error for PdfError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
PdfError::Io(err) => Some(err),
_ => None,
}
}
}
impl From<io::Error> for PdfError {
fn from(err: io::Error) -> Self {
PdfError::Io(err)
}
}
impl From<std::string::FromUtf8Error> for PdfError {
fn from(err: std::string::FromUtf8Error) -> Self {
PdfError::EncodingError(format!("UTF-8 conversion error: {}", err))
}
}
pub type PdfResult<T> = Result<T, PdfError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = PdfError::SyntaxError {
position: 42,
message: "Unexpected token".to_string(),
};
assert_eq!(
format!("{}", err),
"Syntax error at position 42: Unexpected token"
);
}
#[test]
fn test_error_from_io() {
let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
let pdf_err: PdfError = io_err.into();
assert!(matches!(pdf_err, PdfError::Io(_)));
}
#[test]
fn test_type_error() {
let err = PdfError::TypeError {
expected: "Dictionary".to_string(),
found: "Array".to_string(),
};
assert_eq!(
format!("{}", err),
"Type error: expected Dictionary, found Array"
);
}
}