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
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use bonsaidb_core::custom_api::CustomApiError;

/// Errors related to working with [`Client`](crate::Client)
#[derive(thiserror::Error, Debug)]
pub enum Error<ApiError: CustomApiError> {
    #[cfg(feature = "websockets")]
    /// An error occurred from the WebSocket transport layer.
    #[error("a transport error occurred: '{0}'")]
    WebSocket(crate::client::WebSocketError),

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

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

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

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

    /// An error from the custom API.
    #[error("api error: {0}")]
    Api(ApiError),

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

impl<T, ApiError: CustomApiError> From<flume::SendError<T>> for Error<ApiError> {
    fn from(_: flume::SendError<T>) -> Self {
        Self::Disconnected
    }
}

impl<ApiError: CustomApiError> From<flume::RecvError> for Error<ApiError> {
    fn from(_: flume::RecvError) -> Self {
        Self::Disconnected
    }
}

impl<ApiError: CustomApiError> From<Error<ApiError>> for bonsaidb_core::Error {
    fn from(other: Error<ApiError>) -> Self {
        match other {
            Error::Core(err) => err,
            other => Self::Client(other.to_string()),
        }
    }
}

#[cfg(feature = "websockets")]
impl<ApiError: CustomApiError> From<bincode::Error> for Error<ApiError> {
    fn from(other: bincode::Error) -> Self {
        Self::Core(bonsaidb_core::Error::Websocket(format!(
            "error decoding websocket message: {:?}",
            other
        )))
    }
}

#[cfg(not(target_arch = "wasm32"))]
mod fabruic_impls {
    macro_rules! impl_from_fabruic {
        ($error:ty) => {
            impl<ApiError: bonsaidb_core::custom_api::CustomApiError> From<$error>
                for $crate::Error<ApiError>
            {
                fn from(other: $error) -> Self {
                    Self::Core(bonsaidb_core::Error::Transport(other.to_string()))
                }
            }
        };
    }

    impl_from_fabruic!(fabruic::error::Sender);
    impl_from_fabruic!(fabruic::error::Receiver);
    impl_from_fabruic!(fabruic::error::Stream);
    impl_from_fabruic!(fabruic::error::Connecting);
    impl_from_fabruic!(fabruic::error::Connect);
}

#[cfg(feature = "websockets")]
impl<ApiError: CustomApiError> From<crate::client::WebSocketError> for Error<ApiError> {
    #[cfg(not(target_arch = "wasm32"))]
    fn from(err: crate::client::WebSocketError) -> Self {
        if let crate::client::WebSocketError::Http(response) = &err {
            if response.status() == 406 {
                return Self::ProtocolVersionMismatch;
            }
        }

        Self::WebSocket(err)
    }

    #[cfg(target_arch = "wasm32")]
    fn from(err: crate::client::WebSocketError) -> Self {
        Self::WebSocket(err)
    }
}