crc32_field.go 1.7 KB

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