Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/util/leb128.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
//! Little Endian Base 128
19
//!
20
//! The LEB128 encoding is used throughout the networking code. This module provides utilities for
21
//! encoding/decoding this format.
22
//!
23
//! See <https://en.wikipedia.org/wiki/LEB128>.
24
25
/// Returns an LEB128-encoded integer as a list of bytes.
26
///
27
/// This function accepts as parameter an `Into<u64>`. As such, one can also pass a `u8`, `u16`,
28
/// or `u32` for example. Use [`encode_usize`] for the `usize` equivalent.
29
1.85k
pub fn encode(value: impl Into<u64>) -> impl ExactSizeIterator<Item = u8> + Clone {
30
1.85k
    #[derive(Clone)]
31
1.85k
    struct EncodeIter {
32
1.85k
        value: u64,
33
1.85k
        finished: bool,
34
1.85k
    }
35
1.85k
36
1.85k
    impl Iterator for EncodeIter {
37
1.85k
        type Item = u8;
38
1.85k
39
6.37k
        fn next(&mut self) -> Option<Self::Item> {
40
6.37k
            if self.finished {
41
2.19k
                return None;
42
4.18k
            }
43
4.18k
44
4.18k
            if self.value < (1 << 7) {
45
1.97k
                self.finished = true;
46
1.97k
                return Some(u8::try_from(self.value).unwrap());
47
2.20k
            }
48
2.20k
49
2.20k
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
2.20k
            self.value >>= 7;
51
2.20k
            Some(ret)
52
6.37k
        }
_RNvXNvNtNtCsN16ciHI6Qf_7smoldot4util6leb1286encodeNtB2_10EncodeIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
39
4.28k
        fn next(&mut self) -> Option<Self::Item> {
40
4.28k
            if self.finished {
41
1.15k
                return None;
42
3.13k
            }
43
3.13k
44
3.13k
            if self.value < (1 << 7) {
45
935
                self.finished = true;
46
935
                return Some(u8::try_from(self.value).unwrap());
47
2.20k
            }
48
2.20k
49
2.20k
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
2.20k
            self.value >>= 7;
51
2.20k
            Some(ret)
52
4.28k
        }
_RNvXNvNtNtCseuYC0Zibziv_7smoldot4util6leb1286encodeNtB2_10EncodeIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
39
2.08k
        fn next(&mut self) -> Option<Self::Item> {
40
2.08k
            if self.finished {
41
1.04k
                return None;
42
1.04k
            }
43
1.04k
44
1.04k
            if self.value < (1 << 7) {
45
1.04k
                self.finished = true;
46
1.04k
                return Some(u8::try_from(self.value).unwrap());
47
0
            }
48
0
49
0
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
0
            self.value >>= 7;
51
0
            Some(ret)
52
2.08k
        }
53
1.85k
54
1.85k
        fn size_hint(&self) -> (usize, Option<usize>) {
55
345
            let len = self.clone().count();
56
345
            (len, Some(len))
57
345
        }
_RNvXNvNtNtCsN16ciHI6Qf_7smoldot4util6leb1286encodeNtB2_10EncodeIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hint
Line
Count
Source
54
345
        fn size_hint(&self) -> (usize, Option<usize>) {
55
345
            let len = self.clone().count();
56
345
            (len, Some(len))
57
345
        }
Unexecuted instantiation: _RNvXNvNtNtCseuYC0Zibziv_7smoldot4util6leb1286encodeNtB2_10EncodeIterNtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hint
58
1.85k
    }
59
1.85k
60
1.85k
    impl ExactSizeIterator for EncodeIter {}
61
1.85k
62
1.85k
    EncodeIter {
63
1.85k
        value: value.into(),
64
1.85k
        finished: false,
65
1.85k
    }
66
1.85k
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb1286encodeyEB6_
Line
Count
Source
29
778
pub fn encode(value: impl Into<u64>) -> impl ExactSizeIterator<Item = u8> + Clone {
30
778
    #[derive(Clone)]
31
778
    struct EncodeIter {
32
778
        value: u64,
33
778
        finished: bool,
34
778
    }
35
778
36
778
    impl Iterator for EncodeIter {
37
778
        type Item = u8;
38
778
39
778
        fn next(&mut self) -> Option<Self::Item> {
40
778
            if self.finished {
41
778
                return None;
42
778
            }
43
778
44
778
            if self.value < (1 << 7) {
45
778
                self.finished = true;
46
778
                return Some(u8::try_from(self.value).unwrap());
47
778
            }
48
778
49
778
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
778
            self.value >>= 7;
51
778
            Some(ret)
52
778
        }
53
778
54
778
        fn size_hint(&self) -> (usize, Option<usize>) {
55
778
            let len = self.clone().count();
56
778
            (len, Some(len))
57
778
        }
58
778
    }
59
778
60
778
    impl ExactSizeIterator for EncodeIter {}
61
778
62
778
    EncodeIter {
63
778
        value: value.into(),
64
778
        finished: false,
65
778
    }
66
778
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb1286encodemEB6_
Line
Count
Source
29
28
pub fn encode(value: impl Into<u64>) -> impl ExactSizeIterator<Item = u8> + Clone {
30
28
    #[derive(Clone)]
31
28
    struct EncodeIter {
32
28
        value: u64,
33
28
        finished: bool,
34
28
    }
35
28
36
28
    impl Iterator for EncodeIter {
37
28
        type Item = u8;
38
28
39
28
        fn next(&mut self) -> Option<Self::Item> {
40
28
            if self.finished {
41
28
                return None;
42
28
            }
43
28
44
28
            if self.value < (1 << 7) {
45
28
                self.finished = true;
46
28
                return Some(u8::try_from(self.value).unwrap());
47
28
            }
48
28
49
28
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
28
            self.value >>= 7;
51
28
            Some(ret)
52
28
        }
53
28
54
28
        fn size_hint(&self) -> (usize, Option<usize>) {
55
28
            let len = self.clone().count();
56
28
            (len, Some(len))
57
28
        }
58
28
    }
59
28
60
28
    impl ExactSizeIterator for EncodeIter {}
61
28
62
28
    EncodeIter {
63
28
        value: value.into(),
64
28
        finished: false,
65
28
    }
66
28
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb1286encodeyECsDDUKWWCHAU_18smoldot_light_wasm
_RINvNtNtCseuYC0Zibziv_7smoldot4util6leb1286encodeyEB6_
Line
Count
Source
29
898
pub fn encode(value: impl Into<u64>) -> impl ExactSizeIterator<Item = u8> + Clone {
30
898
    #[derive(Clone)]
31
898
    struct EncodeIter {
32
898
        value: u64,
33
898
        finished: bool,
34
898
    }
35
898
36
898
    impl Iterator for EncodeIter {
37
898
        type Item = u8;
38
898
39
898
        fn next(&mut self) -> Option<Self::Item> {
40
898
            if self.finished {
41
898
                return None;
42
898
            }
43
898
44
898
            if self.value < (1 << 7) {
45
898
                self.finished = true;
46
898
                return Some(u8::try_from(self.value).unwrap());
47
898
            }
48
898
49
898
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
898
            self.value >>= 7;
51
898
            Some(ret)
52
898
        }
53
898
54
898
        fn size_hint(&self) -> (usize, Option<usize>) {
55
898
            let len = self.clone().count();
56
898
            (len, Some(len))
57
898
        }
58
898
    }
59
898
60
898
    impl ExactSizeIterator for EncodeIter {}
61
898
62
898
    EncodeIter {
63
898
        value: value.into(),
64
898
        finished: false,
65
898
    }
66
898
}
_RINvNtNtCseuYC0Zibziv_7smoldot4util6leb1286encodemEB6_
Line
Count
Source
29
146
pub fn encode(value: impl Into<u64>) -> impl ExactSizeIterator<Item = u8> + Clone {
30
146
    #[derive(Clone)]
31
146
    struct EncodeIter {
32
146
        value: u64,
33
146
        finished: bool,
34
146
    }
35
146
36
146
    impl Iterator for EncodeIter {
37
146
        type Item = u8;
38
146
39
146
        fn next(&mut self) -> Option<Self::Item> {
40
146
            if self.finished {
41
146
                return None;
42
146
            }
43
146
44
146
            if self.value < (1 << 7) {
45
146
                self.finished = true;
46
146
                return Some(u8::try_from(self.value).unwrap());
47
146
            }
48
146
49
146
            let ret = (1 << 7) | u8::try_from(self.value & 0b111_1111).unwrap();
50
146
            self.value >>= 7;
51
146
            Some(ret)
52
146
        }
53
146
54
146
        fn size_hint(&self) -> (usize, Option<usize>) {
55
146
            let len = self.clone().count();
56
146
            (len, Some(len))
57
146
        }
58
146
    }
59
146
60
146
    impl ExactSizeIterator for EncodeIter {}
61
146
62
146
    EncodeIter {
63
146
        value: value.into(),
64
146
        finished: false,
65
146
    }
66
146
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb1286encodeyECsiUjFBJteJ7x_17smoldot_full_node
67
68
/// Returns an LEB128-encoded `usize` as a list of bytes.
69
///
70
/// See also [`encode`].
71
788
pub fn encode_usize(value: usize) -> impl ExactSizeIterator<Item = u8> + Clone {
72
788
    // `encode_usize` can leverage `encode` thanks to the property checked in this debug_assert.
73
788
    #[cfg(not(any(
74
788
        target_pointer_width = "16",
75
788
        target_pointer_width = "32",
76
788
        target_pointer_width = "64"
77
788
    )))]
78
788
    compile_error!("usize must be <= u64");
79
788
    encode(u64::try_from(value).unwrap())
80
788
}
_RNvNtNtCsN16ciHI6Qf_7smoldot4util6leb12812encode_usize
Line
Count
Source
71
433
pub fn encode_usize(value: usize) -> impl ExactSizeIterator<Item = u8> + Clone {
72
433
    // `encode_usize` can leverage `encode` thanks to the property checked in this debug_assert.
73
433
    #[cfg(not(any(
74
433
        target_pointer_width = "16",
75
433
        target_pointer_width = "32",
76
433
        target_pointer_width = "64"
77
433
    )))]
