async-codec 0.4.1

Utilities for creating async codecs
Documentation
//! # Async Encode/Decode helpers
//!
//! For prior art, see [tokio-codec](https://crates.io/crates/tokio-codec).
//! This borrows many of the ideas that originated there, though with a simpler
//! and `no_std`-compatible approach. No allocation is strictly required by
//! implementers of the [Encode] or [Decode] traits, making them suitable for
//! embedded applications.
//!
//! ## Encoders
//!
//! Encoders are types that implement the [Encode] trait. Consumers of this
//! trait will provide an `Item` to be encoded, along with a buffer into which
//! the resulting bytes should be placed. The `Encode`r may return one of three
//! from this operation:
//!
//! * `EncodeResult::Ok(n)`: The item was successfully encodeded into the
//!   provided buffer and took `n` bytes.
//! * `EncodeResult::Err(e)`: There was an unrecoverable error encoding the
//!   item. Subsequent calls with the same item should return the same error.
//! * `EncodeResult::Overflow(n)`: The item could be encoded, but the encoded
//!   representation would overflow the buffer. If `n > 0`, then a buffer of
//!   length `n` is required to hold the serialized item.
//!
//! Upon an `Overflow` result, the caller should allocate a bigger buffer (if
//! possible), and attempt the operation again. `Encode` implementations may
//! keep a previously encoded `Item` in an internal buffer to make re-attempted
//! encodings cheaper. If this approach is used, the [Encode::reset] method must
//! also be implemented.
//!
//! ## Decoders
//!
//! Decoders implement the [Decode] trait. To decode an `Item`, callers provide
//! the decoder with a buffer containing bytes from the stream. The decoder
//! returns a `usize` indicating that it consumed some number of bytes from the
//! buffer, along with one of three results:
//!
//! * `DecodeResult::Ok(item)`: The `item` was successfully decoded
//! * `DecodeResult::Err(e)`: An error `e` arose when decoding the item. This
//!   does not necessarily invalidate the stream.
//! * `DecodeResult::UnexpectedEnd`: Not enough data to decode yet, caller
//!   should read more and try again with more bytes.
//!
//! Decoders are free to consume bytes in-line with returning `UnexpectedEnd`
//! results and keep a running internal buffer of what's been read so far, or
//! they may opt for consuming the bytes for an `Item` all at once. They should
//! consume bytes in the error case as well so that the caller doesn't provide
//! the same bad data twice.
//!
//! ## Framed
//!
//! The [Framed] type provides a wrapper for `AsyncRead + AsyncWrite` streams
//! that applies an `Encode + Decode` object to create an async `Stream + Sink`
//! of `Item`s. It manages the reads and writes against the underlying stream
//! and the buffers provided to the encode/decode operations. Its error types
//! ([ReadFrameError] and [WriteFrameError]) differentiate between IO errors in
//! the stream (which are usually fatal), and codec errors (which might not be).
//!
//! ## Example
//!
//! ```rust
//! use std::{
//!     io,
//!     str::Utf8Error,
//! };
//!
//! use futures::{
//!     io::Cursor,
//!     prelude::*,
//! };
//!
//! use async_codec::*;
//!
//! struct LineCodec;
//!
//! impl Encode for LineCodec {
//!     type Item = String;
//!     type Error = ();
//!     fn encode(&mut self, item: &String, buf: &mut [u8]) -> EncodeResult<()> {
//!         let needed = item.as_bytes().len() + 1;
//!         if buf.len() < needed {
//!             return EncodeResult::Overflow(needed);
//!         }
//!         buf[..needed - 1].copy_from_slice(item.as_bytes());
//!         buf[needed - 1] = b'\n';
//!         Ok(needed).into()
//!     }
//! }
//!
//! impl Decode for LineCodec {
//!     type Item = String;
//!     type Error = Utf8Error;
//!
//!     fn decode(&mut self, buf: &mut [u8]) -> (usize, DecodeResult<String, Utf8Error>) {
//!         let newline = match buf.iter().position(|b| *b == b'\n') {
//!             Some(idx) => idx,
//!             None => return (0, DecodeResult::UnexpectedEnd),
//!         };
//!         let string_bytes = &buf[..newline];
//!         (
//!             newline + 1,
//!             std::str::from_utf8(string_bytes).map(String::from).into(),
//!         )
//!     }
//! }
//!
//! const SHAKESPEARE: &str = r#"Now is the winter of our discontent
//! Made glorious summer by this sun of York.
//! Some are born great, some achieve greatness
//! And some have greatness thrust upon them.
//! Friends, Romans, countrymen - lend me your ears!
//! I come not to praise Caesar, but to bury him.
//! The evil that men do lives after them
//! The good is oft interred with their bones.
//!                     It is a tale
//! Told by an idiot, full of sound and fury
//! Signifying nothing.
//! Ay me! For aught that I could ever read,
//! Could ever hear by tale or history,
//! The course of true love never did run smooth.
//! I have full cause of weeping, but this heart
//! Shall break into a hundred thousand flaws,
//! Or ere I'll weep.-O Fool, I shall go mad!
//!                     Each your doing,
//! So singular in each particular,
//! Crowns what you are doing in the present deed,
//! That all your acts are queens.
//! "#;
//!
//! #[async_std::main]
//! async fn main() {
//!     let reader = Cursor::new(Vec::from(SHAKESPEARE.as_bytes()));
//!     let mut framed = Framed::new(reader, LineCodec);
//!     let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
//!     let mut actual = vec![];
//!     while let Some(frame) = framed.next().await.transpose().unwrap() {
//!         actual.push(frame);
//!     }
//!     assert_eq!(actual, expected);
//!
//!     let mut actual = vec![0u8; SHAKESPEARE.as_bytes().len()];
//!     let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
//!     let writer = Cursor::new(&mut actual);
//!     let mut framed = Framed::new(writer, LineCodec);
//!     for frame in expected {
//!         framed.send(frame).await.unwrap();
//!     }
//!     assert_eq!(std::str::from_utf8(&actual).unwrap(), SHAKESPEARE);
//! }
//! ```

