Skip to content

Commit

Permalink
impl(generator): support all scalar field types
Browse files Browse the repository at this point in the history
I introduced a new attribute to indicate if a scalar field is optional. I am
planning to capture this attribute from the proto source in a future PR.
  • Loading branch information
coryan committed Oct 30, 2024
1 parent d86962b commit 8716ab4
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 12 deletions.
57 changes: 45 additions & 12 deletions generator/internal/genclient/language/internal/rust/rust.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package rust

import (
"fmt"
"log/slog"

"github.com/googleapis/google-cloud-rust/generator/internal/genclient"
Expand All @@ -40,20 +41,52 @@ func (c *Codec) LoadWellKnownTypes(s *genclient.APIState) {
s.MessageByID[duration.ID] = duration
}

func (c *Codec) FieldType(f *genclient.Field, state *genclient.APIState) string {
func ScalarFieldType(f *genclient.Field) string {
var out string
switch f.Typez {
case genclient.STRING_TYPE:
out = "String"
case genclient.DOUBLE_TYPE:
out = "f64"
case genclient.FLOAT_TYPE:
out = "f32"
case genclient.INT64_TYPE:
out = "i64"
case genclient.UINT64_TYPE:
out = "u64"
case genclient.INT32_TYPE:
out = "i32"
case genclient.FIXED64_TYPE:
out = "u64"
case genclient.FIXED32_TYPE:
out = "u32"
case genclient.BOOL_TYPE:
out = "bool"
case genclient.STRING_TYPE:
out = "String"
case genclient.BYTES_TYPE:
out = "bytes::Bytes"
case genclient.MESSAGE_TYPE:
case genclient.UINT32_TYPE:
out = "u32"
case genclient.SFIXED32_TYPE:
out = "i32"
case genclient.SFIXED64_TYPE:
out = "i64"
case genclient.SINT32_TYPE:
out = "i32"
case genclient.SINT64_TYPE:
out = "i64"

default:
slog.Error("Unexpected field type", "field", *f)
return ""
}
if f.Optional {
return fmt.Sprintf("Option<%s>", out)
}
return out
}

func (c *Codec) FieldType(f *genclient.Field, state *genclient.APIState) string {
if f.Typez == genclient.MESSAGE_TYPE {
m, ok := state.MessageByID[f.TypezID]
if !ok {
slog.Error("unable to lookup type", "id", f.TypezID)
Expand All @@ -62,21 +95,21 @@ func (c *Codec) FieldType(f *genclient.Field, state *genclient.APIState) string
if m.IsMap {
key := c.FieldType(m.Fields[0], state)
val := c.FieldType(m.Fields[1], state)
out = "Option<std::collections::HashMap<" + key + "," + val + ">>"
break
return "Option<std::collections::HashMap<" + key + "," + val + ">>"
}
out = "Option<" + c.MessageName(m, state) + ">"
case genclient.ENUM_TYPE:
return "Option<" + c.MessageName(m, state) + ">"
} else if f.Typez == genclient.ENUM_TYPE {
e, ok := state.EnumByID[f.TypezID]
if !ok {
slog.Error("unable to lookup type", "id", f.TypezID)
return ""
}
out = c.EnumName(e, state)
default:
slog.Error("unhandled fieldType", "type", f.Typez, "id", f.TypezID)
return c.EnumName(e, state)
} else if f.Typez == genclient.GROUP_TYPE {
slog.Error("TODO(#39) - better handling of `oneof` fields")
return ""
}
return out
return ScalarFieldType(f)
}

func (c *Codec) TemplateDir() string {
Expand Down
46 changes: 46 additions & 0 deletions generator/internal/genclient/language/internal/rust/rust_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rust

import (
"testing"

"github.com/googleapis/google-cloud-rust/generator/internal/genclient"
)

type ScalarFieldTest struct {
Typez genclient.Typez
Optional bool
Expected string
}

var scalarFieldTests = []ScalarFieldTest{
{genclient.INT32_TYPE, false, "i32"},
{genclient.INT64_TYPE, false, "i64"},
{genclient.UINT32_TYPE, true, "Option<u32>"},
{genclient.UINT64_TYPE, true, "Option<u64>"},
{genclient.BOOL_TYPE, true, "Option<bool>"},
{genclient.STRING_TYPE, true, "Option<String>"},
{genclient.BYTES_TYPE, true, "Option<bytes::Bytes>"},
}

func TestScalarFields(t *testing.T) {
for _, test := range scalarFieldTests {
field := genclient.Field{Typez: test.Typez, Optional: test.Optional}
if output := ScalarFieldType(&field); output != test.Expected {
t.Errorf("Output %q not equal to expected %q", output, test.Expected)
}
}
}
2 changes: 2 additions & 0 deletions generator/internal/genclient/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ type Field struct {
// JSONName is the name of the field as it appears in JSON. Useful for
// serializing to JSON.
JSONName string
// Optional indicates that the field is marked as optional in proto3.
Optional bool
}

// Pair is a key-value pair.
Expand Down

0 comments on commit 8716ab4

Please sign in to comment.