ronantakizawa/codereview-bench huggingface dataset:
Repository: gin-gonic/gin
File: context.go (Go)

Code before:
			for ; i < len(accepted); i++ {
				if accepted[i] == '*' || offer[i] == '*' {
					return offer
				}
				if accepted[i] != offer[i] {
					break
				}
			}
			if i == len(accepted) {
				return offer
			}
		}
	}
	return ""
}

// SetAccepted sets Accept header data.
func (c *Context) SetAccepted(formats ...string) {
	c.Accepted = formats
}

/************************************/
/***** GOLANG.ORG/X/NET/CONTEXT *****/
/************************************/

// Deadline returns that there is no deadline (ok==false) when c.Request with no Context.
func (c *Context) Deadline() (deadline time.Time, ok bool) {
	if c.Request == nil || c.Request.Context() == nil {
		return
	}
	return c.Request.Context().Deadline()
}

// Done returns nil (chan which will wait forever) when c.Request with no Context.
func (c *Context) Done() <-chan struct{} {
	if c.Request == nil || c.Request.Context() == nil {
		return nil
	}
	return c.Request.Context().Done()
}

// Err returns nil when c.Request with no Context.
func (c *Context) Err() error {
	if c.Request == nil || c.Request.Context() == nil {
		return nil
	}
	return c.Request.Context().Err()
}

// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with

Review comment (suggestion):
I'd say this reads better:
```suggestion
// Deadline returns that there is no deadline (ok==false) when c.Request has no Context.
```
Same in the other two comments.

Code after:
			for ; i < len(accepted); i++ {
				if accepted[i] == '*' || offer[i] == '*' {
					return offer
				}
				if accepted[i] != offer[i] {
					break
				}
			}
			if i == len(accepted) {
				return offer
			}
		}
	}
	return ""
}

// SetAccepted sets Accept header data.
func (c *Context) SetAccepted(formats ...string) {
	c.Accepted = formats
}

/************************************/
/***** GOLANG.ORG/X/NET/CONTEXT *****/
/************************************/

// Deadline returns that there is no deadline (ok==false) when c.Request has no Context.
func (c *Context) Deadline() (deadline time.Time, ok bool) {
	if c.Request == nil || c.Request.Context() == nil {
		return
	}
	return c.Request.Context().Deadline()
}

// Done returns nil (chan which will wait forever) when c.Request has no Context.
func (c *Context) Done() <-chan struct{} {
	if c.Request == nil || c.Request.Context() == nil {
		return nil
	}
	return c.Request.Context().Done()
}

// Err returns nil when c.Request has no Context.
func (c *Context) Err() error {
	if c.Request == nil || c.Request.Context() == nil {
		return nil
	}
	return c.Request.Context().Err()
}

// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
Repository: gin-gonic/gin
File: binding/default_validator.go (Go)

Code before:
// Copyright 2017 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package binding

import (
	"fmt"
	"reflect"
	"strings"
	"sync"

	"github.com/go-playground/validator/v10"
)

type defaultValidator struct {
	once     sync.Once
	validate *validator.Validate
}

type SliceValidateError []error

// Error concatenates all error elements in SliceValidateError into a single string separated by \n.
func (err SliceValidateError) Error() string {
	n := len(err)
	switch n {
	case 0:
		return ""
	default:
		var b strings.Builder
		if err[0] != nil {
			fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error())
		}
		if n > 1 {
			for i := 1; i < n; i++ {
				if err[i] != nil {
					b.WriteString("\n")
					fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error())
				}
			}
		}
		return b.String()
	}
}

var _ StructValidator = &defaultValidator{}

Review comment (suggestion):
How about renaming it to a more grammatically correct form at the same time:
```suggestion
type SliceValidationError []error
```

Code after:
// Copyright 2017 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package binding

import (
	"fmt"
	"reflect"
	"strings"
	"sync"

	"github.com/go-playground/validator/v10"
)

type defaultValidator struct {
	once     sync.Once
	validate *validator.Validate
}

type SliceValidationError []error

