Skip to main content

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}