Skip to content

Commit

Permalink
Major update
Browse files Browse the repository at this point in the history
  • Loading branch information
vi committed Mar 8, 2021
1 parent affd301 commit 85a95df
Show file tree
Hide file tree
Showing 2 changed files with 237 additions and 49 deletions.
14 changes: 9 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
[package]
name = "readwrite"
version = "0.1.2"
version = "0.2.0"
authors = ["Vitaly \"_Vi\" Shukela <vi0oss@gmail.com>"]
license = "MIT/Apache-2.0"
repository = "https://github.com/vi/readwrite"
description = "Combine Read and Write into a single Read+Write object"
readme = "README.md"
categories = []
keywords = ["read","write","combine","socket"]
edition="2018"

[dependencies]
tokio-io = {version = "0.1", optional = true }
futures = {version = "0.1", optional = true }
tokio_dep = {version = "1", optional = true, package="tokio" }
futures = {version = "0.3", optional = true }
pin-project-lite = { version = "0.2.6", optional = true }

[features]
tokio = ["tokio-io","futures"]
default = []
tokio = ["tokio_dep", "pin-project-lite"]
asyncstd = ["futures", "pin-project-lite"]

[package.metadata.docs.rs]
features = [ "tokio" ]
features = [ "tokio", "asyncstd" ]

272 changes: 228 additions & 44 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,99 +59,283 @@ impl<R: Read, W: Write> ReadWrite<R, W> {
}

impl<R: Read, W: Write> Read for ReadWrite<R, W> {
fn read(&mut self, buf:&mut [u8]) -> Result<usize> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.0.read(buf)
}

fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> Result<usize> {
self.0.read_vectored(bufs)
}
}
impl<R: Read, W: Write> Write for ReadWrite<R, W> {
fn write(&mut self, buf:&[u8]) -> Result<usize> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.1.write(buf)
}
fn flush(&mut self,) -> Result<()> {
fn flush(&mut self) -> Result<()> {
self.1.flush()
}

fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> Result<usize> {
self.1.write_vectored(bufs)
}
}

