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