Coverage Report

Created: 2026-03-26 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/leb128fmt-0.1.0/src/lib.rs
Line
Count
Source
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
151
use 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]
168
pub 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]
187
21.5k
pub const fn is_last(byte: u8) -> bool {
188
21.5k
    byte & 0x80 == 0
189
21.5k
}
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]
209
macro_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
16.7M
        pub const fn $func(
219
16.7M
            mut value: $num_ty,
220
16.7M
        ) -> Option<(
221
16.7M
            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
222
16.7M
            usize,
223
16.7M
        )> {
224
            const BITS: u32 = $bits;
225
16.7M
            if <$num_ty>::BITS > BITS && 1 < value >> BITS - 1 {
226
0
                return None;
227
16.7M
            }
228
229
16.7M
            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
230
16.7M
            let mut index = 0;
231
            loop {
232
19.6M
                let mut b = (value & 0x7f) as u8;
233
234
19.6M
                value >>= 7;
235
19.6M
                let done = value == 0;
236
237
19.6M
                if !done {
238
2.90M
                    b |= 0x80;
239
16.7M
                }
240
241
19.6M
                output[index] = b;
242
19.6M
                index += 1;
243
244
19.6M
                if done {
245
16.7M
                    return Some((output, index));
246
2.90M
                }
247
            }
248
16.7M
        }
leb128fmt::encode_u32
Line
Count
Source
218
16.2M
        pub const fn $func(
219
16.2M
            mut value: $num_ty,
220
16.2M
        ) -> Option<(
221
16.2M
            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
222
16.2M
            usize,
223
16.2M
        )> {
224
            const BITS: u32 = $bits;
225
16.2M
            if <$num_ty>::BITS > BITS && 1 < value >> BITS - 1 {
226
0
                return None;
227
16.2M
            }
228
229
16.2M
            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
230
16.2M
            let mut index = 0;
231
            loop {
232
18.2M
                let mut b = (value & 0x7f) as u8;
233
234
18.2M
                value >>= 7;
235
18.2M
                let done = value == 0;
236
237
18.2M
                if !done {
238
2.02M
                    b |= 0x80;
239
16.2M
                }
240
241
18.2M
                output[index] = b;
242
18.2M
                index += 1;
243
244
18.2M
                if done {
245
16.2M
                    return Some((output, index));
246
2.02M
                }
247
            }
248
16.2M
        }
leb128fmt::encode_u64
Line
Count
Source
218
518k
        pub const fn $func(
219
518k
            mut value: $num_ty,
220
518k
        ) -> Option<(
221
518k
            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
222
518k
            usize,
223
518k
        )> {
224
            const BITS: u32 = $bits;
225
518k
            if <$num_ty>::BITS > BITS && 1 < value >> BITS - 1 {
226
0
                return None;
227
518k
            }
228
229
518k
            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
230
518k
            let mut index = 0;
231
            loop {
232
1.40M
                let mut b = (value & 0x7f) as u8;
233
234
1.40M
                value >>= 7;
235
1.40M
                let done = value == 0;
236
237
1.40M
                if !done {
238
884k
                    b |= 0x80;
239
884k
                }
240
241
1.40M
                output[index] = b;
242
1.40M
                index += 1;
243
244
1.40M
                if done {
245
518k
                    return Some((output, index));
246
884k
                }
247
            }
248
518k
        }
249
    };
