ronantakizawa/codereview-bench huggingface dataset:
Repository: gofiber/fiber
File: middleware/envvar/envvar.go (Go)

Code before:
package envvar

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/utils"
	"os"
	"strings"
)

// Config defines the config for middleware.
type Config struct {
	// Path specifies the path of handler that exposes environment variables
	Path string
	// ExportVars specifies the environment variables that should export
	ExportVars map[string]string
	// ExcludeVars specifies the environment variables that should not export
	ExcludeVars map[string]string
}

type EnvVar struct {
	Vars map[string]string `json:"vars"`
}

func (envVar *EnvVar) set(key, val string) {
	envVar.Vars[key] = val
}

func New(config ...Config) fiber.Handler {
	var cfg Config
	if len(config) > 0 {
		cfg = config[0]
	} else {
		cfg = Config{Path: "/envvars"}
	}

	return func(c *fiber.Ctx) error {
		path := c.Path()
		if len(path) < len(cfg.Path) || !strings.HasPrefix(path, cfg.Path) {

Review comment (suggestion):
specifying the path is not necessary in my opinion
you can say outside where the middleware should run

```go
app.Use("/expose/envvars", envvar.New(envvar.Config{
    ...
}))
```



Code after:
package envvar

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/utils"
	"os"
	"strings"
)

// Config defines the config for middleware.
type Config struct {
	// ExportVars specifies the environment variables that should export
	ExportVars map[string]string
	// ExcludeVars specifies the environment variables that should not export
	ExcludeVars map[string]string
}

type EnvVar struct {
	Vars map[string]string `json:"vars"`
}

func (envVar *EnvVar) set(key, val string) {
	envVar.Vars[key] = val
}

var defaultConfig = Config{}

func New(config ...Config) fiber.Handler {
	var cfg = defaultConfig
	if len(config) > 0 {
		cfg = config[0]
	}

	return func(c *fiber.Ctx) error {
		if c.Method() != fiber.MethodGet {
			return fiber.ErrMethodNotAllowed
		}
Repository: gofiber/fiber
File: helpers.go (Go)

Code before:
type testConn struct {
	r bytes.Buffer
	w bytes.Buffer
}

func (c *testConn) Read(b []byte) (int, error)  { return c.r.Read(b) }
func (c *testConn) Write(b []byte) (int, error) { return c.w.Write(b) }
func (c *testConn) Close() error                { return nil }

func (c *testConn) LocalAddr() net.Addr                { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} }
func (c *testConn) RemoteAddr() net.Addr               { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} }
func (c *testConn) SetDeadline(_ time.Time) error      { return nil }
func (c *testConn) SetReadDeadline(_ time.Time) error  { return nil }
func (c *testConn) SetWriteDeadline(_ time.Time) error { return nil }

var getStringImmutable = func(b []byte) string {
	return string(b)
}

var getBytesImmutable = func(s string) (b []byte) {
	return []byte(s)
}

// HTTP methods and their unique INTs
func methodInt(s string) int {
	for i, v := range intMethod {
		if s == v {
			return i
		}
	}

	return -1
}

// HTTP methods slice
var intMethod = []string{
	MethodGet,
	MethodHead,
	MethodPost,
	MethodPut,
	MethodDelete,
	MethodConnect,
	MethodOptions,
	MethodTrace,
	MethodPatch,
}

// HTTP methods were copied from net/http.
const (
	MethodGet     = "GET"     // RFC 7231, 4.3.1
	MethodHead    = "HEAD"    // RFC 7231, 4.3.2

Review comment (performance):
did you check the performance, we had added the switch at that time because the access is faster there than with the map
can you make a comparison here

we should keep the functions which are used for the main path of the application as fast as possible

Code after:

type testConn struct {
	r bytes.Buffer
	w bytes.Buffer
}

func (c *testConn) Read(b []byte) (int, error)  { return c.r.Read(b) }
func (c *testConn) Write(b []byte) (int, error) { return c.w.Write(b) }
func (c *testConn) Close() error                { return nil }

func (c *testConn) LocalAddr() net.Addr                { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} }
func (c *testConn) RemoteAddr() net.Addr               { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} }
func (c *testConn) SetDeadline(_ time.Time) error      { return nil }
func (c *testConn) SetReadDeadline(_ time.Time) error  { return nil }
func (c *testConn) SetWriteDeadline(_ time.Time) error { return nil }

var getStringImmutable = func(b []byte) string {
	return string(b)
}

var getBytesImmutable = func(s string) (b []byte) {
	return []byte(s)
}

// HTTP methods and their unique INTs
func (app *App) methodInt(s string) int {
	// For better performance
	if !app.customMethod {
		switch s {
		case MethodGet:
			return 0
		case MethodHead:
			return 1
		case MethodPost:
			return 2
		case MethodPut:
			return 3
		case MethodDelete:
			return 4
		case MethodConnect:
			return 5
		case MethodOptions:
			return 6
		case MethodTrace:
			return 7
		case MethodPatch:
			return 8
		default:
			return -1
		}
	}
Repository: gofiber/fiber
File: internal/storage/memory/memory_test.go (Go)

Code before:
package memory

import (
	"testing"
	"time"

	"github.com/gofiber/fiber/v2/utils"
)

var testStore = New()

func Test_Memory_Set(t *testing.T) {
	var (
		key = "john"
		val = []byte("doe")
	)

	err := testStore.Set(key, val, 0)
	utils.AssertEqual(t, nil, err)
}

func Test_Memory_Set_Override(t *testing.T) {
	var (
		key = "john"
		val = []byte("doe")
	)

	err := testStore.Set(key, val, 0)
	utils.AssertEqual(t, nil, err)

	err = testStore.Set(key, val, 0)
	utils.AssertEqual(t, nil, err)
}

func Test_Memory_Get(t *testing.T) {
	var (
		key = "john"

Review comment (suggestion):
We should make these names different. e.g `Test_Storage_Memory`

Code after:
package memory

import (
	"testing"
	"time"

	"github.com/gofiber/fiber/v2/utils"
)

var testStore = New()

func Test_Storage_Memory_Set(t *testing.T) {
	var (
		key = "john"
		val = []byte("doe")
	)

	err := testStore.Set(key, val, 0)
	utils.AssertEqual(t, nil, err)
}

func Test_Storage_Memory_Set_Override(t *testing.T) {
	var (
		key = "john"
		val = []byte("doe")
	)

	err := testStore.Set(key, val, 0)
	utils.AssertEqual(t, nil, err)

	err = testStore.Set(key, val, 0)
	utils.AssertEqual(t, nil, err)
}

func Test_Storage_Memory_Get(t *testing.T) {
	var (
		key = "john"
Repository: gofiber/fiber
File: middleware/earlydata/config.go (Go)

Code before:
package earlydata

import (
	"github.com/gofiber/fiber/v3"
)

// Config defines the config for middleware.
type Config struct {
	// IsEarlyData returns whether the request is an early-data request.
	//
	// Optional. Default: a function which checks if the "Early-Data" request header equals "1".
	IsEarlyData func(c fiber.Ctx) bool

	// AllowEarlyData returns whether the early-data request should be allowed or rejected.
	//
	// Optional. Default: a function which rejects the request on unsafe and allows the request on safe HTTP request methods.
	AllowEarlyData func(c fiber.Ctx) bool

	// Error is returned in case an early-data request is rejected.
	//
	// Optional. Default: fiber.ErrTooEarly.
	Error error
}

// ConfigDefault is the default config
var ConfigDefault = Config{
	IsEarlyData: func(c fiber.Ctx) bool {
		return c.Get("Early-Data") == "1"
	},

	AllowEarlyData: func(c fiber.Ctx) bool {
		return fiber.IsMethodSafe(c.Method())
	},

	Error: fiber.ErrTooEarly,
}

// Helper function to set default values

Review comment (suggestion):
can you add a NEXT config property

```go
	// Next defines a function to skip this middleware when returned true.
	//
	// Optional. Default: a function which skips the middleware on safe HTTP request method.
	Next func(c *fiber.Ctx) bool
```

Code after:
package earlydata

import (
	"github.com/gofiber/fiber/v3"
)

const (
	DefaultHeaderName      = "Early-Data"
	DefaultHeaderTrueValue = "1"
)

// Config defines the config for middleware.
type Config struct {
	// Next defines a function to skip this middleware when returned true.
	//
	// Optional. Default: nil
	Next func(c fiber.Ctx) bool

	// IsEarlyData returns whether the request is an early-data request.
	//
	// Optional. Default: a function which checks if the "Early-Data" request header equals "1".
	IsEarlyData func(c fiber.Ctx) bool

	// AllowEarlyData returns whether the early-data request should be allowed or rejected.
	//
	// Optional. Default: a function which rejects the request on unsafe and allows the request on safe HTTP request methods.
	AllowEarlyData func(c fiber.Ctx) bool

	// Error is returned in case an early-data request is rejected.
	//
	// Optional. Default: fiber.ErrTooEarly.
	Error error
}

// ConfigDefault is the default config
var ConfigDefault = Config{
	IsEarlyData: func(c fiber.Ctx) bool {
		return c.Get(DefaultHeaderName) == DefaultHeaderTrueValue
Repository: gofiber/fiber
File: ctx.go (Go)

Code before:
//	QueryInt("id") == 0
func (c *Ctx) QueryInt(key string, defaultValue ...int) int {
	// Use Atoi to convert the param to an int or return zero and an error
	value, err := strconv.Atoi(c.app.getString(c.fasthttp.QueryArgs().Peek(key)))
	if err != nil {
		if len(defaultValue) > 0 {
			return defaultValue[0]
		}
		return 0
	}

	return value
}

// QueryParser binds the query string to a struct.
func (c *Ctx) QueryParser(out interface{}) error {
	data := make(map[string][]string)
	var err error

	c.fasthttp.QueryArgs().VisitAll(func(key, val []byte) {
		if err != nil {
			return
		}

		k := c.app.getString(key)
		v := c.app.getString(val)

		if strings.Contains(k, "[") {
			k, err = parseParamSquareBrackets(k)
		}

		if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) {
			values := strings.Split(v, ",")
			for i := 0; i < len(values); i++ {
				data[k] = append(data[k], values[i])
			}
		} else {
			data[k] = append(data[k], v)
		}
	})

	if err != nil {
		return err
	}

	return c.parseToStruct(queryTag, out, data)
}

func parseParamSquareBrackets(k string) (string, error) {
	bb := bytebufferpool.Get()
	defer bytebufferpool.Put(bb)

Review comment (suggestion):
There seems to be no need to use `c.app.getString` here because `strconv.ParseFloat` is already being used

Code after:
//	QueryInt("id") == 0
func (c *Ctx) QueryInt(key string, defaultValue ...int) int {
	// Use Atoi to convert the param to an int or return zero and an error
	value, err := strconv.Atoi(c.app.getString(c.fasthttp.QueryArgs().Peek(key)))
	if err != nil {
		if len(defaultValue) > 0 {
			return defaultValue[0]
		}
		return 0
	}

	return value
}

// QueryFloat returns float64 value of key string parameter in the url.
// Default to empty or invalid key is 0.
//
//	GET /?name=alex&amount=32.23&id=
//	QueryFloat("amount") = 32.23
//	QueryFloat("amount", 3) = 32.23
//	QueryFloat("name", 1) = 1
//	QueryFloat("name") = 0
//	QueryFloat("id", 3) = 3
func (c *Ctx) QueryFloat(key string, defaultValue ...float64) float64 {
	// use strconv.ParseFloat to convert the param to a float or return zero and an error.
	value, err := strconv.ParseFloat(c.app.getString(c.fasthttp.QueryArgs().Peek(key)), 64)
	if err != nil {
		if len(defaultValue) > 0 {
			return defaultValue[0]
		}
		return 0
	}

	return value
}

// QueryParser binds the query string to a struct.
func (c *Ctx) QueryParser(out interface{}) error {
	data := make(map[string][]string)
	var err error

	c.fasthttp.QueryArgs().VisitAll(func(key, val []byte) {
		if err != nil {
			return
		}

		k := c.app.getString(key)
		v := c.app.getString(val)

		if strings.Contains(k, "[") {
			k, err = parseParamSquareBrackets(k)
Repository: gofiber/fiber
File: helpers.go (Go)

Code before:
		c.fasthttp.ResetBody()
		return
	}
	// 1 != 2
	c.setCanonical(normalizedHeaderETag, etag)
}

func getGroupPath(prefix, path string) string {
	if len(path) == 0 {
		return prefix
	}

	if path[0] != '/' {
		path = "/" + path
	}

	return utils.TrimRight(prefix, '/') + path
}

// return valid offer for header negotiation
func getOffer(header string, offers ...string) string {
	if len(offers) == 0 {
		return ""
	} else if header == "" {
		return offers[0]
	}

	spec, commaPos := "", 0
	for len(header) > 0 && commaPos != -1 {
		commaPos = strings.IndexByte(header, ',')
		if commaPos != -1 {
			spec = utils.Trim(header[:commaPos], ' ')
		} else {
			spec = header
		}
		if factorSign := strings.IndexByte(spec, ';'); factorSign != -1 {
			spec = spec[:factorSign]
		}

		for _, offer := range offers {
			// has star prefix
			if len(spec) >= 1 && spec[len(spec)-1] == '*' {
				return offer
			} else if strings.HasPrefix(spec, offer) {
				return offer
			}
		}
		if commaPos != -1 {
			header = header[commaPos+1:]
		}
	}

Review comment (suggestion):
I believe that can we change that about one line. What do you think?

```suggestion
	if (len(spec) >= 1 && spec[len(spec)-1] == '*') || strings.HasPrefix(spec, offer) {
		return true
```

Code after:
		c.fasthttp.ResetBody()
		return
	}
	// 1 != 2
	c.setCanonical(normalizedHeaderETag, etag)
}

func getGroupPath(prefix, path string) string {
	if len(path) == 0 {
		return prefix
	}

	if path[0] != '/' {
		path = "/" + path
	}

	return utils.TrimRight(prefix, '/') + path
}

// acceptsOffer This function determines if an offer matches a given specification.
// It checks if the specification ends with a '*' or if the offer has the prefix of the specification.
// Returns true if the offer matches the specification, false otherwise.
func acceptsOffer(spec, offer string) bool {
	if len(spec) >= 1 && spec[len(spec)-1] == '*' {
		return true
	} else if strings.HasPrefix(spec, offer) {
		return true
	}
	return false
}

// acceptsOfferType This function determines if an offer type matches a given specification.
// It checks if the specification is equal to */* (i.e., all types are accepted).
// It gets the MIME type of the offer (either from the offer itself or by its file extension).
// It checks if the offer MIME type matches the specification MIME type or if the specification is of the form <MIME_type>/* and the offer MIME type has the same MIME type.
// Returns true if the offer type matches the specification, false otherwise.
func acceptsOfferType(spec, offerType string) bool {
	// Accept: */*
	if spec == "*/*" {
		return true
	}

	var mimetype string
	if strings.IndexByte(offerType, '/') != -1 {
		mimetype = offerType // MIME type
	} else {
		mimetype = utils.GetMIME(offerType) // extension
	}

	if spec == mimetype {
		// Accept: <MIME_type>/<MIME_subtype>
Repository: gofiber/fiber
File: middleware/cors/cors.go (Go)

Code before:
				break
			}
			if o == origin {
				allowOrigin = o
				break
			}
			if matchSubdomain(origin, o) {
				allowOrigin = origin
				break
			}
		}

		// Run AllowOriginsFunc if the logic for
		// handling the value in 'AllowOrigins' does
		// not result in allowOrigin being set.
		if allowOrigin == "" && cfg.AllowOriginsFunc != nil {
			if cfg.AllowOriginsFunc(origin) {
				allowOrigin = origin
			}
		}

		// Simple request
		if c.Method() != fiber.MethodOptions {
			c.Vary(fiber.HeaderOrigin)
			c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin)

			if cfg.AllowCredentials {
				c.Set(fiber.HeaderAccessControlAllowCredentials, "true")
			}
			if exposeHeaders != "" {
				c.Set(fiber.HeaderAccessControlExposeHeaders, exposeHeaders)
			}
			return c.Next()
		}

		// Preflight request
		c.Vary(fiber.HeaderOrigin)
		c.Vary(fiber.HeaderAccessControlRequestMethod)
		c.Vary(fiber.HeaderAccessControlRequestHeaders)
		c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin)
		c.Set(fiber.HeaderAccessControlAllowMethods, allowMethods)

		// Set Allow-Credentials if set to true
		if cfg.AllowCredentials {
			c.Set(fiber.HeaderAccessControlAllowCredentials, "true")
		}

		// Set Allow-Headers if not empty
		if allowHeaders != "" {
			c.Set(fiber.HeaderAccessControlAllowHeaders, allowHeaders)
		} else {

Review comment (suggestion):
```suggestion
		if allowOrigin == "" && cfg.AllowOriginsFunc != nil && cfg.AllowOriginsFunc(origin) {
			allowOrigin = origin
		}
```

Code after:
		allowOrigin := ""

		// Check allowed origins
		for _, o := range allowOrigins {
			if o == "*" {
				allowOrigin = "*"
				break
			}
			if o == origin {
				allowOrigin = o
				break
			}
			if matchSubdomain(origin, o) {
				allowOrigin = origin
				break
			}
		}

		// Run AllowOriginsFunc if the logic for
		// handling the value in 'AllowOrigins' does
		// not result in allowOrigin being set.
		if allowOrigin == "" && cfg.AllowOriginsFunc != nil {
			if cfg.AllowOriginsFunc(origin) {
				allowOrigin = origin
			}
		}

		// Simple request
		if c.Method() != fiber.MethodOptions {
			c.Vary(fiber.HeaderOrigin)
			c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin)

			if cfg.AllowCredentials {
				c.Set(fiber.HeaderAccessControlAllowCredentials, "true")
			}
			if exposeHeaders != "" {
				c.Set(fiber.HeaderAccessControlExposeHeaders, exposeHeaders)
			}
			return c.Next()
		}

		// Preflight request
		c.Vary(fiber.HeaderOrigin)
		c.Vary(fiber.HeaderAccessControlRequestMethod)
		c.Vary(fiber.HeaderAccessControlRequestHeaders)
		c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin)
		c.Set(fiber.HeaderAccessControlAllowMethods, allowMethods)

		// Set Allow-Credentials if set to true
		if cfg.AllowCredentials {
			c.Set(fiber.HeaderAccessControlAllowCredentials, "true")
Repository: gofiber/fiber
File: app.go (Go)

Code before:
// Default Config values
const (
	DefaultBodyLimit            = 4 * 1024 * 1024
	DefaultConcurrency          = 256 * 1024
	DefaultReadBufferSize       = 4096
	DefaultWriteBufferSize      = 4096
	DefaultCompressedFileSuffix = ".fiber.gz"
)

// HTTP methods enabled by default
var DefaultMethods = []string{
	MethodGet,
	MethodHead,
	MethodPost,
	MethodPut,
	MethodDelete,
	MethodConnect,
	MethodOptions,
	MethodTrace,
	MethodPatch,
}

// DefaultErrorHandler that process return errors from handlers
func DefaultErrorHandler(c *Ctx, err error) error {
	var netError net.Error
	if errors.As(err, &netError) {
		// 502 - Bad Gateway
		err = ErrBadGateway
	}

	code := StatusInternalServerError
	var e *Error
	if errors.As(err, &e) {
		code = e.Code
	}
	c.Set(HeaderContentType, MIMETextPlainCharsetUTF8)
	return c.Status(code).SendString(err.Error())
}

// New creates a new Fiber named instance.
//
//	app := fiber.New()
//
// You can pass optional configuration options by passing a Config struct:
//
//	app := fiber.New(fiber.Config{
//	    Prefork: true,
//	    ServerHeader: "Fiber",
//	})
func New(config ...Config) *App {
	// Create a new app

Review comment (suggestion):
```suggestion
	var netErr net.Error
	if errors.As(err, &netErr) {
```

Code after:
// Default Config values
const (
	DefaultBodyLimit            = 4 * 1024 * 1024
	DefaultConcurrency          = 256 * 1024
	DefaultReadBufferSize       = 4096
	DefaultWriteBufferSize      = 4096
	DefaultCompressedFileSuffix = ".fiber.gz"
)

// HTTP methods enabled by default
var DefaultMethods = []string{
	MethodGet,
	MethodHead,
	MethodPost,
	MethodPut,
	MethodDelete,
	MethodConnect,
	MethodOptions,
	MethodTrace,
	MethodPatch,
}

// DefaultErrorHandler that process return errors from handlers
func DefaultErrorHandler(c *Ctx, err error) error {
	code := StatusInternalServerError
	var e *Error
	if errors.As(err, &e) {
		code = e.Code
	}
	c.Set(HeaderContentType, MIMETextPlainCharsetUTF8)
	return c.Status(code).SendString(err.Error())
}

// New creates a new Fiber named instance.
//
//	app := fiber.New()
//
// You can pass optional configuration options by passing a Config struct:
//
//	app := fiber.New(fiber.Config{
//	    Prefork: true,
//	    ServerHeader: "Fiber",
//	})
func New(config ...Config) *App {
	// Create a new app
	app := &App{
		// Create Ctx pool
		pool: sync.Pool{
			New: func() interface{} {
				return new(Ctx)
			},
Repository: gofiber/fiber
File: helpers.go (Go)

Code before:
		// Add to accepted types
		acceptedTypes = append(acceptedTypes, acceptedType{spec, quality, specificity, order})

		// Next
		if commaPos != -1 {
			header = header[commaPos+1:]
		} else {
			break
		}
	}

	// Sort accepted types by quality and specificity, preserving order of equal elements
	if len(acceptedTypes) > 1 {
		for i := 1; i < len(acceptedTypes); i++ {
			swap := false
			lo, hi := 0, i-1
			for lo <= hi {
				mid := (lo + hi) / 2
				if acceptedTypes[i].quality < acceptedTypes[mid].quality ||
					(acceptedTypes[i].quality == acceptedTypes[mid].quality && acceptedTypes[i].specificity < acceptedTypes[mid].specificity) ||
					(acceptedTypes[i].quality == acceptedTypes[mid].quality && acceptedTypes[i].specificity == acceptedTypes[mid].specificity && acceptedTypes[i].order > acceptedTypes[mid].order) {
					lo = mid + 1
				} else {
					hi = mid - 1
				}
			}
			for j := i; j > lo; j-- {
				acceptedTypes[j-1], acceptedTypes[j] = acceptedTypes[j], acceptedTypes[j-1]
				swap = true
			}
			if !swap {
				break
			}
		}
	}

	// Find the first offer that matches the accepted types
	for _, acceptedType := range acceptedTypes {
		for _, offer := range offers {
			if len(offer) == 0 {
				continue
			}
			if isAccepted(acceptedType.spec, offer) {
				return offer
			}
		}
	}

	return ""
}


Review comment (performance):
Maybe we can optimize this logic. What do you think?
```suggestion
			if len(offer) != 0 && isAccepted(acceptedType.spec, offer) {
```

Code after:
			specificity = 4
		}

		// Add to accepted types
		acceptedTypes = append(acceptedTypes, acceptedType{spec, quality, specificity, order})

		// Next
		if commaPos != -1 {
			header = header[commaPos+1:]
		} else {
			break
		}
	}

	if len(acceptedTypes) > 1 {
		// Sort accepted types by quality and specificity, preserving order of equal elements
		sortAcceptedTypes(&acceptedTypes)
	}

	// Find the first offer that matches the accepted types
	for _, acceptedType := range acceptedTypes {
		for _, offer := range offers {
			if len(offer) == 0 {
				continue
			}
			if isAccepted(acceptedType.spec, offer) {
				return offer
			}
		}
	}

	return ""
}

// sortAcceptedTypes sorts accepted types by quality and specificity, preserving order of equal elements
//
// Parameters are not supported, they are ignored when sorting by specificity.
//
// See: https://www.rfc-editor.org/rfc/rfc9110#name-content-negotiation-fields
func sortAcceptedTypes(at *[]acceptedType) {
	if at == nil || len(*at) < 2 {
		return
	}
	acceptedTypes := *at

	for i := 1; i < len(acceptedTypes); i++ {
		lo, hi := 0, i-1
		for lo <= hi {
			mid := (lo + hi) / 2
			if acceptedTypes[i].quality < acceptedTypes[mid].quality ||
				(acceptedTypes[i].quality == acceptedTypes[mid].quality && acceptedTypes[i].specificity < acceptedTypes[mid].specificity) ||