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}