250
}
251
252
encode_uint_arr!(encode_u32, u32, 32);
253
encode_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]
274
macro_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
319
encode_fixed_uint_arr!(encode_fixed_u32, u32, 32);
320
encode_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]
338
macro_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
402
decode_uint_arr!(decode_u32, u32, 32);
403
decode_uint_arr!(decode_u64, u64, 64);
404
405
mod 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.
422
pub trait UInt: private::Sealed {
423
    /// Size of the type in bits.
424
    const BITS: u32;
425
}
426
427
impl UInt for u8 {
428
    const BITS: u32 = u8::BITS;
429
}
430
431
impl UInt for u16 {
432
    const BITS: u32 = u16::BITS;
433
}
434
435
impl UInt for u32 {
436
    const BITS: u32 = u32::BITS;
437
}
438
439
impl UInt for u64 {
440
    const BITS: u32 = u64::BITS;
441
}
442
443
impl UInt for u128 {
444
    const BITS: u32 = u128::BITS;
445
}
446
447
#[derive(Debug, Clone, PartialEq, Eq)]
448
enum InnerError {
449
    NeedMoreBytes,
450
    InvalidEncoding,
451
}
452
453
/// Error when decoding a LEB128 value.
454
#[derive(Debug, Clone, PartialEq, Eq)]
455
pub struct Error(InnerError);
456
457
impl 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")]
467
impl std::error::Error for Error {
468
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
469
        None
470
    }
471
}
472
473
impl 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)]
534
pub fn encode_uint_slice<T, const BITS: u32>(
535
    mut value: T,
536
    output: &mut [u8],
537
    pos: &mut usize,
538
) -> Option<usize>
539
where
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)]
620
pub fn encode_fixed_uint_slice<T, const BITS: u32>(
621
    mut value: T,
622
    output: &mut [u8],
623
    pos: &mut usize,
624
) -> Option<usize>
625
where
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
/// ```
684
17.2k
pub fn decode_uint_slice<T, const BITS: u32>(input: &[u8], pos: &mut usize) -> Result<T, Error>
685
17.2k
where
686
17.2k
    T: core::ops::Shl<u32, Output = T> + core::ops::BitOrAssign + From<u8> + UInt,
687
{
688
17.2k
    assert!(BITS <= T::BITS);
689
17.2k
    if input.len() <= *pos {
690
0
        return Err(Error(InnerError::NeedMoreBytes));
691
17.2k
    }
692
693
17.2k
    let n = input[*pos];
694
17.2k
    if is_last(n) {
695
12.9k
        *pos += 1;
696
12.9k
        return Ok(T::from(n));
697
4.31k
    }
698
699
4.31k
    let mut result = T::from(n & 0x7f);
700
4.31k
    let mut shift: u32 = 7;
701
702
4.31k
    let mut idx = *pos + 1;
703
    loop {
704
4.31k
        if input.len() <= idx {
705
0
            return Err(Error(InnerError::NeedMoreBytes));
706
4.31k
        }
707
708
4.31k
        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
4.31k
        if shift == BITS - (BITS % 7) && 1 << (BITS % 7) <= n {
727
0
            return Err(Error(InnerError::InvalidEncoding));
728
4.31k
        }
729
730
4.31k
        if is_last(n) {
731
4.31k
            result |= T::from(n) << shift;
732
4.31k
            *pos = idx + 1;
733
4.31k
            return Ok(result);
734
0
        }
735
736
0
        result |= T::from(n & 0x7f) << shift;
737
0
        shift += 7;
738
0
        idx += 1;
739
    }
740
17.2k
}
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]
766
macro_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
3.68M
        pub fn $func(
771
3.68M
            mut value: $num_ty,
772
3.68M
        ) -> Option<(
773
3.68M
            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
774
3.68M
            usize,
775
3.68M
        )> {
776
            const BITS: u32 = $bits;
777
3.68M
            if BITS < <$num_ty>::BITS {
778
0
                let v: $num_ty = value >> BITS - 1;
779
0
                if v != 0 && v != -1 {
780
0
                    return None;
781
0
                }
782
3.68M
            }
783
784
3.68M
            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
785
3.68M
            let mut index = 0;
786
            loop {
787
13.2M
                let b = (value & 0x7f) as u8;
788
789
13.2M
                value >>= 7;
790
791
13.2M
                if (value == 0 && b & 0x40 == 0) || (value == -1 && (b & 0x40) != 0) {
792
3.68M
                    output[index] = b;
793
3.68M
                    return Some((output, index + 1));
794
9.53M
                }
795
796
9.53M
                output[index] = b | 0x80;
797
9.53M
                index += 1;
798
            }
799
3.68M
        }
