blob: 87e6d5ae5d3f2e676139b6714151f0d8726513c4 [file] [log] [blame] [edit]
// Copyright 2023 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 http
// A mapping is a collection of key-value pairs where the keys are unique.
// A zero mapping is empty and ready to use.
// A mapping tries to pick a representation that makes [mapping.find] most efficient.
type mapping[K comparable, V any] struct {
s []entry[K, V] // for few pairs
m map[K]V // for many pairs
}
type entry[K comparable, V any] struct {
key K
value V
}
// maxSlice is the maximum number of pairs for which a slice is used.
// It is a variable for benchmarking.
var maxSlice int = 8
// add adds a key-value pair to the mapping.
func (h *mapping[K, V]) add(k K, v V) {
if h.m == nil && len(h.s) < maxSlice {
h.s = append(h.s, entry[K, V]{k, v})
} else {
if h.m == nil {
h.m = map[K]V{}
for _, e := range h.s {
h.m[e.key] = e.value
}
h.s = nil
}
h.m[k] = v
}
}
// find returns the value corresponding to the given key.
// The second return value is false if there is no value
// with that key.
func (h *mapping[K, V]) find(k K) (v V, found bool) {
if h == nil {
return v, false
}
if h.m != nil {
v, found = h.m[k]
return v, found
}
for _, e := range h.s {
if e.key == k {
return e.value, true
}
}
return v, false
}
// eachPair calls f for each pair in the mapping.
// If f returns false, pairs returns immediately.
func (h *mapping[K, V]) eachPair(f func(k K, v V) bool) {
if h == nil {
return
}
if h.m != nil {
for k, v := range h.m {
if !f(k, v) {
return
}
}
} else {
for _, e := range h.s {
if !f(e.key, e.value) {
return
}
}
}
}