78
433
    compile_error!("usize must be <= u64");
79
433
    encode(u64::try_from(value).unwrap())
80
433
}
_RNvNtNtCseuYC0Zibziv_7smoldot4util6leb12812encode_usize
Line
Count
Source
71
355
pub fn encode_usize(value: usize) -> impl ExactSizeIterator<Item = u8> + Clone {
72
355
    // `encode_usize` can leverage `encode` thanks to the property checked in this debug_assert.
73
355
    #[cfg(not(any(
74
355
        target_pointer_width = "16",
75
355
        target_pointer_width = "32",
76
355
        target_pointer_width = "64"
77
355
    )))]
78
355
    compile_error!("usize must be <= u64");
79
355
    encode(u64::try_from(value).unwrap())
80
355
}
81
82
/// Decodes a LEB128-encoded `usize`.
83
///
84
/// > **Note**: When using this function outside of a `nom` "context", you might have to explicit
85
/// >           the type of `E`. Use `nom::error::Error<&[u8]>`.
86
582
pub(crate) fn nom_leb128_usize<'a, E: nom::error::ParseError<&'a [u8]>>(
87
582
    bytes: &'a [u8],
88
582
) -> nom::IResult<&'a [u8], usize, E> {
89
    // `nom_leb128_usize` can leverage `nom_leb128_u64` thanks to the property checked in this
