81 lines
2.1 KiB
V
81 lines
2.1 KiB
V
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
|
|
// This is a pure V implementation of CRC64, providing one standard variant:
|
|
// CRC-64-ECMA-182 (poly 0x42F0E1EBA9EA3693, init 0, refin false, refout false, xorout 0).
|
|
module crc64
|
|
|
|
// Polynomial constants for CRC-64
|
|
pub const ecma = u64(0x42F0E1EBA9EA3693)
|
|
|
|
struct Crc64 {
|
|
mut:
|
|
table []u64
|
|
}
|
|
|
|
// generate_table populates a 256-word MSB-first lookup table for `poly`.
|
|
@[direct_array_access]
|
|
fn (mut c Crc64) generate_table(poly u64) {
|
|
c.table = []u64{len: 256}
|
|
for i in 0 .. 256 {
|
|
mut crc := u64(i) << 56
|
|
for _ in 0 .. 8 {
|
|
if crc & (u64(1) << 63) != 0 {
|
|
crc = (crc << 1) ^ poly
|
|
} else {
|
|
crc <<= 1
|
|
}
|
|
}
|
|
c.table[i] = crc
|
|
}
|
|
}
|
|
|
|
@[direct_array_access]
|
|
fn (c &Crc64) update64(crc u64, b []u8) u64 {
|
|
mut next := crc
|
|
for i in 0 .. b.len {
|
|
next = c.table[u8(next >> 56) ^ b[i]] ^ (next << 8)
|
|
}
|
|
return next
|
|
}
|
|
|
|
// update_state updates an internal CRC state with the bytes in `b`.
|
|
// For CRC-64-ECMA-182, use state 0 for a new stream.
|
|
pub fn (c &Crc64) update_state(state u64, b []u8) u64 {
|
|
return c.update64(state, b)
|
|
}
|
|
|
|
// checksum returns the CRC-64 checksum of data `b` by using the polynomial represented by `c`'s table.
|
|
pub fn (c &Crc64) checksum(b []u8) u64 {
|
|
return c.update_state(u64(0), b)
|
|
}
|
|
|
|
// update returns the updated CRC-64 checksum for `b`, starting from `crc`.
|
|
// Use `crc = 0` for a fresh checksum, or pass a previous result to continue streaming.
|
|
pub fn (c &Crc64) update(crc u64, b []u8) u64 {
|
|
return c.update_state(crc, b)
|
|
}
|
|
|
|
// new creates a `Crc64` polynomial.
|
|
pub fn new(poly u64) &Crc64 {
|
|
mut c := &Crc64{}
|
|
c.generate_table(poly)
|
|
return c
|
|
}
|
|
|
|
// sum_with_poly calculates the CRC-64 checksum of `b` for the provided polynomial.
|
|
pub fn sum_with_poly(poly u64, b []u8) u64 {
|
|
return match poly {
|
|
ecma { ecma_poly.checksum(b) }
|
|
else { new(poly).checksum(b) }
|
|
}
|
|
}
|
|
|
|
const ecma_poly = new(ecma)
|
|
|
|
// sum calculates the CRC-64 checksum of `b` by using the ECMA polynomial.
|
|
pub fn sum(b []u8) u64 {
|
|
return ecma_poly.checksum(b)
|
|
}
|