crc32_field.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package sarama
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "hash/crc32"
  6. )
  7. type crcPolynomial int8
  8. const (
  9. crcIEEE crcPolynomial = iota
  10. crcCastagnoli
  11. )
  12. var castagnoliTable = crc32.MakeTable(crc32.Castagnoli)
  13. // crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s.
  14. type crc32Field struct {
  15. startOffset int
  16. polynomial crcPolynomial
  17. }
  18. func (c *crc32Field) saveOffset(in int) {
  19. c.startOffset = in
  20. }
  21. func (c *crc32Field) reserveLength() int {
  22. return 4
  23. }
  24. func newCRC32Field(polynomial crcPolynomial) *crc32Field {
  25. return &crc32Field{polynomial: polynomial}
  26. }
  27. func (c *crc32Field) run(curOffset int, buf []byte) error {
  28. crc, err := c.crc(curOffset, buf)
  29. if err != nil {
  30. return err
  31. }
  32. binary.BigEndian.PutUint32(buf[c.startOffset:], crc)
  33. return nil
  34. }
  35. func (c *crc32Field) check(curOffset int, buf []byte) error {
  36. crc, err := c.crc(curOffset, buf)
  37. if err != nil {
  38. return err
  39. }
  40. expected := binary.BigEndian.Uint32(buf[c.startOffset:])
  41. if crc != expected {
  42. return PacketDecodingError{fmt.Sprintf("CRC didn't match expected %#x got %#x", expected, crc)}
  43. }
  44. return nil
  45. }
  46. func (c *crc32Field) crc(curOffset int, buf []byte) (uint32, error) {
  47. var tab *crc32.Table
  48. switch c.polynomial {
  49. case crcIEEE:
  50. tab = crc32.IEEETable
  51. case crcCastagnoli:
  52. tab = castagnoliTable
  53. default:
  54. return 0, PacketDecodingError{"invalid CRC type"}
  55. }
  56. return crc32.Checksum(buf[c.startOffset+4:curOffset], tab), nil
  57. }