123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- package sarama
- import (
- "encoding/binary"
- "math"
- )
- type realDecoder struct {
- raw []byte
- off int
- stack []pushDecoder
- }
- // primitives
- func (rd *realDecoder) getInt8() (int8, error) {
- if rd.remaining() < 1 {
- rd.off = len(rd.raw)
- return -1, ErrInsufficientData
- }
- tmp := int8(rd.raw[rd.off])
- rd.off += 1
- return tmp, nil
- }
- func (rd *realDecoder) getInt16() (int16, error) {
- if rd.remaining() < 2 {
- rd.off = len(rd.raw)
- return -1, ErrInsufficientData
- }
- tmp := int16(binary.BigEndian.Uint16(rd.raw[rd.off:]))
- rd.off += 2
- return tmp, nil
- }
- func (rd *realDecoder) getInt32() (int32, error) {
- if rd.remaining() < 4 {
- rd.off = len(rd.raw)
- return -1, ErrInsufficientData
- }
- tmp := int32(binary.BigEndian.Uint32(rd.raw[rd.off:]))
- rd.off += 4
- return tmp, nil
- }
- func (rd *realDecoder) getInt64() (int64, error) {
- if rd.remaining() < 8 {
- rd.off = len(rd.raw)
- return -1, ErrInsufficientData
- }
- tmp := int64(binary.BigEndian.Uint64(rd.raw[rd.off:]))
- rd.off += 8
- return tmp, nil
- }
- func (rd *realDecoder) getArrayLength() (int, error) {
- if rd.remaining() < 4 {
- rd.off = len(rd.raw)
- return -1, ErrInsufficientData
- }
- tmp := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
- rd.off += 4
- if tmp > rd.remaining() {
- rd.off = len(rd.raw)
- return -1, ErrInsufficientData
- } else if tmp > 2*math.MaxUint16 {
- return -1, PacketDecodingError{"invalid array length"}
- }
- return tmp, nil
- }
- // collections
- func (rd *realDecoder) getBytes() ([]byte, error) {
- tmp, err := rd.getInt32()
- if err != nil {
- return nil, err
- }
- n := int(tmp)
- switch {
- case n < -1:
- return nil, PacketDecodingError{"invalid byteslice length"}
- case n == -1:
- return nil, nil
- case n == 0:
- return make([]byte, 0), nil
- case n > rd.remaining():
- rd.off = len(rd.raw)
- return nil, ErrInsufficientData
- }
- tmpStr := rd.raw[rd.off : rd.off+n]
- rd.off += n
- return tmpStr, nil
- }
- func (rd *realDecoder) getString() (string, error) {
- tmp, err := rd.getInt16()
- if err != nil {
- return "", err
- }
- n := int(tmp)
- switch {
- case n < -1:
- return "", PacketDecodingError{"invalid string length"}
- case n == -1:
- return "", nil
- case n == 0:
- return "", nil
- case n > rd.remaining():
- rd.off = len(rd.raw)
- return "", ErrInsufficientData
- }
- tmpStr := string(rd.raw[rd.off : rd.off+n])
- rd.off += n
- return tmpStr, nil
- }
- func (rd *realDecoder) getInt32Array() ([]int32, error) {
- if rd.remaining() < 4 {
- rd.off = len(rd.raw)
- return nil, ErrInsufficientData
- }
- n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
- rd.off += 4
- if rd.remaining() < 4*n {
- rd.off = len(rd.raw)
- return nil, ErrInsufficientData
- }
- if n == 0 {
- return nil, nil
- }
- if n < 0 {
- return nil, PacketDecodingError{"invalid array length"}
- }
- ret := make([]int32, n)
- for i := range ret {
- ret[i] = int32(binary.BigEndian.Uint32(rd.raw[rd.off:]))
- rd.off += 4
- }
- return ret, nil
- }
- func (rd *realDecoder) getInt64Array() ([]int64, error) {
- if rd.remaining() < 4 {
- rd.off = len(rd.raw)
- return nil, ErrInsufficientData
- }
- n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
- rd.off += 4
- if rd.remaining() < 8*n {
- rd.off = len(rd.raw)
- return nil, ErrInsufficientData
- }
- if n == 0 {
- return nil, nil
- }
- if n < 0 {
- return nil, PacketDecodingError{"invalid array length"}
- }
- ret := make([]int64, n)
- for i := range ret {
- ret[i] = int64(binary.BigEndian.Uint64(rd.raw[rd.off:]))
- rd.off += 8
- }
- return ret, nil
- }
- // subsets
- func (rd *realDecoder) remaining() int {
- return len(rd.raw) - rd.off
- }
- func (rd *realDecoder) getSubset(length int) (packetDecoder, error) {
- if length < 0 {
- return nil, PacketDecodingError{"invalid subset size"}
- } else if length > rd.remaining() {
- rd.off = len(rd.raw)
- return nil, ErrInsufficientData
- }
- start := rd.off
- rd.off += length
- return &realDecoder{raw: rd.raw[start:rd.off]}, nil
- }
- // stacks
- func (rd *realDecoder) push(in pushDecoder) error {
- in.saveOffset(rd.off)
- reserve := in.reserveLength()
- if rd.remaining() < reserve {
- rd.off = len(rd.raw)
- return ErrInsufficientData
- }
- rd.stack = append(rd.stack, in)
- rd.off += reserve
- return nil
- }
- func (rd *realDecoder) pop() error {
- // this is go's ugly pop pattern (the inverse of append)
- in := rd.stack[len(rd.stack)-1]
- rd.stack = rd.stack[:len(rd.stack)-1]
- return in.check(rd.off, rd.raw)
- }
|