package dynamic

import (
	"bytes"
	"compress/gzip"
	"errors"
	"fmt"
	"reflect"
	"sort"
	"strings"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"

	"github.com/jhump/protoreflect/desc"
)

// ErrUnknownTagNumber is an error that is returned when an operation refers
// to an unknown tag number.
var ErrUnknownTagNumber = errors.New("unknown tag number")

// UnknownTagNumberError is the same as ErrUnknownTagNumber.
// Deprecated: use ErrUnknownTagNumber
var UnknownTagNumberError = ErrUnknownTagNumber

// ErrUnknownFieldName is an error that is returned when an operation refers
// to an unknown field name.
var ErrUnknownFieldName = errors.New("unknown field name")

// UnknownFieldNameError is the same as ErrUnknownFieldName.
// Deprecated: use ErrUnknownFieldName
var UnknownFieldNameError = ErrUnknownFieldName

// ErrFieldIsNotMap is an error that is returned when map-related operations
// are attempted with fields that are not maps.
var ErrFieldIsNotMap = errors.New("field is not a map type")

// FieldIsNotMapError is the same as ErrFieldIsNotMap.
// Deprecated: use ErrFieldIsNotMap
var FieldIsNotMapError = ErrFieldIsNotMap

// ErrFieldIsNotRepeated is an error that is returned when repeated field
// operations are attempted with fields that are not repeated.
var ErrFieldIsNotRepeated = errors.New("field is not repeated")

// FieldIsNotRepeatedError is the same as ErrFieldIsNotRepeated.
// Deprecated: use ErrFieldIsNotRepeated
var FieldIsNotRepeatedError = ErrFieldIsNotRepeated

// ErrIndexOutOfRange is an error that is returned when an invalid index is
// provided when access a single element of a repeated field.
var ErrIndexOutOfRange = errors.New("index is out of range")

// IndexOutOfRangeError is the same as ErrIndexOutOfRange.
// Deprecated: use ErrIndexOutOfRange
var IndexOutOfRangeError = ErrIndexOutOfRange

// ErrNumericOverflow is an error returned by operations that encounter a
// numeric value that is too large, for example de-serializing a value into an
// int32 field when the value is larger that can fit into a 32-bit value.
var ErrNumericOverflow = errors.New("numeric value is out of range")

// NumericOverflowError is the same as ErrNumericOverflow.
// Deprecated: use ErrNumericOverflow
var NumericOverflowError = ErrNumericOverflow

var typeOfProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
var typeOfDynamicMessage = reflect.TypeOf((*Message)(nil))
var typeOfBytes = reflect.TypeOf(([]byte)(nil))

var varintTypes = map[descriptor.FieldDescriptorProto_Type]bool{}
var fixed32Types = map[descriptor.FieldDescriptorProto_Type]bool{}
var fixed64Types = map[descriptor.FieldDescriptorProto_Type]bool{}

func init() {
	varintTypes[descriptor.FieldDescriptorProto_TYPE_BOOL] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_INT32] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_INT64] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT32] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT64] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT32] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT64] = true
	varintTypes[descriptor.FieldDescriptorProto_TYPE_ENUM] = true

	fixed32Types[descriptor.FieldDescriptorProto_TYPE_FIXED32] = true
	fixed32Types[descriptor.FieldDescriptorProto_TYPE_SFIXED32] = true
	fixed32Types[descriptor.FieldDescriptorProto_TYPE_FLOAT] = true

	fixed64Types[descriptor.FieldDescriptorProto_TYPE_FIXED64] = true
	fixed64Types[descriptor.FieldDescriptorProto_TYPE_SFIXED64] = true
	fixed64Types[descriptor.FieldDescriptorProto_TYPE_DOUBLE] = true
}

// Message is a dynamic protobuf message. Instead of a generated struct,
// like most protobuf messages, this is a map of field number to values and
// a message descriptor, which is used to validate the field values and
// also to de-serialize messages (from the standard binary format, as well
// as from the text format and from JSON).
type Message struct {
	md            *desc.MessageDescriptor
	er            *ExtensionRegistry
	mf            *MessageFactory
	extraFields   map[int32]*desc.FieldDescriptor
	values        map[int32]interface{}
	unknownFields map[int32][]UnknownField
}

// UnknownField represents a field that was parsed from the binary wire
// format for a message, but was not a recognized field number. Enough
// information is preserved so that re-serializing the message won't lose
// any of the unrecognized data.
type UnknownField struct {
	// Encoding indicates how the unknown field was encoded on the wire. If it
	// is proto.WireBytes or proto.WireGroupStart then Contents will be set to
	// the raw bytes. If it is proto.WireTypeFixed32 then the data is in the least
	// significant 32 bits of Value. Otherwise, the data is in all 64 bits of
	// Value.
	Encoding int8
	Contents []byte
	Value    uint64
}

// NewMessage creates a new dynamic message for the type represented by the given
// message descriptor. During de-serialization, a default MessageFactory is used to
// instantiate any nested message fields and no extension fields will be parsed. To
// use a custom MessageFactory or ExtensionRegistry, use MessageFactory.NewMessage.
func NewMessage(md *desc.MessageDescriptor) *Message {
	return NewMessageWithMessageFactory(md, nil)
}

// NewMessageWithExtensionRegistry creates a new dynamic message for the type
// represented by the given message descriptor. During de-serialization, the given
// ExtensionRegistry is used to parse extension fields and nested messages will be
// instantiated using dynamic.NewMessageFactoryWithExtensionRegistry(er).
func NewMessageWithExtensionRegistry(md *desc.MessageDescriptor, er *ExtensionRegistry) *Message {
	mf := NewMessageFactoryWithExtensionRegistry(er)
	return NewMessageWithMessageFactory(md, mf)
}

// NewMessageWithMessageFactory creates a new dynamic message for the type
// represented by the given message descriptor. During de-serialization, the given
// MessageFactory is used to instantiate nested messages.
func NewMessageWithMessageFactory(md *desc.MessageDescriptor, mf *MessageFactory) *Message {
	var er *ExtensionRegistry
	if mf != nil {
		er = mf.er
	}
	return &Message{
		md: md,
		mf: mf,
		er: er,
	}
}

// AsDynamicMessage converts the given message to a dynamic message. If the
// given message is dynamic, it is returned. Otherwise, a dynamic message is
// created using NewMessage.
func AsDynamicMessage(msg proto.Message) (*Message, error) {
	return AsDynamicMessageWithMessageFactory(msg, nil)
}

// AsDynamicMessageWithExtensionRegistry converts the given message to a dynamic
// message. If the given message is dynamic, it is returned. Otherwise, a
// dynamic message is created using NewMessageWithExtensionRegistry.
func AsDynamicMessageWithExtensionRegistry(msg proto.Message, er *ExtensionRegistry) (*Message, error) {
	mf := NewMessageFactoryWithExtensionRegistry(er)
	return AsDynamicMessageWithMessageFactory(msg, mf)
}

// AsDynamicMessageWithMessageFactory converts the given message to a dynamic
// message. If the given message is dynamic, it is returned. Otherwise, a
// dynamic message is created using NewMessageWithMessageFactory.
func AsDynamicMessageWithMessageFactory(msg proto.Message, mf *MessageFactory) (*Message, error) {
	if dm, ok := msg.(*Message); ok {
		return dm, nil
	}
	md, err := desc.LoadMessageDescriptorForMessage(msg)
	if err != nil {
		return nil, err
	}
	dm := NewMessageWithMessageFactory(md, mf)
	err = dm.mergeFrom(msg)
	if err != nil {
		return nil, err
	}
	return dm, nil
}

// GetMessageDescriptor returns a descriptor for this message's type.
func (m *Message) GetMessageDescriptor() *desc.MessageDescriptor {
	return m.md
}

// GetKnownFields returns a slice of descriptors for all known fields. The
// fields will not be in any defined order.
func (m *Message) GetKnownFields() []*desc.FieldDescriptor {
	if len(m.extraFields) == 0 {
		return m.md.GetFields()
	}
	flds := make([]*desc.FieldDescriptor, len(m.md.GetFields()), len(m.md.GetFields())+len(m.extraFields))
	copy(flds, m.md.GetFields())
	for _, fld := range m.extraFields {
		if !fld.IsExtension() {
			flds = append(flds, fld)
		}
	}
	return flds
}

// GetKnownExtensions returns a slice of descriptors for all extensions known by
// the message's extension registry. The fields will not be in any defined order.
func (m *Message) GetKnownExtensions() []*desc.FieldDescriptor {
	if !m.md.IsExtendable() {
		return nil
	}
	exts := m.er.AllExtensionsForType(m.md.GetFullyQualifiedName())
	for _, fld := range m.extraFields {
		if fld.IsExtension() {
			exts = append(exts, fld)
		}
	}
	return exts
}

// GetUnknownFields returns a slice of tag numbers for all unknown fields that
// this message contains. The tags will not be in any defined order.
func (m *Message) GetUnknownFields() []int32 {
	flds := make([]int32, 0, len(m.unknownFields))
	for tag := range m.unknownFields {
		flds = append(flds, tag)
	}
	return flds
}

