// SPDX-License-Identifier: LGPL-2.1-or-later
///|
/// Fixed legal widths only; preserve the complete unsigned parameter.
fn read_uint_be(
input : BytesView,
offset : Int64,
width : Int32,
) -> UInt64 raise SyncError {
guard width == 1 || width == 2 || width == 4 || width == 8 else {
raise InvalidOptions("wire_width")
}
let start = checked_wire_span(input.length(), offset, width)
let mut value = 0UL
for i in 0.. Unit raise SyncError {
guard width == 1 || width == 2 || width == 4 || width == 8 else {
raise InvalidOptions("wire_width")
}
let start = checked_wire_span(output.length(), offset, width)
if width < 8 {
guard value < 1UL << (width * 8) else { raise IntegerOutOfRange }
}
for i in 0..> ((width - 1 - i) * 8)) & 0xffUL).to_byte()
}
}
///|
/// Convert only after proving that an unsigned wire value fits an array index.
fn checked_index(value : UInt64) -> Int32 raise SyncError {
guard value <= 2147483647UL else { raise IntegerOutOfRange }
value.to_int()
}
///|
/// Check a complete span before adding offsets or touching the buffer.
/// An invalid position is a range error; a valid position with too few bytes
/// is truncated input. The end position itself is a valid position.
fn checked_wire_span(
length : Int32,
offset : Int64,
width : Int32,
) -> Int32 raise SyncError {
guard length >= 0 && offset >= 0L && width >= 0 else {
raise IntegerOutOfRange
}
// The signed offset was checked nonnegative before preserving its bits.
let start = checked_index(offset.reinterpret_as_uint64())
guard start <= length else { raise IntegerOutOfRange }
guard width <= length - start else { raise TruncatedInput }
start
}
///|
/// Keep the full UInt32 bit pattern, including values above signed Int32.
fn read_u32_be(input : BytesView, offset : Int64) -> UInt32 raise SyncError {
let start = checked_wire_span(input.length(), offset, 4)
let mut value = 0U
for i in 0..<4 {
value = (value << 8) | input[start + i].to_uint()
}
value
}
///|
/// UInt64 arithmetic never passes through a signed or floating-point value.
/// This stage exercises this internal entry point through whitebox tests only.
#warnings("-unused_value")
fn read_u64_be(input : BytesView, offset : Int64) -> UInt64 raise SyncError {
let start = checked_wire_span(input.length(), offset, 8)
let mut value = 0UL
for i in 0..<8 {
value = (value << 8) | input[start + i].to_uint64()
}
value
}
///|
/// Validate the whole output span first, so failure cannot partially write.
/// This stage exercises the internal writers through whitebox tests only.
#warnings("-unused_value")
fn write_u32_be(
output : FixedArray[Byte],
offset : Int64,
value : UInt32,
) -> Unit raise SyncError {
let start = checked_wire_span(output.length(), offset, 4)
for i in 0..<4 {
output[start + i] = ((value >> ((3 - i) * 8)) & 0xffU).to_byte()
}
}
///|
/// Internal u64 writer; its callers in this stage are whitebox tests only.
#warnings("-unused_value")
fn write_u64_be(
output : FixedArray[Byte],
offset : Int64,
value : UInt64,
) -> Unit raise SyncError {
let start = checked_wire_span(output.length(), offset, 8)
for i in 0..<8 {
output[start + i] = ((value >> ((7 - i) * 8)) & 0xffUL).to_byte()
}
}
///|
/// Check the division bound before computing a nominal block offset.
/// The result is not a basis length and is not yet an index into a basis file.
fn checked_block_offset(
record_index : UInt64,
block_len : UInt64,
) -> UInt64 raise SyncError {
if block_len != 0UL && record_index > 0xffffffffffffffffUL / block_len {
raise IntegerOutOfRange
}
record_index * block_len
}