rmt-flute 0.5.0

ALC/LCT/FLUTE/NORM multicast object-delivery wire formats (RFC 5651/5775/6726/5740): LCT headers with flag-driven CCI/TSI/TOI sizing, header-extension chains, ALC + FEC Payload IDs, FLUTE EXT_FDT/EXT_CENC, and NORM messages.
Documentation
//! Multicast object-delivery wire formats: **ALC / LCT / FLUTE / NORM**.
//!
//! This crate parses and serializes the binary headers used to deliver files
//! and streams over IP multicast. Every format here is **IETF RMT** (Reliable
//! Multicast Transport) — RFC 5651, RFC 5775, RFC 6726, RFC 5740. No
//! broadcast-specific standard is implemented by this crate.
//!
//! Several delivery systems are layered *on top* of these formats and are
//! consumers of this crate rather than owners of it: **DVB** (DVB-IPTV and
//! DVB-MABR / ETSI TS 103 769 file delivery), **3GPP** (MBMS/eMBMS download
//! delivery), and **ATSC 3.0** (ROUTE, A/331 Annex A — written as a
//! profile-and-delta on RFC 5651/5775/6726).
//!
//! Renamed from `dvb-flute` at 0.4.0: the old name named one consumer of an
//! IETF standard rather than the standard itself, and read as a layering
//! error once non-DVB consumers needed to depend on it. All `dvb-flute`
//! versions are yanked; there is no shim.
//!
//! Implements:
//!
//! - [`LctHeader`] — the **Layered Coding Transport** header (RFC 5651 §5). The
//!   fixed first word carries `V`/`C`/`PSI`/`S`/`O`/`H`/`A`/`B`, `HDR_LEN` and
//!   the Codepoint; the `C`, `S`, `O` and `H` flags then drive the byte-widths
//!   of the **CCI**, **TSI** and **TOI** fields (`4*(C+1)`, `4*S+2*H`,
//!   `4*O+2*H` bytes). The shared `H` half-word feeds both TSI *and* TOI. Flag
//!   bits and `HDR_LEN` are recomputed on serialize from the typed field
//!   lengths — there is no raw passthrough.
//! - [`HeaderExtension`] — the LCT/NORM header-extension chain (RFC 5651 §5.2):
//!   variable-length (`HET` 0..=127, carries `HEL`) and fixed-length (`HET`
//!   128..=255, one word) forms; with [`ExtTime`] (EXT_TIME) and the
//!   [`LctExtType`] registry (EXT_NOP/EXT_AUTH/EXT_TIME).
//! - [`AlcPacket`] — an **Asynchronous Layered Coding** packet (RFC 5775):
//!   LCT header + an opaque FEC Payload ID + the encoding-symbol payload, plus
//!   `EXT_FTI` (HET 64) and the Small-Block-Systematic [`FecPayloadId128`].
//! - [`ExtFdt`] / [`ExtCenc`] — the **FLUTE** (RFC 6726) fixed-length LCT
//!   extensions `EXT_FDT` (HET 192) and `EXT_CENC` (HET 193), plus the TOI = 0
//!   FDT-Instance convention. The FDT Instance body is XML and is **out of
//!   scope** of this binary crate — it rides as the packet payload.
//! - [`NormCommonHeader`] + [`NormData`] / [`NormInfo`] / [`NormCmd`] / [`NormFeedback`] — the
//!   **NORM** (RFC 5740) common header and message types (NORM_INFO / NORM_DATA /
//!   NORM_CMD / NORM_NACK / NORM_ACK / NORM_REPORT).
//! - [`SourceBlockPartition`] — the FEC Building Block's (RFC 5052 §9.1)
//!   scheme-agnostic **Block Partitioning Algorithm**: given a transport
//!   object's Transfer-Length, Encoding-Symbol-Length and
//!   Maximum-Source-Block-Length, derive the number of source blocks and each
//!   block's length in symbols. The common substrate `dvb-mabr` and
//!   `atsc3-route` both need (issue #944) without hardcoding any FEC scheme's
//!   FEC Payload ID or Scheme-specific OTI layout.
//!
//! ⚠ **FEC Payload ID** bit layouts are FEC-scheme dependent (RFC 5052 / the FEC
//! Scheme document) and are **not** defined by ALC/NORM themselves; this crate
//! exposes them as opaque byte slices (the caller supplies the length), with
//! [`FecPayloadId128`] provided as one concrete illustrative layout.
//!
//! All integer fields are big-endian. `#![no_std]` + `alloc`; depends only on
//! `broadcast-common`.
//!
//! # Examples
//!
//! Build an LCT header from typed fields (flag-driven CCI/TSI/TOI widths) and
//! round-trip it:
//!
//! ```
//! use rmt_flute::{LctHeader, LCT_VERSION};
//!
//! let cci = [0u8; 4]; // C = 0
//! let tsi = [0u8; 4]; // S = 1, H = 0
//! let hdr = LctHeader {
//!     version: LCT_VERSION,
//!     psi: 0,
//!     close_session: false,
//!     close_object: false,
//!     codepoint: 0,
//!     cci: &cci,
//!     tsi: &tsi,
//!     toi: &[],
//!     extensions: vec![],
//! };
//! let mut buf = vec![0u8; hdr.serialized_len()];
//! hdr.serialize_into(&mut buf).unwrap();
//! let (re, used) = LctHeader::parse(&buf).unwrap();
//! assert_eq!(used, buf.len());
//! assert_eq!(re, hdr);
//! ```
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(missing_docs)]
// Runnable examples, embedded so they render on docs.rs and stay in sync with
// the actual `examples/*.rs` files (shown, not compiled).
#![doc = "\n## Runnable examples\n"]
#![doc = "Run with `cargo run -p rmt-flute --example <name>`.\n"]
#![doc = "\n### `build_lct`\n\n```rust,ignore"]
#![doc = include_str!("../examples/build_lct.rs")]
#![doc = "```\n\n### `parse_flute`\n\n```rust,ignore"]
#![doc = include_str!("../examples/parse_flute.rs")]
#![doc = "```"]

