blob: 99936547817b1519e35be2813d35aba65cdf1c32 [file] [log] [blame]
use iggy::error::IggyError;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tracing::debug;
const STATUS_OK: &[u8] = &[0; 4];
pub(crate) async fn read<T>(stream: &mut T, buffer: &mut [u8]) -> Result<usize, IggyError>
where
T: AsyncRead + AsyncWrite + Unpin,
{
match stream.read_exact(buffer).await {
Ok(0) => Err(IggyError::ConnectionClosed),
Ok(read_bytes) => Ok(read_bytes),
Err(error) => {
if error.kind() == std::io::ErrorKind::UnexpectedEof {
Err(IggyError::ConnectionClosed)
} else {
Err(IggyError::TcpError)
}
}
}
}
pub(crate) async fn send_empty_ok_response<T>(stream: &mut T) -> Result<(), IggyError>
where
T: AsyncRead + AsyncWrite + Unpin,
{
send_ok_response(stream, &[]).await
}
pub(crate) async fn send_ok_response<T>(stream: &mut T, payload: &[u8]) -> Result<(), IggyError>
where
T: AsyncRead + AsyncWrite + Unpin,
{
send_response(stream, STATUS_OK, payload).await
}
pub(crate) async fn send_error_response<T>(
stream: &mut T,
error: IggyError,
) -> Result<(), IggyError>
where
T: AsyncRead + AsyncWrite + Unpin,
{
send_response(stream, &error.as_code().to_le_bytes(), &[]).await
}
pub(crate) async fn send_response<T>(
stream: &mut T,
status: &[u8],
payload: &[u8],
) -> Result<(), IggyError>
where
T: AsyncRead + AsyncWrite + Unpin,
{
debug!("Sending response with status: {:?}...", status);
let length = (payload.len() as u32).to_le_bytes();
stream
.write_all(&[status, &length, payload].as_slice().concat())
.await
.map_err(|_| IggyError::TcpError)?;
debug!("Sent response with status: {:?}", status);
Ok(())
}