-
Notifications
You must be signed in to change notification settings - Fork 0
/
vlq.py
47 lines (40 loc) · 1.43 KB
/
vlq.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""
Source taken from: https://gist.github.com/mjpieters/86b0d152bb51d5f5979346d11005588b
"""
from typing import Tuple
_b64chars = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
_b64table = [None] * (max(_b64chars) + 1)
for i, b in enumerate(_b64chars):
_b64table[b] = i
_encode = _b64chars.decode().__getitem__
_shiftsize, _flag, _mask = 5, 1 << 5, (1 << 5) - 1
def base64vlq_decode(vlqval: str) -> Tuple[int]:
"""Decode Base64 VLQ value"""
results = []
add = results.append
shiftsize, flag, mask = _shiftsize, _flag, _mask
shift = value = 0
# use byte values and a table to go from base64 characters to integers
for v in map(_b64table.__getitem__, vlqval.encode("ascii")):
value += (v & mask) << shift
if v & flag:
shift += shiftsize
continue
# determine sign and add to results
add((value >> 1) * (-1 if value & 1 else 1))
shift = value = 0
return results
def base64vlq_encode(*values: int) -> str:
"""Encode integers to a VLQ value"""
results = []
add = results.append
shiftsize, flag, mask = _shiftsize, _flag, _mask
for v in values:
# add sign bit
v = (abs(v) << 1) | int(v < 0)
while True:
toencode, v = v & mask, v >> shiftsize
add(toencode | (v and flag))
if not v:
break
return bytes(map(_b64chars.__getitem__, results)).decode()