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
#![deny(clippy::all)]
#![deny(missing_docs)]
use codicon::*;
use signrel::SignRel;
use uabs::Uabs;
pub struct Leb128;
#[derive(Debug)]
pub enum Error {
IoError(std::io::Error),
Overflow,
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Overflow => None,
Error::IoError(e) => Some(e),
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
Error::IoError(ref e) => e.fmt(f),
Error::Overflow => write!(f, "LEB128 integer overflow"),
}
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::IoError(e)
}
}
trait ByteMax: SignRel {
const BYTE_MAX: Self::Unsigned;
}
const CONT: u8 = 0b10000000;
macro_rules! leb_impl {
($($s:ident:$u:ident)*) => (
$(
impl ByteMax for $s {
const BYTE_MAX: Self::Unsigned = 0b00111111;
}
impl ByteMax for $u {
const BYTE_MAX: Self::Unsigned = 0b01111111;
}
leb_impl! { $s }
leb_impl! { $u }
)*
);
($t:ident) => (
impl Decoder<Leb128> for $t {
type Error = Error;
fn decode(mut reader: impl Read, _: Leb128) -> Result<Self, Error> {
const BITS: u32 = std::mem::size_of::<$t>() as u32 * 8;
let mut value = <Self as SignRel>::Unsigned::from(0u8);
let mut shift = 0u32;
let mut byte = CONT;
while byte & CONT == CONT {
if shift > BITS {
return Err(Error::Overflow);
}
let mut bytes = [0u8; 1];
reader.read_exact(&mut bytes)?;
byte = bytes[0];
let low = <Self as SignRel>::Unsigned::from(byte & !CONT);
value |= low << shift;
shift += 7;
}
if shift > BITS {
let offs = 1 - (Self::BYTE_MAX >> 6);
let mask = 0b11111111 << 7 - (shift - BITS) >> offs;
if byte & mask != mask && byte & mask != 0 {
return Err(Error::Overflow);
}
}
let off = BITS - std::cmp::min(shift, BITS);
value <<= off;
Ok(value as Self >> off)
}
}
impl Encoder<Leb128> for $t {
type Error = std::io::Error;
fn encode(&self, mut writer: impl Write, _: Leb128) -> std::io::Result<()> {
let mut value = *self;
while value.uabs() > Self::BYTE_MAX {
writer.write_all(&[value as u8 | CONT])?;
value >>= 7;
}
Ok(writer.write_all(&[value as u8 & !CONT])?)
}
}
);
}
leb_impl! { isize:usize i128:u128 i64:u64 i32:u32 i16:u16 i8:u8 }