use std::io;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll};
use futures_core::Stream;
use minarrow::{Field, SuperTable, Table, Vec64};
use tokio::net::TcpListener;
use crate::enums::{BufferChunkSize, IPCMessageProtocol};
use crate::models::readers::ipc::table::TableReader;
use crate::models::decoders::limits::DecodeLimits;
use crate::models::streams::websocket::{WsRead, WsWrite};
use crate::models::transports::websocket::WebSocketTransport;
use crate::traits::transport_reader::IPCTransportReader;
pub struct WebSocketTableReader {
inner: TableReader<Vec64<u8>>,
}
impl WebSocketTableReader {
pub async fn connect(url: &str, limits: Option<DecodeLimits>) -> io::Result<Self> {
let (read_half, write_half) = WebSocketTransport::connect(url).await?;
let (shared_writer, _ws_write) = WsWrite::new_client(write_half);
let ws_read = WsRead::new_client(read_half, shared_writer);
let inner = TableReader::<Vec64<u8>>::new(
ws_read,
BufferChunkSize::WebSocket.chunk_size(),
IPCMessageProtocol::Stream,
limits,
);
Ok(Self { inner })
}
pub async fn accept(
listener: &TcpListener,
limits: Option<DecodeLimits>,
) -> io::Result<Self> {
let (read_half, write_half) = WebSocketTransport::accept(listener).await?;
Ok(Self::from_halves(
read_half,
write_half,
IPCMessageProtocol::Stream,
limits,
))
}
pub fn from_raw_stream(
stream: impl tokio::io::AsyncRead + Unpin + Send + 'static,
protocol: IPCMessageProtocol,
limits: Option<DecodeLimits>,
) -> Self {
let shared_writer = Arc::new(Mutex::new(tokio::io::sink()));
let ws_read = WsRead::new(stream, shared_writer);
let inner = TableReader::<Vec64<u8>>::new(
ws_read,
BufferChunkSize::WebSocket.chunk_size(),
protocol,
limits,
);
Self { inner }
}
pub fn from_halves<R, W>(
read_half: R,
write_half: W,
protocol: IPCMessageProtocol,
limits: Option<DecodeLimits>,
) -> Self
where
R: tokio::io::AsyncRead + Unpin + Send + 'static,
W: tokio::io::AsyncWrite + Unpin + Send + 'static,
{
let (shared_writer, _ws_write) = WsWrite::new(write_half);
let ws_read = WsRead::new(read_half, shared_writer);
let inner = TableReader::<Vec64<u8>>::new(
ws_read,
BufferChunkSize::WebSocket.chunk_size(),
protocol,
limits,
);
Self { inner }
}
pub fn from_client_halves<R, W>(
read_half: R,
write_half: W,
protocol: IPCMessageProtocol,
limits: Option<DecodeLimits>,
) -> Self
where
R: tokio::io::AsyncRead + Unpin + Send + 'static,
W: tokio::io::AsyncWrite + Unpin + Send + 'static,
{
let (shared_writer, _ws_write) = WsWrite::new_client(write_half);
let ws_read = WsRead::new_client(read_half, shared_writer);
let inner = TableReader::<Vec64<u8>>::new(
ws_read,
BufferChunkSize::WebSocket.chunk_size(),
protocol,
limits,
);
Self { inner }
}
#[cfg(feature = "tls")]
pub async fn connect_tls(
url: &str,
config: std::sync::Arc<tokio_rustls::rustls::ClientConfig>,
limits: Option<DecodeLimits>,
) -> io::Result<Self> {
let (read_half, write_half) = WebSocketTransport::connect_tls(url, config).await?;
Ok(Self::from_client_halves(
read_half,
write_half,
IPCMessageProtocol::Stream,
limits,
))
}
}
impl IPCTransportReader for WebSocketTableReader {
async fn read_all_tables(self) -> io::Result<Vec<Table>> {
self.inner.read_all_tables().await
}
async fn read_tables(self, n: Option<usize>) -> io::Result<Vec<Table>> {
self.inner.read_tables(n).await
}
async fn read_to_super_table(
self,
name: Option<String>,
n: Option<usize>,
) -> io::Result<SuperTable> {
self.inner.read_to_super_table(name, n).await
}
async fn combine_to_table(self, name: Option<String>) -> io::Result<Table> {
self.inner.combine_to_table(name).await
}
fn schema(&self) -> Option<&[Field]> {
self.inner.schema()
}
async fn read_next(&mut self) -> io::Result<Option<Table>> {
self.inner.read_next().await
}
}
impl Stream for WebSocketTableReader {
type Item = io::Result<Table>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let me = self.get_mut();
Pin::new(&mut me.inner).poll_next(cx)
}
}