// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors.  All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package proto

/*
 * Routines for encoding data into the wire format for protocol buffers.
 */

import (
	"errors"
	"fmt"
	"reflect"
	"sort"
)

// RequiredNotSetError is the error returned if Marshal is called with
// a protocol buffer struct whose required fields have not
// all been initialized. It is also the error returned if Unmarshal is
// called with an encoded protocol buffer that does not include all the
// required fields.
//
// When printed, RequiredNotSetError reports the first unset required field in a
// message. If the field cannot be precisely determined, it is reported as
// "{Unknown}".
type RequiredNotSetError struct {
	field string
}

func (e *RequiredNotSetError) Error() string {
	return fmt.Sprintf("proto: required field %q not set", e.field)
}

var (
	// ErrRepeatedHasNil is the error returned if Marshal is called with
	// a struct with a repeated field containing a nil element.
	ErrRepeatedHasNil = errors.New("proto: repeated field has nil element")

	// ErrNil is the error returned if Marshal is called with nil.
	ErrNil = errors.New("proto: Marshal called with nil")
)

// The fundamental encoders that put bytes on the wire.
// Those that take integer types all accept uint64 and are
// therefore of type valueEncoder.

const maxVarintBytes = 10 // maximum length of a varint

// EncodeVarint returns the varint encoding of x.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
// Not used by the package itself, but helpful to clients
// wishing to use the same encoding.
func EncodeVarint(x uint64) []byte {
	var buf [maxVarintBytes]byte
	var n int
	for n = 0; x > 127; n++ {
		buf[n] = 0x80 | uint8(x&0x7F)
		x >>= 7
	}
	buf[n] = uint8(x)
	n++
	return buf[0:n]
}

// 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 (p *Buffer) EncodeVarint(x uint64) error {
	for x >= 1<<7 {
		p.buf = append(p.buf, uint8(x&0x7f|0x80))
		x >>= 7
	}
	p.buf = append(p.buf, uint8(x))
	return nil
}

func sizeVarint(x uint64) (n int) {
	for {
		n++
		x >>= 7
		if x == 0 {
			break
		}
	}
	return n
}

// EncodeFixed64 writes a 64-bit integer to the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
func (p *Buffer) EncodeFixed64(x uint64) error {
	p.buf = append(p.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
}

func sizeFixed64(x uint64) int {
	return 8
}

// EncodeFixed32 writes a 32-bit integer to the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
func (p *Buffer) EncodeFixed32(x uint64) error {
	p.buf = append(p.buf,
		uint8(x),
		uint8(x>>8),
		uint8(x>>16),
		uint8(x>>24))
	return nil
}

func sizeFixed32(x uint64) int {
	return 4
}

// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
// to the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) EncodeZigzag64(x uint64) error {
	// use signed number to get arithmetic right shift.
	return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}

func sizeZigzag64(x uint64) int {
	return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}

// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
// to the Buffer.
// This is the format used for the sint32 protocol buffer type.
func (p *Buffer) EncodeZigzag32(x uint64) error {
	// use signed number to get arithmetic right shift.
	return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
}

func sizeZigzag32(x uint64) int {
	return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
}

// 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 (p *Buffer) EncodeRawBytes(b []byte) error {
	p.EncodeVarint(uint64(len(b)))
	p.buf = append(p.buf, b...)
	return nil
}

func sizeRawBytes(b []byte) int {
	return sizeVarint(uint64(len(b))) +
		len(b)
}

// EncodeStringBytes writes an encoded string to the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) EncodeStringBytes(s string) error {
	p.EncodeVarint(uint64(len(s)))
	p.buf = append(p.buf, s...)
	return nil
}

func sizeStringBytes(s string) int {
	return sizeVarint(uint64(len(s))) +
		len(s)
}

// Marshaler is the interface representing objects that can marshal themselves.
type Marshaler interface {
	Marshal() ([]byte, error)
}

