Justcode
A compact binary encoder/decoder with space-efficient encoding scheme. The encoded size will be the same or smaller than the size that the object takes up in memory in a running Rust program.
Justcode is a replacement for bincode, providing similar functionality with a focus on binary encoding without any ideological baggage.
Features
- Compact Encoding: Space-efficient binary encoding that's the same size or smaller than in-memory representation
- Varint Encoding: Variable-length integer encoding for lengths and small values (enabled by default)
- Architecture Invariant: Byte-order independent, works across different architectures
- Streaming API: Reader/Writer API for integration with files, network streams, and compression libraries
- Configurable: Size limits, variable int encoding, and other options
- Derive Macros: Automatic
EncodeandDecodetrait implementations
Usage
Add to your Cargo.toml:
[]
= { = "../services/justcode/justcode-core" }
Example
use ;
;
Configuration
Justcode provides a configurable encoding system:
use config;
// Standard configuration (varint encoding enabled, no size limit)
let config = standard;
// With size limit (recommended for untrusted input)
let config = standard.with_limit; // 1MB limit
// Without variable int encoding (fixed-size integers)
let config = standard.with_variable_int_encoding;
Supported Types
Primitives
- All integer types:
u8,u16,u32,u64,usize,i8,i16,i32,i64 - Floating point:
f32,f64 - Boolean:
bool - Character:
char
Collections
Vec<T>whereT: Encode/DecodeOption<T>whereT: Encode/DecodeStringand&str- Arrays up to 32 elements
- Tuples up to 4 elements
Custom Types
Use the derive macros for structs and enums:
Enum Encoding
Enums are encoded with a variant index (using varint encoding by default) followed by the variant data. The variant index is determined by the order of variants in the enum definition.
Reader/Writer API
For streaming operations:
use ;
let config = standard;
let mut writer = new;
value.encode?;
let bytes = writer.into_bytes;
let mut reader = new;
let decoded = decode?;
Testing
Standard Tests
Run all tests with:
No-Std Tests
Test the no-std code paths separately:
# Run no-std integration tests
# Or use the test script
The no-std tests verify that the conditionally compiled Vec implementations work correctly without the std feature.
FAQ
Is Justcode suitable for storage?
Yes, the encoding format is stable when using the same configuration. Justcode is architecture-invariant and space-efficient, making it suitable for storage. However, it does not implement data versioning schemes or file headers.
Is Justcode suitable for untrusted inputs?
Justcode attempts to protect against hostile data. Use Config::with_limit() to set a maximum size limit to prevent memory exhaustion attacks. Deserializing malicious inputs will fail safely without causing undefined behavior.
What is Justcode's MSRV (minimum supported Rust version)?
Justcode requires Rust 1.70.0 or later.
Why does justcode not respect #[repr(u8)]?
Justcode encodes enum variants using varint encoding (or u32 when variable int encoding is disabled). This ensures compact encoding while maintaining compatibility. If you need to interop with a different protocol, consider implementing Encode and Decode manually.
License
MIT