Repository: goadesign/goa
Pull request #3317 (2023-07-19 20:30:06)

Enable custom primitive types to decode
I'm trying to use the [github.com/c2h5oh/hide](http://github.com/c2h5oh/hide) library and have IDs that marshal/unmarshal automatically.
For reference, this definition exists:
```
package hide

type Uint32 uint32
```

I've created this type in my design file:
```
AccountID = Type("account_id", func() {
	Attribute("account_id", UInt32, func() {
		Meta("struct:field:type", "hide.Uint32", "github.com/c2h5oh/hide")
		Example(10234)
	})
	Required("account_id")
})
```

And this works pretty well except for the generation of the Decode functions.  It correctly creates the type of the var as hide.Uint32 but, after parsing, it tries to use the base type as the conversion.  The problematic line is this:
```
accountID = uint32(v)
```

That doesn't compile.  I would expect that line to be this instead:
```
accountID = hide.Uint32(v)
```


Patch:
diff --git a/Makefile b/Makefile
index 83f1bac2..365f9756 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
 #
 MAJOR=3
 MINOR=12
-BUILD=1
+BUILD=2
 
 GOOS=$(shell go env GOOS)
 GO_FILES=$(shell find . -type f -name '*.go')
diff --git a/README.md b/README.md
index 0a7c0539..c5d45fa3 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 ## Overview
 
-[![GoDev](https://img.shields.io/badge/go-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/goa.design/goa/v3@v3.12.1/dsl?tab=doc)
+[![GoDev](https://img.shields.io/badge/go-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/goa.design/goa/v3@v3.12.2/dsl?tab=doc)
 [![Go Report Card](https://goreportcard.com/badge/goadesign/goa)](https://goreportcard.com/report/goadesign/goa)
 [![Slack](https://img.shields.io/badge/Goa-gray.svg?longCache=true&logo=slack&colorB=red)](https://gophers.slack.com/messages/goa)
 [![Signup](https://img.shields.io/badge/Signup-gray.svg?longCache=true&logo=slack&colorB=red)](https://invite.slack.golangbridge.org/)
@@ -67,7 +67,7 @@ invoking the client code.
 go install goa.design/goa/v3/cmd/goa@v3
 ```
 
-Current Release: `v3.12.1`
+Current Release: `v3.12.2`
 
 ## Teaser
 
@@ -333,7 +333,7 @@ In particular the page
 explains how to leverage the generated code to implement an HTTP or gRPC
 service.
 
-The [![DSL GoDoc](https://img.shields.io/badge/godoc-DSL-blue)](https://pkg.go.dev/goa.design/goa/v3@v3.12.1/dsl?tab=doc)
+The [![DSL GoDoc](https://img.shields.io/badge/godoc-DSL-blue)](https://pkg.go.dev/goa.design/goa/v3@v3.12.2/dsl?tab=doc)
 contains a fully documented reference of all the DSL functions.
 
 ### Instrumentation and System Example
diff --git a/http/codegen/server.go b/http/codegen/server.go
index c25ff7f5..e26c5e9a 100644
--- a/http/codegen/server.go
+++ b/http/codegen/server.go
@@ -1010,10 +1010,10 @@ const typeConversionT = `{{- define "slice_conversion" }}
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "integer"))
 		}
 		{{- if .Pointer }}
-		pv := int(v)
+		pv := {{ if .TypeRef }}{{slice .TypeRef 1 (len .TypeRef)}}{{ else }}int{{ end }}(v)
 		{{ .VarName }} = &pv
 		{{- else }}
-		{{ .VarName }} = int(v)
+		{{ .VarName }} = {{ if .TypeRef }}{{ .TypeRef }}{{ else }}int{{ end }}(v)
 		{{- end }}
 	{{- else if eq .Type.Name "int32" }}
 		v, err2 := strconv.ParseInt({{ .VarName }}Raw, 10, 32)
@@ -1021,27 +1021,27 @@ const typeConversionT = `{{- define "slice_conversion" }}
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "integer"))
 		}
 		{{- if .Pointer }}
-		pv := int32(v)
+		pv := {{ if .TypeRef }}{{ slice .TypeRef 1 (len .TypeRef) }}{{ else }}int32{{ end }}(v)
 		{{ .VarName }} = &pv
 		{{- else }}
-		{{ .VarName }} = int32(v)
+		{{ .VarName }} = {{ if .TypeRef }}{{ .TypeRef }}{{ else }}int32{{ end }}(v)
 		{{- end }}
 	{{- else if eq .Type.Name "int64" }}
 		v, err2 := strconv.ParseInt({{ .VarName }}Raw, 10, 64)
 		if err2 != nil {
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "integer"))
 		}
-		{{ .VarName }} = {{ if .Pointer}}&{{ end }}v
+		{{ if and (ne .TypeRef nil) (and (ne .TypeRef "int64") (ne .TypeRef "*int64")) }}{{ .VarName }} = ({{.TypeRef}})({{ if .Pointer }}&{{ end }}v){{ else }}{{ .VarName }} = {{ if .Pointer }}&{{ end }}v{{ end }}
 	{{- else if eq .Type.Name "uint" }}
 		v, err2 := strconv.ParseUint({{ .VarName }}Raw, 10, strconv.IntSize)
 		if err2 != nil {
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "unsigned integer"))
 		}
 		{{- if .Pointer }}
-		pv := uint(v)
+		pv := {{ if .TypeRef }}{{ slice .TypeRef 1 (len .TypeRef) }}{{ else }}uint{{ end }}(v)
 		{{ .VarName }} = &pv
 		{{- else }}
-		{{ .VarName }} = uint(v)
+		{{ .VarName }} = {{ if .TypeRef }}{{ .TypeRef }}{{ else }}uint{{ end }}(v)
 		{{- end }}
 	{{- else if eq .Type.Name "uint32" }}
 		v, err2 := strconv.ParseUint({{ .VarName }}Raw, 10, 32)
@@ -1049,40 +1049,40 @@ const typeConversionT = `{{- define "slice_conversion" }}
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "unsigned integer"))
 		}
 		{{- if .Pointer }}
-		pv := uint32(v)
+		pv := {{ if .TypeRef }}{{ slice .TypeRef 1 (len .TypeRef) }}{{ else }}uint32{{ end }}(v)
 		{{ .VarName }} = &pv
 		{{- else }}
-		{{ .VarName }} = uint32(v)
+		{{ .VarName }} = {{ if .TypeRef }}{{ .TypeRef }}{{ else }}uint32{{ end }}(v)
 		{{- end }}
 	{{- else if eq .Type.Name "uint64" }}
 		v, err2 := strconv.ParseUint({{ .VarName }}Raw, 10, 64)
 		if err2 != nil {
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "unsigned integer"))
 		}
-		{{ .VarName }} = {{ if .Pointer }}&{{ end }}v
+		{{ if and (ne .TypeRef nil) (and (ne .TypeRef "uint64") (ne .TypeRef "*uint64")) }}{{ .VarName }} = ({{.TypeRef}})({{ if .Pointer }}&{{ end }}v){{ else }}{{ .VarName }} = {{ if .Pointer }}&{{ end }}v{{ end }}
 	{{- else if eq .Type.Name "float32" }}
 		v, err2 := strconv.ParseFloat({{ .VarName }}Raw, 32)
 		if err2 != nil {
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "float"))
 		}
 		{{- if .Pointer }}
