From 0e932930c8ae29f8785d0e646524f37b2a16375c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 15 May 2024 10:47:18 +0200 Subject: [PATCH] internal/impl: enable fully lazy extensions (over Size and Marshal) Extensions will be kept in wire format over proto.Size and proto.Marshal. This change is a significant performance optimization for jobs that read and write Protobuf messages of the same type, but do not need to process extensions. This change is based on work by Patrik Nyblom. Note that the proto.Size semantics for lazy messages might be surprising; see https://protobuf.dev/reference/go/size/ for details. We have been running this change for about two weeks in Google, all known breakages have already been addressed with CL 579995. related to golang/protobuf#1609 Change-Id: I16be78d15304d775bb30e76356a1a61d61300b43 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/580015 Reviewed-by: Lasse Folger Auto-Submit: Michael Stapelberg LUCI-TryBot-Result: Go LUCI --- internal/impl/checkinit.go | 2 +- internal/impl/codec_extension.go | 22 + internal/impl/codec_messageset.go | 22 + internal/impl/encode.go | 30 + internal/impl/lazy_normalized_test.go | 88 ++ internal/impl/lazy_test.go | 569 ++++++++++++ internal/impl/message_reflect.go | 4 + .../lazy_extension_normalized_wire_test.pb.go | 322 +++++++ .../lazy_extension_normalized_wire_test.proto | 28 + .../testprotos/lazy/lazy_extension_test.pb.go | 860 ++++++++++++++++++ .../testprotos/lazy/lazy_extension_test.proto | 80 ++ 11 files changed, 2026 insertions(+), 1 deletion(-) create mode 100644 internal/impl/lazy_normalized_test.go create mode 100644 internal/testprotos/lazy/lazy_extension_normalized_wire_test.pb.go create mode 100644 internal/testprotos/lazy/lazy_extension_normalized_wire_test.proto create mode 100644 internal/testprotos/lazy/lazy_extension_test.pb.go create mode 100644 internal/testprotos/lazy/lazy_extension_test.proto diff --git a/internal/impl/checkinit.go b/internal/impl/checkinit.go index bff041edc..f29e6a8fa 100644 --- a/internal/impl/checkinit.go +++ b/internal/impl/checkinit.go @@ -68,7 +68,7 @@ func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error { } for _, x := range *ext { ei := getExtensionFieldInfo(x.Type()) - if ei.funcs.isInit == nil { + if ei.funcs.isInit == nil || x.isUnexpandedLazy() { continue } v := x.Value() diff --git a/internal/impl/codec_extension.go b/internal/impl/codec_extension.go index 2b8f122c2..4bb0a7a20 100644 --- a/internal/impl/codec_extension.go +++ b/internal/impl/codec_extension.go @@ -99,6 +99,28 @@ func (f *ExtensionField) canLazy(xt protoreflect.ExtensionType) bool { return false } +// isUnexpandedLazy returns true if the ExensionField is lazy and not +// yet expanded, which means it's present and already checked for +// initialized required fields. +func (f *ExtensionField) isUnexpandedLazy() bool { + return f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 +} + +// lazyBuffer retrieves the buffer for a lazy extension if it's not yet expanded. +// +// The returned buffer has to be kept over whatever operation we're planning, +// as re-retrieving it will fail after the message is lazily decoded. +func (f *ExtensionField) lazyBuffer() []byte { + // This function might be in the critical path, so check the atomic without + // taking a look first, then only take the lock if needed. + if !f.isUnexpandedLazy() { + return nil + } + f.lazy.mu.Lock() + defer f.lazy.mu.Unlock() + return f.lazy.b +} + func (f *ExtensionField) lazyInit() { f.lazy.mu.Lock() defer f.lazy.mu.Unlock() diff --git a/internal/impl/codec_messageset.go b/internal/impl/codec_messageset.go index b7a23faf1..7a16ec13d 100644 --- a/internal/impl/codec_messageset.go +++ b/internal/impl/codec_messageset.go @@ -26,6 +26,15 @@ func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int) } num, _ := protowire.DecodeTag(xi.wiretag) size += messageset.SizeField(num) + if fullyLazyExtensions(opts) { + // Don't expand the extension, instead use the buffer to calculate size + if lb := x.lazyBuffer(); lb != nil { + // We got hold of the buffer, so it's still lazy. + // Don't count the tag size in the extension buffer, it's already added. + size += protowire.SizeTag(messageset.FieldMessage) + len(lb) - xi.tagsize + continue + } + } size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts) } @@ -85,6 +94,19 @@ func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts ma xi := getExtensionFieldInfo(x.Type()) num, _ := protowire.DecodeTag(xi.wiretag) b = messageset.AppendFieldStart(b, num) + + if fullyLazyExtensions(opts) { + // Don't expand the extension if it's still in wire format, instead use the buffer content. + if lb := x.lazyBuffer(); lb != nil { + // The tag inside the lazy buffer is a different tag (the extension + // number), but what we need here is the tag for FieldMessage: + b = protowire.AppendVarint(b, protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType)) + b = append(b, lb[xi.tagsize:]...) + b = messageset.AppendFieldEnd(b) + return b, nil + } + } + b, err := xi.funcs.marshal(b, x.Value(), protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType), opts) if err != nil { return b, err diff --git a/internal/impl/encode.go b/internal/impl/encode.go index 845c67d6e..7769a54e6 100644 --- a/internal/impl/encode.go +++ b/internal/impl/encode.go @@ -149,6 +149,14 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt return b, nil } +// fullyLazyExtensions returns true if we should attempt to keep extensions lazy over size and marshal. +func fullyLazyExtensions(opts marshalOptions) bool { + // When deterministic marshaling is requested, force an unmarshal for lazy + // extensions to produce a deterministic result, instead of passing through + // bytes lazily that may or may not match what Go Protobuf would produce. + return opts.flags&piface.MarshalDeterministic == 0 +} + func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) { if ext == nil { return 0 @@ -158,6 +166,14 @@ func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marsha if xi.funcs.size == nil { continue } + if fullyLazyExtensions(opts) { + // Don't expand the extension, instead use the buffer to calculate size + if lb := x.lazyBuffer(); lb != nil { + // We got hold of the buffer, so it's still lazy. + n += len(lb) + continue + } + } n += xi.funcs.size(x.Value(), xi.tagsize, opts) } return n @@ -176,6 +192,13 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, var err error for _, x := range *ext { xi := getExtensionFieldInfo(x.Type()) + if fullyLazyExtensions(opts) { + // Don't expand the extension if it's still in wire format, instead use the buffer content. + if lb := x.lazyBuffer(); lb != nil { + b = append(b, lb...) + continue + } + } b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) } return b, err @@ -191,6 +214,13 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, for _, k := range keys { x := (*ext)[int32(k)] xi := getExtensionFieldInfo(x.Type()) + if fullyLazyExtensions(opts) { + // Don't expand the extension if it's still in wire format, instead use the buffer content. + if lb := x.lazyBuffer(); lb != nil { + b = append(b, lb...) + continue + } + } b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) if err != nil { return b, err diff --git a/internal/impl/lazy_normalized_test.go b/internal/impl/lazy_normalized_test.go new file mode 100644 index 000000000..0b80e1e90 --- /dev/null +++ b/internal/impl/lazy_normalized_test.go @@ -0,0 +1,88 @@ +// 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 impl_test + +import ( + "testing" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protopack" + + lazytestpb "google.golang.org/protobuf/internal/testprotos/lazy" +) + +// Constructs a message encoded in denormalized (non-minimal) wire format, but +// using two levels of nesting: A top-level message with a child message which +// in turn has a grandchild message. +func denormalizedTwoLevel(t *testing.T) ([]byte, *lazytestpb.Top, error) { + // Construct a message with denormalized (non-minimal) wire format: + // 1. Encode a top-level message with submessage B (ext) + C (field) + // 2. Replace the encoding of submessage C (field) with + // another instance of submessage B (ext) + // + // This modification of the wire format is spec'd in Protobuf: + // https://github.com/protocolbuffers/protobuf/issues/9257 + grandchild := &lazytestpb.Sub{} + proto.SetExtension(grandchild, lazytestpb.E_Ext_B, &lazytestpb.Ext{ + SomeFlag: proto.Bool(true), + }) + expectedMessage := &lazytestpb.Top{ + Child: &lazytestpb.Sub{ + Grandchild: grandchild, + }, + A: proto.Uint32(2342), + } + + fullMessage := protopack.Message{ + protopack.Tag{1, protopack.VarintType}, protopack.Varint(2342), + // Child + protopack.Tag{2, protopack.BytesType}, protopack.LengthPrefix(protopack.Message{ + // Grandchild + protopack.Tag{4, protopack.BytesType}, protopack.LengthPrefix(protopack.Message{ + // The first occurrence of B matches expectedMessage: + protopack.Tag{2, protopack.BytesType}, protopack.LengthPrefix(protopack.Message{ + protopack.Tag{1, protopack.VarintType}, protopack.Varint(1), + }), + // This second duplicative occurrence of B is spec'd in Protobuf: + // https://github.com/protocolbuffers/protobuf/issues/9257 + protopack.Tag{2, protopack.BytesType}, protopack.LengthPrefix(protopack.Message{ + protopack.Tag{1, protopack.VarintType}, protopack.Varint(1), + }), + }), + }), + }.Marshal() + + return fullMessage, expectedMessage, nil +} + +func TestNoInvalidWireFormatWithDeterministicLazy(t *testing.T) { + fullMessage, _, err := denormalizedTwoLevel(t) + if err != nil { + t.Fatal(err) + } + + top := &lazytestpb.Top{} + if err := proto.Unmarshal(fullMessage, top); err != nil { + t.Fatal(err) + } + + // Requesting deterministic marshaling should result in unmarshaling (and + // thereby normalizing the non-minimal encoding) when sizing. + // + // If the deterministic flag is dropped (like before cl/624951104), the size + // cache is populated with the non-minimal size. The Marshal call below + // lazily unmarshals (due to the Deterministic flag), which includes + // normalization, and will then report a size mismatch error (instead of + // producing invalid wire format). + proto.MarshalOptions{Deterministic: true}.Size(top) + + _, err = proto.MarshalOptions{ + Deterministic: true, + UseCachedSize: true, + }.Marshal(top) + if err != nil { + t.Fatal(err) + } +} diff --git a/internal/impl/lazy_test.go b/internal/impl/lazy_test.go index 3a52f874b..0c06808a9 100644 --- a/internal/impl/lazy_test.go +++ b/internal/impl/lazy_test.go @@ -5,13 +5,21 @@ package impl_test import ( + "reflect" + "sync" "testing" + "unsafe" + "github.com/google/go-cmp/cmp" + "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/impl" "google.golang.org/protobuf/internal/protobuild" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" + lazytestpb "google.golang.org/protobuf/internal/testprotos/lazy" + "google.golang.org/protobuf/internal/testprotos/messageset/messagesetpb" testpb "google.golang.org/protobuf/internal/testprotos/test" ) @@ -50,3 +58,564 @@ func TestLazyExtensions(t *testing.T) { } checkLazy("after unmarshal", m, flags.LazyUnmarshalExtensions) } + +func TestMessageSetLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + h := &lazytestpb.Holder{Data: &messagesetpb.MessageSet{}} + + ext := &lazytestpb.Rabbit{Name: proto.String("Judy")} + proto.SetExtension(h.GetData(), lazytestpb.E_Rabbit_MessageSetExtension, ext) + + nh := roundtrip(t, h).(*lazytestpb.Holder) + + if extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + + proto.Size(nh) + if extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field) { + t.Errorf("Extension unexpectedly initialized after Size") + } + + proto.Marshal(nh) + if extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field) { + t.Errorf("Extension unexpectedly initialized after Marshal") + } + + if !proto.HasExtension(nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension) { + t.Fatalf("Can't get extension") + } + if extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field) { + t.Errorf("Extension unexpectedly initialized after Has") + } + + nh = roundtrip(t, nh).(*lazytestpb.Holder) + if extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field) { + t.Errorf("Extension unexpectedly initialized after Has") + } + + if diff := cmp.Diff(h, nh, protocmp.Transform()); diff != "" { + t.Errorf("Got %+v, want %+v, diff:\n%s", nh, h, diff) + } + if got, want := extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Diff") + } + int := proto.GetExtension(nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension).(*lazytestpb.Rabbit) + if int.GetName() != "Judy" { + t.Errorf("Extension value \"Judy\" not retained, got: %v", int.GetName()) + } + if got, want := extensionIsInitialized(t, nh.GetData(), lazytestpb.E_Rabbit_MessageSetExtension.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } +} + +var ( + // Trees are fully lazy + treeTemplate = &lazytestpb.Tree{ + Eucalyptus: proto.Bool(true), + } + + spGH = lazytestpb.FlyingFoxSpecies_GREY_HEADED + spP = lazytestpb.FlyingFoxSpecies_SPECTACLED + spLE = lazytestpb.FlyingFoxSpecies_LARGE_EARED + spBB = lazytestpb.FlyingFoxSpecies_BARE_BACKED + spF = lazytestpb.PipistrelleSpecies_FOREST + spR = lazytestpb.PipistrelleSpecies_RUSTY +) + +func TestExtensionLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + tree := proto.Clone(treeTemplate) + proto.SetExtension(tree, lazytestpb.E_Bat, &lazytestpb.FlyingFox{Species: &spGH}) + proto.SetExtension(tree, lazytestpb.E_BatPup, &lazytestpb.FlyingFox{Species: &spP}) + + nt := roundtrip(t, tree).(*lazytestpb.Tree) + + if extensionIsInitialized(t, nt, lazytestpb.E_Bat.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + proto.Size(nt) + if extensionIsInitialized(t, nt, lazytestpb.E_Bat.Field) { + t.Errorf("Extension unexpectedly initialized after Size") + } + + gb, err := proto.Marshal(nt) + if err != nil { + t.Fatalf("proto.Marshal(%+v) failed: %v", nt, err) + } + if extensionIsInitialized(t, nt, lazytestpb.E_Bat.Field) { + t.Errorf("Extension unexpectedly initialized after Marshal") + } + + fox := proto.GetExtension(nt, lazytestpb.E_Bat).(*lazytestpb.FlyingFox) + if got, want := fox.GetSpecies(), spGH; want != got { + t.Errorf("Extension's Speices field not retained, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, nt, lazytestpb.E_Bat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + if extensionIsInitialized(t, nt, lazytestpb.E_BatPup.Field) { + t.Errorf("Extension unexpectedly initialized after Get") + } + foxPup := proto.GetExtension(nt, lazytestpb.E_BatPup).(*lazytestpb.FlyingFox) + if got, want := foxPup.GetSpecies(), spP; want != got { + t.Errorf("Extension's Speices field not retained, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, nt, lazytestpb.E_Bat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + if got, want := extensionIsInitialized(t, nt, lazytestpb.E_BatPup.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + + rt := &lazytestpb.Tree{} + if err := proto.Unmarshal(gb, rt); err != nil { + t.Fatalf("Can't unmarshal pb.Tree: %v", err) + } + + if diff := cmp.Diff(tree, rt, protocmp.Transform()); diff != "" { + t.Errorf("Got %+v, want %+v, diff:\n%s", rt, tree, diff) + } + if got, want := extensionIsInitialized(t, rt, lazytestpb.E_Bat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Diff") + } + + nt = roundtrip(t, tree).(*lazytestpb.Tree) + + proto.ClearExtension(nt, lazytestpb.E_Bat) + proto.ClearExtension(nt, lazytestpb.E_BatPup) + if proto.HasExtension(nt, lazytestpb.E_Bat) { + t.Fatalf("Extension not cleared in (%+v)", nt) + } + if proto.HasExtension(nt, lazytestpb.E_BatPup) { + t.Fatalf("Extension not cleared in (%+v)", nt) + } +} + +func TestExtensionNestedScopeLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + tree := proto.Clone(treeTemplate) + + proto.SetExtension(tree, lazytestpb.E_BatNest_Bat, &lazytestpb.FlyingFox{Species: &spGH}) + + nt := roundtrip(t, tree).(*lazytestpb.Tree) + + if extensionIsInitialized(t, nt, lazytestpb.E_BatNest_Bat.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + proto.Size(nt) + if extensionIsInitialized(t, nt, lazytestpb.E_BatNest_Bat.Field) { + t.Errorf("Extension unexpectedly initialized after Size") + } + + gb, err := proto.Marshal(nt) + if err != nil { + t.Fatalf("proto.Marshal(%+v) failed: %v", nt, err) + } + if extensionIsInitialized(t, nt, lazytestpb.E_BatNest_Bat.Field) { + t.Errorf("Extension unexpectedly initialized after Marshal") + } + + fox := proto.GetExtension(nt, lazytestpb.E_BatNest_Bat).(*lazytestpb.FlyingFox) + if got, want := fox.GetSpecies(), spGH; want != got { + t.Errorf("Extension's Speices field not retained, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, nt, lazytestpb.E_BatNest_Bat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + + rt := &lazytestpb.Tree{} + if err := proto.Unmarshal(gb, rt); err != nil { + t.Fatalf("Can't unmarshal pb.Tree: %v", err) + } + + if diff := cmp.Diff(tree, rt, protocmp.Transform()); diff != "" { + t.Errorf("Got %+v, want %+v, diff:\n%s", rt, tree, diff) + } + if got, want := extensionIsInitialized(t, rt, lazytestpb.E_BatNest_Bat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Diff") + } +} + +func TestExtensionRepeatedMessageLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + posse := []*lazytestpb.FlyingFox{ + {Species: &spLE}, + {Species: &spBB}, + } + m := proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_BatPosse, posse) + if got, want := proto.HasExtension(m, lazytestpb.E_BatPosse), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr := roundtrip(t, m).(*lazytestpb.Tree) + + if extensionIsInitialized(t, mr, lazytestpb.E_BatPosse.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + + mrr := roundtrip(t, mr).(*lazytestpb.Tree) + if got, want := proto.HasExtension(mrr, lazytestpb.E_BatPosse), true; got != want { + t.Errorf("Extension is not present after setting: got %v, want %v", got, want) + } + + if extensionIsInitialized(t, mrr, lazytestpb.E_BatPosse.Field) { + t.Errorf("Extension unexpectedly initialized after Has") + } + + mrr = roundtrip(t, mr).(*lazytestpb.Tree) + foxPosse := proto.GetExtension(mrr, lazytestpb.E_BatPosse).([]*lazytestpb.FlyingFox) + if got, want := foxPosse[0].GetSpecies(), spLE; got != want { + t.Errorf("Extension's Speices field, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_BatPosse.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + + // Set to empty slice instead + m = proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_BatPosse, []*lazytestpb.FlyingFox{}) + if got, want := proto.HasExtension(m, lazytestpb.E_BatPosse), false; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr = roundtrip(t, m).(*lazytestpb.Tree) + + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_BatPosse.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + + if got, want := proto.HasExtension(mr, lazytestpb.E_BatPosse), false; got != want { + t.Errorf("Extension is not present after setting: got %v, want %v", got, want) + } + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_BatPosse.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Has") + } + + mrr = roundtrip(t, mr).(*lazytestpb.Tree) + if got, want := proto.HasExtension(mrr, lazytestpb.E_BatPosse), false; got != want { + t.Errorf("Extension is not present after setting: got %v, want %v", got, want) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_BatPosse.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Has") + } + + foxPosse = proto.GetExtension(mrr, lazytestpb.E_BatPosse).([]*lazytestpb.FlyingFox) + if got, want := len(foxPosse), 0; got != want { + t.Errorf("Extension field length, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_BatPosse.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } +} + +func TestExtensionIntegerLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + var iBat uint32 = 4711 + m := proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_IntegerBat, iBat) + if got, want := proto.HasExtension(m, lazytestpb.E_IntegerBat), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr := roundtrip(t, m).(*lazytestpb.Tree) + + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_IntegerBat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + + if got, want := proto.HasExtension(mr, lazytestpb.E_IntegerBat), true; got != want { + t.Errorf("Extension is not present after setting: got %v, want %v", got, want) + } + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_IntegerBat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Has") + } + + mr = roundtrip(t, m).(*lazytestpb.Tree) + if got, want := proto.GetExtension(mr, lazytestpb.E_IntegerBat).(uint32), iBat; got != want { + t.Errorf("Extension's integer field, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_IntegerBat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } +} + +func TestExtensionBinaryLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + m := proto.Clone(treeTemplate) + bBat := []byte("I'm a bat") + proto.SetExtension(m, lazytestpb.E_BinaryBat, bBat) + if got, want := proto.HasExtension(m, lazytestpb.E_BinaryBat), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr := roundtrip(t, m).(*lazytestpb.Tree) + // A binary extension is never kept lazy + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_BinaryBat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + if got, want := proto.HasExtension(mr, lazytestpb.E_BinaryBat), true; got != want { + t.Errorf("Extension present after roundtrip: got %v, want %v", got, want) + } + + m = proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_BinaryBat, []byte{}) + // An empty binary is also a binary + if got, want := proto.HasExtension(m, lazytestpb.E_BinaryBat), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr = roundtrip(t, m).(*lazytestpb.Tree) + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_BinaryBat.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + if got, want := proto.HasExtension(mr, lazytestpb.E_BinaryBat), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } +} + +func TestExtensionGroupLazy(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + // Group: should behave like message + pip := &lazytestpb.Pipistrelle{Species: &spF} + pips := []*lazytestpb.Pipistrelles{ + {Species: &spF}, + {Species: &spR}, + } + m := proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_Pipistrelle, pip) + if got, want := proto.HasExtension(m, lazytestpb.E_Pipistrelle), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr := roundtrip(t, m).(*lazytestpb.Tree) + + if extensionIsInitialized(t, mr, lazytestpb.E_Pipistrelle.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + if got, want := proto.HasExtension(mr, lazytestpb.E_Pipistrelle), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + if extensionIsInitialized(t, mr, lazytestpb.E_Pipistrelle.Field) { + t.Errorf("Extension unexpectedly initialized after Has") + } + mrr := roundtrip(t, mr).(*lazytestpb.Tree) + if extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelle.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + mrr = roundtrip(t, mr).(*lazytestpb.Tree) + if extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelle.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + pipistrelle := proto.GetExtension(mrr, lazytestpb.E_Pipistrelle).(*lazytestpb.Pipistrelle) + if got, want := pipistrelle.GetSpecies(), spF; got != want { + t.Errorf("Extension's Speices field, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelle.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + + // Group slice, behaves like message slice + m = proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_Pipistrelles, pips) + if got, want := proto.HasExtension(m, lazytestpb.E_Pipistrelles), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + mr = roundtrip(t, m).(*lazytestpb.Tree) + + if extensionIsInitialized(t, mr, lazytestpb.E_Pipistrelles.Field) { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + if got, want := proto.HasExtension(mr, lazytestpb.E_Pipistrelles), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + if extensionIsInitialized(t, mr, lazytestpb.E_Pipistrelles.Field) { + t.Errorf("Extension unexpectedly initialized after Has") + } + mr = roundtrip(t, m).(*lazytestpb.Tree) + mrr = roundtrip(t, mr).(*lazytestpb.Tree) + if got, want := proto.HasExtension(mrr, lazytestpb.E_Pipistrelles), true; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + if extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelles.Field) { + t.Errorf("Extension unexpectedly initialized after Has") + } + mrr = roundtrip(t, mr).(*lazytestpb.Tree) + pipistrelles := proto.GetExtension(mrr, lazytestpb.E_Pipistrelles).([]*lazytestpb.Pipistrelles) + if got, want := pipistrelles[1].GetSpecies(), spR; got != want { + t.Errorf("Extension's Speices field, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelles.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } + + // Setting an empty group slice has no effect + m = proto.Clone(treeTemplate) + proto.SetExtension(m, lazytestpb.E_Pipistrelles, []*lazytestpb.Pipistrelles{}) + if got, want := proto.HasExtension(m, lazytestpb.E_Pipistrelles), false; got != want { + t.Errorf("Extension present after setting empty: got %v, want %v", got, want) + } + mr = roundtrip(t, m).(*lazytestpb.Tree) + + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_Pipistrelles.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Unmarshal") + } + if got, want := proto.HasExtension(mr, lazytestpb.E_Pipistrelles), false; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + if got, want := extensionIsInitialized(t, mr, lazytestpb.E_Pipistrelles.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Has") + } + mrr = roundtrip(t, mr).(*lazytestpb.Tree) + if got, want := proto.HasExtension(mrr, lazytestpb.E_Pipistrelles), false; got != want { + t.Errorf("Extension present after setting: got %v, want %v", got, want) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelles.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Has") + } + noPipistrelles := proto.GetExtension(mrr, lazytestpb.E_Pipistrelles).([]*lazytestpb.Pipistrelles) + if got, want := len(noPipistrelles), 0; got != want { + t.Errorf("Extension's field length, want: %v, got: %v", want, got) + } + if got, want := extensionIsInitialized(t, mrr, lazytestpb.E_Pipistrelles.Field), true; got != want { + t.Errorf("Extension unexpectedly initialized after Get") + } +} + +func TestMarshalMessageSetLazyRace(t *testing.T) { + if !flags.LazyUnmarshalExtensions { + t.Skip("lazy extension unmarshaling disabled; not built with the protolegacy tag") + } + + h := &lazytestpb.Holder{Data: &messagesetpb.MessageSet{}} + + ext := &lazytestpb.Rabbit{Name: proto.String("Judy")} + proto.SetExtension(h.GetData(), lazytestpb.E_Rabbit_MessageSetExtension, ext) + + b, err := proto.Marshal(h) + if err != nil { + t.Fatalf("Could not marshal message: %v", err) + } + if err := proto.Unmarshal(b, h); err != nil { + t.Fatalf("Could not unmarshal message: %v", err) + } + // after Unmarshal, the extension is in undecoded form. + // GetExtension will decode it lazily. Make sure this does + // not race against Marshal. + + // The following pattern is similar to x/sync/errgroup, + // but we want to avoid adding that dependencies just for a test. + var ( + wg sync.WaitGroup + errOnce sync.Once + groupErr error + ) + for n := 30; n > 0; n-- { + wg.Add(2) + go func() { + defer wg.Done() + if err := func() error { + b, err := proto.Marshal(h) + if err == nil { + return proto.Unmarshal(b, &lazytestpb.Rabbit{}) + } + return err + }(); err != nil { + errOnce.Do(func() { groupErr = err }) + } + }() + go func() { + defer wg.Done() + if err := func() error { + if !proto.HasExtension(h.GetData(), lazytestpb.E_Rabbit_MessageSetExtension) { + return errors.New("proto: missing extension") + } + return nil + }(); err != nil { + errOnce.Do(func() { groupErr = err }) + } + }() + } + wg.Wait() + if groupErr != nil { + t.Fatal(groupErr) + } +} + +// Utility functions for the test cases + +// Some functions from pointer_unsafe.go +type pointer struct{ p unsafe.Pointer } + +func (p pointer) Apply(f uintptr) pointer { + return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} +} + +func pointerOfIface(v interface{}) pointer { + type ifaceHeader struct { + Type unsafe.Pointer + Data unsafe.Pointer + } + return pointer{p: (*ifaceHeader)(unsafe.Pointer(&v)).Data} +} + +func (p pointer) AsValueOf(t reflect.Type) reflect.Value { + return reflect.NewAt(t, p.p) +} + +// Highly implementation dependent - uses unsafe pointers to figure +// out if the lazyExtensionValue is initialized. +func extensionIsInitialized(t *testing.T, data interface{}, fieldNo int32) bool { + ext, ok := reflect.TypeOf(data).Elem().FieldByName("extensionFields") + if !ok { + t.Fatalf("Failed to retrieve offset of field \"extensionFields\".") + } + lazy, ok := reflect.TypeOf((*impl.ExtensionField)(nil)).Elem().FieldByName("lazy") + if !ok { + t.Fatalf("Failed to retrieve offset of field \"lazy\".") + } + + pi := pointerOfIface(data) + m, ok := pi.Apply(ext.Offset).AsValueOf(reflect.TypeOf((map[int32]impl.ExtensionField)(nil))).Interface().(*map[int32]impl.ExtensionField) + if !ok { + t.Fatalf("Extension map has unexpected type.") + } + f := (*m)[fieldNo] + // Here we rely on atomicOnce being the first field in the 'lazy' struct. + app, ok := pointerOfIface(&f).Apply(lazy.Offset).AsValueOf(reflect.TypeOf((*uint32)(nil))).Interface().(**uint32) + if !ok { + t.Fatalf("Field atomicOnce does not seem to be the first field, or has changed type.") + } + if *app == nil { + return true // lazy ptr is nil + } + return **app > 0 +} + +func roundtrip(t *testing.T, m proto.Message) proto.Message { + t.Helper() + n := m.ProtoReflect().Type().New().Interface() + b, err := proto.Marshal(m) + if err != nil { + t.Fatalf("proto.Marshal(%+v) failed: %v", m, err) + } + if err := proto.Unmarshal(b, n); err != nil { + t.Fatalf("proto.Unmarshal failed: %v", err) + } + return n +} diff --git a/internal/impl/message_reflect.go b/internal/impl/message_reflect.go index a6f0dbdad..02ad46cee 100644 --- a/internal/impl/message_reflect.go +++ b/internal/impl/message_reflect.go @@ -255,6 +255,10 @@ func (m *extensionMap) Has(xd protoreflect.ExtensionTypeDescriptor) (ok bool) { if !ok { return false } + if x.isUnexpandedLazy() { + // Avoid calling x.Value(), which triggers a lazy unmarshal. + return true + } switch { case xd.IsList(): return x.Value().List().Len() > 0 diff --git a/internal/testprotos/lazy/lazy_extension_normalized_wire_test.pb.go b/internal/testprotos/lazy/lazy_extension_normalized_wire_test.pb.go new file mode 100644 index 000000000..e2da386bc --- /dev/null +++ b/internal/testprotos/lazy/lazy_extension_normalized_wire_test.pb.go @@ -0,0 +1,322 @@ +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: internal/testprotos/lazy/lazy_extension_normalized_wire_test.proto + +package lazy + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +type Sub struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + extensionFields protoimpl.ExtensionFields + + C *uint32 `protobuf:"varint,3,opt,name=c" json:"c,omitempty"` + Grandchild *Sub `protobuf:"bytes,4,opt,name=grandchild" json:"grandchild,omitempty"` +} + +func (x *Sub) Reset() { + *x = Sub{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Sub) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Sub) ProtoMessage() {} + +func (x *Sub) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_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 Sub.ProtoReflect.Descriptor instead. +func (*Sub) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescGZIP(), []int{0} +} + +func (x *Sub) GetC() uint32 { + if x != nil && x.C != nil { + return *x.C + } + return 0 +} + +func (x *Sub) GetGrandchild() *Sub { + if x != nil { + return x.Grandchild + } + return nil +} + +type Top struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + A *uint32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` + Child *Sub `protobuf:"bytes,2,opt,name=child" json:"child,omitempty"` +} + +func (x *Top) Reset() { + *x = Top{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Top) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Top) ProtoMessage() {} + +func (x *Top) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_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 Top.ProtoReflect.Descriptor instead. +func (*Top) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescGZIP(), []int{1} +} + +func (x *Top) GetA() uint32 { + if x != nil && x.A != nil { + return *x.A + } + return 0 +} + +func (x *Top) GetChild() *Sub { + if x != nil { + return x.Child + } + return nil +} + +type Ext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SomeFlag *bool `protobuf:"varint,1,opt,name=some_flag,json=someFlag" json:"some_flag,omitempty"` +} + +func (x *Ext) Reset() { + *x = Ext{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ext) ProtoMessage() {} + +func (x *Ext) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[2] + 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 Ext.ProtoReflect.Descriptor instead. +func (*Ext) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescGZIP(), []int{2} +} + +func (x *Ext) GetSomeFlag() bool { + if x != nil && x.SomeFlag != nil { + return *x.SomeFlag + } + return false +} + +var file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*Sub)(nil), + ExtensionType: (*Ext)(nil), + Field: 2, + Name: "lazy_extension_normalized_wire_test.Ext.b", + Tag: "bytes,2,opt,name=b", + Filename: "internal/testprotos/lazy/lazy_extension_normalized_wire_test.proto", + }, +} + +// Extension fields to Sub. +var ( + // optional lazy_extension_normalized_wire_test.Ext b = 2; + E_Ext_B = &file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_extTypes[0] +) + +var File_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto protoreflect.FileDescriptor + +var file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDesc = []byte{ + 0x0a, 0x42, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6c, 0x61, 0x7a, 0x79, 0x2f, 0x6c, 0x61, 0x7a, 0x79, 0x5f, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x77, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x22, 0x63, 0x0a, 0x03, 0x53, 0x75, 0x62, + 0x12, 0x0c, 0x0a, 0x01, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x01, 0x63, 0x12, 0x48, + 0x0a, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x64, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x77, + 0x69, 0x72, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x52, 0x0a, 0x67, 0x72, + 0x61, 0x6e, 0x64, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x2a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x53, + 0x0a, 0x03, 0x54, 0x6f, 0x70, 0x12, 0x0c, 0x0a, 0x01, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x01, 0x61, 0x12, 0x3e, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x77, + 0x69, 0x72, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x52, 0x05, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x03, 0x45, 0x78, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, + 0x6f, 0x6d, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x73, 0x6f, 0x6d, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x32, 0x60, 0x0a, 0x01, 0x62, 0x12, 0x28, 0x2e, + 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, + 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, + 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x74, 0x52, 0x01, 0x62, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6c, 0x61, 0x7a, + 0x79, +} + +var ( + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescOnce sync.Once + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescData = file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDesc +) + +func file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescGZIP() []byte { + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescOnce.Do(func() { + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescData) + }) + return file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDescData +} + +var file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_goTypes = []interface{}{ + (*Sub)(nil), // 0: lazy_extension_normalized_wire_test.Sub + (*Top)(nil), // 1: lazy_extension_normalized_wire_test.Top + (*Ext)(nil), // 2: lazy_extension_normalized_wire_test.Ext +} +var file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_depIdxs = []int32{ + 0, // 0: lazy_extension_normalized_wire_test.Sub.grandchild:type_name -> lazy_extension_normalized_wire_test.Sub + 0, // 1: lazy_extension_normalized_wire_test.Top.child:type_name -> lazy_extension_normalized_wire_test.Sub + 0, // 2: lazy_extension_normalized_wire_test.Ext.b:extendee -> lazy_extension_normalized_wire_test.Sub + 2, // 3: lazy_extension_normalized_wire_test.Ext.b:type_name -> lazy_extension_normalized_wire_test.Ext + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 3, // [3:4] is the sub-list for extension type_name + 2, // [2:3] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_init() } +func file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_init() { + if File_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Sub); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + case 3: + return &v.extensionFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Top); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ext); 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_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 1, + NumServices: 0, + }, + GoTypes: file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_goTypes, + DependencyIndexes: file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_depIdxs, + MessageInfos: file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_msgTypes, + ExtensionInfos: file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_extTypes, + }.Build() + File_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto = out.File + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_rawDesc = nil + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_goTypes = nil + file_internal_testprotos_lazy_lazy_extension_normalized_wire_test_proto_depIdxs = nil +} diff --git a/internal/testprotos/lazy/lazy_extension_normalized_wire_test.proto b/internal/testprotos/lazy/lazy_extension_normalized_wire_test.proto new file mode 100644 index 000000000..3926fa921 --- /dev/null +++ b/internal/testprotos/lazy/lazy_extension_normalized_wire_test.proto @@ -0,0 +1,28 @@ +// 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. + +syntax = "proto2"; + +package lazy_extension_normalized_wire_test; + +option go_package = "google.golang.org/protobuf/internal/testprotos/lazy"; + +message Sub { + extensions 2 [verification = UNVERIFIED]; + optional uint32 c = 3; + optional Sub grandchild = 4; +} + +message Top { + optional uint32 a = 1; + optional Sub child = 2; +} + +message Ext { + extend Sub { + optional Ext b = 2; + } + + optional bool some_flag = 1; +} diff --git a/internal/testprotos/lazy/lazy_extension_test.pb.go b/internal/testprotos/lazy/lazy_extension_test.pb.go new file mode 100644 index 000000000..889e679a4 --- /dev/null +++ b/internal/testprotos/lazy/lazy_extension_test.pb.go @@ -0,0 +1,860 @@ +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: internal/testprotos/lazy/lazy_extension_test.proto + +package lazy + +import ( + messagesetpb "google.golang.org/protobuf/internal/testprotos/messageset/messagesetpb" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +type FlyingFoxSpecies int32 + +const ( + FlyingFoxSpecies_FLYING_FOX_UNDEFINED FlyingFoxSpecies = 0 + FlyingFoxSpecies_GREY_HEADED FlyingFoxSpecies = 1 + FlyingFoxSpecies_BLACK FlyingFoxSpecies = 2 + FlyingFoxSpecies_SPECTACLED FlyingFoxSpecies = 3 + FlyingFoxSpecies_LARGE_EARED FlyingFoxSpecies = 4 + FlyingFoxSpecies_DUSKY FlyingFoxSpecies = 5 + FlyingFoxSpecies_TORRESIAN FlyingFoxSpecies = 6 + FlyingFoxSpecies_BARE_BACKED FlyingFoxSpecies = 7 +) + +// Enum value maps for FlyingFoxSpecies. +var ( + FlyingFoxSpecies_name = map[int32]string{ + 0: "FLYING_FOX_UNDEFINED", + 1: "GREY_HEADED", + 2: "BLACK", + 3: "SPECTACLED", + 4: "LARGE_EARED", + 5: "DUSKY", + 6: "TORRESIAN", + 7: "BARE_BACKED", + } + FlyingFoxSpecies_value = map[string]int32{ + "FLYING_FOX_UNDEFINED": 0, + "GREY_HEADED": 1, + "BLACK": 2, + "SPECTACLED": 3, + "LARGE_EARED": 4, + "DUSKY": 5, + "TORRESIAN": 6, + "BARE_BACKED": 7, + } +) + +func (x FlyingFoxSpecies) Enum() *FlyingFoxSpecies { + p := new(FlyingFoxSpecies) + *p = x + return p +} + +func (x FlyingFoxSpecies) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FlyingFoxSpecies) Descriptor() protoreflect.EnumDescriptor { + return file_internal_testprotos_lazy_lazy_extension_test_proto_enumTypes[0].Descriptor() +} + +func (FlyingFoxSpecies) Type() protoreflect.EnumType { + return &file_internal_testprotos_lazy_lazy_extension_test_proto_enumTypes[0] +} + +func (x FlyingFoxSpecies) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *FlyingFoxSpecies) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) + if err != nil { + return err + } + *x = FlyingFoxSpecies(num) + return nil +} + +// Deprecated: Use FlyingFoxSpecies.Descriptor instead. +func (FlyingFoxSpecies) EnumDescriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{0} +} + +type PipistrelleSpecies int32 + +const ( + PipistrelleSpecies_PIPISTRELLE_UNDEFINED PipistrelleSpecies = 0 + PipistrelleSpecies_FOREST PipistrelleSpecies = 1 + PipistrelleSpecies_INDIAN PipistrelleSpecies = 2 + PipistrelleSpecies_EGYPTIAN PipistrelleSpecies = 3 + PipistrelleSpecies_RUSTY PipistrelleSpecies = 4 + PipistrelleSpecies_LEAST PipistrelleSpecies = 5 +) + +// Enum value maps for PipistrelleSpecies. +var ( + PipistrelleSpecies_name = map[int32]string{ + 0: "PIPISTRELLE_UNDEFINED", + 1: "FOREST", + 2: "INDIAN", + 3: "EGYPTIAN", + 4: "RUSTY", + 5: "LEAST", + } + PipistrelleSpecies_value = map[string]int32{ + "PIPISTRELLE_UNDEFINED": 0, + "FOREST": 1, + "INDIAN": 2, + "EGYPTIAN": 3, + "RUSTY": 4, + "LEAST": 5, + } +) + +func (x PipistrelleSpecies) Enum() *PipistrelleSpecies { + p := new(PipistrelleSpecies) + *p = x + return p +} + +func (x PipistrelleSpecies) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PipistrelleSpecies) Descriptor() protoreflect.EnumDescriptor { + return file_internal_testprotos_lazy_lazy_extension_test_proto_enumTypes[1].Descriptor() +} + +func (PipistrelleSpecies) Type() protoreflect.EnumType { + return &file_internal_testprotos_lazy_lazy_extension_test_proto_enumTypes[1] +} + +func (x PipistrelleSpecies) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *PipistrelleSpecies) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) + if err != nil { + return err + } + *x = PipistrelleSpecies(num) + return nil +} + +// Deprecated: Use PipistrelleSpecies.Descriptor instead. +func (PipistrelleSpecies) EnumDescriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{1} +} + +// This message contains a message set. +type Holder struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data *messagesetpb.MessageSet `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` +} + +func (x *Holder) Reset() { + *x = Holder{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Holder) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Holder) ProtoMessage() {} + +func (x *Holder) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_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 Holder.ProtoReflect.Descriptor instead. +func (*Holder) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{0} +} + +func (x *Holder) GetData() *messagesetpb.MessageSet { + if x != nil { + return x.Data + } + return nil +} + +// This message may be inserted into a message set. +type Rabbit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (x *Rabbit) Reset() { + *x = Rabbit{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Rabbit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Rabbit) ProtoMessage() {} + +func (x *Rabbit) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_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 Rabbit.ProtoReflect.Descriptor instead. +func (*Rabbit) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{1} +} + +func (x *Rabbit) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +type FlyingFox struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Species *FlyingFoxSpecies `protobuf:"varint,1,opt,name=species,enum=lazy_extension_test.FlyingFoxSpecies" json:"species,omitempty"` +} + +func (x *FlyingFox) Reset() { + *x = FlyingFox{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlyingFox) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlyingFox) ProtoMessage() {} + +func (x *FlyingFox) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[2] + 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 FlyingFox.ProtoReflect.Descriptor instead. +func (*FlyingFox) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{2} +} + +func (x *FlyingFox) GetSpecies() FlyingFoxSpecies { + if x != nil && x.Species != nil { + return *x.Species + } + return FlyingFoxSpecies_FLYING_FOX_UNDEFINED +} + +type Tree struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + extensionFields protoimpl.ExtensionFields + + Eucalyptus *bool `protobuf:"varint,1,opt,name=eucalyptus" json:"eucalyptus,omitempty"` +} + +func (x *Tree) Reset() { + *x = Tree{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Tree) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Tree) ProtoMessage() {} + +func (x *Tree) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[3] + 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 Tree.ProtoReflect.Descriptor instead. +func (*Tree) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{3} +} + +func (x *Tree) GetEucalyptus() bool { + if x != nil && x.Eucalyptus != nil { + return *x.Eucalyptus + } + return false +} + +type Pipistrelle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Species *PipistrelleSpecies `protobuf:"varint,1,opt,name=species,enum=lazy_extension_test.PipistrelleSpecies" json:"species,omitempty"` +} + +func (x *Pipistrelle) Reset() { + *x = Pipistrelle{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Pipistrelle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Pipistrelle) ProtoMessage() {} + +func (x *Pipistrelle) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[4] + 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 Pipistrelle.ProtoReflect.Descriptor instead. +func (*Pipistrelle) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{4} +} + +func (x *Pipistrelle) GetSpecies() PipistrelleSpecies { + if x != nil && x.Species != nil { + return *x.Species + } + return PipistrelleSpecies_PIPISTRELLE_UNDEFINED +} + +type Pipistrelles struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Species *PipistrelleSpecies `protobuf:"varint,1,opt,name=species,enum=lazy_extension_test.PipistrelleSpecies" json:"species,omitempty"` +} + +func (x *Pipistrelles) Reset() { + *x = Pipistrelles{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Pipistrelles) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Pipistrelles) ProtoMessage() {} + +func (x *Pipistrelles) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[5] + 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 Pipistrelles.ProtoReflect.Descriptor instead. +func (*Pipistrelles) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{5} +} + +func (x *Pipistrelles) GetSpecies() PipistrelleSpecies { + if x != nil && x.Species != nil { + return *x.Species + } + return PipistrelleSpecies_PIPISTRELLE_UNDEFINED +} + +// And the ugly version that is not encouraged +type BatNest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *BatNest) Reset() { + *x = BatNest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BatNest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatNest) ProtoMessage() {} + +func (x *BatNest) ProtoReflect() protoreflect.Message { + mi := &file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[6] + 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 BatNest.ProtoReflect.Descriptor instead. +func (*BatNest) Descriptor() ([]byte, []int) { + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP(), []int{6} +} + +var file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*Tree)(nil), + ExtensionType: (*FlyingFox)(nil), + Field: 345570595, + Name: "lazy_extension_test.bat", + Tag: "bytes,345570595,opt,name=bat", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: (*FlyingFox)(nil), + Field: 345570596, + Name: "lazy_extension_test.bat_pup", + Tag: "bytes,345570596,opt,name=bat_pup", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: ([]*FlyingFox)(nil), + Field: 345570597, + Name: "lazy_extension_test.bat_posse", + Tag: "bytes,345570597,rep,name=bat_posse", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: ([]byte)(nil), + Field: 345570598, + Name: "lazy_extension_test.binary_bat", + Tag: "bytes,345570598,opt,name=binary_bat", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: (*uint32)(nil), + Field: 345570599, + Name: "lazy_extension_test.integer_bat", + Tag: "varint,345570599,opt,name=integer_bat", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: (*Pipistrelle)(nil), + Field: 345570600, + Name: "lazy_extension_test.pipistrelle", + Tag: "group,345570600,opt,name=Pipistrelle", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: ([]*Pipistrelles)(nil), + Field: 345570601, + Name: "lazy_extension_test.pipistrelles", + Tag: "group,345570601,rep,name=Pipistrelles", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*messagesetpb.MessageSet)(nil), + ExtensionType: (*Rabbit)(nil), + Field: 345570595, + Name: "lazy_extension_test.Rabbit.message_set_extension", + Tag: "bytes,345570595,opt,name=message_set_extension", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, + { + ExtendedType: (*Tree)(nil), + ExtensionType: (*FlyingFox)(nil), + Field: 345570602, + Name: "lazy_extension_test.BatNest.bat", + Tag: "bytes,345570602,opt,name=bat", + Filename: "internal/testprotos/lazy/lazy_extension_test.proto", + }, +} + +// Extension fields to Tree. +var ( + // optional lazy_extension_test.FlyingFox bat = 345570595; + E_Bat = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[0] + // optional lazy_extension_test.FlyingFox bat_pup = 345570596; + E_BatPup = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[1] + // repeated lazy_extension_test.FlyingFox bat_posse = 345570597; + E_BatPosse = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[2] + // optional bytes binary_bat = 345570598; + E_BinaryBat = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[3] + // optional uint32 integer_bat = 345570599; + E_IntegerBat = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[4] + // optional lazy_extension_test.Pipistrelle pipistrelle = 345570600; + E_Pipistrelle = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[5] + // repeated lazy_extension_test.Pipistrelles pipistrelles = 345570601; + E_Pipistrelles = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[6] + // optional lazy_extension_test.FlyingFox bat = 345570602; + E_BatNest_Bat = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[8] +) + +// Extension fields to messagesetpb.MessageSet. +var ( + // optional lazy_extension_test.Rabbit message_set_extension = 345570595; + E_Rabbit_MessageSetExtension = &file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes[7] +) + +var File_internal_testprotos_lazy_lazy_extension_test_proto protoreflect.FileDescriptor + +var file_internal_testprotos_lazy_lazy_extension_test_proto_rawDesc = []byte{ + 0x0a, 0x32, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6c, 0x61, 0x7a, 0x79, 0x2f, 0x6c, 0x61, 0x7a, 0x79, 0x5f, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x65, 0x74, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x65, 0x74, 0x70, 0x62, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, + 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x42, 0x0a, 0x06, 0x48, 0x6f, 0x6c, 0x64, + 0x65, 0x72, 0x12, 0x38, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x65, 0x74, 0x2e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x97, 0x01, 0x0a, + 0x06, 0x52, 0x61, 0x62, 0x62, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x79, 0x0a, 0x15, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x65, 0x74, 0x2e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x18, 0xa3, 0xfa, 0xe3, 0xa4, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x61, 0x62, 0x62, 0x69, + 0x74, 0x52, 0x13, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4c, 0x0a, 0x09, 0x46, 0x6c, 0x79, 0x69, 0x6e, 0x67, + 0x46, 0x6f, 0x78, 0x12, 0x3f, 0x0a, 0x07, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x6c, 0x79, 0x69, 0x6e, + 0x67, 0x46, 0x6f, 0x78, 0x53, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x52, 0x07, 0x73, 0x70, 0x65, + 0x63, 0x69, 0x65, 0x73, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, + 0x65, 0x75, 0x63, 0x61, 0x6c, 0x79, 0x70, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0a, 0x65, 0x75, 0x63, 0x61, 0x6c, 0x79, 0x70, 0x74, 0x75, 0x73, 0x2a, 0x09, 0x08, 0x90, + 0x4e, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x50, 0x0a, 0x0b, 0x50, 0x69, 0x70, 0x69, 0x73, + 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x69, + 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, + 0x52, 0x07, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x0c, 0x50, 0x69, 0x70, + 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x70, 0x65, + 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6c, 0x61, 0x7a, + 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, + 0x2e, 0x50, 0x69, 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, + 0x69, 0x65, 0x73, 0x52, 0x07, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x22, 0x5a, 0x0a, 0x07, + 0x42, 0x61, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x32, 0x4f, 0x0a, 0x03, 0x62, 0x61, 0x74, 0x12, 0x19, + 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xaa, 0xfa, 0xe3, 0xa4, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x6c, 0x79, 0x69, 0x6e, 0x67, + 0x46, 0x6f, 0x78, 0x52, 0x03, 0x62, 0x61, 0x74, 0x2a, 0x94, 0x01, 0x0a, 0x10, 0x46, 0x6c, 0x79, + 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x78, 0x53, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, + 0x14, 0x46, 0x4c, 0x59, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x58, 0x5f, 0x55, 0x4e, 0x44, 0x45, + 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x52, 0x45, 0x59, 0x5f, + 0x48, 0x45, 0x41, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, 0x41, 0x43, + 0x4b, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x50, 0x45, 0x43, 0x54, 0x41, 0x43, 0x4c, 0x45, + 0x44, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x41, 0x52, 0x47, 0x45, 0x5f, 0x45, 0x41, 0x52, + 0x45, 0x44, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x55, 0x53, 0x4b, 0x59, 0x10, 0x05, 0x12, + 0x0d, 0x0a, 0x09, 0x54, 0x4f, 0x52, 0x52, 0x45, 0x53, 0x49, 0x41, 0x4e, 0x10, 0x06, 0x12, 0x0f, + 0x0a, 0x0b, 0x42, 0x41, 0x52, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x07, 0x2a, + 0x6b, 0x0a, 0x12, 0x50, 0x69, 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x53, 0x70, + 0x65, 0x63, 0x69, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x49, 0x50, 0x49, 0x53, 0x54, 0x52, + 0x45, 0x4c, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x4f, 0x52, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, + 0x49, 0x4e, 0x44, 0x49, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x47, 0x59, 0x50, + 0x54, 0x49, 0x41, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x55, 0x53, 0x54, 0x59, 0x10, + 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x45, 0x41, 0x53, 0x54, 0x10, 0x05, 0x3a, 0x4f, 0x0a, 0x03, + 0x62, 0x61, 0x74, 0x12, 0x19, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xa3, + 0xfa, 0xe3, 0xa4, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x46, + 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x78, 0x52, 0x03, 0x62, 0x61, 0x74, 0x3a, 0x56, 0x0a, + 0x07, 0x62, 0x61, 0x74, 0x5f, 0x70, 0x75, 0x70, 0x12, 0x19, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, + 0x72, 0x65, 0x65, 0x18, 0xa4, 0xfa, 0xe3, 0xa4, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x46, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x78, 0x52, 0x06, 0x62, + 0x61, 0x74, 0x50, 0x75, 0x70, 0x3a, 0x5a, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x5f, 0x70, 0x6f, 0x73, + 0x73, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xa5, 0xfa, + 0xe3, 0xa4, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x6c, + 0x79, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x78, 0x52, 0x08, 0x62, 0x61, 0x74, 0x50, 0x6f, 0x73, 0x73, + 0x65, 0x3a, 0x3c, 0x0a, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x62, 0x61, 0x74, 0x12, + 0x19, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xa6, 0xfa, 0xe3, 0xa4, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x42, 0x61, 0x74, 0x3a, + 0x3e, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x74, 0x12, 0x19, + 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xa7, 0xfa, 0xe3, 0xa4, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x42, 0x61, 0x74, 0x3a, + 0x61, 0x0a, 0x0b, 0x70, 0x69, 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x12, 0x19, + 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xa8, 0xfa, 0xe3, 0xa4, 0x01, 0x20, + 0x01, 0x28, 0x0a, 0x32, 0x20, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x69, 0x70, 0x69, 0x73, 0x74, + 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x52, 0x0b, 0x70, 0x69, 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, + 0x6c, 0x65, 0x3a, 0x64, 0x0a, 0x0c, 0x70, 0x69, 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, + 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x18, 0xa9, 0xfa, + 0xe3, 0xa4, 0x01, 0x20, 0x03, 0x28, 0x0a, 0x32, 0x21, 0x2e, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x65, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x69, + 0x70, 0x69, 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x52, 0x0c, 0x70, 0x69, 0x70, 0x69, + 0x73, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6c, 0x61, 0x7a, 0x79, +} + +var ( + file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescOnce sync.Once + file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescData = file_internal_testprotos_lazy_lazy_extension_test_proto_rawDesc +) + +func file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescGZIP() []byte { + file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescOnce.Do(func() { + file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescData) + }) + return file_internal_testprotos_lazy_lazy_extension_test_proto_rawDescData +} + +var file_internal_testprotos_lazy_lazy_extension_test_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_internal_testprotos_lazy_lazy_extension_test_proto_goTypes = []interface{}{ + (FlyingFoxSpecies)(0), // 0: lazy_extension_test.FlyingFoxSpecies + (PipistrelleSpecies)(0), // 1: lazy_extension_test.PipistrelleSpecies + (*Holder)(nil), // 2: lazy_extension_test.Holder + (*Rabbit)(nil), // 3: lazy_extension_test.Rabbit + (*FlyingFox)(nil), // 4: lazy_extension_test.FlyingFox + (*Tree)(nil), // 5: lazy_extension_test.Tree + (*Pipistrelle)(nil), // 6: lazy_extension_test.Pipistrelle + (*Pipistrelles)(nil), // 7: lazy_extension_test.Pipistrelles + (*BatNest)(nil), // 8: lazy_extension_test.BatNest + (*messagesetpb.MessageSet)(nil), // 9: goproto.proto.messageset.MessageSet +} +var file_internal_testprotos_lazy_lazy_extension_test_proto_depIdxs = []int32{ + 9, // 0: lazy_extension_test.Holder.data:type_name -> goproto.proto.messageset.MessageSet + 0, // 1: lazy_extension_test.FlyingFox.species:type_name -> lazy_extension_test.FlyingFoxSpecies + 1, // 2: lazy_extension_test.Pipistrelle.species:type_name -> lazy_extension_test.PipistrelleSpecies + 1, // 3: lazy_extension_test.Pipistrelles.species:type_name -> lazy_extension_test.PipistrelleSpecies + 5, // 4: lazy_extension_test.bat:extendee -> lazy_extension_test.Tree + 5, // 5: lazy_extension_test.bat_pup:extendee -> lazy_extension_test.Tree + 5, // 6: lazy_extension_test.bat_posse:extendee -> lazy_extension_test.Tree + 5, // 7: lazy_extension_test.binary_bat:extendee -> lazy_extension_test.Tree + 5, // 8: lazy_extension_test.integer_bat:extendee -> lazy_extension_test.Tree + 5, // 9: lazy_extension_test.pipistrelle:extendee -> lazy_extension_test.Tree + 5, // 10: lazy_extension_test.pipistrelles:extendee -> lazy_extension_test.Tree + 9, // 11: lazy_extension_test.Rabbit.message_set_extension:extendee -> goproto.proto.messageset.MessageSet + 5, // 12: lazy_extension_test.BatNest.bat:extendee -> lazy_extension_test.Tree + 4, // 13: lazy_extension_test.bat:type_name -> lazy_extension_test.FlyingFox + 4, // 14: lazy_extension_test.bat_pup:type_name -> lazy_extension_test.FlyingFox + 4, // 15: lazy_extension_test.bat_posse:type_name -> lazy_extension_test.FlyingFox + 6, // 16: lazy_extension_test.pipistrelle:type_name -> lazy_extension_test.Pipistrelle + 7, // 17: lazy_extension_test.pipistrelles:type_name -> lazy_extension_test.Pipistrelles + 3, // 18: lazy_extension_test.Rabbit.message_set_extension:type_name -> lazy_extension_test.Rabbit + 4, // 19: lazy_extension_test.BatNest.bat:type_name -> lazy_extension_test.FlyingFox + 20, // [20:20] is the sub-list for method output_type + 20, // [20:20] is the sub-list for method input_type + 13, // [13:20] is the sub-list for extension type_name + 4, // [4:13] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_internal_testprotos_lazy_lazy_extension_test_proto_init() } +func file_internal_testprotos_lazy_lazy_extension_test_proto_init() { + if File_internal_testprotos_lazy_lazy_extension_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Holder); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Rabbit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlyingFox); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Tree); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + case 3: + return &v.extensionFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Pipistrelle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Pipistrelles); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BatNest); 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_internal_testprotos_lazy_lazy_extension_test_proto_rawDesc, + NumEnums: 2, + NumMessages: 7, + NumExtensions: 9, + NumServices: 0, + }, + GoTypes: file_internal_testprotos_lazy_lazy_extension_test_proto_goTypes, + DependencyIndexes: file_internal_testprotos_lazy_lazy_extension_test_proto_depIdxs, + EnumInfos: file_internal_testprotos_lazy_lazy_extension_test_proto_enumTypes, + MessageInfos: file_internal_testprotos_lazy_lazy_extension_test_proto_msgTypes, + ExtensionInfos: file_internal_testprotos_lazy_lazy_extension_test_proto_extTypes, + }.Build() + File_internal_testprotos_lazy_lazy_extension_test_proto = out.File + file_internal_testprotos_lazy_lazy_extension_test_proto_rawDesc = nil + file_internal_testprotos_lazy_lazy_extension_test_proto_goTypes = nil + file_internal_testprotos_lazy_lazy_extension_test_proto_depIdxs = nil +} diff --git a/internal/testprotos/lazy/lazy_extension_test.proto b/internal/testprotos/lazy/lazy_extension_test.proto new file mode 100644 index 000000000..1d077da90 --- /dev/null +++ b/internal/testprotos/lazy/lazy_extension_test.proto @@ -0,0 +1,80 @@ +// 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. + +syntax = "proto2"; + +package lazy_extension_test; + +import "internal/testprotos/messageset/messagesetpb/message_set.proto"; + +option go_package = "google.golang.org/protobuf/internal/testprotos/lazy"; + +// This message contains a message set. +message Holder { + optional goproto.proto.messageset.MessageSet data = 1; +} + +// This message may be inserted into a message set. +message Rabbit { + extend goproto.proto.messageset.MessageSet { + optional Rabbit message_set_extension = 345570595; + } + optional string name = 1; +} + +enum FlyingFoxSpecies { + FLYING_FOX_UNDEFINED = 0; + GREY_HEADED = 1; + BLACK = 2; + SPECTACLED = 3; + LARGE_EARED = 4; + DUSKY = 5; + TORRESIAN = 6; + BARE_BACKED = 7; +} + +enum PipistrelleSpecies { + PIPISTRELLE_UNDEFINED = 0; + FOREST = 1; + INDIAN = 2; + EGYPTIAN = 3; + RUSTY = 4; + LEAST = 5; +} + +message FlyingFox { + optional FlyingFoxSpecies species = 1; +} + +message Tree { + optional bool eucalyptus = 1; + extensions 10000 to max; +} + +extend Tree { + optional FlyingFox bat = 345570595; +} + +extend Tree { + optional FlyingFox bat_pup = 345570596; +} + +extend Tree { + repeated FlyingFox bat_posse = 345570597; + optional bytes binary_bat = 345570598; + optional uint32 integer_bat = 345570599; + optional group Pipistrelle = 345570600 { + optional PipistrelleSpecies species = 1; + } + repeated group Pipistrelles = 345570601 { + optional PipistrelleSpecies species = 1; + } +} + +// And the ugly version that is not encouraged +message BatNest { + extend Tree { + optional FlyingFox bat = 345570602; + } +}