// Marshal takes the protocol buffer
// and encodes it into the wire format, returning the data.
func Marshal(pb Message) ([]byte, error) {
	// Can the object marshal itself?
	if m, ok := pb.(Marshaler); ok {
		return m.Marshal()
	}
	p := NewBuffer(nil)
	err := p.Marshal(pb)
	var state errorState
	if err != nil && !state.shouldContinue(err, nil) {
		return nil, err
	}
	if p.buf == nil && err == nil {
		// Return a non-nil slice on success.
		return []byte{}, nil
	}
	return p.buf, err
}

// Marshal takes the protocol buffer
// and encodes it into the wire format, writing the result to the
// Buffer.
func (p *Buffer) Marshal(pb Message) error {
	// Can the object marshal itself?
	if m, ok := pb.(Marshaler); ok {
		data, err := m.Marshal()
		if err != nil {
			return err
		}
		p.buf = append(p.buf, data...)
		return nil
	}

	t, base, err := getbase(pb)
	if structPointer_IsNil(base) {
		return ErrNil
	}
	if err == nil {
		err = p.enc_struct(GetProperties(t.Elem()), base)
	}

	if collectStats {
		stats.Encode++
	}

	return err
}

// Size returns the encoded size of a protocol buffer.
func Size(pb Message) (n int) {
	// Can the object marshal itself?  If so, Size is slow.
	// TODO: add Size to Marshaler, or add a Sizer interface.
	if m, ok := pb.(Marshaler); ok {
		b, _ := m.Marshal()
		return len(b)
	}

	t, base, err := getbase(pb)
	if structPointer_IsNil(base) {
		return 0
	}
	if err == nil {
		n = size_struct(GetProperties(t.Elem()), base)
	}

	if collectStats {
		stats.Size++
	}

	return
}

// Individual type encoders.

// Encode a bool.
func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
	v := *structPointer_Bool(base, p.field)
	if v == nil {
		return ErrNil
	}
	x := 0
	if *v {
		x = 1
	}
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, uint64(x))
	return nil
}

func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
	v := *structPointer_BoolVal(base, p.field)
	if !v {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, 1)
	return nil
}

func size_bool(p *Properties, base structPointer) int {
	v := *structPointer_Bool(base, p.field)
	if v == nil {
		return 0
	}
	return len(p.tagcode) + 1 // each bool takes exactly one byte
}

func size_proto3_bool(p *Properties, base structPointer) int {
	v := *structPointer_BoolVal(base, p.field)
	if !v {
		return 0
	}
	return len(p.tagcode) + 1 // each bool takes exactly one byte
}

// Encode an int32.
func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
	v := structPointer_Word32(base, p.field)
	if word32_IsNil(v) {
		return ErrNil
	}
	x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, uint64(x))
	return nil
}

func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
	v := structPointer_Word32Val(base, p.field)
	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
	if x == 0 {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, uint64(x))
	return nil
}

func size_int32(p *Properties, base structPointer) (n int) {
	v := structPointer_Word32(base, p.field)
	if word32_IsNil(v) {
		return 0
	}
	x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
	n += len(p.tagcode)
	n += p.valSize(uint64(x))
	return
}

func size_proto3_int32(p *Properties, base structPointer) (n int) {
	v := structPointer_Word32Val(base, p.field)
	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
	if x == 0 {
		return 0
	}
	n += len(p.tagcode)
	n += p.valSize(uint64(x))
	return
}

// Encode a uint32.
// Exactly the same as int32, except for no sign extension.
func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
	v := structPointer_Word32(base, p.field)
	if word32_IsNil(v) {
		return ErrNil
	}
	x := word32_Get(v)
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, uint64(x))
	return nil
}

func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
	v := structPointer_Word32Val(base, p.field)
	x := word32Val_Get(v)
	if x == 0 {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, uint64(x))
	return nil
}

func size_uint32(p *Properties, base structPointer) (n int) {
	v := structPointer_Word32(base, p.field)
	if word32_IsNil(v) {
		return 0
	}
	x := word32_Get(v)
	n += len(p.tagcode)
	n += p.valSize(uint64(x))
	return
}

