const VLQ_BASE64_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
fn decode_base64_char(c: char) -> Option<i32> {
VLQ_BASE64_CHARS
.iter()
.position(|&ch| ch == c as u8)
.map(|pos| pos as i32)
}
pub fn decode_vlq_value(chars: &mut impl Iterator<Item = char>) -> Option<i32> {
let mut result;
let mut shift;
let mut continuation;
let first_char = chars.next()?;
let mut value = decode_base64_char(first_char)?;
let negative = (value & 1) != 0;
result = (value >> 1) & 0xF;
shift = 4;
continuation = (value & 0x20) != 0;
while continuation {
let ch = chars.next()?;
value = decode_base64_char(ch)?;
result |= (value & 0x1F) << shift;
shift += 5;
continuation = (value & 0x20) != 0;
}
Some(if negative { -result } else { result })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decode_vlq_single_char() {
let mut chars = "A".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(0));
let mut chars = "C".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(1));
let mut chars = "D".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(-1));
}
#[test]
fn test_decode_vlq_multi_char() {
let mut chars = "gC".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(32));
let mut chars = "hC".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(-32));
}
#[test]
fn test_decode_base64_char() {
assert_eq!(decode_base64_char('A'), Some(0));
assert_eq!(decode_base64_char('Z'), Some(25));
assert_eq!(decode_base64_char('a'), Some(26));
assert_eq!(decode_base64_char('z'), Some(51));
assert_eq!(decode_base64_char('0'), Some(52));
assert_eq!(decode_base64_char('9'), Some(61));
assert_eq!(decode_base64_char('+'), Some(62));
assert_eq!(decode_base64_char('/'), Some(63));
assert_eq!(decode_base64_char('!'), None); }
}
#[cfg(test)]
mod vlq_tests {
use super::*;
#[test]
fn test_decode_base64_char_basic() {
assert_eq!(decode_base64_char('A'), Some(0));
assert_eq!(decode_base64_char('Z'), Some(25));
assert_eq!(decode_base64_char('a'), Some(26));
assert_eq!(decode_base64_char('z'), Some(51));
assert_eq!(decode_base64_char('0'), Some(52));
assert_eq!(decode_base64_char('9'), Some(61));
assert_eq!(decode_base64_char('+'), Some(62));
assert_eq!(decode_base64_char('/'), Some(63));
assert_eq!(decode_base64_char('!'), None); }
#[test]
fn test_decode_vlq_single_char_values() {
let mut chars = "A".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(0));
let mut chars = "C".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(1));
let mut chars = "D".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(-1));
let mut chars = "E".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(2));
let mut chars = "F".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(-2));
}
#[test]
fn test_decode_vlq_multi_char_values() {
let mut chars = "gC".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(32));
let mut chars = "hC".chars();
assert_eq!(decode_vlq_value(&mut chars), Some(-32));
}
}