Repository: gin-gonic/gin
Pull request #3975 (2024-05-21 13:34:03)

chore(tree): replace the self-defined 'min' to official one 
 replace the self-defined 'min' to official one and solve the func 'max' name conflict in tree.go.



codecov[bot]: ## [Codecov](https://app.codecov.io/gh/gin-gonic/gin/pull/3975?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 99.05%. Comparing base [(`3dc1cd6`)](https://app.codecov.io/gh/gin-gonic/gin/commit/3dc1cd6572b4e3a0cd170a15debe546c2c72294f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) to head [(`d1a415b`)](https://app.codecov.io/gh/gin-gonic/gin/pull/3975?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic).
> Report is 59 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #3975      +/-   ##
==========================================
- Coverage   99.21%   99.05%   -0.17%     
==========================================
  Files          42       44       +2     
  Lines        3182     2747     -435     
==========================================
- Hits         3157     2721     -436     
+ Misses         17       15       -2     
- Partials        8       11       +3     
```

| [Flag](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | Coverage Δ | |
|---|---|---|
| [](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `?` | |
| [-tags go_json](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `99.04% <100.00%> (?)` | |
| [-tags nomsgpack](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `99.03% <100.00%> (?)` | |
| [go-1.18](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `?` | |
| [go-1.19](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `?` | |
| [go-1.20](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `?` | |
| [go-1.21](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `99.03% <100.00%> (-0.18%)` | :arrow_down: |
| [go-1.22](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `99.05% <100.00%> (?)` | |
| [macos-latest](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `?` | |
| [ubuntu-latest](https://app.codecov.io/gh/gin-gonic/gin/pull/3975/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic) | `99.05% <100.00%> (-0.17%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/gin-gonic/gin/pull/3975?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gin-gonic).


Patch:
diff --git a/binding/form_mapping.go b/binding/form_mapping.go
index 108606f..33389b2 100644
--- a/binding/form_mapping.go
+++ b/binding/form_mapping.go
@@ -193,14 +193,25 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][
 		if !ok {
 			vs = []string{opt.defaultValue}
 		}
+
+		if ok, err = trySetCustom(vs[0], value); ok {
+			return ok, err
+		}
+
 		return true, setSlice(vs, value, field)
 	case reflect.Array:
 		if !ok {
 			vs = []string{opt.defaultValue}
 		}
+
+		if ok, err = trySetCustom(vs[0], value); ok {
+			return ok, err
+		}
+
 		if len(vs) != value.Len() {
 			return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String())
 		}
+
 		return true, setArray(vs, value, field)
 	default:
 		var val string
diff --git a/tree.go b/tree.go
index 878023d..ce0f065 100644
--- a/tree.go
+++ b/tree.go
@@ -65,17 +65,10 @@ func (trees methodTrees) get(method string) *node {
 	return nil
 }
 
-func min(a, b int) int {
-	if a <= b {
-		return a
-	}
-	return b
-}
-
 func longestCommonPrefix(a, b string) int {
 	i := 0
-	max := min(len(a), len(b))
-	for i < max && a[i] == b[i] {
+	max_ := min(len(a), len(b))
+	for i < max_ && a[i] == b[i] {
 		i++
 	}
 	return i
@@ -205,7 +198,7 @@ walk:
 			}
 
 			// Check if a child with the next path byte exists
-			for i, max := 0, len(n.indices); i < max; i++ {
+			for i, max_ := 0, len(n.indices); i < max_; i++ {
 				if c == n.indices[i] {
 					parentFullPathIndex += len(n.path)
 					i = n.incrementChildPrio(i)
@@ -770,7 +763,7 @@ walk: // Outer loop for walking the tree
 				// Runes are up to 4 byte long,
 				// -4 would definitely be another rune.
 				var off int
-				for max := min(npLen, 3); off < max; off++ {
+				for max_ := min(npLen, 3); off < max_; off++ {
 					if i := npLen - off; utf8.RuneStart(oldPath[i]) {
 						// read rune from cached path
 						rv, _ = utf8.DecodeRuneInString(oldPath[i:])


Test patch:
diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go
index ed01a08..afd51f9 100644
--- a/binding/form_mapping_test.go
+++ b/binding/form_mapping_test.go
@@ -5,6 +5,7 @@
 package binding
 
 import (
+	"encoding/hex"
 	"fmt"
 	"mime/multipart"
 	"reflect"
@@ -422,3 +423,89 @@ func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) {
 	assert.EqualValues(t, "/foo", s.FileData.Path)
 	assert.EqualValues(t, "happiness", s.FileData.Name)
 }
+
+type customPath []string
+
+func (p *customPath) UnmarshalParam(param string) error {
+	elems := strings.Split(param, "/")
+	n := len(elems)
+	if n < 2 {
+		return fmt.Errorf("invalid format")
+	}
+
+	*p = elems
+	return nil
+}
+
+func TestMappingCustomSliceUri(t *testing.T) {
+	var s struct {
+		FileData customPath `uri:"path"`
+	}
+	err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "uri")
+	assert.NoError(t, err)
+
+	assert.EqualValues(t, "bar", s.FileData[0])
+	assert.EqualValues(t, "foo", s.FileData[1])
+}
+
+func TestMappingCustomSliceForm(t *testing.T) {
+	var s struct {
+		FileData customPath `form:"path"`
+	}
+	err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "form")
+	assert.NoError(t, err)
+
+	assert.EqualValues(t, "bar", s.FileData[0])
+	assert.EqualValues(t, "foo", s.FileData[1])
+}
+
+type objectID [12]byte
+
+func (o *objectID) UnmarshalParam(param string) error {
+	oid, err := convertTo(param)
+	if err != nil {
+		return err
+	}
+
+	*o = oid
+	return nil
+}
+
+func convertTo(s string) (objectID, error) {
+	var nilObjectID objectID
+	if len(s) != 24 {
+		return nilObjectID, fmt.Errorf("invalid format")
+	}
+
+	var oid [12]byte
+	_, err := hex.Decode(oid[:], []byte(s))
+	if err != nil {
+		return nilObjectID, err
+	}
+
+	return oid, nil
+}
+
+func TestMappingCustomArrayUri(t *testing.T) {
+	var s struct {
+		FileData objectID `uri:"id"`
+	}
+	val := `664a062ac74a8ad104e0e80f`
+	err := mappingByPtr(&s, formSource{"id": {val}}, "uri")
+	assert.NoError(t, err)
+
+	expected, _ := convertTo(val)
+	assert.EqualValues(t, expected, s.FileData)
+}
+
+func TestMappingCustomArrayForm(t *testing.T) {
+	var s struct {
+		FileData objectID `form:"id"`
+	}
+	val := `664a062ac74a8ad104e0e80f`
+	err := mappingByPtr(&s, formSource{"id": {val}}, "form")
+	assert.NoError(t, err)
+
+	expected, _ := convertTo(val)
+	assert.EqualValues(t, expected, s.FileData)
+}