// Error concatenates all error elements in SliceValidationError into a single string separated by \n.
func (err SliceValidationError) Error() string {
	n := len(err)
	switch n {
	case 0:
		return ""
	default:
		var b strings.Builder
		if err[0] != nil {
			fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error())
		}
		if n > 1 {
			for i := 1; i < n; i++ {
				if err[i] != nil {
					b.WriteString("\n")
					fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error())
				}
			}
		}
		return b.String()
	}
}

var _ StructValidator = &defaultValidator{}
Repository: gin-gonic/gin
File: render/json.go (Go)

Code before:
func (r IndentedJSON) Render(w http.ResponseWriter) error {
	r.WriteContentType(w)
	jsonBytes, err := json.MarshalIndent(r.Data, "", "    ")
	if err != nil {
		return err
	}
	_, err = w.Write(jsonBytes)
	return err
}

// WriteContentType (IndentedJSON) writes JSON ContentType.
func (r IndentedJSON) WriteContentType(w http.ResponseWriter) {
	writeContentType(w, jsonContentType)
}

// Render (SecureJSON) marshals the given interface object and writes it with custom ContentType.
func (r SecureJSON) Render(w http.ResponseWriter) error {
	r.WriteContentType(w)
	jsonBytes, err := json.Marshal(r.Data)
	if err != nil {
		return err
	}
	// if the jsonBytes is array values
	if bytes.HasPrefix(jsonBytes, bytesconv.StringToBytes("[")) && bytes.HasSuffix(jsonBytes,
		bytesconv.StringToBytes("]")) {
		_, err = w.Write(bytesconv.StringToBytes(r.Prefix))
		if err != nil {
			return err
		}
	}
	_, err = w.Write(jsonBytes)
	return err
}

// WriteContentType (SecureJSON) writes JSON ContentType.
func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
	writeContentType(w, jsonContentType)
}

// Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType.
func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
	r.WriteContentType(w)
	ret, err := json.Marshal(r.Data)
	if err != nil {
		return err
	}

	if r.Callback == "" {
		_, err = w.Write(ret)
		return err
	}

Review comment (suggestion):
I'd even write:
```suggestion
		if _, err := w.Write(bytesconv.StringToBytes(r.Prefix)); err != nil {
```
here and elsewhere. This way you don't reassign to the outer `err` variable.

Code after:
func (r IndentedJSON) Render(w http.ResponseWriter) error {
	r.WriteContentType(w)
	jsonBytes, err := json.MarshalIndent(r.Data, "", "    ")
	if err != nil {
		return err
	}
	_, err = w.Write(jsonBytes)
	return err
}

// WriteContentType (IndentedJSON) writes JSON ContentType.
func (r IndentedJSON) WriteContentType(w http.ResponseWriter) {
	writeContentType(w, jsonContentType)
}

// Render (SecureJSON) marshals the given interface object and writes it with custom ContentType.
func (r SecureJSON) Render(w http.ResponseWriter) error {
	r.WriteContentType(w)
	jsonBytes, err := json.Marshal(r.Data)
	if err != nil {
		return err
	}
	// if the jsonBytes is array values
	if bytes.HasPrefix(jsonBytes, bytesconv.StringToBytes("[")) && bytes.HasSuffix(jsonBytes,
		bytesconv.StringToBytes("]")) {
		if _, err = w.Write(bytesconv.StringToBytes(r.Prefix)); err != nil {
			return err
		}
	}
	_, err = w.Write(jsonBytes)
	return err
}

// WriteContentType (SecureJSON) writes JSON ContentType.
func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
	writeContentType(w, jsonContentType)
}

// Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType.
func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
	r.WriteContentType(w)
	ret, err := json.Marshal(r.Data)
	if err != nil {
		return err
	}

	if r.Callback == "" {
		_, err = w.Write(ret)
		return err
	}
Repository: gin-gonic/gin
File: context.go (Go)

Code before:

	// Legacy "AppEngine" flag
	if c.engine.AppEngine {
		log.Println(`The AppEngine flag is going to be deprecated. Please check issues #2723 and #2739 and use 'TrustedPlatform: gin.PlatformGoogleAppEngine' instead.`)
		if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
			return addr
		}
	}

	remoteIP, trusted := c.RemoteIP()
	if remoteIP == nil {
		return ""
	}

	if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil {
		for _, headerName := range c.engine.RemoteIPHeaders {
			ip, valid := validateHeader(c.requestHeader(headerName), c.engine)
			if valid {
				return ip
			}
		}
	}
	return remoteIP.String()
}

