in_memory_cache/
error.rs

1//! Error types for the in-memory cache library.
2//!
3//! This module defines a comprehensive error type that covers all failure modes
4//! of the cache operations, avoiding panics in favor of explicit error handling.
5
6use std::fmt;
7use std::io;
8
9/// The main error type for cache operations.
10///
11/// This enum covers all possible error conditions that can occur when
12/// interacting with the cache, from key-not-found conditions to I/O errors.
13#[derive(Debug)]
14pub enum CacheError {
15    /// The requested key was not found in the cache.
16    KeyNotFound(String),
17
18    /// The command received was invalid or malformed.
19    InvalidCommand(String),
20
21    /// Failed to parse the input buffer or protocol message.
22    ParseError(String),
23
24    /// An I/O error occurred (network, file, etc.).
25    IoError(io::Error),
26
27    /// The cache has reached its maximum capacity.
28    CapacityExceeded { current: usize, max: usize },
29
30    /// The provided key is invalid (empty, too long, etc.).
31    InvalidKey(String),
32
33    /// The provided value is invalid (too large, etc.).
34    InvalidValue(String),
35
36    /// A lock could not be acquired (poisoned mutex).
37    LockError(String),
38}
39
40impl fmt::Display for CacheError {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        match self {
43            CacheError::KeyNotFound(key) => write!(f, "key not found: '{}'", key),
44            CacheError::InvalidCommand(cmd) => write!(f, "invalid command: '{}'", cmd),
45            CacheError::ParseError(msg) => write!(f, "parse error: {}", msg),
46            CacheError::IoError(err) => write!(f, "I/O error: {}", err),
47            CacheError::CapacityExceeded { current, max } => {
48                write!(f, "capacity exceeded: {} items (max: {})", current, max)
49            }
50            CacheError::InvalidKey(reason) => write!(f, "invalid key: {}", reason),
51            CacheError::InvalidValue(reason) => write!(f, "invalid value: {}", reason),
52            CacheError::LockError(msg) => write!(f, "lock error: {}", msg),
53        }
54    }
55}
56
57impl std::error::Error for CacheError {
58    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
59        match self {
60            CacheError::IoError(err) => Some(err),
61            _ => None,
62        }
63    }
64}
65
66impl From<io::Error> for CacheError {
67    fn from(err: io::Error) -> Self {
68        CacheError::IoError(err)
69    }
70}
71
72/// A specialized Result type for cache operations.
73pub type CacheResult<T> = Result<T, CacheError>;
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_error_display() {
81        let err = CacheError::KeyNotFound("mykey".to_string());
82        assert_eq!(format!("{}", err), "key not found: 'mykey'");
83
84        let err = CacheError::InvalidCommand("foo".to_string());
85        assert_eq!(format!("{}", err), "invalid command: 'foo'");
86
87        let err = CacheError::CapacityExceeded {
88            current: 100,
89            max: 100,
90        };
91        assert_eq!(
92            format!("{}", err),
93            "capacity exceeded: 100 items (max: 100)"
94        );
95    }
96
97    #[test]
98    fn test_io_error_conversion() {
99        let io_err = io::Error::new(io::ErrorKind::ConnectionRefused, "connection refused");
100        let cache_err: CacheError = io_err.into();
101        assert!(matches!(cache_err, CacheError::IoError(_)));
102    }
103}