func size_proto3_uint32(p *Properties, base structPointer) (n int) {
	v := structPointer_Word32Val(base, p.field)
	x := word32Val_Get(v)
	if x == 0 {
		return 0
	}
	n += len(p.tagcode)
	n += p.valSize(uint64(x))
	return
}

// Encode an int64.
func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
	v := structPointer_Word64(base, p.field)
	if word64_IsNil(v) {
		return ErrNil
	}
	x := word64_Get(v)
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, x)
	return nil
}

func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
	v := structPointer_Word64Val(base, p.field)
	x := word64Val_Get(v)
	if x == 0 {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	p.valEnc(o, x)
	return nil
}

func size_int64(p *Properties, base structPointer) (n int) {
	v := structPointer_Word64(base, p.field)
	if word64_IsNil(v) {
		return 0
	}
	x := word64_Get(v)
	n += len(p.tagcode)
	n += p.valSize(x)
	return
}

func size_proto3_int64(p *Properties, base structPointer) (n int) {
	v := structPointer_Word64Val(base, p.field)
	x := word64Val_Get(v)
	if x == 0 {
		return 0
	}
	n += len(p.tagcode)
	n += p.valSize(x)
	return
}

// Encode a string.
func (o *Buffer) enc_string(p *Properties, base structPointer) error {
	v := *structPointer_String(base, p.field)
	if v == nil {
		return ErrNil
	}
	x := *v
	o.buf = append(o.buf, p.tagcode...)
	o.EncodeStringBytes(x)
	return nil
}

func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
	v := *structPointer_StringVal(base, p.field)
	if v == "" {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	o.EncodeStringBytes(v)
	return nil
}

func size_string(p *Properties, base structPointer) (n int) {
	v := *structPointer_String(base, p.field)
	if v == nil {
		return 0
	}
	x := *v
	n += len(p.tagcode)
	n += sizeStringBytes(x)
	return
}

func size_proto3_string(p *Properties, base structPointer) (n int) {
	v := *structPointer_StringVal(base, p.field)
	if v == "" {
		return 0
	}
	n += len(p.tagcode)
	n += sizeStringBytes(v)
	return
}

// All protocol buffer fields are nillable, but be careful.
func isNil(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
		return v.IsNil()
	}
	return false
}

// Encode a message struct.
func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
	var state errorState
	structp := structPointer_GetStructPointer(base, p.field)
	if structPointer_IsNil(structp) {
		return ErrNil
	}

	// Can the object marshal itself?
	if p.isMarshaler {
		m := structPointer_Interface(structp, p.stype).(Marshaler)
		data, err := m.Marshal()
		if err != nil && !state.shouldContinue(err, nil) {
			return err
		}
		o.buf = append(o.buf, p.tagcode...)
		o.EncodeRawBytes(data)
		return nil
	}

	o.buf = append(o.buf, p.tagcode...)
	return o.enc_len_struct(p.sprop, structp, &state)
}

func size_struct_message(p *Properties, base structPointer) int {
	structp := structPointer_GetStructPointer(base, p.field)
	if structPointer_IsNil(structp) {
		return 0
	}

	// Can the object marshal itself?
	if p.isMarshaler {
		m := structPointer_Interface(structp, p.stype).(Marshaler)
		data, _ := m.Marshal()
		n0 := len(p.tagcode)
		n1 := sizeRawBytes(data)
		return n0 + n1
	}

	n0 := len(p.tagcode)
	n1 := size_struct(p.sprop, structp)
	n2 := sizeVarint(uint64(n1)) // size of encoded length
	return n0 + n1 + n2
}

// Encode a group struct.
func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
	var state errorState
	b := structPointer_GetStructPointer(base, p.field)
	if structPointer_IsNil(b) {
		return ErrNil
	}

	o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
	err := o.enc_struct(p.sprop, b)
	if err != nil && !state.shouldContinue(err, nil) {
		return err
	}
	o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
	return state.err
}

func size_struct_group(p *Properties, base structPointer) (n int) {
	b := structPointer_GetStructPointer(base, p.field)
	if structPointer_IsNil(b) {
		return 0
	}

	n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
	n += size_struct(p.sprop, b)
	n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
	return
}

