wire_codec/varint.rs
1//! Unsigned LEB128 varint encoding, plus zigzag-mapped signed helpers.
2//!
3//! A varint encodes an unsigned integer in one to ten bytes. The low seven
4//! bits of each byte carry payload, and the top bit signals continuation:
5//! `1` means more bytes follow, `0` means the value is complete.
6//!
7//! The encoding is identical to the format used by Protocol Buffers, WebAssembly,
8//! and DWARF. The signed helpers ([`encode_i32`], [`decode_i64`], ...) apply
9//! the [`zigzag`][`crate::zigzag`] mapping first, matching protobuf's
10//! `sint32` / `sint64` wire types.
11//!
12//! # Error contract
13//!
14//! Every function in this module is atomic: on error the cursor is left
15//! exactly where it was. A streaming caller that receives
16//! [`Error::UnexpectedEof`] can append more bytes and retry the same call
17//! without cloning the cursor first.
18//!
19//! # Canonical encodings
20//!
21//! LEB128 allows a value to be padded with redundant `0x80` continuation
22//! bytes followed by a `0x00` terminator (for example `[0x80, 0x00]` is an
23//! overlong encoding of `0`). The plain `decode_*` functions accept these
24//! overlong forms, as Protocol Buffers does. The `decode_*_canonical`
25//! functions reject them with [`Error::InvalidEncoding`], so that every value
26//! has exactly one accepted wire representation. Use the canonical forms when
27//! the encoded bytes are hashed, signed, deduplicated, or compared between
28//! implementations. The encoders always produce the canonical form.
29
30use crate::buf::{ReadBuf, WriteBuf};
31use crate::error::{Error, Result};
32use crate::zigzag;
33
34/// Maximum encoded length of a `u16` varint.
35pub const MAX_LEN_U16: usize = 3;
36/// Maximum encoded length of a `u32` varint.
37pub const MAX_LEN_U32: usize = 5;
38/// Maximum encoded length of a `u64` varint.
39pub const MAX_LEN_U64: usize = 10;
40
41/// Encoded length of `value` as a `u16` varint, in bytes (1 to 3).
42///
43/// # Example
44///
45/// ```
46/// use wire_codec::varint;
47/// assert_eq!(varint::encoded_len_u16(127), 1);
48/// assert_eq!(varint::encoded_len_u16(u16::MAX), 3);
49/// ```
50#[inline]
51#[must_use]
52pub const fn encoded_len_u16(value: u16) -> usize {
53 encoded_len_u64(value as u64)
54}
55
56/// Encoded length of `value` as a `u32` varint, in bytes (1 to 5).
57///
58/// # Example
59///
60/// ```
61/// use wire_codec::varint;
62/// assert_eq!(varint::encoded_len_u32(0), 1);
63/// assert_eq!(varint::encoded_len_u32(127), 1);
64/// assert_eq!(varint::encoded_len_u32(128), 2);
65/// assert_eq!(varint::encoded_len_u32(u32::MAX), 5);
66/// ```
67#[inline]
68#[must_use]
69pub const fn encoded_len_u32(value: u32) -> usize {
70 encoded_len_u64(value as u64)
71}
72
73/// Encoded length of `value` as a `u64` varint, in bytes (1 to 10).
74///
75/// # Example
76///
77/// ```
78/// use wire_codec::varint;
79/// assert_eq!(varint::encoded_len_u64(0), 1);
80/// assert_eq!(varint::encoded_len_u64(u64::MAX), 10);
81/// ```
82#[inline]
83#[must_use]
84pub const fn encoded_len_u64(value: u64) -> usize {
85 let bits = (u64::BITS - value.leading_zeros()) as usize;
86 if bits == 0 { 1 } else { bits.div_ceil(7) }
87}
88
89/// Encoded length of `value` as a `usize` varint, in bytes (1 to 10).
90///
91/// # Example
92///
93/// ```
94/// use wire_codec::varint;
95/// assert_eq!(varint::encoded_len_usize(300), 2);
96/// ```
97#[inline]
98#[must_use]
99pub const fn encoded_len_usize(value: usize) -> usize {
100 // `usize` is at most 64 bits on every supported target.
101 encoded_len_u64(value as u64)
102}
103
104/// Encoded length of `value` as a zigzag `i32` varint, in bytes (1 to 5).
105///
106/// # Example
107///
108/// ```
109/// use wire_codec::varint;
110/// assert_eq!(varint::encoded_len_i32(-1), 1);
111/// assert_eq!(varint::encoded_len_i32(i32::MIN), 5);
112/// ```
113#[inline]
114#[must_use]
115pub const fn encoded_len_i32(value: i32) -> usize {
116 encoded_len_u32(zigzag::encode_i32(value))
117}
118
119/// Encoded length of `value` as a zigzag `i64` varint, in bytes (1 to 10).
120///
121/// # Example
122///
123/// ```
124/// use wire_codec::varint;
125/// assert_eq!(varint::encoded_len_i64(-750), 2);
126/// assert_eq!(varint::encoded_len_i64(i64::MIN), 10);
127/// ```
128#[inline]
129#[must_use]
130pub const fn encoded_len_i64(value: i64) -> usize {
131 encoded_len_u64(zigzag::encode_i64(value))
132}
133
134/// Encode `value` as a `u16` varint into `buf`.
135///
136/// # Errors
137///
138/// Returns [`Error::BufferFull`] if `buf` has fewer than [`encoded_len_u16`]
139/// bytes available. Nothing is written on error.
140///
141/// # Example
142///
143/// ```
144/// use wire_codec::{varint, WriteBuf};
145/// let mut out = [0u8; 3];
146/// let mut buf = WriteBuf::new(&mut out);
147/// varint::encode_u16(300, &mut buf).unwrap();
148/// assert_eq!(buf.written(), &[0xAC, 0x02]);
149/// ```
150#[inline]
151pub fn encode_u16(value: u16, buf: &mut WriteBuf<'_>) -> Result<()> {
152 encode_raw(u64::from(value), buf)
153}
154
155/// Encode `value` as a `u32` varint into `buf`.
156///
157/// # Errors
158///
159/// Returns [`Error::BufferFull`] if `buf` has fewer than [`encoded_len_u32`]
160/// bytes available. Nothing is written on error.
161///
162/// # Example
163///
164/// ```
165/// use wire_codec::{varint, WriteBuf};
166/// let mut out = [0u8; 5];
167/// let mut buf = WriteBuf::new(&mut out);
168/// varint::encode_u32(300, &mut buf).unwrap();
169/// assert_eq!(buf.written(), &[0xAC, 0x02]);
170/// ```
171#[inline]
172pub fn encode_u32(value: u32, buf: &mut WriteBuf<'_>) -> Result<()> {
173 encode_raw(u64::from(value), buf)
174}
175
176/// Encode `value` as a `u64` varint into `buf`.
177///
178/// # Errors
179///
180/// Returns [`Error::BufferFull`] if `buf` has fewer than [`encoded_len_u64`]
181/// bytes available. Nothing is written on error.
182///
183/// # Example
184///
185/// ```
186/// use wire_codec::{varint, WriteBuf};
187/// let mut out = [0u8; varint::MAX_LEN_U64];
188/// let mut buf = WriteBuf::new(&mut out);
189/// varint::encode_u64(u64::MAX, &mut buf).unwrap();
190/// assert_eq!(buf.position(), 10);
191/// ```
192#[inline]
193pub fn encode_u64(value: u64, buf: &mut WriteBuf<'_>) -> Result<()> {
194 encode_raw(value, buf)
195}
196
197/// Encode `value` as a `usize` varint into `buf`.
198///
199/// The wire format is identical to [`encode_u64`], so a value written on a
200/// 64-bit host can be read by [`decode_usize`] on a 32-bit host whenever it
201/// fits.
202///
203/// # Errors
204///
205/// Returns [`Error::BufferFull`] if `buf` has fewer than
206/// [`encoded_len_usize`] bytes available. Nothing is written on error.
207///
208/// # Example
209///
210/// ```
211/// use wire_codec::{varint, WriteBuf};
212/// let payload = b"hello";
213/// let mut out = [0u8; 16];
214/// let mut buf = WriteBuf::new(&mut out);
215/// varint::encode_usize(payload.len(), &mut buf).unwrap();
216/// assert_eq!(buf.written(), &[5]);
217/// ```
218#[inline]
219pub fn encode_usize(value: usize, buf: &mut WriteBuf<'_>) -> Result<()> {
220 // `usize` is at most 64 bits on every supported target.
221 encode_raw(value as u64, buf)
222}
223
224/// Encode `value` as a zigzag `i32` varint (protobuf `sint32`) into `buf`.
225///
226/// # Errors
227///
228/// Returns [`Error::BufferFull`] if `buf` has fewer than [`encoded_len_i32`]
229/// bytes available. Nothing is written on error.
230///
231/// # Example
232///
233/// ```
234/// use wire_codec::{varint, WriteBuf};
235/// let mut out = [0u8; 5];
236/// let mut buf = WriteBuf::new(&mut out);
237/// varint::encode_i32(-2, &mut buf).unwrap();
238/// assert_eq!(buf.written(), &[3]);
239/// ```
240#[inline]
241pub fn encode_i32(value: i32, buf: &mut WriteBuf<'_>) -> Result<()> {
242 encode_raw(u64::from(zigzag::encode_i32(value)), buf)
243}
244
245/// Encode `value` as a zigzag `i64` varint (protobuf `sint64`) into `buf`.
246///
247/// # Errors
248///
249/// Returns [`Error::BufferFull`] if `buf` has fewer than [`encoded_len_i64`]
250/// bytes available. Nothing is written on error.
251///
252/// # Example
253///
254/// ```
255/// use wire_codec::{varint, WriteBuf};
256/// let mut out = [0u8; 10];
257/// let mut buf = WriteBuf::new(&mut out);
258/// varint::encode_i64(-750, &mut buf).unwrap();
259/// assert_eq!(buf.written(), &[0xDB, 0x0B]);
260/// ```
261#[inline]
262pub fn encode_i64(value: i64, buf: &mut WriteBuf<'_>) -> Result<()> {
263 encode_raw(zigzag::encode_i64(value), buf)
264}
265
266/// Decode a `u16` varint from `buf`.
267///
268/// # Errors
269///
270/// - [`Error::UnexpectedEof`] if `buf` is exhausted before the terminator byte.
271/// - [`Error::VarintOverflow`] if the decoded value exceeds `u16::MAX` or if
272/// more than [`MAX_LEN_U16`] bytes would be consumed.
273///
274/// The cursor is unchanged on error.
275///
276/// # Example
277///
278/// ```
279/// use wire_codec::{varint, ReadBuf};
280/// let mut buf = ReadBuf::new(&[0xFF, 0xFF, 0x03]);
281/// assert_eq!(varint::decode_u16(&mut buf).unwrap(), u16::MAX);
282/// ```
283#[inline]
284pub fn decode_u16(buf: &mut ReadBuf<'_>) -> Result<u16> {
285 // The width check inside `decode_with` guarantees the value fits.
286 decode_with(buf, MAX_LEN_U16, u16::BITS, false).map(|v| v as u16)
287}
288
289/// Decode a `u32` varint from `buf`.
290///
291/// # Errors
292///
293/// - [`Error::UnexpectedEof`] if `buf` is exhausted before the terminator byte.
294/// - [`Error::VarintOverflow`] if the decoded value exceeds `u32::MAX` or if
295/// more than [`MAX_LEN_U32`] bytes would be consumed.
296///
297/// The cursor is unchanged on error.
298///
299/// # Example
300///
301/// ```
302/// use wire_codec::{varint, ReadBuf};
303/// let mut buf = ReadBuf::new(&[0xAC, 0x02]);
304/// assert_eq!(varint::decode_u32(&mut buf).unwrap(), 300);
305/// ```
306#[inline]
307pub fn decode_u32(buf: &mut ReadBuf<'_>) -> Result<u32> {
308 decode_with(buf, MAX_LEN_U32, u32::BITS, false).map(|v| v as u32)
309}
310
311/// Decode a `u64` varint from `buf`.
312///
313/// # Errors
314///
315/// - [`Error::UnexpectedEof`] if `buf` is exhausted before the terminator byte.
316/// - [`Error::VarintOverflow`] if more than [`MAX_LEN_U64`] bytes would be
317/// consumed or the final byte carries bits that would overflow `u64`.
318///
319/// The cursor is unchanged on error.
320///
321/// # Example
322///
323/// ```
324/// use wire_codec::{varint, ReadBuf};
325/// let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01];
326/// let mut buf = ReadBuf::new(&bytes);
327/// assert_eq!(varint::decode_u64(&mut buf).unwrap(), u64::MAX);
328/// assert!(buf.is_empty());
329/// ```
330#[inline]
331pub fn decode_u64(buf: &mut ReadBuf<'_>) -> Result<u64> {
332 decode_with(buf, MAX_LEN_U64, u64::BITS, false)
333}
334
335/// Decode a `usize` varint from `buf`.
336///
337/// The bytes are parsed as a `u64` varint and then converted, so the
338/// accepted wire format is the same on every target.
339///
340/// # Errors
341///
342/// - [`Error::UnexpectedEof`] if `buf` is exhausted before the terminator byte.
343/// - [`Error::VarintOverflow`] if the value overflows `u64`, or does not fit
344/// in `usize` on this target (values above `u32::MAX` on 32-bit hosts).
345///
346/// The cursor is unchanged on error.
347///
348/// # Example
349///
350/// ```
351/// use wire_codec::{varint, ReadBuf};
352/// let mut buf = ReadBuf::new(&[0x05, b'h', b'e', b'l', b'l', b'o']);
353/// let len = varint::decode_usize(&mut buf).unwrap();
354/// assert_eq!(buf.read_bytes(len).unwrap(), b"hello");
355/// ```
356#[inline]
357pub fn decode_usize(buf: &mut ReadBuf<'_>) -> Result<usize> {
358 decode_usize_with(buf, false)
359}
360
361/// Decode a zigzag `i32` varint (protobuf `sint32`) from `buf`.
362///
363/// # Errors
364///
365/// Same contract as [`decode_u32`]. The cursor is unchanged on error.
366///
367/// # Example
368///
369/// ```
370/// use wire_codec::{varint, ReadBuf};
371/// let mut buf = ReadBuf::new(&[0x03]);
372/// assert_eq!(varint::decode_i32(&mut buf).unwrap(), -2);
373/// ```
374#[inline]
375pub fn decode_i32(buf: &mut ReadBuf<'_>) -> Result<i32> {
376 decode_u32(buf).map(zigzag::decode_i32)
377}
378
379/// Decode a zigzag `i64` varint (protobuf `sint64`) from `buf`.
380///
381/// # Errors
382///
383/// Same contract as [`decode_u64`]. The cursor is unchanged on error.
384///
385/// # Example
386///
387/// ```
388/// use wire_codec::{varint, ReadBuf};
389/// let mut buf = ReadBuf::new(&[0xDB, 0x0B]);
390/// assert_eq!(varint::decode_i64(&mut buf).unwrap(), -750);
391/// ```
392#[inline]
393pub fn decode_i64(buf: &mut ReadBuf<'_>) -> Result<i64> {
394 decode_u64(buf).map(zigzag::decode_i64)
395}
396
397/// Decode a `u16` varint, rejecting overlong encodings.
398///
399/// # Errors
400///
401/// Everything [`decode_u16`] returns, plus [`Error::InvalidEncoding`] when
402/// the value is padded with redundant continuation bytes. The cursor is
403/// unchanged on error.
404///
405/// # Example
406///
407/// ```
408/// use wire_codec::{varint, Error, ReadBuf};
409/// let mut buf = ReadBuf::new(&[0x80, 0x00]);
410/// assert_eq!(varint::decode_u16_canonical(&mut buf), Err(Error::InvalidEncoding));
411/// assert_eq!(buf.position(), 0);
412/// ```
413#[inline]
414pub fn decode_u16_canonical(buf: &mut ReadBuf<'_>) -> Result<u16> {
415 decode_with(buf, MAX_LEN_U16, u16::BITS, true).map(|v| v as u16)
416}
417
418/// Decode a `u32` varint, rejecting overlong encodings.
419///
420/// # Errors
421///
422/// Everything [`decode_u32`] returns, plus [`Error::InvalidEncoding`] when
423/// the value is padded with redundant continuation bytes. The cursor is
424/// unchanged on error.
425///
426/// # Example
427///
428/// ```
429/// use wire_codec::{varint, Error, ReadBuf};
430/// // `[0x80, 0x80, 0x80, 0x80, 0x00]` is a five-byte encoding of zero.
431/// let mut buf = ReadBuf::new(&[0x80, 0x80, 0x80, 0x80, 0x00]);
432/// assert_eq!(varint::decode_u32_canonical(&mut buf), Err(Error::InvalidEncoding));
433///
434/// let mut buf = ReadBuf::new(&[0xAC, 0x02]);
435/// assert_eq!(varint::decode_u32_canonical(&mut buf), Ok(300));
436/// ```
437#[inline]
438pub fn decode_u32_canonical(buf: &mut ReadBuf<'_>) -> Result<u32> {
439 decode_with(buf, MAX_LEN_U32, u32::BITS, true).map(|v| v as u32)
440}
441
442/// Decode a `u64` varint, rejecting overlong encodings.
443///
444/// # Errors
445///
446/// Everything [`decode_u64`] returns, plus [`Error::InvalidEncoding`] when
447/// the value is padded with redundant continuation bytes. The cursor is
448/// unchanged on error.
449///
450/// # Example
451///
452/// ```
453/// use wire_codec::{varint, Error, ReadBuf};
454/// let mut buf = ReadBuf::new(&[0x81, 0x00]);
455/// assert_eq!(varint::decode_u64_canonical(&mut buf), Err(Error::InvalidEncoding));
456/// ```
457#[inline]
458pub fn decode_u64_canonical(buf: &mut ReadBuf<'_>) -> Result<u64> {
459 decode_with(buf, MAX_LEN_U64, u64::BITS, true)
460}
461
462/// Decode a `usize` varint, rejecting overlong encodings.
463///
464/// # Errors
465///
466/// Everything [`decode_usize`] returns, plus [`Error::InvalidEncoding`] when
467/// the value is padded with redundant continuation bytes. The cursor is
468/// unchanged on error.
469///
470/// # Example
471///
472/// ```
473/// use wire_codec::{varint, ReadBuf};
474/// let mut buf = ReadBuf::new(&[0x05]);
475/// assert_eq!(varint::decode_usize_canonical(&mut buf), Ok(5));
476/// ```
477#[inline]
478pub fn decode_usize_canonical(buf: &mut ReadBuf<'_>) -> Result<usize> {
479 decode_usize_with(buf, true)
480}
481
482/// Decode a zigzag `i32` varint, rejecting overlong encodings.
483///
484/// # Errors
485///
486/// Same contract as [`decode_u32_canonical`]. The cursor is unchanged on
487/// error.
488///
489/// # Example
490///
491/// ```
492/// use wire_codec::{varint, ReadBuf};
493/// let mut buf = ReadBuf::new(&[0x01]);
494/// assert_eq!(varint::decode_i32_canonical(&mut buf), Ok(-1));
495/// ```
496#[inline]
497pub fn decode_i32_canonical(buf: &mut ReadBuf<'_>) -> Result<i32> {
498 decode_u32_canonical(buf).map(zigzag::decode_i32)
499}
500
501/// Decode a zigzag `i64` varint, rejecting overlong encodings.
502///
503/// # Errors
504///
505/// Same contract as [`decode_u64_canonical`]. The cursor is unchanged on
506/// error.
507///
508/// # Example
509///
510/// ```
511/// use wire_codec::{varint, ReadBuf};
512/// let mut buf = ReadBuf::new(&[0x02]);
513/// assert_eq!(varint::decode_i64_canonical(&mut buf), Ok(1));
514/// ```
515#[inline]
516pub fn decode_i64_canonical(buf: &mut ReadBuf<'_>) -> Result<i64> {
517 decode_u64_canonical(buf).map(zigzag::decode_i64)
518}
519
520/// Encode `value` straight into the unwritten tail of `buf`.
521///
522/// The length is computed up front, so there is a single capacity check and
523/// nothing is written when it fails.
524#[inline(always)]
525fn encode_raw(mut value: u64, buf: &mut WriteBuf<'_>) -> Result<()> {
526 let dst = buf.spare_mut();
527 // With room for the longest encoding the length check is skipped; the
528 // common case (a large output buffer) pays one comparison.
529 if dst.len() < MAX_LEN_U64 && dst.len() < encoded_len_u64(value) {
530 return Err(Error::BufferFull);
531 }
532 let mut i = 0;
533 while value >= 0x80 {
534 // Truncation to the low 7 bits is the encoding itself.
535 dst[i] = (value as u8) | 0x80;
536 value >>= 7;
537 i += 1;
538 }
539 dst[i] = value as u8;
540 buf.commit(i + 1);
541 Ok(())
542}
543
544/// Decode from `buf`, committing the cursor only on success.
545#[inline(always)]
546fn decode_with(buf: &mut ReadBuf<'_>, max_len: usize, bits: u32, canonical: bool) -> Result<u64> {
547 let (value, len) = decode_slice(buf.remaining_slice(), max_len, bits, canonical)?;
548 buf.consume(len);
549 Ok(value)
550}
551
552#[inline(always)]
553fn decode_usize_with(buf: &mut ReadBuf<'_>, canonical: bool) -> Result<usize> {
554 let (value, len) = decode_slice(buf.remaining_slice(), MAX_LEN_U64, u64::BITS, canonical)?;
555 let value = usize::try_from(value).map_err(|_| Error::VarintOverflow)?;
556 buf.consume(len);
557 Ok(value)
558}
559
560/// Core LEB128 decoder over a plain slice.
561///
562/// Returns the decoded value and the number of bytes it occupied. `bits` is
563/// the width of the target type; `max_len` is `ceil(bits / 7)`. The final
564/// byte of a maximum-length encoding may only carry `bits - 7 * (max_len - 1)`
565/// payload bits; anything above that overflows the target.
566#[inline(always)]
567pub(crate) fn decode_slice(
568 bytes: &[u8],
569 max_len: usize,
570 bits: u32,
571 canonical: bool,
572) -> Result<(u64, usize)> {
573 let mut value: u64 = 0;
574 let mut shift: u32 = 0;
575 for i in 0..max_len {
576 let Some(&byte) = bytes.get(i) else {
577 return Err(Error::UnexpectedEof);
578 };
579 value |= u64::from(byte & 0x7F) << shift;
580 if byte & 0x80 == 0 {
581 if i == max_len - 1 && u32::from(byte) >> (bits - shift) != 0 {
582 return Err(Error::VarintOverflow);
583 }
584 if canonical && byte == 0 && i != 0 {
585 return Err(Error::InvalidEncoding);
586 }
587 return Ok((value, i + 1));
588 }
589 shift += 7;
590 }
591 Err(Error::VarintOverflow)
592}
593
594#[cfg(test)]
595mod tests {
596 use super::*;
597
598 fn round_trip_u32(value: u32) {
599 let mut storage = [0u8; MAX_LEN_U32];
600 let mut w = WriteBuf::new(&mut storage);
601 encode_u32(value, &mut w).unwrap();
602 let n = w.position();
603 assert_eq!(n, encoded_len_u32(value));
604 let mut r = ReadBuf::new(&storage[..n]);
605 assert_eq!(decode_u32(&mut r).unwrap(), value);
606 assert!(r.is_empty());
607 let mut r = ReadBuf::new(&storage[..n]);
608 assert_eq!(decode_u32_canonical(&mut r).unwrap(), value);
609 }
610
611 fn round_trip_u64(value: u64) {
612 let mut storage = [0u8; MAX_LEN_U64];
613 let mut w = WriteBuf::new(&mut storage);
614 encode_u64(value, &mut w).unwrap();
615 let n = w.position();
616 assert_eq!(n, encoded_len_u64(value));
617 let mut r = ReadBuf::new(&storage[..n]);
618 assert_eq!(decode_u64(&mut r).unwrap(), value);
619 assert!(r.is_empty());
620 let mut r = ReadBuf::new(&storage[..n]);
621 assert_eq!(decode_u64_canonical(&mut r).unwrap(), value);
622 }
623
624 #[test]
625 fn u32_boundaries() {
626 for &v in &[
627 0u32,
628 1,
629 127,
630 128,
631 16_383,
632 16_384,
633 2_097_151,
634 2_097_152,
635 u32::MAX,
636 ] {
637 round_trip_u32(v);
638 }
639 }
640
641 #[test]
642 fn u64_boundaries() {
643 for &v in &[
644 0u64,
645 127,
646 128,
647 1 << 35,
648 1 << 56,
649 (1 << 63) - 1,
650 1 << 63,
651 u64::MAX,
652 ] {
653 round_trip_u64(v);
654 }
655 }
656
657 #[test]
658 fn u16_round_trip_and_bounds() {
659 for v in [0u16, 1, 127, 128, 16_383, 16_384, u16::MAX] {
660 let mut storage = [0u8; MAX_LEN_U16];
661 let mut w = WriteBuf::new(&mut storage);
662 encode_u16(v, &mut w).unwrap();
663 let n = w.position();
664 assert_eq!(n, encoded_len_u16(v));
665 let mut r = ReadBuf::new(&storage[..n]);
666 assert_eq!(decode_u16(&mut r).unwrap(), v);
667 let mut r = ReadBuf::new(&storage[..n]);
668 assert_eq!(decode_u16_canonical(&mut r).unwrap(), v);
669 }
670 // 0x04 in the third byte is bit 16: one past u16::MAX.
671 let mut r = ReadBuf::new(&[0xFF, 0xFF, 0x04]);
672 assert_eq!(decode_u16(&mut r), Err(Error::VarintOverflow));
673 let mut r = ReadBuf::new(&[0x80, 0x80, 0x80, 0x00]);
674 assert_eq!(decode_u16(&mut r), Err(Error::VarintOverflow));
675 }
676
677 #[test]
678 fn signed_round_trip() {
679 for v in [0i32, 1, -1, 63, -64, 64, -65, i32::MAX, i32::MIN] {
680 let mut storage = [0u8; MAX_LEN_U32];
681 let mut w = WriteBuf::new(&mut storage);
682 encode_i32(v, &mut w).unwrap();
683 let n = w.position();
684 assert_eq!(n, encoded_len_i32(v));
685 assert_eq!(decode_i32(&mut ReadBuf::new(&storage[..n])).unwrap(), v);
686 assert_eq!(
687 decode_i32_canonical(&mut ReadBuf::new(&storage[..n])).unwrap(),
688 v
689 );
690 }
691 for v in [0i64, 1, -1, i64::from(i32::MIN) - 1, i64::MAX, i64::MIN] {
692 let mut storage = [0u8; MAX_LEN_U64];
693 let mut w = WriteBuf::new(&mut storage);
694 encode_i64(v, &mut w).unwrap();
695 let n = w.position();
696 assert_eq!(n, encoded_len_i64(v));
697 assert_eq!(decode_i64(&mut ReadBuf::new(&storage[..n])).unwrap(), v);
698 assert_eq!(
699 decode_i64_canonical(&mut ReadBuf::new(&storage[..n])).unwrap(),
700 v
701 );
702 }
703 }
704
705 #[test]
706 fn usize_round_trip() {
707 for v in [0usize, 1, 300, usize::MAX] {
708 let mut storage = [0u8; MAX_LEN_U64];
709 let mut w = WriteBuf::new(&mut storage);
710 encode_usize(v, &mut w).unwrap();
711 let n = w.position();
712 assert_eq!(n, encoded_len_usize(v));
713 assert_eq!(decode_usize(&mut ReadBuf::new(&storage[..n])).unwrap(), v);
714 assert_eq!(
715 decode_usize_canonical(&mut ReadBuf::new(&storage[..n])).unwrap(),
716 v
717 );
718 }
719 }
720
721 #[test]
722 fn usize_too_wide_for_target_overflows() {
723 // 2^32 encoded as a u64 varint.
724 let bytes = [0x80, 0x80, 0x80, 0x80, 0x10];
725 let mut r = ReadBuf::new(&bytes);
726 let result = decode_usize(&mut r);
727 if usize::BITS > 32 {
728 assert_eq!(result.map(|v| v as u64), Ok(1u64 << 32));
729 } else {
730 assert_eq!(result, Err(Error::VarintOverflow));
731 assert_eq!(r.position(), 0);
732 }
733 }
734
735 #[test]
736 fn decode_u32_overflow_on_sixth_byte() {
737 let mut buf = ReadBuf::new(&[0x80, 0x80, 0x80, 0x80, 0x80, 0x01]);
738 assert_eq!(decode_u32(&mut buf), Err(Error::VarintOverflow));
739 assert_eq!(buf.position(), 0, "cursor is unchanged on error");
740 }
741
742 #[test]
743 fn decode_u32_overflow_in_final_byte() {
744 // Five bytes, terminator carries bits above the 32-bit window.
745 for last in [0x10u8, 0x1F, 0x7F] {
746 let bytes = [0xFF, 0xFF, 0xFF, 0xFF, last];
747 let mut buf = ReadBuf::new(&bytes);
748 assert_eq!(decode_u32(&mut buf), Err(Error::VarintOverflow));
749 }
750 let mut buf = ReadBuf::new(&[0xFF, 0xFF, 0xFF, 0xFF, 0x0F]);
751 assert_eq!(decode_u32(&mut buf), Ok(u32::MAX));
752 }
753
754 #[test]
755 fn decode_u64_final_byte_rules() {
756 let mut bytes = [0xFFu8; MAX_LEN_U64];
757 for last in [0x02u8, 0x03, 0x7F, 0x81, 0x80] {
758 bytes[9] = last;
759 let mut buf = ReadBuf::new(&bytes);
760 assert_eq!(
761 decode_u64(&mut buf),
762 Err(Error::VarintOverflow),
763 "last={last:#x}"
764 );
765 assert_eq!(buf.position(), 0);
766 }
767 bytes[9] = 0x01;
768 assert_eq!(decode_u64(&mut ReadBuf::new(&bytes)), Ok(u64::MAX));
769 bytes[9] = 0x00;
770 // Lenient accepts the overlong form; canonical rejects it.
771 assert_eq!(decode_u64(&mut ReadBuf::new(&bytes)), Ok(u64::MAX >> 1));
772 assert_eq!(
773 decode_u64_canonical(&mut ReadBuf::new(&bytes)),
774 Err(Error::InvalidEncoding)
775 );
776 }
777
778 #[test]
779 fn decode_truncated_leaves_cursor_unchanged() {
780 // Continuation bit set on every byte present.
781 let mut buf = ReadBuf::new(&[0x80, 0x80]);
782 assert_eq!(decode_u32(&mut buf), Err(Error::UnexpectedEof));
783 assert_eq!(buf.position(), 0);
784 let mut buf = ReadBuf::new(&[]);
785 assert_eq!(decode_u64(&mut buf), Err(Error::UnexpectedEof));
786 }
787
788 #[test]
789 fn streaming_retry_after_eof_succeeds() {
790 let wire = [0xAC, 0x02, 0x07];
791 let mut filled = 0;
792 let value = loop {
793 let mut r = ReadBuf::new(&wire[..filled]);
794 match decode_u32(&mut r) {
795 Ok(v) => {
796 assert_eq!(r.position(), 2);
797 break v;
798 }
799 Err(Error::UnexpectedEof) => {
800 assert_eq!(r.position(), 0);
801 filled += 1;
802 }
803 Err(e) => panic!("unexpected {e}"),
804 }
805 };
806 assert_eq!(value, 300);
807 assert_eq!(filled, 2);
808 }
809
810 #[test]
811 fn overlong_forms() {
812 let cases: [&[u8]; 4] = [
813 &[0x80, 0x00],
814 &[0x81, 0x00],
815 &[0x80, 0x80, 0x80, 0x80, 0x00],
816 &[0xFF, 0x80, 0x00],
817 ];
818 for bytes in cases {
819 assert!(decode_u32(&mut ReadBuf::new(bytes)).is_ok());
820 let mut r = ReadBuf::new(bytes);
821 assert_eq!(decode_u32_canonical(&mut r), Err(Error::InvalidEncoding));
822 assert_eq!(r.position(), 0);
823 }
824 // A lone zero byte is the canonical encoding of 0.
825 assert_eq!(decode_u32_canonical(&mut ReadBuf::new(&[0x00])), Ok(0));
826 assert_eq!(
827 decode_usize_canonical(&mut ReadBuf::new(&[0x80, 0x00])),
828 Err(Error::InvalidEncoding)
829 );
830 }
831
832 #[test]
833 fn encode_is_atomic_on_buffer_full() {
834 let mut storage = [0xEEu8; 1];
835 let mut w = WriteBuf::new(&mut storage);
836 assert_eq!(encode_u32(300, &mut w), Err(Error::BufferFull));
837 assert_eq!(w.position(), 0);
838 assert_eq!(storage, [0xEE], "nothing is written on error");
839
840 let mut storage = [0u8; 9];
841 let mut w = WriteBuf::new(&mut storage);
842 assert_eq!(encode_u64(u64::MAX, &mut w), Err(Error::BufferFull));
843 assert_eq!(w.position(), 0);
844
845 let mut storage = [0u8; 0];
846 let mut w = WriteBuf::new(&mut storage);
847 assert_eq!(encode_u16(0, &mut w), Err(Error::BufferFull));
848 assert_eq!(encode_i32(0, &mut w), Err(Error::BufferFull));
849 assert_eq!(encode_i64(0, &mut w), Err(Error::BufferFull));
850 assert_eq!(encode_usize(0, &mut w), Err(Error::BufferFull));
851 }
852
853 #[test]
854 fn exact_wire_bytes() {
855 let mut storage = [0u8; MAX_LEN_U64];
856 let mut w = WriteBuf::new(&mut storage);
857 encode_u64(0x80, &mut w).unwrap();
858 assert_eq!(w.written(), &[0x80, 0x01]);
859 let mut w = WriteBuf::new(&mut storage);
860 encode_u32(u32::MAX, &mut w).unwrap();
861 assert_eq!(w.written(), &[0xFF, 0xFF, 0xFF, 0xFF, 0x0F]);
862 }
863}