90
    // debug_assert.
91
    #[cfg(not(any(
92
        target_pointer_width = "16",
93
        target_pointer_width = "32",
94
        target_pointer_width = "64"
95
    )))]
96
    compile_error!("usize must be <= u64");
97
582
    let (
rest, value370
) = nom_leb128_u64(bytes)
?212
;
98
99
370
    let value = match usize::try_from(value) {
100
370
        Ok(v) => v,
101
        Err(_) => {
102
0
            return Err(nom::Err::Error(nom::error::make_error(
103
0
                bytes,
104
0
                nom::error::ErrorKind::LengthValue,
105
0
            )));
106
        }
107
    };
108
109
370
    Ok((rest, value))
110
582
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_
Line
Count
Source
86
507
pub(crate) fn nom_leb128_usize<'a, E: nom::error::ParseError<&'a [u8]>>(
87
507
    bytes: &'a [u8],
88
507
) -> nom::IResult<&'a [u8], usize, E> {
89
    // `nom_leb128_usize` can leverage `nom_leb128_u64` thanks to the property checked in this
90
    // debug_assert.
91
    #[cfg(not(any(
92
        target_pointer_width = "16",
93
        target_pointer_width = "32",
94
        target_pointer_width = "64"
95
    )))]
96
    compile_error!("usize must be <= u64");