// Encode a slice of bools ([]bool).
func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
	s := *structPointer_BoolSlice(base, p.field)
	l := len(s)
	if l == 0 {
		return ErrNil
	}
	for _, x := range s {
		o.buf = append(o.buf, p.tagcode...)
		v := uint64(0)
		if x {
			v = 1
		}
		p.valEnc(o, v)
	}
	return nil
}

func size_slice_bool(p *Properties, base structPointer) int {
	s := *structPointer_BoolSlice(base, p.field)
	l := len(s)
	if l == 0 {
		return 0
	}
	return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
}

// Encode a slice of bools ([]bool) in packed format.
func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
	s := *structPointer_BoolSlice(base, p.field)
	l := len(s)
	if l == 0 {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
	for _, x := range s {
		v := uint64(0)
		if x {
			v = 1
		}
		p.valEnc(o, v)
	}
	return nil
}

func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
	s := *structPointer_BoolSlice(base, p.field)
	l := len(s)
	if l == 0 {
		return 0
	}
	n += len(p.tagcode)
	n += sizeVarint(uint64(l))
	n += l // each bool takes exactly one byte
	return
}

// Encode a slice of bytes ([]byte).
func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
	s := *structPointer_Bytes(base, p.field)
	if s == nil {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	o.EncodeRawBytes(s)
	return nil
}

func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
	s := *structPointer_Bytes(base, p.field)
	if len(s) == 0 {
		return ErrNil
	}
	o.buf = append(o.buf, p.tagcode...)
	o.EncodeRawBytes(s)
	return nil
}

func size_slice_byte(p *Properties, base structPointer) (n int) {
	s := *structPointer_Bytes(base, p.field)
	if s == nil {
		return 0
	}
	n += len(p.tagcode)
	n += sizeRawBytes(s)
	return
}

func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
	s := *structPointer_Bytes(base, p.field)
	if len(s) == 0 {
		return 0
	}
	n += len(p.tagcode)
	n += sizeRawBytes(s)
	return
}

// Encode a slice of int32s ([]int32).
func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return ErrNil
	}
	for i := 0; i < l; i++ {
		o.buf = append(o.buf, p.tagcode...)
		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
		p.valEnc(o, uint64(x))
	}
	return nil
}

func size_slice_int32(p *Properties, base structPointer) (n int) {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return 0
	}
	for i := 0; i < l; i++ {
		n += len(p.tagcode)
		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
		n += p.valSize(uint64(x))
	}
	return
}

// Encode a slice of int32s ([]int32) in packed format.
func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return ErrNil
	}
	// TODO: Reuse a Buffer.
	buf := NewBuffer(nil)
	for i := 0; i < l; i++ {
		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
		p.valEnc(buf, uint64(x))
	}

	o.buf = append(o.buf, p.tagcode...)
	o.EncodeVarint(uint64(len(buf.buf)))
	o.buf = append(o.buf, buf.buf...)
	return nil
}

func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return 0
	}
	var bufSize int
	for i := 0; i < l; i++ {
		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
		bufSize += p.valSize(uint64(x))
	}

	n += len(p.tagcode)
	n += sizeVarint(uint64(bufSize))
	n += bufSize
	return
}

// Encode a slice of uint32s ([]uint32).
// Exactly the same as int32, except for no sign extension.
func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return ErrNil
	}
	for i := 0; i < l; i++ {
		o.buf = append(o.buf, p.tagcode...)
		x := s.Index(i)
		p.valEnc(o, uint64(x))
	}
	return nil
}

func size_slice_uint32(p *Properties, base structPointer) (n int) {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return 0
	}
	for i := 0; i < l; i++ {
		n += len(p.tagcode)
		x := s.Index(i)
		n += p.valSize(uint64(x))
	}
	return
}

// Encode a slice of uint32s ([]uint32) in packed format.
// Exactly the same as int32, except for no sign extension.
func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return ErrNil
	}
	// TODO: Reuse a Buffer.
	buf := NewBuffer(nil)
	for i := 0; i < l; i++ {
		p.valEnc(buf, uint64(s.Index(i)))
	}

	o.buf = append(o.buf, p.tagcode...)
	o.EncodeVarint(uint64(len(buf.buf)))
	o.buf = append(o.buf, buf.buf...)
	return nil
}

