pub mod connection_drop;
pub mod read_small_buf;
pub mod tokio_io;
pub mod tokio_io_read_small_buf;
use xwt_core::prelude::*;
#[derive(Debug, thiserror::Error)]
pub enum EchoError<Endpoint>
where
Endpoint: xwt_core::EndpointConnect + std::fmt::Debug,
Endpoint::Connecting: std::fmt::Debug,
EndpointConnectConnectionFor<Endpoint>: xwt_core::OpenBiStream + std::fmt::Debug,
{
#[error("connect: {0}")]
Connect(#[source] xwt_error::Connect<Endpoint>),
#[error("open: {0}")]
Open(#[source] xwt_error::OpenBi<EndpointConnectConnectionFor<Endpoint>>),
#[error("send: {0}")]
Send(#[source] WriteErrorFor<SendStreamFor<EndpointConnectConnectionFor<Endpoint>>>),
#[error("recv: {0}")]
Recv(#[source] ReadErrorFor<RecvStreamFor<EndpointConnectConnectionFor<Endpoint>>>),
#[error("no response")]
NoResponse,
#[error("bad data")]
BadData(Vec<u8>),
}
pub async fn echo<Endpoint>(endpoint: Endpoint, url: &str) -> Result<(), EchoError<Endpoint>>
where
Endpoint: xwt_core::EndpointConnect + std::fmt::Debug,
Endpoint::Connecting: std::fmt::Debug,
EndpointConnectConnectionFor<Endpoint>: xwt_core::OpenBiStream + std::fmt::Debug,
{
let connection = crate::utils::connect(&endpoint, url)
.await
.map_err(EchoError::Connect)?;
let (mut send_stream, mut recv_stream) = crate::utils::open_bi(&connection)
.await
.map_err(EchoError::Open)?;
let mut to_write = &b"hello"[..];
loop {
let written = send_stream.write(to_write).await.map_err(EchoError::Send)?;
to_write = &to_write[written..];
if to_write.is_empty() {
break;
}
}
let mut read_buf = vec![0u8; 1024];
let Some(read) = recv_stream
.read(&mut read_buf[..])
.await
.map_err(EchoError::Recv)?
else {
return Err(EchoError::NoResponse);
};
read_buf.truncate(read);
if read_buf != b"hello" {
return Err(EchoError::BadData(read_buf));
}
Ok(())
}
#[derive(Debug, thiserror::Error)]
pub enum EchoChunksError<Endpoint, WriteChunk, ReadChunk>
where
Endpoint: xwt_core::EndpointConnect + std::fmt::Debug,
Endpoint::Connecting: std::fmt::Debug,
EndpointConnectConnectionFor<Endpoint>: xwt_core::OpenBiStream + std::fmt::Debug,
WriteChunk: xwt_core::WriteableChunk + std::fmt::Debug,
ReadChunk: xwt_core::ReadableChunk + std::fmt::Debug,
SendStreamFor<EndpointConnectConnectionFor<Endpoint>>: xwt_core::WriteChunk<WriteChunk>,
RecvStreamFor<EndpointConnectConnectionFor<Endpoint>>: xwt_core::ReadChunk<ReadChunk>,
{
#[error("connect: {0}")]
Connect(#[source] xwt_error::Connect<Endpoint>),
#[error("open: {0}")]
Open(#[source] xwt_error::OpenBi<EndpointConnectConnectionFor<Endpoint>>),
#[error("send: {0}")]
Send(
#[source]
WriteChunkErrorFor<SendStreamFor<EndpointConnectConnectionFor<Endpoint>>, WriteChunk>,
),
#[error("recv: {0}")]
Recv(
#[source]
ReadChunkErrorFor<RecvStreamFor<EndpointConnectConnectionFor<Endpoint>>, ReadChunk>,
),
#[error("no response")]
NoResponse,
#[error("bad data")]
BadData(Vec<u8>),
}
pub async fn echo_chunks<Endpoint, WriteChunk, ReadChunk>(
endpoint: Endpoint,
url: &str,
) -> Result<(), EchoChunksError<Endpoint, WriteChunk, ReadChunk>>
where
Endpoint: xwt_core::EndpointConnect + std::fmt::Debug,
Endpoint::Connecting: std::fmt::Debug,
EndpointConnectConnectionFor<Endpoint>: xwt_core::OpenBiStream + std::fmt::Debug,
WriteChunk: xwt_core::WriteableChunk + std::fmt::Debug,
ReadChunk: xwt_core::ReadableChunk + std::fmt::Debug,
<WriteChunk as xwt_core::WriteableChunk>::Data<'static>: From<&'static [u8]>,
for<'a> <ReadChunk as xwt_core::ReadableChunk>::Data<'a>: AsRef<[u8]>,
SendStreamFor<EndpointConnectConnectionFor<Endpoint>>: xwt_core::WriteChunk<WriteChunk>,
RecvStreamFor<EndpointConnectConnectionFor<Endpoint>>: xwt_core::ReadChunk<ReadChunk>,
{
let connection = crate::utils::connect(&endpoint, url)
.await
.map_err(EchoChunksError::Connect)?;
let (mut send_stream, mut recv_stream) = crate::utils::open_bi(&connection)
.await
.map_err(EchoChunksError::Open)?;
let write_data: WriteChunk::Data<'static> = (&b"hello"[..]).into();
send_stream
.write_chunk(write_data)
.await
.map_err(EchoChunksError::Send)?;
let maybe_read_chunk = recv_stream
.read_chunk(1024, false)
.await
.map_err(EchoChunksError::Recv)?;
let Some(read_chunk) = maybe_read_chunk else {
return Err(EchoChunksError::NoResponse);
};
let read_data = read_chunk.data.as_ref();
if read_data != b"hello" {
return Err(EchoChunksError::BadData(read_data.into()));
}
Ok(())
}
#[derive(Debug, thiserror::Error)]
pub enum EchoDatagrmsError<Endpoint>
where
Endpoint: xwt_core::EndpointConnect + std::fmt::Debug,
Endpoint::Connecting: std::fmt::Debug,
EndpointConnectConnectionFor<Endpoint>: xwt_core::datagram::Datagrams + std::fmt::Debug,
ReceiveDatagramFor<EndpointConnectConnectionFor<Endpoint>>: std::fmt::Debug,
{
#[error("connect: {0}")]
Connect(#[source] xwt_error::Connect<Endpoint>),
#[error("send: {0}")]
Send(#[source] SendErrorFor<EndpointConnectConnectionFor<Endpoint>>),
#[error("recv: {0}")]
Recv(#[source] ReceiveErrorFor<EndpointConnectConnectionFor<Endpoint>>),
#[error("bad data")]
BadData(ReceiveDatagramFor<EndpointConnectConnectionFor<Endpoint>>),
}
pub async fn echo_datagrams<Endpoint>(
endpoint: Endpoint,
url: &str,
) -> Result<(), EchoDatagrmsError<Endpoint>>
where
Endpoint: xwt_core::EndpointConnect + std::fmt::Debug,
Endpoint::Connecting: std::fmt::Debug,
EndpointConnectConnectionFor<Endpoint>: xwt_core::datagram::Datagrams + std::fmt::Debug,
ReceiveDatagramFor<EndpointConnectConnectionFor<Endpoint>>: std::fmt::Debug,
{
let connection = crate::utils::connect(&endpoint, url)
.await
.map_err(EchoDatagrmsError::Connect)?;
connection
.send_datagram(&b"hello"[..])
.await
.map_err(EchoDatagrmsError::Send)?;
let read = connection
.receive_datagram()
.await
.map_err(EchoDatagrmsError::Recv)?;
if read.as_ref() != b"hello" {
return Err(EchoDatagrmsError::BadData(read));
}
Ok(())
}