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