func isTrustedProxy(ip net.IP, e *Engine) bool {
	if e.trustedCIDRs != nil {
		for _, cidr := range e.trustedCIDRs {
			if cidr.Contains(ip) {
				return true
			}
		}
	}
	return false
}

// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
// It also checks if the remoteIP is a trusted proxy or not.
// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks
// defined in Engine.TrustedProxies
func (c *Context) RemoteIP() (net.IP, bool) {
	ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr))
	if err != nil {
		return nil, false
	}
	remoteIP := net.ParseIP(ip)
	if remoteIP == nil {
		return nil, false
	}

	return remoteIP, isTrustedProxy(remoteIP, c.engine)

Review comment (suggestion):
```go
func (e *Engine) isTrustedProxy(ip net.IP) bool { }
```

Code after:
	switch c.engine.TrustedPlatform {
	case PlatformGoogleAppEngine:
		if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
			return addr
		}
	case PlatformCloudflare:
		if addr := c.requestHeader("CF-Connecting-IP"); addr != "" {
			return addr
		}
	}

	// Legacy "AppEngine" flag
	if c.engine.AppEngine {
		log.Println(`The AppEngine flag is going to be deprecated. Please check issues #2723 and #2739 and use 'TrustedPlatform: gin.PlatformGoogleAppEngine' instead.`)
		if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
			return addr
		}
	}

	remoteIP, trusted := c.RemoteIP()
	if remoteIP == nil {
		return ""
	}

	if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil {
		for _, headerName := range c.engine.RemoteIPHeaders {
			ip, valid := c.engine.validateHeader(c.requestHeader(headerName))
			if valid {
				return ip
			}
		}
	}
	return remoteIP.String()
}

func (e *Engine) isTrustedProxy(ip net.IP) bool {
	if e.trustedCIDRs != nil {
		for _, cidr := range e.trustedCIDRs {
			if cidr.Contains(ip) {
				return true
			}
		}
	}
	return false
}

// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
// It also checks if the remoteIP is a trusted proxy or not.
// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks
// defined by Engine.SetTrustedProxies()
func (c *Context) RemoteIP() (net.IP, bool) {
Repository: gin-gonic/gin
File: context.go (Go)

Code before:
			if cidr.Contains(ip) {
				return true
			}
		}
	}
	return false
}

// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
// It also checks if the remoteIP is a trusted proxy or not.
// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks
// defined in Engine.TrustedProxies
func (c *Context) RemoteIP() (net.IP, bool) {
	ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr))
	if err != nil {
		return nil, false
	}
	remoteIP := net.ParseIP(ip)
	if remoteIP == nil {
		return nil, false
	}

	return remoteIP, isTrustedProxy(remoteIP, c.engine)
}

func validateHeader(header string, e *Engine) (clientIP string, valid bool) {
	if header == "" {
		return "", false
	}
	items := strings.Split(header, ",")
	for i := len(items) - 1; i >= 0; i-- {
		ipStr := strings.TrimSpace(items[i])
		ip := net.ParseIP(ipStr)
		if ip == nil {
			return "", false
		}

		// X-Forwarded-For is appended by proxy
		// Check IPs in reverse order and stop when find untrusted proxy
		if (i == 0) || (!isTrustedProxy(ip, e)) {
			return ipStr, true
		}
	}
	return
}

// ContentType returns the Content-Type header of the request.
func (c *Context) ContentType() string {
	return filterFlags(c.requestHeader("Content-Type"))
}


Review comment (suggestion):
```go
func (e *Engine) validateHeader(header string) (clientIP string, valid bool) { }
```

Code after:
				return ip
			}
		}
	}
	return remoteIP.String()
}

func (e *Engine) isTrustedProxy(ip net.IP) bool {
	if e.trustedCIDRs != nil {
		for _, cidr := range e.trustedCIDRs {
			if cidr.Contains(ip) {
				return true
			}
		}
	}
	return false
}

// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
// It also checks if the remoteIP is a trusted proxy or not.
// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks
// defined by Engine.SetTrustedProxies()
func (c *Context) RemoteIP() (net.IP, bool) {
	ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr))
	if err != nil {
		return nil, false
	}
	remoteIP := net.ParseIP(ip)
	if remoteIP == nil {
		return nil, false
	}

	return remoteIP, c.engine.isTrustedProxy(remoteIP)
}

func (e *Engine) validateHeader(header string) (clientIP string, valid bool) {
	if header == "" {
		return "", false
	}
	items := strings.Split(header, ",")
	for i := len(items) - 1; i >= 0; i-- {
		ipStr := strings.TrimSpace(items[i])
		ip := net.ParseIP(ipStr)
		if ip == nil {
			return "", false
		}

		// X-Forwarded-For is appended by proxy
		// Check IPs in reverse order and stop when find untrusted proxy
		if (i == 0) || (!e.isTrustedProxy(ip)) {
			return ipStr, true
Repository: gin-gonic/gin
File: routes_test.go (Go)

Code before:
	for _, route := range routes {
		actualRoute := route
		router.GET(route, func(c *Context) {
			// For each defined route context should contain its full path
			assert.Equal(t, actualRoute, c.FullPath())
			c.AbortWithStatus(http.StatusOK)
		})
	}

	for _, route := range routes {
		w := performRequest(router, http.MethodGet, route)
		assert.Equal(t, http.StatusOK, w.Code)
	}

	// Test not found
	router.Use(func(c *Context) {
		// For not found routes full path is empty
		assert.Equal(t, "", c.FullPath())
	})

	w := performRequest(router, http.MethodGet, "/not-found")
	assert.Equal(t, http.StatusNotFound, w.Code)
}

// Reproduction test for the bug of issue #2843
func TestRouteTrailingSlashRoute(t *testing.T) {
	router := New()

	router.NoRoute(func(c *Context) {
		if c.Request.RequestURI == "/login" {
			c.String(200, "login")
		}
	})

	router.GET("/logout", func(c *Context) {
		c.String(200, "logout")
	})

	w := performRequest(router, http.MethodGet, "/login")
	assert.Equal(t, "login", w.Body.String())

	w = performRequest(router, http.MethodGet, "/logout")
	assert.Equal(t, "logout", w.Body.String())
}


Review comment (suggestion):
Perhaps we don't need a new function, could we integrate it into the function 'TestRouterNotFound'?
https://github.com/gin-gonic/gin/blob/4e7584175d7f2b4245249e769110fd1df0d779db/routes_test.go#L434-L470

Code after:
	routes := []string{
		"/simple",
		"/project/:name",
		"/",
		"/news/home",
		"/news",
		"/simple-two/one",
		"/simple-two/one-two",
		"/project/:name/build/*params",
		"/project/:name/bui",
		"/user/:id/status",
		"/user/:id",
		"/user/:id/profile",
	}

	for _, route := range routes {
		actualRoute := route
		router.GET(route, func(c *Context) {
			// For each defined route context should contain its full path
			assert.Equal(t, actualRoute, c.FullPath())
			c.AbortWithStatus(http.StatusOK)
		})
	}

	for _, route := range routes {
		w := performRequest(router, http.MethodGet, route)
		assert.Equal(t, http.StatusOK, w.Code)
	}

	// Test not found
	router.Use(func(c *Context) {
		// For not found routes full path is empty
		assert.Equal(t, "", c.FullPath())
	})

	w := performRequest(router, http.MethodGet, "/not-found")
	assert.Equal(t, http.StatusNotFound, w.Code)
}
Repository: gin-gonic/gin
File: gin_integration_test.go (Go)

Code before:
func isWindows() bool {
	return runtime.GOOS == "windows"
}

func TestEscapedColon(t *testing.T) {
	router := New()
	f := func(u string) {
		router.GET(u, func(c *Context) { c.String(http.StatusOK, u) })
	}
	f("/r/r\\:r")
	f("/r/r:r")
	f("/r/r/:r")
	f("/r/r/\\:r")
	f("/r/r/r\\:r")

	router.updateRouteTrees()
	ts := httptest.NewServer(router)
	defer ts.Close()

	testRequest(t, ts.URL+"/r/r123", "", "/r/r:r")
	testRequest(t, ts.URL+"/r/r:r", "", "/r/r\\:r")
	testRequest(t, ts.URL+"/r/r/r123", "", "/r/r/:r")
	testRequest(t, ts.URL+"/r/r/:r", "", "/r/r/\\:r")
	testRequest(t, ts.URL+"/r/r/r:r", "", "/r/r/r\\:r")
}


Review comment (suggestion):
Should probably add a test case for `\:r` as well, which should not result in expected behaviour.

```
f("/r/r/\:r")
```

Code after:
	testRequest(t, ts.URL+"/get/abc/123/test22", "", "/get/abc/123/:param")
	testRequest(t, ts.URL+"/get/abc/123abg/test", "", "/get/abc/123abg/:param")
	testRequest(t, ts.URL+"/get/abc/123abf/testss", "", "/get/abc/123abf/:param")
	testRequest(t, ts.URL+"/get/abc/123abfff/te", "", "/get/abc/123abfff/:param")
	// 404 not found
	testRequest(t, ts.URL+"/c/d/e", "404 Not Found")
	testRequest(t, ts.URL+"/c/d/e1", "404 Not Found")
	testRequest(t, ts.URL+"/c/d/eee", "404 Not Found")
	testRequest(t, ts.URL+"/c1/d/eee", "404 Not Found")
	testRequest(t, ts.URL+"/c1/d/e2", "404 Not Found")
	testRequest(t, ts.URL+"/cc/dd/ee/ff/gg/hh1", "404 Not Found")
	testRequest(t, ts.URL+"/a/dd", "404 Not Found")
	testRequest(t, ts.URL+"/addr/dd/aa", "404 Not Found")
	testRequest(t, ts.URL+"/something/secondthing/121", "404 Not Found")
}

