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 }