github.com/amazechain/amc@v0.1.3/internal/p2p/encoder/varint.go (about)

     1  package encoder
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/pkg/errors"
     7  )
     8  
     9  const maxVarintLength = 10
    10  
    11  var errExcessMaxLength = errors.Errorf("provided header exceeds the max varint length of %d bytes", maxVarintLength)
    12  
    13  // readVarint at the beginning of a byte slice. This varint may be used to indicate
    14  // the length of the remaining bytes in the reader.
    15  func readVarint(r io.Reader) (uint64, error) {
    16  	b := make([]byte, 0, maxVarintLength)
    17  	for i := 0; i < maxVarintLength; i++ {
    18  		b1 := make([]byte, 1)
    19  		n, err := r.Read(b1)
    20  		if err != nil {
    21  			return 0, err
    22  		}
    23  		if n != 1 {
    24  			return 0, errors.New("did not read a byte from stream")
    25  		}
    26  		b = append(b, b1[0])
    27  
    28  		// If most significant bit is not set, we have reached the end of the Varint.
    29  		if b1[0]&0x80 == 0 {
    30  			break
    31  		}
    32  
    33  		// If the varint is larger than 10 bytes, it is invalid as it would
    34  		// exceed the size of MaxUint64.
    35  		if i+1 >= maxVarintLength {
    36  			return 0, errExcessMaxLength
    37  		}
    38  	}
    39  
    40  	vi, n := DecodeVarint(b)
    41  	if n != len(b) {
    42  		return 0, errors.New("varint did not decode entire byte slice")
    43  	}
    44  	return vi, nil
    45  }
    46  
    47  // DecodeVarint reads a varint-encoded integer from the slice.
    48  // It returns the integer and the number of bytes consumed, or
    49  // zero if there is not enough.
    50  // This is the format for the
    51  // int32, int64, uint32, uint64, bool, and enum
    52  // protocol buffer types.
    53  func DecodeVarint(buf []byte) (x uint64, n int) {
    54  	for shift := uint(0); shift < 64; shift += 7 {
    55  		if n >= len(buf) {
    56  			return 0, 0
    57  		}
    58  		b := uint64(buf[n])
    59  		n++
    60  		x |= (b & 0x7F) << shift
    61  		if (b & 0x80) == 0 {
    62  			return x, n
    63  		}
    64  	}
    65  
    66  	// The number is too large to represent in a 64-bit value.
    67  	return 0, 0
    68  }
    69  
    70  const maxVarintBytes = 10 // maximum length of a varint
    71  
    72  // EncodeVarint returns the varint encoding of x.
    73  // This is the format for the
    74  // int32, int64, uint32, uint64, bool, and enum
    75  // protocol buffer types.
    76  // Not used by the package itself, but helpful to clients
    77  // wishing to use the same encoding.
    78  func EncodeVarint(x uint64) []byte {
    79  	var buf [maxVarintBytes]byte
    80  	var n int
    81  	for n = 0; x > 127; n++ {
    82  		buf[n] = 0x80 | uint8(x&0x7F)
    83  		x >>= 7
    84  	}
    85  	buf[n] = uint8(x)
    86  	n++
    87  	return buf[0:n]
    88  }