Skip to content

Commit c9a9e21

Browse files
authored
Omit setting grpc fields to zero defaults (goadesign#3119)
1 parent 951acc0 commit c9a9e21

8 files changed

+159
-10
lines changed

grpc/codegen/client_types_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func TestClientTypeFiles(t *testing.T) {
2323
{"with-errors", testdata.UnaryRPCWithErrorsDSL, testdata.WithErrorsClientTypeCode},
2424
{"bidirectional-streaming-same-type", testdata.BidirectionalStreamingRPCSameTypeDSL, testdata.BidirectionalStreamingRPCSameTypeClientTypeCode},
2525
{"struct-meta-type", testdata.StructMetaTypeDSL, testdata.StructMetaTypeTypeCode},
26+
{"default-fields", testdata.DefaultFieldsDSL, testdata.DefaultFieldsTypeCode},
2627
}
2728
for _, c := range cases {
2829
t.Run(c.Name, func(t *testing.T) {

grpc/codegen/proto_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func TestProtoFiles(t *testing.T) {
2626
{"method-with-acronym", testdata.MethodWithAcronymDSL, testdata.MethodWithAcronymProtoCode},
2727
{"custom-package-name", testdata.ServiceWithPackageDSL, testdata.ServiceWithPackageCode},
2828
{"struct-meta-type", testdata.StructMetaTypeDSL, testdata.StructMetaTypePackageCode},
29+
{"default-fields", testdata.DefaultFieldsDSL, testdata.DefaultFieldsPackageCode},
2930
}
3031
for _, c := range cases {
3132
t.Run(c.Name, func(t *testing.T) {

grpc/codegen/protobuf_transform.go

+16-2
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ func transformObject(source, target *expr.AttributeExpr, sourceVar, targetVar st
323323
// Default value handling. We need to handle default values if the target
324324
// type uses default values (i.e. attributes with default values are
325325
// non-pointers) and has a default value set.
326-
if tdef := tgtc.DefaultValue; tdef != nil && ta.TargetCtx.UseDefault {
326+
if tdef := tgtc.DefaultValue; tdef != nil && ta.TargetCtx.UseDefault && isNonZero(tdef) {
327327
if ta.proto {
328328
// We set default values in protocol buffer type only if the source type
329329
// uses pointers to hold default values.
@@ -369,6 +369,20 @@ func transformObject(source, target *expr.AttributeExpr, sourceVar, targetVar st
369369
return buffer.String(), nil
370370
}
371371

372+
func isNonZero(v any) bool {
373+
switch v := v.(type) {
374+
case nil:
375+
return false
376+
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
377+
return v != 0
378+
case float32, float64:
379+
return v != 0.0
380+
case string:
381+
return v != ""
382+
}
383+
return true
384+
}
385+
372386
// transformArray returns the code to transform source attribute of array
373387
// type to target attribute of array type. It returns an error if source
374388
// and target are not compatible for transformation.
@@ -963,7 +977,7 @@ case {{ . }}:
963977
transformGoUnionFromProtoTmpl = `switch val := {{ .SourceVar }}.(type) {
964978
{{- range $i, $ref := .SourceValueTypeRefs }}
965979
case {{ . }}:
966-
{{- $field := (print "val." (index $.SourceFieldNames $i)) }}
980+
{{- $field := (print "val." (index $.SourceFieldNames $i)) }}
967981
{{ $.TargetVar }} = {{ convertType (index $.SourceValues $i).Attribute (index $.TargetValues $i).Attribute $field $.TransformAttrs }}
968982
{{- end }}
969983
}`

grpc/codegen/server_types_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ func TestServerTypeFiles(t *testing.T) {
2424
{"elem-validation", testdata.ElemValidationDSL, testdata.ElemValidationServerTypesFile},
2525
{"alias-validation", testdata.AliasValidationDSL, testdata.AliasValidationServerTypesFile},
2626
{"struct-meta-type", testdata.StructMetaTypeDSL, testdata.StructMetaTypeServerTypeCode},
27+
{"default-fields", testdata.DefaultFieldsDSL, testdata.DefaultFieldsServerTypeCode},
2728
}
2829
for _, c := range cases {
2930
t.Run(c.Name, func(t *testing.T) {

grpc/codegen/testdata/client_type_code.go

+30-2
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,11 @@ func NewMethodResult(message *using_meta_typespb.MethodResponse) *usingmetatypes
357357
}
358358
var zeroMessageA int64
359359
if message.A == zeroMessageA {
360-
result.A = 0
360+
result.A = 1
361361
}
362362
var zeroMessageB int64
363363
if message.B == zeroMessageB {
364-
result.B = 0
364+
result.B = 2
365365
}
366366
if message.C != nil {
367367
result.C = make([]time.Duration, len(message.C))
@@ -372,3 +372,31 @@ func NewMethodResult(message *using_meta_typespb.MethodResponse) *usingmetatypes
372372
return result
373373
}
374374
`
375+
376+
const DefaultFieldsTypeCode = `// NewProtoMethodRequest builds the gRPC request type from the payload of the
377+
// "Method" endpoint of the "DefaultFields" service.
378+
func NewProtoMethodRequest(payload *defaultfields.MethodPayload) *default_fieldspb.MethodRequest {
379+
message := &default_fieldspb.MethodRequest{
380+
Req: payload.Req,
381+
Def0: payload.Def0,
382+
Def1: payload.Def1,
383+
Def2: payload.Def2,
384+
Reqs: payload.Reqs,
385+
Defs: payload.Defs,
386+
Defe: payload.Defe,
387+
Rat: payload.Rat,
388+
Flt0: payload.Flt0,
389+
Flt1: payload.Flt1,
390+
}
391+
if payload.Opt != nil {
392+
message.Opt = *payload.Opt
393+
}
394+
if payload.Opts != nil {
395+
message.Opts = *payload.Opts
396+
}
397+
if payload.Flt != nil {
398+
message.Flt = *payload.Flt
399+
}
400+
return message
401+
}
402+
`

grpc/codegen/testdata/dsls.go

+28-4
Original file line numberDiff line numberDiff line change
@@ -870,11 +870,11 @@ var StructMetaTypeDSL = func() {
870870
Payload(func() {
871871
Field(1, "a", Int64, func() {
872872
Meta("struct:field:type", "flag.ErrorHandling", "flag")
873-
Default(0)
873+
Default(1)
874874
})
875875
Field(2, "b", Int64, func() {
876876
Meta("struct:field:type", "flag.ErrorHandling", "flag")
877-
Default(0)
877+
Default(2)
878878
})
879879
Field(3, "c", ArrayOf(Int64), func() {
880880
Elem(func() {
@@ -888,11 +888,11 @@ var StructMetaTypeDSL = func() {
888888
Result(func() {
889889
Field(1, "a", Int64, func() {
890890
Meta("struct:field:type", "flag.ErrorHandling", "flag")
891-
Default(0)
891+
Default(1)
892892
})
893893
Field(2, "b", Int64, func() {
894894
Meta("struct:field:type", "flag.ErrorHandling", "flag")
895-
Default(0)
895+
Default(2)
896896
})
897897
Field(3, "c", ArrayOf(Int64), func() {
898898
Elem(func() {
@@ -907,3 +907,27 @@ var StructMetaTypeDSL = func() {
907907
})
908908
})
909909
}
910+
911+
var DefaultFieldsDSL = func() {
912+
Service("DefaultFields", func() {
913+
Method("Method", func() {
914+
Payload(func() {
915+
Field(1, "req", Int64)
916+
Field(2, "opt", Int64)
917+
Field(3, "def0", Int64, func() { Default(0) })
918+
Field(4, "def1", Int64, func() { Default(1) })
919+
Field(5, "def2", Int64, func() { Default(2) })
920+
Field(6, "reqs", String)
921+
Field(7, "opts", String)
922+
Field(8, "defs", String, func() { Default("!") })
923+
Field(9, "defe", String, func() { Default("") })
924+
Field(10, "rat", Float64)
925+
Field(11, "flt", Float64)
926+
Field(12, "flt0", Float64, func() { Default(0.0) })
927+
Field(13, "flt1", Float64, func() { Default(1.0) })
928+
Required("req", "reqs", "rat")
929+
})
930+
GRPC(func() {})
931+
})
932+
})
933+
}

grpc/codegen/testdata/proto_code.go

+33
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,36 @@ message MethodResponse {
471471
sint64 d = 4;
472472
}
473473
`
474+
475+
const DefaultFieldsPackageCode = `
476+
syntax = "proto3";
477+
478+
package default_fields;
479+
480+
option go_package = "/default_fieldspb";
481+
482+
// Service is the DefaultFields service interface.
483+
service DefaultFields {
484+
// Method implements Method.
485+
rpc Method (MethodRequest) returns (MethodResponse);
486+
}
487+
488+
message MethodRequest {
489+
sint64 req = 1;
490+
sint64 opt = 2;
491+
sint64 def0 = 3;
492+
sint64 def1 = 4;
493+
sint64 def2 = 5;
494+
string reqs = 6;
495+
string opts = 7;
496+
string defs = 8;
497+
string defe = 9;
498+
double rat = 10;
499+
double flt = 11;
500+
double flt0 = 12;
501+
double flt1 = 13;
502+
}
503+
504+
message MethodResponse {
505+
}
506+
`

grpc/codegen/testdata/server_type_code.go

+49-2
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,11 @@ func NewMethodPayload(message *using_meta_typespb.MethodRequest) *usingmetatypes
419419
}
420420
var zeroMessageA int64
421421
if message.A == zeroMessageA {
422-
v.A = 0
422+
v.A = 1
423423
}
424424
var zeroMessageB int64
425425
if message.B == zeroMessageB {
426-
v.B = 0
426+
v.B = 2
427427
}
428428
if message.C != nil {
429429
v.C = make([]time.Duration, len(message.C))
@@ -453,3 +453,50 @@ func NewProtoMethodResponse(result *usingmetatypes.MethodResult) *using_meta_typ
453453
return message
454454
}
455455
`
456+
457+
const DefaultFieldsServerTypeCode = `// NewMethodPayload builds the payload of the "Method" endpoint of the
458+
// "DefaultFields" service from the gRPC request type.
459+
func NewMethodPayload(message *default_fieldspb.MethodRequest) *defaultfields.MethodPayload {
460+
v := &defaultfields.MethodPayload{
461+
Req: message.Req,
462+
Def0: message.Def0,
463+
Def1: message.Def1,
464+
Def2: message.Def2,
465+
Reqs: message.Reqs,
466+
Defs: message.Defs,
467+
Defe: message.Defe,
468+
Rat: message.Rat,
469+
Flt0: message.Flt0,
470+
Flt1: message.Flt1,
471+
}
472+
if message.Opt != 0 {
473+
v.Opt = &message.Opt
474+
}
475+
if message.Opts != "" {
476+
v.Opts = &message.Opts
477+
}
478+
if message.Flt != 0 {
479+
v.Flt = &message.Flt
480+
}
481+
if message.Def1 == 0 {
482+
v.Def1 = 1
483+
}
484+
if message.Def2 == 0 {
485+
v.Def2 = 2
486+
}
487+
if message.Defs == "" {
488+
v.Defs = "!"
489+
}
490+
if message.Flt1 == 0 {
491+
v.Flt1 = 1
492+
}
493+
return v
494+
}
495+
496+
// NewProtoMethodResponse builds the gRPC response type from the result of the
497+
// "Method" endpoint of the "DefaultFields" service.
498+
func NewProtoMethodResponse() *default_fieldspb.MethodResponse {
499+
message := &default_fieldspb.MethodResponse{}
500+
return message
501+
}
502+
`

0 commit comments

Comments
 (0)