Skip to main content

Module framing

Module framing 

Source
Available on crate feature tokio only.
Expand description

Async framing — a tokio_util::codec adapter (the tokio feature). Async framing via tokio_util::codec — the tokio feature.

BinCodec<T> implements Decoder + Encoder for any #[bin] message (anything that is BitDecode/BitEncode), so wrapping a tokio stream is one line:

use bnb::BinCodec;
use tokio_util::codec::Framed;
use futures_util::{SinkExt, StreamExt};

let mut conn = Framed::new(tcp_stream, BinCodec::<MyMsg>::new());
conn.send(MyMsg::Ping).await?;          // it's a `Sink<MyMsg>`
let reply = conn.next().await.unwrap()?; // …and a `Stream<Item = MyMsg>`

The codec relies on each message being self-delimiting (its #[bin] structure or a magic/length prefix bounds it) — decode reads exactly one message and returns None when only a partial frame has arrived, so Framed reads more and retries.

Byte alignment over Framed. Framed’s buffer is byte-granular, so BinCodec advances by whole bytes and starts each decode at a byte boundary. A message whose encoded length is not a whole number of bytes (a sub-byte #[bin] frame) therefore cannot be packed back-to-back on a Framed byte stream — use a byte-aligned message, or carry the bit cursor yourself with BitBuf/MessageStream. (Each UdpFramed datagram is framed independently, so sub-byte messages are fine there.)

The same BinCodec drives datagrams, too: tokio_util::udp::UdpFramed::new(udp_socket, BinCodec::<T>::new()) is a Stream<Item = (T, SocketAddr)> + Sink<(T, SocketAddr)>. So one codec covers async streams (Framed, TCP) and async datagrams (UdpFramed, UDP) — the async mirror of the sync MessageStream / MessageDatagram split. See examples/tokio_udp.

Structs§

BinCodec
A tokio_util::codec codec that frames any bnb #[bin] message T. Construct with BinCodec::new and hand it to Framed.