autocodec
A Rust derive macro for automatic binary protocol serialization and deserialization. Zero runtime dependencies.
Features
#[derive(Codec)]on structs and enums — generates encode/decode automatically- Big-endian (network byte order) by default, per-field or container-level little-endian override
- Configurable length prefixes (
u8,u16,u32,u64) - Custom enum discriminants via
#[repr(u8)]+ native= Nsyntax - Bitfield packing with
#[codec(bits = N)] - Field validation, padding, magic constants, skip with custom defaults
- Custom codec delegation via
#[codec(with = "module")] - Zero-copy parsing with
Bytes<'a> - Allocation guards against malicious inputs (16 MiB limit)
- Computed
encoded_size()without allocation - Error context with field names for debugging
- Composable — any
Codectype works as a field
Quick Start
use ;
// Encode
let header = Header ;
let mut buf = Vecnew;
header.encode;
// Decode
let = decode.unwrap;
assert_eq!;
// Decode exact (errors on trailing bytes)
let decoded = decode_exact.unwrap;
// Pre-calculate size without encoding
assert_eq!;
Supported Types
| Type | Wire format |
|---|---|
u8–u64, u128 |
N bytes, big-endian |
i8–i64, i128 |
N bytes, big-endian |
f32, f64 |
IEEE 754, big-endian |
bool |
1 byte |
String |
u32 length + UTF-8 |
Vec<T> |
u32 length + elements |
Option<T> |
u8 tag + value |
[T; N] |
N elements (no prefix) |
Box<T> |
transparent |
Box<[T]> |
u32 length + elements (like Vec) |
(A, B, ...) |
sequential (up to 8) |
HashMap<K, V> |
u32 length + pairs |
Bytes<'a> |
u32 length + bytes (zero-copy) |
Attributes
Container-level
// default endianness for all fields
// enum discriminant size
Enum discriminants
Use Rust's native #[repr] and = N syntax:
Or use #[codec(discriminant = N)] on individual variants.
Field-level
// per-field endianness
// length prefix type for Vec/String
// minimum length
// maximum length
// not on wire, uses Default
// not on wire, custom default
// N zero bytes after field
// constant value, error on mismatch
// fn(&T) -> bool, error if false
// custom encode/decode functions
// bitfield: pack into N bits
Bitfields
Consecutive fields annotated with #[codec(bits = N)] are packed into the minimum number of bytes (MSB-first):
Zero-Copy Parsing
For read-only access to byte slices without allocation:
use Bytes;
let data = ;
let = decode.unwrap;
assert_eq!;
// `bytes` borrows directly from `data` — no copy
Error Handling
Errors include field context for debugging:
// "in field `version`: not enough bytes: needed 2, have 1"
Error types:
NotEnoughBytes— input too shortInvalidUtf8— string not valid UTF-8UnknownDiscriminant— enum variant not recognizedTooShort/TooLong— length constraint violatedBadMagic— magic constant mismatchValidationFailed— custom validation returned falseTrailingBytes— unexpected data afterdecode_exactAllocationTooLarge— length prefix exceeds 16 MiB safety limitFieldError— wraps any of the above with the field name
About
This library was entirely AI-generated (by Kiro) under my supervision and direction. I reviewed all the code, so any questionable decisions are mine — not the AI's.
License
MIT