func (cdc *Codec) encodeReflectBinary(w io.Writer, info *TypeInfo, rv reflect.Value, fopts FieldOptions, bare bool) (err error) {
	if rv.Kind() == reflect.Ptr {
		panic("not allowed to be called with a reflect.Ptr")
	}
	if !rv.IsValid() {
		panic("not allowed to be called with invalid / zero Value")
	}
	if printLog {
		spew.Printf("(E) encodeReflectBinary(info: %v, rv: %#v (%v), fopts: %v)\n",
			info, rv.Interface(), rv.Type(), fopts)
		defer func() {
			fmt.Printf("(E) -> err: %v\n", err)
		}()
	}

	// Handle override if rv implements json.Marshaler.
	if info.IsAminoMarshaler {
		// First, encode rv into repr instance.
		var rrv, rinfo = reflect.Value{}, (*TypeInfo)(nil)
		rrv, err = toReprObject(rv)
		if err != nil {
			return
		}
		rinfo, err = cdc.getTypeInfo_wlock(info.AminoMarshalReprType)
		if err != nil {
			return
		}
		// Then, encode the repr instance.
		err = cdc.encodeReflectBinary(w, rinfo, rrv, fopts, bare)
		return
	}

	switch info.Type.Kind() {

	//----------------------------------------
	// Complex

	case reflect.Interface:
		err = cdc.encodeReflectBinaryInterface(w, info, rv, fopts, bare)

	case reflect.Array:
		if info.Type.Elem().Kind() == reflect.Uint8 {
			err = cdc.encodeReflectBinaryByteArray(w, info, rv, fopts)
		} else {
			err = cdc.encodeReflectBinaryList(w, info, rv, fopts, bare)
		}

	case reflect.Slice:
		if info.Type.Elem().Kind() == reflect.Uint8 {
			err = cdc.encodeReflectBinaryByteSlice(w, info, rv, fopts)
		} else {
			err = cdc.encodeReflectBinaryList(w, info, rv, fopts, bare)
		}

	case reflect.Struct:
		err = cdc.encodeReflectBinaryStruct(w, info, rv, fopts, bare)

	//----------------------------------------
	// Signed

	case reflect.Int64:
		if fopts.BinFixed64 {
			err = EncodeInt64(w, rv.Int())
		} else {
			err = EncodeUvarint(w, uint64(rv.Int()))
		}

	case reflect.Int32:
		if fopts.BinFixed32 {
			err = EncodeInt32(w, int32(rv.Int()))
		} else {
			err = EncodeUvarint(w, uint64(rv.Int()))
		}

	case reflect.Int16:
		err = EncodeInt16(w, int16(rv.Int()))

	case reflect.Int8:
		err = EncodeInt8(w, int8(rv.Int()))

	case reflect.Int:
		err = EncodeUvarint(w, uint64(rv.Int()))

	//----------------------------------------
	// Unsigned

	case reflect.Uint64:
		if fopts.BinFixed64 {
			err = EncodeUint64(w, rv.Uint())
		} else {
			err = EncodeUvarint(w, rv.Uint())
		}

	case reflect.Uint32:
		if fopts.BinFixed32 {
			err = EncodeUint32(w, uint32(rv.Uint()))
		} else {
			err = EncodeUvarint(w, rv.Uint())
		}

	case reflect.Uint16:
		err = EncodeUint16(w, uint16(rv.Uint()))

	case reflect.Uint8:
		err = EncodeUint8(w, uint8(rv.Uint()))

	case reflect.Uint:
		err = EncodeUvarint(w, rv.Uint())

	//----------------------------------------
	// Misc

	case reflect.Bool:
		err = EncodeBool(w, rv.Bool())

	case reflect.Float64:
		if !fopts.Unsafe {
			err = errors.New("Amino float* support requires `amino:\"unsafe\"`.")
			return
		}
		err = EncodeFloat64(w, rv.Float())

	case reflect.Float32:
		if !fopts.Unsafe {
			err = errors.New("Amino float* support requires `amino:\"unsafe\"`.")
			return
		}
		err = EncodeFloat32(w, float32(rv.Float()))

	case reflect.String:
		err = EncodeString(w, rv.String())

	//----------------------------------------
	// Default

	default:
		panic(fmt.Sprintf("unsupported type %v", info.Type.Kind()))
	}

	return
}
func (cdc *Codec) encodeReflectBinary(w io.Writer, info *TypeInfo, rv reflect.Value, fopts FieldOptions, bare bool) (err error) {
	if rv.Kind() == reflect.Ptr {
		panic("not allowed to be called with a reflect.Ptr")
	}
	if !rv.IsValid() {
		panic("not allowed to be called with invalid / zero Value")
	}
	if printLog {
		spew.Printf("(E) encodeReflectBinary(info: %v, rv: %#v (%v), fopts: %v)\n",
			info, rv.Interface(), rv.Type(), fopts)
		defer func() {
			fmt.Printf("(E) -> err: %v\n", err)
		}()
	}

	// Handle override if rv implements json.Marshaler.
	if info.IsAminoMarshaler {
		// First, encode rv into repr instance.
		var rrv, rinfo = reflect.Value{}, (*TypeInfo)(nil)
		rrv, err = toReprObject(rv)
		if err != nil {
			return
		}
		rinfo, err = cdc.getTypeInfo_wlock(info.AminoMarshalReprType)
		if err != nil {
			return
		}
		// Then, encode the repr instance.
		err = cdc.encodeReflectBinary(w, rinfo, rrv, fopts, bare)
		return
	}

	switch info.Type.Kind() {

	//----------------------------------------
	// Complex

	case reflect.Interface:
		err = cdc.encodeReflectBinaryInterface(w, info, rv, fopts, bare)

	case reflect.Array:
		if info.Type.Elem().Kind() == reflect.Uint8 {
			err = cdc.encodeReflectBinaryByteArray(w, info, rv, fopts)
		} else {
			err = cdc.encodeReflectBinaryList(w, info, rv, fopts, bare)
		}

	case reflect.Slice:
		if info.Type.Elem().Kind() == reflect.Uint8 {
			err = cdc.encodeReflectBinaryByteSlice(w, info, rv, fopts)
		} else {
			err = cdc.encodeReflectBinaryList(w, info, rv, fopts, bare)
		}

	case reflect.Struct:
		err = cdc.encodeReflectBinaryStruct(w, info, rv, fopts, bare)

	//----------------------------------------
	// Signed

	case reflect.Int64:
		if fopts.BinFixed64 {
			err = EncodeInt64(w, rv.Int())
		} else {
			err = EncodeUvarint(w, uint64(rv.Int()))
		}

	case reflect.Int32:
		if fopts.BinFixed32 {
			err = EncodeInt32(w, int32(rv.Int()))
		} else {
			err = EncodeUvarint(w, uint64(rv.Int()))
		}

	case reflect.Int16:
		err = EncodeInt16(w, int16(rv.Int()))

	case reflect.Int8:
		err = EncodeInt8(w, int8(rv.Int()))

	case reflect.Int:
		err = EncodeUvarint(w, uint64(rv.Int()))

	//----------------------------------------
	// Unsigned

	case reflect.Uint64:
		if fopts.BinFixed64 {
			err = EncodeUint64(w, rv.Uint())
		} else {
			err = EncodeUvarint(w, rv.Uint())
		}

	case reflect.Uint32:
		if fopts.BinFixed32 {
			err = EncodeUint32(w, uint32(rv.Uint()))
		} else {
			err = EncodeUvarint(w, rv.Uint())
		}

	case reflect.Uint16:
		err = EncodeUint16(w, uint16(rv.Uint()))

	case reflect.Uint8:
		err = EncodeUint8(w, uint8(rv.Uint()))

	case reflect.Uint:
		err = EncodeUvarint(w, rv.Uint())

	//----------------------------------------
	// Misc

	case reflect.Bool:
		err = EncodeBool(w, rv.Bool())

	case reflect.Float64:
		if !fopts.Unsafe {
			err = errors.New("Amino float* support requires `amino:\"unsafe\"`.")
			return
		}
		err = EncodeFloat64(w, rv.Float())

	case reflect.Float32:
		if !fopts.Unsafe {
			err = errors.New("Amino float* support requires `amino:\"unsafe\"`.")
			return
		}
		err = EncodeFloat32(w, float32(rv.Float()))

	case reflect.String:
		err = EncodeString(w, rv.String())

	//----------------------------------------
	// Default

	default:
		panic(fmt.Sprintf("unsupported type %v", info.Type.Kind()))
	}

	return
}
//----------------------------------------
// cdc.encodeReflectBinary
// This is the main entrypoint for encoding all types in binary form.  This
// function calls encodeReflectBinary*, and generally those functions should
// only call this one, for the prefix bytes are only written here.
// The value may be a nil interface, but not a nil pointer.
// The following contracts apply to all similar encode methods.
// CONTRACT: rv is not a pointer
// CONTRACT: rv is valid.