// Descriptor returns the serialized form of the file descriptor in which the
// message was defined and a path to the message type therein. This mimics the
// method of the same name on message types generated by protoc.
func (m *Message) Descriptor() ([]byte, []int) {
	// get encoded file descriptor
	b, err := proto.Marshal(m.md.GetFile().AsProto())
	if err != nil {
		panic(fmt.Sprintf("failed to get encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
	}
	var zippedBytes bytes.Buffer
	w := gzip.NewWriter(&zippedBytes)
	if _, err := w.Write(b); err != nil {
		panic(fmt.Sprintf("failed to get encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
	}
	if err := w.Close(); err != nil {
		panic(fmt.Sprintf("failed to get an encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
	}

	// and path to message
	path := []int{}
	var d desc.Descriptor
	name := m.md.GetFullyQualifiedName()
	for d = m.md.GetParent(); d != nil; name, d = d.GetFullyQualifiedName(), d.GetParent() {
		found := false
		switch d := d.(type) {
		case (*desc.FileDescriptor):
			for i, md := range d.GetMessageTypes() {
				if md.GetFullyQualifiedName() == name {
					found = true
					path = append(path, i)
				}
			}
		case (*desc.MessageDescriptor):
			for i, md := range d.GetNestedMessageTypes() {
				if md.GetFullyQualifiedName() == name {
					found = true
					path = append(path, i)
				}
			}
		}
		if !found {
			panic(fmt.Sprintf("failed to compute descriptor path for %s", m.md.GetFullyQualifiedName()))
		}
	}
	// reverse the path
	i := 0
	j := len(path) - 1
	for i < j {
		path[i], path[j] = path[j], path[i]
		i++
		j--
	}

	return zippedBytes.Bytes(), path
}

// XXX_MessageName returns the fully qualified name of this message's type. This
// allows dynamic messages to be used with proto.MessageName.
func (m *Message) XXX_MessageName() string {
	return m.md.GetFullyQualifiedName()
}

// FindFieldDescriptor returns a field descriptor for the given tag number. This
// searches known fields in the descriptor, known fields discovered during calls
// to GetField or SetField, and extension fields known by the message's extension
// registry. It returns nil if the tag is unknown.
func (m *Message) FindFieldDescriptor(tagNumber int32) *desc.FieldDescriptor {
	fd := m.md.FindFieldByNumber(tagNumber)
	if fd != nil {
		return fd
	}
	fd = m.er.FindExtension(m.md.GetFullyQualifiedName(), tagNumber)
	if fd != nil {
		return fd
	}
	return m.extraFields[tagNumber]
}

// FindFieldDescriptorByName returns a field descriptor for the given field
// name. This searches known fields in the descriptor, known fields discovered
// during calls to GetField or SetField, and extension fields known by the
// message's extension registry. It returns nil if the name is unknown. If the
// given name refers to an extension, it should be fully qualified and may be
// optionally enclosed in parentheses or brackets.
func (m *Message) FindFieldDescriptorByName(name string) *desc.FieldDescriptor {
	if name == "" {
		return nil
	}
	fd := m.md.FindFieldByName(name)
	if fd != nil {
		return fd
	}
	mustBeExt := false
	if name[0] == '(' {
		if name[len(name)-1] != ')' {
			// malformed name
			return nil
		}
		mustBeExt = true
		name = name[1 : len(name)-1]
	} else if name[0] == '[' {
		if name[len(name)-1] != ']' {
			// malformed name
			return nil
		}
		mustBeExt = true
		name = name[1 : len(name)-1]
	}
	fd = m.er.FindExtensionByName(m.md.GetFullyQualifiedName(), name)
	if fd != nil {
		return fd
	}
	for _, fd := range m.extraFields {
		if fd.IsExtension() && name == fd.GetFullyQualifiedName() {
			return fd
		} else if !mustBeExt && !fd.IsExtension() && name == fd.GetName() {
			return fd
		}
	}

	return nil
}

// FindFieldDescriptorByJSONName returns a field descriptor for the given JSON
// name. This searches known fields in the descriptor, known fields discovered
// during calls to GetField or SetField, and extension fields known by the
// message's extension registry. If no field matches the given JSON name, it
// will fall back to searching field names (e.g. FindFieldDescriptorByName). If
// this also yields no match, nil is returned.
func (m *Message) FindFieldDescriptorByJSONName(name string) *desc.FieldDescriptor {
	if name == "" {
		return nil
	}
	fd := m.md.FindFieldByJSONName(name)
	if fd != nil {
		return fd
	}
	mustBeExt := false
	if name[0] == '(' {
		if name[len(name)-1] != ')' {
			// malformed name
			return nil
		}
		mustBeExt = true
		name = name[1 : len(name)-1]
	} else if name[0] == '[' {
		if name[len(name)-1] != ']' {
			// malformed name
			return nil
		}
		mustBeExt = true
		name = name[1 : len(name)-1]
	}
	fd = m.er.FindExtensionByJSONName(m.md.GetFullyQualifiedName(), name)
	if fd != nil {
		return fd
	}
	for _, fd := range m.extraFields {
		if fd.IsExtension() && name == fd.GetFullyQualifiedJSONName() {
			return fd
		} else if !mustBeExt && !fd.IsExtension() && name == fd.GetJSONName() {
			return fd
		}
	}

	// try non-JSON names
	return m.FindFieldDescriptorByName(name)
}

func (m *Message) checkField(fd *desc.FieldDescriptor) error {
	return checkField(fd, m.md)
}

func checkField(fd *desc.FieldDescriptor, md *desc.MessageDescriptor) error {
	if fd.GetOwner().GetFullyQualifiedName() != md.GetFullyQualifiedName() {
		return fmt.Errorf("given field, %s, is for wrong message type: %s; expecting %s", fd.GetName(), fd.GetOwner().GetFullyQualifiedName(), md.GetFullyQualifiedName())
	}
	if fd.IsExtension() && !md.IsExtension(fd.GetNumber()) {
		return fmt.Errorf("given field, %s, is an extension but is not in message extension range: %v", fd.GetFullyQualifiedName(), md.GetExtensionRanges())
	}
	return nil
}

// GetField returns the value for the given field descriptor. It panics if an
// error is encountered. See TryGetField.
func (m *Message) GetField(fd *desc.FieldDescriptor) interface{} {
	if v, err := m.TryGetField(fd); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetField returns the value for the given field descriptor. An error is
// returned if the given field descriptor does not belong to the right message
// type.
//
// The Go type of the returned value, for scalar fields, is the same as protoc
// would generate for the field (in a non-dynamic message). The table below
// lists the scalar types and the corresponding Go types.
//  +-------------------------+-----------+
//  |       Declared Type     |  Go Type  |
//  +-------------------------+-----------+
//  | int32, sint32, sfixed32 | int32     |
//  | int64, sint64, sfixed64 | int64     |
//  | uint32, fixed32         | uint32    |
//  | uint64, fixed64         | uint64    |
//  | float                   | float32   |
//  | double                  | double32  |
//  | bool                    | bool      |
//  | string                  | string    |
//  | bytes                   | []byte    |
//  +-------------------------+-----------+
//
// Values for enum fields will always be int32 values. You can use the enum
// descriptor associated with the field to lookup value names with those values.
// Values for message type fields may be an instance of the generated type *or*
// may be another *dynamic.Message that represents the type.
//
// If the given field is a map field, the returned type will be
// map[interface{}]interface{}. The actual concrete types of keys and values is
// as described above. If the given field is a (non-map) repeated field, the
// returned type is always []interface{}; the type of the actual elements is as
// described above.
//
// If this message has no value for the given field, its default value is
// returned. If the message is defined in a file with "proto3" syntax, the
// default is always the zero value for the field. The default value for map and
// repeated fields is a nil map or slice (respectively). For field's whose types
// is a message, the default value is an empty message for "proto2" syntax or a
// nil message for "proto3" syntax. Note that the in the latter case, a non-nil
// interface with a nil pointer is returned, not a nil interface. Also note that
// whether the returned value is an empty message or nil depends on if *this*
// message was defined as "proto3" syntax, not the message type referred to by
// the field's type.
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) but corresponds to an unknown field, the unknown value will be
// parsed and become known. The parsed value will be returned, or an error will
// be returned if the unknown value cannot be parsed according to the field
// descriptor's type information.
func (m *Message) TryGetField(fd *desc.FieldDescriptor) (interface{}, error) {
	if err := m.checkField(fd); err != nil {
		return nil, err
	}
	return m.getField(fd)
}

// GetFieldByName returns the value for the field with the given name. It panics
// if an error is encountered. See TryGetFieldByName.
func (m *Message) GetFieldByName(name string) interface{} {
	if v, err := m.TryGetFieldByName(name); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetFieldByName returns the value for the field with the given name. An
// error is returned if the given name is unknown. If the given name refers to
// an extension field, it should be fully qualified and optionally enclosed in
// parenthesis or brackets.
//
// If this message has no value for the given field, its default value is
// returned. (See TryGetField for more info on types and default field values.)
func (m *Message) TryGetFieldByName(name string) (interface{}, error) {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return nil, UnknownFieldNameError
	}
	return m.getField(fd)
}

// GetFieldByNumber returns the value for the field with the given tag number.
// It panics if an error is encountered. See TryGetFieldByNumber.
func (m *Message) GetFieldByNumber(tagNumber int) interface{} {
	if v, err := m.TryGetFieldByNumber(tagNumber); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetFieldByNumber returns the value for the field with the given tag
// number. An error is returned if the given tag is unknown.
//
// If this message has no value for the given field, its default value is
// returned. (See TryGetField for more info on types and default field values.)
func (m *Message) TryGetFieldByNumber(tagNumber int) (interface{}, error) {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return nil, UnknownTagNumberError
	}
	return m.getField(fd)
}

func (m *Message) getField(fd *desc.FieldDescriptor) (interface{}, error) {
	return m.doGetField(fd, false)
}

func (m *Message) doGetField(fd *desc.FieldDescriptor, nilIfAbsent bool) (interface{}, error) {
	res := m.values[fd.GetNumber()]
	if res == nil {
		var err error
		if res, err = m.parseUnknownField(fd); err != nil {
			return nil, err
		}
		if res == nil {
			if nilIfAbsent {
				return nil, nil
			} else {
				def := fd.GetDefaultValue()
				if def != nil {
					return def, nil
				}
				// GetDefaultValue only returns nil for message types
				md := fd.GetMessageType()
				if md.IsProto3() {
					// try to return a proper nil pointer
					msgType := proto.MessageType(md.GetFullyQualifiedName())
					if msgType != nil && msgType.Implements(typeOfProtoMessage) {
						return reflect.Zero(msgType).Interface().(proto.Message), nil
					}
					// fallback to nil dynamic message pointer
					return (*Message)(nil), nil
				} else {
					// for proto2, return default instance of message
					return m.mf.NewMessage(md), nil
				}
			}
		}
	}
	rt := reflect.TypeOf(res)
	if rt.Kind() == reflect.Map {
		// make defensive copies to prevent caller from storing illegal keys and values
		m := res.(map[interface{}]interface{})
		res := map[interface{}]interface{}{}
		for k, v := range m {
			res[k] = v
		}
		return res, nil
	} else if rt.Kind() == reflect.Slice && rt != typeOfBytes {
		// make defensive copies to prevent caller from storing illegal elements
		sl := res.([]interface{})
		res := make([]interface{}, len(sl))
		copy(res, sl)
		return res, nil
	}
	return res, nil
}

// HasField returns true if this message has a value for the given field. If the
// given field is not valid (e.g. belongs to a different message type), false is
// returned. If this message is defined in a file with "proto3" syntax, this
// will return false even if a field was explicitly assigned its zero value (the
// zero values for a field are intentionally indistinguishable from absent).
func (m *Message) HasField(fd *desc.FieldDescriptor) bool {
	if err := m.checkField(fd); err != nil {
		return false
	}
	return m.HasFieldNumber(int(fd.GetNumber()))
}

// HasFieldName returns true if this message has a value for a field with the
// given name. If the given name is unknown, this returns false.
func (m *Message) HasFieldName(name string) bool {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return false
	}
	return m.HasFieldNumber(int(fd.GetNumber()))
}

// HasFieldNumber returns true if this message has a value for a field with the
// given tag number. If the given tag is unknown, this returns false.
func (m *Message) HasFieldNumber(tagNumber int) bool {
	if _, ok := m.values[int32(tagNumber)]; ok {
		return true
	}
	_, ok := m.unknownFields[int32(tagNumber)]
	return ok
}

// SetField sets the value for the given field descriptor to the given value. It
// panics if an error is encountered. See TrySetField.
func (m *Message) SetField(fd *desc.FieldDescriptor, val interface{}) {
	if err := m.TrySetField(fd, val); err != nil {
		panic(err.Error())
	}
}

// TrySetField sets the value for the given field descriptor to the given value.
// An error is returned if the given field descriptor does not belong to the
// right message type or if the given value is not a correct/compatible type for
// the given field.
//
// The Go type expected for a field  is the same as TryGetField would return for
// the field. So message values can be supplied as either the correct generated
// message type or as a *dynamic.Message.
//
// Since it is cumbersome to work with dynamic messages, some concessions are
// made to simplify usage regarding types:
//
//  1. If a numeric type is provided that can be converted *without loss or
//     overflow*, it is accepted. This allows for setting int64 fields using int
//     or int32 values. Similarly for uint64 with uint and uint32 values and for
//     float64 fields with float32 values.
//  2. The value can be a named type, as long as its underlying type is correct.
//  3. Map and repeated fields can be set using any kind of concrete map or
//     slice type, as long as the values within are all of the correct type. So
//     a field defined as a 'map<string, int32>` can be set using a
//     map[string]int32, a map[string]interface{}, or even a
//     map[interface{}]interface{}.
//  4. Finally, dynamic code that chooses to not treat maps as a special-case
//     find that they can set map fields using a slice where each element is a
//     message that matches the implicit map-entry field message type.
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) it will become known. Subsequent operations using tag numbers or
// names will be able to resolve the newly-known type. If the message has a
// value for the unknown value, it is cleared, replaced by the given known
// value.
func (m *Message) TrySetField(fd *desc.FieldDescriptor, val interface{}) error {
	if err := m.checkField(fd); err != nil {
		return err
	}
	return m.setField(fd, val)
}

// SetFieldByName sets the value for the field with the given name to the given
// value. It panics if an error is encountered. See TrySetFieldByName.
func (m *Message) SetFieldByName(name string, val interface{}) {
	if err := m.TrySetFieldByName(name, val); err != nil {
		panic(err.Error())
	}
}

// TrySetFieldByName sets the value for the field with the given name to the
// given value. An error is returned if the given name is unknown or if the
// given value has an incorrect type. If the given name refers to an extension
// field, it should be fully qualified and optionally enclosed in parenthesis or
// brackets.
//
// (See TrySetField for more info on types.)
func (m *Message) TrySetFieldByName(name string, val interface{}) error {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	return m.setField(fd, val)
}

// SetFieldByNumber sets the value for the field with the given tag number to
// the given value. It panics if an error is encountered. See
// TrySetFieldByNumber.
func (m *Message) SetFieldByNumber(tagNumber int, val interface{}) {
	if err := m.TrySetFieldByNumber(tagNumber, val); err != nil {
		panic(err.Error())
	}
}

// TrySetFieldByNumber sets the value for the field with the given tag number to
// the given value. An error is returned if the given tag is unknown or if the
// given value has an incorrect type.
//
// (See TrySetField for more info on types.)
func (m *Message) TrySetFieldByNumber(tagNumber int, val interface{}) error {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	return m.setField(fd, val)
}

func (m *Message) setField(fd *desc.FieldDescriptor, val interface{}) error {
	var err error
	if val, err = validFieldValue(fd, val); err != nil {
		return err
	}
	m.internalSetField(fd, val)
	return nil
}

func (m *Message) internalSetField(fd *desc.FieldDescriptor, val interface{}) {
	if fd.IsRepeated() {
		// Unset fields and zero-length fields are indistinguishable, in both
		// proto2 and proto3 syntax
		if reflect.ValueOf(val).Len() == 0 {
			if m.values != nil {
				delete(m.values, fd.GetNumber())
			}
			return
		}
	} else if m.md.IsProto3() && fd.GetOneOf() == nil {
		// proto3 considers fields that are set to their zero value as unset
		// (we already handled repeated fields above)
		var equal bool
		if b, ok := val.([]byte); ok {
			// can't compare slices, so we have to special-case []byte values
			equal = ok && bytes.Equal(b, fd.GetDefaultValue().([]byte))
		} else {
			defVal := fd.GetDefaultValue()
			equal = defVal == val
			if !equal && defVal == nil {
				// above just checks if value is the nil interface,
				// but we should also test if the given value is a
				// nil pointer
				rv := reflect.ValueOf(val)
				if rv.Kind() == reflect.Ptr && rv.IsNil() {
					equal = true
				}
			}
		}
		if equal {
			if m.values != nil {
				delete(m.values, fd.GetNumber())
			}
			return
		}
	}
	if m.values == nil {
		m.values = map[int32]interface{}{}
	}
	m.values[fd.GetNumber()] = val
	// if this field is part of a one-of, make sure all other one-of choices are cleared
	od := fd.GetOneOf()
	if od != nil {
		for _, other := range od.GetChoices() {
			if other.GetNumber() != fd.GetNumber() {
				delete(m.values, other.GetNumber())
			}
		}
	}
	// also clear any unknown fields
	if m.unknownFields != nil {
		delete(m.unknownFields, fd.GetNumber())
	}
	// and add this field if it was previously unknown
	if existing := m.FindFieldDescriptor(fd.GetNumber()); existing == nil {
		m.addField(fd)
	}
}

func (m *Message) addField(fd *desc.FieldDescriptor) {
	if m.extraFields == nil {
		m.extraFields = map[int32]*desc.FieldDescriptor{}
	}
	m.extraFields[fd.GetNumber()] = fd
}

// ClearField removes any value for the given field. It panics if an error is
// encountered. See TryClearField.
func (m *Message) ClearField(fd *desc.FieldDescriptor) {
	if err := m.TryClearField(fd); err != nil {
		panic(err.Error())
	}
}

// TryClearField removes any value for the given field. An error is returned if
// the given field descriptor does not belong to the right message type.
func (m *Message) TryClearField(fd *desc.FieldDescriptor) error {
	if err := m.checkField(fd); err != nil {
		return err
	}
	m.clearField(fd)
	return nil
}

// ClearFieldByName removes any value for the field with the given name. It
// panics if an error is encountered. See TryClearFieldByName.
func (m *Message) ClearFieldByName(name string) {
	if err := m.TryClearFieldByName(name); err != nil {
		panic(err.Error())
	}
}

// TryClearFieldByName removes any value for the field with the given name. An
// error is returned if the given name is unknown. If the given name refers to
// an extension field, it should be fully qualified and optionally enclosed in
// parenthesis or brackets.
func (m *Message) TryClearFieldByName(name string) error {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	m.clearField(fd)
	return nil
}

// ClearFieldByNumber removes any value for the field with the given tag number.
// It panics if an error is encountered. See TryClearFieldByNumber.
func (m *Message) ClearFieldByNumber(tagNumber int) {
	if err := m.TryClearFieldByNumber(tagNumber); err != nil {
		panic(err.Error())
	}
}

// TryClearFieldByNumber removes any value for the field with the given tag
// number. An error is returned if the given tag is unknown.
func (m *Message) TryClearFieldByNumber(tagNumber int) error {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	m.clearField(fd)
	return nil
}

func (m *Message) clearField(fd *desc.FieldDescriptor) {
	// clear value
	if m.values != nil {
		delete(m.values, fd.GetNumber())
	}
	// also clear any unknown fields
	if m.unknownFields != nil {
		delete(m.unknownFields, fd.GetNumber())
	}
	// and add this field if it was previously unknown
	if existing := m.FindFieldDescriptor(fd.GetNumber()); existing == nil {
		m.addField(fd)
	}
}

// GetOneOfField returns which of the given one-of's fields is set and the
// corresponding value. It panics if an error is encountered. See
// TryGetOneOfField.
func (m *Message) GetOneOfField(od *desc.OneOfDescriptor) (*desc.FieldDescriptor, interface{}) {
	if fd, val, err := m.TryGetOneOfField(od); err != nil {
		panic(err.Error())
	} else {
		return fd, val
	}
}

// TryGetOneOfField returns which of the given one-of's fields is set and the
// corresponding value. An error is returned if the given one-of belongs to the
// wrong message type. If the given one-of has no field set, this method will
// return nil, nil.
//
// The type of the value, if one is set, is the same as would be returned by
// TryGetField using the returned field descriptor.
//
// Like with TryGetField, if the given one-of contains any fields that are not
// known (e.g. not present in this message's descriptor), they will become known
// and any unknown value will be parsed (and become a known value on success).
func (m *Message) TryGetOneOfField(od *desc.OneOfDescriptor) (*desc.FieldDescriptor, interface{}, error) {
	if od.GetOwner().GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
		return nil, nil, fmt.Errorf("given one-of, %s, is for wrong message type: %s; expecting %s", od.GetName(), od.GetOwner().GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
	}
	for _, fd := range od.GetChoices() {
		val, err := m.doGetField(fd, true)
		if err != nil {
			return nil, nil, err
		}
		if val != nil {
			return fd, val, nil
		}
	}
	return nil, nil, nil
}

// ClearOneOfField removes any value for any of the given one-of's fields. It
// panics if an error is encountered. See TryClearOneOfField.
func (m *Message) ClearOneOfField(od *desc.OneOfDescriptor) {
	if err := m.TryClearOneOfField(od); err != nil {
		panic(err.Error())
	}
}

// TryClearOneOfField removes any value for any of the given one-of's fields. An
// error is returned if the given one-of descriptor does not belong to the right
// message type.
func (m *Message) TryClearOneOfField(od *desc.OneOfDescriptor) error {
	if od.GetOwner().GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
		return fmt.Errorf("given one-of, %s, is for wrong message type: %s; expecting %s", od.GetName(), od.GetOwner().GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
	}
	for _, fd := range od.GetChoices() {
		m.clearField(fd)
	}
	return nil
}

// GetMapField returns the value for the given map field descriptor and given
// key. It panics if an error is encountered. See TryGetMapField.
func (m *Message) GetMapField(fd *desc.FieldDescriptor, key interface{}) interface{} {
	if v, err := m.TryGetMapField(fd, key); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetMapField returns the value for the given map field descriptor and given
// key. An error is returned if the given field descriptor does not belong to
// the right message type or if it is not a map field.
//
// If the map field does not contain the requested key, this method returns
// nil, nil. The Go type of the value returned mirrors the type that protoc
// would generate for the field. (See TryGetField for more details on types).
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) but corresponds to an unknown field, the unknown value will be
// parsed and become known. The parsed value will be searched for the requested
// key and any value returned. An error will be returned if the unknown value
// cannot be parsed according to the field descriptor's type information.
func (m *Message) TryGetMapField(fd *desc.FieldDescriptor, key interface{}) (interface{}, error) {
	if err := m.checkField(fd); err != nil {
		return nil, err
	}
	return m.getMapField(fd, key)
}

// GetMapFieldByName returns the value for the map field with the given name and
// given key. It panics if an error is encountered. See TryGetMapFieldByName.
func (m *Message) GetMapFieldByName(name string, key interface{}) interface{} {
	if v, err := m.TryGetMapFieldByName(name, key); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetMapFieldByName returns the value for the map field with the given name
// and given key. An error is returned if the given name is unknown or if it
// names a field that is not a map field.
//
// If this message has no value for the given field or the value has no value
// for the requested key, then this method returns nil, nil.
//
// (See TryGetField for more info on types.)
func (m *Message) TryGetMapFieldByName(name string, key interface{}) (interface{}, error) {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return nil, UnknownFieldNameError
	}
	return m.getMapField(fd, key)
}

// GetMapFieldByNumber returns the value for the map field with the given tag
// number and given key. It panics if an error is encountered. See
// TryGetMapFieldByNumber.
func (m *Message) GetMapFieldByNumber(tagNumber int, key interface{}) interface{} {
	if v, err := m.TryGetMapFieldByNumber(tagNumber, key); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetMapFieldByNumber returns the value for the map field with the given tag
// number and given key. An error is returned if the given tag is unknown or if
// it indicates a field that is not a map field.
//
// If this message has no value for the given field or the value has no value
// for the requested key, then this method returns nil, nil.
//
// (See TryGetField for more info on types.)
func (m *Message) TryGetMapFieldByNumber(tagNumber int, key interface{}) (interface{}, error) {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return nil, UnknownTagNumberError
	}
	return m.getMapField(fd, key)
}

func (m *Message) getMapField(fd *desc.FieldDescriptor, key interface{}) (interface{}, error) {
	if !fd.IsMap() {
		return nil, FieldIsNotMapError
	}
	kfd := fd.GetMessageType().GetFields()[0]
	ki, err := validElementFieldValue(kfd, key)
	if err != nil {
		return nil, err
	}
	mp := m.values[fd.GetNumber()]
	if mp == nil {
		if mp, err = m.parseUnknownField(fd); err != nil {
			return nil, err
		} else if mp == nil {
			return nil, nil
		}
	}
	return mp.(map[interface{}]interface{})[ki], nil
}

// ForEachMapFieldEntry executes the given function for each entry in the map
// value for the given field descriptor. It stops iteration if the function
// returns false. It panics if an error is encountered. See
// TryForEachMapFieldEntry.
func (m *Message) ForEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) {
	if err := m.TryForEachMapFieldEntry(fd, fn); err != nil {
		panic(err.Error())
	}
}

// TryForEachMapFieldEntry executes the given function for each entry in the map
// value for the given field descriptor. An error is returned if the given field
// descriptor does not belong to the right message type or if it is not a  map
// field.
//
// Iteration ends either when all entries have been examined or when the given
// function returns false. So the function is expected to return true for normal
// iteration and false to break out. If this message has no value for the given
// field, it returns without invoking the given function.
//
// The Go type of the key and value supplied to the function mirrors the type
// that protoc would generate for the field. (See TryGetField for more details
// on types).
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) but corresponds to an unknown field, the unknown value will be
// parsed and become known. The parsed value will be searched for the requested
// key and any value returned. An error will be returned if the unknown value
// cannot be parsed according to the field descriptor's type information.
func (m *Message) TryForEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) error {
	if err := m.checkField(fd); err != nil {
		return err
	}
	return m.forEachMapFieldEntry(fd, fn)
}

// ForEachMapFieldEntryByName executes the given function for each entry in the
// map value for the field with the given name. It stops iteration if the
// function returns false. It panics if an error is encountered. See
// TryForEachMapFieldEntryByName.
func (m *Message) ForEachMapFieldEntryByName(name string, fn func(key, val interface{}) bool) {
	if err := m.TryForEachMapFieldEntryByName(name, fn); err != nil {
		panic(err.Error())
	}
}

// TryForEachMapFieldEntryByName executes the given function for each entry in
// the map value for the field with the given name. It stops iteration if the
// function returns false. An error is returned if the given name is unknown or
// if it names a field that is not a map field.
//
// If this message has no value for the given field, it returns without ever
// invoking the given function.
//
// (See TryGetField for more info on types supplied to the function.)
func (m *Message) TryForEachMapFieldEntryByName(name string, fn func(key, val interface{}) bool) error {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	return m.forEachMapFieldEntry(fd, fn)
}

// ForEachMapFieldEntryByNumber executes the given function for each entry in
// the map value for the field with the given tag number. It stops iteration if
// the function returns false. It panics if an error is encountered. See
// TryForEachMapFieldEntryByNumber.
func (m *Message) ForEachMapFieldEntryByNumber(tagNumber int, fn func(key, val interface{}) bool) {
	if err := m.TryForEachMapFieldEntryByNumber(tagNumber, fn); err != nil {
		panic(err.Error())
	}
}

// TryForEachMapFieldEntryByNumber executes the given function for each entry in
// the map value for the field with the given tag number. It stops iteration if
// the function returns false. An error is returned if the given tag is unknown
// or if it indicates a field that is not a map field.
//
// If this message has no value for the given field, it returns without ever
// invoking the given function.
//
// (See TryGetField for more info on types supplied to the function.)
func (m *Message) TryForEachMapFieldEntryByNumber(tagNumber int, fn func(key, val interface{}) bool) error {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	return m.forEachMapFieldEntry(fd, fn)
}

func (m *Message) forEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) error {
	if !fd.IsMap() {
		return FieldIsNotMapError
	}
	mp := m.values[fd.GetNumber()]
	if mp == nil {
		if mp, err := m.parseUnknownField(fd); err != nil {
			return err
		} else if mp == nil {
			return nil
		}
	}
	for k, v := range mp.(map[interface{}]interface{}) {
		if !fn(k, v) {
			break
		}
	}
	return nil
}