97
507
    let (
rest, value295
) = nom_leb128_u64(bytes)
?212
;
98
99
295
    let value = match usize::try_from(value) {
100
295
        Ok(v) => v,
101
        Err(_) => {
102
0
            return Err(nom::Err::Error(nom::error::make_error(
103
0
                bytes,
104
0
                nom::error::ErrorKind::LengthValue,
105
0
            )));
106
        }
107
    };
108
109
295
    Ok((rest, value))
110
507
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb12816nom_leb128_usizeNtNvMNtNtB6_6libp2p7peer_idNtB10_9PublicKey22from_protobuf_encoding12ErrorWrapperEB6_
Line
Count
Source
86
27
pub(crate) fn nom_leb128_usize<'a, E: nom::error::ParseError<&'a [u8]>>(
87
27
    bytes: &'a [u8],
88
27
) -> nom::IResult<&'a [u8], usize, E> {
89
    // `nom_leb128_usize` can leverage `nom_leb128_u64` thanks to the property checked in this
90
    // debug_assert.
91
    #[cfg(not(any(
92
        target_pointer_width = "16",
93
        target_pointer_width = "32",
94
        target_pointer_width = "64"
95
    )))]
96
    compile_error!("usize must be <= u64");
97
27
    let (rest, value) = nom_leb128_u64(bytes)
?0
;
98
99
27
    let value = match usize::try_from(value) {
100
27
        Ok(v) => v,
101
        Err(_) => {
102
0
            return Err(nom::Err::Error(nom::error::make_error(
103
0
                bytes,
104
0
                nom::error::ErrorKind::LengthValue,
105
0
            )));
106
        }
107
    };
108
109
27
    Ok((rest, value))
110
27
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb12816nom_leb128_usizeTRShNtNtCs6ga8gEqbpRc_3nom5error9ErrorKindEEB6_
Line
Count
Source
86
48
pub(crate) fn nom_leb128_usize<'a, E: nom::error::ParseError<&'a [u8]>>(
87
48
    bytes: &'a [u8],
88
48
) -> nom::IResult<&'a [u8], usize, E> {
89
    // `nom_leb128_usize` can leverage `nom_leb128_u64` thanks to the property checked in this
90
    // debug_assert.
91
    #[cfg(not(any(
92
        target_pointer_width = "16",
93
        target_pointer_width = "32",
94
        target_pointer_width = "64"
95
    )))]
96
    compile_error!("usize must be <= u64");
97
48
    let (rest, value) = nom_leb128_u64(bytes)
?0
;
98
99
48
    let value = match usize::try_from(value) {
100
48
        Ok(v) => v,
101
        Err(_) => {
102
0
            return Err(nom::Err::Error(nom::error::make_error(
103
0
                bytes,
104
0
                nom::error::ErrorKind::LengthValue,
105
0
            )));
106
        }
107
    };
