From 227533d456fe32e48ffcd3796f1e6c8f9318b230 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 25 Oct 2019 12:50:15 -0700 Subject: net: move into tokio crate (#1683) A step towards collapsing Tokio sub crates into a single `tokio` crate (#1318). The `net` implementation is now provided by the main `tokio` crate. Functionality can be opted out of by using the various net related feature flags. --- tokio/src/net/tcp/split.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tokio/src/net/tcp/split.rs (limited to 'tokio/src/net/tcp/split.rs') diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs new file mode 100644 index 00000000..db937267 --- /dev/null +++ b/tokio/src/net/tcp/split.rs @@ -0,0 +1,97 @@ +//! `TcpStream` split support. +//! +//! A `TcpStream` can be split into a `ReadHalf` and a +//! `WriteHalf` with the `TcpStream::split` method. `ReadHalf` +//! implements `AsyncRead` while `WriteHalf` implements `AsyncWrite`. +//! +//! Compared to the generic split of `AsyncRead + AsyncWrite`, this specialized +//! split has no associated overhead and enforces all invariants at the type +//! level. + +use super::TcpStream; + +use tokio_io::{AsyncRead, AsyncWrite}; + +use bytes::{Buf, BufMut}; +use std::io; +use std::net::Shutdown; +use std::pin::Pin; +use std::task::{Context, Poll}; + +/// Read half of a `TcpStream`. +#[derive(Debug)] +pub struct ReadHalf<'a>(&'a TcpStream); + +/// Write half of a `TcpStream`. +/// +/// Note that in the `AsyncWrite` implemenation of `TcpStreamWriteHalf`, +/// `poll_shutdown` actually shuts down the TCP stream in the write direction. +#[derive(Debug)] +pub struct WriteHalf<'a>(&'a TcpStream); + +pub(crate) fn split(stream: &mut TcpStream) -> (ReadHalf<'_>, WriteHalf<'_>) { + (ReadHalf(&*stream), WriteHalf(&*stream)) +} + +impl AsyncRead for ReadHalf<'_> { + unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { + false + } + + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + self.0.poll_read_priv(cx, buf) + } + + fn poll_read_buf( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut B, + ) -> Poll> { + self.0.poll_read_buf_priv(cx, buf) + } +} + +impl AsyncWrite for WriteHalf<'_> { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + self.0.poll_write_priv(cx, buf) + } + + #[inline] + fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + // tcp flush is a no-op + Poll::Ready(Ok(())) + } + + // `poll_shutdown` on a write half shutdowns the stream in the "write" direction. + fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + self.0.shutdown(Shutdown::Write).into() + } + + fn poll_write_buf( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut B, + ) -> Poll> { + self.0.poll_write_buf_priv(cx, buf) + } +} + +impl AsRef for ReadHalf<'_> { + fn as_ref(&self) -> &TcpStream { + self.0 + } +} + +impl AsRef for WriteHalf<'_> { + fn as_ref(&self) -> &TcpStream { + self.0 + } +} -- cgit v1.2.3