// Copyright 2014 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package hpackimport ()const ( uint32Max = ^uint32(0) initialHeaderTableSize = 4096)typeEncoderstruct { dynTab dynamicTable// minSize is the minimum table size set by // SetMaxDynamicTableSize after the previous Header Table Size // Update. minSize uint32// maxSizeLimit is the maximum table size this encoder // supports. This will protect the encoder from too large // size. maxSizeLimit uint32// tableSizeUpdate indicates whether "Header Table Size // Update" is required. tableSizeUpdate bool w io.Writer buf []byte}// NewEncoder returns a new Encoder which performs HPACK encoding. An// encoded data is written to w.func ( io.Writer) *Encoder { := &Encoder{minSize: uint32Max,maxSizeLimit: initialHeaderTableSize,tableSizeUpdate: false,w: , } .dynTab.table.init() .dynTab.setMaxSize(initialHeaderTableSize)return}// WriteField encodes f into a single Write to e's underlying Writer.// This function may also produce bytes for "Header Table Size Update"// if necessary. If produced, it is done before encoding f.func ( *Encoder) ( HeaderField) error { .buf = .buf[:0]if .tableSizeUpdate { .tableSizeUpdate = falseif .minSize < .dynTab.maxSize { .buf = appendTableSize(.buf, .minSize) } .minSize = uint32Max .buf = appendTableSize(.buf, .dynTab.maxSize) } , := .searchTable()if { .buf = appendIndexed(.buf, ) } else { := .shouldIndex()if { .dynTab.add() }if == 0 { .buf = appendNewName(.buf, , ) } else { .buf = appendIndexedName(.buf, , , ) } } , := .w.Write(.buf)if == nil && != len(.buf) { = io.ErrShortWrite }return}// searchTable searches f in both stable and dynamic header tables.// The static header table is searched first. Only when there is no// exact match for both name and value, the dynamic header table is// then searched. If there is no match, i is 0. If both name and value// match, i is the matched index and nameValueMatch becomes true. If// only name matches, i points to that index and nameValueMatch// becomes false.func ( *Encoder) ( HeaderField) ( uint64, bool) { , = staticTable.search()if {return , true } , := .dynTab.table.search()if || ( == 0 && != 0) {return + uint64(staticTable.len()), }return , false}// SetMaxDynamicTableSize changes the dynamic header table size to v.// The actual size is bounded by the value passed to// SetMaxDynamicTableSizeLimit.func ( *Encoder) ( uint32) {if > .maxSizeLimit { = .maxSizeLimit }if < .minSize { .minSize = } .tableSizeUpdate = true .dynTab.setMaxSize()}// MaxDynamicTableSize returns the current dynamic header table size.func ( *Encoder) () ( uint32) {return .dynTab.maxSize}// SetMaxDynamicTableSizeLimit changes the maximum value that can be// specified in SetMaxDynamicTableSize to v. By default, it is set to// 4096, which is the same size of the default dynamic header table// size described in HPACK specification. If the current maximum// dynamic header table size is strictly greater than v, "Header Table// Size Update" will be done in the next WriteField call and the// maximum dynamic header table size is truncated to v.func ( *Encoder) ( uint32) { .maxSizeLimit = if .dynTab.maxSize > { .tableSizeUpdate = true .dynTab.setMaxSize() }}// shouldIndex reports whether f should be indexed.func ( *Encoder) ( HeaderField) bool {return !.Sensitive && .Size() <= .dynTab.maxSize}// appendIndexed appends index i, as encoded in "Indexed Header Field"// representation, to dst and returns the extended buffer.func appendIndexed( []byte, uint64) []byte { := len() = appendVarInt(, 7, ) [] |= 0x80return}// appendNewName appends f, as encoded in one of "Literal Header field// - New Name" representation variants, to dst and returns the// extended buffer.//// If f.Sensitive is true, "Never Indexed" representation is used. If// f.Sensitive is false and indexing is true, "Incremental Indexing"// representation is used.func appendNewName( []byte, HeaderField, bool) []byte { = append(, encodeTypeByte(, .Sensitive)) = appendHpackString(, .Name)returnappendHpackString(, .Value)}// appendIndexedName appends f and index i referring indexed name// entry, as encoded in one of "Literal Header field - Indexed Name"// representation variants, to dst and returns the extended buffer.//// If f.Sensitive is true, "Never Indexed" representation is used. If// f.Sensitive is false and indexing is true, "Incremental Indexing"// representation is used.func appendIndexedName( []byte, HeaderField, uint64, bool) []byte { := len()varbyteif { = 6 } else { = 4 } = appendVarInt(, , ) [] |= encodeTypeByte(, .Sensitive)returnappendHpackString(, .Value)}// appendTableSize appends v, as encoded in "Header Table Size Update"// representation, to dst and returns the extended buffer.func appendTableSize( []byte, uint32) []byte { := len() = appendVarInt(, 5, uint64()) [] |= 0x20return}// appendVarInt appends i, as encoded in variable integer form using n// bit prefix, to dst and returns the extended buffer.//// See// https://httpwg.org/specs/rfc7541.html#integer.representationfunc appendVarInt( []byte, byte, uint64) []byte { := uint64((1 << ) - 1)if < {returnappend(, byte()) } = append(, byte()) -= for ; >= 128; >>= 7 { = append(, byte(0x80|(&0x7f))) }returnappend(, byte())}// appendHpackString appends s, as encoded in "String Literal"// representation, to dst and returns the extended buffer.//// s will be encoded in Huffman codes only when it produces strictly// shorter byte string.func appendHpackString( []byte, string) []byte { := HuffmanEncodeLength()if < uint64(len()) { := len() = appendVarInt(, 7, ) = AppendHuffmanString(, ) [] |= 0x80 } else { = appendVarInt(, 7, uint64(len())) = append(, ...) }return}// encodeTypeByte returns type byte. If sensitive is true, type byte// for "Never Indexed" representation is returned. If sensitive is// false and indexing is true, type byte for "Incremental Indexing"// representation is returned. Otherwise, type byte for "Without// Indexing" is returned.func encodeTypeByte(, bool) byte {if {return0x10 }if {return0x40 }return0}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux 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 @zigo_101 (reachable from the left QR code) to get the latest news of Golds.