rustc_serialize/
leb128.rs1use crate::int_overflow::DebugStrictAdd;
4use crate::opaque::MemDecoder;
5use crate::serialize::Decoder;
6
7pub const fn max_leb128_len<T>() -> usize {
9 (size_of::<T>() * 8).div_ceil(7)
11}
12
13pub const fn largest_max_leb128_len() -> usize {
15 max_leb128_len::<u128>()
16}
17
18macro_rules! impl_write_unsigned_leb128 {
19 ($fn_name:ident, $int_ty:ty) => {
20 #[inline]
21 pub fn $fn_name(out: &mut [u8; max_leb128_len::<$int_ty>()], mut value: $int_ty) -> usize {
22 let mut i = 0;
23
24 loop {
25 if value < 0x80 {
26 unsafe {
27 *out.get_unchecked_mut(i) = value as u8;
28 }
29
30 i = i.debug_strict_add(1);
31 break;
32 } else {
33 unsafe {
34 *out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
35 }
36
37 value >>= 7;
38 i = i.debug_strict_add(1);
39 }
40 }
41
42 i
43 }
44 };
45}
46
47#[inline]
pub fn write_u16_leb128(out: &mut [u8; max_leb128_len::<u16>()],
mut value: u16) -> usize {
let mut i = 0;
loop {
if value < 0x80 {
unsafe { *out.get_unchecked_mut(i) = value as u8; }
i = i.debug_strict_add(1);
break;
} else {
unsafe {
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
}
value >>= 7;
i = i.debug_strict_add(1);
}
}
i
}impl_write_unsigned_leb128!(write_u16_leb128, u16);
48#[inline]
pub fn write_u32_leb128(out: &mut [u8; max_leb128_len::<u32>()],
mut value: u32) -> usize {
let mut i = 0;
loop {
if value < 0x80 {
unsafe { *out.get_unchecked_mut(i) = value as u8; }
i = i.debug_strict_add(1);
break;
} else {
unsafe {
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
}
value >>= 7;
i = i.debug_strict_add(1);
}
}
i
}impl_write_unsigned_leb128!(write_u32_leb128, u32);
49#[inline]
pub fn write_u64_leb128(out: &mut [u8; max_leb128_len::<u64>()],
mut value: u64) -> usize {
let mut i = 0;
loop {
if value < 0x80 {
unsafe { *out.get_unchecked_mut(i) = value as u8; }
i = i.debug_strict_add(1);
break;
} else {
unsafe {
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
}
value >>= 7;
i = i.debug_strict_add(1);
}
}
i
}impl_write_unsigned_leb128!(write_u64_leb128, u64);
50#[inline]
pub fn write_u128_leb128(out: &mut [u8; max_leb128_len::<u128>()],
mut value: u128) -> usize {
let mut i = 0;
loop {
if value < 0x80 {
unsafe { *out.get_unchecked_mut(i) = value as u8; }
i = i.debug_strict_add(1);
break;
} else {
unsafe {
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
}
value >>= 7;
i = i.debug_strict_add(1);
}
}
i
}impl_write_unsigned_leb128!(write_u128_leb128, u128);
51#[inline]
pub fn write_usize_leb128(out: &mut [u8; max_leb128_len::<usize>()],
mut value: usize) -> usize {
let mut i = 0;
loop {
if value < 0x80 {
unsafe { *out.get_unchecked_mut(i) = value as u8; }
i = i.debug_strict_add(1);
break;
} else {
unsafe {
*out.get_unchecked_mut(i) = ((value & 0x7f) | 0x80) as u8;
}
value >>= 7;
i = i.debug_strict_add(1);
}
}
i
}impl_write_unsigned_leb128!(write_usize_leb128, usize);
52
53macro_rules! impl_read_unsigned_leb128 {
54 ($fn_name:ident, $int_ty:ty) => {
55 #[inline]
56 pub fn $fn_name(decoder: &mut MemDecoder<'_>) -> $int_ty {
57 let byte = decoder.read_u8();
62 if (byte & 0x80) == 0 {
63 return byte as $int_ty;
64 }
65 let mut result = (byte & 0x7F) as $int_ty;
66 let mut shift = 7;
67 loop {
68 let byte = decoder.read_u8();
69 if (byte & 0x80) == 0 {
70 result |= (byte as $int_ty) << shift;
71 return result;
72 } else {
73 result |= ((byte & 0x7F) as $int_ty) << shift;
74 }
75 shift = shift.debug_strict_add(7);
76 }
77 }
78 };
79}
80
81#[inline]
pub fn read_u16_leb128(decoder: &mut MemDecoder<'_>) -> u16 {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 { return byte as u16; }
let mut result = (byte & 0x7F) as u16;
let mut shift = 7;
loop {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 {
result |= (byte as u16) << shift;
return result;
} else { result |= ((byte & 0x7F) as u16) << shift; }
shift = shift.debug_strict_add(7);
}
}impl_read_unsigned_leb128!(read_u16_leb128, u16);
82#[inline]
pub fn read_u32_leb128(decoder: &mut MemDecoder<'_>) -> u32 {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 { return byte as u32; }
let mut result = (byte & 0x7F) as u32;
let mut shift = 7;
loop {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 {
result |= (byte as u32) << shift;
return result;
} else { result |= ((byte & 0x7F) as u32) << shift; }
shift = shift.debug_strict_add(7);
}
}impl_read_unsigned_leb128!(read_u32_leb128, u32);
83#[inline]
pub fn read_u64_leb128(decoder: &mut MemDecoder<'_>) -> u64 {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 { return byte as u64; }
let mut result = (byte & 0x7F) as u64;
let mut shift = 7;
loop {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 {
result |= (byte as u64) << shift;
return result;
} else { result |= ((byte & 0x7F) as u64) << shift; }
shift = shift.debug_strict_add(7);
}
}impl_read_unsigned_leb128!(read_u64_leb128, u64);
84#[inline]
pub fn read_u128_leb128(decoder: &mut MemDecoder<'_>) -> u128 {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 { return byte as u128; }
let mut result = (byte & 0x7F) as u128;
let mut shift = 7;
loop {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 {
result |= (byte as u128) << shift;
return result;
} else { result |= ((byte & 0x7F) as u128) << shift; }
shift = shift.debug_strict_add(7);
}
}impl_read_unsigned_leb128!(read_u128_leb128, u128);
85#[inline]
pub fn read_usize_leb128(decoder: &mut MemDecoder<'_>) -> usize {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 { return byte as usize; }
let mut result = (byte & 0x7F) as usize;
let mut shift = 7;
loop {
let byte = decoder.read_u8();
if (byte & 0x80) == 0 {
result |= (byte as usize) << shift;
return result;
} else { result |= ((byte & 0x7F) as usize) << shift; }
shift = shift.debug_strict_add(7);
}
}impl_read_unsigned_leb128!(read_usize_leb128, usize);
86
87macro_rules! impl_write_signed_leb128 {
88 ($fn_name:ident, $int_ty:ty) => {
89 #[inline]
90 pub fn $fn_name(out: &mut [u8; max_leb128_len::<$int_ty>()], mut value: $int_ty) -> usize {
91 let mut i = 0;
92
93 loop {
94 let mut byte = (value as u8) & 0x7f;
95 value >>= 7;
96 let more = !(((value == 0) && ((byte & 0x40) == 0))
97 || ((value == -1) && ((byte & 0x40) != 0)));
98
99 if more {
100 byte |= 0x80; }
102
103 unsafe {
104 *out.get_unchecked_mut(i) = byte;
105 }
106
107 i = i.debug_strict_add(1);
108
109 if !more {
110 break;
111 }
112 }
113
114 i
115 }
116 };
117}
118
119#[inline]
pub fn write_i16_leb128(out: &mut [u8; max_leb128_len::<i16>()],
mut value: i16) -> usize {
let mut i = 0;
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
let more =
!(((value == 0) && ((byte & 0x40) == 0)) ||
((value == -1) && ((byte & 0x40) != 0)));
if more { byte |= 0x80; }
unsafe { *out.get_unchecked_mut(i) = byte; }
i = i.debug_strict_add(1);
if !more { break; }
}
i
}impl_write_signed_leb128!(write_i16_leb128, i16);
120#[inline]
pub fn write_i32_leb128(out: &mut [u8; max_leb128_len::<i32>()],
mut value: i32) -> usize {
let mut i = 0;
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
let more =
!(((value == 0) && ((byte & 0x40) == 0)) ||
((value == -1) && ((byte & 0x40) != 0)));
if more { byte |= 0x80; }
unsafe { *out.get_unchecked_mut(i) = byte; }
i = i.debug_strict_add(1);
if !more { break; }
}
i
}impl_write_signed_leb128!(write_i32_leb128, i32);
121#[inline]
pub fn write_i64_leb128(out: &mut [u8; max_leb128_len::<i64>()],
mut value: i64) -> usize {
let mut i = 0;
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
let more =
!(((value == 0) && ((byte & 0x40) == 0)) ||
((value == -1) && ((byte & 0x40) != 0)));
if more { byte |= 0x80; }
unsafe { *out.get_unchecked_mut(i) = byte; }
i = i.debug_strict_add(1);
if !more { break; }
}
i
}impl_write_signed_leb128!(write_i64_leb128, i64);
122#[inline]
pub fn write_i128_leb128(out: &mut [u8; max_leb128_len::<i128>()],
mut value: i128) -> usize {
let mut i = 0;
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
let more =
!(((value == 0) && ((byte & 0x40) == 0)) ||
((value == -1) && ((byte & 0x40) != 0)));
if more { byte |= 0x80; }
unsafe { *out.get_unchecked_mut(i) = byte; }
i = i.debug_strict_add(1);
if !more { break; }
}
i
}impl_write_signed_leb128!(write_i128_leb128, i128);
123#[inline]
pub fn write_isize_leb128(out: &mut [u8; max_leb128_len::<isize>()],
mut value: isize) -> usize {
let mut i = 0;
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
let more =
!(((value == 0) && ((byte & 0x40) == 0)) ||
((value == -1) && ((byte & 0x40) != 0)));
if more { byte |= 0x80; }
unsafe { *out.get_unchecked_mut(i) = byte; }
i = i.debug_strict_add(1);
if !more { break; }
}
i
}impl_write_signed_leb128!(write_isize_leb128, isize);
124
125macro_rules! impl_read_signed_leb128 {
126 ($fn_name:ident, $int_ty:ty) => {
127 #[inline]
128 pub fn $fn_name(decoder: &mut MemDecoder<'_>) -> $int_ty {
129 let mut result = 0;
130 let mut shift = 0;
131 let mut byte;
132
133 loop {
134 byte = decoder.read_u8();
135 result |= <$int_ty>::from(byte & 0x7F) << shift;
136 shift = shift.debug_strict_add(7);
137
138 if (byte & 0x80) == 0 {
139 break;
140 }
141 }
142
143 if (shift < <$int_ty>::BITS) && ((byte & 0x40) != 0) {
144 result |= (!0 << shift);
146 }
147
148 result
149 }
150 };
151}
152
153#[inline]
pub fn read_i16_leb128(decoder: &mut MemDecoder<'_>) -> i16 {
let mut result = 0;
let mut shift = 0;
let mut byte;
loop {
byte = decoder.read_u8();
result |= <i16>::from(byte & 0x7F) << shift;
shift = shift.debug_strict_add(7);
if (byte & 0x80) == 0 { break; }
}
if (shift < <i16>::BITS) && ((byte & 0x40) != 0) {
result |= (!0 << shift);
}
result
}impl_read_signed_leb128!(read_i16_leb128, i16);
154#[inline]
pub fn read_i32_leb128(decoder: &mut MemDecoder<'_>) -> i32 {
let mut result = 0;
let mut shift = 0;
let mut byte;
loop {
byte = decoder.read_u8();
result |= <i32>::from(byte & 0x7F) << shift;
shift = shift.debug_strict_add(7);
if (byte & 0x80) == 0 { break; }
}
if (shift < <i32>::BITS) && ((byte & 0x40) != 0) {
result |= (!0 << shift);
}
result
}impl_read_signed_leb128!(read_i32_leb128, i32);
155#[inline]
pub fn read_i64_leb128(decoder: &mut MemDecoder<'_>) -> i64 {
let mut result = 0;
let mut shift = 0;
let mut byte;
loop {
byte = decoder.read_u8();
result |= <i64>::from(byte & 0x7F) << shift;
shift = shift.debug_strict_add(7);
if (byte & 0x80) == 0 { break; }
}
if (shift < <i64>::BITS) && ((byte & 0x40) != 0) {
result |= (!0 << shift);
}
result
}impl_read_signed_leb128!(read_i64_leb128, i64);
156#[inline]
pub fn read_i128_leb128(decoder: &mut MemDecoder<'_>) -> i128 {
let mut result = 0;
let mut shift = 0;
let mut byte;
loop {
byte = decoder.read_u8();
result |= <i128>::from(byte & 0x7F) << shift;
shift = shift.debug_strict_add(7);
if (byte & 0x80) == 0 { break; }
}
if (shift < <i128>::BITS) && ((byte & 0x40) != 0) {
result |= (!0 << shift);
}
result
}impl_read_signed_leb128!(read_i128_leb128, i128);
157#[inline]
pub fn read_isize_leb128(decoder: &mut MemDecoder<'_>) -> isize {
let mut result = 0;
let mut shift = 0;
let mut byte;
loop {
byte = decoder.read_u8();
result |= <isize>::from(byte & 0x7F) << shift;
shift = shift.debug_strict_add(7);
if (byte & 0x80) == 0 { break; }
}
if (shift < <isize>::BITS) && ((byte & 0x40) != 0) {
result |= (!0 << shift);
}
result
}impl_read_signed_leb128!(read_isize_leb128, isize);
158
159#[cfg(test)]
160mod tests;