Skip to content

Commit

Permalink
fix: go2proto slices of int weren't working (#3713)
Browse files Browse the repository at this point in the history
  • Loading branch information
alecthomas authored Dec 11, 2024
1 parent 6d4332a commit 39de359
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 87 deletions.
31 changes: 18 additions & 13 deletions cmd/go2proto/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,11 @@ func (m Message) DeclName() string { return m.Name }
type Field struct {
ID int
Name string
Type string
OriginType string // The original type of the field, eg. int, string, float32, etc.
ProtoType string // The type of the field in the generated .proto file.
ProtoGoType string // The type of the field in the generated Go protobuf code. eg. int -> int64.
Optional bool
Repeated bool
ProtoGoType string
Pointer bool
}

Expand Down Expand Up @@ -531,21 +532,26 @@ func parsePBTag(tag string) (pbTag, error) {
}

func (s *State) applyFieldType(t types.Type, field *Field) error {
field.OriginType = t.String()
switch t := t.(type) {
case *types.Named:
if err := s.extractDecl(t.Obj(), t); err != nil {
return err
}
ref := t.Obj().Pkg().Path() + "." + t.Obj().Name()
if bt, ok := stdTypes[ref]; ok {
field.Type = bt.ref
field.ProtoType = bt.ref
field.ProtoGoType = protoName(bt.ref)
field.OriginType = t.Obj().Name()
} else {
field.Type = t.Obj().Name()
field.ProtoType = t.Obj().Name()
field.ProtoGoType = protoName(t.Obj().Name())
field.OriginType = t.Obj().Name()
}

case *types.Slice:
if t.Elem().String() == "byte" {
field.Type = "bytes"
field.ProtoType = "bytes"
} else {
field.Repeated = true
return s.applyFieldType(t.Elem(), field)
Expand All @@ -554,31 +560,30 @@ func (s *State) applyFieldType(t types.Type, field *Field) error {
case *types.Pointer:
field.Pointer = true
if _, ok := t.Elem().(*types.Slice); ok {
return fmt.Errorf("pointer to named type is not supported")
return fmt.Errorf("pointer to slice is not supported")
}
return s.applyFieldType(t.Elem(), field)

default:
field.OriginType = t.String()
field.ProtoType = t.String()
field.ProtoGoType = t.String()
switch t.String() {
case "int":
field.Type = "int64"
field.ProtoType = "int64"
field.ProtoGoType = "int64"

case "uint":
field.Type = "uint64"
field.ProtoType = "uint64"
field.ProtoGoType = "uint64"

case "float64":
field.Type = "double"
field.ProtoGoType = "float64"
field.ProtoType = "double"

case "float32":
field.Type = "float"
field.ProtoGoType = "float32"
field.ProtoType = "float"

case "string", "bool", "uint64", "int64", "uint32", "int32":
field.Type = t.String()

default:
return fmt.Errorf("unsupported type %s", t.String())
Expand Down
2 changes: 1 addition & 1 deletion cmd/go2proto/pbtmpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ option {{ $name }} = {{ $value }};
{{- if eq (typeof $decl) "Message" }}
message {{ .Name }} {
{{- range $name, $field := .Fields }}
{{ if .Repeated }}repeated {{else if .Optional}}optional {{ end }}{{ .Type }} {{ .Name | toLowerSnake }} = {{ .ID }};
{{ if .Repeated }}repeated {{else if .Optional}}optional {{ end }}{{ .ProtoType }} {{ .Name | toLowerSnake }} = {{ .ID }};
{{- end }}
}
{{- else if eq (typeof $decl) "Enum" }}
Expand Down
2 changes: 2 additions & 0 deletions cmd/go2proto/testdata/go2proto.to.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions cmd/go2proto/testdata/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
)

type Root struct {
Int int `protobuf:"1"`
String string `protobuf:"2"`
MessagePtr *Message `protobuf:"4"`
Enum Enum `protobuf:"5"`
SumType SumType `protobuf:"6"`
OptionalInt int `protobuf:"7,optional"`
OptionalIntPtr *int `protobuf:"8,optional"`
OptionalMsg *Message `protobuf:"9,optional"`
// RepeatedInt []int `protobuf:"9"`
// RepeatedMsg []Message `protobuf:"10"`
Int int `protobuf:"1"`
String string `protobuf:"2"`
MessagePtr *Message `protobuf:"4"`
Enum Enum `protobuf:"5"`
SumType SumType `protobuf:"6"`
OptionalInt int `protobuf:"7,optional"`
OptionalIntPtr *int `protobuf:"8,optional"`
OptionalMsg *Message `protobuf:"9,optional"`
RepeatedInt []int `protobuf:"10"`
RepeatedMsg []*Message `protobuf:"11"`
}

type Message struct {
Expand Down
2 changes: 2 additions & 0 deletions cmd/go2proto/testdata/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ func TestModel(t *testing.T) {
OptionalInt: 2,
OptionalIntPtr: &intv,
OptionalMsg: &Message{Time: time.Now()},
RepeatedInt: []int{1, 2, 3},
RepeatedMsg: []*Message{&Message{Time: time.Now()}, &Message{Time: time.Now()}},
}
pb := model.ToProto()
data, err := proto.Marshal(pb)
Expand Down
124 changes: 74 additions & 50 deletions cmd/go2proto/testdata/testdatapb/model.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cmd/go2proto/testdata/testdatapb/model.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ message Root {
optional int64 optional_int = 7;
optional int64 optional_int_ptr = 8;
optional Message optional_msg = 9;
repeated int64 repeated_int = 10;
repeated Message repeated_msg = 11;
}


Expand Down
26 changes: 13 additions & 13 deletions cmd/go2proto/toprototmpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import (

var _ fmt.Stringer

var go2protoTmpl = template.Must(template.New("go2proto.mapper.go").
var go2protoTmpl = template.Must(template.New("go2proto.to.go.tmpl").
Funcs(template.FuncMap{
"typeof": func(t any) string { return reflect.Indirect(reflect.ValueOf(t)).Type().Name() },
// Return true if the type is a builtin proto type.
"isBuiltin": func(t Field) bool {
switch t.Type {
case "int32", "int64", "uint32", "uint64", "float", "double", "bool", "string":
switch t.OriginType {
case "int", "uint", "int32", "int64", "uint32", "uint64", "float32", "float64", "bool", "string":
return true
}
return false
Expand Down Expand Up @@ -88,34 +88,34 @@ func (x *{{ .Name }}) ToProto() *destpb.{{ .Name }} {
{{- if $field.Optional}}
{{ $field.EscapedName }}: proto.{{ $field.ProtoGoType | toUpperCamel }}({{ $field.ProtoGoType }}({{if $field.Pointer}}*{{end}}x.{{ $field.Name }})),
{{- else if .Repeated}}
{{ $field.EscapedName }}: protoSlicef(x.{{ $field.Name }}, func(v {{ $field.Type }}) {{ $field.ProtoGoType }} { return {{ $field.ProtoGoType }}(v) }),
{{ $field.EscapedName }}: protoSlicef(x.{{ $field.Name }}, func(v {{ $field.OriginType }}) {{ $field.ProtoGoType }} { return {{ $field.ProtoGoType }}(v) }),
{{- else }}
{{ $field.EscapedName }}: {{ $field.ProtoGoType }}(x.{{ $field.Name }}),
{{- end}}
{{- else if eq $field.Type "google.protobuf.Timestamp" }}
{{- else if eq $field.ProtoType "google.protobuf.Timestamp" }}
{{ $field.EscapedName }}: timestamppb.New(x.{{ $field.Name }}),
{{- else if eq $field.Type "google.protobuf.Duration" }}
{{- else if eq $field.ProtoType "google.protobuf.Duration" }}
{{ $field.EscapedName }}: durationpb.New(x.{{ $field.Name }}),
{{- else if eq (.Type | $.TypeOf) "Message" }}
{{- else if eq (.OriginType | $.TypeOf) "Message" }}
{{- if .Repeated }}
{{ $field.EscapedName }}: protoSlice[*destpb.{{ .Type }}](x.{{ $field.Name }}),
{{ $field.EscapedName }}: protoSlice[*destpb.{{ .ProtoGoType }}](x.{{ $field.Name }}),
{{- else}}
{{ $field.EscapedName }}: x.{{ $field.Name }}.ToProto(),
{{- end}}
{{- else if eq (.Type | $.TypeOf) "Enum" }}
{{- else if eq (.OriginType | $.TypeOf) "Enum" }}
{{- if .Repeated }}
{{ $field.EscapedName }}: protoSlice[destpb.{{ .Type }}](x.{{ $field.Name }}),
{{- else}}
{{ $field.EscapedName }}: x.{{ $field.Name }}.ToProto(),
{{- end}}
{{- else if eq (.Type | $.TypeOf) "SumType" }}
{{- else if eq (.OriginType | $.TypeOf) "SumType" }}
{{- if .Repeated }}
{{ $field.EscapedName }}: protoSlicef(x.{{ $field.Name }}, {{$field.Type}}ToProto),
{{ $field.EscapedName }}: protoSlicef(x.{{ $field.Name }}, {{$field.OriginType}}ToProto),
{{- else}}
{{ $field.EscapedName }}: {{ $field.Type }}ToProto(x.{{ $field.Name }}),
{{ $field.EscapedName }}: {{ $field.OriginType }}ToProto(x.{{ $field.Name }}),
{{- end}}
{{- else }}
{{ $field.EscapedName }}: ??, // x.{{ $field.Name }}.ToProto() // Unknown type: {{ $field.Type }}
{{ $field.EscapedName }}: ??, // x.{{ $field.Name }}.ToProto() // Unknown type: {{ $field.OriginType }}
{{- end}}
{{- end}}
}
Expand Down

0 comments on commit 39de359

Please sign in to comment.