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 {
24 let message = message.into();
25
26 let detail = match (class, origin) {
27 (ErrorClass::Corruption, ErrorOrigin::Store) => {
28 Some(ErrorDetail::Store(StoreError::Corrupt {
29 message: message.clone(),
30 }))
31 }
32 (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
33 Some(ErrorDetail::Store(StoreError::InvariantViolation {
34 message: message.clone(),
35 }))
36 }
37 _ => None,
38 };
39
40 Self {
41 class,
42 origin,
43 message,
44 detail,
45 }
46 }
47
48 pub fn store_not_found(key: impl Into<String>) -> Self {
49 let key = key.into();
50
51 Self {
52 class: ErrorClass::NotFound,
53 origin: ErrorOrigin::Store,
54 message: format!("data key not found: {key}"),
55 detail: Some(ErrorDetail::Store(StoreError::NotFound { key })),
56 }
57 }
58
59 #[must_use]
60 pub const fn is_not_found(&self) -> bool {
61 matches!(
62 self.detail,
63 Some(ErrorDetail::Store(StoreError::NotFound { .. }))
64 )
65 }
66
67 #[must_use]
68 pub fn display_with_class(&self) -> String {
69 format!("{}:{}: {}", self.origin, self.class, self.message)
70 }
71}
72
73#[derive(Debug, ThisError)]
81pub enum ErrorDetail {
82 #[error("{0}")]
83 Store(StoreError),
84 }
94
95#[derive(Debug, ThisError)]
103pub enum StoreError {
104 #[error("key not found: {key}")]
105 NotFound { key: String },
106
107 #[error("store corruption: {message}")]
108 Corrupt { message: String },
109
110 #[error("store invariant violation: {message}")]
111 InvariantViolation { message: String },
112}
113
114#[derive(Clone, Copy, Debug, Eq, PartialEq)]
121pub enum ErrorClass {
122 Corruption,
123 NotFound,
124 Internal,
125 Conflict,
126 Unsupported,
127 InvariantViolation,
128}
129
130impl fmt::Display for ErrorClass {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 let label = match self {
133 Self::Corruption => "corruption",
134 Self::NotFound => "not_found",
135 Self::Internal => "internal",
136 Self::Conflict => "conflict",
137 Self::Unsupported => "unsupported",
138 Self::InvariantViolation => "invariant_violation",
139 };
140 write!(f, "{label}")
141 }
142}
143
144#[derive(Clone, Copy, Debug, Eq, PartialEq)]
151pub enum ErrorOrigin {
152 Serialize,
153 Store,
154 Index,
155 Query,
156 Response,
157 Executor,
158 Interface,
159}
160
161impl fmt::Display for ErrorOrigin {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 let label = match self {
164 Self::Serialize => "serialize",
165 Self::Store => "store",
166 Self::Index => "index",
167 Self::Query => "query",
168 Self::Response => "response",
169 Self::Executor => "executor",
170 Self::Interface => "interface",
171 };
172 write!(f, "{label}")
173 }
174}