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
use std::{
io::{Read, Write},
num::TryFromIntError,
};
use crate::Variable;
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub struct Unsigned(pub(crate) u128);
impl Variable for Unsigned {
fn encode_variable<W: Write>(&self, output: &mut W) -> std::io::Result<usize> {
if self.0 >> 124 != 0 {
return Err(std::io::Error::from(std::io::ErrorKind::InvalidData));
}
let mut value = self.0.to_be_bytes();
let (total_length, extra_bytes) = value
.iter()
.enumerate()
.find_map(|(index, &byte)| {
if byte > 0 {
let extra_bytes = 15 - index;
if byte < 16 {
Some((extra_bytes + 1, extra_bytes))
} else {
Some((extra_bytes + 2, extra_bytes + 1))
}
} else {
None
}
})
.unwrap_or((0, 0));
let total_length = total_length.max(1);
value[16 - total_length] |= (extra_bytes as u8) << 4;
output.write_all(&value[16 - total_length..])?;
Ok(total_length)
}
fn decode_variable<R: Read>(mut input: R) -> std::io::Result<Self> {
let mut buffer = [0_u8; 16];
input.read_exact(&mut buffer[0..1])?;
let length = (buffer[0] >> 4) as usize;
input.read_exact(&mut buffer[16 - length as usize..])?;
if length < 15 {
buffer[15 - length] |= buffer[0] & 0b1111;
buffer[0] = 0;
} else {
buffer[0] &= 0b1111;
}
Ok(Self(u128::from_be_bytes(buffer)))
}
}
macro_rules! impl_primitive_from_varint {
($ty:ty, $dest:ty) => {
impl TryFrom<Unsigned> for $ty {
type Error = TryFromIntError;
fn try_from(value: Unsigned) -> Result<Self, Self::Error> {
value.0.try_into()
}
}
};
}
macro_rules! impl_varint_from_primitive {
($ty:ty, $dest:ty) => {
impl From<$ty> for Unsigned {
fn from(value: $ty) -> Self {
Self(<$dest>::from(value))
}
}
};
}
impl_varint_from_primitive!(u8, u128);
impl_varint_from_primitive!(u16, u128);
impl_varint_from_primitive!(u32, u128);
impl_varint_from_primitive!(u64, u128);
impl_varint_from_primitive!(u128, u128);
impl_primitive_from_varint!(u8, u128);
impl_primitive_from_varint!(u16, u128);
impl_primitive_from_varint!(u32, u128);
impl_primitive_from_varint!(u64, u128);
impl TryFrom<Unsigned> for u128 {
type Error = TryFromIntError;
fn try_from(value: Unsigned) -> Result<Self, Self::Error> {
Ok(value.0)
}
}