1use crate::dto::prelude::*;
2use std::fmt::{self, Display};
3
4#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
12pub struct Error {
13 pub code: ErrorCode,
14 pub message: String,
15}
16
17impl Display for Error {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 write!(f, "[{:?}] {}", self.code, self.message)
20 }
21}
22
23impl Error {
24 #[must_use]
25 pub const fn new(code: ErrorCode, message: String) -> Self {
26 Self { code, message }
27 }
28
29 pub fn conflict(message: impl Into<String>) -> Self {
31 Self::new(ErrorCode::Conflict, message.into())
32 }
33
34 pub fn forbidden(message: impl Into<String>) -> Self {
36 Self::new(ErrorCode::Forbidden, message.into())
37 }
38
39 pub fn internal(message: impl Into<String>) -> Self {
41 Self::new(ErrorCode::Internal, message.into())
42 }
43
44 pub fn invalid(message: impl Into<String>) -> Self {
46 Self::new(ErrorCode::InvalidInput, message.into())
47 }
48
49 pub fn invariant(message: impl Into<String>) -> Self {
51 Self::new(ErrorCode::InvariantViolation, message.into())
52 }
53
54 pub fn exhausted(message: impl Into<String>) -> Self {
56 Self::new(ErrorCode::ResourceExhausted, message.into())
57 }
58
59 pub fn not_found(message: impl Into<String>) -> Self {
61 Self::new(ErrorCode::NotFound, message.into())
62 }
63
64 pub fn unauthorized(message: impl Into<String>) -> Self {
66 Self::new(ErrorCode::Unauthorized, message.into())
67 }
68}
69
70#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
78#[non_exhaustive]
79#[remain::sorted]
80pub enum ErrorCode {
81 Conflict,
82 Forbidden,
83 Internal,
84 InvalidInput,
85 InvariantViolation,
86 NotFound,
87 ResourceExhausted,
88 Unauthorized,
89}