func isWindows() bool {
	return runtime.GOOS == "windows"
}

func TestEscapedColon(t *testing.T) {
	router := New()
	f := func(u string) {
		router.GET(u, func(c *Context) { c.String(http.StatusOK, u) })
	}
	f("/r/r\\:r")
	f("/r/r:r")
	f("/r/r/:r")
	f("/r/r/\\:r")
	f("/r/r/r\\:r")
	assert.Panics(t, func() {
		f("\\foo:")
	})

	router.updateRouteTrees()
	ts := httptest.NewServer(router)
	defer ts.Close()

	testRequest(t, ts.URL+"/r/r123", "", "/r/r:r")
	testRequest(t, ts.URL+"/r/r:r", "", "/r/r\\:r")
	testRequest(t, ts.URL+"/r/r/r123", "", "/r/r/:r")
	testRequest(t, ts.URL+"/r/r/:r", "", "/r/r/\\:r")
	testRequest(t, ts.URL+"/r/r/r:r", "", "/r/r/r\\:r")
}
Repository: gin-gonic/gin
File: tree.go (Go)

Code before:
					"'")
			}

			n.insertChild(path, fullPath, handlers)
			return
		}

		// Otherwise add handle to current node
		if n.handlers != nil {
			panic("handlers are already registered for path '" + fullPath + "'")
		}
		n.handlers = handlers
		n.fullPath = fullPath
		return
	}
}

// Search for a wildcard segment and check the name for invalid characters.
// Returns -1 as index, if no wildcard was found.
func findWildcard(path string) (wildcard string, i int, valid bool) {
	// Find start
	escapeColon := false
	for start, c := range []byte(path) {
		if escapeColon {
			if c == ':' {
				escapeColon = false
				continue
			}
		}
		if c == '\\' {
			escapeColon = true
			continue
		}
		// A wildcard starts with ':' (param) or '*' (catch-all)
		if c != ':' && c != '*' {
			continue
		}

		// Find end and check for invalid characters
		valid = true
		for end, c := range []byte(path[start+1:]) {
			switch c {
			case '/':
				return path[start : start+1+end], start, valid
			case ':', '*':
				valid = false
			}
		}
		return path[start:], start, valid
	}
	return "", -1, false

Review comment (security):
What about a case of `\\foo:`? `escapeColon` would stay true after escape character until colon is reached. It's probably not expected behaviour. It should try to escape next character by the rules. This case is also not covered with test.

Code after:
					"'")
			}

			n.insertChild(path, fullPath, handlers)
			return
		}

		// Otherwise add handle to current node
		if n.handlers != nil {
			panic("handlers are already registered for path '" + fullPath + "'")
		}
		n.handlers = handlers
		n.fullPath = fullPath
		return
	}
}