-		pv := float32(v)
+		pv := {{ if .TypeRef }}{{ slice .TypeRef 1 (len .TypeRef) }}{{ else }}float32{{ end }}(v)
 		{{ .VarName }} = &pv
 		{{- else }}
-		{{ .VarName }} = float32(v)
+		{{ .VarName }} = {{ if .TypeRef }}{{ .TypeRef }}{{ else }}float32{{ end }}(v)
 		{{- end }}
 	{{- else if eq .Type.Name "float64" }}
 		v, err2 := strconv.ParseFloat({{ .VarName }}Raw, 64)
 		if err2 != nil {
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "float"))
 		}
-		{{ .VarName }} = {{ if .Pointer }}&{{ end }}v
+		{{ if and (ne .TypeRef nil) (and (ne .TypeRef "float64") (ne .TypeRef "*float64")) }}{{ .VarName }} = ({{.TypeRef}})({{ if .Pointer }}&{{ end }}v){{ else }}{{ .VarName }} = {{ if .Pointer }}&{{ end }}v{{ end }}
 	{{- else if eq .Type.Name "boolean" }}
 		v, err2 := strconv.ParseBool({{ .VarName }}Raw)
 		if err2 != nil {
 			err = goa.MergeErrors(err, goa.InvalidFieldTypeError({{ printf "%q" .Name }}, {{ .VarName}}Raw, "boolean"))
 		}
-		{{ .VarName }} = {{ if .Pointer }}&{{ end }}v
+		{{ if and (ne .TypeRef nil) (and (ne .TypeRef "bool") (ne .TypeRef "*bool")) }}{{ .VarName }} = ({{.TypeRef}})({{ if .Pointer }}&{{ end }}v){{ else }}{{ .VarName }} = {{ if .Pointer }}&{{ end }}v{{ end }}
 	{{- else }}
 		// unsupported type {{ .Type.Name }} for var {{ .VarName }}
 	{{- end }}
