| package sarama |
| |
| import ( |
| "encoding/binary" |
| "fmt" |
| "hash/crc32" |
| "sync" |
| ) |
| |
| type crcPolynomial int8 |
| |
| const ( |
| crcIEEE crcPolynomial = iota |
| crcCastagnoli |
| ) |
| |
| var crc32FieldPool = sync.Pool{} |
| |
| func acquireCrc32Field(polynomial crcPolynomial) *crc32Field { |
| val := crc32FieldPool.Get() |
| if val != nil { |
| c := val.(*crc32Field) |
| c.polynomial = polynomial |
| return c |
| } |
| return newCRC32Field(polynomial) |
| } |
| |
| func releaseCrc32Field(c *crc32Field) { |
| crc32FieldPool.Put(c) |
| } |
| |
| var castagnoliTable = crc32.MakeTable(crc32.Castagnoli) |
| |
| // crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s. |
| type crc32Field struct { |
| startOffset int |
| polynomial crcPolynomial |
| } |
| |
| func (c *crc32Field) saveOffset(in int) { |
| c.startOffset = in |
| } |
| |
| func (c *crc32Field) reserveLength() int { |
| return 4 |
| } |
| |
| func newCRC32Field(polynomial crcPolynomial) *crc32Field { |
| return &crc32Field{polynomial: polynomial} |
| } |
| |
| func (c *crc32Field) run(curOffset int, buf []byte) error { |
| crc, err := c.crc(curOffset, buf) |
| if err != nil { |
| return err |
| } |
| binary.BigEndian.PutUint32(buf[c.startOffset:], crc) |
| return nil |
| } |
| |
| func (c *crc32Field) check(curOffset int, buf []byte) error { |
| crc, err := c.crc(curOffset, buf) |
| if err != nil { |
| return err |
| } |
| |
| expected := binary.BigEndian.Uint32(buf[c.startOffset:]) |
| if crc != expected { |
| return PacketDecodingError{fmt.Sprintf("CRC didn't match expected %#x got %#x", expected, crc)} |
| } |
| |
| return nil |
| } |
| func (c *crc32Field) crc(curOffset int, buf []byte) (uint32, error) { |
| var tab *crc32.Table |
| switch c.polynomial { |
| case crcIEEE: |
| tab = crc32.IEEETable |
| case crcCastagnoli: |
| tab = castagnoliTable |
| default: |
| return 0, PacketDecodingError{"invalid CRC type"} |
| } |
| return crc32.Checksum(buf[c.startOffset+4:curOffset], tab), nil |
| } |