// varint.mbt
//
// Little-endian base-128 varints for UInt64, used by the WAL and SSTable
// encodings (see docs/format.md ยง1). Encoded lengths range from 1 byte
// (values below 128) to 10 bytes (full UInt64).
pub(all) suberror VarintError {
Truncated
Overflow
}
/// Appends the varint encoding of `v` to `buf`.
pub fn put_varint(buf : @buffer.Buffer, v : UInt64) -> Unit {
let mut rest = v
let mut cont = true
while cont {
if rest < 0x80UL {
cont = false
}
let high = if cont { 0x80UL } else { 0UL }
let byte = (rest & 0x7FUL) | high
buf.write_byte(byte.to_int().to_byte())
rest = rest >> 7
}
}
/// Reads one varint from `bytes` starting at `pos.val`, advancing `pos` past
/// it. Raises `Truncated` if the input ends mid-varint and `Overflow` if the
/// encoding exceeds 10 bytes.
pub fn read_varint(bytes : Bytes, pos : Ref[Int]) -> UInt64 raise VarintError {
let mut result = 0UL
let mut shift = 0
let mut i = pos.val
let mut cont = true
while cont {
if i >= bytes.length() {
raise VarintError::Truncated
}
if shift >= 70 {
raise VarintError::Overflow
}
let b = bytes[i].to_int()
cont = (b & 0x80) != 0
result = result | ((b & 0x7F).reinterpret_as_uint().to_uint64() << shift)
shift += 7
i += 1
}
pos.val = i
result
}