2018-03-01 21:48:18 -08:00
|
|
|
//! A runtime for writing reliable, asynchronous, and slim applications.
|
2016-07-30 17:53:12 -07:00
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! Tokio is an event-driven, non-blocking I/O platform for writing asynchronous
|
|
|
|
|
//! applications with the Rust programming language. At a high level, it
|
|
|
|
|
//! provides a few major components:
|
2017-12-05 16:55:25 +01:00
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! * A multi threaded, work-stealing based task [scheduler][runtime].
|
2018-07-22 13:35:30 -07:00
|
|
|
//! * A [reactor] backed by the operating system's event queue (epoll, kqueue,
|
2018-03-01 21:48:18 -08:00
|
|
|
//! IOCP, etc...).
|
|
|
|
|
//! * Asynchronous [TCP and UDP][net] sockets.
|
2018-05-02 11:19:58 -07:00
|
|
|
//! * Asynchronous [filesystem][fs] operations.
|
2018-03-30 11:50:02 -07:00
|
|
|
//! * [Timer][timer] API for scheduling work in the future.
|
2016-09-02 11:07:52 -07:00
|
|
|
//!
|
2018-03-30 11:50:02 -07:00
|
|
|
//! Tokio is built using [futures] as the abstraction for managing the
|
|
|
|
|
//! complexity of asynchronous programming.
|
2016-09-02 11:07:52 -07:00
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! Guide level documentation is found on the [website].
|
2016-09-02 11:07:52 -07:00
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! [website]: https://tokio.rs/docs/getting-started/hello-world/
|
2018-07-22 13:35:30 -07:00
|
|
|
//! [futures]: http://docs.rs/futures/0.1
|
2017-01-11 09:14:50 -08:00
|
|
|
//!
|
2016-09-02 11:07:52 -07:00
|
|
|
//! # Examples
|
|
|
|
|
//!
|
|
|
|
|
//! A simple TCP echo server:
|
|
|
|
|
//!
|
|
|
|
|
//! ```no_run
|
2017-10-24 16:30:16 -07:00
|
|
|
//! extern crate tokio;
|
2016-09-02 11:07:52 -07:00
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! use tokio::prelude::*;
|
|
|
|
|
//! use tokio::io::copy;
|
2017-10-24 16:30:16 -07:00
|
|
|
//! use tokio::net::TcpListener;
|
2016-09-02 11:07:52 -07:00
|
|
|
//!
|
|
|
|
|
//! fn main() {
|
2017-12-05 16:55:25 +01:00
|
|
|
//! // Bind the server's socket.
|
2017-01-10 10:02:15 -08:00
|
|
|
//! let addr = "127.0.0.1:12345".parse().unwrap();
|
2017-12-12 18:32:50 -06:00
|
|
|
//! let listener = TcpListener::bind(&addr)
|
2017-12-05 16:55:25 +01:00
|
|
|
//! .expect("unable to bind TCP listener");
|
2017-01-10 10:02:15 -08:00
|
|
|
//!
|
|
|
|
|
//! // Pull out a stream of sockets for incoming connections
|
2018-02-21 07:42:22 -08:00
|
|
|
//! let server = listener.incoming()
|
2018-03-01 21:48:18 -08:00
|
|
|
//! .map_err(|e| eprintln!("accept failed = {:?}", e))
|
2018-02-21 07:42:22 -08:00
|
|
|
//! .for_each(|sock| {
|
|
|
|
|
//! // Split up the reading and writing parts of the
|
|
|
|
|
//! // socket.
|
|
|
|
|
//! let (reader, writer) = sock.split();
|
|
|
|
|
//!
|
|
|
|
|
//! // A future that echos the data and returns how
|
|
|
|
|
//! // many bytes were copied...
|
|
|
|
|
//! let bytes_copied = copy(reader, writer);
|
|
|
|
|
//!
|
|
|
|
|
//! // ... after which we'll print what happened.
|
|
|
|
|
//! let handle_conn = bytes_copied.map(|amt| {
|
|
|
|
|
//! println!("wrote {:?} bytes", amt)
|
|
|
|
|
//! }).map_err(|err| {
|
|
|
|
|
//! eprintln!("IO error {:?}", err)
|
|
|
|
|
//! });
|
|
|
|
|
//!
|
|
|
|
|
//! // Spawn the future as a concurrent task.
|
|
|
|
|
//! tokio::spawn(handle_conn)
|
2017-01-10 10:02:15 -08:00
|
|
|
//! });
|
|
|
|
|
//!
|
2018-02-21 07:42:22 -08:00
|
|
|
//! // Start the Tokio runtime
|
|
|
|
|
//! tokio::run(server);
|
2016-09-02 11:07:52 -07:00
|
|
|
//! }
|
|
|
|
|
//! ```
|
2016-07-30 17:53:12 -07:00
|
|
|
|
2018-03-30 15:37:52 -07:00
|
|
|
#![doc(html_root_url = "https://docs.rs/tokio/0.1.5")]
|
2018-03-01 21:48:18 -08:00
|
|
|
#![deny(missing_docs, warnings, missing_debug_implementations)]
|
2016-07-30 17:53:12 -07:00
|
|
|
|
2018-08-24 12:54:42 -07:00
|
|
|
extern crate bytes;
|
2017-02-05 17:06:57 -08:00
|
|
|
#[macro_use]
|
2016-07-30 17:53:12 -07:00
|
|
|
extern crate futures;
|
|
|
|
|
extern crate mio;
|
2018-06-12 19:26:03 +02:00
|
|
|
extern crate tokio_current_thread;
|
2017-02-05 17:06:57 -08:00
|
|
|
extern crate tokio_io;
|
2018-02-21 07:42:22 -08:00
|
|
|
extern crate tokio_executor;
|
2018-08-14 21:18:54 +03:00
|
|
|
extern crate tokio_codec;
|
2018-05-02 11:19:58 -07:00
|
|
|
extern crate tokio_fs;
|
2018-03-02 13:51:34 -08:00
|
|
|
extern crate tokio_reactor;
|
2018-02-21 07:42:22 -08:00
|
|
|
extern crate tokio_threadpool;
|
2018-03-30 11:50:02 -07:00
|
|
|
extern crate tokio_timer;
|
2018-03-15 03:38:59 +11:00
|
|
|
extern crate tokio_tcp;
|
|
|
|
|
extern crate tokio_udp;
|
2016-07-30 17:53:12 -07:00
|
|
|
|
2018-08-16 06:26:10 +02:00
|
|
|
#[cfg(unix)]
|
|
|
|
|
extern crate tokio_uds;
|
|
|
|
|
|
2018-06-06 16:04:39 -07:00
|
|
|
pub mod clock;
|
2018-02-06 07:26:21 -08:00
|
|
|
pub mod executor;
|
2018-05-02 11:19:58 -07:00
|
|
|
pub mod fs;
|
2016-09-02 11:07:52 -07:00
|
|
|
pub mod net;
|
|
|
|
|
pub mod reactor;
|
2018-02-21 07:42:22 -08:00
|
|
|
pub mod runtime;
|
2018-03-30 11:50:02 -07:00
|
|
|
pub mod timer;
|
|
|
|
|
pub mod util;
|
2018-02-21 07:42:22 -08:00
|
|
|
|
|
|
|
|
pub use executor::spawn;
|
|
|
|
|
pub use runtime::run;
|
2018-02-28 09:03:13 -08:00
|
|
|
|
2018-08-24 12:54:42 -07:00
|
|
|
mod length_delimited;
|
|
|
|
|
|
2018-08-14 21:18:54 +03:00
|
|
|
pub mod codec {
|
|
|
|
|
//! Utilities for encoding and decoding frames.
|
|
|
|
|
//!
|
|
|
|
|
//! Contains adapters to go from streams of bytes, [`AsyncRead`] and
|
|
|
|
|
//! [`AsyncWrite`], to framed streams implementing [`Sink`] and [`Stream`].
|
|
|
|
|
//! Framed streams are also known as [transports].
|
|
|
|
|
//!
|
2018-08-15 21:25:25 -07:00
|
|
|
//! [`AsyncRead`]: ../io/trait.AsyncRead.html
|
|
|
|
|
//! [`AsyncWrite`]: ../io/trait.AsyncWrite.html
|
|
|
|
|
//! [`Sink`]: https://docs.rs/futures/0.1/futures/sink/trait.Sink.html
|
|
|
|
|
//! [`Stream`]: https://docs.rs/futures/0.1/futures/stream/trait.Stream.html
|
|
|
|
|
//! [transports]: https://tokio.rs/docs/going-deeper/frames/
|
2018-08-14 21:18:54 +03:00
|
|
|
|
|
|
|
|
pub use tokio_codec::{
|
|
|
|
|
Decoder,
|
|
|
|
|
Encoder,
|
|
|
|
|
Framed,
|
|
|
|
|
FramedParts,
|
|
|
|
|
FramedRead,
|
|
|
|
|
FramedWrite,
|
2018-08-15 21:25:25 -07:00
|
|
|
BytesCodec,
|
|
|
|
|
LinesCodec,
|
2018-08-14 21:18:54 +03:00
|
|
|
};
|
2018-08-24 12:54:42 -07:00
|
|
|
|
|
|
|
|
pub mod length_delimited {
|
|
|
|
|
//! Frame a stream of bytes based on a length prefix
|
|
|
|
|
//!
|
|
|
|
|
//! Many protocols delimit their frames by prefacing frame data with a
|
|
|
|
|
//! frame head that specifies the length of the frame. The
|
|
|
|
|
//! `length_delimited` module provides utilities for handling the length
|
|
|
|
|
//! based framing. This allows the consumer to work with entire frames
|
|
|
|
|
//! without having to worry about buffering or other framing logic.
|
|
|
|
|
//!
|
|
|
|
|
//! # Getting started
|
|
|
|
|
//!
|
|
|
|
|
//! If implementing a protocol from scratch, using length delimited framing
|
2018-08-30 14:50:32 -07:00
|
|
|
//! is an easy way to get started. [`Codec::new()`] will return a length
|
|
|
|
|
//! delimited codec using default configuration values. This can then be
|
|
|
|
|
//! used to construct a framer to adapt a full-duplex byte stream into a
|
|
|
|
|
//! stream of frames.
|
2018-08-24 12:54:42 -07:00
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! use tokio::io::{AsyncRead, AsyncWrite};
|
2018-08-30 14:50:32 -07:00
|
|
|
//! use tokio::codec::*;
|
2018-08-24 12:54:42 -07:00
|
|
|
//!
|
|
|
|
|
//! fn bind_transport<T: AsyncRead + AsyncWrite>(io: T)
|
2018-08-30 14:50:32 -07:00
|
|
|
//! -> Framed<T, LengthDelimitedCodec>
|
2018-08-24 12:54:42 -07:00
|
|
|
//! {
|
2018-08-30 14:50:32 -07:00
|
|
|
//! Framed::new(io, LengthDelimitedCodec::new())
|
2018-08-24 12:54:42 -07:00
|
|
|
//! }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The returned transport implements `Sink + Stream` for `BytesMut`. It
|
|
|
|
|
//! encodes the frame with a big-endian `u32` header denoting the frame
|
|
|
|
|
//! payload length:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! +----------+--------------------------------+
|
|
|
|
|
//! | len: u32 | frame payload |
|
|
|
|
|
//! +----------+--------------------------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! Specifically, given the following:
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # extern crate bytes;
|
|
|
|
|
//! # extern crate futures;
|
|
|
|
|
//! #
|
|
|
|
|
//! use tokio::io::{AsyncRead, AsyncWrite};
|
2018-08-30 14:50:32 -07:00
|
|
|
//! use tokio::codec::*;
|
|
|
|
|
//! use bytes::Bytes;
|
2018-08-24 12:54:42 -07:00
|
|
|
//! use futures::{Sink, Future};
|
|
|
|
|
//!
|
|
|
|
|
//! fn write_frame<T: AsyncRead + AsyncWrite>(io: T) {
|
2018-08-30 14:50:32 -07:00
|
|
|
//! let mut transport = Framed::new(io, LengthDelimitedCodec::new());
|
|
|
|
|
//! let frame = Bytes::from("hello world");
|
2018-08-24 12:54:42 -07:00
|
|
|
//!
|
|
|
|
|
//! transport.send(frame).wait().unwrap();
|
|
|
|
|
//! }
|
|
|
|
|
//! #
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The encoded frame will look like this:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! +---- len: u32 ----+---- data ----+
|
|
|
|
|
//! | \x00\x00\x00\x0b | hello world |
|
|
|
|
|
//! +------------------+--------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! # Decoding
|
|
|
|
|
//!
|
|
|
|
|
//! [`FramedRead`] adapts an [`AsyncRead`] into a `Stream` of [`BytesMut`],
|
|
|
|
|
//! such that each yielded [`BytesMut`] value contains the contents of an
|
|
|
|
|
//! entire frame. There are many configuration parameters enabling
|
|
|
|
|
//! [`FramedRead`] to handle a wide range of protocols. Here are some
|
|
|
|
|
//! examples that will cover the various options at a high level.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Example 1
|
|
|
|
|
//!
|
|
|
|
|
//! The following will parse a `u16` length field at offset 0, including the
|
|
|
|
|
//! frame head in the yielded `BytesMut`.
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # use tokio::io::AsyncRead;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # fn bind_read<T: AsyncRead>(io: T) {
|
|
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_offset(0) // default value
|
|
|
|
|
//! .length_field_length(2)
|
|
|
|
|
//! .length_adjustment(0) // default value
|
|
|
|
|
//! .num_skip(0) // Do not strip frame header
|
|
|
|
|
//! .new_read(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The following frame will be decoded as such:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! INPUT DECODED
|
|
|
|
|
//! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+
|
|
|
|
|
//! | \x00\x0B | Hello world | --> | \x00\x0B | Hello world |
|
|
|
|
|
//! +----------+---------------+ +----------+---------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The value of the length field is 11 (`\x0B`) which represents the length
|
|
|
|
|
//! of the payload, `hello world`. By default, [`FramedRead`] assumes that
|
|
|
|
|
//! the length field represents the number of bytes that **follows** the
|
|
|
|
|
//! length field. Thus, the entire frame has a length of 13: 2 bytes for the
|
|
|
|
|
//! frame head + 11 bytes for the payload.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Example 2
|
|
|
|
|
//!
|
|
|
|
|
//! The following will parse a `u16` length field at offset 0, omitting the
|
|
|
|
|
//! frame head in the yielded `BytesMut`.
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # use tokio::io::AsyncRead;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # fn bind_read<T: AsyncRead>(io: T) {
|
|
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_offset(0) // default value
|
|
|
|
|
//! .length_field_length(2)
|
|
|
|
|
//! .length_adjustment(0) // default value
|
|
|
|
|
//! // `num_skip` is not needed, the default is to skip
|
|
|
|
|
//! .new_read(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The following frame will be decoded as such:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! INPUT DECODED
|
|
|
|
|
//! +-- len ---+--- Payload ---+ +--- Payload ---+
|
|
|
|
|
//! | \x00\x0B | Hello world | --> | Hello world |
|
|
|
|
|
//! +----------+---------------+ +---------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! This is similar to the first example, the only difference is that the
|
|
|
|
|
//! frame head is **not** included in the yielded `BytesMut` value.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Example 3
|
|
|
|
|
//!
|
|
|
|
|
//! The following will parse a `u16` length field at offset 0, including the
|
|
|
|
|
//! frame head in the yielded `BytesMut`. In this case, the length field
|
|
|
|
|
//! **includes** the frame head length.
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # use tokio::io::AsyncRead;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # fn bind_read<T: AsyncRead>(io: T) {
|
|
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_offset(0) // default value
|
|
|
|
|
//! .length_field_length(2)
|
|
|
|
|
//! .length_adjustment(-2) // size of head
|
|
|
|
|
//! .num_skip(0)
|
|
|
|
|
//! .new_read(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The following frame will be decoded as such:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! INPUT DECODED
|
|
|
|
|
//! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+
|
|
|
|
|
//! | \x00\x0D | Hello world | --> | \x00\x0D | Hello world |
|
|
|
|
|
//! +----------+---------------+ +----------+---------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! In most cases, the length field represents the length of the payload
|
|
|
|
|
//! only, as shown in the previous examples. However, in some protocols the
|
|
|
|
|
//! length field represents the length of the whole frame, including the
|
|
|
|
|
//! head. In such cases, we specify a negative `length_adjustment` to adjust
|
|
|
|
|
//! the value provided in the frame head to represent the payload length.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Example 4
|
|
|
|
|
//!
|
|
|
|
|
//! The following will parse a 3 byte length field at offset 0 in a 5 byte
|
|
|
|
|
//! frame head, including the frame head in the yielded `BytesMut`.
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # use tokio::io::AsyncRead;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # fn bind_read<T: AsyncRead>(io: T) {
|
|
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_offset(0) // default value
|
|
|
|
|
//! .length_field_length(3)
|
|
|
|
|
//! .length_adjustment(2) // remaining head
|
|
|
|
|
//! .num_skip(0)
|
|
|
|
|
//! .new_read(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The following frame will be decoded as such:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! INPUT
|
|
|
|
|
//! +---- len -----+- head -+--- Payload ---+
|
|
|
|
|
//! | \x00\x00\x0B | \xCAFE | Hello world |
|
|
|
|
|
//! +--------------+--------+---------------+
|
|
|
|
|
//!
|
|
|
|
|
//! DECODED
|
|
|
|
|
//! +---- len -----+- head -+--- Payload ---+
|
|
|
|
|
//! | \x00\x00\x0B | \xCAFE | Hello world |
|
|
|
|
|
//! +--------------+--------+---------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! A more advanced example that shows a case where there is extra frame
|
|
|
|
|
//! head data between the length field and the payload. In such cases, it is
|
|
|
|
|
//! usually desirable to include the frame head as part of the yielded
|
|
|
|
|
//! `BytesMut`. This lets consumers of the length delimited framer to
|
|
|
|
|
//! process the frame head as needed.
|
|
|
|
|
//!
|
|
|
|
|
//! The positive `length_adjustment` value lets `FramedRead` factor in the
|
|
|
|
|
//! additional head into the frame length calculation.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Example 5
|
|
|
|
|
//!
|
|
|
|
|
//! The following will parse a `u16` length field at offset 1 of a 4 byte
|
|
|
|
|
//! frame head. The first byte and the length field will be omitted from the
|
|
|
|
|
//! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be
|
|
|
|
|
//! included.
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # use tokio::io::AsyncRead;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # fn bind_read<T: AsyncRead>(io: T) {
|
|
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_offset(1) // length of hdr1
|
|
|
|
|
//! .length_field_length(2)
|
|
|
|
|
//! .length_adjustment(1) // length of hdr2
|
|
|
|
|
//! .num_skip(3) // length of hdr1 + LEN
|
|
|
|
|
//! .new_read(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The following frame will be decoded as such:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! INPUT
|
|
|
|
|
//! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+
|
|
|
|
|
//! | \xCA | \x00\x0B | \xFE | Hello world |
|
|
|
|
|
//! +--------+----------+--------+---------------+
|
|
|
|
|
//!
|
|
|
|
|
//! DECODED
|
|
|
|
|
//! +- hdr2 -+--- Payload ---+
|
|
|
|
|
//! | \xFE | Hello world |
|
|
|
|
|
//! +--------+---------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The length field is situated in the middle of the frame head. In this
|
|
|
|
|
//! case, the first byte in the frame head could be a version or some other
|
|
|
|
|
//! identifier that is not needed for processing. On the other hand, the
|
|
|
|
|
//! second half of the head is needed.
|
|
|
|
|
//!
|
|
|
|
|
//! `length_field_offset` indicates how many bytes to skip before starting
|
|
|
|
|
//! to read the length field. `length_adjustment` is the number of bytes to
|
|
|
|
|
//! skip starting at the end of the length field. In this case, it is the
|
|
|
|
|
//! second half of the head.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Example 6
|
|
|
|
|
//!
|
|
|
|
|
//! The following will parse a `u16` length field at offset 1 of a 4 byte
|
|
|
|
|
//! frame head. The first byte and the length field will be omitted from the
|
|
|
|
|
//! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be
|
|
|
|
|
//! included. In this case, the length field **includes** the frame head
|
|
|
|
|
//! length.
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # use tokio::io::AsyncRead;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # fn bind_read<T: AsyncRead>(io: T) {
|
|
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_offset(1) // length of hdr1
|
|
|
|
|
//! .length_field_length(2)
|
|
|
|
|
//! .length_adjustment(-3) // length of hdr1 + LEN, negative
|
|
|
|
|
//! .num_skip(3)
|
|
|
|
|
//! .new_read(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The following frame will be decoded as such:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! INPUT
|
|
|
|
|
//! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+
|
|
|
|
|
//! | \xCA | \x00\x0F | \xFE | Hello world |
|
|
|
|
|
//! +--------+----------+--------+---------------+
|
|
|
|
|
//!
|
|
|
|
|
//! DECODED
|
|
|
|
|
//! +- hdr2 -+--- Payload ---+
|
|
|
|
|
//! | \xFE | Hello world |
|
|
|
|
|
//! +--------+---------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! Similar to the example above, the difference is that the length field
|
|
|
|
|
//! represents the length of the entire frame instead of just the payload.
|
|
|
|
|
//! The length of `hdr1` and `len` must be counted in `length_adjustment`.
|
|
|
|
|
//! Note that the length of `hdr2` does **not** need to be explicitly set
|
|
|
|
|
//! anywhere because it already is factored into the total frame length that
|
|
|
|
|
//! is read from the byte stream.
|
|
|
|
|
//!
|
|
|
|
|
//! # Encoding
|
|
|
|
|
//!
|
|
|
|
|
//! [`FramedWrite`] adapts an [`AsyncWrite`] into a `Sink` of [`BytesMut`],
|
|
|
|
|
//! such that each submitted [`BytesMut`] is prefaced by a length field.
|
|
|
|
|
//! There are fewer configuration options than [`FramedRead`]. Given
|
|
|
|
|
//! protocols that have more complex frame heads, an encoder should probably
|
|
|
|
|
//! be written by hand using [`Encoder`].
|
|
|
|
|
//!
|
|
|
|
|
//! Here is a simple example, given a `FramedWrite` with the following
|
|
|
|
|
//! configuration:
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! # extern crate tokio;
|
|
|
|
|
//! # extern crate bytes;
|
|
|
|
|
//! # use tokio::io::AsyncWrite;
|
|
|
|
|
//! # use tokio::codec::length_delimited;
|
|
|
|
|
//! # use bytes::BytesMut;
|
|
|
|
|
//! # fn write_frame<T: AsyncWrite>(io: T) {
|
2018-08-30 14:50:32 -07:00
|
|
|
//! # let _ =
|
2018-08-24 12:54:42 -07:00
|
|
|
//! length_delimited::Builder::new()
|
|
|
|
|
//! .length_field_length(2)
|
|
|
|
|
//! .new_write(io);
|
|
|
|
|
//! # }
|
|
|
|
|
//! # pub fn main() {}
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! A payload of `hello world` will be encoded as:
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! +- len: u16 -+---- data ----+
|
|
|
|
|
//! | \x00\x0b | hello world |
|
|
|
|
|
//! +------------+--------------+
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! [`FramedRead`]: struct.FramedRead.html
|
|
|
|
|
//! [`FramedWrite`]: struct.FramedWrite.html
|
|
|
|
|
//! [`AsyncRead`]: ../../trait.AsyncRead.html
|
|
|
|
|
//! [`AsyncWrite`]: ../../trait.AsyncWrite.html
|
|
|
|
|
//! [`Encoder`]: ../trait.Encoder.html
|
|
|
|
|
//! [`BytesMut`]: https://docs.rs/bytes/0.4/bytes/struct.BytesMut.html
|
|
|
|
|
pub use ::length_delimited::*;
|
|
|
|
|
}
|
2018-08-30 14:50:32 -07:00
|
|
|
|
|
|
|
|
pub use self::length_delimited::LengthDelimitedCodec;
|
2018-08-14 21:18:54 +03:00
|
|
|
}
|
|
|
|
|
|
2018-03-01 21:48:18 -08:00
|
|
|
pub mod io {
|
|
|
|
|
//! Asynchronous I/O.
|
|
|
|
|
//!
|
|
|
|
|
//! This module is the asynchronous version of `std::io`. Primarily, it
|
|
|
|
|
//! defines two traits, [`AsyncRead`] and [`AsyncWrite`], which extend the
|
|
|
|
|
//! `Read` and `Write` traits of the standard library.
|
|
|
|
|
//!
|
2018-05-02 11:19:58 -07:00
|
|
|
//! # AsyncRead and AsyncWrite
|
|
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! [`AsyncRead`] and [`AsyncWrite`] must only be implemented for
|
|
|
|
|
//! non-blocking I/O types that integrate with the futures type system. In
|
|
|
|
|
//! other words, these types must never block the thread, and instead the
|
|
|
|
|
//! current task is notified when the I/O resource is ready.
|
|
|
|
|
//!
|
2018-05-02 11:19:58 -07:00
|
|
|
//! # Standard input and output
|
|
|
|
|
//!
|
|
|
|
|
//! Tokio provides asynchronous APIs to standard [input], [output], and [error].
|
|
|
|
|
//! These APIs are very similar to the ones provided by `std`, but they also
|
|
|
|
|
//! implement [`AsyncRead`] and [`AsyncWrite`].
|
|
|
|
|
//!
|
|
|
|
|
//! Unlike *most* other Tokio APIs, the standard input / output APIs
|
|
|
|
|
//! **must** be used from the context of the Tokio runtime as they require
|
|
|
|
|
//! Tokio specific features to function.
|
|
|
|
|
//!
|
|
|
|
|
//! [input]: fn.stdin.html
|
|
|
|
|
//! [output]: fn.stdout.html
|
|
|
|
|
//! [error]: fn.stderr.html
|
|
|
|
|
//!
|
|
|
|
|
//! # Utility functions
|
|
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! Utilities functions are provided for working with [`AsyncRead`] /
|
|
|
|
|
//! [`AsyncWrite`] types. For example, [`copy`] asynchronously copies all
|
|
|
|
|
//! data from a source to a destination.
|
|
|
|
|
//!
|
2018-05-02 11:19:58 -07:00
|
|
|
//! # `std` re-exports
|
|
|
|
|
//!
|
2018-03-01 21:48:18 -08:00
|
|
|
//! Additionally, [`Read`], [`Write`], [`Error`], [`ErrorKind`], and
|
|
|
|
|
//! [`Result`] are re-exported from `std::io` for ease of use.
|
|
|
|
|
//!
|
|
|
|
|
//! [`AsyncRead`]: trait.AsyncRead.html
|
|
|
|
|
//! [`AsyncWrite`]: trait.AsyncWrite.html
|
|
|
|
|
//! [`copy`]: fn.copy.html
|
|
|
|
|
//! [`Read`]: trait.Read.html
|
|
|
|
|
//! [`Write`]: trait.Write.html
|
|
|
|
|
//! [`Error`]: struct.Error.html
|
|
|
|
|
//! [`ErrorKind`]: enum.ErrorKind.html
|
|
|
|
|
//! [`Result`]: type.Result.html
|
|
|
|
|
|
|
|
|
|
pub use tokio_io::{
|
|
|
|
|
AsyncRead,
|
|
|
|
|
AsyncWrite,
|
|
|
|
|
};
|
|
|
|
|
|
2018-05-02 11:19:58 -07:00
|
|
|
// standard input, output, and error
|
|
|
|
|
pub use tokio_fs::{
|
|
|
|
|
stdin,
|
|
|
|
|
Stdin,
|
|
|
|
|
stdout,
|
|
|
|
|
Stdout,
|
|
|
|
|
stderr,
|
|
|
|
|
Stderr,
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-01 21:48:18 -08:00
|
|
|
// Utils
|
|
|
|
|
pub use tokio_io::io::{
|
|
|
|
|
copy,
|
|
|
|
|
Copy,
|
|
|
|
|
flush,
|
|
|
|
|
Flush,
|
|
|
|
|
lines,
|
|
|
|
|
Lines,
|
|
|
|
|
read_exact,
|
|
|
|
|
ReadExact,
|
|
|
|
|
read_to_end,
|
|
|
|
|
ReadToEnd,
|
|
|
|
|
read_until,
|
|
|
|
|
ReadUntil,
|
2018-04-04 18:18:12 +02:00
|
|
|
ReadHalf,
|
2018-03-01 21:48:18 -08:00
|
|
|
shutdown,
|
|
|
|
|
Shutdown,
|
|
|
|
|
write_all,
|
|
|
|
|
WriteAll,
|
2018-04-04 18:18:12 +02:00
|
|
|
WriteHalf,
|
2018-03-01 21:48:18 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Re-export io::Error so that users don't have to deal
|
|
|
|
|
// with conflicts when `use`ing `futures::io` and `std::io`.
|
|
|
|
|
pub use ::std::io::{
|
|
|
|
|
Error,
|
|
|
|
|
ErrorKind,
|
|
|
|
|
Result,
|
|
|
|
|
Read,
|
|
|
|
|
Write,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub mod prelude {
|
|
|
|
|
//! A "prelude" for users of the `tokio` crate.
|
|
|
|
|
//!
|
|
|
|
|
//! This prelude is similar to the standard library's prelude in that you'll
|
|
|
|
|
//! almost always want to import its entire contents, but unlike the standard
|
|
|
|
|
//! library's prelude you'll have to do so manually:
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! use tokio::prelude::*;
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! The prelude may grow over time as additional items see ubiquitous use.
|
|
|
|
|
|
|
|
|
|
pub use tokio_io::{
|
|
|
|
|
AsyncRead,
|
|
|
|
|
AsyncWrite,
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-30 11:50:02 -07:00
|
|
|
pub use util::{
|
|
|
|
|
FutureExt,
|
2018-09-07 18:43:03 -04:00
|
|
|
StreamExt,
|
2018-03-30 11:50:02 -07:00
|
|
|
};
|
|
|
|
|
|
2018-03-01 21:48:18 -08:00
|
|
|
pub use ::std::io::{
|
|
|
|
|
Read,
|
|
|
|
|
Write,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub use futures::{
|
|
|
|
|
Future,
|
|
|
|
|
future,
|
|
|
|
|
Stream,
|
|
|
|
|
stream,
|
|
|
|
|
Sink,
|
|
|
|
|
IntoFuture,
|
|
|
|
|
Async,
|
|
|
|
|
AsyncSink,
|
|
|
|
|
Poll,
|
|
|
|
|
task,
|
|
|
|
|
};
|
|
|
|
|
}
|