diff options
Diffstat (limited to 'vendor/google.golang.org/protobuf/encoding')
| -rw-r--r-- | vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go | 160 | 
1 files changed, 160 insertions, 0 deletions
diff --git a/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go b/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go new file mode 100644 index 000000000..2ef36bbcf --- /dev/null +++ b/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go @@ -0,0 +1,160 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package protodelim marshals and unmarshals varint size-delimited messages. +package protodelim + +import ( +	"bufio" +	"encoding/binary" +	"fmt" +	"io" + +	"google.golang.org/protobuf/encoding/protowire" +	"google.golang.org/protobuf/internal/errors" +	"google.golang.org/protobuf/proto" +) + +// MarshalOptions is a configurable varint size-delimited marshaler. +type MarshalOptions struct{ proto.MarshalOptions } + +// MarshalTo writes a varint size-delimited wire-format message to w. +// If w returns an error, MarshalTo returns it unchanged. +func (o MarshalOptions) MarshalTo(w io.Writer, m proto.Message) (int, error) { +	msgBytes, err := o.MarshalOptions.Marshal(m) +	if err != nil { +		return 0, err +	} + +	sizeBytes := protowire.AppendVarint(nil, uint64(len(msgBytes))) +	sizeWritten, err := w.Write(sizeBytes) +	if err != nil { +		return sizeWritten, err +	} +	msgWritten, err := w.Write(msgBytes) +	if err != nil { +		return sizeWritten + msgWritten, err +	} +	return sizeWritten + msgWritten, nil +} + +// MarshalTo writes a varint size-delimited wire-format message to w +// with the default options. +// +// See the documentation for [MarshalOptions.MarshalTo]. +func MarshalTo(w io.Writer, m proto.Message) (int, error) { +	return MarshalOptions{}.MarshalTo(w, m) +} + +// UnmarshalOptions is a configurable varint size-delimited unmarshaler. +type UnmarshalOptions struct { +	proto.UnmarshalOptions + +	// MaxSize is the maximum size in wire-format bytes of a single message. +	// Unmarshaling a message larger than MaxSize will return an error. +	// A zero MaxSize will default to 4 MiB. +	// Setting MaxSize to -1 disables the limit. +	MaxSize int64 +} + +const defaultMaxSize = 4 << 20 // 4 MiB, corresponds to the default gRPC max request/response size + +// SizeTooLargeError is an error that is returned when the unmarshaler encounters a message size +// that is larger than its configured [UnmarshalOptions.MaxSize]. +type SizeTooLargeError struct { +	// Size is the varint size of the message encountered +	// that was larger than the provided MaxSize. +	Size uint64 + +	// MaxSize is the MaxSize limit configured in UnmarshalOptions, which Size exceeded. +	MaxSize uint64 +} + +func (e *SizeTooLargeError) Error() string { +	return fmt.Sprintf("message size %d exceeded unmarshaler's maximum configured size %d", e.Size, e.MaxSize) +} + +// Reader is the interface expected by [UnmarshalFrom]. +// It is implemented by *[bufio.Reader]. +type Reader interface { +	io.Reader +	io.ByteReader +} + +// UnmarshalFrom parses and consumes a varint size-delimited wire-format message +// from r. +// The provided message must be mutable (e.g., a non-nil pointer to a message). +// +// The error is [io.EOF] error only if no bytes are read. +// If an EOF happens after reading some but not all the bytes, +// UnmarshalFrom returns a non-io.EOF error. +// In particular if r returns a non-io.EOF error, UnmarshalFrom returns it unchanged, +// and if only a size is read with no subsequent message, [io.ErrUnexpectedEOF] is returned. +func (o UnmarshalOptions) UnmarshalFrom(r Reader, m proto.Message) error { +	var sizeArr [binary.MaxVarintLen64]byte +	sizeBuf := sizeArr[:0] +	for i := range sizeArr { +		b, err := r.ReadByte() +		if err != nil { +			// Immediate EOF is unexpected. +			if err == io.EOF && i != 0 { +				break +			} +			return err +		} +		sizeBuf = append(sizeBuf, b) +		if b < 0x80 { +			break +		} +	} +	size, n := protowire.ConsumeVarint(sizeBuf) +	if n < 0 { +		return protowire.ParseError(n) +	} + +	maxSize := o.MaxSize +	if maxSize == 0 { +		maxSize = defaultMaxSize +	} +	if maxSize != -1 && size > uint64(maxSize) { +		return errors.Wrap(&SizeTooLargeError{Size: size, MaxSize: uint64(maxSize)}, "") +	} + +	var b []byte +	var err error +	if br, ok := r.(*bufio.Reader); ok { +		// Use the []byte from the bufio.Reader instead of having to allocate one. +		// This reduces CPU usage and allocated bytes. +		b, err = br.Peek(int(size)) +		if err == nil { +			defer br.Discard(int(size)) +		} else { +			b = nil +		} +	} +	if b == nil { +		b = make([]byte, size) +		_, err = io.ReadFull(r, b) +	} + +	if err == io.EOF { +		return io.ErrUnexpectedEOF +	} +	if err != nil { +		return err +	} +	if err := o.Unmarshal(b, m); err != nil { +		return err +	} +	return nil +} + +// UnmarshalFrom parses and consumes a varint size-delimited wire-format message +// from r with the default options. +// The provided message must be mutable (e.g., a non-nil pointer to a message). +// +// See the documentation for [UnmarshalOptions.UnmarshalFrom]. +func UnmarshalFrom(r Reader, m proto.Message) error { +	return UnmarshalOptions{}.UnmarshalFrom(r, m) +}  | 
