diff options
Diffstat (limited to 'vendor/github.com/jhump/protoreflect/internal/codec/encode.go')
| -rw-r--r-- | vendor/github.com/jhump/protoreflect/internal/codec/encode.go | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/vendor/github.com/jhump/protoreflect/internal/codec/encode.go b/vendor/github.com/jhump/protoreflect/internal/codec/encode.go new file mode 100644 index 0000000..524f1bc --- /dev/null +++ b/vendor/github.com/jhump/protoreflect/internal/codec/encode.go @@ -0,0 +1,147 @@ +package codec + +import ( + "github.com/golang/protobuf/proto" +) + +// EncodeVarint writes a varint-encoded integer to the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (cb *Buffer) EncodeVarint(x uint64) error { + for x >= 1<<7 { + cb.buf = append(cb.buf, uint8(x&0x7f|0x80)) + x >>= 7 + } + cb.buf = append(cb.buf, uint8(x)) + return nil +} + +// EncodeTagAndWireType encodes the given field tag and wire type to the +// buffer. This combines the two values and then writes them as a varint. +func (cb *Buffer) EncodeTagAndWireType(tag int32, wireType int8) error { + v := uint64((int64(tag) << 3) | int64(wireType)) + return cb.EncodeVarint(v) +} + +// EncodeFixed64 writes a 64-bit integer to the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (cb *Buffer) EncodeFixed64(x uint64) error { + cb.buf = append(cb.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24), + uint8(x>>32), + uint8(x>>40), + uint8(x>>48), + uint8(x>>56)) + return nil +} + +// EncodeFixed32 writes a 32-bit integer to the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (cb *Buffer) EncodeFixed32(x uint64) error { + cb.buf = append(cb.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24)) + return nil +} + +// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (cb *Buffer) EncodeRawBytes(b []byte) error { + if err := cb.EncodeVarint(uint64(len(b))); err != nil { + return err + } + cb.buf = append(cb.buf, b...) + return nil +} + +// EncodeMessage writes the given message to the buffer. +func (cb *Buffer) EncodeMessage(pm proto.Message) error { + bytes, err := marshalMessage(cb.buf, pm, cb.deterministic) + if err != nil { + return err + } + cb.buf = bytes + return nil +} + +// EncodeDelimitedMessage writes the given message to the buffer with a +// varint-encoded length prefix (the delimiter). +func (cb *Buffer) EncodeDelimitedMessage(pm proto.Message) error { + bytes, err := marshalMessage(cb.tmp, pm, cb.deterministic) + if err != nil { + return err + } + // save truncated buffer if it was grown (so we can re-use it and + // curtail future allocations) + if cap(bytes) > cap(cb.tmp) { + cb.tmp = bytes[:0] + } + return cb.EncodeRawBytes(bytes) +} + +func marshalMessage(b []byte, pm proto.Message, deterministic bool) ([]byte, error) { + // We try to use the most efficient way to marshal to existing slice. + + if deterministic { + // see if the message has custom deterministic methods, preferring an + // "append" method over one that must always re-allocate + madm, ok := pm.(interface { + MarshalAppendDeterministic(b []byte) ([]byte, error) + }) + if ok { + return madm.MarshalAppendDeterministic(b) + } + + mdm, ok := pm.(interface { + MarshalDeterministic() ([]byte, error) + }) + if ok { + bytes, err := mdm.MarshalDeterministic() + if err != nil { + return nil, err + } + if len(b) == 0 { + return bytes, nil + } + return append(b, bytes...), nil + } + + var buf proto.Buffer + buf.SetDeterministic(true) + if err := buf.Marshal(pm); err != nil { + return nil, err + } + bytes := buf.Bytes() + if len(b) == 0 { + return bytes, nil + } + return append(b, bytes...), nil + } + + mam, ok := pm.(interface { + // see if we can append the message, vs. having to re-allocate + MarshalAppend(b []byte) ([]byte, error) + }) + if ok { + return mam.MarshalAppend(b) + } + + // lowest common denominator + bytes, err := proto.Marshal(pm) + if err != nil { + return nil, err + } + if len(b) == 0 { + return bytes, nil + } + return append(b, bytes...), nil +} |
