2022-07-22 10:45:38 +00:00
|
|
|
use std::pin::Pin;
|
|
|
|
use std::task::{Context, Poll};
|
|
|
|
|
|
|
|
use bytes::Bytes;
|
|
|
|
|
|
|
|
use futures::Future;
|
2022-09-01 09:21:24 +00:00
|
|
|
use futures::{Stream, StreamExt};
|
2022-07-22 14:42:26 +00:00
|
|
|
use tokio::io::AsyncRead;
|
2022-07-22 10:45:38 +00:00
|
|
|
|
2022-09-01 08:29:26 +00:00
|
|
|
use crate::bytes_buf::BytesBuf;
|
|
|
|
|
2022-07-22 10:45:38 +00:00
|
|
|
/// A stream of associated data.
|
|
|
|
///
|
|
|
|
/// When sent through Netapp, the Vec may be split in smaller chunk in such a way
|
|
|
|
/// consecutive Vec may get merged, but Vec and error code may not be reordered
|
|
|
|
///
|
|
|
|
/// Error code 255 means the stream was cut before its end. Other codes have no predefined
|
|
|
|
/// meaning, it's up to your application to define their semantic.
|
|
|
|
pub type ByteStream = Pin<Box<dyn Stream<Item = Packet> + Send + Sync>>;
|
|
|
|
|
2022-09-01 09:21:24 +00:00
|
|
|
pub type Packet = Result<Bytes, std::io::Error>;
|
2022-07-22 10:45:38 +00:00
|
|
|
|
2022-07-22 14:42:26 +00:00
|
|
|
// ----
|
|
|
|
|
2022-07-22 10:45:38 +00:00
|
|
|
pub struct ByteStreamReader {
|
|
|
|
stream: ByteStream,
|
2022-09-01 08:29:26 +00:00
|
|
|
buf: BytesBuf,
|
2022-07-22 10:45:38 +00:00
|
|
|
eos: bool,
|
2022-09-01 09:21:24 +00:00
|
|
|
err: Option<std::io::Error>,
|
2022-07-22 10:45:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ByteStreamReader {
|
|
|
|
pub fn new(stream: ByteStream) -> Self {
|
|
|
|
ByteStreamReader {
|
|
|
|
stream,
|
2022-09-01 08:29:26 +00:00
|
|
|
buf: BytesBuf::new(),
|
2022-07-22 10:45:38 +00:00
|
|
|
eos: false,
|
|
|
|
err: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn read_exact(&mut self, read_len: usize) -> ByteStreamReadExact<'_> {
|
|
|
|
ByteStreamReadExact {
|
|
|
|
reader: self,
|
|
|
|
read_len,
|
|
|
|
fail_on_eos: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn read_exact_or_eos(&mut self, read_len: usize) -> ByteStreamReadExact<'_> {
|
|
|
|
ByteStreamReadExact {
|
|
|
|
reader: self,
|
|
|
|
read_len,
|
|
|
|
fail_on_eos: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn read_u8(&mut self) -> Result<u8, ReadExactError> {
|
|
|
|
Ok(self.read_exact(1).await?[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn read_u16(&mut self) -> Result<u16, ReadExactError> {
|
|
|
|
let bytes = self.read_exact(2).await?;
|
|
|
|
let mut b = [0u8; 2];
|
|
|
|
b.copy_from_slice(&bytes[..]);
|
|
|
|
Ok(u16::from_be_bytes(b))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn read_u32(&mut self) -> Result<u32, ReadExactError> {
|
|
|
|
let bytes = self.read_exact(4).await?;
|
|
|
|
let mut b = [0u8; 4];
|
|
|
|
b.copy_from_slice(&bytes[..]);
|
|
|
|
Ok(u32::from_be_bytes(b))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_stream(self) -> ByteStream {
|
2022-09-01 08:29:26 +00:00
|
|
|
let buf_stream = futures::stream::iter(self.buf.into_slices().into_iter().map(Ok));
|
2022-07-22 10:45:38 +00:00
|
|
|
if let Some(err) = self.err {
|
|
|
|
Box::pin(buf_stream.chain(futures::stream::once(async move { Err(err) })))
|
|
|
|
} else if self.eos {
|
|
|
|
Box::pin(buf_stream)
|
|
|
|
} else {
|
|
|
|
Box::pin(buf_stream.chain(self.stream))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-22 11:23:42 +00:00
|
|
|
pub fn take_buffer(&mut self) -> Bytes {
|
2022-09-01 08:29:26 +00:00
|
|
|
self.buf.take_all()
|
2022-07-22 11:23:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn eos(&self) -> bool {
|
2022-09-01 08:29:26 +00:00
|
|
|
self.buf.is_empty() && self.eos
|
2022-07-22 11:23:42 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 10:45:38 +00:00
|
|
|
fn try_get(&mut self, read_len: usize) -> Option<Bytes> {
|
2022-09-01 08:29:26 +00:00
|
|
|
self.buf.take_exact(read_len)
|
2022-07-22 10:45:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum ReadExactError {
|
|
|
|
UnexpectedEos,
|
2022-09-01 09:21:24 +00:00
|
|
|
Stream(std::io::Error),
|
2022-07-22 10:45:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[pin_project::pin_project]
|
|
|
|
pub struct ByteStreamReadExact<'a> {
|
|
|
|
#[pin]
|
|
|
|
reader: &'a mut ByteStreamReader,
|
|
|
|
read_len: usize,
|
|
|
|
fail_on_eos: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Future for ByteStreamReadExact<'a> {
|
|
|
|
type Output = Result<Bytes, ReadExactError>;
|
|
|
|
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<Bytes, ReadExactError>> {
|
|
|
|
let mut this = self.project();
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if let Some(bytes) = this.reader.try_get(*this.read_len) {
|
|
|
|
return Poll::Ready(Ok(bytes));
|
|
|
|
}
|
2022-09-01 09:21:24 +00:00
|
|
|
if let Some(err) = &this.reader.err {
|
|
|
|
let err = std::io::Error::new(err.kind(), format!("{}", err));
|
2022-07-22 10:45:38 +00:00
|
|
|
return Poll::Ready(Err(ReadExactError::Stream(err)));
|
|
|
|
}
|
|
|
|
if this.reader.eos {
|
|
|
|
if *this.fail_on_eos {
|
|
|
|
return Poll::Ready(Err(ReadExactError::UnexpectedEos));
|
|
|
|
} else {
|
2022-07-22 11:23:42 +00:00
|
|
|
return Poll::Ready(Ok(this.reader.take_buffer()));
|
2022-07-22 10:45:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match futures::ready!(this.reader.stream.as_mut().poll_next(cx)) {
|
|
|
|
Some(Ok(slice)) => {
|
2022-09-01 08:29:26 +00:00
|
|
|
this.reader.buf.extend(slice);
|
2022-07-22 10:45:38 +00:00
|
|
|
}
|
|
|
|
Some(Err(e)) => {
|
|
|
|
this.reader.err = Some(e);
|
|
|
|
this.reader.eos = true;
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
this.reader.eos = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-22 14:42:26 +00:00
|
|
|
|
|
|
|
// ----
|
|
|
|
|
2022-09-01 09:21:24 +00:00
|
|
|
/*
|
2022-07-22 14:42:26 +00:00
|
|
|
fn u8_to_io_error(v: u8) -> std::io::Error {
|
|
|
|
use std::io::{Error, ErrorKind};
|
|
|
|
let kind = match v {
|
|
|
|
101 => ErrorKind::ConnectionAborted,
|
|
|
|
102 => ErrorKind::BrokenPipe,
|
|
|
|
103 => ErrorKind::WouldBlock,
|
|
|
|
104 => ErrorKind::InvalidInput,
|
|
|
|
105 => ErrorKind::InvalidData,
|
|
|
|
106 => ErrorKind::TimedOut,
|
|
|
|
107 => ErrorKind::Interrupted,
|
|
|
|
108 => ErrorKind::UnexpectedEof,
|
|
|
|
109 => ErrorKind::OutOfMemory,
|
|
|
|
110 => ErrorKind::ConnectionReset,
|
|
|
|
_ => ErrorKind::Other,
|
|
|
|
};
|
|
|
|
Error::new(kind, "(in netapp stream)")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn io_error_to_u8(e: std::io::Error) -> u8 {
|
2022-07-25 09:07:23 +00:00
|
|
|
use std::io::ErrorKind;
|
2022-07-22 14:42:26 +00:00
|
|
|
match e.kind() {
|
|
|
|
ErrorKind::ConnectionAborted => 101,
|
|
|
|
ErrorKind::BrokenPipe => 102,
|
|
|
|
ErrorKind::WouldBlock => 103,
|
|
|
|
ErrorKind::InvalidInput => 104,
|
|
|
|
ErrorKind::InvalidData => 105,
|
|
|
|
ErrorKind::TimedOut => 106,
|
|
|
|
ErrorKind::Interrupted => 107,
|
|
|
|
ErrorKind::UnexpectedEof => 108,
|
|
|
|
ErrorKind::OutOfMemory => 109,
|
|
|
|
ErrorKind::ConnectionReset => 110,
|
|
|
|
_ => 100,
|
|
|
|
}
|
|
|
|
}
|
2022-09-01 09:21:24 +00:00
|
|
|
*/
|
2022-07-22 14:42:26 +00:00
|
|
|
|
|
|
|
pub fn asyncread_stream<R: AsyncRead + Send + Sync + 'static>(reader: R) -> ByteStream {
|
2022-09-01 09:21:24 +00:00
|
|
|
Box::pin(tokio_util::io::ReaderStream::new(reader))
|
2022-07-22 14:42:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stream_asyncread(stream: ByteStream) -> impl AsyncRead + Send + Sync + 'static {
|
2022-09-01 09:21:24 +00:00
|
|
|
tokio_util::io::StreamReader::new(stream)
|
2022-07-22 14:42:26 +00:00
|
|
|
}
|