1
1
#![doc= include_str!("../.rustme/docs.md")]
2
#![forbid(unsafe_code)]
3
#![warn(
4
    clippy::cargo,
5
    missing_docs,
6
    // clippy::missing_docs_in_private_items,
7
    clippy::nursery,
8
    clippy::pedantic,
9
    future_incompatible,
10
    rust_2018_idioms,
11
)]
12
#![cfg_attr(doc, allow(unknown_lints), warn(rustdoc::all))] // https://github.com/rust-lang/rust/pull/106316
13
#![allow(
14
    clippy::missing_errors_doc, // TODO clippy::missing_errors_doc
15
    clippy::option_if_let_else,
16
    clippy::module_name_repetitions,
17
    clippy::cast_sign_loss,
18
    clippy::cast_possible_truncation,
19
)]
20

            
21
mod signed;
22
mod unsigned;
23

            
24
use std::io::{Read, Write};
25

            
26
pub use self::signed::*;
27
pub use self::unsigned::*;
28

            
29
/// Encodes and decodes a type using a variable-length format.
30
pub trait Variable: Sized {
31
    /// Encodes `self` into `destination`, returning the number of bytes written upon success.
32
    fn encode_variable<W: Write>(&self, destination: W) -> std::io::Result<usize>;
33
    /// Decodes a variable length value from `source`.
34
    fn decode_variable<R: Read>(source: R) -> std::io::Result<Self>;
35

            
36
    /// Encodes `self` into a new `Vec<u8>`.
37
262515
    fn to_variable_vec(&self) -> std::io::Result<Vec<u8>> {
38
262515
        let mut output = Vec::with_capacity(16);
39
262515
        self.encode_variable(&mut output)?;
40
262515
        Ok(output)
41
262515
    }
42
}
43

            
44
macro_rules! impl_primitive_variable {
45
    ($ty:ty,  $dest:ty) => {
46
        impl Variable for $ty {
47
262614
            fn encode_variable<W: Write>(&self, destination: W) -> std::io::Result<usize> {
48
262614
                <$dest>::encode_be_bytes(self.to_be_bytes(), destination)
49
262614
            }
50

            
51
467
            fn decode_variable<R: Read>(source: R) -> std::io::Result<Self> {
52
467
                <$dest>::decode_variable_bytes(source).map(<Self>::from_be_bytes)
53
467
            }
54
        }
55
    };
56
}
57

            
58
impl_primitive_variable!(u8, Unsigned);
59
impl_primitive_variable!(u16, Unsigned);
60
impl_primitive_variable!(u32, Unsigned);
61
impl_primitive_variable!(u64, Unsigned);
62
impl_primitive_variable!(u128, Unsigned);
63
impl_primitive_variable!(usize, Unsigned);
64

            
65
impl_primitive_variable!(i8, Signed);
66
impl_primitive_variable!(i16, Signed);
67
impl_primitive_variable!(i32, Signed);
68
impl_primitive_variable!(i64, Signed);
69
impl_primitive_variable!(i128, Signed);
70
impl_primitive_variable!(isize, Signed);
71

            
72
#[cfg(test)]
73
mod tests {
74
    use std::fmt::Debug;
75

            
76
    use super::*;
77

            
78
    trait TestType: Variable {
79
        type Variable: From<Self> + TryInto<Self> + Variable + Eq + Debug;
80
    }
81

            
82
    macro_rules! impl_test_type {
83
        ($name:ident, $kind:ident) => {
84
            impl TestType for $name {
85
                type Variable = $kind;
86
            }
87
        };
88
    }
89

            
90
    impl_test_type!(u8, Unsigned);
91
    impl_test_type!(u16, Unsigned);
92
    impl_test_type!(u32, Unsigned);
93
    impl_test_type!(u64, Unsigned);
94
    impl_test_type!(u128, Unsigned);
95
    impl_test_type!(usize, Unsigned);
96

            
97
    impl_test_type!(i8, Signed);
98
    impl_test_type!(i16, Signed);
99
    impl_test_type!(i32, Signed);
100
    impl_test_type!(i64, Signed);
101
    impl_test_type!(i128, Signed);
102
    impl_test_type!(isize, Signed);
103

            
104
96
    fn roundtrip<T: TestType + Eq + Debug + Copy>(value: T, expected_bytes: usize) {
105
96
        let mut bytes = Vec::new();
106
96
        let encoded_length = value.encode_variable(&mut bytes).unwrap();
107
96
        println!("Encoded {value:?} to {bytes:02x?}");
108
96
        assert_eq!(
109
            encoded_length, expected_bytes,
110
            "expected {expected_bytes} encoded bytes, got {encoded_length}"
111
        );
112
96
        assert_eq!(
113
96
            encoded_length,
114
96
            bytes.len(),
115
            "vec has more bytes than returned value"
116
        );
117
96
        let decoded = T::decode_variable(&bytes[..]).unwrap();
118
96
        assert_eq!(
119
            decoded, value,
120
            "decoded value did not match: {value:?} vs {decoded:?}",
121
        );
122

            
123
        // Because we now decode and encode directly, we also need to test using
124
        // Signed/Unsigned
125
96
        let variable = <T::Variable as From<T>>::from(value);
126
96
        let mut bytes = Vec::new();
127
96
        let encoded_length = variable.encode_variable(&mut bytes).unwrap();
128
96
        assert_eq!(
129
            encoded_length, expected_bytes,
130
            "expected {expected_bytes} encoded bytes, got {encoded_length}"
131
        );
132
96
        assert_eq!(
133
96
            encoded_length,
134
96
            bytes.len(),
135
            "vec has more bytes than returned value"
136
        );
137
96
        let decoded = <T::Variable as Variable>::decode_variable(&bytes[..]).unwrap();
138
96
        assert_eq!(
139
            decoded, variable,
140
            "decoded value did not match: {variable:?} vs {decoded:?}",
141
        );
142
96
    }
143

            
144
1
    #[test]
145
1
    fn roundtrip_u8() {
146
1
        roundtrip(u8::MIN, 1);
147
1
        roundtrip(2_u8.pow(4) - 1, 1);
148
1
        roundtrip(2_u8.pow(4), 2);
149
1
    }
150

            
151
1
    #[test]
152
1
    fn roundtrip_i8() {
153
1
        roundtrip(0_i8, 1);
154
1
        roundtrip(2_i8.pow(3) - 1, 1);
155
1
        roundtrip(-(2_i8.pow(3)), 1);
156
1

            
157
1
        roundtrip(2_i8.pow(3), 2);
158
1
        roundtrip(-(2_i8.pow(3) + 1), 2);
159
1

            
160
1
        roundtrip(-1_i8, 1);
161
1
    }
162

            
163
1
    #[test]
164
1
    fn roundtrip_u16() {
165
1
        roundtrip(u16::from(u8::MAX), 2);
166
1
        roundtrip(2_u16.pow(12) - 1, 2);
167
1
        roundtrip(2_u16.pow(12), 3);
168
1
    }
169

            
170
1
    #[test]
171
1
    fn roundtrip_i16() {
172
1
        roundtrip(i16::from(i8::MAX), 2);
173
1
        roundtrip(i16::from(i8::MIN), 2);
174
1
        roundtrip(2_i16.pow(11) - 1, 2);
175
1
        roundtrip(-(2_i16.pow(11)), 2);
176
1

            
177
1
        roundtrip(2_i16.pow(11), 3);
178
1
        roundtrip(-(2_i16.pow(11) + 1), 3);
179
1

            
180
1
        roundtrip(-1_i16, 1);
181
1
    }
182

            
183
1
    #[test]
184
1
    fn roundtrip_u32() {
185
1
        roundtrip(u32::from(u16::MAX), 3);
186
1
        roundtrip(2_u32.pow(20) - 1, 3);
187
1
        roundtrip(2_u32.pow(20), 4);
188
1
        roundtrip(2_u32.pow(28) - 1, 4);
189
1
        roundtrip(2_u32.pow(28), 5);
190
1
    }
191

            
192
1
    #[test]
193
1
    fn roundtrip_i32() {
194
1
        roundtrip(i32::from(i16::MAX), 3);
195
1
        roundtrip(i32::from(i16::MIN), 3);
196
1
        roundtrip(2_i32.pow(19) - 1, 3);
197
1
        roundtrip(-(2_i32.pow(19)), 3);
198
1
        roundtrip(2_i32.pow(19), 4);
199
1
        roundtrip(-(2_i32.pow(19) + 1), 4);
200
1

            
201
1
        roundtrip(2_i32.pow(27), 5);
202
1
        roundtrip(-(2_i32.pow(27) + 1), 5);
203
1

            
204
1
        roundtrip(-1_i32, 1);
205
1
    }
206

            
207
1
    #[test]
208
1
    fn roundtrip_u64() {
209
1
        roundtrip(u64::from(u32::MAX), 5);
210
1
        roundtrip(2_u64.pow(36) - 1, 5);
211
1
        roundtrip(2_u64.pow(36), 6);
212
1
        roundtrip(2_u64.pow(44) - 1, 6);
213
1
        roundtrip(2_u64.pow(44), 7);
214
1
        roundtrip(2_u64.pow(52) - 1, 7);
215
1
        roundtrip(2_u64.pow(52), 8);
216
1
        roundtrip(2_u64.pow(60) - 1, 8);
217
1
        roundtrip(2_u64.pow(60), 9);
218
1
    }
219

            
220
1
    #[test]
221
1
    fn roundtrip_i64() {
222
1
        roundtrip(i64::from(i32::MAX), 5);
223
1
        roundtrip(i64::from(i32::MIN), 5);
224
1
        roundtrip(2_i64.pow(35) - 1, 5);
225
1
        roundtrip(-(2_i64.pow(35)), 5);
226
1
        roundtrip(2_i64.pow(35), 6);
227
1
        roundtrip(-(2_i64.pow(35) + 1), 6);
228
1

            
229
1
        roundtrip(2_i64.pow(43), 7);
230
1
        roundtrip(-(2_i64.pow(43) + 1), 7);
231
1

            
232
1
        roundtrip(2_i64.pow(51), 8);
233
1
        roundtrip(-(2_i64.pow(51) + 1), 8);
234
1

            
235
1
        roundtrip(2_i64.pow(59), 9);
236
1
        roundtrip(-(2_i64.pow(59) + 1), 9);
237
1

            
238
1
        roundtrip(-1_i64, 1);
239
1
    }
240

            
241
1
    #[test]
242
1
    fn roundtrip_u128() {
243
1
        roundtrip(u128::from(u64::MAX), 9);
244
1
        roundtrip(2_u128.pow(68) - 1, 9);
245
1
        roundtrip(2_u128.pow(68), 10);
246
1
        roundtrip(2_u128.pow(76) - 1, 10);
247
1
        roundtrip(2_u128.pow(76), 11);
248
1
        roundtrip(2_u128.pow(84) - 1, 11);
249
1
        roundtrip(2_u128.pow(84), 12);
250
1
        roundtrip(2_u128.pow(92) - 1, 12);
251
1
        roundtrip(2_u128.pow(92), 13);
252
1
        roundtrip(2_u128.pow(100) - 1, 13);
253
1
        roundtrip(2_u128.pow(100), 14);
254
1
        roundtrip(2_u128.pow(108) - 1, 14);
255
1
        roundtrip(2_u128.pow(108), 15);
256
1
        roundtrip(2_u128.pow(116) - 1, 15);
257
1
        roundtrip(2_u128.pow(116), 16);
258
1

            
259
1
        // Maximum value
260
1
        roundtrip(2_u128.pow(124) - 1, 16);
261
1

            
262
1
        // Above maximum value
263
1
        assert!(2_u128.pow(124).encode_variable(&mut Vec::new()).is_err());
264
1
    }
265

            
266
1
    #[test]
267
1
    fn roundtrip_i128() {
268
1
        roundtrip(i128::from(i64::MAX), 9);
269
1
        roundtrip(i128::from(i64::MIN), 9);
270
1
        roundtrip(2_i128.pow(67) - 1, 9);
271
1
        roundtrip(-(2_i128.pow(67)), 9);
272
1
        roundtrip(2_i128.pow(67), 10);
273
1
        roundtrip(-(2_i128.pow(67) + 1), 10);
274
1

            
275
1
        roundtrip(2_i128.pow(75), 11);
276
1
        roundtrip(-(2_i128.pow(75) + 1), 11);
277
1

            
278
1
        roundtrip(2_i128.pow(83), 12);
279
1
        roundtrip(-(2_i128.pow(83) + 1), 12);
280
1

            
281
1
        roundtrip(2_i128.pow(91), 13);
282
1
        roundtrip(-(2_i128.pow(91) + 1), 13);
283
1

            
284
1
        roundtrip(2_i128.pow(99), 14);
285
1
        roundtrip(-(2_i128.pow(99) + 1), 14);
286
1

            
287
1
        roundtrip(2_i128.pow(107), 15);
288
1
        roundtrip(-(2_i128.pow(107) + 1), 15);
289
1

            
290
1
        roundtrip(2_i128.pow(115), 16);
291
1
        roundtrip(-(2_i128.pow(115) + 1), 16);
292
1

            
293
1
        // Maximum value
294
1
        roundtrip(2_i128.pow(123) - 1, 16);
295
1
        // Minimum value
296
1
        roundtrip(-(2_i128.pow(123)), 16);
297
1

            
298
1
        // Above maximum
299
1
        assert!(2_i128.pow(123).encode_variable(&mut Vec::new()).is_err());
300
        // Below minimum
301
1
        assert!((-(2_i128.pow(123)) - 1)
302
1
            .encode_variable(&mut Vec::new())
303
1
            .is_err());
304
1
    }
305

            
306
1
    #[test]
307
1
    fn roundtrip_sizes() {
308
1
        // This test is minimal due to *size types being dependent on the
309
1
        // architecture limits.
310
1
        roundtrip(usize::MAX, std::mem::size_of::<usize>() + 1);
311
1
        roundtrip(usize::MIN, 1);
312
1
        roundtrip(isize::MAX, std::mem::size_of::<isize>() + 1);
313
1
        roundtrip(isize::MIN, std::mem::size_of::<isize>() + 1);
314
1
        roundtrip(0_isize, 1);
315
1
    }
316

            
317
1
    #[test]
318
1
    fn conversions() {
319
1
        assert_eq!(
320
1
            isize::try_from(Signed::from(isize::MAX)).unwrap(),
321
1
            isize::MAX
322
1
        );
323
1
        assert_eq!(
324
1
            usize::try_from(Unsigned::from(usize::MAX)).unwrap(),
325
1
            usize::MAX
326
1
        );
327
1
        assert_eq!(i128::try_from(Signed::from(i128::MAX)).unwrap(), i128::MAX);
328
1
        assert_eq!(
329
1
            u128::try_from(Unsigned::from(u128::MAX)).unwrap(),
330
1
            u128::MAX
331
1
        );
332
1
    }
333

            
334
1
    #[test]
335
1
    fn test_signed_ordering() {
336
1
        let mut entries = Vec::new();
337
65537
        for i in i16::MIN..=i16::MAX {
338
65536
            println!("{} => {:02X?}", i, i.to_variable_vec().unwrap());
339
65536
            entries.push(i.to_variable_vec().unwrap());
340
65536
        }
341
1
        let originals = entries.clone();
342
1
        entries.sort();
343
1
        assert_eq!(originals, entries);
344
1
    }
345

            
346
1
    #[test]
347
1
    fn test_unsigned_ordering() {
348
1
        let mut entries = Vec::new();
349
65537
        for i in u16::MIN..=u16::MAX {
350
65536
            println!("{} => {:02X?}", i, i.to_variable_vec().unwrap());
351
65536
            entries.push(i.to_variable_vec().unwrap());
352
65536
        }
353
1
        let originals = entries.clone();
354
1
        entries.sort();
355
1
        assert_eq!(originals, entries);
356
1
    }
357

            
358
1
    #[test]
359
1
    fn overflow_decode() {
360
1
        let unsigned_max = u64::MAX.to_variable_vec().unwrap();
361
1
        u32::decode_variable(&unsigned_max[..]).expect_err("u32 should overflow");
362
1
        let signed_min = i64::MIN.to_variable_vec().unwrap();
363
1
        i32::decode_variable(&signed_min[..]).expect_err("i32 should overflow");
364
1
        let signed_max = i64::MAX.to_variable_vec().unwrap();
365
1
        i32::decode_variable(&signed_max[..]).expect_err("i32 should overflow");
366
1
    }
367
}