Skip to main content

server/
error.rs

1use anyhow::Error as AnyhowError;
2use thiserror::*;
3
4/// Represents possible errors that can occur in the server.
5#[derive(Debug, Error)]
6pub enum ServerError {
7    /// The user's request is not permitted.
8    #[error("forbidden request: {0}")]
9    Forbidden(String),
10
11    /// The resource, e.g. game, cannot be found.
12    #[error("not found")]
13    NotFound,
14
15    /// An error occurred within the domain usage.
16    #[error(transparent)]
17    Domain(#[from] crate::domain::DomainError),
18
19    /// An unexpected error occurred; this wraps infrastrucutre errors as
20    /// well as internal defects.
21    #[error("internal server error: {0}")]
22    Internal(
23        #[from]
24        #[source]
25        AnyhowError,
26    ),
27}
28
29macro_rules! bug_inner {
30    ($msg:expr) => {{
31        let location = std::panic::Location::caller();
32        let message = format!("BUG at {}:{}:{} - {}",
33            location.file(), location.line(), location.column(), $msg);
34
35        #[cfg(feature = "backtrace")]
36        {
37            let backtrace = std::backtrace::Backtrace::capture();
38            if backtrace.status() == std::backtrace::BacktraceStatus::Captured {
39                use std::fmt::Write;
40                let _ = writeln!(message.clone(), "\n\nBacktrace:\n{backtrace:?}");
41            }
42        }
43
44        ServerError::Internal(anyhow::anyhow!(message))
45    }};
46    ($fmt:expr, $($arg:tt)*) => { bug_inner!(format_args!($fmt, $($arg)*)) };
47}
48
49macro_rules! bug {
50    () => {
51        |error| $crate::error::bug_inner!(error)
52    };
53
54    ($($msg:tt)*) => {{
55        |e| $crate::error::bug_inner!(format_args!("{}: {}", format_args!($($msg)*), e))
56    }};
57}
58
59pub(crate) use bug;
60pub(crate) use bug_inner;