use std::fmt;
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone)]
pub enum PdfError {
InvalidPdf(String),
PasswordRequired,
InvalidPassword,
EncryptionNotSupported(String),
PageNotFound(usize),
TextExtractionFailed(String),
RenderingFailed(String),
MetadataExtractionFailed(String),
ExtractionFailed(String),
FontLoadingFailed(String),
IOError(String),
Cancelled,
}
impl fmt::Display for PdfError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PdfError::InvalidPdf(msg) => write!(f, "Invalid PDF: {}", msg),
PdfError::PasswordRequired => write!(f, "PDF is password-protected"),
PdfError::InvalidPassword => write!(f, "Invalid password provided"),
PdfError::EncryptionNotSupported(msg) => {
write!(f, "Encryption not supported: {}", msg)
}
PdfError::PageNotFound(page) => write!(f, "Page {} not found", page),
PdfError::TextExtractionFailed(msg) => write!(f, "Text extraction failed: {}", msg),
PdfError::RenderingFailed(msg) => write!(f, "Page rendering failed: {}", msg),
PdfError::MetadataExtractionFailed(msg) => {
write!(f, "Metadata extraction failed: {}", msg)
}
PdfError::ExtractionFailed(msg) => write!(f, "Extraction failed: {}", msg),
PdfError::FontLoadingFailed(msg) => write!(f, "Font loading failed: {}", msg),
PdfError::IOError(msg) => write!(f, "I/O error: {}", msg),
PdfError::Cancelled => write!(f, "Extraction cancelled"),
}
}
}
impl std::error::Error for PdfError {}
impl From<lopdf::Error> for PdfError {
fn from(err: lopdf::Error) -> Self {
match err {
lopdf::Error::IO(io_err) => PdfError::IOError(io_err.to_string()),
_ => PdfError::InvalidPdf(err.to_string()),
}
}
}
pub type Result<T> = std::result::Result<T, PdfError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_invalid_pdf_error() {
let err = PdfError::InvalidPdf("corrupted header".to_string());
assert_eq!(err.to_string(), "Invalid PDF: corrupted header");
}
#[test]
fn test_password_required_error() {
let err = PdfError::PasswordRequired;
assert_eq!(err.to_string(), "PDF is password-protected");
}
#[test]
fn test_invalid_password_error() {
let err = PdfError::InvalidPassword;
assert_eq!(err.to_string(), "Invalid password provided");
}
#[test]
fn test_encryption_not_supported_error() {
let err = PdfError::EncryptionNotSupported("AES-256".to_string());
assert_eq!(err.to_string(), "Encryption not supported: AES-256");
}
#[test]
fn test_page_not_found_error() {
let err = PdfError::PageNotFound(5);
assert_eq!(err.to_string(), "Page 5 not found");
}
#[test]
fn test_text_extraction_failed_error() {
let err = PdfError::TextExtractionFailed("no text layer".to_string());
assert_eq!(err.to_string(), "Text extraction failed: no text layer");
}
#[test]
fn test_rendering_failed_error() {
let err = PdfError::RenderingFailed("out of memory".to_string());
assert_eq!(err.to_string(), "Page rendering failed: out of memory");
}
#[test]
fn test_metadata_extraction_failed_error() {
let err = PdfError::MetadataExtractionFailed("invalid metadata".to_string());
assert_eq!(err.to_string(), "Metadata extraction failed: invalid metadata");
}
#[test]
fn test_io_error() {
let err = PdfError::IOError("read failed".to_string());
assert_eq!(err.to_string(), "I/O error: read failed");
}
#[test]
fn test_error_debug() {
let err = PdfError::InvalidPassword;
let debug_str = format!("{:?}", err);
assert!(debug_str.contains("InvalidPassword"));
}
#[test]
fn test_error_clone() {
let err1 = PdfError::PageNotFound(3);
let err2 = err1.clone();
assert_eq!(err1.to_string(), err2.to_string());
}
#[test]
fn test_extraction_failed_error() {
let err = PdfError::ExtractionFailed("page data mismatch".to_string());
assert_eq!(err.to_string(), "Extraction failed: page data mismatch");
}
#[test]
fn test_font_loading_failed_error() {
let err = PdfError::FontLoadingFailed("missing font file".to_string());
assert_eq!(err.to_string(), "Font loading failed: missing font file");
}
}