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}