]> git.proxmox.com Git - rustc.git/blame - src/librbml/leb128.rs
New upstream version 1.12.1+dfsg1
[rustc.git] / src / librbml / leb128.rs
CommitLineData
9cc50fc6
SL
1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11#[inline]
12pub fn write_to_vec(vec: &mut Vec<u8>, position: &mut usize, byte: u8) {
13 if *position == vec.len() {
14 vec.push(byte);
15 } else {
16 vec[*position] = byte;
17 }
18
19 *position += 1;
20}
21
22pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, mut value: u64) -> usize {
23 let mut position = start_position;
24 loop {
25 let mut byte = (value & 0x7F) as u8;
26 value >>= 7;
27 if value != 0 {
28 byte |= 0x80;
29 }
30
31 write_to_vec(out, &mut position, byte);
32
33 if value == 0 {
34 break;
35 }
36 }
37
38 return position - start_position;
39}
40
41pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u64, usize) {
42 let mut result = 0;
43 let mut shift = 0;
44 let mut position = start_position;
45 loop {
46 let byte = data[position];
47 position += 1;
48 result |= ((byte & 0x7F) as u64) << shift;
49 if (byte & 0x80) == 0 {
50 break;
51 }
52 shift += 7;
53 }
54
55 (result, position - start_position)
56}
57
58
59pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, mut value: i64) -> usize {
60 let mut position = start_position;
61
62 loop {
63 let mut byte = (value as u8) & 0x7f;
64 value >>= 7;
65 let more = !((((value == 0) && ((byte & 0x40) == 0)) ||
66 ((value == -1) && ((byte & 0x40) != 0))));
67 if more {
68 byte |= 0x80; // Mark this byte to show that more bytes will follow.
69 }
70
71 write_to_vec(out, &mut position, byte);
72
73 if !more {
74 break;
75 }
76 }
77
78 return position - start_position;
79}
80
81pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
82 let mut result = 0;
83 let mut shift = 0;
84 let mut position = start_position;
85 let mut byte;
86
87 loop {
88 byte = data[position];
89 position += 1;
90 result |= ((byte & 0x7F) as i64) << shift;
91 shift += 7;
92
93 if (byte & 0x80) == 0 {
94 break;
95 }
96 }
97
98 if (shift < 64) && ((byte & 0x40) != 0) {
99 // sign extend
100 result |= -(1i64 << shift);
101 }
102
103 (result, position - start_position)
104}
105
106#[test]
107fn test_unsigned_leb128() {
108 let mut stream = Vec::with_capacity(10000);
109
110 for x in 0..62 {
111 let pos = stream.len();
112 let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x);
113 assert_eq!(stream.len(), pos + bytes_written);
114 }
115
116 let mut position = 0;
117 for x in 0..62 {
118 let expected = 3 << x;
119 let (actual, bytes_read) = read_unsigned_leb128(&stream, position);
120 assert_eq!(expected, actual);
121 position += bytes_read;
122 }
123 assert_eq!(stream.len(), position);
124}
125
126#[test]
127fn test_signed_leb128() {
128 let mut values = Vec::new();
129
130 let mut i = -500;
131 while i < 500 {
132 values.push(i * 123457i64);
133 i += 1;
134 }
135
136 let mut stream = Vec::new();
137
138 for &x in &values {
139 let pos = stream.len();
140 let bytes_written = write_signed_leb128(&mut stream, pos, x);
141 assert_eq!(stream.len(), pos + bytes_written);
142 }
143
144 let mut pos = 0;
145 for &x in &values {
146 let (value, bytes_read) = read_signed_leb128(&mut stream, pos);
147 pos += bytes_read;
148 assert_eq!(x, value);
149 }
150 assert_eq!(pos, stream.len());
151}