1
use bonsaidb_core::{arc_bytes::serde::Bytes, schema::Name};
2

            
3
/// Errors related to working with [`Client`](crate::Client)
4
76
#[derive(thiserror::Error, Debug)]
5
pub enum Error {
6
    #[cfg(feature = "websockets")]
7
    /// An error occurred from the WebSocket transport layer.
8
    #[error("a transport error occurred: '{0}'")]
9
    WebSocket(crate::client::WebSocketError),
10

            
11
    /// An error occurred from networking.
12
    #[error("a networking error occurred: '{0}'")]
13
    Network(#[from] bonsaidb_core::networking::Error),
14

            
15
    /// An invalid Url was provided.
16
    #[error("invalid url: '{0}'")]
17
    InvalidUrl(String),
18

            
19
    /// The connection was interrupted.
20
    #[error("unexpected disconnection")]
21
    Disconnected,
22

            
23
    /// The connection was interrupted.
24
    #[error("unexpected disconnection")]
25
    Core(#[from] bonsaidb_core::Error),
26

            
27
    /// An error from a `Api`. The actual error is still serialized, as it
28
    /// could be any type.
29
    #[error("api {name} error")]
30
    Api {
31
        /// The unique name of the api that responded with an error
32
        name: Name,
33
        /// The serialized bytes of the error type.
34
        error: Bytes,
35
    },
36

            
37
    /// The server is incompatible with this version of the client.
38
    #[error("server incompatible with client protocol version")]
39
    ProtocolVersionMismatch,
40
}
41

            
42
impl<T> From<flume::SendError<T>> for Error {
43
    fn from(_: flume::SendError<T>) -> Self {
44
        Self::Disconnected
45
    }
46
}
47

            
48
impl From<flume::RecvError> for Error {
49
    fn from(_: flume::RecvError) -> Self {
50
        Self::Disconnected
51
    }
52
}
53

            
54
impl From<Error> for bonsaidb_core::Error {
55
10545
    fn from(other: Error) -> Self {
56
10545
        match other {
57
10507
            Error::Core(err) => err,
58
38
            other => Self::Client(other.to_string()),
59
        }
60
10545
    }
61
}
62

            
63
#[cfg(feature = "websockets")]
64
impl From<bincode::Error> for Error {
65
    fn from(other: bincode::Error) -> Self {
66
        Self::Core(bonsaidb_core::Error::Websocket(format!(
67
            "error decoding websocket message: {:?}",
68
            other
69
        )))
70
    }
71
}
72

            
73
#[cfg(not(target_arch = "wasm32"))]
74
mod fabruic_impls {
75
    macro_rules! impl_from_fabruic {
76
        ($error:ty) => {
77
            impl From<$error> for $crate::Error {
78
266
                fn from(other: $error) -> Self {
79
266
                    Self::Core(bonsaidb_core::Error::Transport(other.to_string()))
80
266
                }
81
            }
82
        };
83
    }
84

            
85
    impl_from_fabruic!(fabruic::error::Sender);
86
    impl_from_fabruic!(fabruic::error::Receiver);
87
    impl_from_fabruic!(fabruic::error::Stream);
88
    impl_from_fabruic!(fabruic::error::Connecting);
89
    impl_from_fabruic!(fabruic::error::Connect);
90
}
91

            
92
#[cfg(feature = "websockets")]
93
impl From<crate::client::WebSocketError> for Error {
94
    #[cfg(not(target_arch = "wasm32"))]
95
    fn from(err: crate::client::WebSocketError) -> Self {
96
57
        if let crate::client::WebSocketError::Http(response) = &err {
97
19
            if response.status() == 406 {
98
19
                return Self::ProtocolVersionMismatch;
99
            }
100
38
        }
101

            
102
38
        Self::WebSocket(err)
103
57
    }
104

            
105
    #[cfg(target_arch = "wasm32")]
106
    fn from(err: crate::client::WebSocketError) -> Self {
107
        Self::WebSocket(err)
108
    }
109
}
110

            
111
impl From<pot::Error> for Error {
112
    fn from(err: pot::Error) -> Self {
113
        Self::from(bonsaidb_core::Error::from(err))
114
    }
115
}
116

            
117
/// An error returned from an api request.
118
#[derive(thiserror::Error, Debug)]
119
pub enum ApiError<T> {
120
    /// The API returned its own error type.
121
    #[error("api error: {0}")]
122
    Api(T),
123
    /// An error from BonsaiDb occurred.
124
    #[error("client error: {0}")]
125
    Client(#[from] Error),
126
}
127

            
128
impl From<ApiError<Self>> for bonsaidb_core::Error {
129
10545
    fn from(error: ApiError<Self>) -> Self {
130
10545
        match error {
131
            ApiError::Api(err) => err,
132
10545
            ApiError::Client(err) => Self::from(err),
133
        }
134
10545
    }
135
}