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}