tokio_io/codec/decoder.rs
1use bytes::BytesMut;
2use std::io;
3
4use super::encoder::Encoder;
5use {AsyncRead, AsyncWrite};
6
7use _tokio_codec::Framed;
8
9/// Decoding of frames via buffers.
10///
11/// This trait is used when constructing an instance of `Framed` or
12/// `FramedRead`. An implementation of `Decoder` takes a byte stream that has
13/// already been buffered in `src` and decodes the data into a stream of
14/// `Self::Item` frames.
15///
16/// Implementations are able to track state on `self`, which enables
17/// implementing stateful streaming parsers. In many cases, though, this type
18/// will simply be a unit struct (e.g. `struct HttpDecoder`).
19
20// Note: We can't deprecate this trait, because the deprecation carries through to tokio-codec, and
21// there doesn't seem to be a way to un-deprecate the re-export.
22pub trait Decoder {
23 /// The type of decoded frames.
24 type Item;
25
26 /// The type of unrecoverable frame decoding errors.
27 ///
28 /// If an individual message is ill-formed but can be ignored without
29 /// interfering with the processing of future messages, it may be more
30 /// useful to report the failure as an `Item`.
31 ///
32 /// `From<io::Error>` is required in the interest of making `Error` suitable
33 /// for returning directly from a `FramedRead`, and to enable the default
34 /// implementation of `decode_eof` to yield an `io::Error` when the decoder
35 /// fails to consume all available data.
36 ///
37 /// Note that implementors of this trait can simply indicate `type Error =
38 /// io::Error` to use I/O errors as this type.
39 type Error: From<io::Error>;
40
41 /// Attempts to decode a frame from the provided buffer of bytes.
42 ///
43 /// This method is called by `FramedRead` whenever bytes are ready to be
44 /// parsed. The provided buffer of bytes is what's been read so far, and
45 /// this instance of `Decode` can determine whether an entire frame is in
46 /// the buffer and is ready to be returned.
47 ///
48 /// If an entire frame is available, then this instance will remove those
49 /// bytes from the buffer provided and return them as a decoded
50 /// frame. Note that removing bytes from the provided buffer doesn't always
51 /// necessarily copy the bytes, so this should be an efficient operation in
52 /// most circumstances.
53 ///
54 /// If the bytes look valid, but a frame isn't fully available yet, then
55 /// `Ok(None)` is returned. This indicates to the `Framed` instance that
56 /// it needs to read some more bytes before calling this method again.
57 ///
58 /// Note that the bytes provided may be empty. If a previous call to
59 /// `decode` consumed all the bytes in the buffer then `decode` will be
60 /// called again until it returns `Ok(None)`, indicating that more bytes need to
61 /// be read.
62 ///
63 /// Finally, if the bytes in the buffer are malformed then an error is
64 /// returned indicating why. This informs `Framed` that the stream is now
65 /// corrupt and should be terminated.
66 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error>;
67
68 /// A default method available to be called when there are no more bytes
69 /// available to be read from the underlying I/O.
70 ///
71 /// This method defaults to calling `decode` and returns an error if
72 /// `Ok(None)` is returned while there is unconsumed data in `buf`.
73 /// Typically this doesn't need to be implemented unless the framing
74 /// protocol differs near the end of the stream.
75 ///
76 /// Note that the `buf` argument may be empty. If a previous call to
77 /// `decode_eof` consumed all the bytes in the buffer, `decode_eof` will be
78 /// called again until it returns `None`, indicating that there are no more
79 /// frames to yield. This behavior enables returning finalization frames
80 /// that may not be based on inbound data.
81 fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
82 match self.decode(buf)? {
83 Some(frame) => Ok(Some(frame)),
84 None => {
85 if buf.is_empty() {
86 Ok(None)
87 } else {
88 Err(io::Error::new(io::ErrorKind::Other, "bytes remaining on stream").into())
89 }
90 }
91 }
92 }
93
94 /// Provides a `Stream` and `Sink` interface for reading and writing to this
95 /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
96 ///
97 /// Raw I/O objects work with byte sequences, but higher-level code usually
98 /// wants to batch these into meaningful chunks, called "frames". This
99 /// method layers framing on top of an I/O object, by using the `Codec`
100 /// traits to handle encoding and decoding of messages frames. Note that
101 /// the incoming and outgoing frame types may be distinct.
102 ///
103 /// This function returns a *single* object that is both `Stream` and
104 /// `Sink`; grouping this into a single object is often useful for layering
105 /// things like gzip or TLS, which require both read and write access to the
106 /// underlying object.
107 ///
108 /// If you want to work more directly with the streams and sink, consider
109 /// calling `split` on the `Framed` returned by this method, which will
110 /// break them into separate objects, allowing them to interact more easily.
111 fn framed<T: AsyncRead + AsyncWrite + Sized>(self, io: T) -> Framed<T, Self>
112 where
113 Self: Encoder + Sized,
114 {
115 Framed::new(io, self)
116 }
117}