github.com/m3db/m3@v1.5.0/src/dbnode/encoding/proto/buffer_decode.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  // This file is mostly copy-pasta from: https://github.com/jhump/protoreflect/blob/master/dynamic/codec.go
    22  // since the jhump/protoreflect library does not expose the `codedBuffer` type.
    23  
    24  package proto
    25  
    26  import (
    27  	"errors"
    28  	"fmt"
    29  	"io"
    30  	"math"
    31  )
    32  
    33  var (
    34  	// errOverflow is returned when an integer is too large to be represented.
    35  	errOverflow = errors.New("proto: integer overflow")
    36  )
    37  
    38  // A reader/writer type that assists with decoding protobuf's binary representation.
    39  // This code is largely a fork of proto.Buffer, which cannot be used because it has no exported
    40  // field or method that provides access to its underlying reader index.
    41  type buffer struct {
    42  	buf   []byte
    43  	index int
    44  }
    45  
    46  func newCodedBuffer(buf []byte) *buffer {
    47  	return &buffer{buf: buf}
    48  }
    49  
    50  func (cb *buffer) reset(b []byte) {
    51  	cb.buf = b
    52  	cb.index = 0
    53  }
    54  
    55  func (cb *buffer) eof() bool {
    56  	return cb.index >= len(cb.buf)
    57  }
    58  
    59  func (cb *buffer) skip(count int) (int, bool) {
    60  	newIndex := cb.index + count
    61  	if newIndex > len(cb.buf) {
    62  		return 0, false
    63  	}
    64  	cb.index = newIndex
    65  	return 0, true
    66  }
    67  
    68  func (cb *buffer) decodeVarintSlow() (x uint64, err error) {
    69  	i := cb.index
    70  	l := len(cb.buf)
    71  
    72  	for shift := uint(0); shift < 64; shift += 7 {
    73  		if i >= l {
    74  			err = io.ErrUnexpectedEOF
    75  			return
    76  		}
    77  		b := cb.buf[i]
    78  		i++
    79  		x |= (uint64(b) & 0x7F) << shift
    80  		if b < 0x80 {
    81  			cb.index = i
    82  			return
    83  		}
    84  	}
    85  
    86  	// The number is too large to represent in a 64-bit value.
    87  	err = errOverflow
    88  	return
    89  }
    90  
    91  // DecodeVarint reads a varint-encoded integer from the Buffer.
    92  // This is the format for the
    93  // int32, int64, uint32, uint64, bool, and enum
    94  // protocol buffer types.
    95  func (cb *buffer) decodeVarint() (uint64, error) {
    96  	i := cb.index
    97  	buf := cb.buf
    98  
    99  	if i >= len(buf) {
   100  		return 0, io.ErrUnexpectedEOF
   101  	} else if buf[i] < 0x80 {
   102  		cb.index++
   103  		return uint64(buf[i]), nil
   104  	} else if len(buf)-i < 10 {
   105  		return cb.decodeVarintSlow()
   106  	}
   107  
   108  	var b uint64
   109  	// we already checked the first byte
   110  	x := uint64(buf[i]) - 0x80
   111  	i++
   112  
   113  	b = uint64(buf[i])
   114  	i++
   115  	x += b << 7
   116  	if b&0x80 == 0 {
   117  		goto done
   118  	}
   119  	x -= 0x80 << 7
   120  
   121  	b = uint64(buf[i])
   122  	i++
   123  	x += b << 14
   124  	if b&0x80 == 0 {
   125  		goto done
   126  	}
   127  	x -= 0x80 << 14
   128  
   129  	b = uint64(buf[i])
   130  	i++
   131  	x += b << 21
   132  	if b&0x80 == 0 {
   133  		goto done
   134  	}
   135  	x -= 0x80 << 21
   136  
   137  	b = uint64(buf[i])
   138  	i++
   139  	x += b << 28
   140  	if b&0x80 == 0 {
   141  		goto done
   142  	}
   143  	x -= 0x80 << 28
   144  
   145  	b = uint64(buf[i])
   146  	i++
   147  	x += b << 35
   148  	if b&0x80 == 0 {
   149  		goto done
   150  	}
   151  	x -= 0x80 << 35
   152  
   153  	b = uint64(buf[i])
   154  	i++
   155  	x += b << 42
   156  	if b&0x80 == 0 {
   157  		goto done
   158  	}
   159  	x -= 0x80 << 42
   160  
   161  	b = uint64(buf[i])
   162  	i++
   163  	x += b << 49
   164  	if b&0x80 == 0 {
   165  		goto done
   166  	}
   167  	x -= 0x80 << 49
   168  
   169  	b = uint64(buf[i])
   170  	i++
   171  	x += b << 56
   172  	if b&0x80 == 0 {
   173  		goto done
   174  	}
   175  	x -= 0x80 << 56
   176  
   177  	b = uint64(buf[i])
   178  	i++
   179  	x += b << 63
   180  	if b&0x80 == 0 {
   181  		goto done
   182  	}
   183  	// x -= 0x80 << 63 // Always zero.
   184  
   185  	return 0, errOverflow
   186  
   187  done:
   188  	cb.index = i
   189  	return x, nil
   190  }
   191  
   192  func (cb *buffer) decodeTagAndWireType() (tag int32, wireType int8, err error) {
   193  	var v uint64
   194  	v, err = cb.decodeVarint()
   195  	if err != nil {
   196  		return
   197  	}
   198  	// low 7 bits is wire type
   199  	wireType = int8(v & 7)
   200  	// rest is int32 tag number
   201  	v = v >> 3
   202  	if v > math.MaxInt32 {
   203  		err = fmt.Errorf("tag number out of range: %d", v)
   204  		return
   205  	}
   206  	tag = int32(v)
   207  	return
   208  }
   209  
   210  // DecodeFixed64 reads a 64-bit integer from the Buffer.
   211  // This is the format for the
   212  // fixed64, sfixed64, and double protocol buffer types.
   213  func (cb *buffer) decodeFixed64() (x uint64, err error) {
   214  	// x, err already 0
   215  	i := cb.index + 8
   216  	if i < 0 || i > len(cb.buf) {
   217  		err = io.ErrUnexpectedEOF
   218  		return
   219  	}
   220  	cb.index = i
   221  
   222  	x = uint64(cb.buf[i-8])
   223  	x |= uint64(cb.buf[i-7]) << 8
   224  	x |= uint64(cb.buf[i-6]) << 16
   225  	x |= uint64(cb.buf[i-5]) << 24
   226  	x |= uint64(cb.buf[i-4]) << 32
   227  	x |= uint64(cb.buf[i-3]) << 40
   228  	x |= uint64(cb.buf[i-2]) << 48
   229  	x |= uint64(cb.buf[i-1]) << 56
   230  	return
   231  }
   232  
   233  // DecodeFixed32 reads a 32-bit integer from the Buffer.
   234  // This is the format for the
   235  // fixed32, sfixed32, and float protocol buffer types.
   236  func (cb *buffer) decodeFixed32() (x uint64, err error) {
   237  	// x, err already 0
   238  	i := cb.index + 4
   239  	if i < 0 || i > len(cb.buf) {
   240  		err = io.ErrUnexpectedEOF
   241  		return
   242  	}
   243  	cb.index = i
   244  
   245  	x = uint64(cb.buf[i-4])
   246  	x |= uint64(cb.buf[i-3]) << 8
   247  	x |= uint64(cb.buf[i-2]) << 16
   248  	x |= uint64(cb.buf[i-1]) << 24
   249  	return
   250  }
   251  
   252  func decodeZigZag32(v uint64) int32 {
   253  	return int32((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31))
   254  }
   255  
   256  func decodeZigZag64(v uint64) int64 {
   257  	return int64((v >> 1) ^ uint64((int64(v&1)<<63)>>63))
   258  }
   259  
   260  // These are not ValueDecoders: they produce an array of bytes or a string.
   261  // bytes, embedded messages
   262  
   263  // DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
   264  // This is the format used for the bytes protocol buffer
   265  // type and for embedded messages.
   266  func (cb *buffer) decodeRawBytes(alloc bool) (buf []byte, err error) {
   267  	n, err := cb.decodeVarint()
   268  	if err != nil {
   269  		return nil, err
   270  	}
   271  
   272  	nb := int(n)
   273  	if nb < 0 {
   274  		return nil, fmt.Errorf("proto: bad byte length %d", nb)
   275  	}
   276  	end := cb.index + nb
   277  	if end < cb.index || end > len(cb.buf) {
   278  		return nil, io.ErrUnexpectedEOF
   279  	}
   280  
   281  	if !alloc {
   282  		buf = cb.buf[cb.index:end]
   283  		cb.index += nb
   284  		return
   285  	}
   286  
   287  	buf = make([]byte, nb)
   288  	copy(buf, cb.buf[cb.index:])
   289  	cb.index += nb
   290  	return
   291  }