23 lines
680 B
Crystal
23 lines
680 B
Crystal
def vl_encode (n)
|
|
raise "negative numbers aren't vl-encodeable" unless n >= 0
|
|
bytes_needed = n == 0 ? 1 : (n.bit_length - 1) // 7 + 1
|
|
bytes = Bytes.new(bytes_needed)
|
|
(0...bytes_needed).reverse_each do |i|
|
|
bytes[i] = (n & 127).to_u8 | 128
|
|
n >>= 7
|
|
end
|
|
bytes[-1] &= 127
|
|
bytes
|
|
end
|
|
|
|
def vl_decode (bytes)
|
|
size = (bytes.size - 1) * 7 + (bytes[0] & 127).bit_length
|
|
n = size > 63 ? 0.to_i128 : size > 31 ? 0.to_i64 : 0
|
|
bytes.reduce(n) {|result, byte| (result << 7) + (byte & 127) }
|
|
end
|
|
|
|
[0x200000, 0x1fffff].each do |n|
|
|
encoded = vl_encode(n)
|
|
decoded = vl_decode(encoded)
|
|
puts "%8d %12s %8d" % { n, encoded.map {|b| "%02x" % b }.join(":"), decoded }
|
|
end
|