github.com/hamba/avro/v2@v2.22.1-0.20240518180522-aff3955acf7d/pkg/crc64/crc64.go (about) 1 // Package crc64 implements the Avro CRC-64 checksum. 2 // See https://avro.apache.org/docs/current/spec.html#schema_fingerprints for information. 3 package crc64 4 5 import ( 6 "hash" 7 ) 8 9 func init() { 10 buildTable() 11 } 12 13 // Size is the of a CRC-64 checksum in bytes. 14 const Size = 8 15 16 // Empty is the empty checksum. 17 const Empty = 0xc15d213aa4d7a795 18 19 // Table is a 256-word table representing the polynomial for efficient processing. 20 type Table [256]uint64 21 22 func makeTable() *Table { 23 t := new(Table) 24 for i := 0; i < 256; i++ { 25 fp := uint64(i) 26 for j := 0; j < 8; j++ { 27 fp = (fp >> 1) ^ (Empty & -(fp & 1)) 28 } 29 t[i] = fp 30 } 31 return t 32 } 33 34 var crc64Table *Table 35 36 func buildTable() { 37 crc64Table = makeTable() 38 } 39 40 type digest struct { 41 crc uint64 42 tab *Table 43 } 44 45 // New creates a new hash.Hash64 computing the Avro CRC-64 checksum. 46 // Its Sum method will lay the value out in big-endian byte order. 47 func New() hash.Hash64 { 48 return &digest{ 49 crc: Empty, 50 tab: crc64Table, 51 } 52 } 53 54 // Size returns the bytes size of the checksum. 55 func (d *digest) Size() int { 56 return Size 57 } 58 59 // BlockSize returns the block size of the checksum. 60 func (d *digest) BlockSize() int { 61 return 1 62 } 63 64 // Reset resets the hash instance. 65 func (d *digest) Reset() { 66 d.crc = Empty 67 } 68 69 // Write accumulatively adds the given data to the checksum. 70 func (d *digest) Write(p []byte) (n int, err error) { 71 for i := 0; i < len(p); i++ { 72 d.crc = (d.crc >> 8) ^ d.tab[(int)(byte(d.crc)^p[i])&0xff] 73 } 74 75 return len(p), nil 76 } 77 78 // Sum64 returns the checksum as a uint64. 79 func (d *digest) Sum64() uint64 { 80 return d.crc 81 } 82 83 // Sum returns the checksum as a byte slice, using the given byte slice. 84 func (d *digest) Sum(in []byte) []byte { 85 s := d.Sum64() 86 return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) 87 } 88 89 // Sum returns the MD5 checksum of the data. 90 func Sum(data []byte) [Size]byte { 91 d := digest{crc: Empty, tab: crc64Table} 92 d.Reset() 93 _, _ = d.Write(data) 94 s := d.Sum64() 95 //nolint:lll 96 return [Size]byte{byte(s >> 56), byte(s >> 48), byte(s >> 40), byte(s >> 32), byte(s >> 24), byte(s >> 16), byte(s >> 8), byte(s)} 97 }