diff --git a/pkg/version.go b/pkg/version.go
index c6db1ac7..133663d4 100644
--- a/pkg/version.go
+++ b/pkg/version.go
@@ -12,7 +12,7 @@ const (
 	// Minor version number
 	Minor = 12
 	// Build number
-	Build = 1
+	Build = 2
 	// Suffix - set to empty string in release tag commits.
 	Suffix = ""
 )


Test patch:
diff --git a/http/codegen/server_decode_test.go b/http/codegen/server_decode_test.go
index ef9b0e43..9b0a1bc3 100644
--- a/http/codegen/server_decode_test.go
+++ b/http/codegen/server_decode_test.go
@@ -15,6 +15,14 @@ func TestDecode(t *testing.T) {
 		DSL  func()
 		Code string
 	}{
+		{"decode-path-custom-float32", testdata.PayloadPathCustomFloat32DSL, testdata.PayloadPathCustomFloat32DecodeCode},
+		{"decode-path-custom-float64", testdata.PayloadPathCustomFloat64DSL, testdata.PayloadPathCustomFloat64DecodeCode},
+		{"decode-path-custom-int", testdata.PayloadPathCustomIntDSL, testdata.PayloadPathCustomIntDecodeCode},
+		{"decode-path-custom-int32", testdata.PayloadPathCustomInt32DSL, testdata.PayloadPathCustomInt32DecodeCode},
+		{"decode-path-custom-int64", testdata.PayloadPathCustomInt64DSL, testdata.PayloadPathCustomInt64DecodeCode},
+		{"decode-path-custom-uint", testdata.PayloadPathCustomUIntDSL, testdata.PayloadPathCustomUIntDecodeCode},
+		{"decode-path-custom-uint32", testdata.PayloadPathCustomUInt32DSL, testdata.PayloadPathCustomUInt32DecodeCode},
+		{"decode-path-custom-uint64", testdata.PayloadPathCustomUInt64DSL, testdata.PayloadPathCustomUInt64DecodeCode},
 		{"decode-query-bool", testdata.PayloadQueryBoolDSL, testdata.PayloadQueryBoolDecodeCode},
 		{"decode-query-bool-validate", testdata.PayloadQueryBoolValidateDSL, testdata.PayloadQueryBoolValidateDecodeCode},
 		{"decode-query-int", testdata.PayloadQueryIntDSL, testdata.PayloadQueryIntDecodeCode},
diff --git a/http/codegen/testdata/payload_decode_functions.go b/http/codegen/testdata/payload_decode_functions.go
index e52f8065..72ba9425 100644
--- a/http/codegen/testdata/payload_decode_functions.go
+++ b/http/codegen/testdata/payload_decode_functions.go
@@ -5497,3 +5497,223 @@ func DecodeMethodARequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp
 	}
 }
 `
+
+var PayloadPathCustomFloat32DecodeCode = `// DecodeMethodPathCustomFloat32Request returns a decoder for requests sent to
+// the ServicePathCustomFloat32 MethodPathCustomFloat32 endpoint.
+func DecodeMethodPathCustomFloat32Request(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Float32
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseFloat(pRaw, 32)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "float"))
+			}
+			p = hide.Float32(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomFloat32Payload(p)
+
+		return payload, nil
+	}
+}
+`
+
+var PayloadPathCustomFloat64DecodeCode = `// DecodeMethodPathCustomFloat64Request returns a decoder for requests sent to
+// the ServicePathCustomFloat64 MethodPathCustomFloat64 endpoint.
+func DecodeMethodPathCustomFloat64Request(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Float64
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseFloat(pRaw, 64)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "float"))
+			}
+			p = (hide.Float64)(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomFloat64Payload(p)
+
+		return payload, nil
+	}
+}
+`
+
+var PayloadPathCustomIntDecodeCode = `// DecodeMethodPathCustomIntRequest returns a decoder for requests sent to the
+// ServicePathCustomInt MethodPathCustomInt endpoint.
+func DecodeMethodPathCustomIntRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Int
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseInt(pRaw, 10, strconv.IntSize)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "integer"))
+			}
+			p = hide.Int(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomIntPayload(p)
+
+		return payload, nil
+	}
+}
+`
+
+var PayloadPathCustomInt32DecodeCode = `// DecodeMethodPathCustomInt32Request returns a decoder for requests sent to
+// the ServicePathCustomInt32 MethodPathCustomInt32 endpoint.
+func DecodeMethodPathCustomInt32Request(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Int32
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseInt(pRaw, 10, 32)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "integer"))
+			}
+			p = hide.Int32(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomInt32Payload(p)
+
+		return payload, nil
+	}
+}
+`
+var PayloadPathCustomInt64DecodeCode = `// DecodeMethodPathCustomInt64Request returns a decoder for requests sent to
+// the ServicePathCustomInt64 MethodPathCustomInt64 endpoint.
+func DecodeMethodPathCustomInt64Request(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Int64
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseInt(pRaw, 10, 64)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "integer"))
+			}
+			p = (hide.Int64)(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomInt64Payload(p)
+
+		return payload, nil
+	}
+}
+`
+var PayloadPathCustomUIntDecodeCode = `// DecodeMethodPathCustomUIntRequest returns a decoder for requests sent to the
+// ServicePathCustomUInt MethodPathCustomUInt endpoint.
+func DecodeMethodPathCustomUIntRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Uint
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseUint(pRaw, 10, strconv.IntSize)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "unsigned integer"))
+			}
+			p = hide.Uint(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomUIntPayload(p)
+
+		return payload, nil
+	}
+}
+`
+var PayloadPathCustomUInt32DecodeCode = `// DecodeMethodPathCustomUInt32Request returns a decoder for requests sent to
+// the ServicePathCustomUInt32 MethodPathCustomUInt32 endpoint.
+func DecodeMethodPathCustomUInt32Request(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Uint32
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseUint(pRaw, 10, 32)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "unsigned integer"))
+			}
+			p = hide.Uint32(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomUInt32Payload(p)
+
+		return payload, nil
+	}
+}
+`
+var PayloadPathCustomUInt64DecodeCode = `// DecodeMethodPathCustomUInt64Request returns a decoder for requests sent to
+// the ServicePathCustomUInt64 MethodPathCustomUInt64 endpoint.
+func DecodeMethodPathCustomUInt64Request(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) {
+	return func(r *http.Request) (any, error) {
+		var (
+			p   hide.Uint64
+			err error
+
+			params = mux.Vars(r)
+		)
+		{
+			pRaw := params["p"]
+			v, err2 := strconv.ParseUint(pRaw, 10, 64)
+			if err2 != nil {
+				err = goa.MergeErrors(err, goa.InvalidFieldTypeError("p", pRaw, "unsigned integer"))
+			}
+			p = (hide.Uint64)(v)
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewMethodPathCustomUInt64Payload(p)
+
+		return payload, nil
+	}
+}
+`
diff --git a/http/codegen/testdata/payload_dsls.go b/http/codegen/testdata/payload_dsls.go
index 678f2572..72622b52 100644
--- a/http/codegen/testdata/payload_dsls.go
+++ b/http/codegen/testdata/payload_dsls.go
@@ -3380,3 +3380,123 @@ var QueryArrayNestedAliasValidateDSL = func() {
 		})
 	})
 }
+
+var PayloadPathCustomFloat32DSL = func() {
+	Service("ServicePathCustomFloat32", func() {
+		Method("MethodPathCustomFloat32", func() {
+			Payload(func() {
+				Attribute("p", Float32, func() {
+					Meta("struct:field:type", "hide.Float32", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomFloat64DSL = func() {
+	Service("ServicePathCustomFloat64", func() {
+		Method("MethodPathCustomFloat64", func() {
+			Payload(func() {
+				Attribute("p", Float64, func() {
+					Meta("struct:field:type", "hide.Float64", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomIntDSL = func() {
+	Service("ServicePathCustomInt", func() {
+		Method("MethodPathCustomInt", func() {
+			Payload(func() {
+				Attribute("p", Int, func() {
+					Meta("struct:field:type", "hide.Int", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomInt32DSL = func() {
+	Service("ServicePathCustomInt32", func() {
+		Method("MethodPathCustomInt32", func() {
+			Payload(func() {
+				Attribute("p", Int32, func() {
+					Meta("struct:field:type", "hide.Int32", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomInt64DSL = func() {
+	Service("ServicePathCustomInt64", func() {
+		Method("MethodPathCustomInt64", func() {
+			Payload(func() {
+				Attribute("p", Int64, func() {
+					Meta("struct:field:type", "hide.Int64", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomUIntDSL = func() {
+	Service("ServicePathCustomUInt", func() {
+		Method("MethodPathCustomUInt", func() {
+			Payload(func() {
+				Attribute("p", UInt, func() {
+					Meta("struct:field:type", "hide.Uint", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomUInt32DSL = func() {
+	Service("ServicePathCustomUInt32", func() {
+		Method("MethodPathCustomUInt32", func() {
+			Payload(func() {
+				Attribute("p", UInt32, func() {
+					Meta("struct:field:type", "hide.Uint32", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}
+
+var PayloadPathCustomUInt64DSL = func() {
+	Service("ServicePathCustomUInt64", func() {
+		Method("MethodPathCustomUInt64", func() {
+			Payload(func() {
+				Attribute("p", UInt64, func() {
+					Meta("struct:field:type", "hide.Uint64", "github.com/c2h5oh/hide")
+				})
+			})
+			HTTP(func() {
+				GET("/{p}")
+			})
+		})
+	})
+}