varint encoded values

master
Jordan Orelli 8 years ago
parent 73f35ecad8
commit 3b8ff04f04

@ -96,4 +96,27 @@ func (r *Reader) ReadUBitVar() uint64 {
} }
} }
// ReadVarInt reads a variable length int value as a uint64. This is the binary
// representation used by Protobuf. Each byte contributes 7 bits to the value
// in little-endian order. The most-significant bit of each byte represents a
// continuation bit.
func (r *Reader) ReadVarInt() uint64 {
var (
x uint64
b uint64
shift uint
)
for ; shift < 64; shift += 7 {
b = r.ReadBits(8)
if r.Err() != nil {
return 0
}
x |= b & 0x7f << shift
if b&0x80 == 0 {
return x
}
}
return x
}
func (r *Reader) Err() error { return r.err } func (r *Reader) Err() error { return r.err }

@ -104,16 +104,16 @@ func TestUbitVar(t *testing.T) {
r.ReadBits(2) r.ReadBits(2)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ||| | ^--^ : most significant (1111) // ||| | ^--^ : msb (1111)
// ||^---^ : least significant (0110) // ||^---^ : lsb (0110)
// ^^ : prefix (01) // ^^ : prefix (01)
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(0xf6), u) assert.Equal(uint64(0xf6), u)
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ||| |^----+---^ : most significant (1110 1011) // ||| |^----+---^ : msb (1110 1011)
// ||^---^ : least significant (0010) // ||^---^ : lsb (0010)
// ^^ : prefix (10) // ^^ : prefix (10)
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(0xeb2), u) assert.Equal(uint64(0xeb2), u)
@ -124,7 +124,52 @@ func TestUbitVar(t *testing.T) {
// ||| |^----+----+----+----+----+----+---^ : msb (0111 1011 1001 1110 // ||| |^----+----+----+----+----+----+---^ : msb (0111 1011 1001 1110
// ||| | 1111 1011 1011) // ||| | 1111 1011 1011)
// ||^---^ : lsb (1000) // ||^---^ : lsb (1000)
// ^^ : prefix // ^^ : prefix (11)
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(0x7b9efbb8), u) assert.Equal(uint64(0x7b9efbb8), u)
} }
func TestVarInt(t *testing.T) {
var (
assert = assert.New(t)
r *Reader
u uint64
)
r = NewBytesReader(badFood)
r.ReadBits(24)
// 1000 1011 1010 1101 1111 0000 0000 1101
// |^------^ : data
// ^ : stop
u = r.ReadVarInt()
assert.Equal(uint64(0xd), u)
r = NewBytesReader(badFood)
r.ReadBits(16)
// 1000 1011 1010 1101 1111 0000 0000 1101
// || | |^------^ : msb
// || | ^ : stop
// |^------^ : lsb
// ^ : continue
// data bits:
// 0000 0110 1111 0000
// 0 6 f 0
u = r.ReadVarInt()
assert.Equal(uint64(0x6f0), u)
r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101
// || | || | || | |^------^ : msb (000 1101)
// || | || | || | ^ : stop
// || | || | |^------^ : data (111 0000)
// || | || | ^ : continue
// || | |^------^ : data (010 1101)
// || | ^ : continue
// |^------^ : lsb (000 1011)
// ^ : continue
// data bits:
// 0001 1011 1100 0001 0110 1000 1011
// 1 b c 1 6 8 b
u = r.ReadVarInt()
assert.Equal(uint64(0x1bc168b), u)
}

Loading…
Cancel
Save