mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
This puts us on a version that has grpc protocol support. Although we're not actually using that yet, the plugin has handshake changed slightly to allow plugins to declare whether they use the old or new protocols, and so this upgrade allows us to support plugins that were built against newer versions of go-plugin that include this extra field in the handshake. This fixes #15756.
105 lines
2.6 KiB
Go
105 lines
2.6 KiB
Go
/*
|
|
*
|
|
* Copyright 2014 gRPC authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
package grpc
|
|
|
|
import (
|
|
"math"
|
|
"sync"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
)
|
|
|
|
// Codec defines the interface gRPC uses to encode and decode messages.
|
|
// Note that implementations of this interface must be thread safe;
|
|
// a Codec's methods can be called from concurrent goroutines.
|
|
type Codec interface {
|
|
// Marshal returns the wire format of v.
|
|
Marshal(v interface{}) ([]byte, error)
|
|
// Unmarshal parses the wire format into v.
|
|
Unmarshal(data []byte, v interface{}) error
|
|
// String returns the name of the Codec implementation. The returned
|
|
// string will be used as part of content type in transmission.
|
|
String() string
|
|
}
|
|
|
|
// protoCodec is a Codec implementation with protobuf. It is the default codec for gRPC.
|
|
type protoCodec 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 (p protoCodec) 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 (p protoCodec) Marshal(v interface{}) ([]byte, error) {
|
|
cb := protoBufferPool.Get().(*cachedProtoBuffer)
|
|
out, err := p.marshal(v, cb)
|
|
|
|
// put back buffer and lose the ref to the slice
|
|
cb.SetBuf(nil)
|
|
protoBufferPool.Put(cb)
|
|
return out, err
|
|
}
|
|
|
|
func (p protoCodec) Unmarshal(data []byte, v interface{}) error {
|
|
cb := protoBufferPool.Get().(*cachedProtoBuffer)
|
|
cb.SetBuf(data)
|
|
v.(proto.Message).Reset()
|
|
err := cb.Unmarshal(v.(proto.Message))
|
|
cb.SetBuf(nil)
|
|
protoBufferPool.Put(cb)
|
|
return err
|
|
}
|
|
|
|
func (protoCodec) String() string {
|
|
return "proto"
|
|
}
|
|
|
|
var (
|
|
protoBufferPool = &sync.Pool{
|
|
New: func() interface{} {
|
|
return &cachedProtoBuffer{
|
|
Buffer: proto.Buffer{},
|
|
lastMarshaledSize: 16,
|
|
}
|
|
},
|
|
}
|
|
)
|