67 lines
1.6 KiB
Go
67 lines
1.6 KiB
Go
|
package qpack
|
||
|
|
||
|
// copied from the Go standard library HPACK implementation
|
||
|
|
||
|
import "errors"
|
||
|
|
||
|
var errVarintOverflow = errors.New("varint integer overflow")
|
||
|
|
||
|
// appendVarInt appends i, as encoded in variable integer form using n
|
||
|
// bit prefix, to dst and returns the extended buffer.
|
||
|
//
|
||
|
// See
|
||
|
// http://http2.github.io/http2-spec/compression.html#integer.representation
|
||
|
func appendVarInt(dst []byte, n byte, i uint64) []byte {
|
||
|
k := uint64((1 << n) - 1)
|
||
|
if i < k {
|
||
|
return append(dst, byte(i))
|
||
|
}
|
||
|
dst = append(dst, byte(k))
|
||
|
i -= k
|
||
|
for ; i >= 128; i >>= 7 {
|
||
|
dst = append(dst, byte(0x80|(i&0x7f)))
|
||
|
}
|
||
|
return append(dst, byte(i))
|
||
|
}
|
||
|
|
||
|
// readVarInt reads an unsigned variable length integer off the
|
||
|
// beginning of p. n is the parameter as described in
|
||
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
|
||
|
//
|
||
|
// n must always be between 1 and 8.
|
||
|
//
|
||
|
// The returned remain buffer is either a smaller suffix of p, or err != nil.
|
||
|
// The error is errNeedMore if p doesn't contain a complete integer.
|
||
|
func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
|
||
|
if n < 1 || n > 8 {
|
||
|
panic("bad n")
|
||
|
}
|
||
|
if len(p) == 0 {
|
||
|
return 0, p, errNeedMore
|
||
|
}
|
||
|
i = uint64(p[0])
|
||
|
if n < 8 {
|
||
|
i &= (1 << uint64(n)) - 1
|
||
|
}
|
||
|
if i < (1<<uint64(n))-1 {
|
||
|
return i, p[1:], nil
|
||
|
}
|
||
|
|
||
|
origP := p
|
||
|
p = p[1:]
|
||
|
var m uint64
|
||
|
for len(p) > 0 {
|
||
|
b := p[0]
|
||
|
p = p[1:]
|
||
|
i += uint64(b&127) << m
|
||
|
if b&128 == 0 {
|
||
|
return i, p, nil
|
||
|
}
|
||
|
m += 7
|
||
|
if m >= 63 { // TODO: proper overflow check. making this up.
|
||
|
return 0, origP, errVarintOverflow
|
||
|
}
|
||
|
}
|
||
|
return 0, origP, errNeedMore
|
||
|
}
|