// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package reflection_test import ( "fmt" "reflect" "testing" testopenpb "google.golang.org/protobuf/internal/testprotos/testeditions" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" "google.golang.org/protobuf/testing/prototest" ) func Test(t *testing.T) { t.Skip() for _, m := range []protoreflect.ProtoMessage{ &testopenpb.TestAllTypes{}, } { t.Run(fmt.Sprintf("%T", m), func(t *testing.T) { prototest.Message{}.Test(t, m.ProtoReflect().Type()) }) } } // What follows is infrastructure for a complicated but useful set of tests // of different views of a message. // // Every Protobuf message can be accessed in at least two ways: // // - m: a concrete open, hybrid or opaque message // - m.ProtoReflect(): reflective view of the message // // A mutation to one representation must be reflected in the others. // // To test the various views of a message, we construct an implementations of // the protoreflect.Message interface for each. The simplest is the canonical // reflective view provided by the ProtoReflect method. In addition, for each // concrete representation we create another view backed by that concrete API. // (i.e., m.ProtoReflect().KnownFields().Get(1) directly translates to a call // to m.GetFieldOne().) // // Finally, we construct a "shadow" view in which read operations are backed // by one implementation and write operations by another. // // Each of these various views may then be passed to the prototest package // for validation. // // This approach separates the decision of what behaviors to test from the // implementations being tested; new validation tests added to prototest // apply to all the various views without additional effort. The disadvantage // is that there is quite a bit of per-message boilerplate required. // // We could attempt to reduce that boilerplate by use of reflection or code // generation, but both approaches replace simple-but-repetitive code with // something quite complex. Since the purpose of all this is to test the // complex, general-purpose canonical implementation, the simple approach // is safer. // Field numbers for the test messages. var ( largeMessageDesc protoreflect.MessageDescriptor = (&testopenpb.TestManyMessageFieldsMessage{}).ProtoReflect().Descriptor() largeFieldF1 = largeMessageDesc.Fields().ByName("f1").Number() largeFieldF2 = largeMessageDesc.Fields().ByName("f2").Number() largeFieldF3 = largeMessageDesc.Fields().ByName("f3").Number() largeFieldF4 = largeMessageDesc.Fields().ByName("f4").Number() largeFieldF5 = largeMessageDesc.Fields().ByName("f5").Number() largeFieldF6 = largeMessageDesc.Fields().ByName("f6").Number() largeFieldF7 = largeMessageDesc.Fields().ByName("f7").Number() largeFieldF8 = largeMessageDesc.Fields().ByName("f8").Number() largeFieldF9 = largeMessageDesc.Fields().ByName("f9").Number() largeFieldF10 = largeMessageDesc.Fields().ByName("f10").Number() largeFieldF11 = largeMessageDesc.Fields().ByName("f11").Number() largeFieldF12 = largeMessageDesc.Fields().ByName("f12").Number() largeFieldF13 = largeMessageDesc.Fields().ByName("f13").Number() largeFieldF14 = largeMessageDesc.Fields().ByName("f14").Number() largeFieldF15 = largeMessageDesc.Fields().ByName("f15").Number() largeFieldF16 = largeMessageDesc.Fields().ByName("f16").Number() largeFieldF17 = largeMessageDesc.Fields().ByName("f17").Number() largeFieldF18 = largeMessageDesc.Fields().ByName("f18").Number() largeFieldF19 = largeMessageDesc.Fields().ByName("f19").Number() largeFieldF20 = largeMessageDesc.Fields().ByName("f20").Number() largeFieldF21 = largeMessageDesc.Fields().ByName("f21").Number() largeFieldF22 = largeMessageDesc.Fields().ByName("f22").Number() largeFieldF23 = largeMessageDesc.Fields().ByName("f23").Number() largeFieldF24 = largeMessageDesc.Fields().ByName("f24").Number() largeFieldF25 = largeMessageDesc.Fields().ByName("f25").Number() largeFieldF26 = largeMessageDesc.Fields().ByName("f26").Number() largeFieldF27 = largeMessageDesc.Fields().ByName("f27").Number() largeFieldF28 = largeMessageDesc.Fields().ByName("f28").Number() largeFieldF29 = largeMessageDesc.Fields().ByName("f29").Number() largeFieldF30 = largeMessageDesc.Fields().ByName("f30").Number() largeFieldF31 = largeMessageDesc.Fields().ByName("f31").Number() largeFieldF32 = largeMessageDesc.Fields().ByName("f32").Number() largeFieldF33 = largeMessageDesc.Fields().ByName("f33").Number() largeFieldF34 = largeMessageDesc.Fields().ByName("f34").Number() largeFieldF35 = largeMessageDesc.Fields().ByName("f35").Number() largeFieldF36 = largeMessageDesc.Fields().ByName("f36").Number() largeFieldF37 = largeMessageDesc.Fields().ByName("f37").Number() largeFieldF38 = largeMessageDesc.Fields().ByName("f38").Number() largeFieldF39 = largeMessageDesc.Fields().ByName("f39").Number() largeFieldF40 = largeMessageDesc.Fields().ByName("f40").Number() largeFieldF41 = largeMessageDesc.Fields().ByName("f41").Number() largeFieldF42 = largeMessageDesc.Fields().ByName("f42").Number() largeFieldF43 = largeMessageDesc.Fields().ByName("f43").Number() largeFieldF44 = largeMessageDesc.Fields().ByName("f44").Number() largeFieldF45 = largeMessageDesc.Fields().ByName("f45").Number() largeFieldF46 = largeMessageDesc.Fields().ByName("f46").Number() largeFieldF47 = largeMessageDesc.Fields().ByName("f47").Number() largeFieldF48 = largeMessageDesc.Fields().ByName("f48").Number() largeFieldF49 = largeMessageDesc.Fields().ByName("f49").Number() largeFieldF50 = largeMessageDesc.Fields().ByName("f50").Number() largeFieldF51 = largeMessageDesc.Fields().ByName("f51").Number() largeFieldF52 = largeMessageDesc.Fields().ByName("f52").Number() largeFieldF53 = largeMessageDesc.Fields().ByName("f53").Number() largeFieldF54 = largeMessageDesc.Fields().ByName("f54").Number() largeFieldF55 = largeMessageDesc.Fields().ByName("f55").Number() largeFieldF56 = largeMessageDesc.Fields().ByName("f56").Number() largeFieldF57 = largeMessageDesc.Fields().ByName("f57").Number() largeFieldF58 = largeMessageDesc.Fields().ByName("f58").Number() largeFieldF59 = largeMessageDesc.Fields().ByName("f59").Number() largeFieldF60 = largeMessageDesc.Fields().ByName("f60").Number() largeFieldF61 = largeMessageDesc.Fields().ByName("f61").Number() largeFieldF62 = largeMessageDesc.Fields().ByName("f62").Number() largeFieldF63 = largeMessageDesc.Fields().ByName("f63").Number() largeFieldF64 = largeMessageDesc.Fields().ByName("f64").Number() largeFieldF65 = largeMessageDesc.Fields().ByName("f65").Number() largeFieldF66 = largeMessageDesc.Fields().ByName("f66").Number() largeFieldF67 = largeMessageDesc.Fields().ByName("f67").Number() largeFieldF68 = largeMessageDesc.Fields().ByName("f68").Number() largeFieldF69 = largeMessageDesc.Fields().ByName("f69").Number() largeFieldF70 = largeMessageDesc.Fields().ByName("f70").Number() largeFieldF71 = largeMessageDesc.Fields().ByName("f71").Number() largeFieldF72 = largeMessageDesc.Fields().ByName("f72").Number() largeFieldF73 = largeMessageDesc.Fields().ByName("f73").Number() largeFieldF74 = largeMessageDesc.Fields().ByName("f74").Number() largeFieldF75 = largeMessageDesc.Fields().ByName("f75").Number() largeFieldF76 = largeMessageDesc.Fields().ByName("f76").Number() largeFieldF77 = largeMessageDesc.Fields().ByName("f77").Number() largeFieldF78 = largeMessageDesc.Fields().ByName("f78").Number() largeFieldF79 = largeMessageDesc.Fields().ByName("f79").Number() largeFieldF80 = largeMessageDesc.Fields().ByName("f80").Number() largeFieldF81 = largeMessageDesc.Fields().ByName("f81").Number() largeFieldF82 = largeMessageDesc.Fields().ByName("f82").Number() largeFieldF83 = largeMessageDesc.Fields().ByName("f83").Number() largeFieldF84 = largeMessageDesc.Fields().ByName("f84").Number() largeFieldF85 = largeMessageDesc.Fields().ByName("f85").Number() largeFieldF86 = largeMessageDesc.Fields().ByName("f86").Number() largeFieldF87 = largeMessageDesc.Fields().ByName("f87").Number() largeFieldF88 = largeMessageDesc.Fields().ByName("f88").Number() largeFieldF89 = largeMessageDesc.Fields().ByName("f89").Number() largeFieldF90 = largeMessageDesc.Fields().ByName("f90").Number() largeFieldF91 = largeMessageDesc.Fields().ByName("f91").Number() largeFieldF92 = largeMessageDesc.Fields().ByName("f92").Number() largeFieldF93 = largeMessageDesc.Fields().ByName("f93").Number() largeFieldF94 = largeMessageDesc.Fields().ByName("f94").Number() largeFieldF95 = largeMessageDesc.Fields().ByName("f95").Number() largeFieldF96 = largeMessageDesc.Fields().ByName("f96").Number() largeFieldF97 = largeMessageDesc.Fields().ByName("f97").Number() largeFieldF98 = largeMessageDesc.Fields().ByName("f98").Number() largeFieldF99 = largeMessageDesc.Fields().ByName("f99").Number() largeFieldF100 = largeMessageDesc.Fields().ByName("f100").Number() ) var ( messageDesc protoreflect.MessageDescriptor = (&testopenpb.TestAllTypes{}).ProtoReflect().Descriptor() fieldSingularInt32 = messageDesc.Fields().ByName("singular_int32").Number() fieldSingularInt64 = messageDesc.Fields().ByName("singular_int64").Number() fieldSingularUint32 = messageDesc.Fields().ByName("singular_uint32").Number() fieldSingularUint64 = messageDesc.Fields().ByName("singular_uint64").Number() fieldSingularSint32 = messageDesc.Fields().ByName("singular_sint32").Number() fieldSingularSint64 = messageDesc.Fields().ByName("singular_sint64").Number() fieldSingularFixed32 = messageDesc.Fields().ByName("singular_fixed32").Number() fieldSingularFixed64 = messageDesc.Fields().ByName("singular_fixed64").Number() fieldSingularSfixed32 = messageDesc.Fields().ByName("singular_sfixed32").Number() fieldSingularSfixed64 = messageDesc.Fields().ByName("singular_sfixed64").Number() fieldSingularFloat = messageDesc.Fields().ByName("singular_float").Number() fieldSingularDouble = messageDesc.Fields().ByName("singular_double").Number() fieldSingularBool = messageDesc.Fields().ByName("singular_bool").Number() fieldSingularString = messageDesc.Fields().ByName("singular_string").Number() fieldSingularBytes = messageDesc.Fields().ByName("singular_bytes").Number() fieldSingularNestedEnum = messageDesc.Fields().ByName("singular_nested_enum").Number() fieldSingularForeignEnum = messageDesc.Fields().ByName("singular_foreign_enum").Number() fieldSingularImportEnum = messageDesc.Fields().ByName("singular_import_enum").Number() fieldOptionalInt32 = messageDesc.Fields().ByName("optional_int32").Number() fieldOptionalInt64 = messageDesc.Fields().ByName("optional_int64").Number() fieldOptionalUint32 = messageDesc.Fields().ByName("optional_uint32").Number() fieldOptionalUint64 = messageDesc.Fields().ByName("optional_uint64").Number() fieldOptionalSint32 = messageDesc.Fields().ByName("optional_sint32").Number() fieldOptionalSint64 = messageDesc.Fields().ByName("optional_sint64").Number() fieldOptionalFixed32 = messageDesc.Fields().ByName("optional_fixed32").Number() fieldOptionalFixed64 = messageDesc.Fields().ByName("optional_fixed64").Number() fieldOptionalSfixed32 = messageDesc.Fields().ByName("optional_sfixed32").Number() fieldOptionalSfixed64 = messageDesc.Fields().ByName("optional_sfixed64").Number() fieldOptionalFloat = messageDesc.Fields().ByName("optional_float").Number() fieldOptionalDouble = messageDesc.Fields().ByName("optional_double").Number() fieldOptionalBool = messageDesc.Fields().ByName("optional_bool").Number() fieldOptionalString = messageDesc.Fields().ByName("optional_string").Number() fieldOptionalBytes = messageDesc.Fields().ByName("optional_bytes").Number() fieldOptionalGroup = messageDesc.Fields().ByName("optionalgroup").Number() fieldOptionalNestedMessage = messageDesc.Fields().ByName("optional_nested_message").Number() fieldOptionalForeignMessage = messageDesc.Fields().ByName("optional_foreign_message").Number() fieldOptionalImportMessage = messageDesc.Fields().ByName("optional_import_message").Number() fieldOptionalNestedEnum = messageDesc.Fields().ByName("optional_nested_enum").Number() fieldOptionalForeignEnum = messageDesc.Fields().ByName("optional_foreign_enum").Number() fieldOptionalImportEnum = messageDesc.Fields().ByName("optional_import_enum").Number() fieldOptionalLazyNestedMessage = messageDesc.Fields().ByName("optional_lazy_nested_message").Number() fieldNotGroupLikeDelimited = messageDesc.Fields().ByName("not_group_like_delimited").Number() fieldRepeatedInt32 = messageDesc.Fields().ByName("repeated_int32").Number() fieldRepeatedInt64 = messageDesc.Fields().ByName("repeated_int64").Number() fieldRepeatedUint32 = messageDesc.Fields().ByName("repeated_uint32").Number() fieldRepeatedUint64 = messageDesc.Fields().ByName("repeated_uint64").Number() fieldRepeatedSint32 = messageDesc.Fields().ByName("repeated_sint32").Number() fieldRepeatedSint64 = messageDesc.Fields().ByName("repeated_sint64").Number() fieldRepeatedFixed32 = messageDesc.Fields().ByName("repeated_fixed32").Number() fieldRepeatedFixed64 = messageDesc.Fields().ByName("repeated_fixed64").Number() fieldRepeatedSfixed32 = messageDesc.Fields().ByName("repeated_sfixed32").Number() fieldRepeatedSfixed64 = messageDesc.Fields().ByName("repeated_sfixed64").Number() fieldRepeatedFloat = messageDesc.Fields().ByName("repeated_float").Number() fieldRepeatedDouble = messageDesc.Fields().ByName("repeated_double").Number() fieldRepeatedBool = messageDesc.Fields().ByName("repeated_bool").Number() fieldRepeatedString = messageDesc.Fields().ByName("repeated_string").Number() fieldRepeatedBytes = messageDesc.Fields().ByName("repeated_bytes").Number() fieldRepeatedGroup = messageDesc.Fields().ByName("repeatedgroup").Number() fieldRepeatedNestedMessage = messageDesc.Fields().ByName("repeated_nested_message").Number() fieldRepeatedForeignMessage = messageDesc.Fields().ByName("repeated_foreign_message").Number() fieldRepeatedImportMessage = messageDesc.Fields().ByName("repeated_importmessage").Number() fieldRepeatedNestedEnum = messageDesc.Fields().ByName("repeated_nested_enum").Number() fieldRepeatedForeignEnum = messageDesc.Fields().ByName("repeated_foreign_enum").Number() fieldRepeatedImportEnum = messageDesc.Fields().ByName("repeated_importenum").Number() fieldMapInt32Int32 = messageDesc.Fields().ByName("map_int32_int32").Number() fieldMapInt64Int64 = messageDesc.Fields().ByName("map_int64_int64").Number() fieldMapUint32Uint32 = messageDesc.Fields().ByName("map_uint32_uint32").Number() fieldMapUint64Uint64 = messageDesc.Fields().ByName("map_uint64_uint64").Number() fieldMapSint32Sint32 = messageDesc.Fields().ByName("map_sint32_sint32").Number() fieldMapSint64Sint64 = messageDesc.Fields().ByName("map_sint64_sint64").Number() fieldMapFixed32Fixed32 = messageDesc.Fields().ByName("map_fixed32_fixed32").Number() fieldMapFixed64Fixed64 = messageDesc.Fields().ByName("map_fixed64_fixed64").Number() fieldMapSfixed32Sfixed32 = messageDesc.Fields().ByName("map_sfixed32_sfixed32").Number() fieldMapSfixed64Sfixed64 = messageDesc.Fields().ByName("map_sfixed64_sfixed64").Number() fieldMapInt32Float = messageDesc.Fields().ByName("map_int32_float").Number() fieldMapInt32Double = messageDesc.Fields().ByName("map_int32_double").Number() fieldMapBoolBool = messageDesc.Fields().ByName("map_bool_bool").Number() fieldMapStringString = messageDesc.Fields().ByName("map_string_string").Number() fieldMapStringBytes = messageDesc.Fields().ByName("map_string_bytes").Number() fieldMapStringNestedMessage = messageDesc.Fields().ByName("map_string_nested_message").Number() fieldMapStringNestedEnum = messageDesc.Fields().ByName("map_string_nested_enum").Number() fieldDefaultInt32 = messageDesc.Fields().ByName("default_int32").Number() fieldDefaultInt64 = messageDesc.Fields().ByName("default_int64").Number() fieldDefaultUint32 = messageDesc.Fields().ByName("default_uint32").Number() fieldDefaultUint64 = messageDesc.Fields().ByName("default_uint64").Number() fieldDefaultSint32 = messageDesc.Fields().ByName("default_sint32").Number() fieldDefaultSint64 = messageDesc.Fields().ByName("default_sint64").Number() fieldDefaultFixed32 = messageDesc.Fields().ByName("default_fixed32").Number() fieldDefaultFixed64 = messageDesc.Fields().ByName("default_fixed64").Number() fieldDefaultSfixed32 = messageDesc.Fields().ByName("default_sfixed32").Number() fieldDefaultSfixed64 = messageDesc.Fields().ByName("default_sfixed64").Number() fieldDefaultFloat = messageDesc.Fields().ByName("default_float").Number() fieldDefaultDouble = messageDesc.Fields().ByName("default_double").Number() fieldDefaultBool = messageDesc.Fields().ByName("default_bool").Number() fieldDefaultString = messageDesc.Fields().ByName("default_string").Number() fieldDefaultBytes = messageDesc.Fields().ByName("default_bytes").Number() fieldDefaultNestedEnum = messageDesc.Fields().ByName("default_nested_enum").Number() fieldDefaultForeignEnum = messageDesc.Fields().ByName("default_foreign_enum").Number() fieldOneofUint32 = messageDesc.Fields().ByName("oneof_uint32").Number() fieldOneofNestedMessage = messageDesc.Fields().ByName("oneof_nested_message").Number() fieldOneofString = messageDesc.Fields().ByName("oneof_string").Number() fieldOneofBytes = messageDesc.Fields().ByName("oneof_bytes").Number() fieldOneofBool = messageDesc.Fields().ByName("oneof_bool").Number() fieldOneofUint64 = messageDesc.Fields().ByName("oneof_uint64").Number() fieldOneofFloat = messageDesc.Fields().ByName("oneof_float").Number() fieldOneofDouble = messageDesc.Fields().ByName("oneof_double").Number() fieldOneofEnum = messageDesc.Fields().ByName("oneof_enum").Number() fieldOneofGroup = messageDesc.Fields().ByName("oneofgroup").Number() fieldOneofOptionalUint32 = messageDesc.Fields().ByName("oneof_optional_uint32").Number() ) // testMessageType is an implementation of protoreflect.MessageType. type testMessageType struct { protoreflect.MessageDescriptor new func() protoreflect.Message } func (m *testMessageType) New() protoreflect.Message { return m.new() } func (m *testMessageType) Zero() protoreflect.Message { return m.new() } func (m *testMessageType) GoType() reflect.Type { panic("unimplemented") } func (m *testMessageType) Descriptor() protoreflect.MessageDescriptor { return m.MessageDescriptor } // testProtoMessage adapts the concrete API for a message to the ProtoReflect interface. type testProtoMessage struct { m protoreflect.ProtoMessage md protoreflect.MessageDescriptor new func() protoreflect.Message has func(protoreflect.FieldNumber) bool get func(protoreflect.FieldNumber) any set func(protoreflect.FieldNumber, any) clear func(protoreflect.FieldNumber) } func (m *testProtoMessage) ProtoReflect() protoreflect.Message { return (*testMessage)(m) } // testMessage implements protoreflect.Message. type testMessage testProtoMessage func (m *testMessage) Interface() protoreflect.ProtoMessage { return (*testProtoMessage)(m) } func (m *testMessage) ProtoMethods() *protoiface.Methods { return nil } func (m *testMessage) Descriptor() protoreflect.MessageDescriptor { return m.md } func (m *testMessage) Type() protoreflect.MessageType { return &testMessageType{m.md, m.new} } func (m *testMessage) New() protoreflect.Message { return m.new() } func (m *testMessage) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { fields := m.md.Fields() for i := 0; i < fields.Len(); i++ { fd := fields.Get(i) if !m.Has(fd) { continue } if !f(fd, m.Get(fd)) { break } } } func (m *testMessage) Has(fd protoreflect.FieldDescriptor) bool { return m.has(fd.Number()) } func (m *testMessage) Clear(fd protoreflect.FieldDescriptor) { m.clear(fd.Number()) } func (m *testMessage) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { num := fd.Number() switch { case fd.IsMap(): if !m.has(num) { return protoreflect.ValueOfMap(&testMap{reflect.Zero(reflect.TypeOf(m.get(num))), fd}) } return protoreflect.ValueOfMap(&testMap{reflect.ValueOf(m.get(num)), fd}) case fd.IsList(): if !m.has(num) { return protoreflect.ValueOfList(&zeroList{reflect.TypeOf(m.get(num)).Elem(), fd}) } return protoreflect.ValueOfList(&testList{m: (*testProtoMessage)(m), fd: fd}) case fd.Message() != nil: if !m.has(fd.Number()) { return protoreflect.Value{} } } return singularValueOf(m.get(num)) } func (m *testMessage) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { num := fd.Number() switch { case fd.IsMap(): if !v.Map().IsValid() { panic("set with invalid map") } m.set(num, v.Map().(*testMap).val.Interface()) case fd.IsList(): if !v.List().IsValid() { panic("set with invalid list") } m.set(num, v.List().(*testList).field().Interface()) case fd.Message() != nil: i := v.Message().Interface() if p, ok := i.(*testProtoMessage); ok { i = p.m } m.set(num, i) default: m.set(num, v.Interface()) } } func (m *testMessage) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { num := fd.Number() if !m.Has(fd) && (fd.IsMap() || fd.IsList() || fd.Message() != nil) { switch { case fd.IsMap(): typ := reflect.ValueOf(m.get(num)).Type() m.set(num, reflect.MakeMap(typ).Interface()) return protoreflect.ValueOfMap(&testMap{reflect.ValueOf(m.get(num)), fd}) case fd.IsList(): return protoreflect.ValueOfList(&testList{m: (*testProtoMessage)(m), fd: fd}) case fd.Message() != nil: typ := reflect.ValueOf(m.get(num)).Type() m.set(num, reflect.New(typ.Elem()).Interface()) } } return m.Get(fd) } func (m *testMessage) NewMessage(fd protoreflect.FieldDescriptor) protoreflect.Message { return singularValueOf(m.NewField(fd)).Message() } func (m *testMessage) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { num := fd.Number() switch { case fd.IsMap(): typ := reflect.ValueOf(m.get(num)).Type() return protoreflect.ValueOf(&testMap{reflect.MakeMap(typ), fd}) case fd.IsList(): typ := reflect.ValueOf(m.get(num)).Type() return protoreflect.ValueOf(&testList{val: reflect.Zero(typ), fd: fd}) case fd.Message() != nil: typ := reflect.ValueOf(m.get(num)).Type() return singularValueOf(reflect.New(typ.Elem()).Interface()) default: // Obtain the default value of the field by creating an empty message // and calling the getter. n := m.new().(*testMessage) return singularValueOf(n.get(num)) } } func (m *testMessage) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { for i := 0; i < od.Fields().Len(); i++ { fd := od.Fields().Get(i) if m.has(fd.Number()) { return fd } } return nil } func (m *testMessage) GetUnknown() protoreflect.RawFields { return m.m.ProtoReflect().GetUnknown() } func (m *testMessage) SetUnknown(raw protoreflect.RawFields) { m.m.ProtoReflect().SetUnknown(raw) } func (m *testMessage) IsValid() bool { return !reflect.ValueOf(m.m).IsNil() } func singularValueOf(v any) protoreflect.Value { switch v := v.(type) { case protoreflect.ProtoMessage: return protoreflect.ValueOf(v.ProtoReflect()) case protoreflect.Enum: return protoreflect.ValueOf(v.Number()) default: return protoreflect.ValueOf(v) } } // testList implements protoreflect.List over a concrete slice of values. type testList struct { m *testProtoMessage val reflect.Value fd protoreflect.FieldDescriptor } func (x *testList) field() reflect.Value { if x.m == nil { return x.val } return reflect.ValueOf(x.m.get(x.fd.Number())) } func (x *testList) setField(v reflect.Value) { if x.m == nil { x.val = v return } x.m.set(x.fd.Number(), v.Interface()) } func (x *testList) Len() int { return x.field().Len() } func (x *testList) Get(n int) protoreflect.Value { return singularValueOf(x.field().Index(n).Interface()) } func (x *testList) Set(n int, v protoreflect.Value) { switch x.fd.Kind() { case protoreflect.MessageKind, protoreflect.GroupKind: x.field().Index(n).Set(reflect.ValueOf(v.Message().Interface())) case protoreflect.EnumKind: x.field().Index(n).SetInt(int64(v.Enum())) default: x.field().Index(n).Set(reflect.ValueOf(v.Interface())) } } func (x *testList) Append(v protoreflect.Value) { f := x.field() x.setField(reflect.Append(f, reflect.Zero(f.Type().Elem()))) x.Set(f.Len(), v) } func (x *testList) AppendMutable() protoreflect.Value { if x.fd.Message() == nil { panic("invalid AppendMutable on list with non-message value type") } v := x.NewElement() x.Append(v) return v } func (x *testList) Truncate(n int) { x.setField(x.field().Slice(0, n)) } func (x *testList) NewMessage() protoreflect.Message { return x.NewElement().Message() } func (x *testList) NewElement() protoreflect.Value { // For enums, List.NewElement returns the first enum value. if ee := newEnumElement(x.fd); ee.IsValid() { return ee } var v reflect.Value typ := x.field().Type().Elem() if typ.Kind() == reflect.Ptr { v = reflect.New(typ.Elem()) } else { v = reflect.Zero(typ) } return singularValueOf(v.Interface()) } func (x *testList) IsValid() bool { return true } func newEnumElement(fd protoreflect.FieldDescriptor) protoreflect.Value { if fd.Kind() != protoreflect.EnumKind { return protoreflect.Value{} } if val := fd.Enum().Values(); val.Len() > 0 { return protoreflect.ValueOfEnum(val.Get(0).Number()) } return protoreflect.Value{} } // testList implements protoreflect.List over a concrete slice of values. type zeroList struct { typ reflect.Type fd protoreflect.FieldDescriptor } func (x *zeroList) Len() int { return 0 } func (x *zeroList) Get(n int) protoreflect.Value { panic("get on zero list") } func (x *zeroList) Set(n int, v protoreflect.Value) { panic("set on zero list") } func (x *zeroList) Append(v protoreflect.Value) { panic("append on zero list") } func (x *zeroList) AppendMutable() protoreflect.Value { panic("append on zero list") } func (x *zeroList) Truncate(n int) { panic("truncate on zero list") } func (x *zeroList) NewMessage() protoreflect.Message { return x.NewElement().Message() } func (x *zeroList) NewElement() protoreflect.Value { // For enums, List.NewElement returns the first enum value. if ee := newEnumElement(x.fd); ee.IsValid() { return ee } var v reflect.Value if x.typ.Kind() == reflect.Ptr { v = reflect.New(x.typ.Elem()) } else { v = reflect.Zero(x.typ) } return singularValueOf(v.Interface()) } func (x *zeroList) IsValid() bool { return false } // testMap implements a protoreflect.Map over a concrete map. type testMap struct { val reflect.Value fd protoreflect.FieldDescriptor } func (x *testMap) key(k protoreflect.MapKey) reflect.Value { return reflect.ValueOf(k.Interface()) } func (x *testMap) valueToProto(v reflect.Value) protoreflect.Value { if !v.IsValid() { return protoreflect.Value{} } switch x.fd.Message().Fields().ByNumber(2).Kind() { case protoreflect.MessageKind, protoreflect.GroupKind: return protoreflect.ValueOf(v.Interface().(protoreflect.ProtoMessage).ProtoReflect()) case protoreflect.EnumKind: return protoreflect.ValueOf(protoreflect.EnumNumber(v.Int())) default: return protoreflect.ValueOf(v.Interface()) } } func (x *testMap) Len() int { return x.val.Len() } func (x *testMap) Has(k protoreflect.MapKey) bool { return x.val.MapIndex(x.key(k)).IsValid() } func (x *testMap) Get(k protoreflect.MapKey) protoreflect.Value { return x.valueToProto(x.val.MapIndex(x.key(k))) } func (x *testMap) Set(k protoreflect.MapKey, v protoreflect.Value) { f := x.val switch x.fd.MapValue().Kind() { case protoreflect.MessageKind, protoreflect.GroupKind: f.SetMapIndex(x.key(k), reflect.ValueOf(v.Message().Interface())) case protoreflect.EnumKind: rv := reflect.New(f.Type().Elem()).Elem() rv.SetInt(int64(v.Enum())) f.SetMapIndex(x.key(k), rv) default: f.SetMapIndex(x.key(k), reflect.ValueOf(v.Interface())) } } func (x *testMap) Mutable(k protoreflect.MapKey) protoreflect.Value { if x.fd.MapValue().Message() == nil { panic("invalid Mutable on map with non-message value type") } v := x.Get(k) if !v.IsValid() { v = x.NewValue() x.Set(k, v) } return v } func (x *testMap) Clear(k protoreflect.MapKey) { x.val.SetMapIndex(x.key(k), reflect.Value{}) } func (x *testMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { iter := x.val.MapRange() for iter.Next() { if !f(protoreflect.ValueOf(iter.Key().Interface()).MapKey(), x.valueToProto(iter.Value())) { return } } } func (x *testMap) NewMessage() protoreflect.Message { return x.NewValue().Message() } func (x *testMap) NewValue() protoreflect.Value { var v reflect.Value if x.fd.MapValue().Message() != nil { v = reflect.New(x.val.Type().Elem().Elem()) } else { v = reflect.Zero(x.val.Type().Elem()) } return singularValueOf(v.Interface()) } func (x *testMap) IsValid() bool { return !x.val.IsNil() } // A shadow message is a wrapper around two protoreflect.Message implementations // presenting different views of the same underlying data. Read operations // are directed to one implementation and write operations to the other. // shadowProtoMessage implements protoreflect.ProtoMessage as a shadow. type shadowProtoMessage struct { get, set protoreflect.Message new func() (get, set protoreflect.ProtoMessage) } func newShadow(newf func() (get, set protoreflect.ProtoMessage)) protoreflect.ProtoMessage { get, set := newf() return &shadowProtoMessage{ get.ProtoReflect(), set.ProtoReflect(), newf, } } func (m *shadowProtoMessage) ProtoReflect() protoreflect.Message { return (*shadowMessage)(m) } // shadowMessage implements protoreflect.Message as a shadow. type shadowMessage shadowProtoMessage func (m *shadowMessage) Interface() protoreflect.ProtoMessage { return (*shadowProtoMessage)(m) } func (m *shadowMessage) ProtoMethods() *protoiface.Methods { return nil } func (m *shadowMessage) Descriptor() protoreflect.MessageDescriptor { return m.get.Descriptor() } func (m *shadowMessage) Type() protoreflect.MessageType { return &testMessageType{m.Descriptor(), m.New} } func (m *shadowMessage) New() protoreflect.Message { get, set := m.new() return &shadowMessage{ get: get.ProtoReflect(), set: set.ProtoReflect(), new: m.new, } } // TODO: Implement these. func (m *shadowMessage) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { m.get.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { return f(fd, m.Get(fd)) }) } func (m *shadowMessage) Has(fd protoreflect.FieldDescriptor) bool { return m.get.Has(fd) } func (m *shadowMessage) Clear(fd protoreflect.FieldDescriptor) { m.set.Clear(fd) } func (m *shadowMessage) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { v := m.get.Get(fd) switch { case fd.IsList(): return protoreflect.ValueOfList(&shadowList{v.List(), m.set.Get(fd).List()}) case fd.IsMap(): return protoreflect.ValueOfMap(&shadowMap{v.Map(), m.set.Get(fd).Map()}) default: return v } } func (m *shadowMessage) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { switch x := v.Interface().(type) { case *shadowList: m.set.Set(fd, protoreflect.ValueOf(x.set)) case *shadowMap: m.set.Set(fd, protoreflect.ValueOf(x.set)) default: m.set.Set(fd, v) } } func (m *shadowMessage) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { v := m.get.Mutable(fd) switch { case fd.IsList(): return protoreflect.ValueOf(&shadowList{v.List(), m.set.Mutable(fd).List()}) case fd.IsMap(): return protoreflect.ValueOf(&shadowMap{v.Map(), m.set.Mutable(fd).Map()}) default: return v } } func (m *shadowMessage) NewMessage(fd protoreflect.FieldDescriptor) protoreflect.Message { return m.NewField(fd).Message() } func (m *shadowMessage) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { return m.set.NewField(fd) } func (m *shadowMessage) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { return m.get.WhichOneof(od) } func (m *shadowMessage) GetUnknown() protoreflect.RawFields { return m.get.GetUnknown() } func (m *shadowMessage) SetUnknown(raw protoreflect.RawFields) { m.set.SetUnknown(raw) } func (m *shadowMessage) IsValid() bool { return m.get.IsValid() } // shadowList implements protoreflect.List as a shadow. type shadowList struct { get, set protoreflect.List } func (x *shadowList) Len() int { return x.get.Len() } func (x *shadowList) Get(n int) protoreflect.Value { return x.get.Get(n) } func (x *shadowList) Set(n int, v protoreflect.Value) { x.set.Set(n, v) } func (x *shadowList) Append(v protoreflect.Value) { x.set.Append(v) } func (x *shadowList) AppendMutable() protoreflect.Value { return x.set.AppendMutable() } func (x *shadowList) Truncate(n int) { x.set.Truncate(n) } func (x *shadowList) NewMessage() protoreflect.Message { return x.set.NewElement().Message() } func (x *shadowList) NewElement() protoreflect.Value { return x.set.NewElement() } func (x *shadowList) IsValid() bool { return x.get.IsValid() } // shadowMap implements protoreflect.Map as a shadow. type shadowMap struct { get, set protoreflect.Map } func (x *shadowMap) Len() int { return x.get.Len() } func (x *shadowMap) Has(k protoreflect.MapKey) bool { return x.get.Has(k) } func (x *shadowMap) Get(k protoreflect.MapKey) protoreflect.Value { return x.get.Get(k) } func (x *shadowMap) Set(k protoreflect.MapKey, v protoreflect.Value) { x.set.Set(k, v) } func (x *shadowMap) Mutable(k protoreflect.MapKey) protoreflect.Value { return x.set.Mutable(k) } func (x *shadowMap) Clear(k protoreflect.MapKey) { x.set.Clear(k) } func (x *shadowMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { x.get.Range(f) } func (x *shadowMap) NewMessage() protoreflect.Message { return x.set.NewValue().Message() } func (x *shadowMap) NewValue() protoreflect.Value { return x.set.NewValue() } func (x *shadowMap) IsValid() bool { return x.get.IsValid() }