func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
	s := structPointer_Word32Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return 0
	}
	var bufSize int
	for i := 0; i < l; i++ {
		bufSize += p.valSize(uint64(s.Index(i)))
	}

	n += len(p.tagcode)
	n += sizeVarint(uint64(bufSize))
	n += bufSize
	return
}

// Encode a slice of int64s ([]int64).
func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
	s := structPointer_Word64Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return ErrNil
	}
	for i := 0; i < l; i++ {
		o.buf = append(o.buf, p.tagcode...)
		p.valEnc(o, s.Index(i))
	}
	return nil
}

func size_slice_int64(p *Properties, base structPointer) (n int) {
	s := structPointer_Word64Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return 0
	}
	for i := 0; i < l; i++ {
		n += len(p.tagcode)
		n += p.valSize(s.Index(i))
	}
	return
}

// Encode a slice of int64s ([]int64) in packed format.
func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
	s := structPointer_Word64Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return ErrNil
	}
	// TODO: Reuse a Buffer.
	buf := NewBuffer(nil)
	for i := 0; i < l; i++ {
		p.valEnc(buf, s.Index(i))
	}

	o.buf = append(o.buf, p.tagcode...)
	o.EncodeVarint(uint64(len(buf.buf)))
	o.buf = append(o.buf, buf.buf...)
	return nil
}

func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
	s := structPointer_Word64Slice(base, p.field)
	l := s.Len()
	if l == 0 {
		return 0
	}
	var bufSize int
	for i := 0; i < l; i++ {
		bufSize += p.valSize(s.Index(i))
	}

	n += len(p.tagcode)
	n += sizeVarint(uint64(bufSize))
	n += bufSize
	return
}

// Encode a slice of slice of bytes ([][]byte).
func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
	ss := *structPointer_BytesSlice(base, p.field)
	l := len(ss)
	if l == 0 {
		return ErrNil
	}
	for i := 0; i < l; i++ {
		o.buf = append(o.buf, p.tagcode...)
		o.EncodeRawBytes(ss[i])
	}
	return nil
}

func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
	ss := *structPointer_BytesSlice(base, p.field)
	l := len(ss)
	if l == 0 {
		return 0
	}
	n += l * len(p.tagcode)
	for i := 0; i < l; i++ {
		n += sizeRawBytes(ss[i])
	}
	return
}

// Encode a slice of strings ([]string).
func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
	ss := *structPointer_StringSlice(base, p.field)
	l := len(ss)
	for i := 0; i < l; i++ {
		o.buf = append(o.buf, p.tagcode...)
		o.EncodeStringBytes(ss[i])
	}
	return nil
}

func size_slice_string(p *Properties, base structPointer) (n int) {
	ss := *structPointer_StringSlice(base, p.field)
	l := len(ss)
	n += l * len(p.tagcode)
	for i := 0; i < l; i++ {
		n += sizeStringBytes(ss[i])
	}
	return
}

// Encode a slice of message structs ([]*struct).
func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
	var state errorState
	s := structPointer_StructPointerSlice(base, p.field)
	l := s.Len()

	for i := 0; i < l; i++ {
		structp := s.Index(i)
		if structPointer_IsNil(structp) {
			return ErrRepeatedHasNil
		}

		// Can the object marshal itself?
		if p.isMarshaler {
			m := structPointer_Interface(structp, p.stype).(Marshaler)
			data, err := m.Marshal()
			if err != nil && !state.shouldContinue(err, nil) {
				return err
			}
			o.buf = append(o.buf, p.tagcode...)
			o.EncodeRawBytes(data)
			continue
		}

		o.buf = append(o.buf, p.tagcode...)
		err := o.enc_len_struct(p.sprop, structp, &state)
		if err != nil && !state.shouldContinue(err, nil) {
			if err == ErrNil {
				return ErrRepeatedHasNil
			}
			return err
		}
	}
	return state.err
}

