Skip to main content

cache_lite/
error.rs

1/*
2 * @filename: error.rs
3 * @description: Used for describing and handling cache errors
4 * @author: TaimWay <taimway@gmail.com>
5 * 
6 * Copyright (C) 2026 TaimWay
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27use std::fmt;
28use std::io;
29
30/// Cache library error types
31#[derive(Debug)]
32pub enum CacheError {
33    /// I/O operation failed
34    Io(io::Error),
35    /// Invalid cache name
36    InvalidName(String),
37    /// Configuration parsing error
38    ConfigParse(String),
39    /// Cache object not found
40    NotFound(String),
41    /// Permission denied for operation
42    PermissionDenied(String),
43    /// Cache object already exists
44    AlreadyExists(String),
45    /// Cache object has expired
46    Expired(String),
47    /// Invalid configuration provided
48    InvalidConfig(String),
49    /// Serialization/deserialization error
50    Serialization(String),
51    /// Invalid path or directory
52    InvalidPath(String),
53    /// Generic error with message
54    Generic(String),
55}
56
57impl fmt::Display for CacheError {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        match self {
60            CacheError::Io(err) => write!(f, "I/O error: {}", err),
61            CacheError::InvalidName(msg) => write!(f, "Invalid cache name: {}", msg),
62            CacheError::ConfigParse(msg) => write!(f, "Configuration parse error: {}", msg),
63            CacheError::NotFound(msg) => write!(f, "Cache not found: {}", msg),
64            CacheError::PermissionDenied(msg) => write!(f, "Permission denied: {}", msg),
65            CacheError::AlreadyExists(msg) => write!(f, "Cache already exists: {}", msg),
66            CacheError::Expired(msg) => write!(f, "Cache expired: {}", msg),
67            CacheError::InvalidConfig(msg) => write!(f, "Invalid configuration: {}", msg),
68            CacheError::Serialization(msg) => write!(f, "Serialization error: {}", msg),
69            CacheError::InvalidPath(msg) => write!(f, "Invalid path: {}", msg),
70            CacheError::Generic(msg) => write!(f, "Error: {}", msg),
71        }
72    }
73}
74
75impl std::error::Error for CacheError {}
76
77impl From<io::Error> for CacheError {
78    fn from(err: io::Error) -> Self {
79        CacheError::Io(err)
80    }
81}
82
83impl From<serde_json::Error> for CacheError {
84    fn from(err: serde_json::Error) -> Self {
85        CacheError::ConfigParse(err.to_string())
86    }
87}
88
89impl CacheError {
90    /// Returns the error kind as a string
91    pub fn kind(&self) -> &'static str {
92        match self {
93            CacheError::Io(_) => "io",
94            CacheError::InvalidName(_) => "invalid_name",
95            CacheError::ConfigParse(_) => "config_parse",
96            CacheError::NotFound(_) => "not_found",
97            CacheError::PermissionDenied(_) => "permission_denied",
98            CacheError::AlreadyExists(_) => "already_exists",
99            CacheError::Expired(_) => "expired",
100            CacheError::InvalidConfig(_) => "invalid_config",
101            CacheError::Serialization(_) => "serialization",
102            CacheError::InvalidPath(_) => "invalid_path",
103            CacheError::Generic(_) => "generic",
104        }
105    }
106    
107    /// Returns the error message without the error kind prefix
108    pub fn message(&self) -> String {
109        match self {
110            CacheError::Io(err) => err.to_string(),
111            CacheError::InvalidName(msg) => msg.clone(),
112            CacheError::ConfigParse(msg) => msg.clone(),
113            CacheError::NotFound(msg) => msg.clone(),
114            CacheError::PermissionDenied(msg) => msg.clone(),
115            CacheError::AlreadyExists(msg) => msg.clone(),
116            CacheError::Expired(msg) => msg.clone(),
117            CacheError::InvalidConfig(msg) => msg.clone(),
118            CacheError::Serialization(msg) => msg.clone(),
119            CacheError::InvalidPath(msg) => msg.clone(),
120            CacheError::Generic(msg) => msg.clone(),
121        }
122    }
123    
124    /// Creates a new generic error
125    pub fn new<S: Into<String>>(message: S) -> Self {
126        CacheError::Generic(message.into())
127    }
128    
129    /// Checks if the error is an I/O error
130    pub fn is_io_error(&self) -> bool {
131        matches!(self, CacheError::Io(_))
132    }
133    
134    /// Checks if the error indicates something wasn't found
135    pub fn is_not_found(&self) -> bool {
136        matches!(self, CacheError::NotFound(_))
137    }
138    
139    /// Checks if the error indicates permission was denied
140    pub fn is_permission_denied(&self) -> bool {
141        matches!(self, CacheError::PermissionDenied(_))
142    }
143}