#[cfg(all(feature="tokio-io",feature="futures"))]
mod async {
use std::io::{Read, Result, Write,Error};
extern crate tokio_io;
extern crate futures;
use self::tokio_io::{AsyncRead,AsyncWrite};

/// Combined async reader and writer.
/// Note that this struct is only present in `readwrite` if "tokio" Cargo feature is enabled.
///
/// Waiting for [RFC 1787](https://github.com/rust-lang/rfcs/pull/1787) to make it better.
pub struct ReadWriteAsync<R: AsyncRead, W: AsyncWrite>(pub R, pub W);

impl<R: AsyncRead, W: AsyncWrite> From<(R, W)> for ReadWriteAsync<R, W> {
#[cfg(all(feature = "tokio"))]
mod tokio {
use tokio_dep::io::{AsyncRead, AsyncWrite};

use std::pin::Pin;

pin_project_lite::pin_project! {
/// Combined async reader and writer, `tokio 1` version.
/// Note that this struct is only present in `readwrite` if "tokio" Cargo feature is enabled.
pub struct ReadWriteTokio<R, W> {
#[pin]
r: R,
#[pin]
w: W,
}
}

impl<R: AsyncRead, W: AsyncWrite> From<(R, W)> for ReadWriteTokio<R, W> {
fn from((r, w): (R, W)) -> Self {
ReadWriteAsync(r, w)
ReadWriteTokio { r, w }
}
}
impl<R: AsyncRead, W: AsyncWrite> ReadWriteAsync<R, W> {
impl<R: AsyncRead, W: AsyncWrite> ReadWriteTokio<R, W> {
/// Bundle separate async reader and writer into a combined pseudo-socket
pub fn new(r: R, w: W) -> Self {
ReadWriteAsync(r, w)
ReadWriteTokio { r, w }
}
/// Borrow inner objects
pub fn borrow(&self) -> (&R, &W) {
(&self.0, &self.1)
(&self.r, &self.w)
}
/// Borrow the reader
pub fn borrow_read(&self) -> &R {
&self.0
&self.r
}
/// Borrow the writer
pub fn borrow_write(&self) -> &W {
&self.1
&self.w
}
/// Mutably borrow inner objects
pub fn borrow_mut(&mut self) -> (&mut R, &mut W) {
(&mut self.0, &mut self.1)
(&mut self.r, &mut self.w)
}
/// Mutably borrow the reader
pub fn borrow_mut_read(&mut self) -> &mut R {
&mut self.0
&mut self.r
}
/// Mutably borrow the writer
pub fn borrow_mut_write(&mut self) -> &mut W {
&mut self.1
&mut self.w
}
/// Convert ReadWrite back into individual reader and writer pair
pub fn into_inner(self) -> (R, W) {
(self.0, self.1)
(self.r, self.w)
}
/// Convert ReadWrite back into the reader, dropping the writer
pub fn into_reader(self) -> R {
self.0
self.r
}
/// Convert ReadWrite back into the writer, dropping the reader
pub fn into_writer(self) -> W {
self.1
self.w
}

/// Borrow pinned reader and writer
pub fn borrow_pin(self: Pin<&mut Self>) -> (Pin<&mut R>, Pin<&mut W>) {
let p = self.project();
(p.r, p.w)
}
/// Borrow pinned reader
pub fn borrow_pin_read(self: Pin<&mut Self>) -> Pin<&mut R> {
self.project().r
}
/// Borrow pinned writer
pub fn borrow_pin_write(self: Pin<&mut Self>) -> Pin<&mut W> {
self.project().w
}
}

impl<R: AsyncRead, W> AsyncRead for ReadWriteTokio<R, W> {
fn poll_read(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio_dep::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
AsyncRead::poll_read(self.project().r, cx, buf)
}
}

impl<R: AsyncRead, W: AsyncWrite> Read for ReadWriteAsync<R, W> {
fn read(&mut self, buf:&mut [u8]) -> Result<usize> {
self.0.read(buf)

impl<R, W: AsyncWrite> AsyncWrite for ReadWriteTokio<R, W> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &[u8],
) -> std::task::Poll<Result<usize, std::io::Error>> {
self.project().w.poll_write(cx, buf)
}

fn poll_flush(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
self.project().w.poll_flush(cx)
}

fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), std::io::Error>> {
self.project().w.poll_shutdown(cx)
}

fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
bufs: &[std::io::IoSlice<'_>],
) -> std::task::Poll<Result<usize, std::io::Error>> {
self.project().w.poll_write_vectored(cx, bufs)
}

fn is_write_vectored(&self) -> bool {
self.w.is_write_vectored()
}
}
impl<R: AsyncRead, W: AsyncWrite> AsyncRead for ReadWriteAsync<R, W> {}
impl<R: AsyncRead, W: AsyncWrite> Write for ReadWriteAsync<R, W> {
fn write(&mut self, buf:&[u8]) -> Result<usize> {
self.1.write(buf)
}
#[cfg(all(feature = "tokio"))]
pub use tokio::ReadWriteTokio;

#[cfg(all(feature = "asyncstd"))]
mod asyncstd {
use futures::io::{AsyncRead, AsyncWrite};

use std::pin::Pin;

pin_project_lite::pin_project! {
/// Combined async reader and writer, `futures 0.3` version.
/// Note that this struct is only present in `readwrite` if "asyncstd" Cargo feature is enabled.
pub struct ReadWriteAsyncstd<R, W> {
#[pin]
r: R,
#[pin]
w: W,
}
fn flush(&mut self,) -> Result<()> {
self.1.flush()
}

impl<R: AsyncRead, W: AsyncWrite> From<(R, W)> for ReadWriteAsyncstd<R, W> {
fn from((r, w): (R, W)) -> Self {
ReadWriteAsyncstd { r, w }
}
}
impl<R: AsyncRead, W: AsyncWrite> AsyncWrite for ReadWriteAsync<R, W> {
fn shutdown(&mut self) -> futures::Poll<(), Error> {
self.1.shutdown()
impl<R: AsyncRead, W: AsyncWrite> ReadWriteAsyncstd<R, W> {
/// Bundle separate async reader and writer into a combined pseudo-socket
pub fn new(r: R, w: W) -> Self {
ReadWriteAsyncstd { r, w }
}
/// Borrow inner objects
pub fn borrow(&self) -> (&R, &W) {
(&self.r, &self.w)
}
/// Borrow the reader
pub fn borrow_read(&self) -> &R {
&self.r
}
/// Borrow the writer
pub fn borrow_write(&self) -> &W {
&self.w
}
/// Mutably borrow inner objects
pub fn borrow_mut(&mut self) -> (&mut R, &mut W) {
(&mut self.r, &mut self.w)
}
/// Mutably borrow the reader
pub fn borrow_mut_read(&mut self) -> &mut R {
&mut self.r
}
/// Mutably borrow the writer
pub fn borrow_mut_write(&mut self) -> &mut W {
&mut self.w
}
/// Convert ReadWrite back into individual reader and writer pair
pub fn into_inner(self) -> (R, W) {
(self.r, self.w)
}
/// Convert ReadWrite back into the reader, dropping the writer
pub fn into_reader(self) -> R {
self.r
}
/// Convert ReadWrite back into the writer, dropping the reader
pub fn into_writer(self) -> W {
self.w
}

/// Borrow pinned reader and writer
pub fn borrow_pin(self: Pin<&mut Self>) -> (Pin<&mut R>, Pin<&mut W>) {
let p = self.project();
(p.r, p.w)
}
/// Borrow pinned reader
pub fn borrow_pin_read(self: Pin<&mut Self>) -> Pin<&mut R> {
self.project().r
}
/// Borrow pinned writer
pub fn borrow_pin_write(self: Pin<&mut Self>) -> Pin<&mut W> {
self.project().w
}
}

impl<R: AsyncRead, W> AsyncRead for ReadWriteAsyncstd<R, W> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut [u8],
) -> std::task::Poll<std::io::Result<usize>> {
self.project().r.poll_read(cx, buf)
}

fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
bufs: &mut [std::io::IoSliceMut<'_>],
) -> std::task::Poll<std::io::Result<usize>> {
self.project().r.poll_read_vectored(cx, bufs)
}
}

impl<R, W: AsyncWrite> AsyncWrite for ReadWriteAsyncstd<R, W> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &[u8],
) -> std::task::Poll<std::io::Result<usize>> {
self.project().w.poll_write(cx, buf)
}

fn poll_flush(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<std::io::Result<()>> {
self.project().w.poll_flush(cx)
}

fn poll_close(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<std::io::Result<()>> {
self.project().w.poll_close(cx)
}

fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
bufs: &[std::io::IoSlice<'_>],
) -> std::task::Poll<std::io::Result<usize>> {
self.project().w.poll_write_vectored(cx, bufs)
}
}
}
#[cfg(all(feature="tokio-io",feature="futures"))]
pub use async::ReadWriteAsync;
#[cfg(all(feature = "asyncstd"))]
pub use asyncstd::ReadWriteAsyncstd;

0 comments on commit 85a95df

Please sign in to comment.