1use std::error::Error;
2use std::fmt;
3
4#[derive(Debug, Clone)]
6pub enum RullstError {
7 RecordNotFound,
9 DatabaseError(String),
11 SerializationError(String),
13 CacheError(String),
15 Validation(String),
17 Internal(String),
19}
20
21impl fmt::Display for RullstError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 RullstError::RecordNotFound => write!(f, "Record not found"),
25 RullstError::DatabaseError(msg) => write!(f, "Database error: {}", msg),
26 RullstError::SerializationError(msg) => write!(f, "Serialization error: {}", msg),
27 RullstError::CacheError(msg) => write!(f, "Cache error: {}", msg),
28 RullstError::Validation(msg) => write!(f, "Validation error: {}", msg),
29 RullstError::Internal(msg) => write!(f, "Internal error: {}", msg),
30 }
31 }
32}
33
34impl Error for RullstError {}
35
36impl From<sqlx::Error> for RullstError {
37 fn from(err: sqlx::Error) -> Self {
38 match err {
39 sqlx::Error::RowNotFound => RullstError::RecordNotFound,
40 _ => RullstError::DatabaseError(err.to_string()),
41 }
42 }
43}
44
45impl From<serde_json::Error> for RullstError {
46 fn from(err: serde_json::Error) -> Self {
47 RullstError::SerializationError(err.to_string())
48 }
49}
50
51#[cfg(feature = "redis")]
52impl From<redis::RedisError> for RullstError {
53 #[cfg_attr(test, mutants::skip)]
54 fn from(err: redis::RedisError) -> Self {
55 RullstError::CacheError(err.to_string())
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_rullst_error_display() {
65 assert_eq!(RullstError::RecordNotFound.to_string(), "Record not found");
66 assert_eq!(
67 RullstError::DatabaseError("msg".to_string()).to_string(),
68 "Database error: msg"
69 );
70 assert_eq!(
71 RullstError::SerializationError("msg".to_string()).to_string(),
72 "Serialization error: msg"
73 );
74 assert_eq!(
75 RullstError::Validation("msg".to_string()).to_string(),
76 "Validation error: msg"
77 );
78 assert_eq!(
79 RullstError::Internal("msg".to_string()).to_string(),
80 "Internal error: msg"
81 );
82 }
83
84 #[test]
85 fn test_rullst_error_from() {
86 let sqlx_err = sqlx::Error::RowNotFound;
87 let err: RullstError = sqlx_err.into();
88 assert!(matches!(err, RullstError::RecordNotFound));
89
90 let sqlx_other_err = sqlx::Error::PoolClosed;
91 let err2: RullstError = sqlx_other_err.into();
92 assert!(matches!(err2, RullstError::DatabaseError(_)));
93 }
94
95 #[test]
96 fn test_serde_json_error_from() {
97 let json_err = serde_json::from_str::<serde_json::Value>("{invalid}").unwrap_err();
98 let err: RullstError = json_err.into();
99 assert!(matches!(err, RullstError::SerializationError(_)));
100 assert!(err.to_string().contains("Serialization error:"));
101 }
102
103 #[cfg(feature = "redis")]
104 #[test]
105 fn test_redis_error_from() {
106 let redis_err = redis::RedisError::from((redis::ErrorKind::Io, "redis io error"));
107 let err: RullstError = redis_err.into();
108 assert!(matches!(err, RullstError::CacheError(_)));
109 assert_eq!(err.to_string(), "Cache error: redis io error - Io");
110 }
111}