From 735be12481cdc3edfcbca3500172d2164255e1a3 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Fri, 2 Jul 2021 13:03:10 +0200 Subject: force github.com/spf13/cobra@v1.1.3 v1.2.0 is breaking CI (see containers/podman/pull/10844). Signed-off-by: Valentin Rothberg --- .../google.golang.org/grpc/encoding/proto/proto.go | 70 +++++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) (limited to 'vendor/google.golang.org/grpc/encoding') diff --git a/vendor/google.golang.org/grpc/encoding/proto/proto.go b/vendor/google.golang.org/grpc/encoding/proto/proto.go index 3009b35af..66b97a6f6 100644 --- a/vendor/google.golang.org/grpc/encoding/proto/proto.go +++ b/vendor/google.golang.org/grpc/encoding/proto/proto.go @@ -21,7 +21,8 @@ package proto import ( - "fmt" + "math" + "sync" "github.com/golang/protobuf/proto" "google.golang.org/grpc/encoding" @@ -37,22 +38,73 @@ func init() { // codec is a Codec implementation with protobuf. It is the default codec for gRPC. type codec struct{} +type cachedProtoBuffer struct { + lastMarshaledSize uint32 + proto.Buffer +} + +func capToMaxInt32(val int) uint32 { + if val > math.MaxInt32 { + return uint32(math.MaxInt32) + } + return uint32(val) +} + +func marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) { + protoMsg := v.(proto.Message) + newSlice := make([]byte, 0, cb.lastMarshaledSize) + + cb.SetBuf(newSlice) + cb.Reset() + if err := cb.Marshal(protoMsg); err != nil { + return nil, err + } + out := cb.Bytes() + cb.lastMarshaledSize = capToMaxInt32(len(out)) + return out, nil +} + func (codec) Marshal(v interface{}) ([]byte, error) { - vv, ok := v.(proto.Message) - if !ok { - return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v) + if pm, ok := v.(proto.Marshaler); ok { + // object can marshal itself, no need for buffer + return pm.Marshal() } - return proto.Marshal(vv) + + cb := protoBufferPool.Get().(*cachedProtoBuffer) + out, err := marshal(v, cb) + + // put back buffer and lose the ref to the slice + cb.SetBuf(nil) + protoBufferPool.Put(cb) + return out, err } func (codec) Unmarshal(data []byte, v interface{}) error { - vv, ok := v.(proto.Message) - if !ok { - return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v) + protoMsg := v.(proto.Message) + protoMsg.Reset() + + if pu, ok := protoMsg.(proto.Unmarshaler); ok { + // object can unmarshal itself, no need for buffer + return pu.Unmarshal(data) } - return proto.Unmarshal(data, vv) + + cb := protoBufferPool.Get().(*cachedProtoBuffer) + cb.SetBuf(data) + err := cb.Unmarshal(protoMsg) + cb.SetBuf(nil) + protoBufferPool.Put(cb) + return err } func (codec) Name() string { return Name } + +var protoBufferPool = &sync.Pool{ + New: func() interface{} { + return &cachedProtoBuffer{ + Buffer: proto.Buffer{}, + lastMarshaledSize: 16, + } + }, +} -- cgit v1.2.3-54-g00ecf