diff options
author | Carl Lerche <me@carllerche.com> | 2019-10-25 12:50:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-25 12:50:15 -0700 |
commit | 227533d456fe32e48ffcd3796f1e6c8f9318b230 (patch) | |
tree | 498029aaf42dd64eeb8ef0e7d7f29802b45d4e95 /tokio/src/net/tcp/split.rs | |
parent | 03a9378297c73c2e56a6d6b55db22b92427b850a (diff) |
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.
Diffstat (limited to 'tokio/src/net/tcp/split.rs')
-rw-r--r-- | tokio/src/net/tcp/split.rs | 97 |
1 files changed, 97 insertions, 0 deletions
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<io::Result<usize>> { + self.0.poll_read_priv(cx, buf) + } + + fn poll_read_buf<B: BufMut>( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut B, + ) -> Poll<io::Result<usize>> { + 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<io::Result<usize>> { + self.0.poll_write_priv(cx, buf) + } + + #[inline] + fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> { + // 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<io::Result<()>> { + self.0.shutdown(Shutdown::Write).into() + } + + fn poll_write_buf<B: Buf>( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut B, + ) -> Poll<io::Result<usize>> { + self.0.poll_write_buf_priv(cx, buf) + } +} + +impl AsRef<TcpStream> for ReadHalf<'_> { + fn as_ref(&self) -> &TcpStream { + self.0 + } +} + +impl AsRef<TcpStream> for WriteHalf<'_> { + fn as_ref(&self) -> &TcpStream { + self.0 + } +} |