#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![warn(missing_docs)]

#[cfg(feature = "std")]
pub mod framed_std;
#[cfg(all(feature = "std", not(feature = "embrio")))]
pub use crate::framed_std::*;

#[cfg(feature = "embrio")]
pub mod framed_embrio;
#[cfg(all(feature = "embrio", not(feature = "std")))]
pub use crate::framed_embrio::*;

/// The result of an `Encode::encode` call
pub enum EncodeResult<E> {
    /// Item was successfully encoded and took `usize` bytes of the provided
    /// buffer.
    Ok(usize),
    /// There was an error encoding the item.
    Err(E),
    /// The encoded item would overflow the buffer.
    ///
    /// May contain the needed buffer size to successfully hold the encoded
    /// item. The value `0` indicates that the needed buffer size is
    /// unknown.
    Overflow(usize),
}

impl<E> From<Result<usize, E>> for EncodeResult<E> {
    fn from(other: Result<usize, E>) -> Self {
        match other {
            Ok(n) => EncodeResult::Ok(n),
            Err(e) => EncodeResult::Err(e),
        }
    }
}

/// Trait for things that can be encoded to a byte buffer
pub trait Encode {
    /// The item being encoded
    type Item;
    /// The error that may arise from serializing the value
    type Error;

    /// Encode `self` and place the encoded representation in the provided
    /// buffer.
    ///
    /// Returns either a `usize` representing the length of the buffer used, or
    /// an [EncodeResult::Overflow] containing either the minimum required
    /// buffer length, or the error arising from the serialization itself.
    ///
    /// Types implementing `Encode` may employ internal buffering to make
    /// repeated calls to `encode` with the same object cheaper in the event of
    /// an overflow error. If buffering is employed, the internal buffer should
    /// be cleared after the item has been successfully copied into the provided
    /// one.
    fn encode(&mut self, item: &Self::Item, buf: &mut [u8]) -> EncodeResult<Self::Error>;

    /// Signal the encoder that it should discard its internal buffer if it has
    /// one.
    ///
    /// This may be needed if the encoder caches the result of encoding an
    /// `Item` between an `Overflow` result and the `Ok` once the caller has
    /// provided an adequate buffer. Because the caller may not support a
    /// growable buffer, encoders cannot rely on being able to discard thier
    /// buffer when returning `Ok`.
    fn reset(&mut self) {}
}

/// The Result of a `Decode::decode` call
pub enum DecodeResult<T, E> {
    /// Item decoded successfully.
    Ok(T),
    /// A full frame was found, but an error was encountered when decoding it.
    Err(E),
    /// Not enough data to decode a full frame yet, more needs to be read.
    UnexpectedEnd,
}

impl<T, E> From<Result<T, E>> for DecodeResult<T, E> {
    fn from(res: Result<T, E>) -> DecodeResult<T, E> {
        match res {
            Ok(v) => DecodeResult::Ok(v),
            Err(e) => DecodeResult::Err(e),
        }
    }
}

/// Trait for values that can be decoded from a byte buffer
pub trait Decode {
    /// The item being decoded
    type Item;
    /// The error that may arise from a decode operation
    ///
    /// Note that this should *not* be returned in the event of an unexpected
    /// end-of-buffer. Instead, a [DecodeResult::UnexpectedEnd] should be used.
    type Error;

    /// Attempt to decode a value from the buffer
    ///
    /// Returns the number of bytes consumed from the buffer, along with a
    /// [DecodeResult] with either an item, error, or "need more bytes."
    ///
    /// Note that the "bytes consumed" return value should only be non-zero if
    /// either the buffer contains a full frame, or if internal buffering is
    /// employed.
    fn decode(&mut self, buffer: &mut [u8]) -> (usize, DecodeResult<Self::Item, Self::Error>);
}