///|
priv struct Input {
bytes : Bytes
mut pos : Int32
end : Int32
}
///|
fn input(bytes : Bytes) -> Input {
{ bytes, pos: 0, end: bytes.length(), }
}
///|
fn Input::take(self : Input, size : Int32) -> Bytes raise OrcError {
if size < 0 || size > self.end - self.pos {
raise Invalid("truncated field", self.pos)
}
let value = self.bytes[self.pos:self.pos + size].to_owned()
self.pos += size
value
}
///|
fn Input::byte(self : Input) -> Int32 raise OrcError {
if self.pos >= self.end {
raise Invalid("truncated byte", self.pos)
}
let n = self.bytes[self.pos].to_int()
self.pos += 1
n
}
///|
fn Input::little(self : Input, width : Int32) -> UInt64 raise OrcError {
let raw = self.take(width)
let mut n = 0UL
for i = 0; i < width; i = i + 1 {
n = n | (raw[i].to_uint64() << (8 * i))
}
n
}
///|
fn Input::varint(self : Input) -> UInt64 raise OrcError {
let mut n = 0UL
for i = 0; i < 10; i = i + 1 {
let byte = self.byte()
if i == 9 && byte > 1 {
raise Invalid("varint overflow", self.pos - 1)
}
n = n | ((byte & 127).to_uint64() << (i * 7))
if byte < 128 {
return n
}
}
raise Invalid("unterminated varint", self.pos)
}
///|
fn host(n : UInt64) -> Int32 raise OrcError {
if n > 2147483647UL {
raise Limit("host index range")
}
n.to_int()
}
///|
fn zig(n : Int64) -> UInt64 {
(n.reinterpret_as_uint64() << 1) ^ (n >> 63).reinterpret_as_uint64()
}
///|
fn unzig(n : UInt64) -> Int64 {
((n >> 1) ^ (0UL - (n & 1UL))).reinterpret_as_int64()
}
///|
priv struct Output {
bytes : Array[Byte]
}
///|
fn output() -> Output {
{ bytes: [], }
}
///|
fn Output::byte(self : Output, n : Int32) -> Unit {
self.bytes.push(n.to_byte())
}
///|
fn Output::raw(self : Output, raw : Bytes) -> Unit {
for x in raw {
self.bytes.push(x)
}
}
///|
fn Output::little(self : Output, n : UInt64, width : Int32) -> Unit {
for i = 0; i < width; i = i + 1 {
self.bytes.push((n >> (8 * i)).to_byte())
}
}
///|
fn Output::varint(self : Output, n : UInt64) -> Unit {
let mut n = n
while n >= 128UL {
self.bytes.push(((n & 127UL) | 128UL).to_byte())
n = n >> 7
}
self.bytes.push(n.to_byte())
}
///|
fn Output::finish(self : Output) -> Bytes {
Bytes::from_array(self.bytes)
}
///|
fn Output::length(self : Output) -> Int32 {
self.bytes.length()
}
///|
fn sub(bytes : Bytes, start : Int32, size : Int32) -> Bytes raise OrcError {
if start < 0 ||
size < 0 ||
start > bytes.length() ||
size > bytes.length() - start {
raise Invalid("byte range", start)
}
bytes[start:start + size].to_owned()
}
///|
test "uint64 varints preserve extremes and reject malformed input" {
for n in [0UL, 127UL, 128UL, 0xffffffffffffffffUL] {
let out = output()
out.varint(n)
assert_eq(input(out.finish()).varint(), n)
}
for n in [-9223372036854775808L, -1L, 0L, 9223372036854775807L] {
assert_eq(unzig(zig(n)), n)
}
assert_true(
try {
ignore(input(b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02").varint())
false
} catch {
_ => true
},
)
}