// PutMapField sets the value for the given map field descriptor and given key
// to the given value. It panics if an error is encountered. See TryPutMapField.
func (m *Message) PutMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) {
	if err := m.TryPutMapField(fd, key, val); err != nil {
		panic(err.Error())
	}
}

// TryPutMapField sets the value for the given map field descriptor and given
// key to the given value. An error is returned if the given field descriptor
// does not belong to the right message type, if the given field is not a map
// field, or if the given value is not a correct/compatible type for the given
// field.
//
// The Go type expected for a field  is the same as required by TrySetField for
// a field with the same type as the map's value type.
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) it will become known. Subsequent operations using tag numbers or
// names will be able to resolve the newly-known type. If the message has a
// value for the unknown value, it is cleared, replaced by the given known
// value.
func (m *Message) TryPutMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) error {
	if err := m.checkField(fd); err != nil {
		return err
	}
	return m.putMapField(fd, key, val)
}

// PutMapFieldByName sets the value for the map field with the given name and
// given key to the given value. It panics if an error is encountered. See
// TryPutMapFieldByName.
func (m *Message) PutMapFieldByName(name string, key interface{}, val interface{}) {
	if err := m.TryPutMapFieldByName(name, key, val); err != nil {
		panic(err.Error())
	}
}

// TryPutMapFieldByName sets the value for the map field with the given name and
// the given key to the given value. An error is returned if the given name is
// unknown, if it names a field that is not a map, or if the given value has an
// incorrect type.
//
// (See TrySetField for more info on types.)
func (m *Message) TryPutMapFieldByName(name string, key interface{}, val interface{}) error {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	return m.putMapField(fd, key, val)
}

