parser_core/
errors.rs

1//! Error handling for the parser library.
2//!
3//! This module defines the error types used throughout the library and implements
4//! conversions from common external error types to our internal error type.
5
6/// Custom error type for the parser library.
7///
8/// Represents different categories of errors that can occur during parsing operations,
9/// including I/O errors, parsing errors, and format validation errors.
10#[derive(Debug)]
11pub enum ParserError {
12    /// An error occurred while reading or writing a file.
13    ///
14    /// This includes file system errors, issues with file permissions, or
15    /// problems with temporary file creation.
16    IoError(String),
17
18    /// An error occurred while parsing the content of a file.
19    ///
20    /// This includes syntax errors, encoding problems, or issues with
21    /// the internal structure of documents.
22    ParseError(String),
23
24    /// The file has an invalid or unsupported format.
25    ///
26    /// This occurs when the file type cannot be recognized or is not
27    /// supported by the parser library.
28    InvalidFormat(String),
29}
30
31impl std::fmt::Display for ParserError {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        match self {
34            ParserError::IoError(msg) => write!(f, "IO error: {}", msg),
35            ParserError::ParseError(msg) => write!(f, "Parse error: {}", msg),
36            ParserError::InvalidFormat(msg) => write!(f, "Invalid format: {}", msg),
37        }
38    }
39}
40
41/// Implements the std::error::Error trait for ParserError to allow it to be used
42/// with the ? operator and to be boxed as a dyn Error.
43impl std::error::Error for ParserError {}
44
45macro_rules! impl_from_error {
46    ($type:ty, $variant:expr) => {
47        impl From<$type> for ParserError {
48            fn from(err: $type) -> Self {
49                $variant(err.to_string())
50            }
51        }
52    };
53}
54
55// IO errors
56impl_from_error!(std::io::Error, ParserError::IoError);
57impl_from_error!(tesseract::InitializeError, ParserError::IoError);
58impl_from_error!(tesseract::SetImageError, ParserError::IoError);
59impl_from_error!(
60    tesseract::plumbing::TessBaseApiGetUtf8TextError,
61    ParserError::IoError
62);
63
64// Parse errors
65impl_from_error!(pdf_extract::OutputError, ParserError::ParseError);
66impl_from_error!(docx_rs::ReaderError, ParserError::ParseError);
67impl_from_error!(std::string::FromUtf8Error, ParserError::ParseError);
68impl_from_error!(std::str::Utf8Error, ParserError::ParseError);
69impl_from_error!(zip::result::ZipError, ParserError::ParseError);
70impl_from_error!(regex::Error, ParserError::ParseError);
71impl_from_error!(std::process::ExitStatus, ParserError::ParseError);
72impl_from_error!(calamine::XlsxError, ParserError::ParseError);
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_error_display() {
80        // Test each error variant's Display implementation
81        let io_err = ParserError::IoError("failed to read file".to_string());
82        let parse_err = ParserError::ParseError("failed to parse content".to_string());
83        let format_err = ParserError::InvalidFormat("invalid file format".to_string());
84
85        assert_eq!(io_err.to_string(), "IO error: failed to read file");
86        assert_eq!(
87            parse_err.to_string(),
88            "Parse error: failed to parse content"
89        );
90        assert_eq!(
91            format_err.to_string(),
92            "Invalid format: invalid file format"
93        );
94    }
95}