From a26f9a41999b10dd12ede9d7532906f16aa126f6 Mon Sep 17 00:00:00 2001 From: "Samani G. Gikandi" Date: Tue, 29 Sep 2026 18:49:52 -0700 Subject: [PATCH 1/4] feat(pool): adds pool support to well-known types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Context** Today users of vtproto benefit from fully unrolled ser/des but cannot take advantage of pooling, creating GC churn where there would otherwise be none. This diff: * Adds pooling support to the generator for well-known types. * Updates Makefile w/ pooling arguments for gen-wkt and gen-testproto * Adds additional fields to WKTNestedPool test type for testing * Regenerates test wkt and test protos * Adds IsLocalWrapper helper func to generator * Adds new unit tests exercising cloning behavior The new pooling code is inert for existing stubs; as such this change should be backwards compatible. Users can leverage this by regenerating their stubs. **⚠️ Caveats ⚠️** While the code is backwards compatible, this is a _material change in behavior_. Previously there were cases where calling `ResetVT` on a type containing a singular WKT would simply clear the pointer. This meant it was safe to share/reuse WKT objects in certain cases. This is no longer true; all the same terms and conditions that apply to other pooled types apply to WKT wrappers. Currently Struct's do not benefit much from this as we do not have pooling for maps. This will be addressed in a follow on change. --- Makefile | 3 + features/pool/pool.go | 22 +- features/unmarshal/unmarshal.go | 10 +- generator/generatedfile.go | 69 +- generator/generator.go | 7 +- testproto/pool/pool_test.go | 98 ++ testproto/pool/wkt_pool.pb.go | 216 ++++ testproto/pool/wkt_pool.proto | 19 + testproto/pool/wkt_pool_vtproto.pb.go | 1142 +++++++++++++++++ types/known/anypb/any_vtproto.pb.go | 25 +- types/known/durationpb/duration_vtproto.pb.go | 23 +- types/known/emptypb/empty_vtproto.pb.go | 23 +- .../fieldmaskpb/field_mask_vtproto.pb.go | 26 +- types/known/structpb/struct_vtproto.pb.go | 114 +- .../known/timestamppb/timestamp_vtproto.pb.go | 23 +- types/known/wrapperspb/wrappers_vtproto.pb.go | 209 ++- 16 files changed, 1981 insertions(+), 48 deletions(-) create mode 100644 testproto/pool/wkt_pool.pb.go create mode 100644 testproto/pool/wkt_pool.proto create mode 100644 testproto/pool/wkt_pool_vtproto.pb.go diff --git a/Makefile b/Makefile index 4c9f6c0a..f9b795cc 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ gen-wkt: bin/protoc-gen-go-vtproto --plugin protoc-gen-go-vtproto="${GOBIN}/protoc-gen-go-vtproto" \ --go-vtproto_out=. \ --go-vtproto_opt=module=google.golang.org/protobuf,wrap=true \ + --go-vtproto_opt=pool=google.golang.org/protobuf/types/known/*.* \ $(PROTOBUF_ROOT)/src/google/protobuf/any.proto \ $(PROTOBUF_ROOT)/src/google/protobuf/duration.proto \ $(PROTOBUF_ROOT)/src/google/protobuf/empty.proto \ @@ -55,12 +56,14 @@ gen-testproto: get-grpc-testproto gen-wkt-testproto install --proto_path=include \ --go_out=. --plugin protoc-gen-go="${GOBIN}/protoc-gen-go" \ --go-vtproto_out=allow-empty=true:. --plugin protoc-gen-go-vtproto="${GOBIN}/protoc-gen-go-vtproto" \ + --go-vtproto_opt=pool=google.golang.org/protobuf/types/known/*.* \ -I$(PROTOBUF_ROOT)/src \ testproto/ignore_unknown_fields/opt.proto \ testproto/empty/empty.proto \ testproto/pool/pool.proto \ testproto/pool/pool_with_slice_reuse.proto \ testproto/pool/pool_with_oneof.proto \ + testproto/pool/wkt_pool.proto \ testproto/proto3opt/opt.proto \ testproto/proto2/scalars.proto \ testproto/unsafe/unsafe.proto \ diff --git a/features/pool/pool.go b/features/pool/pool.go index 4f7efdca..5521406a 100644 --- a/features/pool/pool.go +++ b/features/pool/pool.go @@ -39,9 +39,9 @@ func (p *pool) message(message *protogen.Message) { } p.once = true - ccTypeName := message.GoIdent + ccTypeName := p.PoolMessageIdent(message) - p.P(`var vtprotoPool_`, ccTypeName, ` = `, p.Ident("sync", "Pool"), `{`) + p.P(`var vtprotoPool_`, ccTypeName.GoName, ` = `, p.Ident("sync", "Pool"), `{`) p.P(`New: func() interface{} {`) p.P(`return &`, ccTypeName, `{}`) p.P(`},`) @@ -58,7 +58,7 @@ func (p *pool) message(message *protogen.Message) { case protoreflect.MessageKind, protoreflect.GroupKind: p.P(`for _, mm := range m.`, fieldName, `{`) if p.ShouldPool(field.Message) { - p.P(`mm.ResetVT()`) + p.PResetVTElement("mm", field.Message) } else { p.P(`mm.Reset()`) } @@ -71,14 +71,14 @@ func (p *pool) message(message *protogen.Message) { } else if field.Oneof != nil && !field.Oneof.Desc.IsSynthetic() { if p.ShouldPool(field.Message) { p.P(`if oneof, ok := m.`, field.Oneof.GoName, `.(*`, field.GoIdent, `); ok {`) - p.P(`oneof.`, fieldName, `.ReturnToVTPool()`) + p.PReturnToVTPool("oneof."+fieldName, field.Message) p.P(`}`) } } else { switch field.Desc.Kind() { case protoreflect.MessageKind, protoreflect.GroupKind: if !field.Desc.IsMap() && p.ShouldPool(field.Message) { - p.P(`m.`, fieldName, `.ReturnToVTPool()`) + p.PReturnToVTPool("m."+fieldName, field.Message) } case protoreflect.BytesKind: p.P(fmt.Sprintf("f%d", len(saved)), ` := m.`, fieldName, `[:0]`) @@ -87,7 +87,11 @@ func (p *pool) message(message *protogen.Message) { } } - p.P(`m.Reset()`) + if p.IsLocalWrapper(message) { + p.P(`(*`, p.QualifiedGoIdent(message.GoIdent), `)(m).Reset()`) + } else { + p.P(`m.Reset()`) + } for i, field := range saved { p.P(`m.`, field.GoName, ` = `, fmt.Sprintf("f%d", i)) } @@ -97,11 +101,11 @@ func (p *pool) message(message *protogen.Message) { p.P(`func (m *`, ccTypeName, `) ReturnToVTPool() {`) p.P(`if m != nil {`) p.P(`m.ResetVT()`) - p.P(`vtprotoPool_`, ccTypeName, `.Put(m)`) + p.P(`vtprotoPool_`, ccTypeName.GoName, `.Put(m)`) p.P(`}`) p.P(`}`) - p.P(`func `, ccTypeName, `FromVTPool() *`, ccTypeName, `{`) - p.P(`return vtprotoPool_`, ccTypeName, `.Get().(*`, ccTypeName, `)`) + p.P(`func `, ccTypeName.GoName, `FromVTPool() *`, ccTypeName, `{`) + p.P(`return vtprotoPool_`, ccTypeName.GoName, `.Get().(*`, ccTypeName, `)`) p.P(`}`) } diff --git a/features/unmarshal/unmarshal.go b/features/unmarshal/unmarshal.go index c5540a51..61f9c6f7 100644 --- a/features/unmarshal/unmarshal.go +++ b/features/unmarshal/unmarshal.go @@ -499,12 +499,16 @@ func (p *unmarshal) fieldItem(field *protogen.Field, fieldname string, message * p.decodeMessage("oneof."+field.GoName, buf, field.Message) p.P(`} else {`) if p.ShouldPool(message) && p.ShouldPool(field.Message) { - p.P(`v := `, msgname, `FromVTPool()`) + p.PDeclFromVTPool("v", field.Message) } else { p.P(`v := &`, msgname, `{}`) } p.decodeMessage("v", buf, field.Message) - p.P(`m.`, fieldname, ` = &`, field.GoIdent, "{", field.GoName, `: v}`) + if p.IsWellKnownType(field.Message) && p.IsLocalWrapper(field.Message) { + p.P(`m.`, fieldname, ` = &`, field.GoIdent, "{", field.GoName, `: (*`, p.QualifiedGoIdent(field.Message.GoIdent), `)(v)}`) + } else { + p.P(`m.`, fieldname, ` = &`, field.GoIdent, "{", field.GoName, `: v}`) + } p.P(`}`) } else if field.Desc.IsMap() { unique := proto.GetExtension(field.Desc.Options(), vtproto.E_Options).(*vtproto.Opts).GetUnique() @@ -565,7 +569,7 @@ func (p *unmarshal) fieldItem(field *protogen.Field, fieldname string, message * } else { p.P(`if m.`, fieldname, ` == nil {`) if p.ShouldPool(message) && p.ShouldPool(field.Message) { - p.P(`m.`, fieldname, ` = `, field.Message.GoIdent, `FromVTPool()`) + p.PAssignFromVTPool("m."+fieldname, field.Message) } else { p.P(`m.`, fieldname, ` = &`, field.Message.GoIdent, `{}`) } diff --git a/generator/generatedfile.go b/generator/generatedfile.go index 07c3d920..dfc85849 100644 --- a/generator/generatedfile.go +++ b/generator/generatedfile.go @@ -16,8 +16,9 @@ import ( type GeneratedFile struct { *protogen.GeneratedFile - Config *Config - LocalPackages map[protoreflect.FullName]bool + Config *Config + LocalPackages map[protoreflect.FullName]bool + OutputGoImportPath protogen.GoImportPath } func (p *GeneratedFile) Ident(path, ident string) string { @@ -52,16 +53,67 @@ func (b *GeneratedFile) ShouldIgnoreUnknownFields(message *protogen.Message) boo } func (b *GeneratedFile) Alloc(vname string, message *protogen.Message, isQualifiedIdent bool) { + if b.ShouldPool(message) { + b.PDeclFromVTPool(vname, message) + return + } + ident := message.GoIdent.GoName if isQualifiedIdent { ident = b.QualifiedGoIdent(message.GoIdent) } + b.P(vname, " := new(", ident, `)`) +} - if b.ShouldPool(message) { - b.P(vname, " := ", ident, `FromVTPool()`) - } else { - b.P(vname, " := new(", ident, `)`) +// PoolMessageIdent is the type used for pool method receivers in the file being generated. +func (p *GeneratedFile) PoolMessageIdent(message *protogen.Message) protogen.GoIdent { + if p.IsLocalWrapper(message) { + return protogen.GoIdent{GoName: message.GoIdent.GoName} } + return message.GoIdent +} + +// PDeclFromVTPool emits `vname := `. Caller must ensure ShouldPool(message). +func (p *GeneratedFile) PDeclFromVTPool(vname string, message *protogen.Message) { + p.P(append([]any{vname, " := "}, p.fromVTPool(message)...)...) +} + +// PAssignFromVTPool emits `target = `. Caller must ensure ShouldPool(message). +func (p *GeneratedFile) PAssignFromVTPool(target string, message *protogen.Message) { + p.P(append([]any{target, " = "}, p.fromVTPool(message)...)...) +} + +func (p *GeneratedFile) fromVTPool(message *protogen.Message) []any { + if p.IsWellKnownType(message) && !p.IsLocalWrapper(message) { + wkt := p.WellKnownTypeMap(message) + fromPool := protogen.GoIdent{GoName: wkt.GoName + "FromVTPool", GoImportPath: wkt.GoImportPath} + return []any{"(*", p.QualifiedGoIdent(message.GoIdent), ")((*", p.QualifiedGoIdent(wkt), ")(", p.QualifiedGoIdent(fromPool), "()))"} + } + if p.IsLocalWrapper(message) || message.GoIdent.GoImportPath == p.OutputGoImportPath { + return []any{p.PoolMessageIdent(message).GoName, "FromVTPool()"} + } + fromPool := protogen.GoIdent{GoName: message.GoIdent.GoName + "FromVTPool", GoImportPath: message.GoIdent.GoImportPath} + return []any{p.QualifiedGoIdent(fromPool), "()"} +} + +// PReturnToVTPool emits a statement that returns a nested message to its pool. +func (p *GeneratedFile) PReturnToVTPool(expr string, message *protogen.Message) { + if p.IsWellKnownType(message) { + wkt := p.WellKnownTypeMap(message) + p.P(`(*`, p.QualifiedGoIdent(wkt), `)(`, expr, `).ReturnToVTPool()`) + return + } + p.P(expr, `.ReturnToVTPool()`) +} + +// PResetVTElement emits a reset for a repeated element. +func (p *GeneratedFile) PResetVTElement(expr string, message *protogen.Message) { + if p.IsWellKnownType(message) { + wkt := p.WellKnownTypeMap(message) + p.P(`(*`, p.QualifiedGoIdent(wkt), `)(`, expr, `).ResetVT()`) + return + } + p.P(expr, `.ResetVT()`) } func (p *GeneratedFile) FieldGoType(field *protogen.Field) (goType string, pointer bool) { @@ -206,3 +258,8 @@ func (p *GeneratedFile) WellKnownTypeMap(message *protogen.Message) protogen.GoI func (p *GeneratedFile) Wrapper() bool { return p.Config.Wrap } + +// IsLocalWrapper is true if the (wrap=true) is true for the message. +func (p *GeneratedFile) IsLocalWrapper(message *protogen.Message) bool { + return p.Wrapper() && p.IsLocalMessage(message) +} diff --git a/generator/generator.go b/generator/generator.go index a575ed45..be12c980 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -114,9 +114,10 @@ func (gen *Generator) Generate() { func (gen *Generator) generateFile(gf *protogen.GeneratedFile, file *protogen.File) { p := &GeneratedFile{ - GeneratedFile: gf, - Config: gen.cfg, - LocalPackages: gen.local, + GeneratedFile: gf, + Config: gen.cfg, + LocalPackages: gen.local, + OutputGoImportPath: file.GoImportPath, } if p.Config.BuildTag != "" { diff --git a/testproto/pool/pool_test.go b/testproto/pool/pool_test.go index be9085fc..259d2ab4 100644 --- a/testproto/pool/pool_test.go +++ b/testproto/pool/pool_test.go @@ -3,11 +3,15 @@ package pool import ( "log" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/structpb" + "google.golang.org/protobuf/types/known/timestamppb" ) func Test_Pool_slice_data_override(t *testing.T) { @@ -186,3 +190,97 @@ func Test_Pool_Optional(t *testing.T) { mFromPool := MemoryPoolExtensionFromVTPool() require.True(t, mFromPool.EqualVT(&MemoryPoolExtension{})) } + +func mustStruct(t *testing.T, m map[string]any) *structpb.Struct { + t.Helper() + st, err := structpb.NewStruct(m) + require.NoError(t, err) + return st +} + +func marshalWKT(t *testing.T, m *WKTNestedPool) []byte { + t.Helper() + b, err := m.MarshalVT() + require.NoError(t, err) + return b +} + +func Test_WKT_nested_pool_reuse(t *testing.T) { + filled := &WKTNestedPool{ + Ts: timestamppb.New(time.Unix(100, 5)), + St: mustStruct(t, map[string]any{"a": 1.0, "b": []any{"x", 2.0}}), + Tss: []*timestamppb.Timestamp{timestamppb.New(time.Unix(1, 0)), timestamppb.New(time.Unix(2, 0))}, + Sts: []*structpb.Struct{mustStruct(t, map[string]any{"k": "v"})}, + } + filledBytes := marshalWKT(t, filled) + emptyBytes := marshalWKT(t, &WKTNestedPool{}) + + t.Run("fields are cleared on reuse", func(t *testing.T) { + msg := WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(filledBytes)) + require.NotNil(t, msg.Ts) + require.NotNil(t, msg.St) + require.Len(t, msg.Tss, 2) + require.Len(t, msg.Sts, 1) + msg.ReturnToVTPool() + + msg = WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(emptyBytes)) + assert.Nil(t, msg.Ts) + assert.Nil(t, msg.St) + assert.Empty(t, msg.Tss) + assert.Empty(t, msg.Sts) + assert.Nil(t, msg.Choice) + msg.ReturnToVTPool() + }) + + t.Run("reused message equals a fresh unmarshal of the second payload", func(t *testing.T) { + second := &WKTNestedPool{ + Ts: timestamppb.New(time.Unix(7, 7)), + Tss: []*timestamppb.Timestamp{timestamppb.New(time.Unix(9, 0))}, + } + secondBytes := marshalWKT(t, second) + + msg := WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(filledBytes)) + msg.ReturnToVTPool() + + msg = WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(secondBytes)) + assert.True(t, msg.EqualVT(second), "got %v, want %v", msg, second) + assert.True(t, proto.Equal(msg, second)) + msg.ReturnToVTPool() + }) + + t.Run("oneof members are cleared and switchable", func(t *testing.T) { + withTs := marshalWKT(t, &WKTNestedPool{Choice: &WKTNestedPool_ChoiceTs{ChoiceTs: timestamppb.New(time.Unix(3, 0))}}) + withDur := marshalWKT(t, &WKTNestedPool{Choice: &WKTNestedPool_ChoiceDur{ChoiceDur: durationpb.New(time.Second)}}) + + msg := WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(withTs)) + require.NotNil(t, msg.GetChoiceTs()) + msg.ReturnToVTPool() + + msg = WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(withDur)) + assert.Nil(t, msg.GetChoiceTs()) + assert.Equal(t, time.Second, msg.GetChoiceDur().AsDuration()) + msg.ReturnToVTPool() + + msg = WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(emptyBytes)) + assert.Nil(t, msg.Choice) + msg.ReturnToVTPool() + }) + + t.Run("CloneVT result is independent of the original", func(t *testing.T) { + msg := WKTNestedPoolFromVTPool() + require.NoError(t, msg.UnmarshalVT(filledBytes)) + clone := msg.CloneVT() + require.True(t, clone.EqualVT(msg)) + msg.ReturnToVTPool() + + assert.True(t, proto.Equal(clone, filled), "clone was corrupted by returning the original") + clone.ReturnToVTPool() + }) +} diff --git a/testproto/pool/wkt_pool.pb.go b/testproto/pool/wkt_pool.pb.go new file mode 100644 index 00000000..addbcca7 --- /dev/null +++ b/testproto/pool/wkt_pool.pb.go @@ -0,0 +1,216 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.10 +// protoc v3.21.12 +// source: pool/wkt_pool.proto + +package pool + +import ( + _ "github.com/planetscale/vtprotobuf/vtproto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb "google.golang.org/protobuf/types/known/durationpb" + structpb "google.golang.org/protobuf/types/known/structpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type WKTNestedPool struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ts *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=ts,proto3" json:"ts,omitempty"` + St *structpb.Struct `protobuf:"bytes,2,opt,name=st,proto3" json:"st,omitempty"` + Tss []*timestamppb.Timestamp `protobuf:"bytes,3,rep,name=tss,proto3" json:"tss,omitempty"` + Sts []*structpb.Struct `protobuf:"bytes,4,rep,name=sts,proto3" json:"sts,omitempty"` + // Types that are valid to be assigned to Choice: + // + // *WKTNestedPool_ChoiceTs + // *WKTNestedPool_ChoiceDur + Choice isWKTNestedPool_Choice `protobuf_oneof:"choice"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WKTNestedPool) Reset() { + *x = WKTNestedPool{} + mi := &file_pool_wkt_pool_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WKTNestedPool) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WKTNestedPool) ProtoMessage() {} + +func (x *WKTNestedPool) ProtoReflect() protoreflect.Message { + mi := &file_pool_wkt_pool_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WKTNestedPool.ProtoReflect.Descriptor instead. +func (*WKTNestedPool) Descriptor() ([]byte, []int) { + return file_pool_wkt_pool_proto_rawDescGZIP(), []int{0} +} + +func (x *WKTNestedPool) GetTs() *timestamppb.Timestamp { + if x != nil { + return x.Ts + } + return nil +} + +func (x *WKTNestedPool) GetSt() *structpb.Struct { + if x != nil { + return x.St + } + return nil +} + +func (x *WKTNestedPool) GetTss() []*timestamppb.Timestamp { + if x != nil { + return x.Tss + } + return nil +} + +func (x *WKTNestedPool) GetSts() []*structpb.Struct { + if x != nil { + return x.Sts + } + return nil +} + +func (x *WKTNestedPool) GetChoice() isWKTNestedPool_Choice { + if x != nil { + return x.Choice + } + return nil +} + +func (x *WKTNestedPool) GetChoiceTs() *timestamppb.Timestamp { + if x != nil { + if x, ok := x.Choice.(*WKTNestedPool_ChoiceTs); ok { + return x.ChoiceTs + } + } + return nil +} + +func (x *WKTNestedPool) GetChoiceDur() *durationpb.Duration { + if x != nil { + if x, ok := x.Choice.(*WKTNestedPool_ChoiceDur); ok { + return x.ChoiceDur + } + } + return nil +} + +type isWKTNestedPool_Choice interface { + isWKTNestedPool_Choice() +} + +type WKTNestedPool_ChoiceTs struct { + ChoiceTs *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=choice_ts,json=choiceTs,proto3,oneof"` +} + +type WKTNestedPool_ChoiceDur struct { + ChoiceDur *durationpb.Duration `protobuf:"bytes,6,opt,name=choice_dur,json=choiceDur,proto3,oneof"` +} + +func (*WKTNestedPool_ChoiceTs) isWKTNestedPool_Choice() {} + +func (*WKTNestedPool_ChoiceDur) isWKTNestedPool_Choice() {} + +var File_pool_wkt_pool_proto protoreflect.FileDescriptor + +const file_pool_wkt_pool_proto_rawDesc = "" + + "\n" + + "\x13pool/wkt_pool.proto\x1a3github.com/planetscale/vtprotobuf/vtproto/ext.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xc4\x02\n" + + "\rWKTNestedPool\x12*\n" + + "\x02ts\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\x02ts\x12'\n" + + "\x02st\x18\x02 \x01(\v2\x17.google.protobuf.StructR\x02st\x12,\n" + + "\x03tss\x18\x03 \x03(\v2\x1a.google.protobuf.TimestampR\x03tss\x12)\n" + + "\x03sts\x18\x04 \x03(\v2\x17.google.protobuf.StructR\x03sts\x129\n" + + "\tchoice_ts\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampH\x00R\bchoiceTs\x12:\n" + + "\n" + + "choice_dur\x18\x06 \x01(\v2\x19.google.protobuf.DurationH\x00R\tchoiceDur:\x04\xa8\xa6\x1f\x01B\b\n" + + "\x06choiceB\x10Z\x0etestproto/poolb\x06proto3" + +var ( + file_pool_wkt_pool_proto_rawDescOnce sync.Once + file_pool_wkt_pool_proto_rawDescData []byte +) + +func file_pool_wkt_pool_proto_rawDescGZIP() []byte { + file_pool_wkt_pool_proto_rawDescOnce.Do(func() { + file_pool_wkt_pool_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_pool_wkt_pool_proto_rawDesc), len(file_pool_wkt_pool_proto_rawDesc))) + }) + return file_pool_wkt_pool_proto_rawDescData +} + +var file_pool_wkt_pool_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pool_wkt_pool_proto_goTypes = []any{ + (*WKTNestedPool)(nil), // 0: WKTNestedPool + (*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp + (*structpb.Struct)(nil), // 2: google.protobuf.Struct + (*durationpb.Duration)(nil), // 3: google.protobuf.Duration +} +var file_pool_wkt_pool_proto_depIdxs = []int32{ + 1, // 0: WKTNestedPool.ts:type_name -> google.protobuf.Timestamp + 2, // 1: WKTNestedPool.st:type_name -> google.protobuf.Struct + 1, // 2: WKTNestedPool.tss:type_name -> google.protobuf.Timestamp + 2, // 3: WKTNestedPool.sts:type_name -> google.protobuf.Struct + 1, // 4: WKTNestedPool.choice_ts:type_name -> google.protobuf.Timestamp + 3, // 5: WKTNestedPool.choice_dur:type_name -> google.protobuf.Duration + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_pool_wkt_pool_proto_init() } +func file_pool_wkt_pool_proto_init() { + if File_pool_wkt_pool_proto != nil { + return + } + file_pool_wkt_pool_proto_msgTypes[0].OneofWrappers = []any{ + (*WKTNestedPool_ChoiceTs)(nil), + (*WKTNestedPool_ChoiceDur)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_pool_wkt_pool_proto_rawDesc), len(file_pool_wkt_pool_proto_rawDesc)), + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pool_wkt_pool_proto_goTypes, + DependencyIndexes: file_pool_wkt_pool_proto_depIdxs, + MessageInfos: file_pool_wkt_pool_proto_msgTypes, + }.Build() + File_pool_wkt_pool_proto = out.File + file_pool_wkt_pool_proto_goTypes = nil + file_pool_wkt_pool_proto_depIdxs = nil +} diff --git a/testproto/pool/wkt_pool.proto b/testproto/pool/wkt_pool.proto new file mode 100644 index 00000000..e5d7437d --- /dev/null +++ b/testproto/pool/wkt_pool.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; +option go_package = "testproto/pool"; + +import "github.com/planetscale/vtprotobuf/vtproto/ext.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; + +message WKTNestedPool { + option (vtproto.mempool) = true; + google.protobuf.Timestamp ts = 1; + google.protobuf.Struct st = 2; + repeated google.protobuf.Timestamp tss = 3; + repeated google.protobuf.Struct sts = 4; + oneof choice { + google.protobuf.Timestamp choice_ts = 5; + google.protobuf.Duration choice_dur = 6; + } +} diff --git a/testproto/pool/wkt_pool_vtproto.pb.go b/testproto/pool/wkt_pool_vtproto.pb.go new file mode 100644 index 00000000..223cb7a6 --- /dev/null +++ b/testproto/pool/wkt_pool_vtproto.pb.go @@ -0,0 +1,1142 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: (devel) +// source: pool/wkt_pool.proto + +package pool + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + durationpb1 "github.com/planetscale/vtprotobuf/types/known/durationpb" + structpb1 "github.com/planetscale/vtprotobuf/types/known/structpb" + timestamppb1 "github.com/planetscale/vtprotobuf/types/known/timestamppb" + proto "google.golang.org/protobuf/proto" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb "google.golang.org/protobuf/types/known/durationpb" + structpb "google.golang.org/protobuf/types/known/structpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + io "io" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *WKTNestedPool) CloneVT() *WKTNestedPool { + if m == nil { + return (*WKTNestedPool)(nil) + } + r := WKTNestedPoolFromVTPool() + r.Ts = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(m.Ts).CloneVT()) + r.St = (*structpb.Struct)((*structpb1.Struct)(m.St).CloneVT()) + if rhs := m.Tss; rhs != nil { + tmpContainer := make([]*timestamppb.Timestamp, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(v).CloneVT()) + } + r.Tss = tmpContainer + } + if rhs := m.Sts; rhs != nil { + tmpContainer := make([]*structpb.Struct, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = (*structpb.Struct)((*structpb1.Struct)(v).CloneVT()) + } + r.Sts = tmpContainer + } + if m.Choice != nil { + r.Choice = m.Choice.(interface{ CloneVT() isWKTNestedPool_Choice }).CloneVT() + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *WKTNestedPool) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *WKTNestedPool_ChoiceTs) CloneVT() isWKTNestedPool_Choice { + if m == nil { + return (*WKTNestedPool_ChoiceTs)(nil) + } + r := new(WKTNestedPool_ChoiceTs) + r.ChoiceTs = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(m.ChoiceTs).CloneVT()) + return r +} + +func (m *WKTNestedPool_ChoiceDur) CloneVT() isWKTNestedPool_Choice { + if m == nil { + return (*WKTNestedPool_ChoiceDur)(nil) + } + r := new(WKTNestedPool_ChoiceDur) + r.ChoiceDur = (*durationpb.Duration)((*durationpb1.Duration)(m.ChoiceDur).CloneVT()) + return r +} + +func (this *WKTNestedPool) EqualVT(that *WKTNestedPool) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Choice == nil && that.Choice != nil { + return false + } else if this.Choice != nil { + if that.Choice == nil { + return false + } + if !this.Choice.(interface { + EqualVT(isWKTNestedPool_Choice) bool + }).EqualVT(that.Choice) { + return false + } + } + if !(*timestamppb1.Timestamp)(this.Ts).EqualVT((*timestamppb1.Timestamp)(that.Ts)) { + return false + } + if !(*structpb1.Struct)(this.St).EqualVT((*structpb1.Struct)(that.St)) { + return false + } + if len(this.Tss) != len(that.Tss) { + return false + } + for i, vx := range this.Tss { + vy := that.Tss[i] + if p, q := vx, vy; p != q { + if p == nil { + p = ×tamppb.Timestamp{} + } + if q == nil { + q = ×tamppb.Timestamp{} + } + if !(*timestamppb1.Timestamp)(p).EqualVT((*timestamppb1.Timestamp)(q)) { + return false + } + } + } + if len(this.Sts) != len(that.Sts) { + return false + } + for i, vx := range this.Sts { + vy := that.Sts[i] + if p, q := vx, vy; p != q { + if p == nil { + p = &structpb.Struct{} + } + if q == nil { + q = &structpb.Struct{} + } + if !(*structpb1.Struct)(p).EqualVT((*structpb1.Struct)(q)) { + return false + } + } + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *WKTNestedPool) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*WKTNestedPool) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *WKTNestedPool_ChoiceTs) EqualVT(thatIface isWKTNestedPool_Choice) bool { + that, ok := thatIface.(*WKTNestedPool_ChoiceTs) + if !ok { + return false + } + if this == that { + return true + } + if this == nil && that != nil || this != nil && that == nil { + return false + } + if p, q := this.ChoiceTs, that.ChoiceTs; p != q { + if p == nil { + p = ×tamppb.Timestamp{} + } + if q == nil { + q = ×tamppb.Timestamp{} + } + if !(*timestamppb1.Timestamp)(p).EqualVT((*timestamppb1.Timestamp)(q)) { + return false + } + } + return true +} + +func (this *WKTNestedPool_ChoiceDur) EqualVT(thatIface isWKTNestedPool_Choice) bool { + that, ok := thatIface.(*WKTNestedPool_ChoiceDur) + if !ok { + return false + } + if this == that { + return true + } + if this == nil && that != nil || this != nil && that == nil { + return false + } + if p, q := this.ChoiceDur, that.ChoiceDur; p != q { + if p == nil { + p = &durationpb.Duration{} + } + if q == nil { + q = &durationpb.Duration{} + } + if !(*durationpb1.Duration)(p).EqualVT((*durationpb1.Duration)(q)) { + return false + } + } + return true +} + +func (m *WKTNestedPool) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WKTNestedPool) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WKTNestedPool) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if vtmsg, ok := m.Choice.(interface { + MarshalToSizedBufferVT([]byte) (int, error) + }); ok { + size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + } + if len(m.Sts) > 0 { + for iNdEx := len(m.Sts) - 1; iNdEx >= 0; iNdEx-- { + size, err := (*structpb1.Struct)(m.Sts[iNdEx]).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Tss) > 0 { + for iNdEx := len(m.Tss) - 1; iNdEx >= 0; iNdEx-- { + size, err := (*timestamppb1.Timestamp)(m.Tss[iNdEx]).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + } + if m.St != nil { + size, err := (*structpb1.Struct)(m.St).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if m.Ts != nil { + size, err := (*timestamppb1.Timestamp)(m.Ts).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WKTNestedPool_ChoiceTs) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WKTNestedPool_ChoiceTs) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ChoiceTs != nil { + size, err := (*timestamppb1.Timestamp)(m.ChoiceTs).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } else { + i = protohelpers.EncodeVarint(dAtA, i, 0) + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *WKTNestedPool_ChoiceDur) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WKTNestedPool_ChoiceDur) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ChoiceDur != nil { + size, err := (*durationpb1.Duration)(m.ChoiceDur).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } else { + i = protohelpers.EncodeVarint(dAtA, i, 0) + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *WKTNestedPool) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WKTNestedPool) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *WKTNestedPool) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if msg, ok := m.Choice.(*WKTNestedPool_ChoiceDur); ok { + size, err := msg.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + } + if msg, ok := m.Choice.(*WKTNestedPool_ChoiceTs); ok { + size, err := msg.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + } + if len(m.Sts) > 0 { + for iNdEx := len(m.Sts) - 1; iNdEx >= 0; iNdEx-- { + size, err := (*structpb1.Struct)(m.Sts[iNdEx]).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Tss) > 0 { + for iNdEx := len(m.Tss) - 1; iNdEx >= 0; iNdEx-- { + size, err := (*timestamppb1.Timestamp)(m.Tss[iNdEx]).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + } + if m.St != nil { + size, err := (*structpb1.Struct)(m.St).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if m.Ts != nil { + size, err := (*timestamppb1.Timestamp)(m.Ts).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WKTNestedPool_ChoiceTs) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *WKTNestedPool_ChoiceTs) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ChoiceTs != nil { + size, err := (*timestamppb1.Timestamp)(m.ChoiceTs).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } else { + i = protohelpers.EncodeVarint(dAtA, i, 0) + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *WKTNestedPool_ChoiceDur) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *WKTNestedPool_ChoiceDur) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ChoiceDur != nil { + size, err := (*durationpb1.Duration)(m.ChoiceDur).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } else { + i = protohelpers.EncodeVarint(dAtA, i, 0) + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} + +var vtprotoPool_WKTNestedPool = sync.Pool{ + New: func() interface{} { + return &WKTNestedPool{} + }, +} + +func (m *WKTNestedPool) ResetVT() { + if m != nil { + (*timestamppb1.Timestamp)(m.Ts).ReturnToVTPool() + (*structpb1.Struct)(m.St).ReturnToVTPool() + for _, mm := range m.Tss { + (*timestamppb1.Timestamp)(mm).ResetVT() + } + f0 := m.Tss[:0] + for _, mm := range m.Sts { + (*structpb1.Struct)(mm).ResetVT() + } + f1 := m.Sts[:0] + if oneof, ok := m.Choice.(*WKTNestedPool_ChoiceTs); ok { + (*timestamppb1.Timestamp)(oneof.ChoiceTs).ReturnToVTPool() + } + if oneof, ok := m.Choice.(*WKTNestedPool_ChoiceDur); ok { + (*durationpb1.Duration)(oneof.ChoiceDur).ReturnToVTPool() + } + m.Reset() + m.Tss = f0 + m.Sts = f1 + } +} +func (m *WKTNestedPool) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_WKTNestedPool.Put(m) + } +} +func WKTNestedPoolFromVTPool() *WKTNestedPool { + return vtprotoPool_WKTNestedPool.Get().(*WKTNestedPool) +} +func (m *WKTNestedPool) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Ts != nil { + l = (*timestamppb1.Timestamp)(m.Ts).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.St != nil { + l = (*structpb1.Struct)(m.St).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.Tss) > 0 { + for _, e := range m.Tss { + l = (*timestamppb1.Timestamp)(e).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if len(m.Sts) > 0 { + for _, e := range m.Sts { + l = (*structpb1.Struct)(e).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if vtmsg, ok := m.Choice.(interface{ SizeVT() int }); ok { + n += vtmsg.SizeVT() + } + n += len(m.unknownFields) + return n +} + +func (m *WKTNestedPool_ChoiceTs) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ChoiceTs != nil { + l = (*timestamppb1.Timestamp)(m.ChoiceTs).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } else { + n += 2 + } + return n +} +func (m *WKTNestedPool_ChoiceDur) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ChoiceDur != nil { + l = (*durationpb1.Duration)(m.ChoiceDur).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } else { + n += 2 + } + return n +} +func (m *WKTNestedPool) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WKTNestedPool: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WKTNestedPool: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Ts == nil { + m.Ts = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(timestamppb1.TimestampFromVTPool())) + } + if err := (*timestamppb1.Timestamp)(m.Ts).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field St", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.St == nil { + m.St = (*structpb.Struct)((*structpb1.Struct)(structpb1.StructFromVTPool())) + } + if err := (*structpb1.Struct)(m.St).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tss", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if len(m.Tss) == cap(m.Tss) { + m.Tss = append(m.Tss, ×tamppb.Timestamp{}) + } else { + m.Tss = m.Tss[:len(m.Tss)+1] + if m.Tss[len(m.Tss)-1] == nil { + m.Tss[len(m.Tss)-1] = ×tamppb.Timestamp{} + } + } + if err := (*timestamppb1.Timestamp)(m.Tss[len(m.Tss)-1]).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if len(m.Sts) == cap(m.Sts) { + m.Sts = append(m.Sts, &structpb.Struct{}) + } else { + m.Sts = m.Sts[:len(m.Sts)+1] + if m.Sts[len(m.Sts)-1] == nil { + m.Sts[len(m.Sts)-1] = &structpb.Struct{} + } + } + if err := (*structpb1.Struct)(m.Sts[len(m.Sts)-1]).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChoiceTs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Choice.(*WKTNestedPool_ChoiceTs); ok { + if err := (*timestamppb1.Timestamp)(oneof.ChoiceTs).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(timestamppb1.TimestampFromVTPool())) + if err := (*timestamppb1.Timestamp)(v).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Choice = &WKTNestedPool_ChoiceTs{ChoiceTs: v} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChoiceDur", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Choice.(*WKTNestedPool_ChoiceDur); ok { + if err := (*durationpb1.Duration)(oneof.ChoiceDur).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := (*durationpb.Duration)((*durationpb1.Duration)(durationpb1.DurationFromVTPool())) + if err := (*durationpb1.Duration)(v).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Choice = &WKTNestedPool_ChoiceDur{ChoiceDur: v} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WKTNestedPool) UnmarshalVTUnsafe(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WKTNestedPool: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WKTNestedPool: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Ts == nil { + m.Ts = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(timestamppb1.TimestampFromVTPool())) + } + if err := (*timestamppb1.Timestamp)(m.Ts).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field St", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.St == nil { + m.St = (*structpb.Struct)((*structpb1.Struct)(structpb1.StructFromVTPool())) + } + if err := (*structpb1.Struct)(m.St).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tss", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if len(m.Tss) == cap(m.Tss) { + m.Tss = append(m.Tss, ×tamppb.Timestamp{}) + } else { + m.Tss = m.Tss[:len(m.Tss)+1] + if m.Tss[len(m.Tss)-1] == nil { + m.Tss[len(m.Tss)-1] = ×tamppb.Timestamp{} + } + } + if err := (*timestamppb1.Timestamp)(m.Tss[len(m.Tss)-1]).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if len(m.Sts) == cap(m.Sts) { + m.Sts = append(m.Sts, &structpb.Struct{}) + } else { + m.Sts = m.Sts[:len(m.Sts)+1] + if m.Sts[len(m.Sts)-1] == nil { + m.Sts[len(m.Sts)-1] = &structpb.Struct{} + } + } + if err := (*structpb1.Struct)(m.Sts[len(m.Sts)-1]).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChoiceTs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Choice.(*WKTNestedPool_ChoiceTs); ok { + if err := (*timestamppb1.Timestamp)(oneof.ChoiceTs).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(timestamppb1.TimestampFromVTPool())) + if err := (*timestamppb1.Timestamp)(v).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Choice = &WKTNestedPool_ChoiceTs{ChoiceTs: v} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChoiceDur", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Choice.(*WKTNestedPool_ChoiceDur); ok { + if err := (*durationpb1.Duration)(oneof.ChoiceDur).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := (*durationpb.Duration)((*durationpb1.Duration)(durationpb1.DurationFromVTPool())) + if err := (*durationpb1.Duration)(v).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Choice = &WKTNestedPool_ChoiceDur{ChoiceDur: v} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/types/known/anypb/any_vtproto.pb.go b/types/known/anypb/any_vtproto.pb.go index c99b9e61..fd0913a4 100644 --- a/types/known/anypb/any_vtproto.pb.go +++ b/types/known/anypb/any_vtproto.pb.go @@ -10,6 +10,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" anypb "google.golang.org/protobuf/types/known/anypb" io "io" + sync "sync" unsafe "unsafe" ) @@ -26,7 +27,7 @@ func (m *Any) CloneVT() *Any { if m == nil { return (*Any)(nil) } - r := new(Any) + r := AnyFromVTPool() r.TypeUrl = m.TypeUrl if rhs := m.Value; rhs != nil { tmpBytes := make([]byte, len(rhs)) @@ -137,6 +138,28 @@ func (m *Any) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_Any = sync.Pool{ + New: func() interface{} { + return &Any{} + }, +} + +func (m *Any) ResetVT() { + if m != nil { + f0 := m.Value[:0] + (*anypb.Any)(m).Reset() + m.Value = f0 + } +} +func (m *Any) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Any.Put(m) + } +} +func AnyFromVTPool() *Any { + return vtprotoPool_Any.Get().(*Any) +} func (m *Any) SizeVT() (n int) { if m == nil { return 0 diff --git a/types/known/durationpb/duration_vtproto.pb.go b/types/known/durationpb/duration_vtproto.pb.go index 681ae9f7..d5e3cd9c 100644 --- a/types/known/durationpb/duration_vtproto.pb.go +++ b/types/known/durationpb/duration_vtproto.pb.go @@ -10,6 +10,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" io "io" + sync "sync" ) const ( @@ -25,7 +26,7 @@ func (m *Duration) CloneVT() *Duration { if m == nil { return (*Duration)(nil) } - r := new(Duration) + r := DurationFromVTPool() r.Seconds = m.Seconds r.Nanos = m.Nanos return r @@ -124,6 +125,26 @@ func (m *Duration) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_Duration = sync.Pool{ + New: func() interface{} { + return &Duration{} + }, +} + +func (m *Duration) ResetVT() { + if m != nil { + (*durationpb.Duration)(m).Reset() + } +} +func (m *Duration) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Duration.Put(m) + } +} +func DurationFromVTPool() *Duration { + return vtprotoPool_Duration.Get().(*Duration) +} func (m *Duration) SizeVT() (n int) { if m == nil { return 0 diff --git a/types/known/emptypb/empty_vtproto.pb.go b/types/known/emptypb/empty_vtproto.pb.go index 470c82ac..6a5327bd 100644 --- a/types/known/emptypb/empty_vtproto.pb.go +++ b/types/known/emptypb/empty_vtproto.pb.go @@ -10,6 +10,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" io "io" + sync "sync" ) const ( @@ -25,7 +26,7 @@ func (m *Empty) CloneVT() *Empty { if m == nil { return (*Empty)(nil) } - r := new(Empty) + r := EmptyFromVTPool() return r } @@ -96,6 +97,26 @@ func (m *Empty) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_Empty = sync.Pool{ + New: func() interface{} { + return &Empty{} + }, +} + +func (m *Empty) ResetVT() { + if m != nil { + (*emptypb.Empty)(m).Reset() + } +} +func (m *Empty) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Empty.Put(m) + } +} +func EmptyFromVTPool() *Empty { + return vtprotoPool_Empty.Get().(*Empty) +} func (m *Empty) SizeVT() (n int) { if m == nil { return 0 diff --git a/types/known/fieldmaskpb/field_mask_vtproto.pb.go b/types/known/fieldmaskpb/field_mask_vtproto.pb.go index 9f52025d..6e2dd465 100644 --- a/types/known/fieldmaskpb/field_mask_vtproto.pb.go +++ b/types/known/fieldmaskpb/field_mask_vtproto.pb.go @@ -10,6 +10,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" io "io" + sync "sync" unsafe "unsafe" ) @@ -26,7 +27,7 @@ func (m *FieldMask) CloneVT() *FieldMask { if m == nil { return (*FieldMask)(nil) } - r := new(FieldMask) + r := FieldMaskFromVTPool() if rhs := m.Paths; rhs != nil { tmpContainer := make([]string, len(rhs)) copy(tmpContainer, rhs) @@ -129,6 +130,29 @@ func (m *FieldMask) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_FieldMask = sync.Pool{ + New: func() interface{} { + return &FieldMask{} + }, +} + +func (m *FieldMask) ResetVT() { + if m != nil { + clear(m.Paths) + f0 := m.Paths[:0] + (*fieldmaskpb.FieldMask)(m).Reset() + m.Paths = f0 + } +} +func (m *FieldMask) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_FieldMask.Put(m) + } +} +func FieldMaskFromVTPool() *FieldMask { + return vtprotoPool_FieldMask.Get().(*FieldMask) +} func (m *FieldMask) SizeVT() (n int) { if m == nil { return 0 diff --git a/types/known/structpb/struct_vtproto.pb.go b/types/known/structpb/struct_vtproto.pb.go index 0699c097..d244be73 100644 --- a/types/known/structpb/struct_vtproto.pb.go +++ b/types/known/structpb/struct_vtproto.pb.go @@ -12,6 +12,7 @@ import ( structpb "google.golang.org/protobuf/types/known/structpb" io "io" math "math" + sync "sync" unsafe "unsafe" ) @@ -36,7 +37,7 @@ func (m *Struct) CloneVT() *Struct { if m == nil { return (*Struct)(nil) } - r := new(Struct) + r := StructFromVTPool() if rhs := m.Fields; rhs != nil { tmpContainer := make(map[string]*structpb.Value, len(rhs)) for k, v := range rhs { @@ -51,7 +52,7 @@ func (m *Value) CloneVT() *Value { if m == nil { return (*Value)(nil) } - r := new(Value) + r := ValueFromVTPool() if m.Kind != nil { switch c := m.Kind.(type) { case *structpb.Value_NullValue: @@ -129,7 +130,7 @@ func (m *ListValue) CloneVT() *ListValue { if m == nil { return (*ListValue)(nil) } - r := new(ListValue) + r := ListValueFromVTPool() if rhs := m.Values; rhs != nil { tmpContainer := make([]*structpb.Value, len(rhs)) for k, v := range rhs { @@ -911,6 +912,79 @@ func (m *ListValue) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_Struct = sync.Pool{ + New: func() interface{} { + return &Struct{} + }, +} + +func (m *Struct) ResetVT() { + if m != nil { + (*structpb.Struct)(m).Reset() + } +} +func (m *Struct) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Struct.Put(m) + } +} +func StructFromVTPool() *Struct { + return vtprotoPool_Struct.Get().(*Struct) +} + +var vtprotoPool_Value = sync.Pool{ + New: func() interface{} { + return &Value{} + }, +} + +func (m *Value) ResetVT() { + if m != nil { + if oneof, ok := m.Kind.(*structpb.Value_StructValue); ok { + (*Struct)(oneof.StructValue).ReturnToVTPool() + } + if oneof, ok := m.Kind.(*structpb.Value_ListValue); ok { + (*ListValue)(oneof.ListValue).ReturnToVTPool() + } + (*structpb.Value)(m).Reset() + } +} +func (m *Value) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Value.Put(m) + } +} +func ValueFromVTPool() *Value { + return vtprotoPool_Value.Get().(*Value) +} + +var vtprotoPool_ListValue = sync.Pool{ + New: func() interface{} { + return &ListValue{} + }, +} + +func (m *ListValue) ResetVT() { + if m != nil { + for _, mm := range m.Values { + (*Value)(mm).ResetVT() + } + f0 := m.Values[:0] + (*structpb.ListValue)(m).Reset() + m.Values = f0 + } +} +func (m *ListValue) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_ListValue.Put(m) + } +} +func ListValueFromVTPool() *ListValue { + return vtprotoPool_ListValue.Get().(*ListValue) +} func (m *Struct) SizeVT() (n int) { if m == nil { return 0 @@ -1362,11 +1436,11 @@ func (m *Value) UnmarshalVT(dAtA []byte) error { return err } } else { - v := &structpb.Struct{} + v := StructFromVTPool() if err := (*Struct)(v).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } - m.Kind = &structpb.Value_StructValue{StructValue: v} + m.Kind = &structpb.Value_StructValue{StructValue: (*structpb.Struct)(v)} } iNdEx = postIndex case 6: @@ -1403,11 +1477,11 @@ func (m *Value) UnmarshalVT(dAtA []byte) error { return err } } else { - v := &structpb.ListValue{} + v := ListValueFromVTPool() if err := (*ListValue)(v).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } - m.Kind = &structpb.Value_ListValue{ListValue: v} + m.Kind = &structpb.Value_ListValue{ListValue: (*structpb.ListValue)(v)} } iNdEx = postIndex default: @@ -1489,7 +1563,14 @@ func (m *ListValue) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Values = append(m.Values, &structpb.Value{}) + if len(m.Values) == cap(m.Values) { + m.Values = append(m.Values, &structpb.Value{}) + } else { + m.Values = m.Values[:len(m.Values)+1] + if m.Values[len(m.Values)-1] == nil { + m.Values[len(m.Values)-1] = &structpb.Value{} + } + } if err := (*Value)(m.Values[len(m.Values)-1]).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1849,11 +1930,11 @@ func (m *Value) UnmarshalVTUnsafe(dAtA []byte) error { return err } } else { - v := &structpb.Struct{} + v := StructFromVTPool() if err := (*Struct)(v).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { return err } - m.Kind = &structpb.Value_StructValue{StructValue: v} + m.Kind = &structpb.Value_StructValue{StructValue: (*structpb.Struct)(v)} } iNdEx = postIndex case 6: @@ -1890,11 +1971,11 @@ func (m *Value) UnmarshalVTUnsafe(dAtA []byte) error { return err } } else { - v := &structpb.ListValue{} + v := ListValueFromVTPool() if err := (*ListValue)(v).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { return err } - m.Kind = &structpb.Value_ListValue{ListValue: v} + m.Kind = &structpb.Value_ListValue{ListValue: (*structpb.ListValue)(v)} } iNdEx = postIndex default: @@ -1976,7 +2057,14 @@ func (m *ListValue) UnmarshalVTUnsafe(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Values = append(m.Values, &structpb.Value{}) + if len(m.Values) == cap(m.Values) { + m.Values = append(m.Values, &structpb.Value{}) + } else { + m.Values = m.Values[:len(m.Values)+1] + if m.Values[len(m.Values)-1] == nil { + m.Values[len(m.Values)-1] = &structpb.Value{} + } + } if err := (*Value)(m.Values[len(m.Values)-1]).UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil { return err } diff --git a/types/known/timestamppb/timestamp_vtproto.pb.go b/types/known/timestamppb/timestamp_vtproto.pb.go index 5c63f308..5540cac0 100644 --- a/types/known/timestamppb/timestamp_vtproto.pb.go +++ b/types/known/timestamppb/timestamp_vtproto.pb.go @@ -10,6 +10,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" io "io" + sync "sync" ) const ( @@ -25,7 +26,7 @@ func (m *Timestamp) CloneVT() *Timestamp { if m == nil { return (*Timestamp)(nil) } - r := new(Timestamp) + r := TimestampFromVTPool() r.Seconds = m.Seconds r.Nanos = m.Nanos return r @@ -124,6 +125,26 @@ func (m *Timestamp) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_Timestamp = sync.Pool{ + New: func() interface{} { + return &Timestamp{} + }, +} + +func (m *Timestamp) ResetVT() { + if m != nil { + (*timestamppb.Timestamp)(m).Reset() + } +} +func (m *Timestamp) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Timestamp.Put(m) + } +} +func TimestampFromVTPool() *Timestamp { + return vtprotoPool_Timestamp.Get().(*Timestamp) +} func (m *Timestamp) SizeVT() (n int) { if m == nil { return 0 diff --git a/types/known/wrapperspb/wrappers_vtproto.pb.go b/types/known/wrapperspb/wrappers_vtproto.pb.go index 0dac9b28..9c6cac8b 100644 --- a/types/known/wrapperspb/wrappers_vtproto.pb.go +++ b/types/known/wrapperspb/wrappers_vtproto.pb.go @@ -12,6 +12,7 @@ import ( wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" io "io" math "math" + sync "sync" unsafe "unsafe" ) @@ -36,7 +37,7 @@ func (m *DoubleValue) CloneVT() *DoubleValue { if m == nil { return (*DoubleValue)(nil) } - r := new(DoubleValue) + r := DoubleValueFromVTPool() r.Value = m.Value return r } @@ -45,7 +46,7 @@ func (m *FloatValue) CloneVT() *FloatValue { if m == nil { return (*FloatValue)(nil) } - r := new(FloatValue) + r := FloatValueFromVTPool() r.Value = m.Value return r } @@ -54,7 +55,7 @@ func (m *Int64Value) CloneVT() *Int64Value { if m == nil { return (*Int64Value)(nil) } - r := new(Int64Value) + r := Int64ValueFromVTPool() r.Value = m.Value return r } @@ -63,7 +64,7 @@ func (m *UInt64Value) CloneVT() *UInt64Value { if m == nil { return (*UInt64Value)(nil) } - r := new(UInt64Value) + r := UInt64ValueFromVTPool() r.Value = m.Value return r } @@ -72,7 +73,7 @@ func (m *Int32Value) CloneVT() *Int32Value { if m == nil { return (*Int32Value)(nil) } - r := new(Int32Value) + r := Int32ValueFromVTPool() r.Value = m.Value return r } @@ -81,7 +82,7 @@ func (m *UInt32Value) CloneVT() *UInt32Value { if m == nil { return (*UInt32Value)(nil) } - r := new(UInt32Value) + r := UInt32ValueFromVTPool() r.Value = m.Value return r } @@ -90,7 +91,7 @@ func (m *BoolValue) CloneVT() *BoolValue { if m == nil { return (*BoolValue)(nil) } - r := new(BoolValue) + r := BoolValueFromVTPool() r.Value = m.Value return r } @@ -99,7 +100,7 @@ func (m *StringValue) CloneVT() *StringValue { if m == nil { return (*StringValue)(nil) } - r := new(StringValue) + r := StringValueFromVTPool() r.Value = m.Value return r } @@ -108,7 +109,7 @@ func (m *BytesValue) CloneVT() *BytesValue { if m == nil { return (*BytesValue)(nil) } - r := new(BytesValue) + r := BytesValueFromVTPool() if rhs := m.Value; rhs != nil { tmpBytes := make([]byte, len(rhs)) copy(tmpBytes, rhs) @@ -859,6 +860,196 @@ func (m *BytesValue) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +var vtprotoPool_DoubleValue = sync.Pool{ + New: func() interface{} { + return &DoubleValue{} + }, +} + +func (m *DoubleValue) ResetVT() { + if m != nil { + (*wrapperspb.DoubleValue)(m).Reset() + } +} +func (m *DoubleValue) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_DoubleValue.Put(m) + } +} +func DoubleValueFromVTPool() *DoubleValue { + return vtprotoPool_DoubleValue.Get().(*DoubleValue) +} + +var vtprotoPool_FloatValue = sync.Pool{ + New: func() interface{} { + return &FloatValue{} + }, +} + +func (m *FloatValue) ResetVT() { + if m != nil { + (*wrapperspb.FloatValue)(m).Reset() + } +} +func (m *FloatValue) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_FloatValue.Put(m) + } +} +func FloatValueFromVTPool() *FloatValue { + return vtprotoPool_FloatValue.Get().(*FloatValue) +} + +var vtprotoPool_Int64Value = sync.Pool{ + New: func() interface{} { + return &Int64Value{} + }, +} + +func (m *Int64Value) ResetVT() { + if m != nil { + (*wrapperspb.Int64Value)(m).Reset() + } +} +func (m *Int64Value) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Int64Value.Put(m) + } +} +func Int64ValueFromVTPool() *Int64Value { + return vtprotoPool_Int64Value.Get().(*Int64Value) +} + +var vtprotoPool_UInt64Value = sync.Pool{ + New: func() interface{} { + return &UInt64Value{} + }, +} + +func (m *UInt64Value) ResetVT() { + if m != nil { + (*wrapperspb.UInt64Value)(m).Reset() + } +} +func (m *UInt64Value) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_UInt64Value.Put(m) + } +} +func UInt64ValueFromVTPool() *UInt64Value { + return vtprotoPool_UInt64Value.Get().(*UInt64Value) +} + +var vtprotoPool_Int32Value = sync.Pool{ + New: func() interface{} { + return &Int32Value{} + }, +} + +func (m *Int32Value) ResetVT() { + if m != nil { + (*wrapperspb.Int32Value)(m).Reset() + } +} +func (m *Int32Value) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Int32Value.Put(m) + } +} +func Int32ValueFromVTPool() *Int32Value { + return vtprotoPool_Int32Value.Get().(*Int32Value) +} + +var vtprotoPool_UInt32Value = sync.Pool{ + New: func() interface{} { + return &UInt32Value{} + }, +} + +func (m *UInt32Value) ResetVT() { + if m != nil { + (*wrapperspb.UInt32Value)(m).Reset() + } +} +func (m *UInt32Value) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_UInt32Value.Put(m) + } +} +func UInt32ValueFromVTPool() *UInt32Value { + return vtprotoPool_UInt32Value.Get().(*UInt32Value) +} + +var vtprotoPool_BoolValue = sync.Pool{ + New: func() interface{} { + return &BoolValue{} + }, +} + +func (m *BoolValue) ResetVT() { + if m != nil { + (*wrapperspb.BoolValue)(m).Reset() + } +} +func (m *BoolValue) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_BoolValue.Put(m) + } +} +func BoolValueFromVTPool() *BoolValue { + return vtprotoPool_BoolValue.Get().(*BoolValue) +} + +var vtprotoPool_StringValue = sync.Pool{ + New: func() interface{} { + return &StringValue{} + }, +} + +func (m *StringValue) ResetVT() { + if m != nil { + (*wrapperspb.StringValue)(m).Reset() + } +} +func (m *StringValue) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_StringValue.Put(m) + } +} +func StringValueFromVTPool() *StringValue { + return vtprotoPool_StringValue.Get().(*StringValue) +} + +var vtprotoPool_BytesValue = sync.Pool{ + New: func() interface{} { + return &BytesValue{} + }, +} + +func (m *BytesValue) ResetVT() { + if m != nil { + f0 := m.Value[:0] + (*wrapperspb.BytesValue)(m).Reset() + m.Value = f0 + } +} +func (m *BytesValue) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_BytesValue.Put(m) + } +} +func BytesValueFromVTPool() *BytesValue { + return vtprotoPool_BytesValue.Get().(*BytesValue) +} func (m *DoubleValue) SizeVT() (n int) { if m == nil { return 0 From d7e54e7fbe36f3b7bc3be84b542b001620663965 Mon Sep 17 00:00:00 2001 From: "Samani G. Gikandi" Date: Wed, 30 Sep 2026 11:46:59 -0700 Subject: [PATCH 2/4] feat(pool): adds pooling for maps This diff refactors #156 to add support for pooling maps. **Caveats** * Just like with pooled slices, pooled maps do not shrink. This is a footgun we may want to document explicitly. --- Makefile | 1 + features/pool/pool.go | 15 +- testproto/pool/pool_test.go | 52 + testproto/pool/pool_with_map_reuse.pb.go | 383 +++ testproto/pool/pool_with_map_reuse.proto | 32 + .../pool/pool_with_map_reuse_vtproto.pb.go | 2700 +++++++++++++++++ 6 files changed, 3182 insertions(+), 1 deletion(-) create mode 100644 testproto/pool/pool_with_map_reuse.pb.go create mode 100644 testproto/pool/pool_with_map_reuse.proto create mode 100644 testproto/pool/pool_with_map_reuse_vtproto.pb.go diff --git a/Makefile b/Makefile index f9b795cc..bb789a1f 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,7 @@ gen-testproto: get-grpc-testproto gen-wkt-testproto install testproto/empty/empty.proto \ testproto/pool/pool.proto \ testproto/pool/pool_with_slice_reuse.proto \ + testproto/pool/pool_with_map_reuse.proto \ testproto/pool/pool_with_oneof.proto \ testproto/pool/wkt_pool.proto \ testproto/proto3opt/opt.proto \ diff --git a/features/pool/pool.go b/features/pool/pool.go index 5521406a..a76a5078 100644 --- a/features/pool/pool.go +++ b/features/pool/pool.go @@ -68,6 +68,19 @@ func (p *pool) message(message *protogen.Message) { } p.P(fmt.Sprintf("f%d", len(saved)), ` := m.`, fieldName, `[:0]`) saved = append(saved, field) + } else if field.Desc.IsMap() { + // Pooled message values go back to their pool; other values are dropped + // by clear. The map itself is kept so its buckets are reused. + if valueField := field.Message.Fields[1]; valueField.Message != nil && p.ShouldPool(valueField.Message) { + p.P(`for _, v := range m.`, fieldName, `{`) + p.P(`if v != nil {`) + p.PReturnToVTPool("v", valueField.Message) + p.P(`}`) + p.P(`}`) + } + p.P(`clear(m.`, fieldName, `)`) + p.P(fmt.Sprintf("f%d", len(saved)), ` := m.`, fieldName) + saved = append(saved, field) } else if field.Oneof != nil && !field.Oneof.Desc.IsSynthetic() { if p.ShouldPool(field.Message) { p.P(`if oneof, ok := m.`, field.Oneof.GoName, `.(*`, field.GoIdent, `); ok {`) @@ -77,7 +90,7 @@ func (p *pool) message(message *protogen.Message) { } else { switch field.Desc.Kind() { case protoreflect.MessageKind, protoreflect.GroupKind: - if !field.Desc.IsMap() && p.ShouldPool(field.Message) { + if p.ShouldPool(field.Message) { p.PReturnToVTPool("m."+fieldName, field.Message) } case protoreflect.BytesKind: diff --git a/testproto/pool/pool_test.go b/testproto/pool/pool_test.go index 259d2ab4..46235c54 100644 --- a/testproto/pool/pool_test.go +++ b/testproto/pool/pool_test.go @@ -284,3 +284,55 @@ func Test_WKT_nested_pool_reuse(t *testing.T) { clone.ReturnToVTPool() }) } + +func Test_Pool_Reuse_Map(t *testing.T) { + allocs := testing.AllocsPerRun(10, func() { + obj := MapReuseTest1FromVTPool() + if obj.GetIntToStringMap() == nil { + obj.IntToStringMap = make(map[int32]string) + } + obj.IntToStringMap[1] = "test1" + obj.IntToStringMap[2] = "test2" + obj.IntToStringMap[3] = "test3" + if obj.GetStringToEnumMap() == nil { + obj.StringToEnumMap = make(map[string]MapReuseTest1_TEST) + } + obj.StringToEnumMap["test1"] = MapReuseTest1_test1 + obj.StringToEnumMap["test2"] = MapReuseTest1_test2 + obj.ReturnToVTPool() + }) + require.Less(t, int(allocs), 1) +} + +func Test_Pool_Map_PooledValues(t *testing.T) { + v := MapReuseTest1FromVTPool() + v.IntToStringMap = map[int32]string{1: "a"} + + obj := MapReuseTest2FromVTPool() + obj.Count = 7 + obj.IntToMapReuseTest1Map = map[int32]*MapReuseTest1{1: v, 2: nil} + obj.IntToTestObjWithoutPoolMap = map[int32]*TestObjWithoutPool{1: {Name: "x"}, 2: nil} + + // nil map values must not panic + require.NotPanics(t, obj.ReturnToVTPool) + + // values returned to the pool are reset + require.Empty(t, v.IntToStringMap) + + got := MapReuseTest2FromVTPool() + require.Zero(t, got.Count) + require.Empty(t, got.IntToMapReuseTest1Map) + require.Empty(t, got.IntToTestObjWithoutPoolMap) + got.ReturnToVTPool() +} + +func Test_Pool_Map_NilMapAndWKTValues(t *testing.T) { + require.NotPanics(t, func() { MapReuseTest2FromVTPool().ReturnToVTPool() }) + + obj := MapReuseTest3FromVTPool() + obj.StringToTimestampMap = map[string]*timestamppb.Timestamp{"a": timestamppb.Now(), "b": nil} + obj.ReturnToVTPool() + got := MapReuseTest3FromVTPool() + require.Empty(t, got.StringToTimestampMap) + got.ReturnToVTPool() +} diff --git a/testproto/pool/pool_with_map_reuse.pb.go b/testproto/pool/pool_with_map_reuse.pb.go new file mode 100644 index 00000000..f4bd3026 --- /dev/null +++ b/testproto/pool/pool_with_map_reuse.pb.go @@ -0,0 +1,383 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.10 +// protoc v3.21.12 +// source: pool/pool_with_map_reuse.proto + +package pool + +import ( + _ "github.com/planetscale/vtprotobuf/vtproto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type MapReuseTest1_TEST int32 + +const ( + MapReuseTest1_test1 MapReuseTest1_TEST = 0 + MapReuseTest1_test2 MapReuseTest1_TEST = 1 +) + +// Enum value maps for MapReuseTest1_TEST. +var ( + MapReuseTest1_TEST_name = map[int32]string{ + 0: "test1", + 1: "test2", + } + MapReuseTest1_TEST_value = map[string]int32{ + "test1": 0, + "test2": 1, + } +) + +func (x MapReuseTest1_TEST) Enum() *MapReuseTest1_TEST { + p := new(MapReuseTest1_TEST) + *p = x + return p +} + +func (x MapReuseTest1_TEST) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MapReuseTest1_TEST) Descriptor() protoreflect.EnumDescriptor { + return file_pool_pool_with_map_reuse_proto_enumTypes[0].Descriptor() +} + +func (MapReuseTest1_TEST) Type() protoreflect.EnumType { + return &file_pool_pool_with_map_reuse_proto_enumTypes[0] +} + +func (x MapReuseTest1_TEST) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MapReuseTest1_TEST.Descriptor instead. +func (MapReuseTest1_TEST) EnumDescriptor() ([]byte, []int) { + return file_pool_pool_with_map_reuse_proto_rawDescGZIP(), []int{0, 0} +} + +type MapReuseTest1 struct { + state protoimpl.MessageState `protogen:"open.v1"` + IntToStringMap map[int32]string `protobuf:"bytes,1,rep,name=intToStringMap,proto3" json:"intToStringMap,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + StringToEnumMap map[string]MapReuseTest1_TEST `protobuf:"bytes,2,rep,name=stringToEnumMap,proto3" json:"stringToEnumMap,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value,enum=MapReuseTest1_TEST"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MapReuseTest1) Reset() { + *x = MapReuseTest1{} + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MapReuseTest1) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapReuseTest1) ProtoMessage() {} + +func (x *MapReuseTest1) ProtoReflect() protoreflect.Message { + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapReuseTest1.ProtoReflect.Descriptor instead. +func (*MapReuseTest1) Descriptor() ([]byte, []int) { + return file_pool_pool_with_map_reuse_proto_rawDescGZIP(), []int{0} +} + +func (x *MapReuseTest1) GetIntToStringMap() map[int32]string { + if x != nil { + return x.IntToStringMap + } + return nil +} + +func (x *MapReuseTest1) GetStringToEnumMap() map[string]MapReuseTest1_TEST { + if x != nil { + return x.StringToEnumMap + } + return nil +} + +type TestObjWithoutPool struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Age uint64 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TestObjWithoutPool) Reset() { + *x = TestObjWithoutPool{} + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TestObjWithoutPool) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestObjWithoutPool) ProtoMessage() {} + +func (x *TestObjWithoutPool) ProtoReflect() protoreflect.Message { + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestObjWithoutPool.ProtoReflect.Descriptor instead. +func (*TestObjWithoutPool) Descriptor() ([]byte, []int) { + return file_pool_pool_with_map_reuse_proto_rawDescGZIP(), []int{1} +} + +func (x *TestObjWithoutPool) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TestObjWithoutPool) GetAge() uint64 { + if x != nil { + return x.Age + } + return 0 +} + +type MapReuseTest2 struct { + state protoimpl.MessageState `protogen:"open.v1"` + IntToMapReuseTest1Map map[int32]*MapReuseTest1 `protobuf:"bytes,1,rep,name=intToMapReuseTest1Map,proto3" json:"intToMapReuseTest1Map,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + IntToTestObjWithoutPoolMap map[int32]*TestObjWithoutPool `protobuf:"bytes,2,rep,name=intToTestObjWithoutPoolMap,proto3" json:"intToTestObjWithoutPoolMap,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Count uint32 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MapReuseTest2) Reset() { + *x = MapReuseTest2{} + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MapReuseTest2) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapReuseTest2) ProtoMessage() {} + +func (x *MapReuseTest2) ProtoReflect() protoreflect.Message { + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapReuseTest2.ProtoReflect.Descriptor instead. +func (*MapReuseTest2) Descriptor() ([]byte, []int) { + return file_pool_pool_with_map_reuse_proto_rawDescGZIP(), []int{2} +} + +func (x *MapReuseTest2) GetIntToMapReuseTest1Map() map[int32]*MapReuseTest1 { + if x != nil { + return x.IntToMapReuseTest1Map + } + return nil +} + +func (x *MapReuseTest2) GetIntToTestObjWithoutPoolMap() map[int32]*TestObjWithoutPool { + if x != nil { + return x.IntToTestObjWithoutPoolMap + } + return nil +} + +func (x *MapReuseTest2) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +type MapReuseTest3 struct { + state protoimpl.MessageState `protogen:"open.v1"` + StringToTimestampMap map[string]*timestamppb.Timestamp `protobuf:"bytes,1,rep,name=stringToTimestampMap,proto3" json:"stringToTimestampMap,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MapReuseTest3) Reset() { + *x = MapReuseTest3{} + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MapReuseTest3) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapReuseTest3) ProtoMessage() {} + +func (x *MapReuseTest3) ProtoReflect() protoreflect.Message { + mi := &file_pool_pool_with_map_reuse_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapReuseTest3.ProtoReflect.Descriptor instead. +func (*MapReuseTest3) Descriptor() ([]byte, []int) { + return file_pool_pool_with_map_reuse_proto_rawDescGZIP(), []int{3} +} + +func (x *MapReuseTest3) GetStringToTimestampMap() map[string]*timestamppb.Timestamp { + if x != nil { + return x.StringToTimestampMap + } + return nil +} + +var File_pool_pool_with_map_reuse_proto protoreflect.FileDescriptor + +const file_pool_pool_with_map_reuse_proto_rawDesc = "" + + "\n" + + "\x1epool/pool_with_map_reuse.proto\x1a3github.com/planetscale/vtprotobuf/vtproto/ext.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xea\x02\n" + + "\rMapReuseTest1\x12J\n" + + "\x0eintToStringMap\x18\x01 \x03(\v2\".MapReuseTest1.IntToStringMapEntryR\x0eintToStringMap\x12M\n" + + "\x0fstringToEnumMap\x18\x02 \x03(\v2#.MapReuseTest1.StringToEnumMapEntryR\x0fstringToEnumMap\x1aA\n" + + "\x13IntToStringMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\x05R\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1aW\n" + + "\x14StringToEnumMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12)\n" + + "\x05value\x18\x02 \x01(\x0e2\x13.MapReuseTest1.TESTR\x05value:\x028\x01\"\x1c\n" + + "\x04TEST\x12\t\n" + + "\x05test1\x10\x00\x12\t\n" + + "\x05test2\x10\x01:\x04\xa8\xa6\x1f\x01\":\n" + + "\x12TestObjWithoutPool\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x10\n" + + "\x03age\x18\x02 \x01(\x04R\x03age\"\xba\x03\n" + + "\rMapReuseTest2\x12_\n" + + "\x15intToMapReuseTest1Map\x18\x01 \x03(\v2).MapReuseTest2.IntToMapReuseTest1MapEntryR\x15intToMapReuseTest1Map\x12n\n" + + "\x1aintToTestObjWithoutPoolMap\x18\x02 \x03(\v2..MapReuseTest2.IntToTestObjWithoutPoolMapEntryR\x1aintToTestObjWithoutPoolMap\x12\x14\n" + + "\x05count\x18\x03 \x01(\rR\x05count\x1aX\n" + + "\x1aIntToMapReuseTest1MapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\x05R\x03key\x12$\n" + + "\x05value\x18\x02 \x01(\v2\x0e.MapReuseTest1R\x05value:\x028\x01\x1ab\n" + + "\x1fIntToTestObjWithoutPoolMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\x05R\x03key\x12)\n" + + "\x05value\x18\x02 \x01(\v2\x13.TestObjWithoutPoolR\x05value:\x028\x01:\x04\xa8\xa6\x1f\x01\"\xd8\x01\n" + + "\rMapReuseTest3\x12\\\n" + + "\x14stringToTimestampMap\x18\x01 \x03(\v2(.MapReuseTest3.StringToTimestampMapEntryR\x14stringToTimestampMap\x1ac\n" + + "\x19StringToTimestampMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x120\n" + + "\x05value\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x05value:\x028\x01:\x04\xa8\xa6\x1f\x01B\x10Z\x0etestproto/poolb\x06proto3" + +var ( + file_pool_pool_with_map_reuse_proto_rawDescOnce sync.Once + file_pool_pool_with_map_reuse_proto_rawDescData []byte +) + +func file_pool_pool_with_map_reuse_proto_rawDescGZIP() []byte { + file_pool_pool_with_map_reuse_proto_rawDescOnce.Do(func() { + file_pool_pool_with_map_reuse_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_pool_pool_with_map_reuse_proto_rawDesc), len(file_pool_pool_with_map_reuse_proto_rawDesc))) + }) + return file_pool_pool_with_map_reuse_proto_rawDescData +} + +var file_pool_pool_with_map_reuse_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pool_pool_with_map_reuse_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_pool_pool_with_map_reuse_proto_goTypes = []any{ + (MapReuseTest1_TEST)(0), // 0: MapReuseTest1.TEST + (*MapReuseTest1)(nil), // 1: MapReuseTest1 + (*TestObjWithoutPool)(nil), // 2: TestObjWithoutPool + (*MapReuseTest2)(nil), // 3: MapReuseTest2 + (*MapReuseTest3)(nil), // 4: MapReuseTest3 + nil, // 5: MapReuseTest1.IntToStringMapEntry + nil, // 6: MapReuseTest1.StringToEnumMapEntry + nil, // 7: MapReuseTest2.IntToMapReuseTest1MapEntry + nil, // 8: MapReuseTest2.IntToTestObjWithoutPoolMapEntry + nil, // 9: MapReuseTest3.StringToTimestampMapEntry + (*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp +} +var file_pool_pool_with_map_reuse_proto_depIdxs = []int32{ + 5, // 0: MapReuseTest1.intToStringMap:type_name -> MapReuseTest1.IntToStringMapEntry + 6, // 1: MapReuseTest1.stringToEnumMap:type_name -> MapReuseTest1.StringToEnumMapEntry + 7, // 2: MapReuseTest2.intToMapReuseTest1Map:type_name -> MapReuseTest2.IntToMapReuseTest1MapEntry + 8, // 3: MapReuseTest2.intToTestObjWithoutPoolMap:type_name -> MapReuseTest2.IntToTestObjWithoutPoolMapEntry + 9, // 4: MapReuseTest3.stringToTimestampMap:type_name -> MapReuseTest3.StringToTimestampMapEntry + 0, // 5: MapReuseTest1.StringToEnumMapEntry.value:type_name -> MapReuseTest1.TEST + 1, // 6: MapReuseTest2.IntToMapReuseTest1MapEntry.value:type_name -> MapReuseTest1 + 2, // 7: MapReuseTest2.IntToTestObjWithoutPoolMapEntry.value:type_name -> TestObjWithoutPool + 10, // 8: MapReuseTest3.StringToTimestampMapEntry.value:type_name -> google.protobuf.Timestamp + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name +} + +func init() { file_pool_pool_with_map_reuse_proto_init() } +func file_pool_pool_with_map_reuse_proto_init() { + if File_pool_pool_with_map_reuse_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_pool_pool_with_map_reuse_proto_rawDesc), len(file_pool_pool_with_map_reuse_proto_rawDesc)), + NumEnums: 1, + NumMessages: 9, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pool_pool_with_map_reuse_proto_goTypes, + DependencyIndexes: file_pool_pool_with_map_reuse_proto_depIdxs, + EnumInfos: file_pool_pool_with_map_reuse_proto_enumTypes, + MessageInfos: file_pool_pool_with_map_reuse_proto_msgTypes, + }.Build() + File_pool_pool_with_map_reuse_proto = out.File + file_pool_pool_with_map_reuse_proto_goTypes = nil + file_pool_pool_with_map_reuse_proto_depIdxs = nil +} diff --git a/testproto/pool/pool_with_map_reuse.proto b/testproto/pool/pool_with_map_reuse.proto new file mode 100644 index 00000000..3e83a09c --- /dev/null +++ b/testproto/pool/pool_with_map_reuse.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; +option go_package = "testproto/pool"; + +import "github.com/planetscale/vtprotobuf/vtproto/ext.proto"; +import "google/protobuf/timestamp.proto"; + +message MapReuseTest1 { + option (vtproto.mempool) = true; + enum TEST { + test1 = 0; + test2 = 1; + } + map intToStringMap = 1; + map stringToEnumMap = 2; +} + +message TestObjWithoutPool { + string name = 1; + uint64 age = 2; +} + +message MapReuseTest2 { + option (vtproto.mempool) = true; + map intToMapReuseTest1Map = 1; + map intToTestObjWithoutPoolMap = 2; + uint32 count = 3; +} + +message MapReuseTest3 { + option (vtproto.mempool) = true; + map stringToTimestampMap = 1; +} diff --git a/testproto/pool/pool_with_map_reuse_vtproto.pb.go b/testproto/pool/pool_with_map_reuse_vtproto.pb.go new file mode 100644 index 00000000..c0a77297 --- /dev/null +++ b/testproto/pool/pool_with_map_reuse_vtproto.pb.go @@ -0,0 +1,2700 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: (devel) +// source: pool/pool_with_map_reuse.proto + +package pool + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + timestamppb1 "github.com/planetscale/vtprotobuf/types/known/timestamppb" + proto "google.golang.org/protobuf/proto" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + io "io" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *MapReuseTest1) CloneVT() *MapReuseTest1 { + if m == nil { + return (*MapReuseTest1)(nil) + } + r := MapReuseTest1FromVTPool() + if rhs := m.IntToStringMap; rhs != nil { + tmpContainer := make(map[int32]string, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v + } + r.IntToStringMap = tmpContainer + } + if rhs := m.StringToEnumMap; rhs != nil { + tmpContainer := make(map[string]MapReuseTest1_TEST, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v + } + r.StringToEnumMap = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *MapReuseTest1) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *TestObjWithoutPool) CloneVT() *TestObjWithoutPool { + if m == nil { + return (*TestObjWithoutPool)(nil) + } + r := new(TestObjWithoutPool) + r.Name = m.Name + r.Age = m.Age + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *TestObjWithoutPool) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *MapReuseTest2) CloneVT() *MapReuseTest2 { + if m == nil { + return (*MapReuseTest2)(nil) + } + r := MapReuseTest2FromVTPool() + r.Count = m.Count + if rhs := m.IntToMapReuseTest1Map; rhs != nil { + tmpContainer := make(map[int32]*MapReuseTest1, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.IntToMapReuseTest1Map = tmpContainer + } + if rhs := m.IntToTestObjWithoutPoolMap; rhs != nil { + tmpContainer := make(map[int32]*TestObjWithoutPool, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.IntToTestObjWithoutPoolMap = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *MapReuseTest2) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *MapReuseTest3) CloneVT() *MapReuseTest3 { + if m == nil { + return (*MapReuseTest3)(nil) + } + r := MapReuseTest3FromVTPool() + if rhs := m.StringToTimestampMap; rhs != nil { + tmpContainer := make(map[string]*timestamppb.Timestamp, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(v).CloneVT()) + } + r.StringToTimestampMap = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *MapReuseTest3) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (this *MapReuseTest1) EqualVT(that *MapReuseTest1) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if len(this.IntToStringMap) != len(that.IntToStringMap) { + return false + } + for i, vx := range this.IntToStringMap { + vy, ok := that.IntToStringMap[i] + if !ok { + return false + } + if vx != vy { + return false + } + } + if len(this.StringToEnumMap) != len(that.StringToEnumMap) { + return false + } + for i, vx := range this.StringToEnumMap { + vy, ok := that.StringToEnumMap[i] + if !ok { + return false + } + if vx != vy { + return false + } + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *MapReuseTest1) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*MapReuseTest1) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *TestObjWithoutPool) EqualVT(that *TestObjWithoutPool) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Name != that.Name { + return false + } + if this.Age != that.Age { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *TestObjWithoutPool) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*TestObjWithoutPool) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *MapReuseTest2) EqualVT(that *MapReuseTest2) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if len(this.IntToMapReuseTest1Map) != len(that.IntToMapReuseTest1Map) { + return false + } + for i, vx := range this.IntToMapReuseTest1Map { + vy, ok := that.IntToMapReuseTest1Map[i] + if !ok { + return false + } + if p, q := vx, vy; p != q { + if p == nil { + p = &MapReuseTest1{} + } + if q == nil { + q = &MapReuseTest1{} + } + if !p.EqualVT(q) { + return false + } + } + } + if len(this.IntToTestObjWithoutPoolMap) != len(that.IntToTestObjWithoutPoolMap) { + return false + } + for i, vx := range this.IntToTestObjWithoutPoolMap { + vy, ok := that.IntToTestObjWithoutPoolMap[i] + if !ok { + return false + } + if p, q := vx, vy; p != q { + if p == nil { + p = &TestObjWithoutPool{} + } + if q == nil { + q = &TestObjWithoutPool{} + } + if !p.EqualVT(q) { + return false + } + } + } + if this.Count != that.Count { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *MapReuseTest2) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*MapReuseTest2) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *MapReuseTest3) EqualVT(that *MapReuseTest3) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if len(this.StringToTimestampMap) != len(that.StringToTimestampMap) { + return false + } + for i, vx := range this.StringToTimestampMap { + vy, ok := that.StringToTimestampMap[i] + if !ok { + return false + } + if p, q := vx, vy; p != q { + if p == nil { + p = ×tamppb.Timestamp{} + } + if q == nil { + q = ×tamppb.Timestamp{} + } + if !(*timestamppb1.Timestamp)(p).EqualVT((*timestamppb1.Timestamp)(q)) { + return false + } + } + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *MapReuseTest3) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*MapReuseTest3) + if !ok { + return false + } + return this.EqualVT(that) +} +func (m *MapReuseTest1) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MapReuseTest1) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *MapReuseTest1) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.StringToEnumMap) > 0 { + for k := range m.StringToEnumMap { + v := m.StringToEnumMap[k] + baseI := i + i = protohelpers.EncodeVarint(dAtA, i, uint64(v)) + i-- + dAtA[i] = 0x10 + i -= len(k) + copy(dAtA[i:], k) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.IntToStringMap) > 0 { + for k := range m.IntToStringMap { + v := m.IntToStringMap[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i = protohelpers.EncodeVarint(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *TestObjWithoutPool) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TestObjWithoutPool) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TestObjWithoutPool) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Age != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Age)) + i-- + dAtA[i] = 0x10 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MapReuseTest2) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MapReuseTest2) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *MapReuseTest2) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Count != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Count)) + i-- + dAtA[i] = 0x18 + } + if len(m.IntToTestObjWithoutPoolMap) > 0 { + for k := range m.IntToTestObjWithoutPoolMap { + v := m.IntToTestObjWithoutPoolMap[k] + baseI := i + size, err := v.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i = protohelpers.EncodeVarint(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.IntToMapReuseTest1Map) > 0 { + for k := range m.IntToMapReuseTest1Map { + v := m.IntToMapReuseTest1Map[k] + baseI := i + size, err := v.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i = protohelpers.EncodeVarint(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *MapReuseTest3) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MapReuseTest3) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *MapReuseTest3) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.StringToTimestampMap) > 0 { + for k := range m.StringToTimestampMap { + v := m.StringToTimestampMap[k] + baseI := i + size, err := (*timestamppb1.Timestamp)(v).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *MapReuseTest1) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MapReuseTest1) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *MapReuseTest1) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.StringToEnumMap) > 0 { + for k := range m.StringToEnumMap { + v := m.StringToEnumMap[k] + baseI := i + i = protohelpers.EncodeVarint(dAtA, i, uint64(v)) + i-- + dAtA[i] = 0x10 + i -= len(k) + copy(dAtA[i:], k) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.IntToStringMap) > 0 { + for k := range m.IntToStringMap { + v := m.IntToStringMap[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i = protohelpers.EncodeVarint(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *TestObjWithoutPool) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TestObjWithoutPool) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TestObjWithoutPool) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Age != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Age)) + i-- + dAtA[i] = 0x10 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MapReuseTest2) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MapReuseTest2) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *MapReuseTest2) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Count != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Count)) + i-- + dAtA[i] = 0x18 + } + if len(m.IntToTestObjWithoutPoolMap) > 0 { + for k := range m.IntToTestObjWithoutPoolMap { + v := m.IntToTestObjWithoutPoolMap[k] + baseI := i + size, err := v.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i = protohelpers.EncodeVarint(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.IntToMapReuseTest1Map) > 0 { + for k := range m.IntToMapReuseTest1Map { + v := m.IntToMapReuseTest1Map[k] + baseI := i + size, err := v.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i = protohelpers.EncodeVarint(dAtA, i, uint64(k)) + i-- + dAtA[i] = 0x8 + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *MapReuseTest3) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MapReuseTest3) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *MapReuseTest3) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.StringToTimestampMap) > 0 { + for k := range m.StringToTimestampMap { + v := m.StringToTimestampMap[k] + baseI := i + size, err := (*timestamppb1.Timestamp)(v).MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = protohelpers.EncodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +var vtprotoPool_MapReuseTest1 = sync.Pool{ + New: func() interface{} { + return &MapReuseTest1{} + }, +} + +func (m *MapReuseTest1) ResetVT() { + if m != nil { + clear(m.IntToStringMap) + f0 := m.IntToStringMap + clear(m.StringToEnumMap) + f1 := m.StringToEnumMap + m.Reset() + m.IntToStringMap = f0 + m.StringToEnumMap = f1 + } +} +func (m *MapReuseTest1) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_MapReuseTest1.Put(m) + } +} +func MapReuseTest1FromVTPool() *MapReuseTest1 { + return vtprotoPool_MapReuseTest1.Get().(*MapReuseTest1) +} + +var vtprotoPool_MapReuseTest2 = sync.Pool{ + New: func() interface{} { + return &MapReuseTest2{} + }, +} + +func (m *MapReuseTest2) ResetVT() { + if m != nil { + for _, v := range m.IntToMapReuseTest1Map { + if v != nil { + v.ReturnToVTPool() + } + } + clear(m.IntToMapReuseTest1Map) + f0 := m.IntToMapReuseTest1Map + clear(m.IntToTestObjWithoutPoolMap) + f1 := m.IntToTestObjWithoutPoolMap + m.Reset() + m.IntToMapReuseTest1Map = f0 + m.IntToTestObjWithoutPoolMap = f1 + } +} +func (m *MapReuseTest2) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_MapReuseTest2.Put(m) + } +} +func MapReuseTest2FromVTPool() *MapReuseTest2 { + return vtprotoPool_MapReuseTest2.Get().(*MapReuseTest2) +} + +var vtprotoPool_MapReuseTest3 = sync.Pool{ + New: func() interface{} { + return &MapReuseTest3{} + }, +} + +func (m *MapReuseTest3) ResetVT() { + if m != nil { + for _, v := range m.StringToTimestampMap { + if v != nil { + (*timestamppb1.Timestamp)(v).ReturnToVTPool() + } + } + clear(m.StringToTimestampMap) + f0 := m.StringToTimestampMap + m.Reset() + m.StringToTimestampMap = f0 + } +} +func (m *MapReuseTest3) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_MapReuseTest3.Put(m) + } +} +func MapReuseTest3FromVTPool() *MapReuseTest3 { + return vtprotoPool_MapReuseTest3.Get().(*MapReuseTest3) +} +func (m *MapReuseTest1) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.IntToStringMap) > 0 { + for k, v := range m.IntToStringMap { + _ = k + _ = v + mapEntrySize := 1 + protohelpers.SizeOfVarint(uint64(k)) + 1 + len(v) + protohelpers.SizeOfVarint(uint64(len(v))) + n += mapEntrySize + 1 + protohelpers.SizeOfVarint(uint64(mapEntrySize)) + } + } + if len(m.StringToEnumMap) > 0 { + for k, v := range m.StringToEnumMap { + _ = k + _ = v + mapEntrySize := 1 + len(k) + protohelpers.SizeOfVarint(uint64(len(k))) + 1 + protohelpers.SizeOfVarint(uint64(v)) + n += mapEntrySize + 1 + protohelpers.SizeOfVarint(uint64(mapEntrySize)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *TestObjWithoutPool) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Age != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Age)) + } + n += len(m.unknownFields) + return n +} + +func (m *MapReuseTest2) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.IntToMapReuseTest1Map) > 0 { + for k, v := range m.IntToMapReuseTest1Map { + _ = k + _ = v + l = 0 + if v != nil { + l = v.SizeVT() + } + l += 1 + protohelpers.SizeOfVarint(uint64(l)) + mapEntrySize := 1 + protohelpers.SizeOfVarint(uint64(k)) + l + n += mapEntrySize + 1 + protohelpers.SizeOfVarint(uint64(mapEntrySize)) + } + } + if len(m.IntToTestObjWithoutPoolMap) > 0 { + for k, v := range m.IntToTestObjWithoutPoolMap { + _ = k + _ = v + l = 0 + if v != nil { + l = v.SizeVT() + } + l += 1 + protohelpers.SizeOfVarint(uint64(l)) + mapEntrySize := 1 + protohelpers.SizeOfVarint(uint64(k)) + l + n += mapEntrySize + 1 + protohelpers.SizeOfVarint(uint64(mapEntrySize)) + } + } + if m.Count != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Count)) + } + n += len(m.unknownFields) + return n +} + +func (m *MapReuseTest3) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.StringToTimestampMap) > 0 { + for k, v := range m.StringToTimestampMap { + _ = k + _ = v + l = 0 + if v != nil { + l = (*timestamppb1.Timestamp)(v).SizeVT() + } + l += 1 + protohelpers.SizeOfVarint(uint64(l)) + mapEntrySize := 1 + len(k) + protohelpers.SizeOfVarint(uint64(len(k))) + l + n += mapEntrySize + 1 + protohelpers.SizeOfVarint(uint64(mapEntrySize)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *MapReuseTest1) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MapReuseTest1: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MapReuseTest1: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntToStringMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IntToStringMap == nil { + m.IntToStringMap = make(map[int32]string) + } + var mapkey int32 + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.IntToStringMap[mapkey] = mapvalue + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StringToEnumMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.StringToEnumMap == nil { + m.StringToEnumMap = make(map[string]MapReuseTest1_TEST) + } + var mapkey string + var mapvalue MapReuseTest1_TEST + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= MapReuseTest1_TEST(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.StringToEnumMap[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TestObjWithoutPool) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TestObjWithoutPool: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TestObjWithoutPool: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Age", wireType) + } + m.Age = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Age |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MapReuseTest2) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MapReuseTest2: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MapReuseTest2: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntToMapReuseTest1Map", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IntToMapReuseTest1Map == nil { + m.IntToMapReuseTest1Map = make(map[int32]*MapReuseTest1) + } + var mapkey int32 + var mapvalue *MapReuseTest1 + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return protohelpers.ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &MapReuseTest1{} + if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.IntToMapReuseTest1Map[mapkey] = mapvalue + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntToTestObjWithoutPoolMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IntToTestObjWithoutPoolMap == nil { + m.IntToTestObjWithoutPoolMap = make(map[int32]*TestObjWithoutPool) + } + var mapkey int32 + var mapvalue *TestObjWithoutPool + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return protohelpers.ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &TestObjWithoutPool{} + if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.IntToTestObjWithoutPoolMap[mapkey] = mapvalue + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Count", wireType) + } + m.Count = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Count |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MapReuseTest3) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MapReuseTest3: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MapReuseTest3: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StringToTimestampMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.StringToTimestampMap == nil { + m.StringToTimestampMap = make(map[string]*timestamppb.Timestamp) + } + var mapkey string + var mapvalue *timestamppb.Timestamp + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return protohelpers.ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = ×tamppb.Timestamp{} + if err := (*timestamppb1.Timestamp)(mapvalue).UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.StringToTimestampMap[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MapReuseTest1) UnmarshalVTUnsafe(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MapReuseTest1: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MapReuseTest1: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntToStringMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IntToStringMap == nil { + m.IntToStringMap = make(map[int32]string) + } + var mapkey int32 + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + if intStringLenmapvalue == 0 { + mapvalue = "" + } else { + mapvalue = unsafe.String(&dAtA[iNdEx], intStringLenmapvalue) + } + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.IntToStringMap[mapkey] = mapvalue + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StringToEnumMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.StringToEnumMap == nil { + m.StringToEnumMap = make(map[string]MapReuseTest1_TEST) + } + var mapkey string + var mapvalue MapReuseTest1_TEST + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + if intStringLenmapkey == 0 { + mapkey = "" + } else { + mapkey = unsafe.String(&dAtA[iNdEx], intStringLenmapkey) + } + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= MapReuseTest1_TEST(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.StringToEnumMap[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TestObjWithoutPool) UnmarshalVTUnsafe(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TestObjWithoutPool: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TestObjWithoutPool: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var stringValue string + if intStringLen > 0 { + stringValue = unsafe.String(&dAtA[iNdEx], intStringLen) + } + m.Name = stringValue + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Age", wireType) + } + m.Age = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Age |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MapReuseTest2) UnmarshalVTUnsafe(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MapReuseTest2: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MapReuseTest2: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntToMapReuseTest1Map", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IntToMapReuseTest1Map == nil { + m.IntToMapReuseTest1Map = make(map[int32]*MapReuseTest1) + } + var mapkey int32 + var mapvalue *MapReuseTest1 + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return protohelpers.ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &MapReuseTest1{} + if err := mapvalue.UnmarshalVTUnsafe(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.IntToMapReuseTest1Map[mapkey] = mapvalue + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IntToTestObjWithoutPoolMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IntToTestObjWithoutPoolMap == nil { + m.IntToTestObjWithoutPoolMap = make(map[int32]*TestObjWithoutPool) + } + var mapkey int32 + var mapvalue *TestObjWithoutPool + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapkey |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return protohelpers.ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &TestObjWithoutPool{} + if err := mapvalue.UnmarshalVTUnsafe(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.IntToTestObjWithoutPoolMap[mapkey] = mapvalue + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Count", wireType) + } + m.Count = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Count |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MapReuseTest3) UnmarshalVTUnsafe(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MapReuseTest3: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MapReuseTest3: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StringToTimestampMap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.StringToTimestampMap == nil { + m.StringToTimestampMap = make(map[string]*timestamppb.Timestamp) + } + var mapkey string + var mapvalue *timestamppb.Timestamp + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return protohelpers.ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return protohelpers.ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + if intStringLenmapkey == 0 { + mapkey = "" + } else { + mapkey = unsafe.String(&dAtA[iNdEx], intStringLenmapkey) + } + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return protohelpers.ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = ×tamppb.Timestamp{} + if err := (*timestamppb1.Timestamp)(mapvalue).UnmarshalVTUnsafe(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.StringToTimestampMap[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} From 2c5329d682e393f336172c4fc783ad633dfc5ebb Mon Sep 17 00:00:00 2001 From: "Samani G. Gikandi" Date: Wed, 30 Sep 2026 12:17:32 -0700 Subject: [PATCH 3/4] chore: regenerates wkt wrappers This diff regenerates the wkt wrappers with map pooling support. --- types/known/structpb/struct_vtproto.pb.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/types/known/structpb/struct_vtproto.pb.go b/types/known/structpb/struct_vtproto.pb.go index d244be73..cd1a9922 100644 --- a/types/known/structpb/struct_vtproto.pb.go +++ b/types/known/structpb/struct_vtproto.pb.go @@ -920,7 +920,15 @@ var vtprotoPool_Struct = sync.Pool{ func (m *Struct) ResetVT() { if m != nil { + for _, v := range m.Fields { + if v != nil { + (*Value)(v).ReturnToVTPool() + } + } + clear(m.Fields) + f0 := m.Fields (*structpb.Struct)(m).Reset() + m.Fields = f0 } } func (m *Struct) ReturnToVTPool() { From f768d86bb99e92091d4c538c48914d11ae86ff3a Mon Sep 17 00:00:00 2001 From: "Samani G. Gikandi" Date: Wed, 30 Sep 2026 14:54:02 -0700 Subject: [PATCH 4/4] feat(pool): adds pool support for maps during unmarshal This diff updates the generated unmarshal code to pull map values from pools when pooling is enabled for both parent messages and the value type. **Caveats** * If a given key is repeated, the old pooled value will be dropped and picked up by GC. This is done for simplicity. * If unmarshal fails partway through, any values pulled from the pool will be left for GC. This behavior matches what happens with oneof's. --- features/unmarshal/unmarshal.go | 12 +- generator/generatedfile.go | 16 +- testproto/pool/pool_test.go | 160 ++++++++++++------ .../pool/pool_with_map_reuse_vtproto.pb.go | 8 +- types/known/structpb/pool_map_test.go | 25 +++ types/known/structpb/struct_vtproto.pb.go | 4 +- 6 files changed, 165 insertions(+), 60 deletions(-) create mode 100644 types/known/structpb/pool_map_test.go diff --git a/features/unmarshal/unmarshal.go b/features/unmarshal/unmarshal.go index 61f9c6f7..31a1b577 100644 --- a/features/unmarshal/unmarshal.go +++ b/features/unmarshal/unmarshal.go @@ -157,7 +157,7 @@ func (p *unmarshal) declareMapField(varName string, nullable bool, field *protog } } -func (p *unmarshal) mapField(varName string, field *protogen.Field, unique bool) { +func (p *unmarshal) mapField(varName string, field *protogen.Field, unique, pool bool) { switch field.Desc.Kind() { case protoreflect.DoubleKind: p.P(`var `, varName, `temp uint64`) @@ -226,7 +226,11 @@ func (p *unmarshal) mapField(varName string, field *protogen.Field, unique bool) p.P(`return `, p.Ident("io", `ErrUnexpectedEOF`)) p.P(`}`) buf := `dAtA[iNdEx:postmsgIndex]` - p.P(varName, ` = &`, p.noStarOrSliceType(field), `{}`) + if pool { + p.PAssignFromVTPool(varName, field.Message) + } else { + p.P(varName, ` = &`, p.noStarOrSliceType(field), `{}`) + } p.decodeMessage(varName, buf, field.Message) p.P(`iNdEx = postmsgIndex`) case protoreflect.BytesKind: @@ -531,9 +535,9 @@ func (p *unmarshal) fieldItem(field *protogen.Field, fieldname string, message * p.P(`fieldNum := int32(wire >> 3)`) p.P(`if fieldNum == 1 {`) - p.mapField("mapkey", field.Message.Fields[0], unique) + p.mapField("mapkey", field.Message.Fields[0], unique, false) p.P(`} else if fieldNum == 2 {`) - p.mapField("mapvalue", field.Message.Fields[1], unique) + p.mapField("mapvalue", field.Message.Fields[1], unique, p.ShouldPool(message) && p.ShouldPool(field.Message.Fields[1].Message)) p.P(`} else {`) p.P(`iNdEx = entryPreIndex`) p.P(`skippy, err := `, p.Helper("Skip"), `(dAtA[iNdEx:])`) diff --git a/generator/generatedfile.go b/generator/generatedfile.go index dfc85849..5f2da578 100644 --- a/generator/generatedfile.go +++ b/generator/generatedfile.go @@ -80,7 +80,19 @@ func (p *GeneratedFile) PDeclFromVTPool(vname string, message *protogen.Message) // PAssignFromVTPool emits `target = `. Caller must ensure ShouldPool(message). func (p *GeneratedFile) PAssignFromVTPool(target string, message *protogen.Message) { - p.P(append([]any{target, " = "}, p.fromVTPool(message)...)...) + expr := p.fromVTPool(message) + if p.IsLocalWrapper(message) { + // The wrapper shares its layout with the underlying message, which is the type targets hold. + expr = p.convertExpr(message, expr) + } + p.P(append([]any{target, " = "}, expr...)...) +} + +// convertExpr wraps expr in a pointer conversion to the message's own Go type. +func (p *GeneratedFile) convertExpr(message *protogen.Message, expr []any) []any { + out := []any{"(*", p.QualifiedGoIdent(message.GoIdent), ")("} + out = append(out, expr...) + return append(out, ")") } func (p *GeneratedFile) fromVTPool(message *protogen.Message) []any { @@ -259,7 +271,7 @@ func (p *GeneratedFile) Wrapper() bool { return p.Config.Wrap } -// IsLocalWrapper is true if the (wrap=true) is true for the message. +// IsLocalWrapper is true when wrap=true and the message belongs to a locally generated package. func (p *GeneratedFile) IsLocalWrapper(message *protogen.Message) bool { return p.Wrapper() && p.IsLocalMessage(message) } diff --git a/testproto/pool/pool_test.go b/testproto/pool/pool_test.go index 46235c54..b3dff9e8 100644 --- a/testproto/pool/pool_test.go +++ b/testproto/pool/pool_test.go @@ -285,54 +285,118 @@ func Test_WKT_nested_pool_reuse(t *testing.T) { }) } -func Test_Pool_Reuse_Map(t *testing.T) { - allocs := testing.AllocsPerRun(10, func() { - obj := MapReuseTest1FromVTPool() - if obj.GetIntToStringMap() == nil { - obj.IntToStringMap = make(map[int32]string) - } - obj.IntToStringMap[1] = "test1" - obj.IntToStringMap[2] = "test2" - obj.IntToStringMap[3] = "test3" - if obj.GetStringToEnumMap() == nil { - obj.StringToEnumMap = make(map[string]MapReuseTest1_TEST) - } - obj.StringToEnumMap["test1"] = MapReuseTest1_test1 - obj.StringToEnumMap["test2"] = MapReuseTest1_test2 - obj.ReturnToVTPool() +func Test_Pool_Map(t *testing.T) { + t.Run("reset", func(t *testing.T) { + t.Run("reuses map allocation", func(t *testing.T) { + allocs := testing.AllocsPerRun(10, func() { + obj := MapReuseTest1FromVTPool() + if obj.GetIntToStringMap() == nil { + obj.IntToStringMap = make(map[int32]string) + } + obj.IntToStringMap[1] = "test1" + obj.IntToStringMap[2] = "test2" + obj.IntToStringMap[3] = "test3" + if obj.GetStringToEnumMap() == nil { + obj.StringToEnumMap = make(map[string]MapReuseTest1_TEST) + } + obj.StringToEnumMap["test1"] = MapReuseTest1_test1 + obj.StringToEnumMap["test2"] = MapReuseTest1_test2 + obj.ReturnToVTPool() + }) + require.Less(t, int(allocs), 1) + }) + + t.Run("returns pooled values and tolerates nil values", func(t *testing.T) { + v := MapReuseTest1FromVTPool() + v.IntToStringMap = map[int32]string{1: "a"} + + obj := MapReuseTest2FromVTPool() + obj.Count = 7 + obj.IntToMapReuseTest1Map = map[int32]*MapReuseTest1{1: v, 2: nil} + obj.IntToTestObjWithoutPoolMap = map[int32]*TestObjWithoutPool{1: {Name: "x"}, 2: nil} + + require.NotPanics(t, obj.ReturnToVTPool) + require.Empty(t, v.IntToStringMap) // returned values are reset + + got := MapReuseTest2FromVTPool() + require.Zero(t, got.Count) + require.Empty(t, got.IntToMapReuseTest1Map) + require.Empty(t, got.IntToTestObjWithoutPoolMap) + got.ReturnToVTPool() + }) + + t.Run("nil map and WKT values", func(t *testing.T) { + require.NotPanics(t, func() { MapReuseTest2FromVTPool().ReturnToVTPool() }) + + obj := MapReuseTest3FromVTPool() + obj.StringToTimestampMap = map[string]*timestamppb.Timestamp{"a": timestamppb.Now(), "b": nil} + obj.ReturnToVTPool() + got := MapReuseTest3FromVTPool() + require.Empty(t, got.StringToTimestampMap) + got.ReturnToVTPool() + }) }) - require.Less(t, int(allocs), 1) -} - -func Test_Pool_Map_PooledValues(t *testing.T) { - v := MapReuseTest1FromVTPool() - v.IntToStringMap = map[int32]string{1: "a"} - - obj := MapReuseTest2FromVTPool() - obj.Count = 7 - obj.IntToMapReuseTest1Map = map[int32]*MapReuseTest1{1: v, 2: nil} - obj.IntToTestObjWithoutPoolMap = map[int32]*TestObjWithoutPool{1: {Name: "x"}, 2: nil} - - // nil map values must not panic - require.NotPanics(t, obj.ReturnToVTPool) - // values returned to the pool are reset - require.Empty(t, v.IntToStringMap) - - got := MapReuseTest2FromVTPool() - require.Zero(t, got.Count) - require.Empty(t, got.IntToMapReuseTest1Map) - require.Empty(t, got.IntToTestObjWithoutPoolMap) - got.ReturnToVTPool() -} - -func Test_Pool_Map_NilMapAndWKTValues(t *testing.T) { - require.NotPanics(t, func() { MapReuseTest2FromVTPool().ReturnToVTPool() }) - - obj := MapReuseTest3FromVTPool() - obj.StringToTimestampMap = map[string]*timestamppb.Timestamp{"a": timestamppb.Now(), "b": nil} - obj.ReturnToVTPool() - got := MapReuseTest3FromVTPool() - require.Empty(t, got.StringToTimestampMap) - got.ReturnToVTPool() + t.Run("unmarshal", func(t *testing.T) { + t.Run("round trip into dirtied pooled parent", func(t *testing.T) { + src := &MapReuseTest2{ + Count: 3, + IntToMapReuseTest1Map: map[int32]*MapReuseTest1{ + 1: {IntToStringMap: map[int32]string{1: "a", 2: "b"}}, + 2: {StringToEnumMap: map[string]MapReuseTest1_TEST{"x": MapReuseTest1_test2}}, + }, + IntToTestObjWithoutPoolMap: map[int32]*TestObjWithoutPool{1: {Name: "n", Age: 9}}, + } + data, err := src.MarshalVT() + require.NoError(t, err) + + // Dirty the pool first so stale state would show up. + dirty := MapReuseTest2FromVTPool() + dirty.Count = 99 + dirty.IntToMapReuseTest1Map = map[int32]*MapReuseTest1{7: MapReuseTest1FromVTPool()} + dirty.IntToMapReuseTest1Map[7].IntToStringMap = map[int32]string{7: "stale"} + dirty.ReturnToVTPool() + + got := MapReuseTest2FromVTPool() + require.NoError(t, got.UnmarshalVT(data)) + require.True(t, proto.Equal(src, got)) + got.ReturnToVTPool() + }) + + t.Run("WKT values", func(t *testing.T) { + src := &MapReuseTest3{StringToTimestampMap: map[string]*timestamppb.Timestamp{ + "a": timestamppb.New(time.Unix(10, 5)), + "b": timestamppb.New(time.Unix(20, 0)), + }} + data, err := src.MarshalVT() + require.NoError(t, err) + + for range 3 { + got := MapReuseTest3FromVTPool() + require.NoError(t, got.UnmarshalVT(data)) + require.True(t, proto.Equal(src, got)) + got.ReturnToVTPool() + } + }) + + t.Run("allocates fewer values than unpooled", func(t *testing.T) { + src := &MapReuseTest2{IntToMapReuseTest1Map: map[int32]*MapReuseTest1{ + 1: {StringToEnumMap: map[string]MapReuseTest1_TEST{"x": MapReuseTest1_test2}}, + }} + data, err := src.MarshalVT() + require.NoError(t, err) + + // The StringToEnumMap key string still allocates on every unmarshal, + // so compare against the unpooled path instead of asserting zero. + pooled := testing.AllocsPerRun(20, func() { + m := MapReuseTest2FromVTPool() + _ = m.UnmarshalVT(data) + m.ReturnToVTPool() + }) + unpooled := testing.AllocsPerRun(20, func() { + _ = (&MapReuseTest2{}).UnmarshalVT(data) + }) + require.Less(t, pooled, unpooled) + }) + }) } diff --git a/testproto/pool/pool_with_map_reuse_vtproto.pb.go b/testproto/pool/pool_with_map_reuse_vtproto.pb.go index c0a77297..10607d68 100644 --- a/testproto/pool/pool_with_map_reuse_vtproto.pb.go +++ b/testproto/pool/pool_with_map_reuse_vtproto.pb.go @@ -1465,7 +1465,7 @@ func (m *MapReuseTest2) UnmarshalVT(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &MapReuseTest1{} + mapvalue = MapReuseTest1FromVTPool() if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -1779,7 +1779,7 @@ func (m *MapReuseTest3) UnmarshalVT(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = ×tamppb.Timestamp{} + mapvalue = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(timestamppb1.TimestampFromVTPool())) if err := (*timestamppb1.Timestamp)(mapvalue).UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -2336,7 +2336,7 @@ func (m *MapReuseTest2) UnmarshalVTUnsafe(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &MapReuseTest1{} + mapvalue = MapReuseTest1FromVTPool() if err := mapvalue.UnmarshalVTUnsafe(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -2654,7 +2654,7 @@ func (m *MapReuseTest3) UnmarshalVTUnsafe(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = ×tamppb.Timestamp{} + mapvalue = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(timestamppb1.TimestampFromVTPool())) if err := (*timestamppb1.Timestamp)(mapvalue).UnmarshalVTUnsafe(dAtA[iNdEx:postmsgIndex]); err != nil { return err } diff --git a/types/known/structpb/pool_map_test.go b/types/known/structpb/pool_map_test.go new file mode 100644 index 00000000..c7b7cba2 --- /dev/null +++ b/types/known/structpb/pool_map_test.go @@ -0,0 +1,25 @@ +package structpb + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + structpb "google.golang.org/protobuf/types/known/structpb" +) + +func TestStructPooledFieldsRoundTrip(t *testing.T) { + src, err := structpb.NewStruct(map[string]any{ + "a": 1.0, "b": "s", "c": []any{1.0, "x"}, "d": map[string]any{"k": true}, + }) + require.NoError(t, err) + data, err := proto.Marshal(src) + require.NoError(t, err) + + for i := 0; i < 3; i++ { + got := StructFromVTPool() + require.NoError(t, got.UnmarshalVT(data)) + require.True(t, proto.Equal(src, (*structpb.Struct)(got))) + got.ReturnToVTPool() + } +} diff --git a/types/known/structpb/struct_vtproto.pb.go b/types/known/structpb/struct_vtproto.pb.go index cd1a9922..baa90254 100644 --- a/types/known/structpb/struct_vtproto.pb.go +++ b/types/known/structpb/struct_vtproto.pb.go @@ -1254,7 +1254,7 @@ func (m *Struct) UnmarshalVT(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &structpb.Value{} + mapvalue = (*structpb.Value)(ValueFromVTPool()) if err := (*Value)(mapvalue).UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { return err } @@ -1744,7 +1744,7 @@ func (m *Struct) UnmarshalVTUnsafe(dAtA []byte) error { if postmsgIndex > l { return io.ErrUnexpectedEOF } - mapvalue = &structpb.Value{} + mapvalue = (*structpb.Value)(ValueFromVTPool()) if err := (*Value)(mapvalue).UnmarshalVTUnsafe(dAtA[iNdEx:postmsgIndex]); err != nil { return err }