]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_serialize/src/leb128.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_serialize / src / leb128.rs
CommitLineData
49aad941
FG
1use crate::opaque::MemDecoder;
2use crate::serialize::Decoder;
3
487cf647
FG
4/// Returns the length of the longest LEB128 encoding for `T`, assuming `T` is an integer type
5pub const fn max_leb128_len<T>() -> usize {
6 // The longest LEB128 encoding for an integer uses 7 bits per byte.
7 (std::mem::size_of::<T>() * 8 + 6) / 7
5869c6ff
XL
8}
9
487cf647
FG
10/// Returns the length of the longest LEB128 encoding of all supported integer types.
11pub const fn largest_max_leb128_len() -> usize {
12 max_leb128_len::<u128>()
5869c6ff
XL
13}
14
2c00a5a8 15macro_rules! impl_write_unsigned_leb128 {
5869c6ff 16 ($fn_name:ident, $int_ty:ty) => {
2c00a5a8 17 #[inline]
5869c6ff 18 pub fn $fn_name(
487cf647 19 out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
5869c6ff
XL
20 mut value: $int_ty,
21 ) -> &[u8] {
22 let mut i = 0;
23
74b04a01
XL
24 loop {
25 if value < 0x80 {
5869c6ff
XL
26 unsafe {
27 *out.get_unchecked_mut(i).as_mut_ptr() = value as u8;
28 }
29
30 i += 1;
2c00a5a8 31 break;
74b04a01 32 } else {
5869c6ff
XL
33 unsafe {
34 *out.get_unchecked_mut(i).as_mut_ptr() = ((value & 0x7f) | 0x80) as u8;
35 }
36
74b04a01 37 value >>= 7;
5869c6ff 38 i += 1;
2c00a5a8
XL
39 }
40 }
5869c6ff
XL
41
42 unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
9cc50fc6 43 }
dfeec247 44 };
476ff2be
SL
45}
46
2c00a5a8
XL
47impl_write_unsigned_leb128!(write_u16_leb128, u16);
48impl_write_unsigned_leb128!(write_u32_leb128, u32);
49impl_write_unsigned_leb128!(write_u64_leb128, u64);
50impl_write_unsigned_leb128!(write_u128_leb128, u128);
51impl_write_unsigned_leb128!(write_usize_leb128, usize);
52
2c00a5a8 53macro_rules! impl_read_unsigned_leb128 {
5869c6ff 54 ($fn_name:ident, $int_ty:ty) => {
2c00a5a8 55 #[inline]
49aad941 56 pub fn $fn_name(decoder: &mut MemDecoder<'_>) -> $int_ty {
5099ac24
FG
57 // The first iteration of this loop is unpeeled. This is a
58 // performance win because this code is hot and integer values less
59 // than 128 are very common, typically occurring 50-80% or more of
60 // the time, even for u64 and u128.
49aad941 61 let byte = decoder.read_u8();
5099ac24
FG
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;
74b04a01 67 loop {
49aad941 68 let byte = decoder.read_u8();
2c00a5a8 69 if (byte & 0x80) == 0 {
74b04a01 70 result |= (byte as $int_ty) << shift;
5099ac24 71 return result;
74b04a01
XL
72 } else {
73 result |= ((byte & 0x7F) as $int_ty) << shift;
2c00a5a8
XL
74 }
75 shift += 7;
76 }
2c00a5a8 77 }
dfeec247 78 };
9cc50fc6
SL
79}
80
2c00a5a8
XL
81impl_read_unsigned_leb128!(read_u16_leb128, u16);
82impl_read_unsigned_leb128!(read_u32_leb128, u32);
83impl_read_unsigned_leb128!(read_u64_leb128, u64);
84impl_read_unsigned_leb128!(read_u128_leb128, u128);
85impl_read_unsigned_leb128!(read_usize_leb128, usize);
86
5869c6ff
XL
87macro_rules! impl_write_signed_leb128 {
88 ($fn_name:ident, $int_ty:ty) => {
89 #[inline]
90 pub fn $fn_name(
487cf647 91 out: &mut [::std::mem::MaybeUninit<u8>; max_leb128_len::<$int_ty>()],
5869c6ff
XL
92 mut value: $int_ty,
93 ) -> &[u8] {
94 let mut i = 0;
95
96 loop {
97 let mut byte = (value as u8) & 0x7f;
98 value >>= 7;
99 let more = !(((value == 0) && ((byte & 0x40) == 0))
100 || ((value == -1) && ((byte & 0x40) != 0)));
9cc50fc6 101
5869c6ff
XL
102 if more {
103 byte |= 0x80; // Mark this byte to show that more bytes will follow.
104 }
105
106 unsafe {
107 *out.get_unchecked_mut(i).as_mut_ptr() = byte;
108 }
109
110 i += 1;
111
112 if !more {
113 break;
114 }
115 }
9cc50fc6 116
5869c6ff 117 unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
9cc50fc6 118 }
5869c6ff 119 };
476ff2be
SL
120}
121
5869c6ff
XL
122impl_write_signed_leb128!(write_i16_leb128, i16);
123impl_write_signed_leb128!(write_i32_leb128, i32);
124impl_write_signed_leb128!(write_i64_leb128, i64);
125impl_write_signed_leb128!(write_i128_leb128, i128);
126impl_write_signed_leb128!(write_isize_leb128, isize);
9cc50fc6 127
5869c6ff
XL
128macro_rules! impl_read_signed_leb128 {
129 ($fn_name:ident, $int_ty:ty) => {
130 #[inline]
49aad941 131 pub fn $fn_name(decoder: &mut MemDecoder<'_>) -> $int_ty {
5869c6ff
XL
132 let mut result = 0;
133 let mut shift = 0;
5869c6ff 134 let mut byte;
9cc50fc6 135
5869c6ff 136 loop {
49aad941 137 byte = decoder.read_u8();
5869c6ff
XL
138 result |= <$int_ty>::from(byte & 0x7F) << shift;
139 shift += 7;
9cc50fc6 140
5869c6ff
XL
141 if (byte & 0x80) == 0 {
142 break;
143 }
144 }
145
146 if (shift < <$int_ty>::BITS) && ((byte & 0x40) != 0) {
147 // sign extend
148 result |= (!0 << shift);
149 }
150
5099ac24 151 result
5869c6ff
XL
152 }
153 };
9cc50fc6 154}
5869c6ff
XL
155
156impl_read_signed_leb128!(read_i16_leb128, i16);
157impl_read_signed_leb128!(read_i32_leb128, i32);
158impl_read_signed_leb128!(read_i64_leb128, i64);
159impl_read_signed_leb128!(read_i128_leb128, i128);
160impl_read_signed_leb128!(read_isize_leb128, isize);