// PutMapFieldByNumber sets the value for the map field with the given tag
// number and given key to the given value. It panics if an error is
// encountered. See TryPutMapFieldByNumber.
func (m *Message) PutMapFieldByNumber(tagNumber int, key interface{}, val interface{}) {
	if err := m.TryPutMapFieldByNumber(tagNumber, key, val); err != nil {
		panic(err.Error())
	}
}

// TryPutMapFieldByNumber sets the value for the map field with the given tag
// number and the given key to the given value. An error is returned if the
// given tag is unknown, if it indicates a field that is not a map, or if the
// given value has an incorrect type.
//
// (See TrySetField for more info on types.)
func (m *Message) TryPutMapFieldByNumber(tagNumber int, key interface{}, val interface{}) error {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	return m.putMapField(fd, key, val)
}

func (m *Message) putMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) error {
	if !fd.IsMap() {
		return FieldIsNotMapError
	}
	kfd := fd.GetMessageType().GetFields()[0]
	ki, err := validElementFieldValue(kfd, key)
	if err != nil {
		return err
	}
	vfd := fd.GetMessageType().GetFields()[1]
	vi, err := validElementFieldValue(vfd, val)
	if err != nil {
		return err
	}
	mp := m.values[fd.GetNumber()]
	if mp == nil {
		if mp, err = m.parseUnknownField(fd); err != nil {
			return err
		} else if mp == nil {
			mp = map[interface{}]interface{}{}
			m.internalSetField(fd, map[interface{}]interface{}{ki: vi})
			return nil
		}
	}
	mp.(map[interface{}]interface{})[ki] = vi
	return nil
}

// RemoveMapField changes the value for the given field descriptor by removing
// any value associated with the given key. It panics if an error is
// encountered. See TryRemoveMapField.
func (m *Message) RemoveMapField(fd *desc.FieldDescriptor, key interface{}) {
	if err := m.TryRemoveMapField(fd, key); err != nil {
		panic(err.Error())
	}
}

// TryRemoveMapField changes the value for the given field descriptor by
// removing any value associated with the given key. An error is returned if the
// given field descriptor does not belong to the right message type or if the
// given field is not a map field.
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) it will become known. Subsequent operations using tag numbers or
// names will be able to resolve the newly-known type. If the message has a
// value for the unknown value, it is parsed and any value for the given key
// removed.
func (m *Message) TryRemoveMapField(fd *desc.FieldDescriptor, key interface{}) error {
	if err := m.checkField(fd); err != nil {
		return err
	}
	return m.removeMapField(fd, key)
}

// RemoveMapFieldByName changes the value for the field with the given name by
// removing any value associated with the given key. It panics if an error is
// encountered. See TryRemoveMapFieldByName.
func (m *Message) RemoveMapFieldByName(name string, key interface{}) {
	if err := m.TryRemoveMapFieldByName(name, key); err != nil {
		panic(err.Error())
	}
}

// TryRemoveMapFieldByName changes the value for the field with the given name
// by removing any value associated with the given key. An error is returned if
// the given name is unknown or if it names a field that is not a map.
func (m *Message) TryRemoveMapFieldByName(name string, key interface{}) error {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	return m.removeMapField(fd, key)
}

// RemoveMapFieldByNumber changes the value for the field with the given tag
// number by removing any value associated with the given key. It panics if an
// error is encountered. See TryRemoveMapFieldByNumber.
func (m *Message) RemoveMapFieldByNumber(tagNumber int, key interface{}) {
	if err := m.TryRemoveMapFieldByNumber(tagNumber, key); err != nil {
		panic(err.Error())
	}
}

// TryRemoveMapFieldByNumber changes the value for the field with the given tag
// number by removing any value associated with the given key. An error is
// returned if the given tag is unknown or if it indicates a field that is not
// a map.
func (m *Message) TryRemoveMapFieldByNumber(tagNumber int, key interface{}) error {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	return m.removeMapField(fd, key)
}

