// 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[ comparable,  any] struct {
	s []entry[, ] // for few pairs
	m map[]       // for many pairs
}

type entry[ comparable,  any] struct {
	key   
	value 
}

// 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 ( *mapping[, ]) ( ,  ) {
	if .m == nil && len(.s) < maxSlice {
		.s = append(.s, entry[, ]{, })
	} else {
		if .m == nil {
			.m = map[]{}
			for ,  := range .s {
				.m[.key] = .value
			}
			.s = nil
		}
		.m[] = 
	}
}

// find returns the value corresponding to the given key.
// The second return value is false if there is no value
// with that key.
func ( *mapping[, ]) ( ) ( ,  bool) {
	if  == nil {
		return , false
	}
	if .m != nil {
		,  = .m[]
		return , 
	}
	for ,  := range .s {
		if .key ==  {
			return .value, true
		}
	}
	return , false
}

// eachPair calls f for each pair in the mapping.
// If f returns false, pairs returns immediately.
func ( *mapping[, ]) ( func( ,  ) bool) {
	if  == nil {
		return
	}
	if .m != nil {
		for ,  := range .m {
			if !(, ) {
				return
			}
		}
	} else {
		for ,  := range .s {
			if !(.key, .value) {
				return
			}
		}
	}
}