The void-codec crate provides binary serialization for the Minecraft protocol. It includes Encode/Decode traits, derive macros, and implementations for all primitive types used by the protocol.
Encode::encode appends bytes to the buffer.Decode::decode reads bytes from the front of the slice, advancing the slice reference.The void-codec-macros crate provides #[derive(Encode, Decode)] for automatic implementation:
Fields are encoded/decoded in declaration order using their type's Encode/Decode implementation.
#[codec(varint32)]Encode an i32 field as a variable-length integer (1-5 bytes) instead of fixed 4 bytes:
#[codec(json)]Encode/decode a field as a JSON string (serialize with serde, then encode as a Minecraft string).
#[codec(fixed_length)]Encode a Vec<T> without a length prefix. The length is determined by a literal value, another field, or an arithmetic expression:
Without this attribute, Vec<T> is encoded with a VarI32 length prefix followed by the elements.
With fixed_length, Vec<u8> uses an optimized bulk copy path (not element-by-element decode).
#[codec(remaining)]Consume all remaining bytes in the buffer as a Vec<u8>. No length prefix is encoded or expected:
Must be on the last field. During decode, all remaining bytes are consumed.
#[codec(tagged)])For enums where each variant wraps a different packet type. The tag is a VarI32 prefix:
Encoding writes the packet_id as a VarI32, then the variant's payload. Decoding reads the VarI32 tag and dispatches to the matching variant.
For simple enums with integer discriminants. The enum is encoded as its underlying integer type:
Supports #[repr(u8)], #[repr(i32)], and other integer repr types.
Add #[codec(varint32)] to encode a #[repr(i32)] enum as a variable-length integer:
Built-in Encode/Decode implementations:
| Type | Encoding |
|---|---|
u8, i8 |
1 byte |
u16, i16 |
2 bytes, big-endian |
u32, i32 |
4 bytes, big-endian |
u64, i64 |
8 bytes, big-endian |
u128, i128 |
16 bytes, big-endian |
f32 |
4 bytes, IEEE 754, big-endian |
f64 |
8 bytes, IEEE 754, big-endian |
bool |
1 byte (0x00 or 0x01) |
String |
VarI32 length prefix + UTF-8 bytes |
VarI32 |
1-5 bytes, variable-length encoding |
VarI64 |
1-10 bytes, variable-length encoding |
Uuid |
16 bytes (128-bit, big-endian) |
Nbt (ussr_nbt) |
NBT binary format |
Vec<T> |
VarI32 length prefix + elements |
Option<T> |
1-byte bool prefix + value if present |
Define a new packet struct and derive the codec:
The derive macros generate the serialization code at compile time, ensuring zero-cost abstraction with no runtime reflection.