From fb87dc3942e4179aa1eb8007f8f3d384fd4b9fca Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Mon, 4 Mar 2019 13:49:52 +1100 Subject: [PATCH] Automatically bind to int32 and int64 --- codegen/config/config.go | 6 +- codegen/testserver/generated.go | 308 ++++++++++++++++++++++++++++++ codegen/testserver/gqlgen.yml | 2 + codegen/testserver/models.go | 9 + codegen/testserver/resolver.go | 3 + codegen/testserver/schema.graphql | 10 + codegen/testserver/stub.go | 4 + graphql/int.go | 50 +++++ graphql/int_test.go | 71 +++++++ 9 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 graphql/int_test.go diff --git a/codegen/config/config.go b/codegen/config/config.go index 1638239d003..cf54e8fb6a6 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -339,12 +339,16 @@ func (c *Config) InjectBuiltins(s *ast.Schema) { "__EnumValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.EnumValue"}}, "__InputValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.InputValue"}}, "__Schema": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Schema"}}, - "Int": {Model: StringList{"github.com/99designs/gqlgen/graphql.Int"}}, "Float": {Model: StringList{"github.com/99designs/gqlgen/graphql.Float"}}, "String": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, "Boolean": {Model: StringList{"github.com/99designs/gqlgen/graphql.Boolean"}}, "Time": {Model: StringList{"github.com/99designs/gqlgen/graphql.Time"}}, "Map": {Model: StringList{"github.com/99designs/gqlgen/graphql.Map"}}, + "Int": {Model: StringList{ + "github.com/99designs/gqlgen/graphql.Int", + "github.com/99designs/gqlgen/graphql.Int32", + "github.com/99designs/gqlgen/graphql.Int64", + }}, "ID": { Model: StringList{ "github.com/99designs/gqlgen/graphql.ID", diff --git a/codegen/testserver/generated.go b/codegen/testserver/generated.go index 5be09523697..6932d23fd05 100644 --- a/codegen/testserver/generated.go +++ b/codegen/testserver/generated.go @@ -53,6 +53,14 @@ type DirectiveRoot struct { } type ComplexityRoot struct { + Autobind struct { + Int func(childComplexity int) int + Int32 func(childComplexity int) int + Int64 func(childComplexity int) int + IdStr func(childComplexity int) int + IdInt func(childComplexity int) int + } + Circle struct { Radius func(childComplexity int) int Area func(childComplexity int) int @@ -121,6 +129,7 @@ type ComplexityRoot struct { DirectiveInput func(childComplexity int, arg InputDirectives) int InputSlice func(childComplexity int, arg []string) int ShapeUnion func(childComplexity int) int + Autobind func(childComplexity int) int Panics func(childComplexity int) int ValidType func(childComplexity int) int } @@ -181,6 +190,7 @@ type QueryResolver interface { DirectiveInput(ctx context.Context, arg InputDirectives) (*string, error) InputSlice(ctx context.Context, arg []string) (bool, error) ShapeUnion(ctx context.Context) (ShapeUnion, error) + Autobind(ctx context.Context) (*Autobind, error) Panics(ctx context.Context) (*Panics, error) ValidType(ctx context.Context) (*ValidType, error) } @@ -207,6 +217,41 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { + case "Autobind.Int": + if e.complexity.Autobind.Int == nil { + break + } + + return e.complexity.Autobind.Int(childComplexity), true + + case "Autobind.Int32": + if e.complexity.Autobind.Int32 == nil { + break + } + + return e.complexity.Autobind.Int32(childComplexity), true + + case "Autobind.Int64": + if e.complexity.Autobind.Int64 == nil { + break + } + + return e.complexity.Autobind.Int64(childComplexity), true + + case "Autobind.IdStr": + if e.complexity.Autobind.IdStr == nil { + break + } + + return e.complexity.Autobind.IdStr(childComplexity), true + + case "Autobind.IdInt": + if e.complexity.Autobind.IdInt == nil { + break + } + + return e.complexity.Autobind.IdInt(childComplexity), true + case "Circle.Radius": if e.complexity.Circle.Radius == nil { break @@ -526,6 +571,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.ShapeUnion(childComplexity), true + case "Query.Autobind": + if e.complexity.Query.Autobind == nil { + break + } + + return e.complexity.Query.Autobind(childComplexity), true + case "Query.Panics": if e.complexity.Query.Panics == nil { break @@ -797,6 +849,7 @@ scalar MarshalPanic directiveInput(arg: InputDirectives!): String inputSlice(arg: [String!]!): Boolean! shapeUnion: ShapeUnion! + autobind: Autobind } type Subscription { @@ -811,6 +864,15 @@ type User { updated: Time } +type Autobind { + int: Int! + int32: Int! + int64: Int! + + idStr: ID! + idInt: ID! +} + type Error { id: ID! errorOnNonRequiredField: String @@ -1508,6 +1570,136 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg // region **************************** field.gotpl ***************************** +func (ec *executionContext) _Autobind_int(ctx context.Context, field graphql.CollectedField, obj *Autobind) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Autobind", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Int, nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Autobind_int32(ctx context.Context, field graphql.CollectedField, obj *Autobind) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Autobind", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Int32, nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int32) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNInt2int32(ctx, field.Selections, res) +} + +func (ec *executionContext) _Autobind_int64(ctx context.Context, field graphql.CollectedField, obj *Autobind) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Autobind", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Int64, nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int64) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNInt2int64(ctx, field.Selections, res) +} + +func (ec *executionContext) _Autobind_idStr(ctx context.Context, field graphql.CollectedField, obj *Autobind) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Autobind", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IdStr, nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _Autobind_idInt(ctx context.Context, field graphql.CollectedField, obj *Autobind) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Autobind", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IdInt, nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNID2int(ctx, field.Selections, res) +} + func (ec *executionContext) _Circle_radius(ctx context.Context, field graphql.CollectedField, obj *Circle) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -2494,6 +2686,29 @@ func (ec *executionContext) _Query_shapeUnion(ctx context.Context, field graphql return ec.marshalNShapeUnion2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐShapeUnion(ctx, field.Selections, res) } +func (ec *executionContext) _Query_autobind(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Query", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Autobind(rctx) + }) + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*Autobind) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalOAutobind2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐAutobind(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_panics(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -4083,6 +4298,53 @@ func (ec *executionContext) _ShapeUnion(ctx context.Context, sel ast.SelectionSe // region **************************** object.gotpl **************************** +var autobindImplementors = []string{"Autobind"} + +func (ec *executionContext) _Autobind(ctx context.Context, sel ast.SelectionSet, obj *Autobind) graphql.Marshaler { + fields := graphql.CollectFields(ctx, sel, autobindImplementors) + + out := graphql.NewFieldSet(fields) + invalid := false + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Autobind") + case "int": + out.Values[i] = ec._Autobind_int(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + case "int32": + out.Values[i] = ec._Autobind_int32(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + case "int64": + out.Values[i] = ec._Autobind_int64(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + case "idStr": + out.Values[i] = ec._Autobind_idStr(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + case "idInt": + out.Values[i] = ec._Autobind_idInt(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalid { + return graphql.Null + } + return out +} + var circleImplementors = []string{"Circle", "Shape", "ShapeUnion"} func (ec *executionContext) _Circle(ctx context.Context, sel ast.SelectionSet, obj *Circle) graphql.Marshaler { @@ -4659,6 +4921,17 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "autobind": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_autobind(ctx, field) + return res + }) case "panics": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -5089,6 +5362,14 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return graphql.MarshalBoolean(v) } +func (ec *executionContext) unmarshalNID2int(ctx context.Context, v interface{}) (int, error) { + return graphql.UnmarshalIntID(v) +} + +func (ec *executionContext) marshalNID2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + return graphql.MarshalIntID(v) +} + func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { return graphql.UnmarshalID(v) } @@ -5121,6 +5402,22 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return graphql.MarshalInt(v) } +func (ec *executionContext) unmarshalNInt2int32(ctx context.Context, v interface{}) (int32, error) { + return graphql.UnmarshalInt32(v) +} + +func (ec *executionContext) marshalNInt2int32(ctx context.Context, sel ast.SelectionSet, v int32) graphql.Marshaler { + return graphql.MarshalInt32(v) +} + +func (ec *executionContext) unmarshalNInt2int64(ctx context.Context, v interface{}) (int64, error) { + return graphql.UnmarshalInt64(v) +} + +func (ec *executionContext) marshalNInt2int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { + return graphql.MarshalInt64(v) +} + func (ec *executionContext) unmarshalNMarshalPanic2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐMarshalPanic(ctx context.Context, v interface{}) (MarshalPanic, error) { var res MarshalPanic return res, res.UnmarshalGQL(v) @@ -5501,6 +5798,17 @@ func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel a return graphql.MarshalString(v) } +func (ec *executionContext) marshalOAutobind2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐAutobind(ctx context.Context, sel ast.SelectionSet, v Autobind) graphql.Marshaler { + return ec._Autobind(ctx, sel, &v) +} + +func (ec *executionContext) marshalOAutobind2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐAutobind(ctx context.Context, sel ast.SelectionSet, v *Autobind) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Autobind(ctx, sel, v) +} + func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { return graphql.UnmarshalBoolean(v) } diff --git a/codegen/testserver/gqlgen.yml b/codegen/testserver/gqlgen.yml index 26a1572c51e..dff1dd02a47 100644 --- a/codegen/testserver/gqlgen.yml +++ b/codegen/testserver/gqlgen.yml @@ -54,3 +54,5 @@ models: model: "github.com/99designs/gqlgen/codegen/testserver.Panics" MarshalPanic: model: "github.com/99designs/gqlgen/codegen/testserver.MarshalPanic" + Autobind: + model: "github.com/99designs/gqlgen/codegen/testserver.Autobind" diff --git a/codegen/testserver/models.go b/codegen/testserver/models.go index bedcb790114..690b4d31d82 100644 --- a/codegen/testserver/models.go +++ b/codegen/testserver/models.go @@ -62,3 +62,12 @@ type Panics struct { func (p *Panics) FieldFuncMarshal(ctx context.Context, u []MarshalPanic) []MarshalPanic { return []MarshalPanic{MarshalPanic("aa"), MarshalPanic("bb")} } + +type Autobind struct { + Int int + Int32 int32 + Int64 int64 + + IdStr string + IdInt int +} diff --git a/codegen/testserver/resolver.go b/codegen/testserver/resolver.go index 565a4c6a4eb..91c494ab1a8 100644 --- a/codegen/testserver/resolver.go +++ b/codegen/testserver/resolver.go @@ -107,6 +107,9 @@ func (r *queryResolver) InputSlice(ctx context.Context, arg []string) (bool, err func (r *queryResolver) ShapeUnion(ctx context.Context) (ShapeUnion, error) { panic("not implemented") } +func (r *queryResolver) Autobind(ctx context.Context) (*Autobind, error) { + panic("not implemented") +} func (r *queryResolver) Panics(ctx context.Context) (*Panics, error) { panic("not implemented") } diff --git a/codegen/testserver/schema.graphql b/codegen/testserver/schema.graphql index c400847ad97..d6a7fb51274 100644 --- a/codegen/testserver/schema.graphql +++ b/codegen/testserver/schema.graphql @@ -17,6 +17,7 @@ type Query { directiveInput(arg: InputDirectives!): String inputSlice(arg: [String!]!): Boolean! shapeUnion: ShapeUnion! + autobind: Autobind } type Subscription { @@ -31,6 +32,15 @@ type User { updated: Time } +type Autobind { + int: Int! + int32: Int! + int64: Int! + + idStr: ID! + idInt: ID! +} + type Error { id: ID! errorOnNonRequiredField: String diff --git a/codegen/testserver/stub.go b/codegen/testserver/stub.go index 1e732362073..a99c44461fc 100644 --- a/codegen/testserver/stub.go +++ b/codegen/testserver/stub.go @@ -39,6 +39,7 @@ type Stub struct { DirectiveInput func(ctx context.Context, arg InputDirectives) (*string, error) InputSlice func(ctx context.Context, arg []string) (bool, error) ShapeUnion func(ctx context.Context) (ShapeUnion, error) + Autobind func(ctx context.Context) (*Autobind, error) Panics func(ctx context.Context) (*Panics, error) ValidType func(ctx context.Context) (*ValidType, error) } @@ -147,6 +148,9 @@ func (r *stubQuery) InputSlice(ctx context.Context, arg []string) (bool, error) func (r *stubQuery) ShapeUnion(ctx context.Context) (ShapeUnion, error) { return r.QueryResolver.ShapeUnion(ctx) } +func (r *stubQuery) Autobind(ctx context.Context) (*Autobind, error) { + return r.QueryResolver.Autobind(ctx) +} func (r *stubQuery) Panics(ctx context.Context) (*Panics, error) { return r.QueryResolver.Panics(ctx) } diff --git a/graphql/int.go b/graphql/int.go index ff87574cab7..57d0d589bae 100644 --- a/graphql/int.go +++ b/graphql/int.go @@ -27,3 +27,53 @@ func UnmarshalInt(v interface{}) (int, error) { return 0, fmt.Errorf("%T is not an int", v) } } + +func MarshalInt64(i int64) Marshaler { + return WriterFunc(func(w io.Writer) { + io.WriteString(w, strconv.FormatInt(i, 10)) + }) +} + +func UnmarshalInt64(v interface{}) (int64, error) { + switch v := v.(type) { + case string: + return strconv.ParseInt(v, 10, 64) + case int: + return int64(v), nil + case int64: + return v, nil + case json.Number: + return strconv.ParseInt(string(v), 10, 64) + default: + return 0, fmt.Errorf("%T is not an int", v) + } +} + +func MarshalInt32(i int32) Marshaler { + return WriterFunc(func(w io.Writer) { + io.WriteString(w, strconv.FormatInt(int64(i), 10)) + }) +} + +func UnmarshalInt32(v interface{}) (int32, error) { + switch v := v.(type) { + case string: + iv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + return 0, err + } + return int32(iv), nil + case int: + return int32(v), nil + case int64: + return int32(v), nil + case json.Number: + iv, err := strconv.ParseInt(string(v), 10, 32) + if err != nil { + return 0, err + } + return int32(iv), nil + default: + return 0, fmt.Errorf("%T is not an int", v) + } +} diff --git a/graphql/int_test.go b/graphql/int_test.go new file mode 100644 index 00000000000..ada9ca5d8bc --- /dev/null +++ b/graphql/int_test.go @@ -0,0 +1,71 @@ +package graphql + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestInt(t *testing.T) { + t.Run("marshal", func(t *testing.T) { + assert.Equal(t, "123", m2s(MarshalInt(123))) + }) + + t.Run("unmarshal", func(t *testing.T) { + assert.Equal(t, 123, mustUnmarshalInt(123)) + assert.Equal(t, 123, mustUnmarshalInt(int64(123))) + assert.Equal(t, 123, mustUnmarshalInt(json.Number("123"))) + assert.Equal(t, 123, mustUnmarshalInt("123")) + }) +} + +func mustUnmarshalInt(v interface{}) int { + res, err := UnmarshalInt(v) + if err != nil { + panic(err) + } + return res +} + +func TestInt32(t *testing.T) { + t.Run("marshal", func(t *testing.T) { + assert.Equal(t, "123", m2s(MarshalInt32(123))) + }) + + t.Run("unmarshal", func(t *testing.T) { + assert.Equal(t, int32(123), mustUnmarshalInt32(123)) + assert.Equal(t, int32(123), mustUnmarshalInt32(int64(123))) + assert.Equal(t, int32(123), mustUnmarshalInt32(json.Number("123"))) + assert.Equal(t, int32(123), mustUnmarshalInt32("123")) + }) +} + +func mustUnmarshalInt32(v interface{}) int32 { + res, err := UnmarshalInt32(v) + if err != nil { + panic(err) + } + return res +} + +func TestInt64(t *testing.T) { + t.Run("marshal", func(t *testing.T) { + assert.Equal(t, "123", m2s(MarshalInt32(123))) + }) + + t.Run("unmarshal", func(t *testing.T) { + assert.Equal(t, int64(123), mustUnmarshalInt64(123)) + assert.Equal(t, int64(123), mustUnmarshalInt64(int64(123))) + assert.Equal(t, int64(123), mustUnmarshalInt64(json.Number("123"))) + assert.Equal(t, int64(123), mustUnmarshalInt64("123")) + }) +} + +func mustUnmarshalInt64(v interface{}) int64 { + res, err := UnmarshalInt64(v) + if err != nil { + panic(err) + } + return res +}