dogy_backend_api/service/users/
error.rs

1//! This module contains the error types for users in axum handlers.
2//!
3//! This follows the rust-10x production code convention for handling errors.
4//! See [this video](https://www.youtube.com/watch?v=j-VQCYP7wyw) to know more about it.
5
6use serde::Serialize;
7use serde_with::{serde_as, DisplayFromStr};
8use sqlx::Error as SqlxError;
9
10//pub type Result<T> = core::result::Result<T, Error>;
11
12/// Error types for users in axum handlers.
13#[serde_as]
14#[derive(Debug, Serialize)]
15pub enum Error {
16    /// This error will occur if a user tries to create a new user with an existing `user_id`.
17    UserAlreadyExists,
18
19    /// This error wraps [`sqlx::Error`] for the error codes that haven't been map.
20    ///
21    /// Serves as a fallback error if in case an unknown error with no mapping occurs.
22    Sqlx(#[serde_as(as = "DisplayFromStr")] sqlx::Error),
23}
24
25impl From<SqlxError> for Error {
26    /// Maps generic sqlx errors into a user-defined error type. Otherwise, just return generic
27    /// sqlx error as a `String`.
28    fn from(err: SqlxError) -> Self {
29        if let SqlxError::Database(db_err) = &err {
30            if let Some(code) = db_err.code() {
31                match code.as_ref() {
32                    "23505" => Error::UserAlreadyExists,
33                    //"23503" => Error::Sqlx(SqlxError::Database(DatabaseError::ForeignKeyViolation)),
34                    _ => Error::Sqlx(err),
35                }
36            } else {
37                Error::Sqlx(err)
38            }
39        } else {
40            Error::Sqlx(err)
41        }
42    }
43}
44
45// Boilerplate for Errors
46impl core::fmt::Display for Error {
47    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
48        write!(fmt, "{self:?}")
49    }
50}
51
52impl std::error::Error for Error {}