From ebbe537fe59f3a43d9d9ecb54820a8620e8be6d7 Mon Sep 17 00:00:00 2001 From: Josh Humphries <2035234+jhump@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:12:59 -0400 Subject: [PATCH] add support for required fields and groups --- buf.gen.yaml | 2 +- decode.go | 81 ++-- decode_test.go | 38 ++ .../proto/buf/protoyaml/test/v1/const.pb.go | 2 +- .../buf/protoyaml/test/v1/editions.pb.go | 355 ++++++++++++++++++ .../gen/proto/buf/protoyaml/test/v1/pb2.pb.go | 2 +- .../gen/proto/buf/protoyaml/test/v1/pb3.pb.go | 2 +- .../buf/protoyaml/test/v1/validate.pb.go | 2 +- .../conformance/proto3/test_all_types.pb.go | 2 +- .../buf/protoyaml/test/v1/editions.proto | 36 ++ internal/protoyamltest/fuzz.go | 6 +- 11 files changed, 490 insertions(+), 38 deletions(-) create mode 100644 internal/gen/proto/buf/protoyaml/test/v1/editions.pb.go create mode 100644 internal/proto/buf/protoyaml/test/v1/editions.proto diff --git a/buf.gen.yaml b/buf.gen.yaml index db5c4d6..68671f5 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -6,6 +6,6 @@ managed: except: - buf.build/bufbuild/protovalidate plugins: - - plugin: buf.build/protocolbuffers/go:v1.33.0 + - plugin: buf.build/protocolbuffers/go:v1.34.0 out: internal/gen/proto opt: paths=source_relative diff --git a/decode.go b/decode.go index 62e3c11..dd2fae8 100644 --- a/decode.go +++ b/decode.go @@ -55,6 +55,10 @@ type UnmarshalOptions struct { protoregistry.ExtensionTypeResolver } + // If AllowPartial is set, input for messages that will result in missing + // required fields will not return an error. + AllowPartial bool + // DiscardUnknown specifies whether to discard unknown fields instead of // returning an error. DiscardUnknown bool @@ -243,32 +247,32 @@ func (u *unmarshaler) unmarshalScalar( node *yaml.Node, field protoreflect.FieldDescriptor, forKey bool, -) protoreflect.Value { +) (protoreflect.Value, bool) { switch field.Kind() { case protoreflect.BoolKind: - return protoreflect.ValueOfBool(u.unmarshalBool(node, forKey)) + return protoreflect.ValueOfBool(u.unmarshalBool(node, forKey)), true case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - return protoreflect.ValueOfInt32(int32(u.unmarshalInteger(node, 32))) + return protoreflect.ValueOfInt32(int32(u.unmarshalInteger(node, 32))), true case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return protoreflect.ValueOfInt64(u.unmarshalInteger(node, 64)) + return protoreflect.ValueOfInt64(u.unmarshalInteger(node, 64)), true case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - return protoreflect.ValueOfUint32(uint32(u.unmarshalUnsigned(node, 32))) + return protoreflect.ValueOfUint32(uint32(u.unmarshalUnsigned(node, 32))), true case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return protoreflect.ValueOfUint64(u.unmarshalUnsigned(node, 64)) + return protoreflect.ValueOfUint64(u.unmarshalUnsigned(node, 64)), true case protoreflect.FloatKind: - return protoreflect.ValueOfFloat32(float32(u.unmarshalFloat(node, 32))) + return protoreflect.ValueOfFloat32(float32(u.unmarshalFloat(node, 32))), true case protoreflect.DoubleKind: - return protoreflect.ValueOfFloat64(u.unmarshalFloat(node, 64)) + return protoreflect.ValueOfFloat64(u.unmarshalFloat(node, 64)), true case protoreflect.StringKind: u.checkKind(node, yaml.ScalarNode) - return protoreflect.ValueOfString(node.Value) + return protoreflect.ValueOfString(node.Value), true case protoreflect.BytesKind: - return protoreflect.ValueOfBytes(u.unmarshalBytes(node)) + return protoreflect.ValueOfBytes(u.unmarshalBytes(node)), true case protoreflect.EnumKind: - return protoreflect.ValueOfEnum(u.unmarshalEnum(node, field)) + return protoreflect.ValueOfEnum(u.unmarshalEnum(node, field)), true default: u.addErrorf(node, "unimplemented scalar type %v", field.Kind()) - return protoreflect.Value{} + return protoreflect.Value{}, false } } @@ -550,10 +554,12 @@ func (u *unmarshaler) unmarshalField(node *yaml.Node, field protoreflect.FieldDe u.unmarshalList(node, field, message.ProtoReflect().Mutable(field).List()) case field.IsMap(): u.unmarshalMap(node, field, message.ProtoReflect().Mutable(field).Map()) - case field.Kind() == protoreflect.MessageKind: + case field.Message() != nil: u.unmarshalMessage(node, message.ProtoReflect().Mutable(field).Message().Interface(), false) default: - message.ProtoReflect().Set(field, u.unmarshalScalar(node, field, false)) + if val, ok := u.unmarshalScalar(node, field, false); ok { + message.ProtoReflect().Set(field, val) + } } } @@ -569,7 +575,11 @@ func (u *unmarshaler) unmarshalList(node *yaml.Node, field protoreflect.FieldDes } default: for _, itemNode := range node.Content { - list.Append(u.unmarshalScalar(itemNode, field, false)) + val, ok := u.unmarshalScalar(itemNode, field, false) + if !ok { + continue + } + list.Append(val) } } } @@ -577,21 +587,29 @@ func (u *unmarshaler) unmarshalList(node *yaml.Node, field protoreflect.FieldDes // Unmarshal the map, with explicit handling for maps to messages. func (u *unmarshaler) unmarshalMap(node *yaml.Node, field protoreflect.FieldDescriptor, mapVal protoreflect.Map) { - if u.checkKind(node, yaml.MappingNode) { - mapKeyField := field.MapKey() - mapValueField := field.MapValue() - for i := 1; i < len(node.Content); i += 2 { - keyNode := node.Content[i-1] - valueNode := node.Content[i] - mapKey := u.unmarshalScalar(keyNode, mapKeyField, true) - switch mapValueField.Kind() { - case protoreflect.MessageKind, protoreflect.GroupKind: - mapValue := mapVal.NewValue() - u.unmarshalMessage(valueNode, mapValue.Message().Interface(), false) - mapVal.Set(mapKey.MapKey(), mapValue) - default: - mapVal.Set(mapKey.MapKey(), u.unmarshalScalar(valueNode, mapValueField, false)) + if !u.checkKind(node, yaml.MappingNode) { + return + } + mapKeyField := field.MapKey() + mapValueField := field.MapValue() + for i := 1; i < len(node.Content); i += 2 { + keyNode := node.Content[i-1] + valueNode := node.Content[i] + mapKey, ok := u.unmarshalScalar(keyNode, mapKeyField, true) + if !ok { + continue + } + switch mapValueField.Kind() { + case protoreflect.MessageKind, protoreflect.GroupKind: + mapValue := mapVal.NewValue() + u.unmarshalMessage(valueNode, mapValue.Message().Interface(), false) + mapVal.Set(mapKey.MapKey(), mapValue) + default: + val, ok := u.unmarshalScalar(valueNode, mapValueField, false) + if !ok { + continue } + mapVal.Set(mapKey.MapKey(), val) } } } @@ -648,6 +666,11 @@ func (u *unmarshaler) unmarshalMessage(node *yaml.Node, message proto.Message, f return } u.unmarshalMessageFields(node, message, forAny) + if len(u.errors) == 0 && !u.options.AllowPartial { + if err := proto.CheckInitialized(message); err != nil { + u.addError(node, err) + } + } } func (u *unmarshaler) unmarshalMessageFields(node *yaml.Node, message proto.Message, forAny bool) { diff --git a/decode_test.go b/decode_test.go index c956a45..457d47a 100644 --- a/decode_test.go +++ b/decode_test.go @@ -18,9 +18,11 @@ import ( "testing" testv1 "github.com/bufbuild/protoyaml-go/internal/gen/proto/buf/protoyaml/test/v1" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/durationpb" ) @@ -98,6 +100,42 @@ func TestExtension(t *testing.T) { require.Equal(t, "hi", proto.GetExtension(actual, testv1.E_P2TStringExt)) } +func TestEditions(t *testing.T) { + t.Parallel() + + expected := &testv1.EditionsTest{ + Name: proto.String("foobar"), + Nested: &testv1.EditionsTest_Nested{ + Ids: []int64{0, 1, 1, 2, 3, 5, 8}, + }, + Enum: testv1.OpenEnum_ZERO, + } + actual := &testv1.EditionsTest{} + data := []byte(` +name: "foobar" +enum: ZERO +nested: + ids: [0, 1, 1, 2, 3, 5, 8]`) + err := Unmarshal(data, actual) + require.NoError(t, err) + require.Empty(t, cmp.Diff(expected, actual, protocmp.Transform())) +} + +func TestRequiredFields(t *testing.T) { + t.Parallel() + + actual := &testv1.EditionsTest{} + err := Unmarshal([]byte(`enum: ZERO`), actual) + require.ErrorContains(t, err, "required field buf.protoyaml.test.v1.EditionsTest.name not set") + + err = UnmarshalOptions{AllowPartial: true}.Unmarshal([]byte(`enum: ZERO`), actual) + require.NoError(t, err) + expected := &testv1.EditionsTest{ + Enum: testv1.OpenEnum_ZERO, + } + require.Empty(t, cmp.Diff(expected, actual, protocmp.Transform())) +} + func TestDiscardUnknown(t *testing.T) { t.Parallel() diff --git a/internal/gen/proto/buf/protoyaml/test/v1/const.pb.go b/internal/gen/proto/buf/protoyaml/test/v1/const.pb.go index 9c9b9b1..735926e 100644 --- a/internal/gen/proto/buf/protoyaml/test/v1/const.pb.go +++ b/internal/gen/proto/buf/protoyaml/test/v1/const.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.0 // protoc (unknown) // source: buf/protoyaml/test/v1/const.proto diff --git a/internal/gen/proto/buf/protoyaml/test/v1/editions.pb.go b/internal/gen/proto/buf/protoyaml/test/v1/editions.pb.go new file mode 100644 index 0000000..927087e --- /dev/null +++ b/internal/gen/proto/buf/protoyaml/test/v1/editions.pb.go @@ -0,0 +1,355 @@ +// Copyright 2023-2024 Buf Technologies, Inc. +// +// 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 +// +// http://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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: buf/protoyaml/test/v1/editions.proto + +package testv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type OpenEnum int32 + +const ( + OpenEnum_ZERO OpenEnum = 0 +) + +// Enum value maps for OpenEnum. +var ( + OpenEnum_name = map[int32]string{ + 0: "ZERO", + } + OpenEnum_value = map[string]int32{ + "ZERO": 0, + } +) + +func (x OpenEnum) Enum() *OpenEnum { + p := new(OpenEnum) + *p = x + return p +} + +func (x OpenEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (OpenEnum) Descriptor() protoreflect.EnumDescriptor { + return file_buf_protoyaml_test_v1_editions_proto_enumTypes[0].Descriptor() +} + +func (OpenEnum) Type() protoreflect.EnumType { + return &file_buf_protoyaml_test_v1_editions_proto_enumTypes[0] +} + +func (x OpenEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use OpenEnum.Descriptor instead. +func (OpenEnum) EnumDescriptor() ([]byte, []int) { + return file_buf_protoyaml_test_v1_editions_proto_rawDescGZIP(), []int{0} +} + +type ClosedEnum int32 + +const ( + ClosedEnum_ONE ClosedEnum = 1 +) + +// Enum value maps for ClosedEnum. +var ( + ClosedEnum_name = map[int32]string{ + 1: "ONE", + } + ClosedEnum_value = map[string]int32{ + "ONE": 1, + } +) + +func (x ClosedEnum) Enum() *ClosedEnum { + p := new(ClosedEnum) + *p = x + return p +} + +func (x ClosedEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ClosedEnum) Descriptor() protoreflect.EnumDescriptor { + return file_buf_protoyaml_test_v1_editions_proto_enumTypes[1].Descriptor() +} + +func (ClosedEnum) Type() protoreflect.EnumType { + return &file_buf_protoyaml_test_v1_editions_proto_enumTypes[1] +} + +func (x ClosedEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ClosedEnum.Descriptor instead. +func (ClosedEnum) EnumDescriptor() ([]byte, []int) { + return file_buf_protoyaml_test_v1_editions_proto_rawDescGZIP(), []int{1} +} + +type EditionsTest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` + Nested *EditionsTest_Nested `protobuf:"group,2,opt,name=Nested,json=nested" json:"nested,omitempty"` + Enum OpenEnum `protobuf:"varint,3,opt,name=enum,enum=buf.protoyaml.test.v1.OpenEnum" json:"enum,omitempty"` +} + +func (x *EditionsTest) Reset() { + *x = EditionsTest{} + if protoimpl.UnsafeEnabled { + mi := &file_buf_protoyaml_test_v1_editions_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EditionsTest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EditionsTest) ProtoMessage() {} + +func (x *EditionsTest) ProtoReflect() protoreflect.Message { + mi := &file_buf_protoyaml_test_v1_editions_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EditionsTest.ProtoReflect.Descriptor instead. +func (*EditionsTest) Descriptor() ([]byte, []int) { + return file_buf_protoyaml_test_v1_editions_proto_rawDescGZIP(), []int{0} +} + +func (x *EditionsTest) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *EditionsTest) GetNested() *EditionsTest_Nested { + if x != nil { + return x.Nested + } + return nil +} + +func (x *EditionsTest) GetEnum() OpenEnum { + if x != nil { + return x.Enum + } + return OpenEnum_ZERO +} + +type EditionsTest_Nested struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ids []int64 `protobuf:"varint,1,rep,name=ids" json:"ids,omitempty"` +} + +func (x *EditionsTest_Nested) Reset() { + *x = EditionsTest_Nested{} + if protoimpl.UnsafeEnabled { + mi := &file_buf_protoyaml_test_v1_editions_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EditionsTest_Nested) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EditionsTest_Nested) ProtoMessage() {} + +func (x *EditionsTest_Nested) ProtoReflect() protoreflect.Message { + mi := &file_buf_protoyaml_test_v1_editions_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EditionsTest_Nested.ProtoReflect.Descriptor instead. +func (*EditionsTest_Nested) Descriptor() ([]byte, []int) { + return file_buf_protoyaml_test_v1_editions_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *EditionsTest_Nested) GetIds() []int64 { + if x != nil { + return x.Ids + } + return nil +} + +var File_buf_protoyaml_test_v1_editions_proto protoreflect.FileDescriptor + +var file_buf_protoyaml_test_v1_editions_proto_rawDesc = []byte{ + 0x0a, 0x24, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x2f, + 0x74, 0x65, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x62, 0x75, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x22, 0xd3, 0x01, + 0x0a, 0x0c, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54, 0x65, 0x73, 0x74, 0x12, 0x19, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x05, 0xaa, 0x01, + 0x02, 0x08, 0x03, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x49, 0x0a, 0x06, 0x6e, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x62, 0x75, 0x66, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x4e, + 0x65, 0x73, 0x74, 0x65, 0x64, 0x42, 0x05, 0xaa, 0x01, 0x02, 0x28, 0x02, 0x52, 0x06, 0x6e, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, + 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x45, + 0x6e, 0x75, 0x6d, 0x42, 0x05, 0xaa, 0x01, 0x02, 0x08, 0x02, 0x52, 0x04, 0x65, 0x6e, 0x75, 0x6d, + 0x1a, 0x21, 0x0a, 0x06, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x03, 0x69, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x42, 0x05, 0xaa, 0x01, 0x02, 0x18, 0x02, 0x52, 0x03, + 0x69, 0x64, 0x73, 0x2a, 0x14, 0x0a, 0x08, 0x4f, 0x70, 0x65, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, + 0x08, 0x0a, 0x04, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x2a, 0x1b, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x4e, 0x45, 0x10, 0x01, + 0x1a, 0x04, 0x3a, 0x02, 0x10, 0x02, 0x42, 0xf3, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x62, + 0x75, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x2e, 0x74, 0x65, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x62, 0x75, 0x66, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x79, 0x61, 0x6d, 0x6c, 0x2d, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x75, 0x66, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x76, 0x31, + 0x3b, 0x74, 0x65, 0x73, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x50, 0x54, 0xaa, 0x02, 0x15, + 0x42, 0x75, 0x66, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x2e, 0x54, 0x65, + 0x73, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x42, 0x75, 0x66, 0x5c, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x21, + 0x42, 0x75, 0x66, 0x5c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, 0x6d, 0x6c, 0x5c, 0x54, 0x65, + 0x73, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x18, 0x42, 0x75, 0x66, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x61, + 0x6d, 0x6c, 0x3a, 0x3a, 0x54, 0x65, 0x73, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x08, 0x65, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07, +} + +var ( + file_buf_protoyaml_test_v1_editions_proto_rawDescOnce sync.Once + file_buf_protoyaml_test_v1_editions_proto_rawDescData = file_buf_protoyaml_test_v1_editions_proto_rawDesc +) + +func file_buf_protoyaml_test_v1_editions_proto_rawDescGZIP() []byte { + file_buf_protoyaml_test_v1_editions_proto_rawDescOnce.Do(func() { + file_buf_protoyaml_test_v1_editions_proto_rawDescData = protoimpl.X.CompressGZIP(file_buf_protoyaml_test_v1_editions_proto_rawDescData) + }) + return file_buf_protoyaml_test_v1_editions_proto_rawDescData +} + +var file_buf_protoyaml_test_v1_editions_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_buf_protoyaml_test_v1_editions_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_buf_protoyaml_test_v1_editions_proto_goTypes = []interface{}{ + (OpenEnum)(0), // 0: buf.protoyaml.test.v1.OpenEnum + (ClosedEnum)(0), // 1: buf.protoyaml.test.v1.ClosedEnum + (*EditionsTest)(nil), // 2: buf.protoyaml.test.v1.EditionsTest + (*EditionsTest_Nested)(nil), // 3: buf.protoyaml.test.v1.EditionsTest.Nested +} +var file_buf_protoyaml_test_v1_editions_proto_depIdxs = []int32{ + 3, // 0: buf.protoyaml.test.v1.EditionsTest.nested:type_name -> buf.protoyaml.test.v1.EditionsTest.Nested + 0, // 1: buf.protoyaml.test.v1.EditionsTest.enum:type_name -> buf.protoyaml.test.v1.OpenEnum + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_buf_protoyaml_test_v1_editions_proto_init() } +func file_buf_protoyaml_test_v1_editions_proto_init() { + if File_buf_protoyaml_test_v1_editions_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_buf_protoyaml_test_v1_editions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EditionsTest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_buf_protoyaml_test_v1_editions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EditionsTest_Nested); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_buf_protoyaml_test_v1_editions_proto_rawDesc, + NumEnums: 2, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_buf_protoyaml_test_v1_editions_proto_goTypes, + DependencyIndexes: file_buf_protoyaml_test_v1_editions_proto_depIdxs, + EnumInfos: file_buf_protoyaml_test_v1_editions_proto_enumTypes, + MessageInfos: file_buf_protoyaml_test_v1_editions_proto_msgTypes, + }.Build() + File_buf_protoyaml_test_v1_editions_proto = out.File + file_buf_protoyaml_test_v1_editions_proto_rawDesc = nil + file_buf_protoyaml_test_v1_editions_proto_goTypes = nil + file_buf_protoyaml_test_v1_editions_proto_depIdxs = nil +} diff --git a/internal/gen/proto/buf/protoyaml/test/v1/pb2.pb.go b/internal/gen/proto/buf/protoyaml/test/v1/pb2.pb.go index a7eb756..bd16464 100644 --- a/internal/gen/proto/buf/protoyaml/test/v1/pb2.pb.go +++ b/internal/gen/proto/buf/protoyaml/test/v1/pb2.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.0 // protoc (unknown) // source: buf/protoyaml/test/v1/pb2.proto diff --git a/internal/gen/proto/buf/protoyaml/test/v1/pb3.pb.go b/internal/gen/proto/buf/protoyaml/test/v1/pb3.pb.go index 56f076b..f787912 100644 --- a/internal/gen/proto/buf/protoyaml/test/v1/pb3.pb.go +++ b/internal/gen/proto/buf/protoyaml/test/v1/pb3.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.0 // protoc (unknown) // source: buf/protoyaml/test/v1/pb3.proto diff --git a/internal/gen/proto/buf/protoyaml/test/v1/validate.pb.go b/internal/gen/proto/buf/protoyaml/test/v1/validate.pb.go index 3342e46..6ccd199 100644 --- a/internal/gen/proto/buf/protoyaml/test/v1/validate.pb.go +++ b/internal/gen/proto/buf/protoyaml/test/v1/validate.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.0 // protoc (unknown) // source: buf/protoyaml/test/v1/validate.proto diff --git a/internal/gen/proto/bufext/cel/expr/conformance/proto3/test_all_types.pb.go b/internal/gen/proto/bufext/cel/expr/conformance/proto3/test_all_types.pb.go index dada4de..d91c16a 100644 --- a/internal/gen/proto/bufext/cel/expr/conformance/proto3/test_all_types.pb.go +++ b/internal/gen/proto/bufext/cel/expr/conformance/proto3/test_all_types.pb.go @@ -17,7 +17,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.0 // protoc (unknown) // source: bufext/cel/expr/conformance/proto3/test_all_types.proto diff --git a/internal/proto/buf/protoyaml/test/v1/editions.proto b/internal/proto/buf/protoyaml/test/v1/editions.proto new file mode 100644 index 0000000..4fc6c21 --- /dev/null +++ b/internal/proto/buf/protoyaml/test/v1/editions.proto @@ -0,0 +1,36 @@ +// Copyright 2023-2024 Buf Technologies, Inc. +// +// 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 +// +// http://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. + +edition = "2023"; + +package buf.protoyaml.test.v1; + +message EditionsTest { + string name = 1 [features.field_presence=LEGACY_REQUIRED]; + Nested nested = 2 [features.message_encoding=DELIMITED]; + message Nested { + repeated int64 ids = 1 [features.repeated_field_encoding=EXPANDED]; + } + OpenEnum enum = 3 [features.field_presence=IMPLICIT]; +} + +enum OpenEnum { + ZERO = 0; +} + +enum ClosedEnum { + option features.enum_type=CLOSED; + ONE = 1; +} + diff --git a/internal/protoyamltest/fuzz.go b/internal/protoyamltest/fuzz.go index 9e5a2d5..633c4dd 100644 --- a/internal/protoyamltest/fuzz.go +++ b/internal/protoyamltest/fuzz.go @@ -111,7 +111,7 @@ func populateField(rnd *rand.Rand, field protoreflect.FieldDescriptor, msg proto populateList(rnd, field, msg.ProtoReflect().Mutable(field).List(), depth) case field.IsMap(): populateMap(rnd, field, msg.ProtoReflect().Mutable(field).Map(), depth) - case field.Kind() == protoreflect.MessageKind: + case field.Message() != nil: populateMessage(rnd, msg.ProtoReflect().Mutable(field).Message().Interface(), depth) default: msg.ProtoReflect().Set(field, populateScalar(rnd, field)) @@ -125,7 +125,7 @@ func populateList(rnd *rand.Rand, field protoreflect.FieldDescriptor, list proto length := rnd.Intn(10) for i := 0; i < length; i++ { switch field.Kind() { - case protoreflect.MessageKind: + case protoreflect.MessageKind, protoreflect.GroupKind: msg := list.NewElement() populateMessage(rnd, msg.Message().Interface(), depth+1) list.Append(msg) @@ -164,7 +164,7 @@ func populateMap(rnd *rand.Rand, field protoreflect.FieldDescriptor, mapVal prot func populateMapValue(rnd *rand.Rand, field protoreflect.FieldDescriptor, mapKey protoreflect.MapKey, mapVal protoreflect.Map, depth int) { switch field.Kind() { - case protoreflect.MessageKind: + case protoreflect.MessageKind, protoreflect.GroupKind: populateMessage(rnd, mapVal.Mutable(mapKey).Message().Interface(), depth) default: mapVal.Set(mapKey, populateScalar(rnd, field))