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