leb128fmt::encode_s32
Line
Count
Source
770
1.62M
        pub fn $func(
771
1.62M
            mut value: $num_ty,
772
1.62M
        ) -> Option<(
773
1.62M
            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
774
1.62M
            usize,
775
1.62M
        )> {
776
            const BITS: u32 = $bits;
777
1.62M
            if BITS < <$num_ty>::BITS {
778
0
                let v: $num_ty = value >> BITS - 1;
779
0
                if v != 0 && v != -1 {
780
0
                    return None;
781
0
                }
782
1.62M
            }
783
784
1.62M
            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
785
1.62M
            let mut index = 0;
786
            loop {
787
3.97M
                let b = (value & 0x7f) as u8;
788
789
3.97M
                value >>= 7;
790
791
3.97M
                if (value == 0 && b & 0x40 == 0) || (value == -1 && (b & 0x40) != 0) {
792
1.62M
                    output[index] = b;
793
1.62M
                    return Some((output, index + 1));
794
2.35M
                }
795
796
2.35M
                output[index] = b | 0x80;
797
2.35M
                index += 1;
798
            }
799
1.62M
        }
leb128fmt::encode_s64
Line
Count
Source
770
2.05M
        pub fn $func(
771
2.05M
            mut value: $num_ty,
772
2.05M
        ) -> Option<(
773
2.05M
            [u8; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize],
774
2.05M
            usize,
775
2.05M
        )> {
776
            const BITS: u32 = $bits;
777
2.05M
            if BITS < <$num_ty>::BITS {
778
0
                let v: $num_ty = value >> BITS - 1;
779
0
                if v != 0 && v != -1 {
780
0
                    return None;
781
0
                }
782
2.05M
            }
783
784
2.05M
            let mut output = [0; (($bits / 7) + if $bits % 7 == 0 { 0 } else { 1 }) as usize];
785
2.05M
            let mut index = 0;
786
            loop {
787
9.23M
                let b = (value & 0x7f) as u8;
788
789
9.23M
                value >>= 7;
790
791
9.23M
                if (value == 0 && b & 0x40 == 0) || (value == -1 && (b & 0x40) != 0) {
792
2.05M
                    output[index] = b;
793
2.05M
                    return Some((output, index + 1));
794
7.17M
                }
795
796
7.17M
                output[index] = b | 0x80;
797
7.17M
                index += 1;
798
            }
799
2.05M
        }
800
    };
801
}
802
803
encode_sint_arr!(encode_s32, i32, 32);
804
encode_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]
831
macro_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
884
encode_fixed_sint_arr!(encode_fixed_s32, i32, 32);
885
encode_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]
915
macro_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
1040
decode_sint_arr!(decode_s32, i32, 32);
1041
decode_sint_arr!(decode_s64, i64, 64);
1042
1043
/// Sealed trait for supported signed integer types.
1044
pub trait SInt: private::Sealed {
1045
    /// Size of the type in bits.
1046
    const BITS: u32;
1047
}
1048
1049
impl SInt for i8 {
1050
    const BITS: u32 = i8::BITS;
1051
}
1052
1053
impl SInt for i16 {
1054
    const BITS: u32 = i16::BITS;
1055
}
1056
1057
impl SInt for i32 {
1058
    const BITS: u32 = i32::BITS;
1059
}
1060
1061
impl SInt for i64 {
1062
    const BITS: u32 = i64::BITS;
1063
}
1064
1065
impl 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)]
1114
pub fn encode_sint_slice<T, const BITS: u32>(
1115
    mut value: T,
1116
    output: &mut [u8],
1117
    pos: &mut usize,
1118
) -> Option<usize>
1119
where
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)]
1199
pub fn encode_fixed_sint_slice<T, const BITS: u32>(
1200
    mut value: T,
1201
    output: &mut [u8],
1202
    pos: &mut usize,
1203
) -> Option<usize>
1204
where
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
/// ```
1285
pub fn decode_sint_slice<T, const BITS: u32>(input: &[u8], pos: &mut usize) -> Result<T, Error>
1286
where
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)]
1400
mod 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
}