108
109
48
    Ok((rest, value))
110
48
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeTRShNtNtCs6ga8gEqbpRc_3nom5error9ErrorKindEECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsih6EgvAwZF2_13smoldot_light
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeNtNvMNtNtB6_6libp2p7peer_idNtB11_9PublicKey22from_protobuf_encoding12ErrorWrapperEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeTRShNtNtCs6ga8gEqbpRc_3nom5error9ErrorKindEECsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12816nom_leb128_usizeINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsibGXYHQB8Ea_25json_rpc_general_requests
111
112
/// Decodes a LEB128-encoded `u64`.
113
///
114
/// > **Note**: When using this function outside of a `nom` "context", you might have to explicit
115
/// >           the type of `E`. Use `nom::error::Error<&[u8]>`.
116
3.08k
pub(crate) fn nom_leb128_u64<'a, E: nom::error::ParseError<&'a [u8]>>(
117
3.08k
    bytes: &'a [u8],
118
3.08k
) -> nom::IResult<&'a [u8], u64, E> {
119
3.08k
    let mut out = 0u64;
120
121
4.11k
    for (n, byte) in 
bytes.iter().enumerate()3.08k
{
122
4.11k
        if (7 * n) >= usize::try_from(u64::BITS).unwrap() {
123
2
            return Err(nom::Err::Error(nom::error::make_error(
124
2
                bytes,
125
2
                nom::error::ErrorKind::LengthValue,
126
2
            )));
127
4.11k
        }
128
4.11k
129
4.11k
        match u64::from(*byte & 0b111_1111).checked_mul(1 << (7 * n)) {
130
4.11k
            Some(o) => out |= o,
131
            None => {
132
0
                return Err(nom::Err::Error(nom::error::make_error(
133
0
                    bytes,
134
0
                    nom::error::ErrorKind::LengthValue,
135
0
                )))
136
            }
137
        };
138
139
4.11k
        if (*byte & 0x80) == 0 {
140
            // We want to avoid LEB128 numbers such as `[0x81, 0x0]`.
141
2.86k
            if n >= 1 && 
*byte == 0x0919
{
142
0
                return Err(nom::Err::Error(nom::error::make_error(
143
0
                    bytes,
144
0
                    nom::error::ErrorKind::Verify,
145
0
                )));
146
2.86k
            }
147
2.86k
148
2.86k
            return Ok((&bytes[(n + 1)..], out));
149
1.24k
        }
150
    }
151
152
211
    Err(nom::Err::Incomplete(nom::Needed::Unknown))
153
3.08k
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_
Line
Count
Source
116
1.31k
pub(crate) fn nom_leb128_u64<'a, E: nom::error::ParseError<&'a [u8]>>(
117
1.31k
    bytes: &'a [u8],
118
1.31k
) -> nom::IResult<&'a [u8], u64, E> {
119
1.31k
    let mut out = 0u64;
120
121
1.31k
    for (n, byte) in 
bytes.iter().enumerate()1.31k
{
122
1.31k
        if (7 * n) >= usize::try_from(u64::BITS).unwrap() {
123
2
            return Err(nom::Err::Error(nom::error::make_error(
124
2
                bytes,
125
2
                nom::error::ErrorKind::LengthValue,
126
2
            )));
127
1.31k
        }
128
1.31k
129
1.31k
        match u64::from(*byte & 0b111_1111).checked_mul(1 << (7 * n)) {
130
1.31k
            Some(o) => out |= o,
131
            None => {
132
0
                return Err(nom::Err::Error(nom::error::make_error(
133
0
                    bytes,
134
0
                    nom::error::ErrorKind::LengthValue,
135
0
                )))
136
            }
137
        };
138
139
1.31k
        if (*byte & 0x80) == 0 {
140
            // We want to avoid LEB128 numbers such as `[0x81, 0x0]`.
141
1.10k
            if n >= 1 && 
*byte == 0x0145
{
142
0
                return Err(nom::Err::Error(nom::error::make_error(
143
0
                    bytes,
144
0
                    nom::error::ErrorKind::Verify,
145
0
                )));
146
1.10k
            }
147
1.10k
148
1.10k
            return Ok((&bytes[(n + 1)..], out));
149
217
        }
150
    }
