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/codec"
	"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))

// 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 {
			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 = codec.DecodeLengthDelimitedField(fd, unk.Contents, m.mf)
		} else {
			val, err = codec.DecodeScalarField(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 codec.Buffer
		b.SetDeterministic(defaultDeterminism)
		for tag := range unknownTags {
			fd := m.FindFieldDescriptor(tag)
			if err := b.EncodeFieldValue(fd, m.values[tag]); err != nil {
				return err
			}
		}
		ub = append(ub, b.Bytes()...)
		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 codec.Buffer
		_ = m.marshalUnknownFields(&b)
		_ = proto.UnmarshalMerge(b.Bytes(), 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
}
