embedded_jsonrpc/
varint.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! # Varint Encoding and Decoding Library
//!
//! This crate provides utilities for encoding and decoding unsigned integers (`usize`)
//! using the variable-length integer (varint) format. Varints are commonly used in protocols
//! and file formats like Protocol Buffers to efficiently encode integers of varying sizes.
//!
//! ## Functionality
//!
//! - [`encode`] - Encodes a `usize` value into a buffer as a varint and returns the number of bytes written.
//! - [`decode`] - Decodes a varint from a byte buffer, returning the value and the number of bytes read.
//!
//! ## Examples
//!
//! ### Encoding a Value
//!
//! ```rust
//! use embedded_jsonrpc::varint::encode;
//!
//! let mut buffer = [0u8; 10]; // Create a buffer with sufficient size
//! let bytes_written = encode(300, &mut buffer);
//! println!("Encoded 300 into {:?} using {} bytes", &buffer[..bytes_written], bytes_written);
//! ```
//!
//! ### Decoding a Value
//!
//! ```rust
//! use embedded_jsonrpc::varint::decode;
//!
//! let buffer = [0xac, 0x02]; // Encoded varint for 300
//! if let Some((value, bytes_read)) = decode(&buffer) {
//!     println!("Decoded value: {}, bytes read: {}", value, bytes_read);
//! } else {
//!     println!("Failed to decode value");
//! }
//! ```
//!
//! ## License
//!
//! This crate is licensed under the Mozilla Public License 2.0 (MPL-2.0).
//! See the LICENSE file for more details.
//!

/// Encodes a usize into a varint and writes it into the provided buffer.
/// Returns the number of bytes written.
pub fn encode(value: usize, buf: &mut [u8]) -> usize {
    let mut value = value;
    let mut i = 0;

    while value >= 0x80 {
        buf[i] = (value as u8 & 0x7F) | 0x80; // Lower 7 bits + MSB = 1
        value >>= 7; // Shift out the lower 7 bits
        i += 1;
    }

    buf[i] = value as u8; // Write the final byte with MSB = 0
    i + 1
}

/// Decodes a varint from the provided buffer.
/// Returns the decoded value and the number of bytes read, or `None` if the buffer is incomplete.
pub fn decode(buf: &[u8]) -> Option<(usize, usize)> {
    let mut value = 0usize;
    let mut shift = 0;
    let mut i = 0;

    for byte in buf {
        let byte = *byte as usize;
        value |= (byte & 0x7F) << shift; // Add the lower 7 bits to the value
        shift += 7;

        i += 1;
        if byte & 0x80 == 0 {
            // MSB = 0 indicates the end of the varint
            return Some((value, i));
        }

        if shift >= usize::BITS as usize {
            // Varint is too long; invalid
            return None;
        }
    }

    None // Buffer ended before varint was fully decoded
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_known_vectors() {
        // These arrays are of the form (value, expected_encoded_form).
        let vectors: [(usize, [u8; 10], usize); 9] = [
            (0, [0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
            (1, [0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
            (127, [0x7f, 0, 0, 0, 0, 0, 0, 0, 0, 0], 1),
            (128, [0x80, 0x01, 0, 0, 0, 0, 0, 0, 0, 0], 2),
            (255, [0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0], 2),
            (300, [0xac, 0x02, 0, 0, 0, 0, 0, 0, 0, 0], 2),
            (16384, [0x80, 0x80, 0x01, 0, 0, 0, 0, 0, 0, 0], 3),
            (2097151, [0xff, 0xff, 0x7f, 0, 0, 0, 0, 0, 0, 0], 3),
            (268435455, [0xff, 0xff, 0xff, 0x7f, 0, 0, 0, 0, 0, 0], 4),
        ];

        for (val, expected, expected_size) in vectors.iter() {
            let mut buf = [0u8; 10]; // Buffer larger than necessary to test encoding
            let encoded_size = encode(*val, &mut buf);
            assert_eq!(
                &buf[..encoded_size],
                &expected[..*expected_size],
                "Failed encoding for value {}",
                val
            );

            let decoded = decode(&buf[..encoded_size]).unwrap();
            assert_eq!(
                decoded,
                (*val, *expected_size),
                "Failed decoding for value {}",
                val
            );
        }
    }

    #[test]
    fn test_encoding_decoding_round_trip() {
        let mut buf = [0u8; 10];
        let values = [
            0,
            1,
            127,
            128,
            255,
            1023,
            16383,
            16384,
            2097151,
            268435455,
            usize::MAX,
        ];

        for &val in &values {
            let encoded_size = encode(val, &mut buf);
            let decoded = decode(&buf[..encoded_size]).unwrap();
            assert_eq!(
                decoded,
                (val, encoded_size),
                "Failed round-trip for value {}",
                val
            );
        }
    }

    #[test]
    fn test_incomplete_buffer() {
        let mut buf = [0u8; 2];
        encode(300, &mut buf);
        assert_eq!(
            decode(&buf[..1]),
            None,
            "Should have failed due to incomplete buffer"
        ); // Incomplete varint
    }

    #[test]
    fn test_invalid_varint_too_long() {
        let mut buf = [0x80u8; 11]; // All continuation bits set
        buf[10] = 0; // Terminate varint
        assert_eq!(
            decode(&buf),
            None,
            "Should have failed due to varint being too long"
        ); // More than 10 bytes, thus more than usize bits, invalid for usize
    }
}