func canIndexOrdinally(v reflect.Value) bool {
	if !v.IsValid() {
		return false
	}
	switch t := v.Type(); t.Kind() {
	case reflect.Ptr, reflect.Interface:
		return canIndexOrdinally(v.Elem())
	case reflect.Slice, reflect.Array:
		return true
	}
	return false
}
canIndexOrdinally returns whether a value contains an ordered sequence of elements.
package form
import (
	"encoding"
	"errors"
	"fmt"
	"io"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"
)
func NewEncoder(w io.Writer) *Encoder {
	return &Encoder{w, defaultDelimiter, defaultEscape, false}
}
type Encoder struct {
	w io.Writer
	d rune
	e rune
	z bool
}
func (e *Encoder) DelimitWith(r rune) *Encoder {
	e.d = r
	return e
}
func (e *Encoder) EscapeWith(r rune) *Encoder {
	e.e = r
	return e
}
func (e *Encoder) KeepZeros(z bool) *Encoder {
	e.z = z
	return e
}
func (e Encoder) Encode(dst interface{}) error {
	v := reflect.ValueOf(dst)
	n, err := encodeToNode(v, e.z)
	if err != nil {
		return err
	}
	s := n.values(e.d, e.e).Encode()
	l, err := io.WriteString(e.w, s)
	switch {
	case err != nil:
		return err
	case l != len(s):
		return errors.New("could not write data completely")
	}
	return nil
}
func EncodeToString(dst interface{}) (string, error) {
	return EncodeToStringWith(dst, defaultDelimiter, defaultEscape, defaultKeepZeros)
}
func EncodeToStringWith(dst interface{}, d rune, e rune, z bool) (string, error) {
	v := reflect.ValueOf(dst)
	n, err := encodeToNode(v, z)
	if err != nil {
		return "", err
	}
	vs := n.values(d, e)
	return vs.Encode(), nil
}
func EncodeToValues(dst interface{}) (url.Values, error) {
	return EncodeToValuesWith(dst, defaultDelimiter, defaultEscape, defaultKeepZeros)
}
func EncodeToValuesWith(dst interface{}, d rune, e rune, z bool) (url.Values, error) {
	v := reflect.ValueOf(dst)
	n, err := encodeToNode(v, z)
	if err != nil {
		return nil, err
	}
	vs := n.values(d, e)
	return vs, nil
}
func encodeToNode(v reflect.Value, z bool) (n node, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("%v", e)
		}
	}()
	return getNode(encodeValue(v, z)), nil
}
func encodeValue(v reflect.Value, z bool) interface{} {
	t := v.Type()
	k := v.Kind()
	if s, ok := marshalValue(v); ok {
		return s
	} else if !z && isEmptyValue(v) {
		return ""  
	}
	switch k {
	case reflect.Ptr, reflect.Interface:
		return encodeValue(v.Elem(), z)
	case reflect.Struct:
		if t.ConvertibleTo(timeType) {
			return encodeTime(v)
		} else if t.ConvertibleTo(urlType) {
			return encodeURL(v)
		}
		return encodeStruct(v, z)
	case reflect.Slice:
		return encodeSlice(v, z)
	case reflect.Array:
		return encodeArray(v, z)
	case reflect.Map:
		return encodeMap(v, z)
	case reflect.Invalid, reflect.Uintptr, reflect.UnsafePointer, reflect.Chan, reflect.Func:
		panic(t.String() + " has unsupported kind " + t.Kind().String())
	default:
		return encodeBasic(v)
	}
}
func encodeStruct(v reflect.Value, z bool) interface{} {
	t := v.Type()
	n := node{}
	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		k, oe := fieldInfo(f)
		if k == "-" {
			continue
		} else if fv := v.Field(i); oe && isEmptyValue(fv) {
			delete(n, k)
		} else {
			n[k] = encodeValue(fv, z)
		}
	}
	return n
}
func encodeMap(v reflect.Value, z bool) interface{} {
	n := node{}
	for _, i := range v.MapKeys() {
		k := getString(encodeValue(i, z))
		n[k] = encodeValue(v.MapIndex(i), z)
	}
	return n
}
func encodeArray(v reflect.Value, z bool) interface{} {
	n := node{}
	for i := 0; i < v.Len(); i++ {
		n[strconv.Itoa(i)] = encodeValue(v.Index(i), z)
	}
	return n
}
func encodeSlice(v reflect.Value, z bool) interface{} {
	t := v.Type()
	if t.Elem().Kind() == reflect.Uint8 {
		return string(v.Bytes())  
	}
	n := node{}
	for i := 0; i < v.Len(); i++ {
		n[strconv.Itoa(i)] = encodeValue(v.Index(i), z)
	}
	return n
}
func encodeTime(v reflect.Value) string {
	t := v.Convert(timeType).Interface().(time.Time)
	if t.Year() == 0 && (t.Month() == 0 || t.Month() == 1) && (t.Day() == 0 || t.Day() == 1) {
		return t.Format("15:04:05.999999999Z07:00")
	} else if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 && t.Nanosecond() == 0 {
		return t.Format("2006-01-02")
	}
	return t.Format("2006-01-02T15:04:05.999999999Z07:00")
}
func encodeURL(v reflect.Value) string {
	u := v.Convert(urlType).Interface().(url.URL)
	return u.String()
}
func encodeBasic(v reflect.Value) string {
	t := v.Type()
	switch k := t.Kind(); k {
	case reflect.Bool:
		return strconv.FormatBool(v.Bool())
	case reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64:
		return strconv.FormatInt(v.Int(), 10)
	case reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64:
		return strconv.FormatUint(v.Uint(), 10)
	case reflect.Float32:
		return strconv.FormatFloat(v.Float(), 'g', -1, 32)
	case reflect.Float64:
		return strconv.FormatFloat(v.Float(), 'g', -1, 64)
	case reflect.Complex64, reflect.Complex128:
		s := fmt.Sprintf("%g", v.Complex())
		return strings.TrimSuffix(strings.TrimPrefix(s, "("), ")")
	case reflect.String:
		return v.String()
	}
	panic(t.String() + " has unsupported kind " + t.Kind().String())
}
func isEmptyValue(v reflect.Value) bool {
	switch t := v.Type(); v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Complex64, reflect.Complex128:
		return v.Complex() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	case reflect.Struct:
		if t.ConvertibleTo(timeType) {
			return v.Convert(timeType).Interface().(time.Time).IsZero()
		}
		return reflect.DeepEqual(v, reflect.Zero(t))
	}
	return false
}