func (m *Message) removeMapField(fd *desc.FieldDescriptor, key interface{}) error {
	if !fd.IsMap() {
		return FieldIsNotMapError
	}
	kfd := fd.GetMessageType().GetFields()[0]
	ki, err := validElementFieldValue(kfd, key)
	if err != nil {
		return err
	}
	mp := m.values[fd.GetNumber()]
	if mp == nil {
		if mp, err = m.parseUnknownField(fd); err != nil {
			return err
		} else if mp == nil {
			return nil
		}
	}
	res := mp.(map[interface{}]interface{})
	delete(res, ki)
	if len(res) == 0 {
		delete(m.values, fd.GetNumber())
	}
	return nil
}

// FieldLength returns the number of elements in this message for the given
// field descriptor. It panics if an error is encountered. See TryFieldLength.
func (m *Message) FieldLength(fd *desc.FieldDescriptor) int {
	l, err := m.TryFieldLength(fd)
	if err != nil {
		panic(err.Error())
	}
	return l
}

// TryFieldLength returns the number of elements in this message for the given
// field descriptor. An error is returned if the given field descriptor does not
// belong to the right message type or if it is neither a map field nor a
// repeated field.
func (m *Message) TryFieldLength(fd *desc.FieldDescriptor) (int, error) {
	if err := m.checkField(fd); err != nil {
		return 0, err
	}
	return m.fieldLength(fd)
}

// FieldLengthByName returns the number of elements in this message for the
// field with the given name. It panics if an error is encountered. See
// TryFieldLengthByName.
func (m *Message) FieldLengthByName(name string) int {
	l, err := m.TryFieldLengthByName(name)
	if err != nil {
		panic(err.Error())
	}
	return l
}

// TryFieldLengthByName returns the number of elements in this message for the
// field with the given name. An error is returned if the given name is unknown
// or if the named field is neither a map field nor a repeated field.
func (m *Message) TryFieldLengthByName(name string) (int, error) {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return 0, UnknownFieldNameError
	}
	return m.fieldLength(fd)
}

// FieldLengthByNumber returns the number of elements in this message for the
// field with the given tag number. It panics if an error is encountered. See
// TryFieldLengthByNumber.
func (m *Message) FieldLengthByNumber(tagNumber int32) int {
	l, err := m.TryFieldLengthByNumber(tagNumber)
	if err != nil {
		panic(err.Error())
	}
	return l
}

// TryFieldLengthByNumber returns the number of elements in this message for the
// field with the given tag number. An error is returned if the given tag is
// unknown or if the named field is neither a map field nor a repeated field.
func (m *Message) TryFieldLengthByNumber(tagNumber int32) (int, error) {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return 0, UnknownTagNumberError
	}
	return m.fieldLength(fd)
}

func (m *Message) fieldLength(fd *desc.FieldDescriptor) (int, error) {
	if !fd.IsRepeated() {
		return 0, FieldIsNotRepeatedError
	}
	val := m.values[fd.GetNumber()]
	if val == nil {
		var err error
		if val, err = m.parseUnknownField(fd); err != nil {
			return 0, err
		} else if val == nil {
			return 0, nil
		}
	}
	if sl, ok := val.([]interface{}); ok {
		return len(sl), nil
	} else if mp, ok := val.(map[interface{}]interface{}); ok {
		return len(mp), nil
	}
	return 0, nil
}

// GetRepeatedField returns the value for the given repeated field descriptor at
// the given index. It panics if an error is encountered. See
// TryGetRepeatedField.
func (m *Message) GetRepeatedField(fd *desc.FieldDescriptor, index int) interface{} {
	if v, err := m.TryGetRepeatedField(fd, index); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetRepeatedField returns the value for the given repeated field descriptor
// at the given index. An error is returned if the given field descriptor does
// not belong to the right message type, if it is not a repeated field, or if
// the given index is out of range (less than zero or greater than or equal to
// the length of the repeated field). Also, even though map fields technically
// are repeated fields, if the given field is a map field an error will result:
// map representation does not lend itself to random access by index.
//
// The Go type of the value returned mirrors the type that protoc would generate
// for the field's element type. (See TryGetField for more details on types).
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) but corresponds to an unknown field, the unknown value will be
// parsed and become known. The value at the given index in the parsed value
// will be returned. An error will be returned if the unknown value cannot be
// parsed according to the field descriptor's type information.
func (m *Message) TryGetRepeatedField(fd *desc.FieldDescriptor, index int) (interface{}, error) {
	if index < 0 {
		return nil, IndexOutOfRangeError
	}
	if err := m.checkField(fd); err != nil {
		return nil, err
	}
	return m.getRepeatedField(fd, index)
}

// GetRepeatedFieldByName returns the value for the repeated field with the
// given name at the given index. It panics if an error is encountered. See
// TryGetRepeatedFieldByName.
func (m *Message) GetRepeatedFieldByName(name string, index int) interface{} {
	if v, err := m.TryGetRepeatedFieldByName(name, index); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetRepeatedFieldByName returns the value for the repeated field with the
// given name at the given index. An error is returned if the given name is
// unknown, if it names a field that is not a repeated field (or is a map
// field), or if the given index is out of range (less than zero or greater
// than or equal to the length of the repeated field).
//
// (See TryGetField for more info on types.)
func (m *Message) TryGetRepeatedFieldByName(name string, index int) (interface{}, error) {
	if index < 0 {
		return nil, IndexOutOfRangeError
	}
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return nil, UnknownFieldNameError
	}
	return m.getRepeatedField(fd, index)
}

// GetRepeatedFieldByNumber returns the value for the repeated field with the
// given tag number at the given index. It panics if an error is encountered.
// See TryGetRepeatedFieldByNumber.
func (m *Message) GetRepeatedFieldByNumber(tagNumber int, index int) interface{} {
	if v, err := m.TryGetRepeatedFieldByNumber(tagNumber, index); err != nil {
		panic(err.Error())
	} else {
		return v
	}
}

// TryGetRepeatedFieldByNumber returns the value for the repeated field with the
// given tag number at the given index. An error is returned if the given tag is
// unknown, if it indicates a field that is not a repeated field (or is a map
// field), or if the given index is out of range (less than zero or greater than
// or equal to the length of the repeated field).
//
// (See TryGetField for more info on types.)
func (m *Message) TryGetRepeatedFieldByNumber(tagNumber int, index int) (interface{}, error) {
	if index < 0 {
		return nil, IndexOutOfRangeError
	}
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return nil, UnknownTagNumberError
	}
	return m.getRepeatedField(fd, index)
}

func (m *Message) getRepeatedField(fd *desc.FieldDescriptor, index int) (interface{}, error) {
	if fd.IsMap() || !fd.IsRepeated() {
		return nil, FieldIsNotRepeatedError
	}
	sl := m.values[fd.GetNumber()]
	if sl == nil {
		var err error
		if sl, err = m.parseUnknownField(fd); err != nil {
			return nil, err
		} else if sl == nil {
			return nil, IndexOutOfRangeError
		}
	}
	res := sl.([]interface{})
	if index >= len(res) {
		return nil, IndexOutOfRangeError
	}
	return res[index], nil
}

// AddRepeatedField appends the given value to the given repeated field. It
// panics if an error is encountered. See TryAddRepeatedField.
func (m *Message) AddRepeatedField(fd *desc.FieldDescriptor, val interface{}) {
	if err := m.TryAddRepeatedField(fd, val); err != nil {
		panic(err.Error())
	}
}

// TryAddRepeatedField appends the given value to the given repeated field. An
// error is returned if the given field descriptor does not belong to the right
// message type, if the given field is not repeated, or if the given value is
// not a correct/compatible type for the given field. If the given field is a
// map field, the call will succeed if the given value is an instance of the
// map's entry message type.
//
// The Go type expected for a field  is the same as required by TrySetField for
// a non-repeated field of the same type.
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) it will become known. Subsequent operations using tag numbers or
// names will be able to resolve the newly-known type. If the message has a
// value for the unknown value, it is parsed and the given value is appended to
// it.
func (m *Message) TryAddRepeatedField(fd *desc.FieldDescriptor, val interface{}) error {
	if err := m.checkField(fd); err != nil {
		return err
	}
	return m.addRepeatedField(fd, val)
}

// AddRepeatedFieldByName appends the given value to the repeated field with the
// given name. It panics if an error is encountered. See
// TryAddRepeatedFieldByName.
func (m *Message) AddRepeatedFieldByName(name string, val interface{}) {
	if err := m.TryAddRepeatedFieldByName(name, val); err != nil {
		panic(err.Error())
	}
}

// TryAddRepeatedFieldByName appends the given value to the repeated field with
// the given name. An error is returned if the given name is unknown, if it
// names a field that is not repeated, or if the given value has an incorrect
// type.
//
// (See TrySetField for more info on types.)
func (m *Message) TryAddRepeatedFieldByName(name string, val interface{}) error {
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	return m.addRepeatedField(fd, val)
}

// AddRepeatedFieldByNumber appends the given value to the repeated field with
// the given tag number. It panics if an error is encountered. See
// TryAddRepeatedFieldByNumber.
func (m *Message) AddRepeatedFieldByNumber(tagNumber int, val interface{}) {
	if err := m.TryAddRepeatedFieldByNumber(tagNumber, val); err != nil {
		panic(err.Error())
	}
}

// TryAddRepeatedFieldByNumber appends the given value to the repeated field
// with the given tag number. An error is returned if the given tag is unknown,
// if it indicates a field that is not repeated, or if the given value has an
// incorrect type.
//
// (See TrySetField for more info on types.)
func (m *Message) TryAddRepeatedFieldByNumber(tagNumber int, val interface{}) error {
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	return m.addRepeatedField(fd, val)
}

func (m *Message) addRepeatedField(fd *desc.FieldDescriptor, val interface{}) error {
	if !fd.IsRepeated() {
		return FieldIsNotRepeatedError
	}
	val, err := validElementFieldValue(fd, val)
	if err != nil {
		return err
	}

	if fd.IsMap() {
		// We're lenient. Just as we allow setting a map field to a slice of entry messages, we also allow
		// adding entries one at a time (as if the field were a normal repeated field).
		msg := val.(proto.Message)
		dm, err := asDynamicMessage(msg, fd.GetMessageType(), m.mf)
		if err != nil {
			return err
		}
		k, err := dm.TryGetFieldByNumber(1)
		if err != nil {
			return err
		}
		v, err := dm.TryGetFieldByNumber(2)
		if err != nil {
			return err
		}
		return m.putMapField(fd, k, v)
	}

	sl := m.values[fd.GetNumber()]
	if sl == nil {
		if sl, err = m.parseUnknownField(fd); err != nil {
			return err
		} else if sl == nil {
			sl = []interface{}{}
		}
	}
	res := sl.([]interface{})
	res = append(res, val)
	m.internalSetField(fd, res)
	return nil
}

// SetRepeatedField sets the value for the given repeated field descriptor and
// given index to the given value. It panics if an error is encountered. See
// SetRepeatedField.
func (m *Message) SetRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) {
	if err := m.TrySetRepeatedField(fd, index, val); err != nil {
		panic(err.Error())
	}
}

