vlen/mod.rs
1//! # vlen: High-performance variable-length numeric encoding
2//!
3//! `vlen` is an enhanced version of the original `vu128` variable-length
4//! numeric encoding. Numeric types up to 128 bits are supported (integers
5//! and floating-point), with smaller values being encoded using fewer
6//! bytes. Every integer width shares one wire format, so a value encoded
7//! as one type decodes as any wider type.
8//!
9//! The compression matches the widely used [VLQ] and [LEB128]
10//! encodings for values below `2^28` (and caps at 9 bytes for `u64`,
11//! where LEB128 needs up to 10), and it decodes faster on modern
12//! pipelined architectures because the encoded length is announced by
13//! the first byte instead of continuation bits spread across the value.
14//!
15//! [VLQ]: https://en.wikipedia.org/wiki/Variable-length_quantity
16//! [LEB128]: https://en.wikipedia.org/wiki/LEB128
17//!
18//! ## Quick Start
19//!
20//! ```rust
21//! use vlen::{Decode, Encode};
22//!
23//! let mut buf = [0u8; 5];
24//! let value = 12345u32;
25//!
26//! let len = value.encode(&mut buf)?;
27//! assert_eq!(len, value.encoded_size());
28//!
29//! let (decoded, decoded_len) = u32::decode(&buf[..len])?;
30//! assert_eq!(decoded, value);
31//! assert_eq!(decoded_len, len);
32//! # Ok::<(), vlen::Error>(())
33//! ```
34//!
35//! ## Two API layers
36//!
37//! - The [`Encode`] and [`Decode`] traits (and the free [`encode()`],
38//! [`decode()`], and [`bulk_encode`]/[`bulk_decode`] functions) work on
39//! ordinary slices, validate their input, and return typed
40//! [`Error`]s. Use these for untrusted or tightly-sized data.
41//! - The array-based functions ([`encode_u32`], [`decode_u32`], and
42//! friends) are the infallible fast core. They are all `const fn`,
43//! so they also work in compile-time contexts:
44//!
45//! ```rust
46//! const LEN: usize = {
47//! let mut buf = [0u8; 5];
48//! vlen::encode_u32(&mut buf, 12345)
49//! };
50//! assert_eq!(LEN, 2);
51//! ```
52//!
53//! ## Choosing an API
54//!
55//! | Need | Use |
56//! | --- | --- |
57//! | One checked value | [`Encode`]/[`Decode`] or [`encode()`]/[`decode()`] |
58//! | Canonical first value | [`decode_canonical()`] |
59//! | Exact whole input | [`decode_exact()`]; use [`decode_strict()`] when it must also be canonical |
60//! | A mixed-type message | [`Writer`] and [`Reader`]; use [`Reader::read_canonical`] and [`Reader::finish`] for strict fields and framing |
61//! | A homogeneous batch | [`bulk_encode()`]/[`bulk_decode()`], or the specialized `u32`, `u64`, `i32`, and `i64` variants |
62//! | Lazy stream decoding | [`decode_iter()`], or a specialized iterator such as [`decode_iter_u32()`] |
63//! | An owned buffer (`alloc`) | [`encode_to_vec()`], [`encode_append()`], and the bulk `Vec` helpers |
64//! | Compile-time or trusted fixed arrays | [`encode_u32()`]/[`decode_u32()`] and their typed counterparts |
65//!
66//! ## Exact and canonical decoding
67//!
68//! The normal decoder accepts over-long encodings so protocols can reserve a
69//! fixed-width slot before its value is known. Opt into stricter validation
70//! when encoded bytes must have one deterministic representation:
71//!
72//! ```rust
73//! let reserved = [0x85, 0x00]; // the value 5 in an over-long two-byte slot
74//! assert_eq!(vlen::decode::<u32>(&reserved), Ok((5, 2)));
75//! assert!(matches!(
76//! vlen::decode_strict::<u32>(&reserved),
77//! Err(vlen::StrictError::NonCanonical { .. })
78//! ));
79//! assert_eq!(vlen::decode_exact::<u32>(&[5]), Ok(5));
80//! ```
81
82#![cfg_attr(not(test), no_std)]
83#![cfg_attr(docsrs, feature(doc_cfg))]
84#![deny(unsafe_code)]
85
86#[cfg(feature = "alloc")]
87extern crate alloc;
88
89pub mod bulk;
90mod cursor;
91pub mod decode;
92pub mod encode;
93mod error;
94#[cfg(all(
95 feature = "simd",
96 any(
97 target_arch = "aarch64",
98 target_arch = "x86_64",
99 all(target_arch = "wasm32", target_feature = "simd128")
100 )
101))]
102#[allow(unsafe_code)]
103mod kernels;
104#[cfg(feature = "serde")]
105pub mod serde;
106
107pub use cursor::{Reader, Writer};
108pub use error::{Error, Result, StrictError, StrictResult};
109
110pub use decode::{
111 Decode, decode, decode_canonical, decode_exact, decode_f32, decode_f64,
112 decode_i8, decode_i16, decode_i32, decode_i64, decode_i128, decode_strict,
113 decode_u8, decode_u16, decode_u32, decode_u64, decode_u128,
114};
115
116pub use encode::{
117 Encode, encode, encode_f32, encode_f64, encode_i8, encode_i16, encode_i32,
118 encode_i64, encode_i128, encode_u8, encode_u16, encode_u32, encode_u64,
119 encode_u128, encoded_len, encoded_size, encoded_size_u8, encoded_size_u16,
120 encoded_size_u32, encoded_size_u64, encoded_size_u128,
121};
122
123pub use bulk::{
124 DecodeIter, DecodeIterI32, DecodeIterI64, DecodeIterU32, DecodeIterU64,
125 bulk_decode, bulk_decode_i32, bulk_decode_i64, bulk_decode_u32,
126 bulk_decode_u64, bulk_encode, bulk_encode_i32, bulk_encode_i64,
127 bulk_encode_u32, bulk_encode_u64, decode_iter, decode_iter_i32,
128 decode_iter_i64, decode_iter_u32, decode_iter_u64,
129};
130
131/// Decodes a single value from a slice, discarding the length.
132///
133/// Trailing bytes after the first value are ignored.
134#[inline]
135pub fn decode_value<T: Decode>(buf: &[u8]) -> Result<T> {
136 let (value, _) = T::decode(buf)?;
137 Ok(value)
138}
139
140/// Encodes a value into a newly allocated buffer.
141#[cfg(feature = "alloc")]
142#[must_use]
143pub fn encode_to_vec<T: Encode>(value: T) -> alloc::vec::Vec<u8> {
144 let mut buf = alloc::vec![0u8; value.encoded_size()];
145 let len = value
146 .encode(&mut buf)
147 .expect("buffer sized by encoded_size");
148 debug_assert_eq!(len, buf.len());
149 buf
150}
151
152/// Appends the encoding of `value` to a byte vector.
153#[cfg(feature = "alloc")]
154#[inline]
155pub fn encode_append<T: Encode>(buf: &mut alloc::vec::Vec<u8>, value: T) {
156 const STACK_SIZE: usize = <u128 as Encode>::MAX_ENCODED_SIZE;
157 if T::MAX_ENCODED_SIZE <= STACK_SIZE {
158 let mut tmp = [0u8; STACK_SIZE];
159 let len = value
160 .encode(&mut tmp)
161 .expect("MAX_ENCODED_SIZE fits the stack buffer");
162 debug_assert_eq!(len, value.encoded_size());
163 buf.extend_from_slice(&tmp[..len]);
164 return;
165 }
166 let start = buf.len();
167 let predicted = value.encoded_size();
168 let end = start
169 .checked_add(predicted)
170 .expect("encoded size overflows Vec length");
171 buf.resize(end, 0);
172 let len = value
173 .encode(&mut buf[start..])
174 .expect("buffer sized by encoded_size");
175 debug_assert_eq!(len, predicted);
176}
177
178/// Appends the encodings of all `values` to a byte vector.
179#[cfg(feature = "alloc")]
180pub fn bulk_encode_append<T: Encode>(
181 buf: &mut alloc::vec::Vec<u8>,
182 values: &[T],
183) {
184 let total: usize = values.iter().map(|v| v.encoded_size()).sum();
185 let start = buf.len();
186 buf.resize(start + total, 0);
187 let len = bulk_encode(&mut buf[start..], values)
188 .expect("buffer sized by encoded_size");
189 debug_assert_eq!(len, total);
190}
191
192/// Encodes a slice of values into a newly allocated buffer.
193#[cfg(feature = "alloc")]
194#[must_use]
195pub fn bulk_encode_to_vec<T: Encode>(values: &[T]) -> alloc::vec::Vec<u8> {
196 let total = values.iter().map(|v| v.encoded_size()).sum();
197 let mut buf = alloc::vec![0u8; total];
198 let len =
199 bulk_encode(&mut buf, values).expect("buffer sized by encoded_size");
200 debug_assert_eq!(len, total);
201 buf
202}
203
204/// Decodes every value in a slice into a newly allocated vector.
205///
206/// The buffer must contain a whole number of valid encodings.
207#[cfg(feature = "alloc")]
208pub fn bulk_decode_values<T: Decode>(buf: &[u8]) -> Result<alloc::vec::Vec<T>> {
209 decode_iter(buf).collect()
210}