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; + } +}