1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
//! 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].
//!
//! [`AsyncRead`]: #
//! [`AsyncWrite`]: #
//! [`Sink`]: #
//! [`Stream`]: #
//! [transports]: #

pub use codecs::{BytesCodec, LinesCodec};
pub use framed::{Framed, FramedParts};
pub use framed_read::{FramedRead, Decoder};
pub use framed_write::{FramedWrite, Encoder};

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
    //! is an easy way to get started. [`Framed::new()`] will adapt a
    //! full-duplex byte stream with a length delimited framer using default
    //! configuration values.
    //!
    //! ```
    //! use tokio_io::{AsyncRead, AsyncWrite};
    //! use tokio_io::codec::length_delimited;
    //!
    //! fn bind_transport<T: AsyncRead + AsyncWrite>(io: T)
    //!     -> length_delimited::Framed<T>
    //! {
    //!     length_delimited::Framed::new(io)
    //! }
    //! ```
    //!
    //! 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_io;
    //! # extern crate bytes;
    //! # extern crate futures;
    //! #
    //! use tokio_io::{AsyncRead, AsyncWrite};
    //! use tokio_io::codec::length_delimited;
    //! use bytes::BytesMut;
    //! use futures::{Sink, Future};
    //!
    //! fn write_frame<T: AsyncRead + AsyncWrite>(io: T) {
    //!     let mut transport = length_delimited::Framed::new(io);
    //!     let frame = BytesMut::from("hello world");
    //!
    //!     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
    //! [`FrameRead`] 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`.
    //!
    //! ```
    //! # use tokio_io::AsyncRead;
    //! # use tokio_io::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);
    //! # }
    //! ```
    //!
    //! 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`.
    //!
    //! ```
    //! # use tokio_io::AsyncRead;
    //! # use tokio_io::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);
    //! # }
    //! ```
    //!
    //! 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.
    //!
    //! ```
    //! # use tokio_io::AsyncRead;
    //! # use tokio_io::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);
    //! # }
    //! ```
    //!
    //! 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`.
    //!
    //! ```
    //! # use tokio_io::AsyncRead;
    //! # use tokio_io::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);
    //! # }
    //! ```
    //!
    //! 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.
    //!
    //! ```
    //! # use tokio_io::AsyncRead;
    //! # use tokio_io::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);
    //! # }
    //! ```
    //!
    //! 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.
    //!
    //! ```
    //! # use tokio_io::AsyncRead;
    //! # use tokio_io::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);
    //! # }
    //! ```
    //!
    //! 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_io;
    //! # extern crate bytes;
    //! # use tokio_io::AsyncWrite;
    //! # use tokio_io::codec::length_delimited;
    //! # use bytes::BytesMut;
    //! # fn write_frame<T: AsyncWrite>(io: T) {
    //! # let _: length_delimited::FramedWrite<T, BytesMut> =
    //! 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::*;
}