use async_trait::async_trait;
use derive_more::Display;
use futures::stream::LocalBoxStream;
use medea_client_api_proto::{ClientMsg, ServerMsg};
use tracerr::Traced;
use crate::{
platform,
rpc::{ApiUrl, ClientDisconnect, CloseMsg},
utils::{Caused, JsonParseError},
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TransportState {
Connecting,
Open,
Closing,
Closed(CloseMsg),
}
impl TransportState {
#[must_use]
pub const fn can_close(self) -> bool {
matches!(self, Self::Connecting | Self::Open)
}
}
#[allow(unused_lifetimes)]
#[async_trait(?Send)]
#[cfg_attr(feature = "mockable", mockall::automock)]
#[cfg_attr(feature = "mockable", allow(clippy::missing_docs_in_private_items))]
pub trait RpcTransport {
async fn connect(&self, url: ApiUrl) -> Result<(), Traced<TransportError>>;
fn on_message(&self) -> LocalBoxStream<'static, ServerMsg>;
fn set_close_reason(&self, reason: ClientDisconnect);
fn send(&self, msg: &ClientMsg) -> Result<(), Traced<TransportError>>;
fn on_state_change(&self) -> LocalBoxStream<'static, TransportState>;
}
#[derive(Caused, Clone, Debug, Display, PartialEq)]
#[cause(error = platform::Error)]
pub enum TransportError {
#[display(fmt = "Failed to create WebSocket: {}", _0)]
CreateSocket(platform::Error),
#[display(fmt = "Failed to init WebSocket")]
InitSocket,
#[display(fmt = "Failed to parse client message: {}", _0)]
SerializeClientMessage(JsonParseError),
#[display(fmt = "Failed to parse server message: {}", _0)]
ParseServerMessage(JsonParseError),
#[display(fmt = "Message is not a string")]
MessageNotString,
#[display(fmt = "Failed to send message: {}", _0)]
SendMessage(platform::Error),
#[display(fmt = "Underlying socket is closed")]
ClosedSocket,
}