///|
/// The largest integer representable by MoonBit's portable `Int` type.
const MAX_PORTABLE_INT : Int = 2147483647
///|
/// Reads an RFC 3284 big-endian base-128 unsigned integer.
/// Encodings with redundant leading zero groups are rejected.
fn read_varint(cursor : ByteCursor) -> Int raise VcdiffError {
let start = cursor.offset()
let mut value = 0
let mut groups = 0
let mut first_payload = 0
while true {
let byte = cursor.read_byte()
let payload = byte.to_int() & 0x7f
if groups == 0 {
first_payload = payload
}
groups += 1
if groups > 5 || value > (MAX_PORTABLE_INT - payload) / 128 {
raise IntegerOverflow(offset=start)
}
value = value * 128 + payload
let continues = (byte.to_int() & 0x80) != 0
if !continues {
if groups > 1 && first_payload == 0 {
raise InvalidVarint(
offset=start,
reason="non-canonical leading zero group",
)
}
break
}
}
value
}
///|
/// Encodes a non-negative integer using the canonical RFC 3284 representation.
fn encode_varint(value : Int) -> Bytes raise VcdiffError {
if value < 0 {
raise InvalidOption(option="varint", reason="must not be negative")
}
let groups : Array[Byte] = []
let mut remaining = value
groups.push((remaining & 0x7f).to_byte())
remaining = remaining / 128
while remaining > 0 {
groups.push((remaining & 0x7f).to_byte())
remaining = remaining / 128
}
let result : Array[Byte] = []
for i = groups.length() - 1; i >= 0; i = i - 1 {
let payload = groups[i].to_int()
if i == 0 {
result.push(payload.to_byte())
} else {
result.push((payload | 0x80).to_byte())
}
}
Bytes::from_array(result)
}
///|
/// Writes one canonical RFC integer into an existing byte buffer.
fn write_varint(buffer : @buffer.Buffer, value : Int) -> Unit raise VcdiffError {
buffer.write_bytes(encode_varint(value))
}
///|
/// Returns the encoded byte width without allocating.
fn varint_width(value : Int) -> Int raise VcdiffError {
if value < 0 {
raise InvalidOption(option="varint", reason="must not be negative")
}
let mut width = 1
let mut remaining = value / 128
while remaining > 0 {
width += 1
remaining = remaining / 128
}
width
}
///|
/// Decodes exactly one canonical RFC 3284 unsigned integer.
///
/// Any bytes following the integer are rejected so callers cannot
/// accidentally ignore malformed suffix data.
pub fn decode_unsigned_integer(data : Bytes) -> Int raise VcdiffError {
let cursor = ByteCursor::new(data)
let value = read_varint(cursor)
let trailing = cursor.remaining()
if trailing != 0 {
ignore(cursor.read_exact(trailing))
raise LengthMismatch(
offset=cursor.offset() - trailing,
expected=cursor.offset() - trailing,
actual=data.length(),
)
}
value
}
///|
/// Encodes one non-negative integer in canonical RFC 3284 form.
pub fn encode_unsigned_integer(value : Int) -> Bytes raise VcdiffError {
let buffer = @buffer.Buffer(size_hint=varint_width(value))
write_varint(buffer, value)
buffer.to_bytes()
}