]> git.proxmox.com Git - rustc.git/blame - src/librustc_serialize/leb128.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_serialize / leb128.rs
CommitLineData
2c00a5a8 1macro_rules! impl_write_unsigned_leb128 {
dfeec247 2 ($fn_name:ident, $int_ty:ident) => {
2c00a5a8 3 #[inline]
8faf50e0 4 pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) {
74b04a01
XL
5 loop {
6 if value < 0x80 {
7 out.push(value as u8);
2c00a5a8 8 break;
74b04a01
XL
9 } else {
10 out.push(((value & 0x7f) | 0x80) as u8);
11 value >>= 7;
2c00a5a8
XL
12 }
13 }
9cc50fc6 14 }
dfeec247 15 };
476ff2be
SL
16}
17
2c00a5a8
XL
18impl_write_unsigned_leb128!(write_u16_leb128, u16);
19impl_write_unsigned_leb128!(write_u32_leb128, u32);
20impl_write_unsigned_leb128!(write_u64_leb128, u64);
21impl_write_unsigned_leb128!(write_u128_leb128, u128);
22impl_write_unsigned_leb128!(write_usize_leb128, usize);
23
2c00a5a8 24macro_rules! impl_read_unsigned_leb128 {
dfeec247 25 ($fn_name:ident, $int_ty:ident) => {
2c00a5a8
XL
26 #[inline]
27 pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
74b04a01 28 let mut result = 0;
2c00a5a8
XL
29 let mut shift = 0;
30 let mut position = 0;
74b04a01
XL
31 loop {
32 let byte = slice[position];
2c00a5a8 33 position += 1;
2c00a5a8 34 if (byte & 0x80) == 0 {
74b04a01
XL
35 result |= (byte as $int_ty) << shift;
36 return (result, position);
37 } else {
38 result |= ((byte & 0x7F) as $int_ty) << shift;
2c00a5a8
XL
39 }
40 shift += 7;
41 }
2c00a5a8 42 }
dfeec247 43 };
9cc50fc6
SL
44}
45
2c00a5a8
XL
46impl_read_unsigned_leb128!(read_u16_leb128, u16);
47impl_read_unsigned_leb128!(read_u32_leb128, u32);
48impl_read_unsigned_leb128!(read_u64_leb128, u64);
49impl_read_unsigned_leb128!(read_u128_leb128, u128);
50impl_read_unsigned_leb128!(read_usize_leb128, usize);
51
476ff2be
SL
52#[inline]
53/// encodes an integer using signed leb128 encoding and stores
54/// the result using a callback function.
55///
56/// The callback `write` is called once for each position
57/// that is to be written to with the byte to be encoded
58/// at that position.
8faf50e0 59pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W)
dfeec247
XL
60where
61 W: FnMut(u8),
476ff2be 62{
9cc50fc6
SL
63 loop {
64 let mut byte = (value as u8) & 0x7f;
65 value >>= 7;
dfeec247
XL
66 let more =
67 !(((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && ((byte & 0x40) != 0)));
32a655c1 68
9cc50fc6
SL
69 if more {
70 byte |= 0x80; // Mark this byte to show that more bytes will follow.
71 }
72
8faf50e0 73 write(byte);
9cc50fc6
SL
74
75 if !more {
76 break;
77 }
78 }
476ff2be
SL
79}
80
b7449926 81#[inline]
8faf50e0 82pub fn write_signed_leb128(out: &mut Vec<u8>, value: i128) {
74b04a01 83 write_signed_leb128_to(value, |v| out.push(v))
9cc50fc6
SL
84}
85
c30ab7b3 86#[inline]
32a655c1 87pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
9cc50fc6
SL
88 let mut result = 0;
89 let mut shift = 0;
90 let mut position = start_position;
91 let mut byte;
92
93 loop {
94 byte = data[position];
95 position += 1;
dc9dc135 96 result |= i128::from(byte & 0x7F) << shift;
9cc50fc6
SL
97 shift += 7;
98
99 if (byte & 0x80) == 0 {
100 break;
101 }
102 }
103
104 if (shift < 64) && ((byte & 0x40) != 0) {
105 // sign extend
32a655c1 106 result |= -(1 << shift);
9cc50fc6
SL
107 }
108
109 (result, position - start_position)
110}