1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use bytes::Bytes;
use http::uri::InvalidUri;
use snafu::{Location, Snafu};
use url::Url;

/// Errors that originate from this crate
#[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum Error {
    /// Encountered a `401 UNAUTHORIZED` http status code
    #[snafu(display("trying to perform an unauthorized request"))]
    Unauthorized,

    /// Encountered a non-success http status code that was not handled otherwise
    #[snafu(display("server returned a non-success http status code {status}"))]
    NonSuccessStatus {
        /// The returned status code.
        status: http::StatusCode,

        /// The data returned from the request
        data: Bytes,
    },

    /// An error occurred when building a HTTP request
    #[snafu(display("could not build http request: {source}"))]
    BuildRequest {
        /// The source http error
        source: http::Error,
    },

    /// Encountered a URL which cannot be a base where a base url was required
    #[snafu(display("base url {url} cannot be a base"))]
    UrlCannotBeABase {
        /// The url which cannot be a base
        url: Url,
    },

    /// Couldn't parse a HTTP URI
    #[snafu(display("couldn't parse uri"))]
    ParseUri {
        /// The source invalid uri error
        source: InvalidUri,
    },

    /// A query string couldn't be created from the given type
    #[snafu(display("can't create query string: {message}"))]
    QueryString {
        /// A message describing the reason for this error
        message: String,
    },

    /// Couldn't create a query from a given string
    #[cfg(feature = "serde")]
    #[snafu(display("couldn't build query string from serde url params"))]
    SerdeUrlParams {
        /// The source of the serde_url_params error
        source: serde_url_params::Error,
    },

    /// serde_json error
    #[cfg(feature = "serde")]
    #[snafu(display("serde json error"))]
    Json {
        /// The source of the serde_json error
        source: serde_json::Error,
    },

    /// custom error returned e.g. by a custom trait implementation in a different crate
    #[snafu(display("{message}"))]
    Custom {
        /// The custom error message
        message: String,

        /// The location where the error happened
        location: Location,
    },
}

impl Error {
    /// Create a custom error
    #[track_caller]
    pub fn custom(message: String) -> Self {
        let location = std::panic::Location::caller();

        Error::Custom {
            message,
            location: Location::new(location.file(), location.line(), location.column()),
        }
    }
}