use std::{error::Error, fmt};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ErrorKind {
InvalidArgument,
NotFound,
Conflict,
Business,
Unavailable,
Infrastructure,
Internal,
}
#[derive(Debug)]
pub struct SaddleError {
kind: ErrorKind,
code: &'static str,
message: String,
}
impl SaddleError {
pub fn new(kind: ErrorKind, code: &'static str, message: impl Into<String>) -> Self {
Self {
kind,
code,
message: message.into(),
}
}
pub const fn kind(&self) -> ErrorKind {
self.kind
}
pub const fn code(&self) -> &'static str {
self.code
}
pub fn message(&self) -> &str {
&self.message
}
}
impl fmt::Display for SaddleError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{}: {}", self.code, self.message)
}
}
impl Error for SaddleError {}
pub type Result<T> = std::result::Result<T, SaddleError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_exposes_stable_classification() {
let error = SaddleError::new(ErrorKind::NotFound, "user.not_found", "user not found");
assert_eq!(error.kind(), ErrorKind::NotFound);
assert_eq!(error.code(), "user.not_found");
assert_eq!(error.to_string(), "user.not_found: user not found");
}
}