Source File
hpack.go
Belonging Package
golang.org/x/net/http2/hpack
package hpack
import (
)
type DecodingError struct {
Err error
}
func ( DecodingError) () string {
return fmt.Sprintf("decoding error: %v", .Err)
}
type InvalidIndexError int
func ( InvalidIndexError) () string {
return fmt.Sprintf("invalid indexed representation index %d", int())
}
type HeaderField struct {
Name, Value string
type Decoder struct {
dynTab dynamicTable
emit func(f HeaderField)
emitEnabled bool // whether calls to emit are enabled
maxStrLen int // 0 means unlimited
saveBuf bytes.Buffer
firstField bool // processing the first field of the header block
}
func ( uint32, func( HeaderField)) *Decoder {
:= &Decoder{
emit: ,
emitEnabled: true,
firstField: true,
}
.dynTab.table.init()
.dynTab.allowedMaxSize =
.dynTab.setMaxSize()
return
}
var ErrStringLength = errors.New("hpack: string too long")
func ( *Decoder) ( func( HeaderField)) {
.emit =
}
func ( *Decoder) ( bool) { .emitEnabled = }
func ( *Decoder) () bool { return .emitEnabled }
func ( *Decoder) ( uint32) {
.dynTab.setMaxSize()
}
func ( *Decoder) ( uint32) {
.dynTab.allowedMaxSize =
}
table headerFieldTable
size uint32 // in bytes
maxSize uint32 // current maxSize
allowedMaxSize uint32 // maxSize may go up to this, inclusive
}
func ( *dynamicTable) ( uint32) {
.maxSize =
.evict()
}
func ( *dynamicTable) ( HeaderField) {
.table.addEntry()
.size += .Size()
.evict()
}
return .dynTab.table.len() + staticTable.len()
}
if == 0 {
return
}
if <= uint64(staticTable.len()) {
return staticTable.ents[-1], true
}
if > uint64(.maxTableIndex()) {
return
return
var errNeedMore = errors.New("need more data")
type indexType int
const (
indexedTrue indexType = iota
indexedFalse
indexedNever
)
func ( indexType) () bool { return == indexedTrue }
func ( indexType) () bool { return == indexedNever }
return .parseFieldIndexed()
return .parseFieldLiteral(6, indexedTrue)
return .parseFieldLiteral(4, indexedFalse)
return .parseFieldLiteral(4, indexedNever)
return .parseDynamicTableSizeUpdate()
}
return DecodingError{errors.New("invalid encoding")}
}
func ( *Decoder) () error {
:= .buf
, , := readVarInt(7, )
if != nil {
return
}
, := .at()
if ! {
return DecodingError{InvalidIndexError()}
}
.buf =
return .callEmit(HeaderField{Name: .Name, Value: .Value})
}
func ( *Decoder) ( uint8, indexType) error {
:= .buf
, , := readVarInt(, )
if != nil {
return
}
var HeaderField
:= .emitEnabled || .indexed()
if > 0 {
, := .at()
if ! {
return DecodingError{InvalidIndexError()}
}
.Name = .Name
} else {
.Name, , = .readString(, )
if != nil {
return
}
}
.Value, , = .readString(, )
if != nil {
return
}
.buf =
if .indexed() {
.dynTab.add()
}
.Sensitive = .sensitive()
return .callEmit()
}
func ( *Decoder) ( HeaderField) error {
if .maxStrLen != 0 {
if len(.Name) > .maxStrLen || len(.Value) > .maxStrLen {
return ErrStringLength
}
}
if .emitEnabled {
.emit()
}
return nil
}
if !.firstField && .dynTab.size > 0 {
return DecodingError{errors.New("dynamic table size update MUST occur at the beginning of a header block")}
}
:= .buf
, , := readVarInt(5, )
if != nil {
return
}
if > uint64(.dynTab.allowedMaxSize) {
return DecodingError{errors.New("dynamic table size update too large")}
}
.dynTab.setMaxSize(uint32())
.buf =
return nil
}
var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
func ( byte, []byte) ( uint64, []byte, error) {
if < 1 || > 8 {
panic("bad n")
}
if len() == 0 {
return 0, , errNeedMore
}
= uint64([0])
if < 8 {
&= (1 << uint64()) - 1
}
if < (1<<uint64())-1 {
return , [1:], nil
}
:=
= [1:]
var uint64
for len() > 0 {
:= [0]
= [1:]
+= uint64(&127) <<
if &128 == 0 {
return , , nil
}
+= 7
if >= 63 { // TODO: proper overflow check. making this up.
return 0, , errVarintOverflow
}
}
return 0, , errNeedMore
}
func ( *Decoder) ( []byte, bool) ( string, []byte, error) {
if len() == 0 {
return "", , errNeedMore
}
:= [0]&128 != 0
, , := readVarInt(7, )
if != nil {
return "", ,
}
if .maxStrLen != 0 && > uint64(.maxStrLen) {
return "", nil, ErrStringLength
}
if uint64(len()) < {
return "", , errNeedMore
}
if ! {
if {
= string([:])
}
return , [:], nil
}
if {
:= bufPool.Get().(*bytes.Buffer)
.Reset() // don't trust others
defer bufPool.Put()
if := huffmanDecode(, .maxStrLen, [:]); != nil {
.Reset()
return "", nil,
}
= .String()
.Reset() // be nice to GC
}
return , [:], nil
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |