///|
/// CRC-32C (Castagnoli), reversed polynomial 0x82F63B78.
let crc_table : FixedArray[UInt] = build_crc_table()
///|
fn build_crc_table() -> FixedArray[UInt] {
let table : FixedArray[UInt] = FixedArray::make(256, 0)
let mut i = 0
while i < 256 {
let mut crc = i.reinterpret_as_uint()
let mut bit = 0
while bit < 8 {
if (crc & 1) == 1 {
crc = (crc >> 1) ^ 0x82F63B78
} else {
crc = crc >> 1
}
bit = bit + 1
}
table[i] = crc
i = i + 1
}
table
}
///|
pub fn crc32c(data : Bytes) -> UInt {
let mut crc : UInt = 0xFFFFFFFF
let mut i = 0
while i < data.length() {
let idx = ((crc ^ data[i].to_uint()) & 0xFF).reinterpret_as_int()
crc = crc_table[idx] ^ (crc >> 8)
i = i + 1
}
crc ^ 0xFFFFFFFF
}
///|
/// CRC over `data[start:end]`, treating the four CRC bytes as zero.
pub fn crc32c_region(
data : Bytes,
start : Int,
end : Int,
crc_offset : Int,
) -> UInt {
let mut crc : UInt = 0xFFFFFFFF
let mut i = start
while i < end {
let byte : UInt = if i >= crc_offset && i < crc_offset + 4 {
0
} else {
data[i].to_uint()
}
let idx = ((crc ^ byte) & 0xFF).reinterpret_as_int()
crc = crc_table[idx] ^ (crc >> 8)
i = i + 1
}
crc ^ 0xFFFFFFFF
}
///|
pub fn verify_crc(
raw : Bytes,
start : Int,
end : Int,
crc_offset : Int,
) -> Bool {
if start < 0 ||
end > raw.length() ||
start > end ||
crc_offset < start ||
crc_offset + 4 > end {
return false
}
@binary.read_uint(raw, crc_offset) ==
crc32c_region(raw, start, end, crc_offset)
}