Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl(generator): support more field types #61

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 139 additions & 35 deletions generator/internal/genclient/translator/openapi/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package openapi

import (
"fmt"
"strings"

"github.com/googleapis/google-cloud-rust/generator/internal/genclient"
"github.com/googleapis/google-cloud-rust/generator/internal/genclient/language"
Expand Down Expand Up @@ -123,7 +124,14 @@ func makeMessageFields(messageName string, message *base.Schema) ([]*genclient.F
if err != nil {
return nil, err
}
field, err := makeField(messageName, name, schema)
optional := true
for _, r := range message.Required {
if name == r {
optional = false
break
}
}
field, err := makeField(messageName, name, optional, schema)
if err != nil {
return nil, err
}
Expand All @@ -132,66 +140,145 @@ func makeMessageFields(messageName string, message *base.Schema) ([]*genclient.F
return fields, nil
}

func makeField(messageName, name string, field *base.Schema) (*genclient.Field, error) {
func makeField(messageName, name string, optional bool, field *base.Schema) (*genclient.Field, error) {
if len(field.AllOf) != 0 {
return makeAllOfField(messageName, name, field)
}
if len(field.Type) == 0 {
return nil, fmt.Errorf("missing field type for field %s.%s", messageName, name)
}
type_name := field.Type[0]
optional := true
for _, r := range field.Required {
if name == r {
optional = false
break
}
}
switch type_name {
case "string":
case "boolean":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.STRING_TYPE,
Typez: genclient.BOOL_TYPE,
Optional: optional,
}, nil
case "string":
return makeStringType(messageName, name, field.Format, optional, field)
case "integer":
{
typez, err := makeIntegerType(field.Format)
if err != nil {
return nil, err
}
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: typez,
Optional: optional,
}, nil
}
return makeIntegerField(messageName, name, field.Format, optional, field)
case "object":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.MESSAGE_TYPE,
Optional: true,
}, nil

case "array":
return makeArrayField(messageName, name, field)
default:
return nil, fmt.Errorf("unknown type for field %q", name)
}
}

func makeIntegerType(format string) (genclient.Typez, error) {
func makeAllOfField(messageName, name string, field *base.Schema) (*genclient.Field, error) {
for _, proxy := range field.AllOf {
typezID := strings.TrimPrefix(proxy.GetReference(), "#/components/schemas/")
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.MESSAGE_TYPE,
TypezID: typezID,
Optional: true,
}, nil
}
return nil, fmt.Errorf("cannot build any AllOf schema for field %s.%s", messageName, name)
}

func makeStringType(messageName, name, format string, optional bool, field *base.Schema) (*genclient.Field, error) {
switch format {
case "":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be case "string"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. A normal string has no "format" field. Integers as strings have {"type": "string", "format": "int64"}.

I sure don't like how OpenAPI represents primitive types 🤷

return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.STRING_TYPE,
Optional: optional,
}, nil
case "int64":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.INT64_TYPE,
Optional: optional,
}, nil
case "uint64":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.UINT64_TYPE,
Optional: optional,
}, nil
case "byte":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.BYTES_TYPE,
Optional: optional,
}, nil
case "google-duration":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.MESSAGE_TYPE,
TypezID: ".google.protobuf.Duration",
Optional: true,
}, nil
case "date-time":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.MESSAGE_TYPE,
TypezID: ".google.protobuf.Timestamp",
Optional: true,
}, nil
case "google-fieldmask":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.MESSAGE_TYPE,
TypezID: ".google.protobuf.FieldMask",
Optional: true,
}, nil
default:
return nil, fmt.Errorf("unknown string format (%q) for field %s.%s", field.Format, messageName, name)
}
}

func makeIntegerField(messageName, name, format string, optional bool, field *base.Schema) (*genclient.Field, error) {
switch format {
case "int32":
return genclient.INT32_TYPE, nil
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.INT32_TYPE,
Optional: optional,
}, nil
case "int64":
return genclient.INT64_TYPE, nil
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.INT64_TYPE,
Optional: optional,
}, nil
case "uint32":
return genclient.UINT32_TYPE, nil
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.UINT32_TYPE,
Optional: optional,
}, nil
case "uint64":
return genclient.UINT64_TYPE, nil
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.UINT64_TYPE,
Optional: optional,
}, nil
default:
return 0, fmt.Errorf("unknown integer format %q", format)
return nil, fmt.Errorf("unknown integer format (%q) for field %s.%s", format, messageName, name)
}
}

Expand All @@ -203,23 +290,40 @@ func makeArrayField(messageName, name string, field *base.Schema) (*genclient.Fi
if err != nil {
return nil, fmt.Errorf("cannot build schema for %s.%s error=%q", messageName, name, err)
}
if schema.Type[0] == "string" {
switch schema.Type[0] {
case "string":
field, err := makeStringType(messageName, name, schema.Format, false, field)
if err != nil {
return nil, err
}
field.Repeated = true
field.Optional = false
return field, nil
case "integer":
field, err := makeIntegerField(messageName, name, schema.Format, false, field)
if err != nil {
return nil, err
}
field.Repeated = true
field.Optional = false
return field, nil
case "boolean":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.STRING_TYPE,
Typez: genclient.BOOL_TYPE,
Optional: false,
Repeated: true,
}, nil
}
if schema.Type[0] == "object" {
case "object":
return &genclient.Field{
Name: name,
Documentation: field.Description,
Typez: genclient.MESSAGE_TYPE,
Optional: false,
Repeated: true,
}, nil
default:
return nil, fmt.Errorf("unknown array field type for %s.%s %q", messageName, name, schema.Type[0])
}
return nil, fmt.Errorf("unknown array field type for %s.%s %q", messageName, name, schema.Type[0])
}
Loading