func size_slice_struct_message(p *Properties, base structPointer) (n int) {
	s := structPointer_StructPointerSlice(base, p.field)
	l := s.Len()
	n += l * len(p.tagcode)
	for i := 0; i < l; i++ {
		structp := s.Index(i)
		if structPointer_IsNil(structp) {
			return // return the size up to this point
		}

		// Can the object marshal itself?
		if p.isMarshaler {
			m := structPointer_Interface(structp, p.stype).(Marshaler)
			data, _ := m.Marshal()
			n += len(p.tagcode)
			n += sizeRawBytes(data)
			continue
		}

		n0 := size_struct(p.sprop, structp)
		n1 := sizeVarint(uint64(n0)) // size of encoded length
		n += n0 + n1
	}
	return
}

// Encode a slice of group structs ([]*struct).
func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
	var state errorState
	s := structPointer_StructPointerSlice(base, p.field)
	l := s.Len()

	for i := 0; i < l; i++ {
		b := s.Index(i)
		if structPointer_IsNil(b) {
			return ErrRepeatedHasNil
		}

		o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))

		err := o.enc_struct(p.sprop, b)

		if err != nil && !state.shouldContinue(err, nil) {
			if err == ErrNil {
				return ErrRepeatedHasNil
			}
			return err
		}

		o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
	}
	return state.err
}

func size_slice_struct_group(p *Properties, base structPointer) (n int) {
	s := structPointer_StructPointerSlice(base, p.field)
	l := s.Len()

	n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
	n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
	for i := 0; i < l; i++ {
		b := s.Index(i)
		if structPointer_IsNil(b) {
			return // return size up to this point
		}

		n += size_struct(p.sprop, b)
	}
	return
}

// Encode an extension map.
func (o *Buffer) enc_map(p *Properties, base structPointer) error {
	v := *structPointer_ExtMap(base, p.field)
	if err := encodeExtensionMap(v); err != nil {
		return err
	}
	// Fast-path for common cases: zero or one extensions.
	if len(v) <= 1 {
		for _, e := range v {
			o.buf = append(o.buf, e.enc...)
		}
		return nil
	}

	// Sort keys to provide a deterministic encoding.
	keys := make([]int, 0, len(v))
	for k := range v {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)

	for _, k := range keys {
		o.buf = append(o.buf, v[int32(k)].enc...)
	}
	return nil
}

func size_map(p *Properties, base structPointer) int {
	v := *structPointer_ExtMap(base, p.field)
	return sizeExtensionMap(v)
}

// Encode a map field.
func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
	var state errorState // XXX: or do we need to plumb this through?

	/*
		A map defined as
			map<key_type, value_type> map_field = N;
		is encoded in the same way as
			message MapFieldEntry {
				key_type key = 1;
				value_type value = 2;
			}
			repeated MapFieldEntry map_field = N;
	*/

	v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
	if v.Len() == 0 {
		return nil
	}

	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)

	enc := func() error {
		if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
			return err
		}
		if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil {
			return err
		}
		return nil
	}

	keys := v.MapKeys()
	sort.Sort(mapKeys(keys))
	for _, key := range keys {
		val := v.MapIndex(key)

		keycopy.Set(key)
		valcopy.Set(val)

		o.buf = append(o.buf, p.tagcode...)
		if err := o.enc_len_thing(enc, &state); err != nil {
			return err
		}
	}
	return nil
}

func size_new_map(p *Properties, base structPointer) int {
	v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V

	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)

	n := 0
	for _, key := range v.MapKeys() {
		val := v.MapIndex(key)
		keycopy.Set(key)
		valcopy.Set(val)

		// Tag codes are two bytes per map entry.
		n += 2
		n += p.mkeyprop.size(p.mkeyprop, keybase)
		n += p.mvalprop.size(p.mvalprop, valbase)
	}
	return n
}

