Skip to main content

rullst_orm/
error.rs

1use std::error::Error;
2use std::fmt;
3
4/// The standard error type for rullst-orm, shielding users from internal dependency errors.
5#[derive(Debug, Clone)]
6pub enum RullstError {
7    /// A record was not found in the database.
8    RecordNotFound,
9    /// A general database or query error.
10    DatabaseError(String),
11    /// A serialization or deserialization error (e.g., JSON).
12    SerializationError(String),
13    /// A cache or event-related error.
14    CacheError(String),
15    /// A validation error, such as invalid SQL identifiers.
16    Validation(String),
17    /// Other internal errors.
18    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}