1use std::error::Error;
4use std::fmt;
5
6#[derive(Debug, Eq, PartialEq)]
12#[non_exhaustive]
13pub enum BuildError {
14 DuplicateOperation {
16 name: String,
18 },
19 DuplicateHandler {
21 name: String,
23 },
24 MissingDescriptor {
26 name: String,
28 },
29 MissingHandler {
31 name: String,
33 },
34 InvalidModule {
36 name: String,
38 message: String,
40 },
41 InvalidOperation {
43 name: String,
45 message: String,
47 },
48 InvalidHandler {
50 name: String,
52 message: String,
54 },
55 MissingReceiptSink,
64}
65
66impl BuildError {
67 #[must_use]
69 pub fn duplicate_operation(name: impl Into<String>) -> Self {
70 Self::DuplicateOperation { name: name.into() }
71 }
72
73 #[must_use]
75 pub fn duplicate_handler(name: impl Into<String>) -> Self {
76 Self::DuplicateHandler { name: name.into() }
77 }
78
79 #[must_use]
81 pub fn missing_descriptor(name: impl Into<String>) -> Self {
82 Self::MissingDescriptor { name: name.into() }
83 }
84
85 #[must_use]
87 pub fn missing_handler(name: impl Into<String>) -> Self {
88 Self::MissingHandler { name: name.into() }
89 }
90
91 #[must_use]
93 pub fn invalid_module(name: impl Into<String>, message: impl Into<String>) -> Self {
94 Self::InvalidModule {
95 name: name.into(),
96 message: message.into(),
97 }
98 }
99
100 #[must_use]
102 pub fn invalid_operation(name: impl Into<String>, message: impl Into<String>) -> Self {
103 Self::InvalidOperation {
104 name: name.into(),
105 message: message.into(),
106 }
107 }
108
109 #[must_use]
111 pub fn invalid_handler(name: impl Into<String>, message: impl Into<String>) -> Self {
112 Self::InvalidHandler {
113 name: name.into(),
114 message: message.into(),
115 }
116 }
117}
118
119impl fmt::Display for BuildError {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 match self {
122 Self::DuplicateOperation { name } => {
123 write!(f, "operation `{name}` is already registered")
124 }
125 Self::DuplicateHandler { name } => {
126 write!(f, "handler for operation `{name}` is already registered")
127 }
128 Self::MissingDescriptor { name } => {
129 write!(f, "handler `{name}` has no matching operation descriptor")
130 }
131 Self::MissingHandler { name } => {
132 write!(f, "operation `{name}` has no registered handler")
133 }
134 Self::InvalidModule { name, message } => {
135 write!(f, "module `{name}` is invalid: {message}")
136 }
137 Self::InvalidOperation { name, message } => {
138 write!(f, "operation `{name}` is invalid: {message}")
139 }
140 Self::InvalidHandler { name, message } => {
141 write!(f, "handler `{name}` is invalid: {message}")
142 }
143 Self::MissingReceiptSink => f.write_str(
144 "core has no receipt sink: a sinkless core silently drops every runtime \
145 receipt. Wire one with CoreBuilder::receipt_sink, or opt out explicitly \
146 with CoreBuilder::without_receipts",
147 ),
148 }
149 }
150}
151
152impl Error for BuildError {}
153
154#[derive(Clone, Debug, Eq, PartialEq)]
156#[non_exhaustive]
157pub struct ReceiptSinkHandlerCause {
158 pub code: String,
160 pub message: String,
162}
163
164impl ReceiptSinkHandlerCause {
165 #[must_use]
167 pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
168 Self {
169 code: code.into(),
170 message: message.into(),
171 }
172 }
173
174 #[must_use]
176 pub fn code(&self) -> &str {
177 &self.code
178 }
179
180 #[must_use]
182 pub fn message(&self) -> &str {
183 &self.message
184 }
185}
186
187#[derive(Debug, Eq, PartialEq)]
194#[non_exhaustive]
195pub enum RuntimeError {
196 UnknownOperation {
198 name: String,
200 },
201 MissingHandler {
203 name: String,
205 },
206 Handler {
208 name: String,
210 code: String,
212 message: String,
214 },
215 Denied {
219 name: String,
221 code: String,
223 message: String,
225 },
226 ReceiptSink {
228 name: String,
230 message: String,
232 caused_by_handler: Option<ReceiptSinkHandlerCause>,
234 },
235 StatusSink {
237 name: String,
239 message: String,
241 caused_by_handler: Option<ReceiptSinkHandlerCause>,
243 },
244}
245
246impl RuntimeError {
247 #[must_use]
249 pub fn unknown_operation(name: impl Into<String>) -> Self {
250 Self::UnknownOperation { name: name.into() }
251 }
252
253 #[must_use]
255 pub fn missing_handler(name: impl Into<String>) -> Self {
256 Self::MissingHandler { name: name.into() }
257 }
258
259 #[must_use]
261 pub fn handler(
262 name: impl Into<String>,
263 code: impl Into<String>,
264 message: impl Into<String>,
265 ) -> Self {
266 Self::Handler {
267 name: name.into(),
268 code: code.into(),
269 message: message.into(),
270 }
271 }
272
273 #[must_use]
275 pub fn denied(
276 name: impl Into<String>,
277 code: impl Into<String>,
278 message: impl Into<String>,
279 ) -> Self {
280 Self::Denied {
281 name: name.into(),
282 code: code.into(),
283 message: message.into(),
284 }
285 }
286
287 #[must_use]
289 pub fn receipt_sink(name: impl Into<String>, message: impl Into<String>) -> Self {
290 Self::ReceiptSink {
291 name: name.into(),
292 message: message.into(),
293 caused_by_handler: None,
294 }
295 }
296
297 #[must_use]
299 pub fn receipt_sink_after_handler_failure(
300 name: impl Into<String>,
301 message: impl Into<String>,
302 cause: ReceiptSinkHandlerCause,
303 ) -> Self {
304 Self::ReceiptSink {
305 name: name.into(),
306 message: message.into(),
307 caused_by_handler: Some(cause),
308 }
309 }
310
311 #[must_use]
313 pub fn status_sink(name: impl Into<String>, message: impl Into<String>) -> Self {
314 Self::StatusSink {
315 name: name.into(),
316 message: message.into(),
317 caused_by_handler: None,
318 }
319 }
320
321 #[must_use]
323 pub fn status_sink_after_handler_failure(
324 name: impl Into<String>,
325 message: impl Into<String>,
326 cause: ReceiptSinkHandlerCause,
327 ) -> Self {
328 Self::StatusSink {
329 name: name.into(),
330 message: message.into(),
331 caused_by_handler: Some(cause),
332 }
333 }
334}
335
336impl fmt::Display for RuntimeError {
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 match self {
339 Self::UnknownOperation { name } => write!(f, "unknown operation `{name}`"),
340 Self::MissingHandler { name } => {
341 write!(f, "operation `{name}` has no registered handler")
342 }
343 Self::Handler {
344 name,
345 code,
346 message,
347 } => {
348 write!(
349 f,
350 "handler for operation `{name}` failed with {code}: {message}"
351 )
352 }
353 Self::Denied {
354 name,
355 code,
356 message,
357 } => {
358 write!(f, "operation `{name}` denied with {code}: {message}")
359 }
360 Self::ReceiptSink {
361 name,
362 message,
363 caused_by_handler,
364 } => {
365 if let Some(cause) = caused_by_handler {
366 write!(
367 f,
368 "receipt sink for operation `{name}` failed after handler error {}: {}: {message}",
369 cause.code(),
370 cause.message()
371 )
372 } else {
373 write!(f, "receipt sink for operation `{name}` failed: {message}")
374 }
375 }
376 Self::StatusSink {
377 name,
378 message,
379 caused_by_handler,
380 } => {
381 if let Some(cause) = caused_by_handler {
382 write!(
383 f,
384 "status sink for operation `{name}` failed after handler error {}: {}: {message}",
385 cause.code(),
386 cause.message()
387 )
388 } else {
389 write!(f, "status sink for operation `{name}` failed: {message}")
390 }
391 }
392 }
393 }
394}
395
396impl Error for RuntimeError {}