github.com/segmentio/encoding@v0.4.0/proto/decode.go (about) 1 package proto 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "io" 7 "unsafe" 8 ) 9 10 // DecodeTag reverses the encoding applied by EncodeTag. 11 func DecodeTag(tag uint64) (FieldNumber, WireType) { 12 return FieldNumber(tag >> 3), WireType(tag & 7) 13 } 14 15 // DecodeZigZag reverses the encoding applied by EncodeZigZag. 16 func DecodeZigZag(v uint64) int64 { 17 return decodeZigZag64(v) 18 } 19 20 func decodeZigZag64(v uint64) int64 { 21 return int64(v>>1) ^ -(int64(v) & 1) 22 } 23 24 func decodeZigZag32(v uint32) int32 { 25 return int32(v>>1) ^ -(int32(v) & 1) 26 } 27 28 type decodeFunc = func([]byte, unsafe.Pointer, flags) (int, error) 29 30 var ( 31 errVarintOverflow = errors.New("varint overflowed 64 bits integer") 32 ) 33 34 func decodeVarint(b []byte) (uint64, int, error) { 35 if len(b) != 0 && b[0] < 0x80 { 36 // Fast-path for decoding the common case of varints that fit on a 37 // single byte. 38 // 39 // This path is ~60% faster than calling binary.Uvarint. 40 return uint64(b[0]), 1, nil 41 } 42 43 var x uint64 44 var s uint 45 46 for i, c := range b { 47 if c < 0x80 { 48 if i > 9 || i == 9 && c > 1 { 49 return 0, i, errVarintOverflow 50 } 51 return x | uint64(c)<<s, i + 1, nil 52 } 53 x |= uint64(c&0x7f) << s 54 s += 7 55 } 56 57 return x, len(b), io.ErrUnexpectedEOF 58 } 59 60 func decodeVarintZigZag(b []byte) (int64, int, error) { 61 v, n, err := decodeVarint(b) 62 return decodeZigZag64(v), n, err 63 } 64 65 func decodeLE32(b []byte) (uint32, int, error) { 66 if len(b) < 4 { 67 return 0, 0, io.ErrUnexpectedEOF 68 } 69 return binary.LittleEndian.Uint32(b), 4, nil 70 } 71 72 func decodeLE64(b []byte) (uint64, int, error) { 73 if len(b) < 8 { 74 return 0, 0, io.ErrUnexpectedEOF 75 } 76 return binary.LittleEndian.Uint64(b), 8, nil 77 } 78 79 func decodeTag(b []byte) (f fieldNumber, t wireType, n int, err error) { 80 v, n, err := decodeVarint(b) 81 return fieldNumber(v >> 3), wireType(v & 7), n, err 82 } 83 84 func decodeVarlen(b []byte) ([]byte, int, error) { 85 v, n, err := decodeVarint(b) 86 if err != nil { 87 return nil, n, err 88 } 89 if v > uint64(len(b)-n) { 90 return nil, n, io.ErrUnexpectedEOF 91 } 92 return b[n : n+int(v)], n + int(v), nil 93 }