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

Support "bytes" proto (v2/v3) type. #13

Merged
merged 3 commits into from Nov 27, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -13,5 +13,6 @@ $ godoc -http 'localhost:8080'

```
$ protoc --go_out="${GOPATH}/src" --proto_path=testdata test_proto_v2.proto test_proto_v3.proto
$ protoc --gogofast_out="${GOPATH}/src" --proto_path=testdata test_proto_gogo.proto
$ go test -v ./...
```
1 change: 1 addition & 0 deletions go.sum
Expand Up @@ -2,6 +2,7 @@ github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/jmillikin-stripe/godebug v0.0.0-20180620173319-8279e1966bc1 h1:JgsVrDAUy59N248f3l4RGZ0hij5u1HTit8iJr1mFSBY=
github.com/jmillikin-stripe/godebug v0.0.0-20180620173319-8279e1966bc1/go.mod h1:gFqr/IKD8P+Hluq9gThCR944BAu6jUqd5H/R3PrPfuM=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
Expand Down
27 changes: 22 additions & 5 deletions internal/go/skycfg/proto_message.go
Expand Up @@ -217,7 +217,8 @@ func valueToStarlark(val reflect.Value) starlark.Value {
if msg, ok := iface.(proto.Message); ok {
return NewSkyProtoMessage(msg)
}
if val.Type().Kind() == reflect.Struct {
t := val.Type()
if t.Kind() == reflect.Struct {
// Might have been generated by gogo-protobuf
//
// Need to check if this is a non-pointer map value, which
Expand All @@ -229,7 +230,11 @@ func valueToStarlark(val reflect.Value) starlark.Value {
}
}
}
if val.Type().Kind() == reflect.Slice {
// Handle []byte ([]uint8) -> string special case.
if t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
return starlark.String(string(val.Interface().([]byte)))
}
if t.Kind() == reflect.Slice {
var items []starlark.Value
for ii := 0; ii < val.Len(); ii++ {
items = append(items, valueToStarlark(val.Index(ii)))
Expand All @@ -239,7 +244,7 @@ func valueToStarlark(val reflect.Value) starlark.Value {
list: starlark.NewList(items),
}
}
if val.Type().Kind() == reflect.Map {
if t.Kind() == reflect.Map {
dict := &starlark.Dict{}
for _, keyVal := range val.MapKeys() {
elemVal := val.MapIndex(keyVal)
Expand Down Expand Up @@ -303,7 +308,8 @@ func valueFromStarlark(t reflect.Type, sky starlark.Value) (reflect.Value, error
return reflect.Value{}, err
}

// Handle the use of typedefs in Kubernetes
// Handle the use of typedefs in Kubernetes and "string" ->
// "bytes" conversion.
if scalarType := scalar.Type(); !scalarType.AssignableTo(t) {
if scalarType.Kind() != reflect.String || !scalarType.ConvertibleTo(t) {
return reflect.Value{}, typeError(t, sky)
Expand Down Expand Up @@ -375,7 +381,18 @@ func valueFromStarlark(t reflect.Type, sky starlark.Value) (reflect.Value, error
}

func scalarFromStarlark(t reflect.Type, sky starlark.Value) (reflect.Value, error) {
switch t.Kind() {
k := t.Kind()
// Handling special case of Starlark string to []byte (aka []uint8 aka
// proto "bytes") assigment.
if k == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
val, ok := sky.(starlark.String)
if !ok {
return reflect.Value{}, typeError(t, sky)
}
return reflect.ValueOf([]byte(val)), nil
}

switch k {
case reflect.Ptr:
val := reflect.New(t.Elem())
elem, err := scalarFromStarlark(t.Elem(), sky)
Expand Down
10 changes: 10 additions & 0 deletions internal/go/skycfg/proto_test.go
Expand Up @@ -301,6 +301,7 @@ func TestMessageAttrNames(t *testing.T) {
"f_nested_enum",
"f_oneof_a",
"f_oneof_b",
"f_bytes",
}
sort.Strings(want)
if !reflect.DeepEqual(want, got) {
Expand Down Expand Up @@ -341,6 +342,7 @@ func TestMessageV2(t *testing.T) {
f_toplevel_enum = proto.package("skycfg.test_proto").ToplevelEnumV2.TOPLEVEL_ENUM_V2_B,
f_nested_enum = proto.package("skycfg.test_proto").MessageV2.NestedEnum.NESTED_ENUM_B,
f_oneof_a = "string in oneof",
f_bytes = "also some string",
)`)
gotMsg := val.(*skyProtoMessage).msg
wantMsg := &pb.MessageV2{
Expand Down Expand Up @@ -373,6 +375,7 @@ func TestMessageV2(t *testing.T) {
FToplevelEnum: pb.ToplevelEnumV2_TOPLEVEL_ENUM_V2_B.Enum(),
FNestedEnum: pb.MessageV2_NESTED_ENUM_B.Enum(),
FOneof: &pb.MessageV2_FOneofA{"string in oneof"},
FBytes: []byte("also some string"),
}
if diff := ProtoDiff(wantMsg, gotMsg); diff != "" {
t.Fatalf("diff from expected message:\n%s", diff)
Expand All @@ -397,6 +400,7 @@ func TestMessageV2(t *testing.T) {
"f_nested_enum": `<skycfg.test_proto.MessageV2.NestedEnum NESTED_ENUM_B=1>`,
"f_oneof_a": `"string in oneof"`,
"f_oneof_b": `None`,
"f_bytes": `"also some string"`,
}
attrs := val.(starlark.HasAttrs)
for attrName, wantAttr := range wantAttrs {
Expand Down Expand Up @@ -444,6 +448,7 @@ func TestMessageV3(t *testing.T) {
f_toplevel_enum = proto.package("skycfg.test_proto").ToplevelEnumV3.TOPLEVEL_ENUM_V3_B,
f_nested_enum = proto.package("skycfg.test_proto").MessageV3.NestedEnum.NESTED_ENUM_B,
f_oneof_a = "string in oneof",
f_bytes = "also some string",
)`)
gotMsg := val.(*skyProtoMessage).msg
wantMsg := &pb.MessageV3{
Expand Down Expand Up @@ -476,6 +481,7 @@ func TestMessageV3(t *testing.T) {
FToplevelEnum: pb.ToplevelEnumV3_TOPLEVEL_ENUM_V3_B,
FNestedEnum: pb.MessageV3_NESTED_ENUM_B,
FOneof: &pb.MessageV3_FOneofA{"string in oneof"},
FBytes: []byte("also some string"),
}
if diff := ProtoDiff(wantMsg, gotMsg); diff != "" {
t.Fatalf("diff from expected message:\n%s", diff)
Expand All @@ -500,6 +506,7 @@ func TestMessageV3(t *testing.T) {
"f_nested_enum": `<skycfg.test_proto.MessageV3.NestedEnum NESTED_ENUM_B=1>`,
"f_oneof_a": `"string in oneof"`,
"f_oneof_b": `None`,
"f_bytes": `"also some string"`,
}
attrs := val.(starlark.HasAttrs)
for attrName, wantAttr := range wantAttrs {
Expand Down Expand Up @@ -547,6 +554,7 @@ func TestMessageGogo(t *testing.T) {
f_toplevel_enum = proto.package("skycfg.test_proto").ToplevelEnumV2.TOPLEVEL_ENUM_V2_B,
f_nested_enum = gogo_proto.package("skycfg.test_proto").MessageGogo.NestedEnum.NESTED_ENUM_B,
f_oneof_a = "string in oneof",
f_bytes = "also some string",
)`)
gotMsg := val.(*skyProtoMessage).msg
wantMsg := &pb.MessageGogo{
Expand Down Expand Up @@ -579,6 +587,7 @@ func TestMessageGogo(t *testing.T) {
FToplevelEnum: pb.ToplevelEnumV2_TOPLEVEL_ENUM_V2_B.Enum(),
FNestedEnum: pb.MessageGogo_NESTED_ENUM_B.Enum(),
FOneof: &pb.MessageGogo_FOneofA{"string in oneof"},
FBytes: []byte("also some string"),
}
if diff := ProtoDiff(wantMsg, gotMsg); diff != "" {
t.Fatalf("diff from expected message:\n%s", diff)
Expand All @@ -603,6 +612,7 @@ func TestMessageGogo(t *testing.T) {
"f_nested_enum": `<skycfg.test_proto.MessageGogo.NestedEnum NESTED_ENUM_B=1>`,
"f_oneof_a": `"string in oneof"`,
"f_oneof_b": `None`,
"f_bytes": `"also some string"`,
}
attrs := val.(starlark.HasAttrs)
for attrName, wantAttr := range wantAttrs {
Expand Down
4 changes: 3 additions & 1 deletion testdata/test_proto_gogo.proto
Expand Up @@ -50,5 +50,7 @@ message MessageGogo {
string f_oneof_b = 18;
}

// NEXT: 19
optional bytes f_bytes = 19;

// NEXT: 20
}
4 changes: 3 additions & 1 deletion testdata/test_proto_v2.proto
Expand Up @@ -38,7 +38,9 @@ message MessageV2 {
string f_oneof_b = 18;
}

// NEXT: 19
optional bytes f_bytes = 19;

// NEXT: 20
}

enum ToplevelEnumV2 {
Expand Down
4 changes: 3 additions & 1 deletion testdata/test_proto_v3.proto
Expand Up @@ -39,7 +39,9 @@ message MessageV3 {
string f_oneof_b = 18;
}

// NEXT: 19
bytes f_bytes = 19;

// NEXT: 20
}

enum ToplevelEnumV3 {
Expand Down