Skip to main content

haagenti_core/
error.rs

1//! Error types for compression operations.
2
3use thiserror::Error;
4
5/// Result type alias for compression operations.
6pub type Result<T> = core::result::Result<T, Error>;
7
8/// Compression error types.
9#[derive(Debug, Error)]
10pub enum Error {
11    /// Input data is corrupted or invalid.
12    #[error("corrupted data: {message}")]
13    CorruptedData {
14        message: String,
15        #[source]
16        source: Option<Box<dyn std::error::Error + Send + Sync>>,
17    },
18
19    /// Buffer too small for output.
20    #[error("buffer too small: need {required} bytes, got {provided}")]
21    BufferTooSmall { required: usize, provided: usize },
22
23    /// Invalid compression level specified.
24    #[error("invalid compression level {level}: must be in range [{min}, {max}]")]
25    InvalidLevel { level: i32, min: i32, max: i32 },
26
27    /// Dictionary not found or invalid.
28    #[error("invalid dictionary: {0}")]
29    InvalidDictionary(String),
30
31    /// Checksum verification failed.
32    #[error("checksum mismatch: expected 0x{expected:08x}, got 0x{actual:08x}")]
33    ChecksumMismatch { expected: u32, actual: u32 },
34
35    /// Unexpected end of input stream.
36    #[error("unexpected EOF after {bytes_read} bytes")]
37    UnexpectedEof { bytes_read: usize },
38
39    /// I/O error from underlying stream.
40    #[error("I/O error: {0}")]
41    Io(#[from] std::io::Error),
42
43    /// Memory allocation failed.
44    #[error("allocation failed: could not allocate {requested_bytes} bytes")]
45    AllocationFailed { requested_bytes: usize },
46
47    /// Algorithm-specific error.
48    #[error("{algorithm} error: {message}")]
49    Algorithm {
50        algorithm: &'static str,
51        message: String,
52    },
53
54    /// Stream state error.
55    #[error("invalid state: expected {expected}, got {actual}")]
56    InvalidState {
57        expected: &'static str,
58        actual: &'static str,
59    },
60
61    /// Unsupported feature or format.
62    #[error("unsupported: {0}")]
63    Unsupported(String),
64}
65
66impl Error {
67    /// Create a corrupted data error.
68    pub fn corrupted(message: impl Into<String>) -> Self {
69        Error::CorruptedData {
70            message: message.into(),
71            source: None,
72        }
73    }
74
75    /// Create a corrupted data error with offset context.
76    pub fn corrupted_at(message: impl Into<String>, offset: usize) -> Self {
77        Error::CorruptedData {
78            message: format!("{} at offset {}", message.into(), offset),
79            source: None,
80        }
81    }
82
83    /// Create a buffer too small error.
84    pub fn buffer_too_small(required: usize, provided: usize) -> Self {
85        Error::BufferTooSmall { required, provided }
86    }
87
88    /// Create a checksum mismatch error.
89    pub fn checksum_mismatch(expected: u32, actual: u32) -> Self {
90        Error::ChecksumMismatch { expected, actual }
91    }
92
93    /// Create an unexpected EOF error.
94    pub fn unexpected_eof(bytes_read: usize) -> Self {
95        Error::UnexpectedEof { bytes_read }
96    }
97
98    /// Create an I/O error with a custom message.
99    pub fn io(message: impl Into<String>) -> Self {
100        Error::Io(std::io::Error::other(message.into()))
101    }
102
103    /// Create an algorithm-specific error.
104    pub fn algorithm(algorithm: &'static str, message: impl Into<String>) -> Self {
105        Error::Algorithm {
106            algorithm,
107            message: message.into(),
108        }
109    }
110
111    /// Check if error is recoverable (can retry with different parameters).
112    pub fn is_recoverable(&self) -> bool {
113        matches!(
114            self,
115            Error::UnexpectedEof { .. } | Error::BufferTooSmall { .. }
116        )
117    }
118
119    /// Get error category for metrics.
120    pub fn category(&self) -> &'static str {
121        match self {
122            Error::CorruptedData { .. } => "corrupted_data",
123            Error::BufferTooSmall { .. } => "buffer_too_small",
124            Error::InvalidLevel { .. } => "invalid_level",
125            Error::InvalidDictionary(_) => "invalid_dictionary",
126            Error::ChecksumMismatch { .. } => "checksum_mismatch",
127            Error::UnexpectedEof { .. } => "unexpected_eof",
128            Error::Io(_) => "io_error",
129            Error::AllocationFailed { .. } => "allocation_failed",
130            Error::Algorithm { .. } => "algorithm_error",
131            Error::InvalidState { .. } => "invalid_state",
132            Error::Unsupported(_) => "unsupported",
133        }
134    }
135}