1use thiserror::Error;
9
10pub type Result<T, E = Error> = std::result::Result<T, E>;
12
13#[derive(Debug, Error)]
15pub enum Error {
16 #[error("{0}")]
18 Msg(String),
19
20 #[error("{context}: {inner}")]
23 WithContext {
24 context: String,
26 inner: Box<dyn std::error::Error + Send + Sync + 'static>,
28 },
29
30 #[error(transparent)]
32 Io(#[from] std::io::Error),
33
34 #[error(transparent)]
36 Reqwest(#[from] reqwest::Error),
37
38 #[error(transparent)]
40 Json(#[from] serde_json::Error),
41
42 #[error(transparent)]
44 Archive(#[from] easy_archive::ArchiveError),
45
46 #[error(transparent)]
48 ParseInt(#[from] std::num::ParseIntError),
49
50 #[error(transparent)]
52 Join(#[from] tokio::task::JoinError),
53}
54
55impl Error {
56 pub fn msg(message: impl Into<String>) -> Self {
58 Error::Msg(message.into())
59 }
60}
61
62pub trait Context<T> {
64 fn context(self, context: impl std::fmt::Display) -> Result<T>;
66
67 fn with_context<F, D>(self, f: F) -> Result<T>
69 where
70 F: FnOnce() -> D,
71 D: std::fmt::Display;
72}
73
74impl<T, E> Context<T> for std::result::Result<T, E>
75where
76 E: std::error::Error + Send + Sync + 'static,
77{
78 fn context(self, context: impl std::fmt::Display) -> Result<T> {
79 self.map_err(|e| Error::WithContext {
80 context: context.to_string(),
81 inner: Box::new(e),
82 })
83 }
84
85 fn with_context<F, D>(self, f: F) -> Result<T>
86 where
87 F: FnOnce() -> D,
88 D: std::fmt::Display,
89 {
90 self.map_err(|e| Error::WithContext {
91 context: f().to_string(),
92 inner: Box::new(e),
93 })
94 }
95}
96
97impl<T> Context<T> for Option<T> {
98 fn context(self, context: impl std::fmt::Display) -> Result<T> {
99 self.ok_or_else(|| Error::msg(context.to_string()))
100 }
101
102 fn with_context<F, D>(self, f: F) -> Result<T>
103 where
104 F: FnOnce() -> D,
105 D: std::fmt::Display,
106 {
107 self.ok_or_else(|| Error::msg(f().to_string()))
108 }
109}
110
111macro_rules! err {
113 ($($arg:tt)*) => {
114 $crate::error::Error::msg(format!($($arg)*))
115 };
116}
117
118macro_rules! bail {
120 ($($arg:tt)*) => {
121 return Err($crate::error::Error::msg(format!($($arg)*)))
122 };
123}
124
125pub(crate) use bail;
126pub(crate) use err;