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 #[error("{0}")]
88 ViewPatch(crate::traits::ViewPatchError),
89 }
99
100#[derive(Debug, ThisError)]
108pub enum StoreError {
109 #[error("key not found: {key}")]
110 NotFound { key: String },
111
112 #[error("store corruption: {message}")]
113 Corrupt { message: String },
114
115 #[error("store invariant violation: {message}")]
116 InvariantViolation { message: String },
117}
118
119#[derive(Clone, Copy, Debug, Eq, PartialEq)]
126pub enum ErrorClass {
127 Corruption,
128 NotFound,
129 Internal,
130 Conflict,
131 Unsupported,
132 InvariantViolation,
133}
134
135impl fmt::Display for ErrorClass {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 let label = match self {
138 Self::Corruption => "corruption",
139 Self::NotFound => "not_found",
140 Self::Internal => "internal",
141 Self::Conflict => "conflict",
142 Self::Unsupported => "unsupported",
143 Self::InvariantViolation => "invariant_violation",
144 };
145 write!(f, "{label}")
146 }
147}
148
149#[derive(Clone, Copy, Debug, Eq, PartialEq)]
156pub enum ErrorOrigin {
157 Serialize,
158 Store,
159 Index,
160 Query,
161 Response,
162 Executor,
163 Interface,
164}
165
166impl fmt::Display for ErrorOrigin {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 let label = match self {
169 Self::Serialize => "serialize",
170 Self::Store => "store",
171 Self::Index => "index",
172 Self::Query => "query",
173 Self::Response => "response",
174 Self::Executor => "executor",
175 Self::Interface => "interface",
176 };
177 write!(f, "{label}")
178 }
179}