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
//! # 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>);
}