151
152
211
    Err(nom::Err::Incomplete(nom::Needed::Unknown))
153
1.31k
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb12814nom_leb128_u64NtNvMNtNtB6_6libp2p7peer_idNtBY_9PublicKey22from_protobuf_encoding12ErrorWrapperEB6_
Line
Count
Source
116
162
pub(crate) fn nom_leb128_u64<'a, E: nom::error::ParseError<&'a [u8]>>(
117
162
    bytes: &'a [u8],
118
162
) -> nom::IResult<&'a [u8], u64, E> {
119
162
    let mut out = 0u64;
120
121
162
    for (n, byte) in bytes.iter().enumerate() {
122
162
        if (7 * n) >= usize::try_from(u64::BITS).unwrap() {
123
0
            return Err(nom::Err::Error(nom::error::make_error(
124
0
                bytes,
125
0
                nom::error::ErrorKind::LengthValue,
126
0
            )));
127
162
        }
128
162
129
162
        match u64::from(*byte & 0b111_1111).checked_mul(1 << (7 * n)) {
130
162
            Some(o) => out |= o,
131
            None => {
132
0
                return Err(nom::Err::Error(nom::error::make_error(
133
0
                    bytes,
134
0
                    nom::error::ErrorKind::LengthValue,
135
0
                )))
136
            }
137
        };
138
139
162
        if (*byte & 0x80) == 0 {
140
            // We want to avoid LEB128 numbers such as `[0x81, 0x0]`.
141
162
            if n >= 1 && 
*byte == 0x00
{
142
0
                return Err(nom::Err::Error(nom::error::make_error(
143
0
                    bytes,
144
0
                    nom::error::ErrorKind::Verify,
145
0
                )));
146
162
            }
147
162
148
162
            return Ok((&bytes[(n + 1)..], out));
149
0
        }
150
    }
151
152
0
    Err(nom::Err::Incomplete(nom::Needed::Unknown))
153
162
}
_RINvNtNtCsN16ciHI6Qf_7smoldot4util6leb12814nom_leb128_u64TRShNtNtCs6ga8gEqbpRc_3nom5error9ErrorKindEEB6_
Line
Count
Source
116
144
pub(crate) fn nom_leb128_u64<'a, E: nom::error::ParseError<&'a [u8]>>(
117
144
    bytes: &'a [u8],
118
144
) -> nom::IResult<&'a [u8], u64, E> {
119
144
    let mut out = 0u64;
120
121
144
    for (n, byte) in bytes.iter().enumerate() {
122
144
        if (7 * n) >= usize::try_from(u64::BITS).unwrap() {
123
0
            return Err(nom::Err::Error(nom::error::make_error(
124
0
                bytes,
125
0
                nom::error::ErrorKind::LengthValue,
126
0
            )));
127
144
        }
128
144
129
144
        match u64::from(*byte & 0b111_1111).checked_mul(1 << (7 * n)) {
130
144
            Some(o) => out |= o,
131
            None => {
132
0
                return Err(nom::Err::Error(nom::error::make_error(
133
0
                    bytes,
134
0
                    nom::error::ErrorKind::LengthValue,
135
0
                )))
136
            }
137
        };
138
139
144
        if (*byte & 0x80) == 0 {
140
            // We want to avoid LEB128 numbers such as `[0x81, 0x0]`.
141
144
            if n >= 1 && 
*byte == 0x00
{
142
0
                return Err(nom::Err::Error(nom::error::make_error(
143
0
                    bytes,
144
0
                    nom::error::ErrorKind::Verify,
145
0
                )));
146
144
            }
147
144
148
144
            return Ok((&bytes[(n + 1)..], out));
149
0
        }
150
    }
