1use std::fmt;
2use thiserror::Error as ThisError;
3
4#[derive(Debug, ThisError)]
11#[error("{message}")]
12pub struct InternalError {
13 pub class: ErrorClass,
14 pub origin: ErrorOrigin,
15 pub message: String,
16
17 pub detail: Option<ErrorDetail>,
20}
21
22impl InternalError {
23 pub fn new(class: ErrorClass, origin: ErrorOrigin, message: impl Into<String>) -> Self {
27 let message = message.into();
28
29 let detail = match (class, origin) {
30 (ErrorClass::Corruption, ErrorOrigin::Store) => {
31 Some(ErrorDetail::Store(StoreError::Corrupt {
32 message: message.clone(),
33 }))
34 }
35 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
36 Some(ErrorDetail::Store(StoreError::InvariantViolation {
37 message: message.clone(),
38 }))
39 }
40 _ => None,
41 };
42
43 Self {
44 class,
45 origin,
46 message,
47 detail,
48 }
49 }
50
51 pub fn store_not_found(key: impl Into<String>) -> Self {
52 let key = key.into();
53
54 Self {
55 class: ErrorClass::NotFound,
56 origin: ErrorOrigin::Store,
57 message: format!("data key not found: {key}"),
58 detail: Some(ErrorDetail::Store(StoreError::NotFound { key })),
59 }
60 }
61
62 #[must_use]
63 pub const fn is_not_found(&self) -> bool {
64 matches!(
65 self.detail,
66 Some(ErrorDetail::Store(StoreError::NotFound { .. }))
67 )
68 }
69
70 #[must_use]
71 pub fn display_with_class(&self) -> String {
72 format!("{}:{}: {}", self.origin, self.class, self.message)
73 }
74}
75
76#[derive(Debug, ThisError)]
84pub enum ErrorDetail {
85 #[error("{0}")]
86 Store(StoreError),
87 }
97
98#[derive(Debug, ThisError)]
106pub enum StoreError {
107 #[error("key not found: {key}")]
108 NotFound { key: String },
109
110 #[error("store corruption: {message}")]
111 Corrupt { message: String },
112
113 #[error("store invariant violation: {message}")]
114 InvariantViolation { message: String },
115}
116
117#[derive(Clone, Copy, Debug, Eq, PartialEq)]
124pub enum ErrorClass {
125 Corruption,
126 NotFound,
127 Internal,
128 Conflict,
129 Unsupported,
130 InvariantViolation,
131}
132
133impl fmt::Display for ErrorClass {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 let label = match self {
136 Self::Corruption => "corruption",
137 Self::NotFound => "not_found",
138 Self::Internal => "internal",
139 Self::Conflict => "conflict",
140 Self::Unsupported => "unsupported",
141 Self::InvariantViolation => "invariant_violation",
142 };
143 write!(f, "{label}")
144 }
145}
146
147#[derive(Clone, Copy, Debug, Eq, PartialEq)]
154pub enum ErrorOrigin {
155 Serialize,
156 Store,
157 Index,
158 Query,
159 Response,
160 Executor,
161 Interface,
162}
163
164impl fmt::Display for ErrorOrigin {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 let label = match self {
167 Self::Serialize => "serialize",
168 Self::Store => "store",
169 Self::Index => "index",
170 Self::Query => "query",
171 Self::Response => "response",
172 Self::Executor => "executor",
173 Self::Interface => "interface",
174 };
175 write!(f, "{label}")
176 }
177}