blob: 32236e50f038b71d669b355d221c9bcf16a3f26b [file] [log] [blame]
khenaidooac637102019-01-14 15:44:34 -05001package sarama
2
3import (
4 "encoding/binary"
5 "fmt"
6 "hash/crc32"
Scott Baker8461e152019-10-01 14:44:30 -07007 "sync"
khenaidooac637102019-01-14 15:44:34 -05008)
9
10type crcPolynomial int8
11
12const (
13 crcIEEE crcPolynomial = iota
14 crcCastagnoli
15)
16
Scott Baker8461e152019-10-01 14:44:30 -070017var crc32FieldPool = sync.Pool{}
18
19func acquireCrc32Field(polynomial crcPolynomial) *crc32Field {
20 val := crc32FieldPool.Get()
21 if val != nil {
22 c := val.(*crc32Field)
23 c.polynomial = polynomial
24 return c
25 }
26 return newCRC32Field(polynomial)
27}
28
29func releaseCrc32Field(c *crc32Field) {
30 crc32FieldPool.Put(c)
31}
32
khenaidooac637102019-01-14 15:44:34 -050033var castagnoliTable = crc32.MakeTable(crc32.Castagnoli)
34
35// crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s.
36type crc32Field struct {
37 startOffset int
38 polynomial crcPolynomial
39}
40
41func (c *crc32Field) saveOffset(in int) {
42 c.startOffset = in
43}
44
45func (c *crc32Field) reserveLength() int {
46 return 4
47}
48
49func newCRC32Field(polynomial crcPolynomial) *crc32Field {
50 return &crc32Field{polynomial: polynomial}
51}
52
53func (c *crc32Field) run(curOffset int, buf []byte) error {
54 crc, err := c.crc(curOffset, buf)
55 if err != nil {
56 return err
57 }
58 binary.BigEndian.PutUint32(buf[c.startOffset:], crc)
59 return nil
60}
61
62func (c *crc32Field) check(curOffset int, buf []byte) error {
63 crc, err := c.crc(curOffset, buf)
64 if err != nil {
65 return err
66 }
67
68 expected := binary.BigEndian.Uint32(buf[c.startOffset:])
69 if crc != expected {
70 return PacketDecodingError{fmt.Sprintf("CRC didn't match expected %#x got %#x", expected, crc)}
71 }
72
73 return nil
74}
khenaidood948f772021-08-11 17:49:24 -040075
khenaidooac637102019-01-14 15:44:34 -050076func (c *crc32Field) crc(curOffset int, buf []byte) (uint32, error) {
77 var tab *crc32.Table
78 switch c.polynomial {
79 case crcIEEE:
80 tab = crc32.IEEETable
81 case crcCastagnoli:
82 tab = castagnoliTable
83 default:
84 return 0, PacketDecodingError{"invalid CRC type"}
85 }
86 return crc32.Checksum(buf[c.startOffset+4:curOffset], tab), nil
87}