use core::future::{Future, poll_fn};
use core::pin::Pin;
use bytes::Bytes;
use futures_core03::Stream;
use futures_sink03::Sink;
use tokio::net::TcpStream;
use tokio_tungstenite029::tungstenite::Error;
use tokio_tungstenite029::tungstenite::protocol::Message as WsMessage;
use tokio_tungstenite029::{MaybeTlsStream, WebSocketStream, connect_async};
use crate::client::{ClientImpl, EmptyCallback, Message, ServiceBuilder, SocketImpl};
#[doc(hidden)]
pub type Socket = WebSocketStream<MaybeTlsStream<TcpStream>>;
pub mod prelude {
pub mod ws {
pub use crate::api::ChannelId;
pub use crate::client::{
Channel, EmptyCallback, Error, Handle, Listener, Packet, RawPacket, RequestBuilder,
State, StateListener,
};
use crate::tungstenite029::Tungstenite029Impl;
#[inline]
pub fn connect(url: impl AsRef<str>) -> ServiceBuilder<EmptyCallback> {
crate::tungstenite029::connect(url)
}
pub type Service = crate::client::Service<Tungstenite029Impl>;
pub type ServiceBuilder<C> = crate::client::ServiceBuilder<Tungstenite029Impl, C>;
}
}
#[derive(Clone, Copy)]
pub enum Tungstenite029Impl {}
#[inline]
pub fn connect(url: impl AsRef<str>) -> ServiceBuilder<Tungstenite029Impl, EmptyCallback> {
crate::client::connect(url)
}
impl crate::client::sealed_client::Sealed for Tungstenite029Impl {}
impl ClientImpl for Tungstenite029Impl {
type Error = Error;
type Socket = Socket;
#[inline]
async fn connect(url: &str) -> Result<Self::Socket, Self::Error> {
let (socket, _) = connect_async(url).await?;
Ok(socket)
}
}
impl crate::client::sealed_socket::Sealed for Socket {}
impl SocketImpl for Socket {
type Error = Error;
#[inline]
fn recv(&mut self) -> impl Future<Output = Option<Result<Message, Self::Error>>> + Send + '_ {
poll_fn(move |cx| {
Pin::new(&mut *self)
.poll_next(cx)
.map(|message| message.map(|message| message.map(convert)))
})
}
#[inline]
fn send(&mut self, data: &[u8]) -> impl Future<Output = Result<(), Self::Error>> + Send + '_ {
let message = WsMessage::Binary(Bytes::copy_from_slice(data));
async move {
poll_fn(|cx| Pin::new(&mut *self).poll_ready(cx)).await?;
Pin::new(&mut *self).start_send(message)?;
poll_fn(|cx| Pin::new(&mut *self).poll_flush(cx)).await
}
}
#[inline]
fn close(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send + '_ {
poll_fn(move |cx| Pin::new(&mut *self).poll_close(cx))
}
}
#[inline]
fn convert(message: WsMessage) -> Message {
match message {
WsMessage::Binary(data) => Message::Binary(data),
WsMessage::Ping(..) => Message::Ping,
WsMessage::Pong(..) => Message::Pong,
WsMessage::Close(..) => Message::Close,
WsMessage::Text(..) | WsMessage::Frame(..) => Message::Text,
}
}