// mapEncodeScratch returns a new reflect.Value matching the map's value type,
// and a structPointer suitable for passing to an encoder or sizer.
func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
	// Prepare addressable doubly-indirect placeholders for the key and value types.
	// This is needed because the element-type encoders expect **T, but the map iteration produces T.

	keycopy = reflect.New(mapType.Key()).Elem()                 // addressable K
	keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
	keyptr.Set(keycopy.Addr())                                  //
	keybase = toStructPointer(keyptr.Addr())                    // **K

	// Value types are more varied and require special handling.
	switch mapType.Elem().Kind() {
	case reflect.Slice:
		// []byte
		var dummy []byte
		valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
		valbase = toStructPointer(valcopy.Addr())
	case reflect.Ptr:
		// message; the generated field type is map[K]*Msg (so V is *Msg),
		// so we only need one level of indirection.
		valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
		valbase = toStructPointer(valcopy.Addr())
	default:
		// everything else
		valcopy = reflect.New(mapType.Elem()).Elem()                // addressable V
		valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
		valptr.Set(valcopy.Addr())                                  //
		valbase = toStructPointer(valptr.Addr())                    // **V
	}
	return
}

// Encode a struct.
func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
	var state errorState
	// Encode fields in tag order so that decoders may use optimizations
	// that depend on the ordering.
	// https://developers.google.com/protocol-buffers/docs/encoding#order
	for _, i := range prop.order {
		p := prop.Prop[i]
		if p.enc != nil {
			err := p.enc(o, p, base)
			if err != nil {
				if err == ErrNil {
					if p.Required && state.err == nil {
						state.err = &RequiredNotSetError{p.Name}
					}
				} else if !state.shouldContinue(err, p) {
					return err
				}
			}
		}
	}

	// Add unrecognized fields at the end.
	if prop.unrecField.IsValid() {
		v := *structPointer_Bytes(base, prop.unrecField)
		if len(v) > 0 {
			o.buf = append(o.buf, v...)
		}
	}

	return state.err
}

func size_struct(prop *StructProperties, base structPointer) (n int) {
	for _, i := range prop.order {
		p := prop.Prop[i]
		if p.size != nil {
			n += p.size(p, base)
		}
	}

	// Add unrecognized fields at the end.
	if prop.unrecField.IsValid() {
		v := *structPointer_Bytes(base, prop.unrecField)
		n += len(v)
	}

	return
}

var zeroes [20]byte // longer than any conceivable sizeVarint

// Encode a struct, preceded by its encoded length (as a varint).
func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
	return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
}

// Encode something, preceded by its encoded length (as a varint).
func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
	iLen := len(o.buf)
	o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
	iMsg := len(o.buf)
	err := enc()
	if err != nil && !state.shouldContinue(err, nil) {
		return err
	}
	lMsg := len(o.buf) - iMsg
	lLen := sizeVarint(uint64(lMsg))
	switch x := lLen - (iMsg - iLen); {
	case x > 0: // actual length is x bytes larger than the space we reserved
		// Move msg x bytes right.
		o.buf = append(o.buf, zeroes[:x]...)
		copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
	case x < 0: // actual length is x bytes smaller than the space we reserved
		// Move msg x bytes left.
		copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
		o.buf = o.buf[:len(o.buf)+x] // x is negative
	}
	// Encode the length in the reserved space.
	o.buf = o.buf[:iLen]
	o.EncodeVarint(uint64(lMsg))
	o.buf = o.buf[:len(o.buf)+lMsg]
	return state.err
}

// errorState maintains the first error that occurs and updates that error
// with additional context.
type errorState struct {
	err error
}

// shouldContinue reports whether encoding should continue upon encountering the
// given error. If the error is RequiredNotSetError, shouldContinue returns true
// and, if this is the first appearance of that error, remembers it for future
// reporting.
//
// If prop is not nil, it may update any error with additional context about the
// field with the error.
func (s *errorState) shouldContinue(err error, prop *Properties) bool {
	// Ignore unset required fields.
	reqNotSet, ok := err.(*RequiredNotSetError)
	if !ok {
		return false
	}
	if s.err == nil {
		if prop != nil {
			err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
		}
		s.err = err
	}
	return true
}
