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_crc
directive:#[payload(bincode, no_crc)]
. - Disable automatic CRC calculation and implement the
PayloadCrc
trait manually for the specific payload. Automatic CRC calculation can be disabled using theno_auto_crc
directive:#[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 |