|
- package codec
-
- import (
- "errors"
- "fmt"
- "io"
- "math"
-
- "github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/protoc-gen-go/descriptor"
- )
-
- // ErrOverflow is returned when an integer is too large to be represented.
- var ErrOverflow = errors.New("proto: integer overflow")
-
- // ErrBadWireType is returned when decoding a wire-type from a buffer that
- // is not valid.
- var ErrBadWireType = errors.New("proto: bad wiretype")
-
- var varintTypes = map[descriptor.FieldDescriptorProto_Type]bool{}
- var fixed32Types = map[descriptor.FieldDescriptorProto_Type]bool{}
- var fixed64Types = map[descriptor.FieldDescriptorProto_Type]bool{}
-
- func init() {
- varintTypes[descriptor.FieldDescriptorProto_TYPE_BOOL] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_INT32] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_INT64] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT32] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT64] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT32] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT64] = true
- varintTypes[descriptor.FieldDescriptorProto_TYPE_ENUM] = true
-
- fixed32Types[descriptor.FieldDescriptorProto_TYPE_FIXED32] = true
- fixed32Types[descriptor.FieldDescriptorProto_TYPE_SFIXED32] = true
- fixed32Types[descriptor.FieldDescriptorProto_TYPE_FLOAT] = true
-
- fixed64Types[descriptor.FieldDescriptorProto_TYPE_FIXED64] = true
- fixed64Types[descriptor.FieldDescriptorProto_TYPE_SFIXED64] = true
- fixed64Types[descriptor.FieldDescriptorProto_TYPE_DOUBLE] = true
- }
-
- func (cb *Buffer) decodeVarintSlow() (x uint64, err error) {
- i := cb.index
- l := len(cb.buf)
-
- for shift := uint(0); shift < 64; shift += 7 {
- if i >= l {
- err = io.ErrUnexpectedEOF
- return
- }
- b := cb.buf[i]
- i++
- x |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- cb.index = i
- return
- }
- }
-
- // The number is too large to represent in a 64-bit value.
- err = ErrOverflow
- return
- }
-
- // DecodeVarint reads a varint-encoded integer from the Buffer.
- // This is the format for the
- // int32, int64, uint32, uint64, bool, and enum
- // protocol buffer types.
- func (cb *Buffer) DecodeVarint() (uint64, error) {
- i := cb.index
- buf := cb.buf
-
- if i >= len(buf) {
- return 0, io.ErrUnexpectedEOF
- } else if buf[i] < 0x80 {
- cb.index++
- return uint64(buf[i]), nil
- } else if len(buf)-i < 10 {
- return cb.decodeVarintSlow()
- }
-
- var b uint64
- // we already checked the first byte
- x := uint64(buf[i]) - 0x80
- i++
-
- b = uint64(buf[i])
- i++
- x += b << 7
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 7
-
- b = uint64(buf[i])
- i++
- x += b << 14
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 14
-
- b = uint64(buf[i])
- i++
- x += b << 21
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 21
-
- b = uint64(buf[i])
- i++
- x += b << 28
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 28
-
- b = uint64(buf[i])
- i++
- x += b << 35
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 35
-
- b = uint64(buf[i])
- i++
- x += b << 42
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 42
-
- b = uint64(buf[i])
- i++
- x += b << 49
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 49
-
- b = uint64(buf[i])
- i++
- x += b << 56
- if b&0x80 == 0 {
- goto done
- }
- x -= 0x80 << 56
-
- b = uint64(buf[i])
- i++
- x += b << 63
- if b&0x80 == 0 {
- goto done
- }
- // x -= 0x80 << 63 // Always zero.
-
- return 0, ErrOverflow
-
- done:
- cb.index = i
- return x, nil
- }
-
- // DecodeTagAndWireType decodes a field tag and wire type from input.
- // This reads a varint and then extracts the two fields from the varint
- // value read.
- func (cb *Buffer) DecodeTagAndWireType() (tag int32, wireType int8, err error) {
- var v uint64
- v, err = cb.DecodeVarint()
- if err != nil {
- return
- }
- // low 7 bits is wire type
- wireType = int8(v & 7)
- // rest is int32 tag number
- v = v >> 3
- if v > math.MaxInt32 {
- err = fmt.Errorf("tag number out of range: %d", v)
- return
- }
- tag = int32(v)
- return
- }
-
- // DecodeFixed64 reads a 64-bit integer from the Buffer.
- // This is the format for the
- // fixed64, sfixed64, and double protocol buffer types.
- func (cb *Buffer) DecodeFixed64() (x uint64, err error) {
- // x, err already 0
- i := cb.index + 8
- if i < 0 || i > len(cb.buf) {
- err = io.ErrUnexpectedEOF
- return
- }
- cb.index = i
-
- x = uint64(cb.buf[i-8])
- x |= uint64(cb.buf[i-7]) << 8
- x |= uint64(cb.buf[i-6]) << 16
- x |= uint64(cb.buf[i-5]) << 24
- x |= uint64(cb.buf[i-4]) << 32
- x |= uint64(cb.buf[i-3]) << 40
- x |= uint64(cb.buf[i-2]) << 48
- x |= uint64(cb.buf[i-1]) << 56
- return
- }
-
- // DecodeFixed32 reads a 32-bit integer from the Buffer.
- // This is the format for the
- // fixed32, sfixed32, and float protocol buffer types.
- func (cb *Buffer) DecodeFixed32() (x uint64, err error) {
- // x, err already 0
- i := cb.index + 4
- if i < 0 || i > len(cb.buf) {
- err = io.ErrUnexpectedEOF
- return
- }
- cb.index = i
-
- x = uint64(cb.buf[i-4])
- x |= uint64(cb.buf[i-3]) << 8
- x |= uint64(cb.buf[i-2]) << 16
- x |= uint64(cb.buf[i-1]) << 24
- return
- }
-
- // DecodeZigZag32 decodes a signed 32-bit integer from the given
- // zig-zag encoded value.
- func DecodeZigZag32(v uint64) int32 {
- return int32((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31))
- }
-
- // DecodeZigZag64 decodes a signed 64-bit integer from the given
- // zig-zag encoded value.
- func DecodeZigZag64(v uint64) int64 {
- return int64((v >> 1) ^ uint64((int64(v&1)<<63)>>63))
- }
-
- // DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
- // This is the format used for the bytes protocol buffer
- // type and for embedded messages.
- func (cb *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
- n, err := cb.DecodeVarint()
- if err != nil {
- return nil, err
- }
-
- nb := int(n)
- if nb < 0 {
- return nil, fmt.Errorf("proto: bad byte length %d", nb)
- }
- end := cb.index + nb
- if end < cb.index || end > len(cb.buf) {
- return nil, io.ErrUnexpectedEOF
- }
-
- if !alloc {
- buf = cb.buf[cb.index:end]
- cb.index = end
- return
- }
-
- buf = make([]byte, nb)
- copy(buf, cb.buf[cb.index:])
- cb.index = end
- return
- }
-
- // ReadGroup reads the input until a "group end" tag is found
- // and returns the data up to that point. Subsequent reads from
- // the buffer will read data after the group end tag. If alloc
- // is true, the data is copied to a new slice before being returned.
- // Otherwise, the returned slice is a view into the buffer's
- // underlying byte slice.
- //
- // This function correctly handles nested groups: if a "group start"
- // tag is found, then that group's end tag will be included in the
- // returned data.
- func (cb *Buffer) ReadGroup(alloc bool) ([]byte, error) {
- var groupEnd, dataEnd int
- groupEnd, dataEnd, err := cb.findGroupEnd()
- if err != nil {
- return nil, err
- }
- var results []byte
- if !alloc {
- results = cb.buf[cb.index:dataEnd]
- } else {
- results = make([]byte, dataEnd-cb.index)
- copy(results, cb.buf[cb.index:])
- }
- cb.index = groupEnd
- return results, nil
- }
-
- // SkipGroup is like ReadGroup, except that it discards the
- // data and just advances the buffer to point to the input
- // right *after* the "group end" tag.
- func (cb *Buffer) SkipGroup() error {
- groupEnd, _, err := cb.findGroupEnd()
- if err != nil {
- return err
- }
- cb.index = groupEnd
- return nil
- }
-
- func (cb *Buffer) findGroupEnd() (groupEnd int, dataEnd int, err error) {
- bs := cb.buf
- start := cb.index
- defer func() {
- cb.index = start
- }()
- for {
- fieldStart := cb.index
- // read a field tag
- _, wireType, err := cb.DecodeTagAndWireType()
- if err != nil {
- return 0, 0, err
- }
- // skip past the field's data
- switch wireType {
- case proto.WireFixed32:
- if err := cb.Skip(4); err != nil {
- return 0, 0, err
- }
- case proto.WireFixed64:
- if err := cb.Skip(8); err != nil {
- return 0, 0, err
- }
- case proto.WireVarint:
- // skip varint by finding last byte (has high bit unset)
- i := cb.index
- limit := i + 10 // varint cannot be >10 bytes
- for {
- if i >= limit {
- return 0, 0, ErrOverflow
- }
- if i >= len(bs) {
- return 0, 0, io.ErrUnexpectedEOF
- }
- if bs[i]&0x80 == 0 {
- break
- }
- i++
- }
- // TODO: This would only overflow if buffer length was MaxInt and we
- // read the last byte. This is not a real/feasible concern on 64-bit
- // systems. Something to worry about for 32-bit systems? Do we care?
- cb.index = i + 1
- case proto.WireBytes:
- l, err := cb.DecodeVarint()
- if err != nil {
- return 0, 0, err
- }
- if err := cb.Skip(int(l)); err != nil {
- return 0, 0, err
- }
- case proto.WireStartGroup:
- if err := cb.SkipGroup(); err != nil {
- return 0, 0, err
- }
- case proto.WireEndGroup:
- return cb.index, fieldStart, nil
- default:
- return 0, 0, ErrBadWireType
- }
- }
- }
|