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}