// Search for a wildcard segment and check the name for invalid characters.
// Returns -1 as index, if no wildcard was found.
func findWildcard(path string) (wildcard string, i int, valid bool) {
	// Find start
	escapeColon := false
	for start, c := range []byte(path) {
		if escapeColon {
			escapeColon = false
			if c == ':' {
				continue
			}
			panic("invalid escape string in path '" + path + "'")
		}
		if c == '\\' {
			escapeColon = true
			continue
		}
		// A wildcard starts with ':' (param) or '*' (catch-all)
		if c != ':' && c != '*' {
			continue
		}

		// Find end and check for invalid characters
		valid = true
		for end, c := range []byte(path[start+1:]) {
			switch c {
			case '/':
				return path[start : start+1+end], start, valid
			case ':', '*':
				valid = false
			}
		}
		return path[start:], start, valid
	}
Repository: gin-gonic/gin
File: binding/form_mapping.go (Go)

Code before:
		return true, v.UnmarshalParam(val)
	}
	return false, nil
}

func trySplit(vs []string, field reflect.StructField) (newVs []string, err error) {
	cfTag := field.Tag.Get("collection_format")
	if cfTag == "" || cfTag == "multi" {
		return vs, nil
	}

	var sep string
	switch cfTag {
	case "csv":
		sep = ","
	case "ssv":
		sep = " "
	case "tsv":
		sep = "\t"
	case "pipes":
		sep = "|"
	default:
		return vs, fmt.Errorf("%s is not supported in the collection_format. (csv, ssv, pipes)", cfTag)
	}

	newVs = make([]string, 0)
	for _, v := range vs {
		newVs = append(newVs, strings.Split(v, sep)...)
	}

	return newVs, nil
}

func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) {
	vs, ok := form[tagValue]
	if !ok && !opt.isDefaultExists {
		return false, nil
	}

	switch value.Kind() {
	case reflect.Slice:
		if !ok {
			vs = []string{opt.defaultValue}
		}

		if ok, err = trySetCustom(vs[0], value); ok {
			return ok, err
		}

		if vs, err = trySplit(vs, field); err != nil {
			return false, err

Review comment (performance):
```go
	totalLength := 0
	for _, v := range vs {
		totalLength += strings.Count(v, sep) + 1
	}
	newVs := make([]string, 0, totalLength)
	for _, v := range vs {
		newVs = append(newVs, strings.Split(v, sep)...)
	}
```

Benchmark

```sh
goos: darwin
goarch: arm64
BenchmarkSplitStringsOriginal-10         1258774               924.5 ns/op
BenchmarkSplitStringsOptimized-10        1716301               697.3 ns/op
PASS
```


Code after:
		return true, v.UnmarshalParam(val)
	}
	return false, nil
}

func trySplit(vs []string, field reflect.StructField) (newVs []string, err error) {
	cfTag := field.Tag.Get("collection_format")
	if cfTag == "" || cfTag == "multi" {
		return vs, nil
	}

	var sep string
	switch cfTag {
	case "csv":
		sep = ","
	case "ssv":
		sep = " "
	case "tsv":
		sep = "\t"
	case "pipes":
		sep = "|"
	default:
		return vs, fmt.Errorf("%s is not supported in the collection_format. (csv, ssv, pipes)", cfTag)
	}

	totalLength := 0
	for _, v := range vs {
		totalLength += strings.Count(v, sep) + 1
	}
	newVs = make([]string, 0, totalLength)
	for _, v := range vs {
		newVs = append(newVs, strings.Split(v, sep)...)
	}

	return newVs, nil
}

func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) {
	vs, ok := form[tagValue]
	if !ok && !opt.isDefaultExists {
		return false, nil
	}

	switch value.Kind() {
	case reflect.Slice:
		if !ok {
			vs = []string{opt.defaultValue}
		}

		if ok, err = trySetCustom(vs[0], value); ok {
			return ok, err