use bonsaidb_core::api::Infallible;
use bonsaidb_core::arc_bytes::serde::Bytes;
use bonsaidb_core::networking;
use bonsaidb_core::schema::Name;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[cfg(feature = "websockets")]
#[error("a transport error occurred: '{0}'")]
WebSocket(crate::client::WebSocketError),
#[error("a networking error occurred: '{0}'")]
Network(#[from] bonsaidb_core::networking::Error),
#[error("invalid url: '{0}'")]
InvalidUrl(String),
#[error("{0}")]
Core(#[from] bonsaidb_core::Error),
#[error("api {name} error")]
Api {
name: Name,
error: Bytes,
},
#[error("server incompatible with client protocol version")]
ProtocolVersionMismatch,
}
impl Error {
pub(crate) fn disconnected() -> Self {
Self::Core(bonsaidb_core::Error::Networking(
networking::Error::Disconnected,
))
}
pub(crate) fn request_timeout() -> Self {
Self::Core(bonsaidb_core::Error::Networking(
networking::Error::RequestTimeout,
))
}
pub(crate) fn connect_timeout() -> Self {
Self::Core(bonsaidb_core::Error::Networking(
networking::Error::ConnectTimeout,
))
}
}
impl<T> From<flume::SendError<T>> for Error {
fn from(_: flume::SendError<T>) -> Self {
Self::disconnected()
}
}
impl From<flume::RecvTimeoutError> for Error {
fn from(err: flume::RecvTimeoutError) -> Self {
match err {
flume::RecvTimeoutError::Timeout => Self::request_timeout(),
flume::RecvTimeoutError::Disconnected => Self::disconnected(),
}
}
}
impl From<flume::RecvError> for Error {
fn from(_: flume::RecvError) -> Self {
Self::disconnected()
}
}
impl From<Error> for bonsaidb_core::Error {
fn from(other: Error) -> Self {
match other {
Error::Core(err) => err,
other => Self::other("bonsaidb-client", other),
}
}
}
#[cfg(feature = "websockets")]
impl From<bincode::Error> for Error {
fn from(other: bincode::Error) -> Self {
Self::Core(bonsaidb_core::Error::other("bincode", other))
}
}
#[cfg(not(target_arch = "wasm32"))]
mod fabruic_impls {
macro_rules! impl_from_fabruic {
($error:ty) => {
impl From<$error> for $crate::Error {
fn from(other: $error) -> Self {
Self::Core(bonsaidb_core::Error::other("quic", other))
}
}
};
}
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 From<crate::client::WebSocketError> for Error {
#[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)
}
}
impl From<pot::Error> for Error {
fn from(err: pot::Error) -> Self {
Self::from(bonsaidb_core::Error::from(err))
}
}
#[derive(thiserror::Error, Debug)]
pub enum ApiError<T> {
#[error("api error: {0}")]
Api(T),
#[error("client error: {0}")]
Client(#[from] Error),
}
impl From<ApiError<Self>> for bonsaidb_core::Error {
fn from(error: ApiError<Self>) -> Self {
match error {
ApiError::Api(err) => err,
ApiError::Client(err) => Self::from(err),
}
}
}
impl From<ApiError<Infallible>> for Error {
fn from(err: ApiError<Infallible>) -> Self {
match err {
ApiError::Client(err) => err,
ApiError::Api(_) => unreachable!("infallible"),
}
}
}