v2 / vlib / hash / crc64 / crc64.v
80 lines · 68 sloc · 2.1 KB · 0de4244590b0fd16cdba621a4dfa4609ebd6defc
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4
5// This is a pure V implementation of CRC64, providing one standard variant:
6// CRC-64-ECMA-182 (poly 0x42F0E1EBA9EA3693, init 0, refin false, refout false, xorout 0).
7module crc64
8
9// Polynomial constants for CRC-64
10pub const ecma = u64(0x42F0E1EBA9EA3693)
11
12struct Crc64 {
13mut:
14 table []u64
15}
16
17// generate_table populates a 256-word MSB-first lookup table for `poly`.
18@[direct_array_access]
19fn (mut c Crc64) generate_table(poly u64) {
20 c.table = []u64{len: 256}
21 for i in 0 .. 256 {
22 mut crc := u64(i) << 56
23 for _ in 0 .. 8 {
24 if crc & (u64(1) << 63) != 0 {
25 crc = (crc << 1) ^ poly
26 } else {
27 crc <<= 1
28 }
29 }
30 c.table[i] = crc
31 }
32}
33
34@[direct_array_access]
35fn (c &Crc64) update64(crc u64, b []u8) u64 {
36 mut next := crc
37 for i in 0 .. b.len {
38 next = c.table[u8(next >> 56) ^ b[i]] ^ (next << 8)
39 }
40 return next
41}
42
43// update_state updates an internal CRC state with the bytes in `b`.
44// For CRC-64-ECMA-182, use state 0 for a new stream.
45pub fn (c &Crc64) update_state(state u64, b []u8) u64 {
46 return c.update64(state, b)
47}
48
49// checksum returns the CRC-64 checksum of data `b` by using the polynomial represented by `c`'s table.
50pub fn (c &Crc64) checksum(b []u8) u64 {
51 return c.update_state(u64(0), b)
52}
53
54// update returns the updated CRC-64 checksum for `b`, starting from `crc`.
55// Use `crc = 0` for a fresh checksum, or pass a previous result to continue streaming.
56pub fn (c &Crc64) update(crc u64, b []u8) u64 {
57 return c.update_state(crc, b)
58}
59
60// new creates a `Crc64` polynomial.
61pub fn new(poly u64) &Crc64 {
62 mut c := &Crc64{}
63 c.generate_table(poly)
64 return c
65}
66
67// sum_with_poly calculates the CRC-64 checksum of `b` for the provided polynomial.
68pub fn sum_with_poly(poly u64, b []u8) u64 {
69 return match poly {
70 ecma { ecma_poly.checksum(b) }
71 else { new(poly).checksum(b) }
72 }
73}
74
75const ecma_poly = new(ecma)
76
77// sum calculates the CRC-64 checksum of `b` by using the ECMA polynomial.
78pub fn sum(b []u8) u64 {
79 return ecma_poly.checksum(b)
80}
81