func (ps *ProtoStream) encodeKeyToScratch(fieldNumber int, wireType protowire.Type) {
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(fieldNumber)<<3+uint64(wireType))
}
encodeKeyToScratch encodes a protobuf key into ps.scratch.
package molecule
import (
	"bytes"
	"io"
	"math"
	"github.com/richardartoul/molecule/src/protowire"
)
const (
	defaultBufferSize int = 1024 * 8
)
type ProtoStream struct {
	outputWriter io.Writer
	scratchBuffer []byte
	scratchArray [20]byte
	childStream *ProtoStream
	childBuffer *bytes.Buffer
	BufferFactory func() []byte
}
func NewProtoStream(outputWriter io.Writer) *ProtoStream {
	return &ProtoStream{
		scratchBuffer: make([]byte, 0, defaultBufferSize),
		childStream:   nil,
		childBuffer:   nil,
		outputWriter:  outputWriter,
		BufferFactory: func() []byte { return make([]byte, 0, defaultBufferSize) },
	}
}
func (ps *ProtoStream) Reset(outputWriter io.Writer) {
	ps.outputWriter = outputWriter
	ps.scratchBuffer = ps.scratchBuffer[:0]
}
func (ps *ProtoStream) Double(fieldNumber int, value float64) error {
	if value == 0.0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.Fixed64Type)
	ps.scratchBuffer = protowire.AppendFixed64(ps.scratchBuffer, math.Float64bits(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) DoublePacked(fieldNumber int, values []float64) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendFixed64(ps.scratchBuffer, math.Float64bits(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Float(fieldNumber int, value float32) error {
	if value == 0.0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.Fixed32Type)
	ps.scratchBuffer = protowire.AppendFixed32(ps.scratchBuffer, math.Float32bits(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) FloatPacked(fieldNumber int, values []float32) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendFixed32(ps.scratchBuffer, math.Float32bits(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Int32(fieldNumber int, value int32) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) Int32Packed(fieldNumber int, values []int32) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Int64(fieldNumber int, value int64) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) Int64Packed(fieldNumber int, values []int64) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Uint32(fieldNumber int, value uint32) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) Uint32Packed(fieldNumber int, values []uint32) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Uint64(fieldNumber int, value uint64) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, value)
	return ps.writeScratch()
}
func (ps *ProtoStream) Uint64Packed(fieldNumber int, values []uint64) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, value)
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Sint32(fieldNumber int, value int32) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, protowire.EncodeZigZag(int64(value)))
	return ps.writeScratch()
}
func (ps *ProtoStream) Sint32Packed(fieldNumber int, values []int32) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, protowire.EncodeZigZag(int64(value)))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Sint64(fieldNumber int, value int64) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, zigzag64(uint64(value)))
	return ps.writeScratch()
}
func (ps *ProtoStream) Sint64Packed(fieldNumber int, values []int64) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, zigzag64(uint64(value)))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Fixed32(fieldNumber int, value uint32) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.Fixed32Type)
	ps.scratchBuffer = protowire.AppendFixed32(ps.scratchBuffer, value)
	return ps.writeScratch()
}
func (ps *ProtoStream) Fixed32Packed(fieldNumber int, values []uint32) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendFixed32(ps.scratchBuffer, value)
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Fixed64(fieldNumber int, value uint64) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.Fixed64Type)
	ps.scratchBuffer = protowire.AppendFixed64(ps.scratchBuffer, value)
	return ps.writeScratch()
}
func (ps *ProtoStream) Fixed64Packed(fieldNumber int, values []uint64) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendFixed64(ps.scratchBuffer, value)
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Sfixed32(fieldNumber int, value int32) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.Fixed32Type)
	ps.scratchBuffer = protowire.AppendFixed32(ps.scratchBuffer, uint32(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) Sfixed32Packed(fieldNumber int, values []int32) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendFixed32(ps.scratchBuffer, uint32(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Sfixed64(fieldNumber int, value int64) error {
	if value == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.Fixed64Type)
	ps.scratchBuffer = protowire.AppendFixed64(ps.scratchBuffer, uint64(value))
	return ps.writeScratch()
}
func (ps *ProtoStream) Sfixed64Packed(fieldNumber int, values []int64) error {
	if len(values) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	for _, value := range values {
		ps.scratchBuffer = protowire.AppendFixed64(ps.scratchBuffer, uint64(value))
	}
	return ps.writeScratchAsPacked(fieldNumber)
}
func (ps *ProtoStream) Bool(fieldNumber int, value bool) error {
	if value == false {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.VarintType)
	var bit uint64
	if value {
		bit = 1
	}
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, bit)
	return ps.writeScratch()
}
func (ps *ProtoStream) String(fieldNumber int, value string) error {
	if len(value) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.BytesType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(len(value)))
	err := ps.writeScratch()
	if err != nil {
		return err
	}
	return ps.writeAllString(value)
}
func (ps *ProtoStream) Bytes(fieldNumber int, value []byte) error {
	if len(value) == 0 {
		return nil
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.BytesType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(len(value)))
	err := ps.writeScratch()
	if err != nil {
		return err
	}
	return ps.writeAll(value)
}
func (ps *ProtoStream) Embedded(fieldNumber int, inner func(*ProtoStream) error) error {
	if ps.childStream == nil {
		ps.childBuffer = bytes.NewBuffer(ps.BufferFactory())
		ps.childStream = NewProtoStream(ps.childBuffer)
	}
	ps.childBuffer.Reset()
	err := inner(ps.childStream)
	if err != nil {
		return err
	}
	ps.scratchBuffer = ps.scratchBuffer[:0]
	ps.encodeKeyToScratch(fieldNumber, protowire.BytesType)
	ps.scratchBuffer = protowire.AppendVarint(ps.scratchBuffer, uint64(ps.childBuffer.Len()))
	err = ps.writeScratch()
	if err != nil {
		return err
	}
	return ps.writeAll(ps.childBuffer.Bytes())
}
func (ps *ProtoStream) writeScratch() error {
	return ps.writeAll(ps.scratchBuffer)
}
func (ps *ProtoStream) writeScratchAsPacked(fieldNumber int) error {
	keysize := ps.scratchArray[:0]
	keysize = protowire.AppendVarint(keysize, uint64((fieldNumber<<3)|int(protowire.BytesType)))
	keysize = protowire.AppendVarint(keysize, uint64(len(ps.scratchBuffer)))
	err := ps.writeAll(keysize)
	if err != nil {
		return err
	}
	err = ps.writeScratch()
	if err != nil {
		return err
	}
	return nil
}
func (ps *ProtoStream) writeAll(buf []byte) error {
	for len(buf) > 0 {
		n, err := ps.outputWriter.Write(buf)
		if err != nil {
			return err
		}
		buf = buf[n:]
	}
	return nil
}
func (ps *ProtoStream) writeAllString(value string) error {
	for len(value) > 0 {
		n, err := io.WriteString(ps.outputWriter, value)
		if err != nil {
			return err
		}
		value = value[n:]
	}
	return nil
}