| Crates.io | justcode-core |
| lib.rs | justcode-core |
| version | 0.3.0 |
| created_at | 2025-11-06 08:27:01.9424+00 |
| updated_at | 2025-11-07 05:59:23.211871+00 |
| description | Compact binary encoder/decoder with space-efficient encoding |
| homepage | https://github.com/entropy-tamer/justcode |
| repository | https://github.com/entropy-tamer/justcode |
| max_upload_size | |
| id | 1919288 |
| size | 105,128 |
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.
Encode and Decode trait implementationsAdd to your Cargo.toml:
[dependencies]
justcode-core = "0.3.0"
Or if using from a local path:
[dependencies]
justcode-core = { path = "../services/justcode/justcode-core" }
For derive macros support:
[dependencies]
justcode-core = { version = "0.3.0", features = ["derive"] }
# or
justcode-core = { path = "../services/justcode/justcode-core", features = ["derive"] }
use justcode_core::{config, Decode, Encode};
#[derive(Encode, Decode, PartialEq, Debug)]
struct Entity {
x: f32,
y: f32,
}
#[derive(Encode, Decode, PartialEq, Debug)]
struct World(Vec<Entity>);
fn main() {
let config = config::standard();
let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);
let encoded: Vec<u8> = justcode_core::encode_to_vec(&world, config).unwrap();
// The length of the vector is encoded as a varint u64, which in this case is encoded as a single byte
// See the documentation on varint for more information.
// The 4 floats are encoded in 4 bytes each.
assert_eq!(encoded.len(), 1 + 4 * 4);
let (decoded, len): (World, usize) = justcode_core::decode_from_slice(&encoded[..], config).unwrap();
assert_eq!(world, decoded);
assert_eq!(len, encoded.len()); // read all bytes
}
Justcode provides a configurable encoding system:
use justcode_core::config;
// Standard configuration (varint encoding enabled, no size limit)
let config = config::standard();
// With size limit (recommended for untrusted input)
let config = config::standard().with_limit(1024 * 1024); // 1MB limit
// Without variable int encoding (fixed-size integers)
let config = config::standard().with_variable_int_encoding(false);
u8, u16, u32, u64, usize, i8, i16, i32, i64f32, f64boolcharVec<T> where T: Encode/DecodeOption<T> where T: Encode/DecodeString and &strUse the derive macros for structs and enums:
#[derive(Encode, Decode)]
struct MyStruct {
field1: u32,
field2: String,
}
#[derive(Encode, Decode)]
enum MyEnum {
Variant1,
Variant2(u32),
Variant3 { x: f32, y: f32 },
}
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.
For streaming operations:
use justcode_core::{config, writer::Writer, reader::Reader};
let config = config::standard();
let mut writer = Writer::new(config);
value.encode(&mut writer)?;
let bytes = writer.into_bytes();
let mut reader = Reader::new(&bytes, config);
let decoded = T::decode(&mut reader)?;
Run all tests with:
cargo test --workspace
Test the no-std code paths separately:
cargo test --package justcode-core --test no_std_integration --no-default-features --features derive
The no-std tests verify that the conditionally compiled Vec implementations work correctly without the std feature.
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.
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.
Justcode requires Rust 1.70.0 or later.
#[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.
MIT