| Crates.io | lencode |
| lib.rs | lencode |
| version | 0.1.0 |
| created_at | 2025-09-16 17:34:17.222066+00 |
| updated_at | 2025-09-16 17:34:17.222066+00 |
| description | A crate for encoding and decoding variable-length data using the Lencode varint encoding scheme and deduplication |
| homepage | |
| repository | https://github.com/sam0x17/lencode |
| max_upload_size | |
| id | 1842101 |
| size | 431,429 |
Compact, fast binary encoding with varints, optional deduplication, and opportunistic zstd compression for bytes and strings. no_std by default, with an opt‑in std feature.
std (uses zstd-safe)#[derive(Encode, Decode)] for your typessolana adds v2/v3 SDK types[dependencies]
lencode = "0.1"
# With standard library types (e.g., Cow)
lencode = { version = "0.1", features = ["std"] }
# With Solana type support (implies std)
lencode = { version = "0.1", features = ["solana"] }
use lencode::prelude::*;
#[derive(Encode, Decode, PartialEq, Debug)]
struct Point { x: u64, y: u64 }
let p = Point { x: 3, y: 5 };
let mut buf = Vec::new();
encode(&p, &mut buf)?;
let q: Point = decode(&mut Cursor::new(&buf))?;
assert_eq!(p, q);
use lencode::prelude::*;
let values: Vec<u128> = (0..10).collect();
let mut buf = Vec::new();
encode(&values, &mut buf)?;
let rt: Vec<u128> = decode(&mut Cursor::new(&buf))?;
assert_eq!(values, rt);
To benefit from deduplication for your own types, implement Pack and the marker traits and pass the encoder/decoder via encode_ext/decode_ext.
use lencode::prelude::*;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
struct MyId(u32);
impl Pack for MyId {
fn pack(&self, w: &mut impl Write) -> Result<usize> { self.0.pack(w) }
fn unpack(r: &mut impl Read) -> Result<Self> { Ok(Self(u32::unpack(r)?)) }
}
impl DedupeEncodeable for MyId {}
impl DedupeDecodeable for MyId {}
let vals = vec![MyId(42), MyId(7), MyId(42), MyId(7), MyId(42)];
// Encode with deduplication enabled
let mut enc = DedupeEncoder::new();
let mut buf = Vec::new();
encode_ext(&vals, &mut buf, Some(&mut enc))?;
// Decode with deduplication enabled
let mut dec = DedupeDecoder::new();
let roundtrip: Vec<MyId> = decode_ext(&mut Cursor::new(&buf), Some(&mut dec))?;
assert_eq!(roundtrip, vals);
&[u8], Vec<u8], VecDeque<u8], &str, and String use a compact flagged header: varint((payload_len << 1) | flag) + payload.
flag = 0 → raw bytes/UTF‑8flag = 1 → zstd frame (original size stored inside the frame)The encoder picks whichever is smaller per value.
bool, f32, f64[T; N]Option<T>&[u8], Vec<u8], VecDeque<u8], &str, StringVec<T>, BTreeMap<K,V>, BTreeSet<V>, VecDeque<T>, LinkedList<T>, BinaryHeap<T>(T1,) … up to 11 elementsstd feature: adds support for std::borrow::Cow<'_, T>solana feature: Pubkey, Signature, Hash, messages (legacy/v0), and related v2/v3 typesNote: HashMap/HashSet are not implemented.
default: core + no_std (uses alloc)std: enables std adapters and Cowsolana: Solana SDK v2 + Agave v3 types (implies std)s390x-unknown-linux-gnu using crossPack always uses a stable little‑endian layout# Full suite
cargo bench --all-features
# Compare against borsh/bincode
cargo bench --bench roundup --features std
# Solana‑specific
cargo bench --bench solana_bench --features solana
Errors use lencode::io::Error and map to std::io::Error under std.
use lencode::prelude::*;
use lencode::io::Error;
let mut buf = Vec::new();
match encode(&123u64, &mut buf) {
Ok(n) => eprintln!("wrote {n} bytes"),
Err(Error::WriterOutOfSpace) => eprintln!("buffer too small"),
Err(Error::ReaderOutOfData) => eprintln!("unexpected EOF"),
Err(Error::InvalidData) => eprintln!("corrupted data"),
Err(e) => eprintln!("other error: {e}"),
}
examples/size_comparison.rs: space savings on repeated Solana pubkeysexamples/versioned_tx_compression.rs: end‑to‑end on Solana versioned transactionsRun with --features solana.
MIT
DedupeEncoder/DedupeDecoderno_std by default; std and solana featuresEncode/Decode