<div align="center">
<h1><code>duplex</code></h1>
<p>
<strong>The Duplex trait: interactive streams</strong>
</p>
<p>
<a href="https://github.com/sunfishcode/duplex/actions?query=workflow%3ACI"><img src="https://github.com/sunfishcode/duplex/workflows/CI/badge.svg" alt="Github Actions CI Status" /></a>
<a href="https://crates.io/crates/duplex"><img src="https://img.shields.io/crates/v/duplex.svg" alt="crates.io page" /></a>
<a href="https://docs.rs/duplex"><img src="https://docs.rs/duplex/badge.svg" alt="docs.rs docs" /></a>
</p>
</div>
This crate defines the [`Duplex`] trait, for types that have logically
independent input and output channels.
The [`Read`] and [`Write`] traits take their streams by `&mut self` and block,
so they cannot be used on the same stream simultaneously. This crate provides
and implements the [`HalfDuplex`] trait for any type which implements
[`Duplex`], [`Read`], and [`Write`].
The [`AsyncRead`] and [`AsyncWrite`] traits take their streams by `&mut self`
but do not block, so they can be used on the same stream simultaneously, at
least when they're connected to an endpoint which supports it. When the
"futures-io" feature is enabled, this crate provides and implements the
[`FullDuplex`] trait for any type which implements [`Duplex`], [`AsyncRead`],
and [`AsyncWrite`].
Tokio uses its own `AsyncRead`, and `AsyncWrite`. When the "tokio" feature is
enabled, this crate also provides and implements [`TokioFullDuplex`] for any
type which implements [`Duplex`], [`tokio::io::AsyncRead`], and
[`tokio::io::AsyncWrite`].
Normal [`File`]s are not duplex devices, because even though they support input
and output, the input and output are not logically independent since they share
a current-position pointer in the OS. Character devices are often unified with
files in OS APIs, however they may represent duplex devices. So while `File`
does not implement `Duplex`, [`CharDevice`] does.
The following are some notable types for which `Duplex` is implemented:
| [`std::net::TcpStream`] | | |
| [`io_streams::StreamDuplexer`] | | |
| [`nameless::DuplexByteStream`] | | |
| [`nameless::DuplexTextStream`] | | |
| [`char_device::CharDevice`] | `feature = char-device` | |
| [`socketpair::SocketpairStream`] | `feature = socketpair` | |
| [`ssh2::Stream`] | `feature = ssh2` | |
| [`ssh2::Channel`] | `feature = ssh2` | |
| [`serialport::TTYPort`] | `all(unix, feature = serialport)` | [serialport dependencies] |
| [`readwrite::ReadWrite`] | `feature = readwrite` | |
| [`duplexify::Duplexify`] | `feature = duplexify` | |
[serialport dependencies]: https://gitlab.com/susurrus/serialport-rs#dependencies
[`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
[`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
[`TcpStream`]: https://doc.rust-lang.org/std/net/struct.TcpStream.html
[`std::net::TcpStream`]: https://doc.rust-lang.org/std/net/struct.TcpStream.html
[`UnixStream`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html
[`std::os::unix::net::UnixStream`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html
[`File`]: https://doc.rust-lang.org/std/fs/struct.File.html
[`CharDevice`]: https://docs.rs/char-device/latest/char_device/struct.CharDevice.html
[`char_device::CharDevice`]: https://docs.rs/char_device/latest/char_device/struct.CharDevice.html
[`ssh2::Stream`]: https://docs.rs/ssh2/latest/ssh2/struct.Stream.html
[`ssh2::Channel`]: https://docs.rs/ssh2/latest/ssh2/struct.Channel.html
[`serialport::TTYPort`]: https://docs.rs/serialport/latest/serialport/struct.TTYPort.html
[`readwrite::ReadWrite`]: https://docs.rs/readwrite/latest/readwrite/struct.ReadWrite.html
[`duplexify::Duplexify`]: https://docs.rs/duplexify/latest/duplexify/struct.Duplexify.html
[`socketpair::SocketpairStream`]: https://docs.rs/socketpair/latest/socketpair/struct.SocketpairStream.html
[`io_streams::StreamDuplexer`]: https://docs.rs/io-streams/latest/io_streams/struct.StreamDuplexer.html
[`nameless::DuplexByteStream`]: https://docs.rs/nameless/latest/nameless/struct.DuplexByteStream.html
[`nameless::DuplexTextStream`]: https://docs.rs/nameless/latest/nameless/struct.DuplexTextStream.html
[`AsyncRead`]: https://docs.rs/futures-io/latest/futures_io/trait.AsyncRead.html
[`AsyncWrite`]: https://docs.rs/futures-io/latest/futures_io/trait.AsyncWrite.html
[`tokio::io::AsyncRead`]: https://docs.rs/tokio/latest/tokio/io/trait.AsyncRead.html
[`tokio::io::AsyncWrite`]: https://docs.rs/tokio/latest/tokio/io/trait.AsyncWrite.html
[`Duplex`]: https://docs.rs/duplex/latest/duplex/trait.Duplex.html
[`HalfDuplex`]: https://docs.rs/duplex/latest/duplex/trait.HalfDuplex.html
[`FullDuplex`]: https://docs.rs/duplex/latest/duplex/trait.FullDuplex.html
[`TokioFullDuplex`]: https://docs.rs/duplex/latest/duplex/trait.TokioFullDuplex.html