use std::io;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use crate::async_api::TorusAsync;
fn to_io_err(e: crate::Error) -> io::Error {
match e {
crate::Error::Os(code) => io::Error::from_raw_os_error(code),
other => io::Error::other(other),
}
}
pub struct TorusAsyncReader {
torus: Arc<TorusAsync>,
fd: i32,
offset: u64,
scratch: Vec<u8>,
user_data: u64,
submitted: bool,
}
impl TorusAsyncReader {
pub fn new(torus: Arc<TorusAsync>, fd: i32) -> Self {
Self {
torus,
fd,
offset: 0,
scratch: Vec::new(),
user_data: 0,
submitted: false,
}
}
pub fn with_offset(torus: Arc<TorusAsync>, fd: i32, offset: u64) -> Self {
Self {
torus,
fd,
offset,
scratch: Vec::new(),
user_data: 0,
submitted: false,
}
}
}
impl AsyncRead for TorusAsyncReader {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
let this = self.get_mut();
let needed = buf.remaining();
if needed == 0 {
return Poll::Ready(Ok(()));
}
if this.scratch.len() < needed {
this.scratch.resize(needed, 0);
}
match this.torus.poll_read_op(
this.fd,
&mut this.scratch[..needed],
this.offset,
&mut this.user_data,
&mut this.submitted,
cx,
) {
Poll::Ready(Ok(bytes)) => {
buf.put_slice(&this.scratch[..bytes]);
this.offset += bytes as u64;
this.submitted = false;
Poll::Ready(Ok(()))
}
Poll::Ready(Err(e)) => Poll::Ready(Err(to_io_err(e))),
Poll::Pending => Poll::Pending,
}
}
}
pub struct TorusAsyncWriter {
torus: Arc<TorusAsync>,
fd: i32,
offset: u64,
user_data: u64,
submitted: bool,
}
impl TorusAsyncWriter {
pub fn new(torus: Arc<TorusAsync>, fd: i32) -> Self {
Self {
torus,
fd,
offset: 0,
user_data: 0,
submitted: false,
}
}
pub fn with_offset(torus: Arc<TorusAsync>, fd: i32, offset: u64) -> Self {
Self {
torus,
fd,
offset,
user_data: 0,
submitted: false,
}
}
}
impl AsyncWrite for TorusAsyncWriter {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
let this = self.get_mut();
match this.torus.poll_write_op(
this.fd,
buf,
this.offset,
&mut this.user_data,
&mut this.submitted,
cx,
) {
Poll::Ready(Ok(bytes)) => {
this.offset += bytes as u64;
this.submitted = false;
Poll::Ready(Ok(bytes))
}
Poll::Ready(Err(e)) => Poll::Ready(Err(to_io_err(e))),
Poll::Pending => Poll::Pending,
}
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
}