Skip to main content

tokio_io/codec/
mod.rs

1//! Utilities for encoding and decoding frames.
2//!
3//! Contains adapters to go from streams of bytes, [`AsyncRead`] and
4//! [`AsyncWrite`], to framed streams implementing [`Sink`] and [`Stream`].
5//! Framed streams are also known as [transports].
6//!
7//! [`AsyncRead`]: #
8//! [`AsyncWrite`]: #
9//! [`Sink`]: #
10//! [`Stream`]: #
11//! [transports]: #
12
13// tokio_io::codec originally held all codec-related helpers. This is now intended to be in
14// tokio_codec instead. However, for backward compatibility, this remains here. When the next major
15// breaking change comes, `Encoder` and `Decoder` need to be moved to `tokio_codec`, and the rest
16// of this module should be removed.
17
18#![doc(hidden)]
19#![allow(deprecated)]
20
21mod bytes_codec;
22mod decoder;
23mod encoder;
24mod lines_codec;
25
26pub use self::bytes_codec::BytesCodec;
27pub use self::decoder::Decoder;
28pub use self::encoder::Encoder;
29pub use self::lines_codec::LinesCodec;
30
31pub use framed::{Framed, FramedParts};
32pub use framed_read::FramedRead;
33pub use framed_write::FramedWrite;
34
35#[deprecated(since = "0.1.8", note = "Moved to tokio-codec")]
36#[doc(hidden)]
37pub mod length_delimited {
38    //! Frame a stream of bytes based on a length prefix
39    //!
40    //! Many protocols delimit their frames by prefacing frame data with a
41    //! frame head that specifies the length of the frame. The
42    //! `length_delimited` module provides utilities for handling the length
43    //! based framing. This allows the consumer to work with entire frames
44    //! without having to worry about buffering or other framing logic.
45    //!
46    //! # Getting started
47    //!
48    //! If implementing a protocol from scratch, using length delimited framing
49    //! is an easy way to get started. [`Framed::new()`](length_delimited::Framed::new) will adapt a
50    //! full-duplex byte stream with a length delimited framer using default
51    //! configuration values.
52    //!
53    //! ```
54    //! use tokio_io::{AsyncRead, AsyncWrite};
55    //! use tokio_io::codec::length_delimited;
56    //!
57    //! fn bind_transport<T: AsyncRead + AsyncWrite>(io: T)
58    //!     -> length_delimited::Framed<T>
59    //! {
60    //!     length_delimited::Framed::new(io)
61    //! }
62    //! ```
63    //!
64    //! The returned transport implements `Sink + Stream` for `BytesMut`. It
65    //! encodes the frame with a big-endian `u32` header denoting the frame
66    //! payload length:
67    //!
68    //! ```text
69    //! +----------+--------------------------------+
70    //! | len: u32 |          frame payload         |
71    //! +----------+--------------------------------+
72    //! ```
73    //!
74    //! Specifically, given the following:
75    //!
76    //! ```
77    //! # extern crate tokio_io;
78    //! # extern crate bytes;
79    //! # extern crate futures;
80    //! #
81    //! use tokio_io::{AsyncRead, AsyncWrite};
82    //! use tokio_io::codec::length_delimited;
83    //! use bytes::BytesMut;
84    //! use futures::{Sink, Future};
85    //!
86    //! fn write_frame<T: AsyncRead + AsyncWrite>(io: T) {
87    //!     let mut transport = length_delimited::Framed::new(io);
88    //!     let frame = BytesMut::from("hello world");
89    //!
90    //!     transport.send(frame).wait().unwrap();
91    //! }
92    //! #
93    //! # pub fn main() {}
94    //! ```
95    //!
96    //! The encoded frame will look like this:
97    //!
98    //! ```text
99    //! +---- len: u32 ----+---- data ----+
100    //! | \x00\x00\x00\x0b |  hello world |
101    //! +------------------+--------------+
102    //! ```
103    //!
104    //! # Decoding
105    //!
106    //! [`FramedRead`] adapts an [`AsyncRead`] into a `Stream` of [`BytesMut`],
107    //! such that each yielded [`BytesMut`] value contains the contents of an
108    //! entire frame. There are many configuration parameters enabling
109    //! [`FramedRead`] to handle a wide range of protocols. Here are some
110    //! examples that will cover the various options at a high level.
111    //!
112    //! ## Example 1
113    //!
114    //! The following will parse a `u16` length field at offset 0, including the
115    //! frame head in the yielded `BytesMut`.
116    //!
117    //! ```
118    //! # use tokio_io::AsyncRead;
119    //! # use tokio_io::codec::length_delimited;
120    //! # fn bind_read<T: AsyncRead>(io: T) {
121    //! length_delimited::Builder::new()
122    //!     .length_field_offset(0) // default value
123    //!     .length_field_length(2)
124    //!     .length_adjustment(0)   // default value
125    //!     .num_skip(0) // Do not strip frame header
126    //!     .new_read(io);
127    //! # }
128    //! ```
129    //!
130    //! The following frame will be decoded as such:
131    //!
132    //! ```text
133    //!          INPUT                           DECODED
134    //! +-- len ---+--- Payload ---+     +-- len ---+--- Payload ---+
135    //! | \x00\x0B |  Hello world  | --> | \x00\x0B |  Hello world  |
136    //! +----------+---------------+     +----------+---------------+
137    //! ```
138    //!
139    //! The value of the length field is 11 (`\x0B`) which represents the length
140    //! of the payload, `hello world`. By default, [`FramedRead`] assumes that
141    //! the length field represents the number of bytes that **follows** the
142    //! length field. Thus, the entire frame has a length of 13: 2 bytes for the
143    //! frame head + 11 bytes for the payload.
144    //!
145    //! ## Example 2
146    //!
147    //! The following will parse a `u16` length field at offset 0, omitting the
148    //! frame head in the yielded `BytesMut`.
149    //!
150    //! ```
151    //! # use tokio_io::AsyncRead;
152    //! # use tokio_io::codec::length_delimited;
153    //! # fn bind_read<T: AsyncRead>(io: T) {
154    //! length_delimited::Builder::new()
155    //!     .length_field_offset(0) // default value
156    //!     .length_field_length(2)
157    //!     .length_adjustment(0)   // default value
158    //!     // `num_skip` is not needed, the default is to skip
159    //!     .new_read(io);
160    //! # }
161    //! ```
162    //!
163    //! The following frame will be decoded as such:
164    //!
165    //! ```text
166    //!          INPUT                        DECODED
167    //! +-- len ---+--- Payload ---+     +--- Payload ---+
168    //! | \x00\x0B |  Hello world  | --> |  Hello world  |
169    //! +----------+---------------+     +---------------+
170    //! ```
171    //!
172    //! This is similar to the first example, the only difference is that the
173    //! frame head is **not** included in the yielded `BytesMut` value.
174    //!
175    //! ## Example 3
176    //!
177    //! The following will parse a `u16` length field at offset 0, including the
178    //! frame head in the yielded `BytesMut`. In this case, the length field
179    //! **includes** the frame head length.
180    //!
181    //! ```
182    //! # use tokio_io::AsyncRead;
183    //! # use tokio_io::codec::length_delimited;
184    //! # fn bind_read<T: AsyncRead>(io: T) {
185    //! length_delimited::Builder::new()
186    //!     .length_field_offset(0) // default value
187    //!     .length_field_length(2)
188    //!     .length_adjustment(-2)  // size of head
189    //!     .num_skip(0)
190    //!     .new_read(io);
191    //! # }
192    //! ```
193    //!
194    //! The following frame will be decoded as such:
195    //!
196    //! ```text
197    //!          INPUT                           DECODED
198    //! +-- len ---+--- Payload ---+     +-- len ---+--- Payload ---+
199    //! | \x00\x0D |  Hello world  | --> | \x00\x0D |  Hello world  |
200    //! +----------+---------------+     +----------+---------------+
201    //! ```
202    //!
203    //! In most cases, the length field represents the length of the payload
204    //! only, as shown in the previous examples. However, in some protocols the
205    //! length field represents the length of the whole frame, including the
206    //! head. In such cases, we specify a negative `length_adjustment` to adjust
207    //! the value provided in the frame head to represent the payload length.
208    //!
209    //! ## Example 4
210    //!
211    //! The following will parse a 3 byte length field at offset 0 in a 5 byte
212    //! frame head, including the frame head in the yielded `BytesMut`.
213    //!
214    //! ```
215    //! # use tokio_io::AsyncRead;
216    //! # use tokio_io::codec::length_delimited;
217    //! # fn bind_read<T: AsyncRead>(io: T) {
218    //! length_delimited::Builder::new()
219    //!     .length_field_offset(0) // default value
220    //!     .length_field_length(3)
221    //!     .length_adjustment(2)  // remaining head
222    //!     .num_skip(0)
223    //!     .new_read(io);
224    //! # }
225    //! ```
226    //!
227    //! The following frame will be decoded as such:
228    //!
229    //! ```text
230    //!                  INPUT
231    //! +---- len -----+- head -+--- Payload ---+
232    //! | \x00\x00\x0B | \xCAFE |  Hello world  |
233    //! +--------------+--------+---------------+
234    //!
235    //!                  DECODED
236    //! +---- len -----+- head -+--- Payload ---+
237    //! | \x00\x00\x0B | \xCAFE |  Hello world  |
238    //! +--------------+--------+---------------+
239    //! ```
240    //!
241    //! A more advanced example that shows a case where there is extra frame
242    //! head data between the length field and the payload. In such cases, it is
243    //! usually desirable to include the frame head as part of the yielded
244    //! `BytesMut`. This lets consumers of the length delimited framer to
245    //! process the frame head as needed.
246    //!
247    //! The positive `length_adjustment` value lets `FramedRead` factor in the
248    //! additional head into the frame length calculation.
249    //!
250    //! ## Example 5
251    //!
252    //! The following will parse a `u16` length field at offset 1 of a 4 byte
253    //! frame head. The first byte and the length field will be omitted from the
254    //! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be
255    //! included.
256    //!
257    //! ```
258    //! # use tokio_io::AsyncRead;
259    //! # use tokio_io::codec::length_delimited;
260    //! # fn bind_read<T: AsyncRead>(io: T) {
261    //! length_delimited::Builder::new()
262    //!     .length_field_offset(1) // length of hdr1
263    //!     .length_field_length(2)
264    //!     .length_adjustment(1)  // length of hdr2
265    //!     .num_skip(3) // length of hdr1 + LEN
266    //!     .new_read(io);
267    //! # }
268    //! ```
269    //!
270    //! The following frame will be decoded as such:
271    //!
272    //! ```text
273    //!                  INPUT
274    //! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+
275    //! |  \xCA  | \x00\x0B |  \xFE  |  Hello world  |
276    //! +--------+----------+--------+---------------+
277    //!
278    //!          DECODED
279    //! +- hdr2 -+--- Payload ---+
280    //! |  \xFE  |  Hello world  |
281    //! +--------+---------------+
282    //! ```
283    //!
284    //! The length field is situated in the middle of the frame head. In this
285    //! case, the first byte in the frame head could be a version or some other
286    //! identifier that is not needed for processing. On the other hand, the
287    //! second half of the head is needed.
288    //!
289    //! `length_field_offset` indicates how many bytes to skip before starting
290    //! to read the length field.  `length_adjustment` is the number of bytes to
291    //! skip starting at the end of the length field. In this case, it is the
292    //! second half of the head.
293    //!
294    //! ## Example 6
295    //!
296    //! The following will parse a `u16` length field at offset 1 of a 4 byte
297    //! frame head. The first byte and the length field will be omitted from the
298    //! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be
299    //! included. In this case, the length field **includes** the frame head
300    //! length.
301    //!
302    //! ```
303    //! # use tokio_io::AsyncRead;
304    //! # use tokio_io::codec::length_delimited;
305    //! # fn bind_read<T: AsyncRead>(io: T) {
306    //! length_delimited::Builder::new()
307    //!     .length_field_offset(1) // length of hdr1
308    //!     .length_field_length(2)
309    //!     .length_adjustment(-3)  // length of hdr1 + LEN, negative
310    //!     .num_skip(3)
311    //!     .new_read(io);
312    //! # }
313    //! ```
314    //!
315    //! The following frame will be decoded as such:
316    //!
317    //! ```text
318    //!                  INPUT
319    //! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+
320    //! |  \xCA  | \x00\x0F |  \xFE  |  Hello world  |
321    //! +--------+----------+--------+---------------+
322    //!
323    //!          DECODED
324    //! +- hdr2 -+--- Payload ---+
325    //! |  \xFE  |  Hello world  |
326    //! +--------+---------------+
327    //! ```
328    //!
329    //! Similar to the example above, the difference is that the length field
330    //! represents the length of the entire frame instead of just the payload.
331    //! The length of `hdr1` and `len` must be counted in `length_adjustment`.
332    //! Note that the length of `hdr2` does **not** need to be explicitly set
333    //! anywhere because it already is factored into the total frame length that
334    //! is read from the byte stream.
335    //!
336    //! # Encoding
337    //!
338    //! [`FramedWrite`] adapts an [`AsyncWrite`] into a `Sink` of [`BytesMut`],
339    //! such that each submitted [`BytesMut`] is prefaced by a length field.
340    //! There are fewer configuration options than [`FramedRead`]. Given
341    //! protocols that have more complex frame heads, an encoder should probably
342    //! be written by hand using [`Encoder`].
343    //!
344    //! Here is a simple example, given a `FramedWrite` with the following
345    //! configuration:
346    //!
347    //! ```
348    //! # extern crate tokio_io;
349    //! # extern crate bytes;
350    //! # use tokio_io::AsyncWrite;
351    //! # use tokio_io::codec::length_delimited;
352    //! # use bytes::BytesMut;
353    //! # fn write_frame<T: AsyncWrite>(io: T) {
354    //! # let _: length_delimited::FramedWrite<T, BytesMut> =
355    //! length_delimited::Builder::new()
356    //!     .length_field_length(2)
357    //!     .new_write(io);
358    //! # }
359    //! # pub fn main() {}
360    //! ```
361    //!
362    //! A payload of `hello world` will be encoded as:
363    //!
364    //! ```text
365    //! +- len: u16 -+---- data ----+
366    //! |  \x00\x0b  |  hello world |
367    //! +------------+--------------+
368    //! ```
369    //!
370    //! [`FramedRead`]: struct.FramedRead.html
371    //! [`FramedWrite`]: struct.FramedWrite.html
372    //! [`AsyncRead`]: ../../trait.AsyncRead.html
373    //! [`AsyncWrite`]: ../../trait.AsyncWrite.html
374    //! [`Encoder`]: ../trait.Encoder.html
375    //! [`BytesMut`]: https://docs.rs/bytes/0.4/bytes/struct.BytesMut.html
376
377    pub use length_delimited::*;
378}