1// Copyright 2023 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package http
6
7// A mapping is a collection of key-value pairs where the keys are unique.
8// A zero mapping is empty and ready to use.
9// A mapping tries to pick a representation that makes [mapping.find] most efficient.
10type mapping[K comparable, V any] struct {
11	s []entry[K, V] // for few pairs
12	m map[K]V       // for many pairs
13}
14
15type entry[K comparable, V any] struct {
16	key   K
17	value V
18}
19
20// maxSlice is the maximum number of pairs for which a slice is used.
21// It is a variable for benchmarking.
22var maxSlice int = 8
23
24// add adds a key-value pair to the mapping.
25func (h *mapping[K, V]) add(k K, v V) {
26	if h.m == nil && len(h.s) < maxSlice {
27		h.s = append(h.s, entry[K, V]{k, v})
28	} else {
29		if h.m == nil {
30			h.m = map[K]V{}
31			for _, e := range h.s {
32				h.m[e.key] = e.value
33			}
34			h.s = nil
35		}
36		h.m[k] = v
37	}
38}
39
40// find returns the value corresponding to the given key.
41// The second return value is false if there is no value
42// with that key.
43func (h *mapping[K, V]) find(k K) (v V, found bool) {
44	if h == nil {
45		return v, false
46	}
47	if h.m != nil {
48		v, found = h.m[k]
49		return v, found
50	}
51	for _, e := range h.s {
52		if e.key == k {
53			return e.value, true
54		}
55	}
56	return v, false
57}
58
59// eachPair calls f for each pair in the mapping.
60// If f returns false, pairs returns immediately.
61func (h *mapping[K, V]) eachPair(f func(k K, v V) bool) {
62	if h == nil {
63		return
64	}
65	if h.m != nil {
66		for k, v := range h.m {
67			if !f(k, v) {
68				return
69			}
70		}
71	} else {
72		for _, e := range h.s {
73			if !f(e.key, e.value) {
74				return
75			}
76		}
77	}
78}
79