// TrySetRepeatedField sets the value for the given repeated field descriptor
// and given index to the given value. An error is returned if the given field
// descriptor does not belong to the right message type, if the given field is
// not repeated, or if the given value is not a correct/compatible type for the
// given field. Also, even though map fields technically are repeated fields, if
// the given field is a map field an error will result: map representation does
// not lend itself to random access by index.
//
// The Go type expected for a field  is the same as required by TrySetField for
// a non-repeated field of the same type.
//
// If the given field descriptor is not known (e.g. not present in the message
// descriptor) it will become known. Subsequent operations using tag numbers or
// names will be able to resolve the newly-known type. If the message has a
// value for the unknown value, it is parsed and the element at the given index
// is replaced with the given value.
func (m *Message) TrySetRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) error {
	if index < 0 {
		return IndexOutOfRangeError
	}
	if err := m.checkField(fd); err != nil {
		return err
	}
	return m.setRepeatedField(fd, index, val)
}

// SetRepeatedFieldByName sets the value for the repeated field with the given
// name and given index to the given value. It panics if an error is
// encountered. See TrySetRepeatedFieldByName.
func (m *Message) SetRepeatedFieldByName(name string, index int, val interface{}) {
	if err := m.TrySetRepeatedFieldByName(name, index, val); err != nil {
		panic(err.Error())
	}
}

// TrySetRepeatedFieldByName sets the value for the repeated field with the
// given name and the given index to the given value. An error is returned if
// the given name is unknown, if it names a field that is not repeated (or is a
// map field), or if the given value has an incorrect type.
//
// (See TrySetField for more info on types.)
func (m *Message) TrySetRepeatedFieldByName(name string, index int, val interface{}) error {
	if index < 0 {
		return IndexOutOfRangeError
	}
	fd := m.FindFieldDescriptorByName(name)
	if fd == nil {
		return UnknownFieldNameError
	}
	return m.setRepeatedField(fd, index, val)
}

// SetRepeatedFieldByNumber sets the value for the repeated field with the given
// tag number and given index to the given value. It panics if an error is
// encountered. See TrySetRepeatedFieldByNumber.
func (m *Message) SetRepeatedFieldByNumber(tagNumber int, index int, val interface{}) {
	if err := m.TrySetRepeatedFieldByNumber(tagNumber, index, val); err != nil {
		panic(err.Error())
	}
}

// TrySetRepeatedFieldByNumber sets the value for the repeated field with the
// given tag number and the given index to the given value. An error is returned
// if the given tag is unknown, if it indicates a field that is not repeated (or
// is a map field), or if the given value has an incorrect type.
//
// (See TrySetField for more info on types.)
func (m *Message) TrySetRepeatedFieldByNumber(tagNumber int, index int, val interface{}) error {
	if index < 0 {
		return IndexOutOfRangeError
	}
	fd := m.FindFieldDescriptor(int32(tagNumber))
	if fd == nil {
		return UnknownTagNumberError
	}
	return m.setRepeatedField(fd, index, val)
}

func (m *Message) setRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) error {
	if fd.IsMap() || !fd.IsRepeated() {
		return FieldIsNotRepeatedError
	}
	val, err := validElementFieldValue(fd, val)
	if err != nil {
		return err
	}
	sl := m.values[fd.GetNumber()]
	if sl == nil {
		if sl, err = m.parseUnknownField(fd); err != nil {
			return err
		} else if sl == nil {
			return IndexOutOfRangeError
		}
	}
	res := sl.([]interface{})
	if index >= len(res) {
		return IndexOutOfRangeError
	}
	res[index] = val
	return nil
}

// GetUnknownField gets the value(s) for the given unknown tag number. If this
// message has no unknown fields with the given tag, nil is returned.
func (m *Message) GetUnknownField(tagNumber int32) []UnknownField {
	if u, ok := m.unknownFields[tagNumber]; ok {
		return u
	} else {
		return nil
	}
}

func (m *Message) parseUnknownField(fd *desc.FieldDescriptor) (interface{}, error) {
	unks, ok := m.unknownFields[fd.GetNumber()]
	if !ok {
		return nil, nil
	}
	var v interface{}
	var sl []interface{}
	var mp map[interface{}]interface{}
	if fd.IsMap() {
		mp = map[interface{}]interface{}{}
	}
	var err error
	for _, unk := range unks {
		var val interface{}
		if unk.Encoding == proto.WireBytes || unk.Encoding == proto.WireStartGroup {
			val, err = unmarshalLengthDelimitedField(fd, unk.Contents, m.mf)
		} else {
			val, err = unmarshalSimpleField(fd, unk.Value)
		}
		if err != nil {
			return nil, err
		}
		if fd.IsMap() {
			newEntry := val.(*Message)
			kk, err := newEntry.TryGetFieldByNumber(1)
			if err != nil {
				return nil, err
			}
			vv, err := newEntry.TryGetFieldByNumber(2)
			if err != nil {
				return nil, err
			}
			mp[kk] = vv
			v = mp
		} else if fd.IsRepeated() {
			t := reflect.TypeOf(val)
			if t.Kind() == reflect.Slice && t != typeOfBytes {
				// append slices if we unmarshalled a packed repeated field
				newVals := val.([]interface{})
				sl = append(sl, newVals...)
			} else {
				sl = append(sl, val)
			}
			v = sl
		} else {
			v = val
		}
	}
	m.internalSetField(fd, v)
	return v, nil
}

func validFieldValue(fd *desc.FieldDescriptor, val interface{}) (interface{}, error) {
	return validFieldValueForRv(fd, reflect.ValueOf(val))
}

func validFieldValueForRv(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
	if fd.IsMap() && val.Kind() == reflect.Map {
		return validFieldValueForMapField(fd, val)
	}

	if fd.IsRepeated() { // this will also catch map fields where given value was not a map
		if val.Kind() != reflect.Array && val.Kind() != reflect.Slice {
			if fd.IsMap() {
				return nil, fmt.Errorf("value for map field must be a map; instead was %v", val.Type())
			} else {
				return nil, fmt.Errorf("value for repeated field must be a slice; instead was %v", val.Type())
			}
		}

		if fd.IsMap() {
			// value should be a slice of entry messages that we need convert into a map[interface{}]interface{}
			m := map[interface{}]interface{}{}
			for i := 0; i < val.Len(); i++ {
				e, err := validElementFieldValue(fd, val.Index(i).Interface())
				if err != nil {
					return nil, err
				}
				msg := e.(proto.Message)
				dm, err := asDynamicMessage(msg, fd.GetMessageType(), nil)
				if err != nil {
					return nil, err
				}
				k, err := dm.TryGetFieldByNumber(1)
				if err != nil {
					return nil, err
				}
				v, err := dm.TryGetFieldByNumber(2)
				if err != nil {
					return nil, err
				}
				m[k] = v
			}
			return m, nil
		}

		// make a defensive copy while checking contents (also converts to []interface{})
		s := make([]interface{}, val.Len())
		for i := 0; i < val.Len(); i++ {
			ev := val.Index(i)
			if ev.Kind() == reflect.Interface {
				// unwrap it
				ev = reflect.ValueOf(ev.Interface())
			}
			e, err := validElementFieldValueForRv(fd, ev)
			if err != nil {
				return nil, err
			}
			s[i] = e
		}

		return s, nil
	}

	return validElementFieldValueForRv(fd, val)
}

func asDynamicMessage(m proto.Message, md *desc.MessageDescriptor, mf *MessageFactory) (*Message, error) {
	if dm, ok := m.(*Message); ok {
		return dm, nil
	}
	dm := NewMessageWithMessageFactory(md, mf)
	if err := dm.mergeFrom(m); err != nil {
		return nil, err
	}
	return dm, nil
}

func validElementFieldValue(fd *desc.FieldDescriptor, val interface{}) (interface{}, error) {
	return validElementFieldValueForRv(fd, reflect.ValueOf(val))
}

