leb128fmt/
lib.rs

1//! Leb128fmt is a library to decode and encode [LEB128][leb128] formatted numbers.
2//! LEB128 is a variable length integer compression format.
3//!
4//! The library does not allocate memory and can be used in `no_std` and
5//! `no_std::no_alloc` environments.
6//!
7//! Various functions are provided which encode and decode signed and unsigned
8//! integers with the number of bits in the function name. There are generic
9//! functions provided to read and write slices of encoded values as well.
10//!
11//! There are encoding functions with the word `fixed` in the name which will
12//! write out a value using the maximum number of bytes for a given bit size.
13//! For instance, using [`encode_fixed_u32`] will always use 5 bytes to
14//! write out the value. While always using the maximum number of bytes removes
15//! the benefit of compression, in some scenarios, it is beneficial to have a
16//! fixed encoding size.
17//!
18//! Finally, there are macros provided which you can use to build your own
19//! encoding and decoding functions for unusual variants like signed 33 bit
20//! values.
21//!
22//! # Examples
23//!
24//! ## Functions using Arrays
25//!
26//! ```rust
27//! // Encode an unsigned 32 bit number:
28//! let (output, written_len) = leb128fmt::encode_u32(43110).unwrap();
29//! // The number of bytes written in the output array
30//! assert_eq!(written_len, 3);
31//! assert_eq!(&output[..written_len], &[0xE6, 0xD0, 0x02]);
32//! // The entire output array. Note you should only use &output[..written_len] to copy
33//! // into your output buffer
34//! assert_eq!(output, [0xE6, 0xD0, 0x02, 0x00, 0x00]);
35//!
36//! // Decode an unsigned 32 bit number:
37//! let input = [0xE6, 0xD0, 0x02, 0x00, 0x00];
38//! let (result, read_len) = leb128fmt::decode_u32(input).unwrap();
39//! assert_eq!(result, 43110);
40//! assert_eq!(read_len, 3);
41//! ```
42//!
43//! ### Helper Functions
44//!
45//! If you are reading from an input buffer, you can use [`is_last`] and
46//! [`max_len`] to determine the bytes to copy into the array.
47//!
48//! ```rust
49//! let buffer = vec![0xFE, 0xFE, 0xE6, 0xD0, 0x02, 0xFE, 0xFE, 0xFE];
50//! let pos = 2;
51//! let end = buffer.iter().skip(pos).copied().position(leb128fmt::is_last).map(|p| pos + p);
52//! if let Some(end) = end {
53//!     if end <= pos + leb128fmt::max_len::<32>() {
54//!         let mut input = [0u8; leb128fmt::max_len::<32>()];
55//!         input[..=end - pos].copy_from_slice(&buffer[pos..=end]);
56//!         let (result, read_len) = leb128fmt::decode_u32(input).unwrap();
57//!         assert_eq!(result, 43110);
58//!         assert_eq!(read_len, 3);
59//!     } else {
60//!         // invalid LEB128 encoding
61//!#        panic!();
62//!     }
63//! } else {
64//!   if buffer.len() - pos < leb128fmt::max_len::<32>() {
65//!      // Need more bytes in the buffer
66//!#     panic!();
67//!   } else {
68//!      // invalid LEB128 encoding
69//!#     panic!();
70//!   }
71//! }
72//!
73//! ```
74//!
75//! ## Functions Using Slices
76//!
77//! ```rust
78//! let mut buffer = vec![0xFE; 10];
79//! let mut pos = 1;
80//!
81//! // Encode an unsigned 64 bit number with a mutable slice:
82//! let result = leb128fmt::encode_uint_slice::<u64, 64>(43110u64, &mut buffer, &mut pos);
83//! // The number of bytes written in the output array
84//! assert_eq!(result, Some(3));
85//! assert_eq!(pos, 4);
86//!
87//! assert_eq!(buffer, [0xFE, 0xE6, 0xD0, 0x02, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]);
88//!
89//! // Decode an unsigned 64 bit number with a slice:
90//! pos = 1;
91//! let result = leb128fmt::decode_uint_slice::<u64, 64>(&buffer, &mut pos);
92//! assert_eq!(result, Ok(43110));
93//! assert_eq!(pos, 4);
94//! ```
95//!
96//! ## Functions Using Fixed Sized Encoding
97//!
98//! There may be several different ways to encode a value. For instance, `0` can
99//! be encoded as 32 bits unsigned:
100//!
101//! ```rust
102//! let mut pos = 0;
103//! assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x00], &mut pos), Ok(0));
104//! pos = 0;
105//! assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x00], &mut pos), Ok(0));
106//! pos = 0;
107//! assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x80, 0x00], &mut pos), Ok(0));
108//! pos = 0;
109//! assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x80, 0x80, 0x00], &mut pos), Ok(0));
110//! pos = 0;
111//! assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x80, 0x80, 0x80, 0x00], &mut pos), Ok(0));
112//! ```
113//!
114//! There are functions provided to encode a value using the maximum number of
115//! bytes possible for a given bit size. Using the maximum number of bytes
116//! removes the benefit of compression, but it may be useful in a few scenarios.
117//!
118//! For instance, if a binary format needs to store the size or offset of some
119//! data before the size of data is known, it can be beneficial to write a fixed
120//! sized `0` placeholder value first. Then, once the real value is known, the
121//! `0` placeholder can be overwritten without moving other bytes. The real
122//! value is also written out using the fixed maximum number of bytes.
123//!
124//! ```rust
125//! // Encode an unsigned 32 bit number with all 5 bytes:
126//! let output  = leb128fmt::encode_fixed_u32(43110).unwrap();
127//! assert_eq!(output, [0xE6, 0xD0, 0x82, 0x80, 0x00]);
128//!
129//! // Decode an unsigned 32 bit number:
130//! let input = output;
131//! let (result, read_len) = leb128fmt::decode_u32(input).unwrap();
132//! assert_eq!(result, 43110);
133//!
134//! // Note that all 5 bytes are read
135//! assert_eq!(read_len, 5);
136//! ```
137//!
138//! [leb128]: https://en.wikipedia.org/wiki/LEB128
139
140#![cfg_attr(not(feature = "std"), no_std)]
141#![cfg_attr(docsrs, feature(doc_cfg))]
142#![warn(
143    missing_copy_implementations,
144    missing_debug_implementations,
145    missing_docs,
146    rust_2018_idioms,
147    unused_lifetimes,
148    unused_qualifications
149)]
150
151use core::fmt;
152
153/// Returns the maximum byte length that is used to encode a value for a given
154/// number of `BITS`.
155///
156/// A value can possibly be encoded with a fewer number of bytes.
157///
158/// # Example
159///
160/// ```rust
161/// assert_eq!(5, leb128fmt::max_len::<32>());
162/// assert_eq!(10, leb128fmt::max_len::<64>());
163///
164/// assert_eq!(5, leb128fmt::max_len::<33>());
165/// ```
166#[inline]
167#[must_use]
168pub const fn max_len<const BITS: u32>() -> usize {
169    let rem = if BITS % 7 == 0 { 0 } else { 1 };
170    ((BITS / 7) + rem) as usize
171}
172
173/// Returns true if this is the last byte in an encoded LEB128 value.
174///
175/// # Example
176///
177/// ```rust
178/// let bytes = &[0x42, 0x8F, 0xFF, 0x7F, 0xFF];
179/// let pos = 1;
180/// let end = bytes.iter().skip(pos).copied().position(leb128fmt::is_last);
181/// let end = end.unwrap();
182/// assert_eq!(pos + end, 3);
183/// let value = &bytes[pos..=pos + end];
184/// ```
185#[inline]
186#[must_use]
187pub const fn is_last(byte: u8) -> bool {
188    byte & 0x80 == 0
189}
190
191/// Builds custom unsigned integer encode functions.
192///
193/// The macro's 3 parameters are:
194///
195/// 1. The name of the function.
196/// 2. The type to return.
197/// 3. The number of encoded BITS to decode.
198///
199/// ```rust
200/// leb128fmt::encode_uint_arr!(encode_u33, u64, 33);
201///
202/// let result = encode_u33(0);
203/// assert_eq!(Some(([0x00, 0x00, 0x00, 0x00, 0x00], 1)), result);
204///
205/// let result = encode_u33(8589934591);
206/// assert_eq!(Some(([0xFF, 0xFF, 0xFF, 0xFF, 0x1F], 5)), result);
207/// ```
208#[macro_export]
209macro_rules! encode_uint_arr {
210    ($func:ident, $num_ty:ty, $bits:literal) => {
211        /// Encodes a value as an unsigned LEB128 number.
212        ///
213        /// If the value can be encoded in the given number of bits, then return
214        /// the encoded output and the index after the last byte written.
215        ///
216        /// If the value cannot be encoded with the given number of bits, then return None.
217        #[must_use]
218        pub const fn $func(
219            mut value: $num_ty,
220        ) -> Option<(
221            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
222            usize,
223        )> {
224            const BITS: u32 = $bits;
225            if <$num_ty>::BITS > BITS && 1 < value >> BITS - 1 {
226                return None;
227            }
228
229            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
230            let mut index = 0;
231            loop {
232                let mut b = (value & 0x7f) as u8;
233
234                value >>= 7;
235                let done = value == 0;
236
237                if !done {
238                    b |= 0x80;
239                }
240
241                output[index] = b;
242                index += 1;
243
244                if done {
245                    return Some((output, index));
246                }
247            }
248        }
249    };
250}
251
252encode_uint_arr!(encode_u32, u32, 32);
253encode_uint_arr!(encode_u64, u64, 64);
254
255/// Builds custom unsigned integer encode functions with the max byte length of
256/// byte arrays used.
257///
258/// The macro's 3 parameters are:
259///
260/// 1. The name of the function.
261/// 2. The type to return.
262/// 3. The number of encoded BITS to decode.
263///
264/// ```rust
265/// leb128fmt::encode_fixed_uint_arr!(encode_fixed_u33, u64, 33);
266///
267/// let output = encode_fixed_u33(0);
268/// assert_eq!(Some([0x80, 0x80, 0x80, 0x80, 0x00]), output);
269///
270/// let output = encode_fixed_u33(8589934591);
271/// assert_eq!(Some([0xFF, 0xFF, 0xFF, 0xFF, 0x1F]), output);
272/// ```
273#[macro_export]
274macro_rules! encode_fixed_uint_arr {
275    ($func:ident, $num_ty:ty, $bits:literal) => {
276        /// Encodes an unsigned LEB128 number with using the maximum number of
277        /// bytes for the given bits length.
278        ///
279        /// If the value can be encoded in the given number of bits, then return
280        /// the encoded value.
281        ///
282        /// If the value cannot be encoded with the given number of bits, then return None.
283        #[must_use]
284        pub const fn $func(
285            value: $num_ty,
286        ) -> Option<[u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize]> {
287            const BITS: u32 = $bits;
288            if <$num_ty>::BITS > BITS && 1 < value >> BITS - 1 {
289                return None;
290            }
291
292            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
293
294            let mut index = 0;
295            let mut shift: u32 = 0;
296            loop {
297                let v = value >> shift;
298
299                let mut b = (v & 0x7f) as u8;
300
301                let done = shift == BITS - (BITS % 7);
302
303                if !done {
304                    b |= 0x80;
305                }
306
307                output[index] = b;
308                index += 1;
309                shift += 7;
310
311                if done {
312                    return Some(output);
313                }
314            }
315        }
316    };
317}
318
319encode_fixed_uint_arr!(encode_fixed_u32, u32, 32);
320encode_fixed_uint_arr!(encode_fixed_u64, u64, 64);
321
322/// Builds custom unsigned integer decode functions.
323///
324/// The macro's 3 parameters are:
325///
326/// 1. The name of the function.
327/// 2. The type to return.
328/// 3. The number of encoded BITS to decode.
329///
330/// ```rust
331/// leb128fmt::decode_uint_arr!(decode_u33, u64, 33);
332///
333/// let input = [0xFF, 0xFF, 0xFF, 0xFF, 0x1F];
334/// let result = decode_u33(input);
335/// assert_eq!(Some((8589934591, 5)), result);
336/// ```
337#[macro_export]
338macro_rules! decode_uint_arr {
339    ($func:ident, $num_ty:ty, $bits:literal) => {
340        /// Decodes an unsigned LEB128 number.
341        ///
342        /// If there is a valid encoded value, returns the decoded value and the
343        /// index after the last byte read.
344        ///
345        /// If the encoding is incorrect, returns `None`.
346        ///
347        /// If the size in bits of the returned type is less than the size of the value in bits, returns `None`.
348        /// For instance, if 33 bits are being decoded, then the returned type must be at least a `u64`.
349        #[must_use]
350        pub const fn $func(
351            input: [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
352        ) -> Option<($num_ty, usize)> {
353            const BITS: u32 = $bits;
354            if <$num_ty>::BITS < BITS {
355                return None;
356            }
357
358            let n = input[0];
359            if n & 0x80 == 0 {
360                return Some((n as $num_ty, 1));
361            }
362
363            let mut result = (n & 0x7f) as $num_ty;
364            let mut shift = 7;
365            let mut pos = 1;
366            loop {
367                let n = input[pos];
368
369                // If unnecessary bits are set (the bits would be dropped when
370                // the value is shifted), then return an error.
371                //
372                // This error may be too strict.
373                //
374                // There should be at least a simple check to quickly
375                // determine that the decoding has failed instead of
376                // misinterpreting further data.
377                //
378                // For a less strict check, the && condition could be:
379                //
380                // (n & 0x80) != 0
381                //
382                // Another stricter condition is if the last byte has a 0 value.
383                // The encoding is correct but not the minimal number of bytes
384                // was used to express the final value.
385                if shift == BITS - (BITS % 7) && 1 << (BITS % 7) <= n {
386                    return None;
387                }
388
389                if n & 0x80 == 0 {
390                    result |= (n as $num_ty) << shift;
391                    return Some((result, pos + 1));
392                }
393
394                result |= ((n & 0x7f) as $num_ty) << shift;
395                shift += 7;
396                pos += 1;
397            }
398        }
399    };
400}
401
402decode_uint_arr!(decode_u32, u32, 32);
403decode_uint_arr!(decode_u64, u64, 64);
404
405mod private {
406    pub trait Sealed {}
407
408    impl Sealed for u8 {}
409    impl Sealed for u16 {}
410    impl Sealed for u32 {}
411    impl Sealed for u64 {}
412    impl Sealed for u128 {}
413
414    impl Sealed for i8 {}
415    impl Sealed for i16 {}
416    impl Sealed for i32 {}
417    impl Sealed for i64 {}
418    impl Sealed for i128 {}
419}
420
421/// Sealed trait for supported unsigned integer types.
422pub trait UInt: private::Sealed {
423    /// Size of the type in bits.
424    const BITS: u32;
425}
426
427impl UInt for u8 {
428    const BITS: u32 = u8::BITS;
429}
430
431impl UInt for u16 {
432    const BITS: u32 = u16::BITS;
433}
434
435impl UInt for u32 {
436    const BITS: u32 = u32::BITS;
437}
438
439impl UInt for u64 {
440    const BITS: u32 = u64::BITS;
441}
442
443impl UInt for u128 {
444    const BITS: u32 = u128::BITS;
445}
446
447#[derive(Debug, Clone, PartialEq, Eq)]
448enum InnerError {
449    NeedMoreBytes,
450    InvalidEncoding,
451}
452
453/// Error when decoding a LEB128 value.
454#[derive(Debug, Clone, PartialEq, Eq)]
455pub struct Error(InnerError);
456
457impl fmt::Display for Error {
458    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459        match self.0 {
460            InnerError::NeedMoreBytes => f.write_str("need more bytes"),
461            InnerError::InvalidEncoding => f.write_str("invalid encoding"),
462        }
463    }
464}
465
466#[cfg(feature = "std")]
467impl std::error::Error for Error {
468    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
469        None
470    }
471}
472
473impl Error {
474    /// If more bytes are needed in the slice to decode the value
475    #[inline]
476    #[must_use]
477    pub const fn is_more_bytes_needed(&self) -> bool {
478        matches!(self.0, InnerError::NeedMoreBytes)
479    }
480
481    /// If the value has an invalid encoding
482    #[inline]
483    #[must_use]
484    pub const fn is_invalid_encoding(&self) -> bool {
485        matches!(self.0, InnerError::InvalidEncoding)
486    }
487}
488
489/// Encodes a given value into an output slice using the fixed set of bytes.
490///
491/// # Examples
492///
493/// ```rust
494/// let mut buffer = vec![254; 10];
495/// let mut pos = 0;
496/// let result = leb128fmt::encode_uint_slice::<_, 32>(0u32, &mut buffer, &mut pos);
497/// assert_eq!(Some(1), result);
498/// assert_eq!(1, pos);
499/// assert_eq!(&[0x00], &buffer[..pos]);
500///
501/// assert_eq!(&[0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
502///
503/// let result = leb128fmt::encode_uint_slice::<_, 32>(u32::MAX, &mut buffer, &mut pos);
504/// assert_eq!(Some(5), result);
505/// assert_eq!(6, pos);
506/// assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF, 0x0F], &buffer[1..pos]);
507///
508/// assert_eq!(&[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
509///
510/// // Will try to encode even if the output slice is not as big as the maximum
511/// // number of bytes required to output every value for the given BITS
512/// let mut buffer = vec![254; 4];
513/// let mut pos = 0;
514/// let result = leb128fmt::encode_uint_slice::<_, 32>(1028u32, &mut buffer, &mut pos);
515/// assert_eq!(Some(2), result);
516/// assert_eq!(&[0x84, 0x08, 0xFE, 0xFE], buffer.as_slice());
517///
518/// // Will return `None` if the output buffer is not long enough but will have partially written
519/// // the value
520/// let mut buffer = vec![254; 4];
521/// let mut pos = 0;
522/// let result = leb128fmt::encode_uint_slice::<_, 32>(u32::MAX, &mut buffer, &mut pos);
523/// assert_eq!(None, result);
524/// assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF], buffer.as_slice());
525///
526/// // Will return `None` if the given value cannot be encoded with the given number of bits.
527/// let mut buffer = vec![254; 10];
528/// let mut pos = 0;
529/// let result = leb128fmt::encode_uint_slice::<_, 32>(u64::MAX, &mut buffer, &mut pos);
530/// assert_eq!(None, result);
531/// assert_eq!(&[0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
532/// ```
533#[allow(clippy::manual_let_else)]
534pub fn encode_uint_slice<T, const BITS: u32>(
535    mut value: T,
536    output: &mut [u8],
537    pos: &mut usize,
538) -> Option<usize>
539where
540    T: Copy
541        + PartialEq
542        + core::ops::BitAnd
543        + core::ops::Shr<u32>
544        + core::ops::ShrAssign<u32>
545        + From<u8>
546        + UInt,
547    <T as core::ops::Shr<u32>>::Output: PartialEq<T>,
548    u8: TryFrom<<T as core::ops::BitAnd<T>>::Output>,
549{
550    if BITS < T::BITS && value >> BITS != T::from(0) {
551        return None;
552    }
553
554    let mut index = *pos;
555    loop {
556        if output.len() <= index {
557            return None;
558        }
559
560        let mut b = match u8::try_from(value & T::from(0x7f)) {
561            Ok(b) => b,
562            Err(_) => unreachable!(),
563        };
564
565        value >>= 7;
566
567        let done = value == T::from(0);
568
569        if !done {
570            b |= 0x80;
571        }
572
573        output[index] = b;
574        index += 1;
575
576        if done {
577            let len = index - *pos;
578            *pos = index;
579            return Some(len);
580        }
581    }
582}
583
584/// Encodes a given value into an output slice using a fixed set of bytes.
585///
586/// # Examples
587///
588/// ```rust
589/// let mut buffer = vec![254; 10];
590/// let mut pos = 0;
591/// let result = leb128fmt::encode_fixed_uint_slice::<_, 32>(0u32, &mut buffer, &mut pos);
592/// assert_eq!(Some(5), result);
593/// assert_eq!(5, pos);
594/// assert_eq!(&[0x80, 0x80, 0x80, 0x80, 0x00], &buffer[..pos]);
595///
596/// assert_eq!(&[0x80, 0x80, 0x80, 0x80, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
597///
598/// let result = leb128fmt::encode_fixed_uint_slice::<_, 32>(u32::MAX, &mut buffer, &mut pos);
599/// assert_eq!(Some(5), result);
600/// assert_eq!(10, pos);
601/// assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF, 0x0F], &buffer[5..pos]);
602///
603/// assert_eq!(&[0x80, 0x80, 0x80, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F], buffer.as_slice());
604///
605/// // Will return `None` if the output buffer is not long enough.
606/// let mut buffer = vec![254; 4];
607/// let mut pos = 0;
608/// let result = leb128fmt::encode_fixed_uint_slice::<_, 32>(u32::MAX, &mut buffer, &mut pos);
609/// assert_eq!(None, result);
610/// assert_eq!(&[0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
611///
612/// // Will return `None` if the given value cannot be encoded with the given number of bits.
613/// let mut buffer = vec![254; 10];
614/// let mut pos = 0;
615/// let result = leb128fmt::encode_fixed_uint_slice::<_, 32>(u64::MAX, &mut buffer, &mut pos);
616/// assert_eq!(None, result);
617/// assert_eq!(&[0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
618/// ```
619#[allow(clippy::manual_let_else)]
620pub fn encode_fixed_uint_slice<T, const BITS: u32>(
621    mut value: T,
622    output: &mut [u8],
623    pos: &mut usize,
624) -> Option<usize>
625where
626    T: Copy + core::ops::BitAnd + core::ops::Shr<u32> + core::ops::ShrAssign<u32> + From<u8> + UInt,
627    <T as core::ops::Shr<u32>>::Output: PartialEq<T>,
628    u8: TryFrom<<T as core::ops::BitAnd>::Output>,
629{
630    if BITS < T::BITS && value >> BITS != T::from(0) {
631        return None;
632    }
633
634    if output[*pos..].len() < max_len::<BITS>() {
635        return None;
636    }
637
638    let mut index = *pos;
639    for _ in 0..(max_len::<BITS>() - 1) {
640        let mut b = match u8::try_from(value & T::from(0x7f)) {
641            Ok(b) => b,
642            Err(_) => unreachable!(),
643        };
644
645        b |= 0x80;
646
647        value >>= 7;
648
649        output[index] = b;
650        index += 1;
651    }
652
653    let b = match u8::try_from(value & T::from(0x7f)) {
654        Ok(b) => b,
655        Err(_) => unreachable!(),
656    };
657    output[index] = b;
658    index += 1;
659
660    let len = index - *pos;
661    *pos = index;
662    Some(len)
663}
664
665/// Decodes an unsigned integer from a slice of bytes and starting at a given position.
666///
667/// # Errors
668///
669/// Returns an error if the value is not properly encoded or if more bytes are
670/// needed to decode the value.
671///
672/// # Panics
673///
674/// Panics if the size in bits of the returned type is less than the size of the value in bits.
675/// For instance, if 33 bits are being decoded, then the returned type must be at least a `u64`.
676///
677/// ```rust
678/// let input = [0x42, 0x8F, 0xFF, 0x7F, 0xFF];
679/// let mut pos = 1;
680/// let result = leb128fmt::decode_uint_slice::<u32, 32>(&input, &mut pos);
681/// assert_eq!(result, Ok(2097039));
682/// assert_eq!(pos, 4);
683/// ```
684pub fn decode_uint_slice<T, const BITS: u32>(input: &[u8], pos: &mut usize) -> Result<T, Error>
685where
686    T: core::ops::Shl<u32, Output = T> + core::ops::BitOrAssign + From<u8> + UInt,
687{
688    assert!(BITS <= T::BITS);
689    if input.len() <= *pos {
690        return Err(Error(InnerError::NeedMoreBytes));
691    }
692
693    let n = input[*pos];
694    if is_last(n) {
695        *pos += 1;
696        return Ok(T::from(n));
697    }
698
699    let mut result = T::from(n & 0x7f);
700    let mut shift: u32 = 7;
701
702    let mut idx = *pos + 1;
703    loop {
704        if input.len() <= idx {
705            return Err(Error(InnerError::NeedMoreBytes));
706        }
707
708        let n = input[idx];
709
710        // If unnecessary bits are set (the bits would be dropped when
711        // the value is shifted), then return an error.
712        //
713        // This error may be too strict.
714        //
715        // There should be at least a simple check to quickly
716        // determine that the decoding has failed instead of
717        // misinterpreting further data.
718        //
719        // For a less strict check, the && condition could be:
720        //
721        // (n & 0x80) != 0
722        //
723        // Another stricter condition is if the last byte has a 0 value.
724        // The encoding is correct but not the minimal number of bytes
725        // was used to express the final value.
726        if shift == BITS - (BITS % 7) && 1 << (BITS % 7) <= n {
727            return Err(Error(InnerError::InvalidEncoding));
728        }
729
730        if is_last(n) {
731            result |= T::from(n) << shift;
732            *pos = idx + 1;
733            return Ok(result);
734        }
735
736        result |= T::from(n & 0x7f) << shift;
737        shift += 7;
738        idx += 1;
739    }
740}
741
742/// Builds custom signed integer encode functions.
743///
744/// The macro's 3 parameters are:
745///
746/// 1. The name of the function.
747/// 2. The type to return.
748/// 3. The number of encoded BITS to decode.
749///
750/// ```rust
751/// leb128fmt::encode_sint_arr!(encode_s33, i64, 33);
752///
753/// let result = encode_s33(0);
754/// assert_eq!(Some(([0x00, 0x00, 0x00, 0x00, 0x00], 1)), result);
755///
756/// let result = encode_s33(4_294_967_295);
757/// assert_eq!(Some(([0xFF, 0xFF, 0xFF, 0xFF, 0x0F], 5)), result);
758///
759/// let result = encode_s33(-4_294_967_296);
760/// assert_eq!(Some(([0x80, 0x80, 0x80, 0x80, 0x70], 5)), result);
761///
762/// let result = encode_s33(-1);
763/// assert_eq!(Some(([0x7F, 0x00, 0x00, 0x00, 0x00], 1)), result);
764/// ```
765#[macro_export]
766macro_rules! encode_sint_arr {
767    ($func:ident, $num_ty:ty, $bits:literal) => {
768        /// Encodes a value as a signed LEB128 number.
769        #[must_use]
770        pub fn $func(
771            mut value: $num_ty,
772        ) -> Option<(
773            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
774            usize,
775        )> {
776            const BITS: u32 = $bits;
777            if BITS < <$num_ty>::BITS {
778                let v: $num_ty = value >> BITS - 1;
779                if v != 0 && v != -1 {
780                    return None;
781                }
782            }
783
784            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
785            let mut index = 0;
786            loop {
787                let b = (value & 0x7f) as u8;
788
789                value >>= 7;
790
791                if (value == 0 && b & 0x40 == 0) || (value == -1 && (b & 0x40) != 0) {
792                    output[index] = b;
793                    return Some((output, index + 1));
794                }
795
796                output[index] = b | 0x80;
797                index += 1;
798            }
799        }
800    };
801}
802
803encode_sint_arr!(encode_s32, i32, 32);
804encode_sint_arr!(encode_s64, i64, 64);
805
806/// Builds custom signed integer encode functions with the max byte length of
807/// byte arrays used.
808///
809/// The macro's 3 parameters are:
810///
811/// 1. The name of the function.
812/// 2. The type to return.
813/// 3. The number of encoded BITS to decode.
814///
815/// ```rust
816/// leb128fmt::encode_fixed_sint_arr!(encode_fixed_s33, i64, 33);
817///
818/// let result = encode_fixed_s33(0);
819/// assert_eq!(Some([0x80, 0x80, 0x80, 0x80, 0x00]), result);
820///
821/// let result = encode_fixed_s33(4_294_967_295);
822/// assert_eq!(Some([0xFF, 0xFF, 0xFF, 0xFF, 0x0F]), result);
823///
824/// let result = encode_fixed_s33(-4_294_967_296);
825/// assert_eq!(Some([0x80, 0x80, 0x80, 0x80, 0x70]), result);
826///
827/// let result = encode_fixed_s33(-1);
828/// assert_eq!(Some([0xFF, 0xFF, 0xFF, 0xFF, 0x7F]), result);
829/// ```
830#[macro_export]
831macro_rules! encode_fixed_sint_arr {
832    ($func:ident, $num_ty:ty, $bits:literal) => {
833        /// Encodes a value as a signed LEB128 number.
834        #[must_use]
835        pub const fn $func(
836            mut value: $num_ty,
837        ) -> Option<[u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize]> {
838            const BITS: u32 = $bits;
839            if BITS < <$num_ty>::BITS {
840                let v = value >> BITS - 1;
841                if v != 0 && v != -1 {
842                    return None;
843                }
844            }
845
846            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
847            let mut index = 0;
848            let mut extend_negative = false;
849            loop {
850                let b = (value & 0x7f) as u8;
851
852                value >>= 7;
853
854                output[index] = b | 0x80;
855                index += 1;
856
857                if value == 0 && b & 0x40 == 0 {
858                    break;
859                }
860                if value == -1 && (b & 0x40) != 0 {
861                    extend_negative = true;
862                    break;
863                }
864            }
865
866            loop {
867                if index == output.len() {
868                    output[index - 1] &= 0x7F;
869                    return Some(output);
870                }
871
872                if extend_negative {
873                    output[index] = 0xFF;
874                } else {
875                    output[index] = 0x80;
876                }
877
878                index += 1;
879            }
880        }
881    };
882}
883
884encode_fixed_sint_arr!(encode_fixed_s32, i32, 32);
885encode_fixed_sint_arr!(encode_fixed_s64, i64, 64);
886
887/// Builds custom signed integer decode functions.
888///
889/// The macro's 3 parameters are:
890///
891/// 1. The name of the function.
892/// 2. The type to return.
893/// 3. The number of encoded BITS to decode.
894///
895/// ```rust
896/// leb128fmt::decode_sint_arr!(decode_s33, i64, 33);
897///
898/// let input = [0xFF, 0xFF, 0xFF, 0xFF, 0x0F];
899/// let result = decode_s33(input);
900/// assert_eq!(Some((4_294_967_295, 5)), result);
901///
902/// let input = [0x7F, 0x00, 0x00, 0x00, 0x00];
903/// let result = decode_s33(input);
904/// assert_eq!(Some((-1, 1)), result);
905///
906/// let input = [0xFF, 0xFF, 0xFF, 0xFF, 0x7F];
907/// let result = decode_s33(input);
908/// assert_eq!(Some((-1, 5)), result);
909///
910/// let input = [0xFF, 0xFF, 0xFF, 0xFF, 0x1F];
911/// let result = decode_s33(input);
912/// assert_eq!(None, result);
913/// ```
914#[macro_export]
915macro_rules! decode_sint_arr {
916    ($func:ident, $num_ty:ty, $bits:literal) => {
917        /// Decodes an unsigned LEB128 number.
918        ///
919        /// If there is a valid encoded value, returns the decoded value and the
920        /// index after the last byte read.
921        ///
922        /// If the encoding is incorrect, returns `None`.
923        ///
924        /// If the size in bits of the returned type is less than the size of the value in bits, returns `None`.
925        /// For instance, if 33 bits are being decoded, then the returned type must be at least a `u64`.
926        #[must_use]
927        pub const fn $func(
928            input: [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
929        ) -> Option<($num_ty, usize)> {
930            const BITS: u32 = $bits;
931            if <$num_ty>::BITS < BITS {
932                return None;
933            }
934
935            let mut result = 0;
936            let mut shift = 0;
937            let mut n;
938            let mut pos = 0;
939
940            loop {
941                n = input[pos];
942                let more = n & 0x80 != 0;
943
944                // For the last valid shift, perform some checks to ensure the
945                // encoding is valid.
946                //
947                // Notably, the one bit that MUST NOT be set is the high order bit
948                // indicating there are more bytes to decode.
949                //
950                // For a signed integer, depending on if the value is positive or negative,
951                // some bits SHOULD or SHOULD NOT be set.
952                //
953                // The expectation is that if this is a negative number, then
954                // there should have been a sign extension so that all the bits
955                // greater than the highest order bit is a 1.
956                //
957                // 32-bit
958                // ------
959                //
960                // The maximum shift value is 28 meaning a 32-bit number is
961                // encoded in a maximum of 5 bytes. If the shift value is 35 or
962                // greater, then, the byte's value will be shifted out beyond the
963                // 32-bit value.
964                //
965                // With 28 being the highest valid shift value, the highest
966                // order relevant bit in the final byte should be 0x08 or:
967                //
968                // 0000 1000
969                //
970                // Any higher bit is "lost" during the bitshift.
971                //
972                // Due to the encoding rules and two's complement, if the
973                // highest order relevant bit is set, then the number is
974                // negative and the `1` is extended to the higher bits like:
975                //
976                // 0111 1000
977                //
978                // Note that the highest order bit (the first bit from left to right)
979                // MUST BE a 0. It is the bit which indicates more bytes should
980                // be processed. For the maximum final byte (byte #5 for a
981                // 32-bit number)), it MUST be 0. There are no additional bytes
982                // to decode.
983                //
984                // If the highest order relevant bit is not set, then the
985                // integer is positive. Any of the lower bits can be set.
986                //
987                // 0000 0111
988                //
989                // So the conditions to check are:
990                //
991                // 1. The highest order bit is not set (so there are no more
992                //    bytes to decode). If it is set, the encoding is invalid.
993                //    This is the "more" check.
994                //
995                // 2. Determine if any sign extended negative bit is set.
996                //    So is any bit in:
997                //
998                //    0111 1000
999                //
1000                //    set. If none of the bits are set, then the number is
1001                //    positive, and the encoding is valid.
1002                //    This is the "(n & mask != 0)" check.
1003                // 3. If any sign extended negative bits are set, the number is
1004                //    negative, and ALL of the bits MUST be set for a valid negative number.
1005                //    This is the "(n < mask)"" check.
1006                //    An equivalent check would be that "(n < mask) || (n >= 0x80)"
1007                //    But the earlier check for "more" removes the need for the additional check.
1008                //
1009                //    The check could also be "(n & mask) != mask".
1010                //
1011                // Another stricter condition is if the last byte has a 0 value.
1012                // The encoding is correct but not the minimal number of bytes
1013                // was used to express the final value.
1014                if shift == BITS - (BITS % 7) {
1015                    #[allow(clippy::cast_sign_loss)]
1016                    let mask = ((-1i8 << ((BITS % 7).saturating_sub(1))) & 0x7f) as u8;
1017                    if more || (n & mask != 0 && n < mask) {
1018                        return None;
1019                    }
1020                }
1021
1022                result |= ((n & 0x7f) as $num_ty) << shift;
1023                shift += 7;
1024                pos += 1;
1025
1026                if !more {
1027                    break;
1028                }
1029            }
1030
1031            if shift < <$num_ty>::BITS && n & 0x40 != 0 {
1032                result |= -1 << shift;
1033            }
1034
1035            Some((result, pos))
1036        }
1037    };
1038}
1039
1040decode_sint_arr!(decode_s32, i32, 32);
1041decode_sint_arr!(decode_s64, i64, 64);
1042
1043/// Sealed trait for supported signed integer types.
1044pub trait SInt: private::Sealed {
1045    /// Size of the type in bits.
1046    const BITS: u32;
1047}
1048
1049impl SInt for i8 {
1050    const BITS: u32 = i8::BITS;
1051}
1052
1053impl SInt for i16 {
1054    const BITS: u32 = i16::BITS;
1055}
1056
1057impl SInt for i32 {
1058    const BITS: u32 = i32::BITS;
1059}
1060
1061impl SInt for i64 {
1062    const BITS: u32 = i64::BITS;
1063}
1064
1065impl SInt for i128 {
1066    const BITS: u32 = i128::BITS;
1067}
1068
1069/// Encodes a given value into an output slice using the fixed set of bytes.
1070///
1071/// # Examples
1072///
1073/// ```rust
1074/// let mut buffer = vec![254; 10];
1075/// let mut pos = 0;
1076/// let result = leb128fmt::encode_sint_slice::<_, 32>(0i32, &mut buffer, &mut pos);
1077/// assert_eq!(Some(1), result);
1078/// assert_eq!(1, pos);
1079/// assert_eq!(&[0x00], &buffer[..pos]);
1080///
1081/// assert_eq!(&[0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
1082///
1083/// let result = leb128fmt::encode_sint_slice::<_, 32>(i32::MAX, &mut buffer, &mut pos);
1084/// assert_eq!(Some(5), result);
1085/// assert_eq!(6, pos);
1086/// assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF, 0x07], &buffer[1..pos]);
1087///
1088/// assert_eq!(&[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
1089///
1090/// // Will try to encode even if the output slice is not as big as the maximum
1091/// // number of bytes required to output every value for the given BITS
1092/// let mut buffer = vec![254; 4];
1093/// let mut pos = 0;
1094/// let result = leb128fmt::encode_sint_slice::<_, 32>(1028i32, &mut buffer, &mut pos);
1095/// assert_eq!(Some(2), result);
1096/// assert_eq!(&[0x84, 0x08, 0xFE, 0xFE], buffer.as_slice());
1097///
1098/// // Will return `None` if the output buffer is not long enough but will have partially written
1099/// // the value
1100/// let mut buffer = vec![254; 4];
1101/// let mut pos = 0;
1102/// let result = leb128fmt::encode_sint_slice::<_, 32>(i32::MAX, &mut buffer, &mut pos);
1103/// assert_eq!(None, result);
1104/// assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF], buffer.as_slice());
1105///
1106/// // Will return `None` if the given value cannot be encoded with the given number of bits.
1107/// let mut buffer = vec![254; 10];
1108/// let mut pos = 0;
1109/// let result = leb128fmt::encode_sint_slice::<_, 32>(i64::MAX, &mut buffer, &mut pos);
1110/// assert_eq!(None, result);
1111/// assert_eq!(&[0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
1112/// ```
1113#[allow(clippy::manual_let_else)]
1114pub fn encode_sint_slice<T, const BITS: u32>(
1115    mut value: T,
1116    output: &mut [u8],
1117    pos: &mut usize,
1118) -> Option<usize>
1119where
1120    T: Copy
1121        + PartialEq
1122        + core::ops::BitAnd
1123        + core::ops::Shr<u32>
1124        + core::ops::ShrAssign<u32>
1125        + From<i8>
1126        + SInt,
1127    <T as core::ops::Shr<u32>>::Output: PartialEq<T>,
1128    u8: TryFrom<<T as core::ops::BitAnd<T>>::Output>,
1129{
1130    if BITS < T::BITS {
1131        let v = value >> BITS;
1132        if v != T::from(0) && v != T::from(-1) {
1133            return None;
1134        }
1135    }
1136
1137    let mut index = *pos;
1138    loop {
1139        if output.len() <= index {
1140            return None;
1141        }
1142
1143        let b = match u8::try_from(value & T::from(0x7f)) {
1144            Ok(b) => b,
1145            Err(_) => unreachable!(),
1146        };
1147
1148        value >>= 7;
1149
1150        if (value == T::from(0) && b & 0x40 == 0) || (value == T::from(-1) && (b & 0x40) != 0) {
1151            output[index] = b;
1152            index += 1;
1153            let len = index - *pos;
1154            *pos = index;
1155            return Some(len);
1156        }
1157
1158        output[index] = b | 0x80;
1159        index += 1;
1160    }
1161}
1162
1163/// Encodes a given value into an output slice using a fixed set of bytes.
1164///
1165/// # Examples
1166///
1167/// ```rust
1168/// let mut buffer = vec![254; 10];
1169/// let mut pos = 0;
1170/// let result = leb128fmt::encode_fixed_sint_slice::<_, 32>(0i32, &mut buffer, &mut pos);
1171/// assert_eq!(Some(5), result);
1172/// assert_eq!(5, pos);
1173/// assert_eq!(&[0x80, 0x80, 0x80, 0x80, 0x00], &buffer[..pos]);
1174///
1175/// assert_eq!(&[0x80, 0x80, 0x80, 0x80, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
1176///
1177/// let result = leb128fmt::encode_fixed_sint_slice::<_, 32>(i32::MAX, &mut buffer, &mut pos);
1178/// assert_eq!(Some(5), result);
1179/// assert_eq!(10, pos);
1180/// assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF, 0x07], &buffer[5..pos]);
1181///
1182/// assert_eq!(&[0x80, 0x80, 0x80, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07], buffer.as_slice());
1183///
1184/// // Will return `None` if the output buffer is not long enough.
1185/// let mut buffer = vec![254; 4];
1186/// let mut pos = 0;
1187/// let result = leb128fmt::encode_fixed_sint_slice::<_, 32>(i32::MAX, &mut buffer, &mut pos);
1188/// assert_eq!(None, result);
1189/// assert_eq!(&[0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
1190///
1191/// // Will return `None` if the given value cannot be encoded with the given number of bits.
1192/// let mut buffer = vec![254; 10];
1193/// let mut pos = 0;
1194/// let result = leb128fmt::encode_fixed_sint_slice::<_, 32>(i64::MAX, &mut buffer, &mut pos);
1195/// assert_eq!(None, result);
1196/// assert_eq!(&[0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], buffer.as_slice());
1197/// ```
1198#[allow(clippy::manual_let_else)]
1199pub fn encode_fixed_sint_slice<T, const BITS: u32>(
1200    mut value: T,
1201    output: &mut [u8],
1202    pos: &mut usize,
1203) -> Option<usize>
1204where
1205    T: Copy
1206        + PartialEq
1207        + core::ops::BitAnd
1208        + core::ops::Shr<u32>
1209        + core::ops::ShrAssign<u32>
1210        + From<i8>
1211        + SInt,
1212    <T as core::ops::Shr<u32>>::Output: PartialEq<T>,
1213    u8: TryFrom<<T as core::ops::BitAnd>::Output>,
1214{
1215    if BITS < T::BITS {
1216        let v = value >> BITS;
1217        if v != T::from(0) && v != T::from(-1) {
1218            return None;
1219        }
1220    }
1221
1222    if output[*pos..].len() < max_len::<BITS>() {
1223        return None;
1224    }
1225
1226    let mut index = *pos;
1227    let mut extend_negative = false;
1228    loop {
1229        let b = match u8::try_from(value & T::from(0x7f)) {
1230            Ok(b) => b,
1231            Err(_) => unreachable!(),
1232        };
1233
1234        value >>= 7;
1235
1236        output[index] = b | 0x80;
1237        index += 1;
1238
1239        if value == T::from(0) && b & 0x40 == 0 {
1240            break;
1241        }
1242        if value == T::from(-1) && (b & 0x40) != 0 {
1243            extend_negative = true;
1244            break;
1245        }
1246    }
1247
1248    loop {
1249        if index == *pos + max_len::<BITS>() {
1250            output[index - 1] &= 0x7F;
1251            let len = index - *pos;
1252            *pos = index;
1253            return Some(len);
1254        }
1255
1256        if extend_negative {
1257            output[index] = 0xFF;
1258        } else {
1259            output[index] = 0x80;
1260        }
1261
1262        index += 1;
1263    }
1264}
1265
1266/// Decodes an unsigned integer from a slice of bytes and starting at a given position.
1267///
1268/// # Errors
1269///
1270/// Returns an error if the value is not properly encoded or if more bytes are
1271/// needed to decode the value.
1272///
1273/// # Panics
1274///
1275/// Panics if the size in bits of the returned type is less than the size of the value in bits.
1276/// For instance, if 33 bits are being decoded, then the returned type must be at least a `u64`.
1277///
1278/// ```rust
1279/// let input = [0x42, 0x8F, 0xFF, 0x7F, 0xFF];
1280/// let mut pos = 1;
1281/// let result = leb128fmt::decode_sint_slice::<i32, 32>(&input, &mut pos);
1282/// assert_eq!(result, Ok(-113));
1283/// assert_eq!(pos, 4);
1284/// ```
1285pub fn decode_sint_slice<T, const BITS: u32>(input: &[u8], pos: &mut usize) -> Result<T, Error>
1286where
1287    T: core::ops::Shl<u32, Output = T> + core::ops::BitOrAssign + From<i8> + From<u8> + SInt,
1288{
1289    assert!(BITS <= T::BITS);
1290
1291    let mut result = T::from(0i8);
1292    let mut shift = 0;
1293    let mut n;
1294
1295    let mut idx = *pos;
1296    loop {
1297        if input.len() <= idx {
1298            return Err(Error(InnerError::NeedMoreBytes));
1299        }
1300
1301        n = input[idx];
1302        let more = n & 0x80 != 0;
1303
1304        // For the last valid shift, perform some checks to ensure the
1305        // encoding is valid.
1306        //
1307        // Notably, the one bit that MUST NOT be set is the high order bit
1308        // indicating there are more bytes to decode.
1309        //
1310        // For a signed integer, depending on if the value is positive or negative,
1311        // some bits SHOULD or SHOULD NOT be set.
1312        //
1313        // The expectation is that if this is a negative number, then
1314        // there should have been a sign extension so that all the bits
1315        // greater than the highest order bit is a 1.
1316        //
1317        // 32-bit
1318        // ------
1319        //
1320        // The maximum shift value is 28 meaning a 32-bit number is
1321        // encoded in a maximum of 5 bytes. If the shift value is 35 or
1322        // greater, then, the byte's value will be shifted out beyond the
1323        // 32-bit value.
1324        //
1325        // With 28 being the highest valid shift value, the highest
1326        // order relevant bit in the final byte should be 0x08 or:
1327        //
1328        // 0000 1000
1329        //
1330        // Any higher bit is "lost" during the bitshift.
1331        //
1332        // Due to the encoding rules and two's complement, if the
1333        // highest order relevant bit is set, then the number is
1334        // negative and the `1` is extended to the higher bits like:
1335        //
1336        // 0111 1000
1337        //
1338        // Note that the highest order bit (the first bit from left to right)
1339        // MUST BE a 0. It is the bit which indicates more bytes should
1340        // be processed. For the maximum final byte (byte #5 for a
1341        // 32-bit number)), it MUST be 0. There are no additional bytes
1342        // to decode.
1343        //
1344        // If the highest order relevant bit is not set, then the
1345        // integer is positive. Any of the lower bits can be set.
1346        //
1347        // 0000 0111
1348        //
1349        // So the conditions to check are:
1350        //
1351        // 1. The highest order bit is not set (so there are no more
1352        //    bytes to decode). If it is set, the encoding is invalid.
1353        //    This is the "more" check.
1354        //
1355        // 2. Determine if any sign extended negative bit is set.
1356        //    So is any bit in:
1357        //
1358        //    0111 1000
1359        //
1360        //    set. If none of the bits are set, then the number is
1361        //    positive, and the encoding is valid.
1362        //    This is the "(n & mask != 0)" check.
1363        // 3. If any sign extended negative bits are set, the number is
1364        //    negative, and ALL of the bits MUST be set for a valid negative number.
1365        //    This is the "(n < mask)"" check.
1366        //    An equivalent check would be that "(n < mask) || (n >= 0x80)"
1367        //    But the earlier check for "more" removes the need for the additional check.
1368        //
1369        //    The check could also be "(n & mask) != mask".
1370        //
1371        // Another stricter condition is if the last byte has a 0 value.
1372        // The encoding is correct but not the minimal number of bytes
1373        // was used to express the final value.
1374        if shift == BITS - (BITS % 7) {
1375            #[allow(clippy::cast_sign_loss)]
1376            let mask = ((-1i8 << ((BITS % 7).saturating_sub(1))) & 0x7f) as u8;
1377            if more || (n & mask != 0 && n < mask) {
1378                return Err(Error(InnerError::InvalidEncoding));
1379            }
1380        }
1381
1382        result |= T::from(n & 0x7f) << shift;
1383        shift += 7;
1384        idx += 1;
1385
1386        if !more {
1387            break;
1388        }
1389    }
1390
1391    if shift < T::BITS && n & 0x40 != 0 {
1392        result |= T::from(-1i8) << shift;
1393    }
1394
1395    *pos = idx;
1396    Ok(result)
1397}
1398
1399#[cfg(test)]
1400mod tests {
1401    use super::*;
1402
1403    #[test]
1404    fn test_encode_u8() {
1405        let mut buffer = [0; 4];
1406        let mut pos = 1;
1407        let written = encode_fixed_uint_slice::<_, 8>(u8::MAX, &mut buffer, &mut pos);
1408        assert_eq!(3, pos);
1409        assert_eq!([0x00, 0xFF, 0x01, 0x00], buffer);
1410        assert_eq!(Some(2), written);
1411    }
1412
1413    #[test]
1414    fn test_encode_u32() {
1415        let mut buffer = [0; 6];
1416        let mut pos = 1;
1417        let written = encode_fixed_uint_slice::<_, 32>(u32::MAX, &mut buffer, &mut pos);
1418        assert_eq!(6, pos);
1419        assert_eq!([0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F], buffer);
1420        assert_eq!(Some(5), written);
1421    }
1422
1423    #[test]
1424    fn test_encode_u64_as_33_bits_2() {
1425        let mut buffer = [0; 6];
1426        let mut pos = 1;
1427        let written = encode_fixed_uint_slice::<_, 33>(2u64.pow(33) - 1, &mut buffer, &mut pos);
1428        let mut pos = 1;
1429        let value = decode_uint_slice::<u64, 33>(&buffer, &mut pos).unwrap();
1430        assert_eq!(8_589_934_592 - 1, value);
1431        assert_eq!(6, pos);
1432        assert_eq!([0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F], buffer);
1433        assert_eq!(Some(5), written);
1434    }
1435
1436    #[test]
1437    fn test_encode_u64_as_33_bits_with_too_large_value() {
1438        let mut buffer = [0; 6];
1439        let mut pos = 1;
1440        let written = encode_fixed_uint_slice::<_, 33>(2u64.pow(34) - 1, &mut buffer, &mut pos);
1441        assert_eq!(1, pos);
1442        assert_eq!([0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buffer);
1443        assert_eq!(None, written);
1444    }
1445
1446    #[test]
1447    fn test_encode_u64() {
1448        let mut buffer = [0; 20];
1449        let mut pos = 1;
1450        let written = encode_fixed_uint_slice::<_, 64>(u64::MAX, &mut buffer, &mut pos);
1451        assert_eq!(11, pos);
1452        assert_eq!(Some(10), written);
1453    }
1454
1455    #[test]
1456    fn test_decode_u32() {
1457        let input = [0xff, 0xff, 0xff, 0xff, 0x0f];
1458        let result = decode_u32(input);
1459        assert_eq!(result, Some((u32::MAX, 5)));
1460
1461        let input = [0x00, 0x00, 0x00, 0x00, 0x00];
1462        let result = decode_u32(input);
1463        assert_eq!(result, Some((u32::MIN, 1)));
1464
1465        // Valid but in-efficient way to encode 0.
1466        let input = [0x80, 0x80, 0x80, 0x80, 0x00];
1467        let result = decode_u32(input);
1468        assert_eq!(result, Some((u32::MIN, 5)));
1469    }
1470
1471    #[test]
1472    fn test_decode_u32_errors() {
1473        // Maximum of 5 bytes encoding, the 0x80 bit must not be set.
1474        let input = [0xff, 0xff, 0xff, 0xff, 0x8f];
1475        let result = decode_u32(input);
1476        assert_eq!(result, None);
1477
1478        // Parts of 0x1f (0x10) will be shifted out of the final value and lost.
1479        // This may too strict of a check since it could be ok.
1480        let input = [0xff, 0xff, 0xff, 0xff, 0x1f];
1481        let result = decode_u32(input);
1482        assert_eq!(result, None);
1483    }
1484
1485    #[test]
1486    fn test_decode_u64() {
1487        let input = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01];
1488        let result = decode_u64(input);
1489        assert_eq!(result, Some((u64::MAX, 10)));
1490
1491        let input = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
1492        let result = decode_u64(input);
1493        assert_eq!(result, Some((u64::MIN, 1)));
1494
1495        // Valid but in-efficient way to encode 0.
1496        let input = [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00];
1497        let result = decode_u64(input);
1498        assert_eq!(result, Some((u64::MIN, 10)));
1499    }
1500
1501    #[test]
1502    fn test_decode_u64_errors() {
1503        // Maximum of 10 bytes encoding, the 0x80 bit must not be set in the final byte.
1504        let input = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81];
1505        let result = decode_u64(input);
1506        assert_eq!(result, None);
1507
1508        // 0x02 will be shifted out of the final value and lost.
1509        // This may too strict of a check since it could be ok.
1510        let input = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02];
1511        let result = decode_u64(input);
1512        assert_eq!(result, None);
1513    }
1514
1515    #[test]
1516    fn test_decode_s32() {
1517        let input = [0xff, 0xff, 0xff, 0xff, 0x07];
1518        let result = decode_s32(input);
1519        assert_eq!(result, Some((i32::MAX, 5)));
1520
1521        let input = [0x80, 0x80, 0x80, 0x80, 0x78];
1522        let result = decode_s32(input);
1523        assert_eq!(result, Some((i32::MIN, 5)));
1524
1525        let input = [0x00, 0x00, 0x00, 0x00, 0x00];
1526        let result = decode_s32(input);
1527        assert_eq!(result, Some((0, 1)));
1528
1529        // Valid but in-efficient way to encode 0.
1530        let input = [0x80, 0x80, 0x80, 0x80, 0x00];
1531        let result = decode_s32(input);
1532        assert_eq!(result, Some((0, 5)));
1533
1534        let input = [0x40, 0x00, 0x00, 0x00, 0x00];
1535        let result = decode_s32(input);
1536        assert_eq!(result, Some((-64, 1)));
1537
1538        // Valid but in-efficient way to encode -64.
1539        let input = [0xc0, 0x7f, 0x00, 0x00, 0x00];
1540        let result = decode_s32(input);
1541        assert_eq!(result, Some((-64, 2)));
1542    }
1543
1544    #[test]
1545    fn test_decode_s32_errors() {
1546        // Maximum of 5 bytes encoding, the 0x80 bit must not be set in the final byte.
1547        let input = [0x80, 0x80, 0x80, 0x80, 0x80];
1548        let result = decode_s32(input);
1549        assert_eq!(result, None);
1550
1551        // If the highest valid bit is set, it should be sign extended. (final byte should be 0x78)
1552        let input = [0x80, 0x80, 0x80, 0x80, 0x08];
1553        let result = decode_s32(input);
1554        assert_eq!(result, None);
1555
1556        // If the highest valid bit is set, it should be sign extended. (final byte should be 0x78)
1557        let input = [0x80, 0x80, 0x80, 0x80, 0x38];
1558        let result = decode_s32(input);
1559        assert_eq!(result, None);
1560    }
1561
1562    #[test]
1563    fn test_decode_s33() {
1564        decode_sint_arr!(decode_s33, i64, 33);
1565
1566        let input = [0xff, 0xff, 0xff, 0xff, 0x0f];
1567        let result = decode_s33(input);
1568        assert_eq!(result, Some((i64::from(u32::MAX), 5)));
1569
1570        let input = [0x80, 0x80, 0x80, 0x80, 0x70];
1571        let result = decode_s33(input);
1572        assert_eq!(result, Some((i64::from(i32::MIN) * 2, 5)));
1573
1574        let input = [0x00, 0x00, 0x00, 0x00, 0x00];
1575        let result = decode_s33(input);
1576        assert_eq!(result, Some((0, 1)));
1577
1578        // Valid but in-efficient way to encode 0.
1579        let input = [0x80, 0x80, 0x80, 0x80, 0x00];
1580        let result = decode_s33(input);
1581        assert_eq!(result, Some((0, 5)));
1582
1583        let input = [0x40, 0x00, 0x00, 0x00, 0x00];
1584        let result = decode_s33(input);
1585        assert_eq!(result, Some((-64, 1)));
1586
1587        // Valid but in-efficient way to encode -64.
1588        let input = [0xc0, 0x7f, 0x00, 0x00, 0x00];
1589        let result = decode_s33(input);
1590        assert_eq!(result, Some((-64, 2)));
1591    }
1592
1593    #[test]
1594    fn test_decode_s33_errors() {
1595        decode_sint_arr!(decode_s33, i64, 33);
1596
1597        // Maximum of 5 bytes encoding, the 0x80 bit must not be set in the final byte.
1598        let input = [0x80, 0x80, 0x80, 0x80, 0x80];
1599        let result = decode_s33(input);
1600        assert_eq!(result, None);
1601
1602        // If the highest valid bit is set, it should be sign extended. (final byte should be 0x70)
1603        let input = [0x80, 0x80, 0x80, 0x80, 0x10];
1604        let result = decode_s33(input);
1605        assert_eq!(result, None);
1606
1607        // If the highest valid bit is set, it should be sign extended. (final byte should be 0x70)
1608        let input = [0x80, 0x80, 0x80, 0x80, 0x30];
1609        let result = decode_s33(input);
1610        assert_eq!(result, None);
1611    }
1612
1613    #[test]
1614    fn test_decode_s64() {
1615        let input = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00];
1616        let result = decode_s64(input);
1617        assert_eq!(result, Some((i64::MAX, 10)));
1618
1619        let input = [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f];
1620        let result = decode_s64(input);
1621        assert_eq!(result, Some((i64::MIN, 10)));
1622
1623        let input = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
1624        let result = decode_s64(input);
1625        assert_eq!(result, Some((0, 1)));
1626
1627        // Valid but in-efficient way to encode 0.
1628        let input = [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00];
1629        let result = decode_s64(input);
1630        assert_eq!(result, Some((0, 10)));
1631    }
1632
1633    #[test]
1634    fn test_decode_s64_errors() {
1635        // Maximum of 10 bytes encoding, the 0x80 bit must not be set in the final byte.
1636        let input = [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80];
1637        let result = decode_s64(input);
1638        assert_eq!(result, None);
1639
1640        // If the highest valid bit is set, it should be sign extended. (final byte should be 0x78)
1641        let input = [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08];
1642        let result = decode_s64(input);
1643        assert_eq!(result, None);
1644
1645        // If the highest valid bit is set, it should be sign extended. (final byte should be 0x78)
1646        let input = [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x28];
1647        let result = decode_s64(input);
1648        assert_eq!(result, None);
1649    }
1650}