1use futures::future::LocalBoxFuture;
2use futures::FutureExt;
3use serde::Serialize;
4use std::collections::HashMap;
5use std::io;
6
7use crate::ErrorResponse;
8
9pub trait ErrorExt<T> {
10 fn or_err(self, s: impl ToString) -> Result<T, Error>;
11}
12
13impl<T> ErrorExt<T> for Option<T> {
14 fn or_err(self, s: impl ToString) -> Result<T, Error> {
15 match self {
16 Some(t) => Ok(t),
17 None => Err(Error::from(s.to_string())),
18 }
19 }
20}
21
22impl<T, E> ErrorExt<T> for Result<T, E>
23where
24 E: Into<Error> + std::fmt::Display,
25{
26 fn or_err(self, s: impl ToString) -> Result<T, Error> {
27 match self {
28 Ok(t) => Ok(t),
29 Err(e) => Err(Error::from(format!("{}: {}", s.to_string(), e))),
30 }
31 }
32}
33
34#[derive(Clone, Debug, Serialize)]
35pub struct Error {
36 code: i32,
37 message: String,
38 context: HashMap<String, String>,
39}
40
41impl Error {
42 pub fn response<'a, T: 'a>(s: impl ToString) -> LocalBoxFuture<'a, Result<T, Self>> {
43 let err = Self::from(s.to_string());
44 futures::future::err(err).boxed_local()
45 }
46
47 pub fn from_string(s: impl ToString) -> Self {
48 Self::from(s.to_string())
49 }
50}
51
52impl From<String> for Error {
53 fn from(message: String) -> Self {
54 Error {
55 code: 1,
56 message,
57 context: Default::default(),
58 }
59 }
60}
61
62impl From<io::Error> for Error {
63 fn from(e: io::Error) -> Self {
64 Error {
65 code: e.raw_os_error().unwrap_or(1),
66 message: e.to_string(),
67 context: Default::default(),
68 }
69 }
70}
71
72impl From<anyhow::Error> for Error {
73 fn from(e: anyhow::Error) -> Self {
74 Self::from_string(e)
75 }
76}
77
78impl From<ErrorResponse> for Error {
79 fn from(e: ErrorResponse) -> Self {
80 Error {
81 code: e.code,
82 message: e.message,
83 context: e.context,
84 }
85 }
86}
87
88impl From<Error> for ErrorResponse {
89 fn from(e: Error) -> Self {
90 ErrorResponse {
91 code: e.code,
92 message: e.message,
93 context: e.context,
94 }
95 }
96}
97
98impl std::error::Error for Error {}
99
100impl std::fmt::Display for Error {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{} (code: {})", self.message, self.code)
103 }
104}