blob: 0efa8e558cf565a1512b6f36b450ff93857eaf4a [file] [log] [blame]
// Copyright 2022 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.
//go:build ignore
package main
import (
"bytes"
"fmt"
"go/format"
"os"
"sort"
"golang.org/x/net/http2/hpack"
)
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
var staticTableEntries = [...]hpack.HeaderField{
{Name: ":authority"},
{Name: ":method", Value: "GET"},
{Name: ":method", Value: "POST"},
{Name: ":path", Value: "/"},
{Name: ":path", Value: "/index.html"},
{Name: ":scheme", Value: "http"},
{Name: ":scheme", Value: "https"},
{Name: ":status", Value: "200"},
{Name: ":status", Value: "204"},
{Name: ":status", Value: "206"},
{Name: ":status", Value: "304"},
{Name: ":status", Value: "400"},
{Name: ":status", Value: "404"},
{Name: ":status", Value: "500"},
{Name: "accept-charset"},
{Name: "accept-encoding", Value: "gzip, deflate"},
{Name: "accept-language"},
{Name: "accept-ranges"},
{Name: "accept"},
{Name: "access-control-allow-origin"},
{Name: "age"},
{Name: "allow"},
{Name: "authorization"},
{Name: "cache-control"},
{Name: "content-disposition"},
{Name: "content-encoding"},
{Name: "content-language"},
{Name: "content-length"},
{Name: "content-location"},
{Name: "content-range"},
{Name: "content-type"},
{Name: "cookie"},
{Name: "date"},
{Name: "etag"},
{Name: "expect"},
{Name: "expires"},
{Name: "from"},
{Name: "host"},
{Name: "if-match"},
{Name: "if-modified-since"},
{Name: "if-none-match"},
{Name: "if-range"},
{Name: "if-unmodified-since"},
{Name: "last-modified"},
{Name: "link"},
{Name: "location"},
{Name: "max-forwards"},
{Name: "proxy-authenticate"},
{Name: "proxy-authorization"},
{Name: "range"},
{Name: "referer"},
{Name: "refresh"},
{Name: "retry-after"},
{Name: "server"},
{Name: "set-cookie"},
{Name: "strict-transport-security"},
{Name: "transfer-encoding"},
{Name: "user-agent"},
{Name: "vary"},
{Name: "via"},
{Name: "www-authenticate"},
}
type pairNameValue struct {
name, value string
}
type byNameItem struct {
name string
id uint64
}
type byNameValueItem struct {
pairNameValue
id uint64
}
func headerFieldToString(f hpack.HeaderField) string {
return fmt.Sprintf("{Name: \"%s\", Value:\"%s\", Sensitive: %t}", f.Name, f.Value, f.Sensitive)
}
func pairNameValueToString(v pairNameValue) string {
return fmt.Sprintf("{name: \"%s\", value:\"%s\"}", v.name, v.value)
}
const header = `
// go generate gen.go
// Code generated by the command above; DO NOT EDIT.
package hpack
var staticTable = &headerFieldTable{
evictCount: 0,
byName: map[string]uint64{
`
//go:generate go run gen.go
func main() {
var bb bytes.Buffer
fmt.Fprintf(&bb, header)
byName := make(map[string]uint64)
byNameValue := make(map[pairNameValue]uint64)
for index, entry := range staticTableEntries {
id := uint64(index) + 1
byName[entry.Name] = id
byNameValue[pairNameValue{entry.Name, entry.Value}] = id
}
// Sort maps for deterministic generation.
byNameItems := sortByName(byName)
byNameValueItems := sortByNameValue(byNameValue)
for _, item := range byNameItems {
fmt.Fprintf(&bb, "\"%s\":%d,\n", item.name, item.id)
}
fmt.Fprintf(&bb, "},\n")
fmt.Fprintf(&bb, "byNameValue: map[pairNameValue]uint64{\n")
for _, item := range byNameValueItems {
fmt.Fprintf(&bb, "%s:%d,\n", pairNameValueToString(item.pairNameValue), item.id)
}
fmt.Fprintf(&bb, "},\n")
fmt.Fprintf(&bb, "ents: []HeaderField{\n")
for _, value := range staticTableEntries {
fmt.Fprintf(&bb, "%s,\n", headerFieldToString(value))
}
fmt.Fprintf(&bb, "},\n")
fmt.Fprintf(&bb, "}\n")
genFile("static_table.go", &bb)
}
func sortByNameValue(byNameValue map[pairNameValue]uint64) []byNameValueItem {
var byNameValueItems []byNameValueItem
for k, v := range byNameValue {
byNameValueItems = append(byNameValueItems, byNameValueItem{k, v})
}
sort.Slice(byNameValueItems, func(i, j int) bool {
return byNameValueItems[i].id < byNameValueItems[j].id
})
return byNameValueItems
}
func sortByName(byName map[string]uint64) []byNameItem {
var byNameItems []byNameItem
for k, v := range byName {
byNameItems = append(byNameItems, byNameItem{k, v})
}
sort.Slice(byNameItems, func(i, j int) bool {
return byNameItems[i].id < byNameItems[j].id
})
return byNameItems
}
func genFile(name string, buf *bytes.Buffer) {
b, err := format.Source(buf.Bytes())
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := os.WriteFile(name, b, 0644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}