1use crate::{Result, SourceMapError};
7
8const BASE64_CHARS: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9
10const BASE64_DECODE: [i8; 256] = {
11 let mut table = [-1i8; 256];
12 let mut i = 0;
13 while i < 64 {
14 table[BASE64_CHARS[i] as usize] = i as i8;
15 i += 1;
16 }
17 table
18};
19
20const VLQ_CONTINUATION_BIT: u8 = 0b100000;
21const VLQ_BASE_MASK: u8 = 0b011111;
22
23pub fn vlq_encode(value: i32) -> String {
37 let mut result = String::new();
38 let mut value = if value < 0 { ((-value) << 1) + 1 } else { value << 1 };
39
40 loop {
41 let mut digit = (value & VLQ_BASE_MASK as i32) as u8;
42 value >>= 5;
43
44 if value > 0 {
45 digit |= VLQ_CONTINUATION_BIT;
46 }
47
48 result.push(BASE64_CHARS[digit as usize] as char);
49
50 if value == 0 {
51 break;
52 }
53 }
54
55 result
56}
57
58pub fn vlq_decode(s: &str) -> Result<(i32, usize)> {
71 vlq_decode_from_slice(s.as_bytes())
72}
73
74pub fn vlq_decode_from_slice(bytes: &[u8]) -> Result<(i32, usize)> {
76 let mut result: i32 = 0;
77 let mut shift: u32 = 0;
78 let mut count = 0;
79
80 for &byte in bytes {
81 count += 1;
82
83 let decoded = BASE64_DECODE[byte as usize];
84 if decoded < 0 {
85 return Err(SourceMapError::invalid_vlq(count - 1, format!("Invalid Base64 character: '{}'", byte as char)));
86 }
87
88 let decoded = decoded as u8;
89
90 result |= ((decoded & VLQ_BASE_MASK) as i32) << shift;
91 shift += 5;
92
93 if decoded & VLQ_CONTINUATION_BIT == 0 {
94 break;
95 }
96 }
97
98 let is_negative = result & 1 != 0;
99 result >>= 1;
100
101 if is_negative {
102 result = -result;
103 }
104
105 Ok((result, count))
106}
107
108pub fn vlq_encode_many(values: &[i32]) -> String {
110 values.iter().map(|v| vlq_encode(*v)).collect()
111}
112
113pub fn vlq_decode_many(s: &str) -> Result<Vec<i32>> {
115 let bytes = s.as_bytes();
116 let mut pos = 0;
117 let mut result = Vec::new();
118
119 while pos < bytes.len() {
120 let (value, consumed) = vlq_decode_from_slice(&bytes[pos..])?;
121 result.push(value);
122 pos += consumed;
123 }
124
125 Ok(result)
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_encode_zero() {
134 assert_eq!(vlq_encode(0), "A");
135 }
136
137 #[test]
138 fn test_encode_positive() {
139 assert_eq!(vlq_encode(1), "C");
140 assert_eq!(vlq_encode(2), "E");
141 assert_eq!(vlq_encode(15), "e");
142 assert_eq!(vlq_encode(16), "gB");
143 assert_eq!(vlq_encode(31), "+B");
144 assert_eq!(vlq_encode(32), "gC");
145 }
146
147 #[test]
148 fn test_encode_negative() {
149 assert_eq!(vlq_encode(-1), "D");
150 assert_eq!(vlq_encode(-2), "F");
151 assert_eq!(vlq_encode(-16), "hB");
152 }
153
154 #[test]
155 fn test_decode_zero() {
156 assert_eq!(vlq_decode("A"), Ok((0, 1)));
157 }
158
159 #[test]
160 fn test_decode_positive() {
161 assert_eq!(vlq_decode("C"), Ok((1, 1)));
162 assert_eq!(vlq_decode("gB"), Ok((16, 2)));
163 }
164
165 #[test]
166 fn test_decode_negative() {
167 assert_eq!(vlq_decode("D"), Ok((-1, 1)));
168 assert_eq!(vlq_decode("hB"), Ok((-16, 2)));
169 }
170
171 #[test]
172 fn test_roundtrip() {
173 for value in [-1000, -100, -10, -1, 0, 1, 10, 100, 1000, 12345] {
174 let encoded = vlq_encode(value);
175 let (decoded, _) = vlq_decode(&encoded).unwrap();
176 assert_eq!(decoded, value, "Failed for value {}", value);
177 }
178 }
179
180 #[test]
181 fn test_decode_many() {
182 let encoded = "AAAA";
183 let decoded = vlq_decode_many(encoded).unwrap();
184 assert_eq!(decoded, vec![0, 0, 0, 0]);
185 }
186
187 #[test]
188 fn test_encode_many() {
189 let values = vec![0, 1, 2, 3];
190 let encoded = vlq_encode_many(&values);
191 assert_eq!(encoded, "ACEG");
192 }
193}