extern crate alloc;

mod alc;
mod error;
mod ext;
mod fec;
mod flute;
mod lct;
mod lct_ext;
mod norm;

pub use alc::{
    AlcPacket, FEC_PAYLOAD_ID_128_LEN, FecPayloadId128, HET_EXT_FTI as ALC_HET_EXT_FTI, PSI_SPI,
};
pub use error::{Error, Result};
pub use ext::{FIXED_HET_MIN, HeaderExtension, WORD, chain_len, parse_chain, serialize_chain};
pub use fec::SourceBlockPartition;
pub use flute::{
    CencAlgorithm, ExtCenc, ExtFdt, FDT_INSTANCE_ID_MAX, FLUTE_VERSION, HET_EXT_CENC, HET_EXT_FDT,
    TOI_FDT,
};
pub use lct::{FIXED_HEADER_LEN, LCT_VERSION, LctHeader};
pub use lct_ext::{
    ExtTime, HET_EXT_AUTH as LCT_HET_EXT_AUTH, HET_EXT_NOP, HET_EXT_TIME, LctExtType, USE_ERT,
    USE_SCT_HIGH, USE_SCT_LOW, USE_SLC,
};
pub use norm::{
    COMMON_HEADER_LEN, FEEDBACK_FIXED_LEN, HET_EXT_AUTH as NORM_HET_EXT_AUTH, HET_EXT_CC,
    HET_EXT_FTI as NORM_HET_EXT_FTI, HET_EXT_RATE, NORM_FLAG_EXPLICIT, NORM_FLAG_FILE,
    NORM_FLAG_INFO, NORM_FLAG_REPAIR, NORM_FLAG_STREAM, NORM_FLAG_UNRELIABLE, NORM_INFO_FIXED_LEN,
    NORM_NODE_ANY, NORM_NODE_NONE, NORM_VERSION, NormAckType, NormCmd, NormCmdType,
    NormCommonHeader, NormData, NormFeedback, NormInfo, NormMessageType, SENDER_WORD_LEN,
    SenderWord,
};