Specification
Block
A block supports fields of the following types:
| Type | Size in Binary Format (bytes) |
|---|---|
| u8 | 1 |
| u16 | 2 |
| u32 | 4 |
| u64 | 8 |
| u128 | 16 |
| i8 | 1 |
| i16 | 2 |
| i32 | 4 |
| i64 | 8 |
| i128 | 16 |
| f32 | 4 |
| f64 | 8 |
| bool | 1 |
| [u8; n] | n |
Any structure marked with the block macro will have the following extended representation in binary format:
| Field | Type |
|---|---|
| Signature | [u8; 4] |
| User-defined fields | Available types |
| CRC | [u8; 4] |
Thus, the total binary length of a block is calculated as:
length = 4 (Signature) + Block's Fields Length + 4 (CRC)
The block signature is generated automatically based on its name (including the module path) and the names of all its fields. The signature hash is computed using a 32-bit algorithm.
The block's CRC (32-bit) is generated based on the values of user-defined fields, excluding the signature and the CRC itself.
Payload
Any data type that implements the PayloadEncode and PayloadDecode<T> traits can be used as a payload. These traits handle the conversion of a payload to bytes and its unpacking from bytes, respectively. When serializing a payload into binary format, brec automatically adds a PayloadHeader to each payload.
PayloadHeader Structure
| Field | Size | Description |
|---|---|---|
| Signature Length | 1 byte | Length of the signature: 4, 8, 16, 32, 64, or 128 bytes |
| Signature | 4 to 128 bytes | Unique signature of the payload |
| CRC Length | 1 byte | Length of the CRC: 4, 8, 16, 32, 64, or 128 bytes |
| CRC | 4 to 128 bytes | CRC checksum of the payload |
| Payload Body Length | 4 bytes | Length of the payload body (u32) |
As seen in the PayloadHeader structure, it does not have a fixed size since the lengths of the signature and CRC can vary. For example, when using the bincode feature, both the signature and CRC lengths are set to 4 bytes (32 bits). However, users can implement their own versions with different lengths.
Thus, any payload in binary format is represented as follows:
| Component | Size | Description |
|---|---|---|
PayloadHeader |
14 - 262 bytes | Header containing metadata about the payload |
| Payload's body | --- | Payload data encoded using PayloadEncode |
The CRC of the payload is generated based on the bytes produced by PayloadEncode. This introduces some constraints on CRC verification since brec does not restrict the types of data used in a payload. If a payload contains data types that do not guarantee a strict byte sequence, CRC verification will always fail due to byte order variations. As a result, extracting the payload from the data stream will become impossible.
A simple example of such a situation is a HashMap, which does not guarantee a consistent field order when reconstructed. For instance, defining a payload like this:
#[payload(bincode)]
#[derive(serde::Deserialize, serde::Serialize)]
pub struct MyPayloadB {
items: HashMap<String, String>,
}
would make it impossible to extract this payload, as the CRC would always be different (except when the number of keys in the map is ≤ 1). This issue can be resolved in several ways:
- The simplest approach is to avoid using "unstable" data types and instead choose one that guarantees a fixed byte sequence.
- Disable CRC verification for this specific payload by using the
no_crcdirective:#[payload(bincode, no_crc)]. - Disable automatic CRC calculation and implement the
PayloadCrctrait manually for the specific payload. Automatic CRC calculation can be disabled using theno_auto_crcdirective:#[payload(bincode, no_auto_crc)].
Packet
A packet serves as a container for storing a set of blocks and optionally a single payload. Each packet includes its own header, PacketHeader:
PacketHeader Structure
| Field | Size | Description |
|---|---|---|
| Signature | 8 bytes | Static packet signature |
| Size | 8 bytes | Total size of the packet (excluding the PacketHeader) |
| Block's length | 8 bytes | Total length of all blocks (including signatures and CRC) in the packet |
| Payload existence flag | 1 byte | 0 - packet without payload; 1 - packet contains a payload |
| CRC | 4 bytes | CRC of the PacketHeader (not the entire packet, only the header) |
Thus, in binary format, a packet is structured as follows:
| Component | Size | Count |
|---|---|---|
PacketHeader |
29 bytes | 1 |
Block |
--- | 0 to 255 |
Payload |
--- | 0 or 1 |