151
152
0
    Err(nom::Err::Incomplete(nom::Needed::Unknown))
153
144
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64TRShNtNtCs6ga8gEqbpRc_3nom5error9ErrorKindEECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsih6EgvAwZF2_13smoldot_light
_RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_
Line
Count
Source
116
1.46k
pub(crate) fn nom_leb128_u64<'a, E: nom::error::ParseError<&'a [u8]>>(
117
1.46k
    bytes: &'a [u8],
118
1.46k
) -> nom::IResult<&'a [u8], u64, E> {
119
1.46k
    let mut out = 0u64;
120
121
2.49k
    for (n, byte) in 
bytes.iter().enumerate()1.46k
{
122
2.49k
        if (7 * n) >= usize::try_from(u64::BITS).unwrap() {
123
0
            return Err(nom::Err::Error(nom::error::make_error(
124
0
                bytes,
125
0
                nom::error::ErrorKind::LengthValue,
126
0
            )));
127
2.49k
        }
128
2.49k
129
2.49k
        match u64::from(*byte & 0b111_1111).checked_mul(1 << (7 * n)) {
130
2.49k
            Some(o) => out |= o,
131
            None => {
132
0
                return Err(nom::Err::Error(nom::error::make_error(
133
0
                    bytes,
134
0
                    nom::error::ErrorKind::LengthValue,
135
0
                )))
136
            }
137
        };
138
139
2.49k
        if (*byte & 0x80) == 0 {
140
            // We want to avoid LEB128 numbers such as `[0x81, 0x0]`.
141
1.46k
            if n >= 1 && 
*byte == 0x0774
{
142
0
                return Err(nom::Err::Error(nom::error::make_error(
143
0
                    bytes,
144
0
                    nom::error::ErrorKind::Verify,
145
0
                )));
146
1.46k
            }
147
1.46k
148
1.46k
            return Ok((&bytes[(n + 1)..], out));
149
1.03k
        }
150
    }
151
152
0
    Err(nom::Err::Incomplete(nom::Needed::Unknown))
153
1.46k
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64NtNvMNtNtB6_6libp2p7peer_idNtBZ_9PublicKey22from_protobuf_encoding12ErrorWrapperEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64TRShNtNtCs6ga8gEqbpRc_3nom5error9ErrorKindEECsiUjFBJteJ7x_17smoldot_full_node
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4util6leb12814nom_leb128_u64INtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEECsibGXYHQB8Ea_25json_rpc_general_requests
154
155
#[cfg(test)]
156
mod tests {
157
    #[test]
158
1
    fn basic_encode() {
159
1
        let obtained = super::encode(0x123_4567_89ab_cdef_u64).collect::<Vec<_>>();
160
1
        assert_eq!(obtained, &[239, 155, 175, 205, 248, 172, 209, 145, 1]);
161
1
    }
162
163
    #[test]
164
1
    fn encode_zero() {
165
1
        let obtained = super::encode(0u64).collect::<Vec<_>>();
166
1
        assert_eq!(obtained, &[0x0u8]);
167
1
    }
168
169
    #[test]
170
1
    fn exact_size_iterator() {
171
129
        for _ in 0..128 {
172
128
            let iter = super::encode(rand::random::<u64>());
173
128
            let expected = iter.len();
174
128
            let obtained = iter.count();
175
128
            assert_eq!(expected, obtained);
176
        }
177
1
    }
178
179
    #[test]
180
1
    fn decode_large_value() {
181
1
        // Carefully crafted LEB128 that overflows the left shift before overflowing the
182
1
        // encoded size.
183
256
        let encoded = (0..256).map(|_| 129).collect::<Vec<_>>();
184
1
        assert!(super::nom_leb128_usize::<nom::error::Error<&[u8]>>(&encoded).is_err());
185
1
    }
186
187
    // TODO: more tests
188
}