func validElementFieldValueForRv(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
	t := fd.GetType()
	if !val.IsValid() {
		return nil, typeError(fd, nil)
	}

	switch t {
	case descriptor.FieldDescriptorProto_TYPE_SFIXED32,
		descriptor.FieldDescriptorProto_TYPE_INT32,
		descriptor.FieldDescriptorProto_TYPE_SINT32,
		descriptor.FieldDescriptorProto_TYPE_ENUM:
		return toInt32(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_SFIXED64,
		descriptor.FieldDescriptorProto_TYPE_INT64,
		descriptor.FieldDescriptorProto_TYPE_SINT64:
		return toInt64(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
		descriptor.FieldDescriptorProto_TYPE_UINT32:
		return toUint32(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
		descriptor.FieldDescriptorProto_TYPE_UINT64:
		return toUint64(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
		return toFloat32(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
		return toFloat64(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_BOOL:
		return toBool(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_BYTES:
		return toBytes(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_STRING:
		return toString(reflect.Indirect(val), fd)

	case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
		descriptor.FieldDescriptorProto_TYPE_GROUP:
		m, err := asMessage(val, fd.GetFullyQualifiedName())
		// check that message is correct type
		if err != nil {
			return nil, err
		}
		var msgType string
		if dm, ok := m.(*Message); ok {
			msgType = dm.GetMessageDescriptor().GetFullyQualifiedName()
		} else {
			msgType = proto.MessageName(m)
		}
		if msgType != fd.GetMessageType().GetFullyQualifiedName() {
			return nil, fmt.Errorf("message field %s requires value of type %s; received %s", fd.GetFullyQualifiedName(), fd.GetMessageType().GetFullyQualifiedName(), msgType)
		}
		return m, nil

	default:
		return nil, fmt.Errorf("unable to handle unrecognized field type: %v", fd.GetType())
	}
}

func toInt32(v reflect.Value, fd *desc.FieldDescriptor) (int32, error) {
	if v.Kind() == reflect.Int32 {
		return int32(v.Int()), nil
	}
	return 0, typeError(fd, v.Type())
}

func toUint32(v reflect.Value, fd *desc.FieldDescriptor) (uint32, error) {
	if v.Kind() == reflect.Uint32 {
		return uint32(v.Uint()), nil
	}
	return 0, typeError(fd, v.Type())
}

func toFloat32(v reflect.Value, fd *desc.FieldDescriptor) (float32, error) {
	if v.Kind() == reflect.Float32 {
		return float32(v.Float()), nil
	}
	return 0, typeError(fd, v.Type())
}

func toInt64(v reflect.Value, fd *desc.FieldDescriptor) (int64, error) {
	if v.Kind() == reflect.Int64 || v.Kind() == reflect.Int || v.Kind() == reflect.Int32 {
		return v.Int(), nil
	}
	return 0, typeError(fd, v.Type())
}

func toUint64(v reflect.Value, fd *desc.FieldDescriptor) (uint64, error) {
	if v.Kind() == reflect.Uint64 || v.Kind() == reflect.Uint || v.Kind() == reflect.Uint32 {
		return v.Uint(), nil
	}
	return 0, typeError(fd, v.Type())
}

func toFloat64(v reflect.Value, fd *desc.FieldDescriptor) (float64, error) {
	if v.Kind() == reflect.Float64 || v.Kind() == reflect.Float32 {
		return v.Float(), nil
	}
	return 0, typeError(fd, v.Type())
}

func toBool(v reflect.Value, fd *desc.FieldDescriptor) (bool, error) {
	if v.Kind() == reflect.Bool {
		return v.Bool(), nil
	}
	return false, typeError(fd, v.Type())
}

func toBytes(v reflect.Value, fd *desc.FieldDescriptor) ([]byte, error) {
	if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
		return v.Bytes(), nil
	}
	return nil, typeError(fd, v.Type())
}

func toString(v reflect.Value, fd *desc.FieldDescriptor) (string, error) {
	if v.Kind() == reflect.String {
		return v.String(), nil
	}
	return "", typeError(fd, v.Type())
}

func typeError(fd *desc.FieldDescriptor, t reflect.Type) error {
	return fmt.Errorf(
		"%s field %s is not compatible with value of type %v",
		getTypeString(fd), fd.GetFullyQualifiedName(), t)
}

func getTypeString(fd *desc.FieldDescriptor) string {
	return strings.ToLower(fd.GetType().String())
}

func asMessage(v reflect.Value, fieldName string) (proto.Message, error) {
	t := v.Type()
	// we need a pointer to a struct that implements proto.Message
	if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct || !t.Implements(typeOfProtoMessage) {
		return nil, fmt.Errorf("message field %s requires is not compatible with value of type %v", fieldName, v.Type())
	}
	return v.Interface().(proto.Message), nil
}

// Reset resets this message to an empty message. It removes all values set in
// the message.
func (m *Message) Reset() {
	for k := range m.values {
		delete(m.values, k)
	}
	for k := range m.unknownFields {
		delete(m.unknownFields, k)
	}
}

// String returns this message rendered in compact text format.
func (m *Message) String() string {
	b, err := m.MarshalText()
	if err != nil {
		panic(fmt.Sprintf("Failed to create string representation of message: %s", err.Error()))
	}
	return string(b)
}

// ProtoMessage is present to satisfy the proto.Message interface.
func (m *Message) ProtoMessage() {
}

// ConvertTo converts this dynamic message into the given message. This is
// shorthand for resetting then merging:
//   target.Reset()
//   m.MergeInto(target)
func (m *Message) ConvertTo(target proto.Message) error {
	if err := m.checkType(target); err != nil {
		return err
	}

	target.Reset()
	return m.mergeInto(target)
}

// ConvertFrom converts the given message into this dynamic message. This is
// shorthand for resetting then merging:
//   m.Reset()
//   m.MergeFrom(target)
func (m *Message) ConvertFrom(target proto.Message) error {
	if err := m.checkType(target); err != nil {
		return err
	}

	m.Reset()
	return m.mergeFrom(target)
}

// MergeInto merges this dynamic message into the given message. All field
// values in this message will be set on the given message. For map fields,
// entries are added to the given message (if the given message has existing
// values for like keys, they are overwritten). For slice fields, elements are
// added.
//
// If the given message has a different set of known fields, it is possible for
// some known fields in this message to be represented as unknown fields in the
// given message after merging, and vice versa.
func (m *Message) MergeInto(target proto.Message) error {
	if err := m.checkType(target); err != nil {
		return err
	}
	return m.mergeInto(target)
}

// MergeFrom merges the given message into this dynamic message. All field
// values in the given message will be set on this message. For map fields,
// entries are added to this message (if this message has existing values for
// like keys, they are overwritten). For slice fields, elements are added.
//
// If the given message has a different set of known fields, it is possible for
// some known fields in that message to be represented as unknown fields in this
// message after merging, and vice versa.
func (m *Message) MergeFrom(source proto.Message) error {
	if err := m.checkType(source); err != nil {
		return err
	}
	return m.mergeFrom(source)
}

// Merge implements the proto.Merger interface so that dynamic messages are
// compatible with the proto.Merge function. It delegates to MergeFrom but will
// panic on error as the proto.Merger interface doesn't allow for returning an
// error.
//
// Unlike nearly all other methods, this method can work if this message's type
// is not defined (such as instantiating the message without using NewMessage).
// This is strictly so that dynamic message's are compatible with the
// proto.Clone function, which instantiates a new message via reflection (thus
// its message descriptor will not be set) and than calls Merge.
func (m *Message) Merge(source proto.Message) {
	if m.md == nil {
		// To support proto.Clone, initialize the descriptor from the source.
		if dm, ok := source.(*Message); ok {
			m.md = dm.md
			// also make sure the clone uses the same message factory and
			// extensions and also knows about the same extra fields (if any)
			m.mf = dm.mf
			m.er = dm.er
			m.extraFields = dm.extraFields
		} else if md, err := desc.LoadMessageDescriptorForMessage(source); err != nil {
			panic(err.Error())
		} else {
			m.md = md
		}
	}

	if err := m.MergeFrom(source); err != nil {
		panic(err.Error())
	}
}

func (m *Message) checkType(target proto.Message) error {
	if dm, ok := target.(*Message); ok {
		if dm.md.GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
			return fmt.Errorf("given message has wrong type: %q; expecting %q", dm.md.GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
		}
		return nil
	}

	msgName := proto.MessageName(target)
	if msgName != m.md.GetFullyQualifiedName() {
		return fmt.Errorf("given message has wrong type: %q; expecting %q", msgName, m.md.GetFullyQualifiedName())
	}
	return nil
}

func (m *Message) mergeInto(pm proto.Message) error {
	if dm, ok := pm.(*Message); ok {
		return dm.mergeFrom(m)
	}

	target := reflect.ValueOf(pm)
	if target.Kind() == reflect.Ptr {
		target = target.Elem()
	}

	// track tags for which the dynamic message has data but the given
	// message doesn't know about it
	u := target.FieldByName("XXX_unrecognized")
	var unknownTags map[int32]struct{}
	if u.IsValid() && u.Type() == typeOfBytes {
		unknownTags = map[int32]struct{}{}
		for tag := range m.values {
			unknownTags[tag] = struct{}{}
		}
	}

	// check that we can successfully do the merge
	structProps := proto.GetProperties(reflect.TypeOf(pm).Elem())
	for _, prop := range structProps.Prop {
		if prop.Tag == 0 {
			continue // one-of or special field (such as XXX_unrecognized, etc.)
		}
		tag := int32(prop.Tag)
		v, ok := m.values[tag]
		if !ok {
			continue
		}
		if unknownTags != nil {
			delete(unknownTags, tag)
		}
		f := target.FieldByName(prop.Name)
		ft := f.Type()
		val := reflect.ValueOf(v)
		if !canConvert(val, ft) {
			return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
		}
	}
	// check one-of fields
	for _, oop := range structProps.OneofTypes {
		prop := oop.Prop
		tag := int32(prop.Tag)
		v, ok := m.values[tag]
		if !ok {
			continue
		}
		if unknownTags != nil {
			delete(unknownTags, tag)
		}
		stf, ok := oop.Type.Elem().FieldByName(prop.Name)
		if !ok {
			return fmt.Errorf("one-of field indicates struct field name %s, but type %v has no such field", prop.Name, oop.Type.Elem())
		}
		ft := stf.Type
		val := reflect.ValueOf(v)
		if !canConvert(val, ft) {
			return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
		}
	}
	// and check extensions, too
	for tag, ext := range proto.RegisteredExtensions(pm) {
		v, ok := m.values[tag]
		if !ok {
			continue
		}
		if unknownTags != nil {
			delete(unknownTags, tag)
		}
		ft := reflect.TypeOf(ext.ExtensionType)
		val := reflect.ValueOf(v)
		if !canConvert(val, ft) {
			return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
		}
	}

	// now actually perform the merge
	for _, prop := range structProps.Prop {
		v, ok := m.values[int32(prop.Tag)]
		if !ok {
			continue
		}
		f := target.FieldByName(prop.Name)
		if err := mergeVal(reflect.ValueOf(v), f); err != nil {
			return err
		}
	}
	// merge one-ofs
	for _, oop := range structProps.OneofTypes {
		prop := oop.Prop
		tag := int32(prop.Tag)
		v, ok := m.values[tag]
		if !ok {
			continue
		}
		oov := reflect.New(oop.Type.Elem())
		f := oov.Elem().FieldByName(prop.Name)
		if err := mergeVal(reflect.ValueOf(v), f); err != nil {
			return err
		}
		target.Field(oop.Field).Set(oov)
	}
	// merge extensions, too
	for tag, ext := range proto.RegisteredExtensions(pm) {
		v, ok := m.values[tag]
		if !ok {
			continue
		}
		e := reflect.New(reflect.TypeOf(ext.ExtensionType)).Elem()
		if err := mergeVal(reflect.ValueOf(v), e); err != nil {
			return err
		}
		if err := proto.SetExtension(pm, ext, e.Interface()); err != nil {
			// shouldn't happen since we already checked that the extension type was compatible above
			return err
		}
	}

	// if we have fields that the given message doesn't know about, add to its unknown fields
	if len(unknownTags) > 0 {
		ub := u.Interface().([]byte)
		var b codedBuffer
		for tag := range unknownTags {
			fd := m.FindFieldDescriptor(tag)
			if err := marshalField(tag, fd, m.values[tag], &b, false); err != nil {
				return err
			}
		}
		ub = append(ub, b.buf...)
		u.Set(reflect.ValueOf(ub))
	}

	// finally, convey unknown fields into the given message by letting it unmarshal them
	// (this will append to its unknown fields if not known; if somehow the given message recognizes
	// a field even though the dynamic message did not, it will get correctly unmarshalled)
	if unknownTags != nil && len(m.unknownFields) > 0 {
		var b codedBuffer
		m.marshalUnknownFields(&b)
		proto.UnmarshalMerge(b.buf, pm)
	}

	return nil
}

func canConvert(src reflect.Value, target reflect.Type) bool {
	if src.Kind() == reflect.Interface {
		src = reflect.ValueOf(src.Interface())
	}
	srcType := src.Type()
	// we allow convertible types instead of requiring exact types so that calling
	// code can, for example, assign an enum constant to an enum field. In that case,
	// one type is the enum type (a sub-type of int32) and the other may be the int32
	// type. So we automatically do the conversion in that case.
	if srcType.ConvertibleTo(target) {
		return true
	} else if target.Kind() == reflect.Ptr && srcType.ConvertibleTo(target.Elem()) {
		return true
	} else if target.Kind() == reflect.Slice {
		if srcType.Kind() != reflect.Slice {
			return false
		}
		et := target.Elem()
		for i := 0; i < src.Len(); i++ {
			if !canConvert(src.Index(i), et) {
				return false
			}
		}
		return true
	} else if target.Kind() == reflect.Map {
		if srcType.Kind() != reflect.Map {
			return false
		}
		return canConvertMap(src, target)
	} else if srcType == typeOfDynamicMessage && target.Implements(typeOfProtoMessage) {
		z := reflect.Zero(target).Interface()
		msgType := proto.MessageName(z.(proto.Message))
		return msgType == src.Interface().(*Message).GetMessageDescriptor().GetFullyQualifiedName()
	} else {
		return false
	}
}

func mergeVal(src, target reflect.Value) error {
	if src.Kind() == reflect.Interface && !src.IsNil() {
		src = src.Elem()
	}
	srcType := src.Type()
	targetType := target.Type()
	if srcType.ConvertibleTo(targetType) {
		if targetType.Implements(typeOfProtoMessage) && !target.IsNil() {
			Merge(target.Interface().(proto.Message), src.Convert(targetType).Interface().(proto.Message))
		} else {
			target.Set(src.Convert(targetType))
		}
	} else if targetType.Kind() == reflect.Ptr && srcType.ConvertibleTo(targetType.Elem()) {
		if !src.CanAddr() {
			target.Set(reflect.New(targetType.Elem()))
			target.Elem().Set(src.Convert(targetType.Elem()))
		} else {
			target.Set(src.Addr().Convert(targetType))
		}
	} else if targetType.Kind() == reflect.Slice {
		l := target.Len()
		newL := l + src.Len()
		if target.Cap() < newL {
			// expand capacity of the slice and copy
			newSl := reflect.MakeSlice(targetType, newL, newL)
			for i := 0; i < target.Len(); i++ {
				newSl.Index(i).Set(target.Index(i))
			}
			target.Set(newSl)
		} else {
			target.SetLen(newL)
		}
		for i := 0; i < src.Len(); i++ {
			dest := target.Index(l + i)
			if dest.Kind() == reflect.Ptr {
				dest.Set(reflect.New(dest.Type().Elem()))
			}
			if err := mergeVal(src.Index(i), dest); err != nil {
				return err
			}
		}
	} else if targetType.Kind() == reflect.Map {
		return mergeMapVal(src, target, targetType)
	} else if srcType == typeOfDynamicMessage && targetType.Implements(typeOfProtoMessage) {
		dm := src.Interface().(*Message)
		if target.IsNil() {
			target.Set(reflect.New(targetType.Elem()))
		}
		m := target.Interface().(proto.Message)
		if err := dm.mergeInto(m); err != nil {
			return err
		}
	} else {
		return fmt.Errorf("cannot convert %v to %v", srcType, targetType)
	}
	return nil
}

func (m *Message) mergeFrom(pm proto.Message) error {
	if dm, ok := pm.(*Message); ok {
		// if given message is also a dynamic message, we merge differently
		for tag, v := range dm.values {
			fd := m.FindFieldDescriptor(tag)
			if fd == nil {
				fd = dm.FindFieldDescriptor(tag)
			}
			if err := mergeField(m, fd, v); err != nil {
				return err
			}
		}
		return nil
	}

	pmrv := reflect.ValueOf(pm)
	if pmrv.IsNil() {
		// nil is an empty message, so nothing to do
		return nil
	}

	// check that we can successfully do the merge
	src := pmrv.Elem()
	values := map[*desc.FieldDescriptor]interface{}{}
	props := proto.GetProperties(reflect.TypeOf(pm).Elem())
	if props == nil {
		return fmt.Errorf("could not determine message properties to merge for %v", reflect.TypeOf(pm).Elem())
	}

	// regular fields
	for _, prop := range props.Prop {
		if prop.Tag == 0 {
			continue // one-of or special field (such as XXX_unrecognized, etc.)
		}
		fd := m.FindFieldDescriptor(int32(prop.Tag))
		if fd == nil {
			// Our descriptor has different fields than this message object. So
			// try to reflect on the message object's fields.
			md, err := desc.LoadMessageDescriptorForMessage(pm)
			if err != nil {
				return err
			}
			fd = md.FindFieldByNumber(int32(prop.Tag))
			if fd == nil {
				return fmt.Errorf("message descriptor %q did not contain field for tag %d (%q)", md.GetFullyQualifiedName(), prop.Tag, prop.Name)
			}
		}
		rv := src.FieldByName(prop.Name)
		if (rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Slice) && rv.IsNil() {
			continue
		}
		if v, err := validFieldValueForRv(fd, rv); err != nil {
			return err
		} else {
			values[fd] = v
		}
	}

	// one-of fields
	for _, oop := range props.OneofTypes {
		oov := src.Field(oop.Field).Elem()
		if !oov.IsValid() || oov.Type() != oop.Type {
			// this field is unset (in other words, one-of message field is not currently set to this option)
			continue
		}
		prop := oop.Prop
		rv := oov.Elem().FieldByName(prop.Name)
		fd := m.FindFieldDescriptor(int32(prop.Tag))
		if fd == nil {
			// Our descriptor has different fields than this message object. So
			// try to reflect on the message object's fields.
			md, err := desc.LoadMessageDescriptorForMessage(pm)
			if err != nil {
				return err
			}
			fd = md.FindFieldByNumber(int32(prop.Tag))
			if fd == nil {
				return fmt.Errorf("message descriptor %q did not contain field for tag %d (%q in one-of %q)", md.GetFullyQualifiedName(), prop.Tag, prop.Name, src.Type().Field(oop.Field).Name)
			}
		}
		if v, err := validFieldValueForRv(fd, rv); err != nil {
			return err
		} else {
			values[fd] = v
		}
	}

	// extension fields
	rexts, _ := proto.ExtensionDescs(pm)
	var unknownExtensions []byte
	for _, ed := range rexts {
		v, _ := proto.GetExtension(pm, ed)
		if v == nil {
			continue
		}
		if ed.ExtensionType == nil {
			extBytes, _ := v.([]byte)
			if len(extBytes) > 0 {
				unknownExtensions = append(unknownExtensions, extBytes...)
			}
			continue
		}
		fd := m.er.FindExtension(m.md.GetFullyQualifiedName(), ed.Field)
		if fd == nil {
			var err error
			if fd, err = desc.LoadFieldDescriptorForExtension(ed); err != nil {
				return err
			}
		}
		if v, err := validFieldValue(fd, v); err != nil {
			return err
		} else {
			values[fd] = v
		}
	}

	// now actually perform the merge
	for fd, v := range values {
		mergeField(m, fd, v)
	}

	u := src.FieldByName("XXX_unrecognized")
	if u.IsValid() && u.Type() == typeOfBytes {
		// ignore any error returned: pulling in unknown fields is best-effort
		m.UnmarshalMerge(u.Interface().([]byte))
	}

	// lastly, also extract any unknown extensions the message may have (unknown extensions
	// are stored with other extensions, not in the XXX_unrecognized field, so we have to do
	// more than just the step above...)
	if len(unknownExtensions) > 0 {
		// pulling in unknown fields is best-effort, so we just ignore errors
		m.UnmarshalMerge(unknownExtensions)
	}
	return nil
}

// Validate checks that all required fields are present. It returns an error if any are absent.
func (m *Message) Validate() error {
	missingFields := m.findMissingFields()
	if len(missingFields) == 0 {
		return nil
	}
	return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
}

func (m *Message) findMissingFields() []string {
	if m.md.IsProto3() {
		// proto3 does not allow required fields
		return nil
	}
	var missingFields []string
	for _, fd := range m.md.GetFields() {
		if fd.IsRequired() {
			if _, ok := m.values[fd.GetNumber()]; !ok {
				missingFields = append(missingFields, fd.GetName())
			}
		}
	}
	return missingFields
}

// ValidateRecursive checks that all required fields are present and also
// recursively validates all fields who are also messages. It returns an error
// if any required fields, in this message or nested within, are absent.
func (m *Message) ValidateRecursive() error {
	return m.validateRecursive("")
}

func (m *Message) validateRecursive(prefix string) error {
	if missingFields := m.findMissingFields(); len(missingFields) > 0 {
		for i := range missingFields {
			missingFields[i] = fmt.Sprintf("%s%s", prefix, missingFields[i])
		}
		return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
	}

	for tag, fld := range m.values {
		fd := m.FindFieldDescriptor(tag)
		var chprefix string
		var md *desc.MessageDescriptor
		checkMsg := func(pm proto.Message) error {
			var dm *Message
			if d, ok := pm.(*Message); ok {
				dm = d
			} else {
				dm = m.mf.NewDynamicMessage(md)
				if err := dm.ConvertFrom(pm); err != nil {
					return nil
				}
			}
			if err := dm.validateRecursive(chprefix); err != nil {
				return err
			}
			return nil
		}
		isMap := fd.IsMap()
		if isMap && fd.GetMapValueType().GetMessageType() != nil {
			md = fd.GetMapValueType().GetMessageType()
			mp := fld.(map[interface{}]interface{})
			for k, v := range mp {
				chprefix = fmt.Sprintf("%s%s[%v].", prefix, getName(fd), k)
				if err := checkMsg(v.(proto.Message)); err != nil {
					return err
				}
			}
		} else if !isMap && fd.GetMessageType() != nil {
			md = fd.GetMessageType()
			if fd.IsRepeated() {
				sl := fld.([]interface{})
				for i, v := range sl {
					chprefix = fmt.Sprintf("%s%s[%d].", prefix, getName(fd), i)
					if err := checkMsg(v.(proto.Message)); err != nil {
						return err
					}
				}
			} else {
				chprefix = fmt.Sprintf("%s%s.", prefix, getName(fd))
				if err := checkMsg(fld.(proto.Message)); err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func getName(fd *desc.FieldDescriptor) string {
	if fd.IsExtension() {
		return fmt.Sprintf("(%s)", fd.GetFullyQualifiedName())
	} else {
		return fd.GetName()
	}
}

// knownFieldTags return tags of present and recognized fields, in sorted order.
func (m *Message) knownFieldTags() []int {
	if len(m.values) == 0 {
		return []int(nil)
	}

	keys := make([]int, len(m.values))
	i := 0
	for k := range m.values {
		keys[i] = int(k)
		i++
	}

	sort.Ints(keys)
	return keys
}

// allKnownFieldTags return tags of present and recognized fields, including
// those that are unset, in sorted order. This only includes extensions that are
// present. Known but not-present extensions are not included in the returned
// set of tags.
func (m *Message) allKnownFieldTags() []int {
	fds := m.md.GetFields()
	keys := make([]int, 0, len(fds)+len(m.extraFields))

	for k := range m.values {
		keys = append(keys, int(k))
	}

	// also include known fields that are not present
	for _, fd := range fds {
		if _, ok := m.values[fd.GetNumber()]; !ok {
			keys = append(keys, int(fd.GetNumber()))
		}
	}
	for _, fd := range m.extraFields {
		if !fd.IsExtension() { // skip extensions that are not present
			if _, ok := m.values[fd.GetNumber()]; !ok {
				keys = append(keys, int(fd.GetNumber()))
			}
		}
	}

	sort.Ints(keys)
	return keys
}

// unknownFieldTags return tags of present but unrecognized fields, in sorted order.
func (m *Message) unknownFieldTags() []int {
	if len(m.unknownFields) == 0 {
		return []int(nil)
	}
	keys := make([]int, len(m.unknownFields))
	i := 0
	for k := range m.unknownFields {
		keys[i] = int(k)
		i++
	}
	sort.Ints(keys)
	return keys
}
