///|
pub(all) enum Endian {
Big
Little
} derive(Eq)
///|
pub extend Endian with Eq::{equal, not_equal}
///|
fn need(data : Bytes, pos : Int, width : Int) -> Unit raise {
if pos < 0 || width < 0 || pos > data.length() || width > data.length() - pos {
raise Failure("truncated bytes at \{pos}, need \{width}")
}
}
///|
// Every offset in this implementation is zero-based; standard tables are not.
fn uint_at(
data : Bytes,
pos : Int,
width : Int,
endian : Endian,
) -> UInt64 raise {
need(data, pos, width)
let mut v = 0UL
for i in 0.. Int64 raise {
let shift = (8 - width) * 8
(uint_at(data, pos, width, endian) << shift).reinterpret_as_int64() >> shift
}
///|
fn put_uint(
out : Array[Byte],
pos : Int,
width : Int,
v : UInt64,
endian : Endian,
) -> Unit {
for i in 0..>
(i * 8)).to_byte()
}
}
///|
fn real_at(
data : Bytes,
pos : Int,
width : Int,
endian : Endian,
) -> Double raise {
let bits = uint_at(data, pos, width, endian)
if width == 4 {
Float::reinterpret_from_uint(bits.to_uint()).to_double()
} else {
bits.reinterpret_as_double()
}
}
///|
fn finite(x : Double) -> Bool {
!x.is_nan() && !x.is_inf()
}
///|
fn slice(data : Bytes, start : Int, count : Int) -> Bytes {
Bytes::makei(count, i => data[start + i])
}
///|
fn copy_into(out : Array[Byte], at : Int, data : Bytes) -> Unit {
for i in 0..