Coverage Report

Created: 2025-06-24 06:17

/rust/registry/src/index.crates.io-6f17d22bba15001f/protobuf-3.2.0/src/varint/decode.rs
Line
Count
Source (jump to first uncovered line)
1
//! Varint decode utilities.
2
3
use crate::error::WireError;
4
use crate::varint::MAX_VARINT32_ENCODED_LEN;
5
use crate::varint::MAX_VARINT_ENCODED_LEN;
6
7
trait DecodeVarint {
8
    const MAX_ENCODED_LEN: usize;
9
    const LAST_BYTE_MAX_VALUE: u8;
10
11
    fn from_u64(value: u64) -> Self;
12
}
13
14
impl DecodeVarint for u64 {
15
    const MAX_ENCODED_LEN: usize = MAX_VARINT_ENCODED_LEN;
16
    const LAST_BYTE_MAX_VALUE: u8 = 0x01;
17
18
0
    fn from_u64(value: u64) -> Self {
19
0
        value
20
0
    }
21
}
22
23
impl DecodeVarint for u32 {
24
    const MAX_ENCODED_LEN: usize = MAX_VARINT32_ENCODED_LEN;
25
    const LAST_BYTE_MAX_VALUE: u8 = 0x0f;
26
27
0
    fn from_u64(value: u64) -> Self {
28
0
        value as u32
29
0
    }
30
}
31
32
/// Decode a varint, and return decoded value and decoded byte count.
33
#[inline]
34
0
fn decode_varint_full<D: DecodeVarint>(rem: &[u8]) -> crate::Result<Option<(D, usize)>> {
35
0
    let mut r: u64 = 0;
36
0
    for (i, &b) in rem.iter().enumerate() {
37
0
        if i == D::MAX_ENCODED_LEN - 1 {
38
0
            if b > D::LAST_BYTE_MAX_VALUE {
39
0
                return Err(WireError::IncorrectVarint.into());
40
0
            }
41
0
            let r = r | ((b as u64) << (i as u64 * 7));
42
0
            return Ok(Some((D::from_u64(r), i + 1)));
43
0
        }
44
0
45
0
        r = r | (((b & 0x7f) as u64) << (i as u64 * 7));
46
0
        if b < 0x80 {
47
0
            return Ok(Some((D::from_u64(r), i + 1)));
48
0
        }
49
    }
50
0
    Ok(None)
51
0
}
Unexecuted instantiation: protobuf::varint::decode::decode_varint_full::<u32>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_full::<u64>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_full::<u64>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_full::<u32>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_full::<u32>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_full::<u64>
52
53
#[inline]
54
0
fn decode_varint_impl<D: DecodeVarint>(buf: &[u8]) -> crate::Result<Option<(D, usize)>> {
55
0
    if buf.len() >= 1 && buf[0] < 0x80 {
56
        // The the most common case.
57
0
        let ret = buf[0] as u64;
58
0
        let consume = 1;
59
0
        Ok(Some((D::from_u64(ret), consume)))
60
0
    } else if buf.len() >= 2 && buf[1] < 0x80 {
61
        // Handle the case of two bytes too.
62
0
        let ret = (buf[0] & 0x7f) as u64 | (buf[1] as u64) << 7;
63
0
        let consume = 2;
64
0
        Ok(Some((D::from_u64(ret), consume)))
65
    } else {
66
        // Read from array when buf at at least 10 bytes,
67
        // max len for varint.
68
0
        decode_varint_full(buf)
69
    }
70
0
}
Unexecuted instantiation: protobuf::varint::decode::decode_varint_impl::<u32>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_impl::<u64>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_impl::<u64>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_impl::<u32>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_impl::<u32>
Unexecuted instantiation: protobuf::varint::decode::decode_varint_impl::<u64>
71
72
/// Try decode a varint. Return `None` if the buffer does not contain complete varint.
73
#[inline]
74
0
pub(crate) fn decode_varint64(buf: &[u8]) -> crate::Result<Option<(u64, usize)>> {
75
0
    decode_varint_impl(buf)
76
0
}
77
78
/// Try decode a varint. Return `None` if the buffer does not contain complete varint.
79
#[inline]
80
0
pub(crate) fn decode_varint32(buf: &[u8]) -> crate::Result<Option<(u32, usize)>> {
81
0
    decode_varint_impl(buf)
82
0
}
83
84
#[cfg(test)]
85
mod tests {
86
    use crate::hex::decode_hex;
87
    use crate::varint::decode::decode_varint32;
88
    use crate::varint::decode::decode_varint64;
89
90
    #[test]
91
    fn test_decode_varint64() {
92
        assert_eq!((0, 1), decode_varint64(&decode_hex("00")).unwrap().unwrap());
93
        assert_eq!(
94
            (u64::MAX, 10),
95
            decode_varint64(&decode_hex("ff ff ff ff ff ff ff ff ff 01"))
96
                .unwrap()
97
                .unwrap()
98
        );
99
        assert!(decode_varint64(&decode_hex("ff ff ff ff ff ff ff ff ff 02")).is_err());
100
    }
101
102
    #[test]
103
    fn test_decode_varint32() {
104
        assert_eq!((0, 1), decode_varint32(&decode_hex("00")).unwrap().unwrap());
105
        assert_eq!(
106
            (u32::MAX, 5),
107
            decode_varint32(&decode_hex("ff ff ff ff 0f"))
108
                .unwrap()
109
                .unwrap()
110
        );
111
        assert!(decode_varint32(&decode_hex("ff ff ff ff 10")).is_err());
112
    }
113
}