]> git.lizzy.rs Git - rust.git/blob - src/librbml/leb128.rs
Auto merge of #30602 - tsion:mir-graphviz-display, r=nikomatsakis
[rust.git] / src / librbml / leb128.rs
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]
12 pub fn write_to_vec(vec: &mut Vec<u8>, position: &mut usize, byte: u8)
13 {
14     if *position == vec.len() {
15         vec.push(byte);
16     } else {
17         vec[*position] = byte;
18     }
19
20     *position += 1;
21 }
22
23 pub fn write_unsigned_leb128(out: &mut Vec<u8>,
24                              start_position: usize,
25                              mut value: u64)
26                              -> usize {
27     let mut position = start_position;
28     loop
29     {
30         let mut byte = (value & 0x7F) as u8;
31         value >>= 7;
32         if value != 0 {
33             byte |= 0x80;
34         }
35
36         write_to_vec(out, &mut position, byte);
37
38         if value == 0 {
39             break;
40         }
41     }
42
43     return position - start_position;
44 }
45
46 pub fn read_unsigned_leb128(data: &[u8],
47                             start_position: usize)
48                             -> (u64, usize) {
49     let mut result = 0;
50     let mut shift = 0;
51     let mut position = start_position;
52     loop {
53         let byte = data[position];
54         position += 1;
55         result |= ((byte & 0x7F) as u64) << shift;
56         if (byte & 0x80) == 0 {
57             break;
58         }
59         shift += 7;
60     }
61
62     (result, position - start_position)
63 }
64
65
66 pub fn write_signed_leb128(out: &mut Vec<u8>,
67                            start_position: usize,
68                            mut value: i64) -> usize {
69     let mut position = start_position;
70
71     loop {
72         let mut byte = (value as u8) & 0x7f;
73         value >>= 7;
74         let more = !((((value == 0 ) && ((byte & 0x40) == 0)) ||
75                       ((value == -1) && ((byte & 0x40) != 0))));
76         if more {
77             byte |= 0x80; // Mark this byte to show that more bytes will follow.
78         }
79
80         write_to_vec(out, &mut position, byte);
81
82         if !more {
83             break;
84         }
85     }
86
87     return position - start_position;
88 }
89
90 pub fn read_signed_leb128(data: &[u8],
91                           start_position: usize)
92                           -> (i64, usize) {
93     let mut result = 0;
94     let mut shift = 0;
95     let mut position = start_position;
96     let mut byte;
97
98     loop {
99         byte = data[position];
100         position += 1;
101         result |= ((byte & 0x7F) as i64) << shift;
102         shift += 7;
103
104         if (byte & 0x80) == 0 {
105             break;
106         }
107     }
108
109     if (shift < 64) && ((byte & 0x40) != 0) {
110         /* sign extend */
111         result |= -(1i64 << shift);
112     }
113
114     (result, position - start_position)
115 }
116
117 #[test]
118 fn test_unsigned_leb128() {
119     let mut stream = Vec::with_capacity(10000);
120
121     for x in 0..62 {
122         let pos = stream.len();
123         let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x);
124         assert_eq!(stream.len(), pos + bytes_written);
125     }
126
127     let mut position = 0;
128     for x in 0..62 {
129         let expected = 3 << x;
130         let (actual, bytes_read) = read_unsigned_leb128(&stream, position);
131         assert_eq!(expected, actual);
132         position += bytes_read;
133     }
134     assert_eq!(stream.len(), position);
135 }
136
137 #[test]
138 fn test_signed_leb128() {
139     let mut values = Vec::new();
140
141     let mut i = -500;
142     while i < 500 {
143         values.push(i * 123457i64);
144         i += 1;
145     }
146
147     let mut stream = Vec::new();
148
149     for &x in &values {
150         let pos = stream.len();
151         let bytes_written = write_signed_leb128(&mut stream, pos, x);
152         assert_eq!(stream.len(), pos + bytes_written);
153     }
154
155     let mut pos = 0;
156     for &x in &values {
157         let (value, bytes_read) = read_signed_leb128(&mut stream, pos);
158         pos += bytes_read;
159         assert_eq!(x, value);
160     }
161     assert_eq!(pos, stream.len());
162 }