Skip to content

Commit

Permalink
fix minor interoperability issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
raulk committed Jul 29, 2020
1 parent 9946570 commit 35d989b
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions varint.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,25 @@ import (
)

var (
ErrOverflow = errors.New("varints larger than uint64 not yet supported")
ErrOverflow = errors.New("varints larger than uint63 not supported")
ErrUnderflow = errors.New("varints malformed, could not reach the end")
ErrNotMinimal = errors.New("varint not minimally encoded")
)

const (
// MaxLenUvarint63 is the maximum number of bytes representing an uvarint in
// this encoding, supporting a maximum value of 2^63 (uint63), aka
// MaxValueUvarint63.
MaxLenUvarint63 = 9

// MaxValueUvarint63 is the maximum encodable uint63 value.
MaxValueUvarint63 = 1 << 63
)

// UvarintSize returns the size (in bytes) of `num` encoded as a unsigned varint.
//
// This may return a size greater than MaxUvarintLen63, which would be an
// illegal value, and would be rejected by readers.
func UvarintSize(num uint64) int {
bits := bits.Len64(num)
q, r := bits/7, bits%7
Expand All @@ -39,10 +52,14 @@ func FromUvarint(buf []byte) (uint64, int, error) {
var x uint64
var s uint
for i, b := range buf {
if (i == 8 && b >= 0x80) || i >= MaxLenUvarint63 {
// this is the 9th and last byte we're willing to read, but it
// signals there's more (1 in MSB).
// or this is the >= 10th byte, and for some reason we're still here.
return 0, 0, ErrOverflow
}
if b < 0x80 {
if i > 9 || i == 9 && b > 1 {
return 0, 0, ErrOverflow
} else if b == 0 && s > 0 {
if b == 0 && s > 0 {
return 0, 0, ErrNotMinimal
}
return x | uint64(b)<<s, i + 1, nil
Expand Down Expand Up @@ -70,12 +87,14 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
}
return 0, err
}
if (i == 8 && b >= 0x80) || i >= MaxLenUvarint63 {
// this is the 9th and last byte we're willing to read, but it
// signals there's more (1 in MSB).
// or this is the >= 10th byte, and for some reason we're still here.
return 0, ErrOverflow
}
if b < 0x80 {
if i > 9 || i == 9 && b > 1 {
return 0, ErrOverflow
} else if b == 0 && s > 0 {
// we should never _finish_ on a 0 byte if we
// have more than one byte.
if b == 0 && s > 0 {
return 0, ErrNotMinimal
}
return x | uint64(b)<<s, nil
Expand All @@ -89,6 +108,9 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
//
// This is provided for convenience so users of this library can avoid built-in
// varint functions and easily audit code for uses of those functions.
//
// Make sure that x is smaller or equal to MaxValueUvarint63, otherwise this
// function will produce values that may be rejected by readers.
func PutUvarint(buf []byte, x uint64) int {
return binary.PutUvarint(buf, x)
}

0 comments on commit 35d989b

Please sign in to comment.