func (enc *Encoder) encodeInterface(v reflect.Value) (int, error) {
	if v.IsNil() || !v.CanInterface() {
		msg := fmt.Sprintf("can't encode nil interface")
		err := marshalError("encodeInterface", ErrNilInterface, msg,
			nil, nil)
		return 0, err
	}
	ve := reflect.ValueOf(v.Interface())
	ve = enc.indirect(ve)
	return enc.encode(ve)
}
encodeInterface examines the interface represented by the passed reflection
value to detect whether it is an interface that can be encoded if it is,
extracts the underlying value to pass back into the encode function for
encoding according to its type.

A MarshalError is returned if any issues are encountered while encoding
the interface.
package xdr
import (
	"fmt"
	"io"
	"math"
	"reflect"
	"time"
)
var errIOEncode = "%s while encoding %d bytes"
func Marshal(w io.Writer, v interface{}) (int, error) {
	enc := Encoder{w: w}
	return enc.Encode(v)
}
type Encoder struct {
	w io.Writer
}
func (enc *Encoder) EncodeInt(v int32) (int, error) {
	var b [4]byte
	b[0] = byte(v >> 24)
	b[1] = byte(v >> 16)
	b[2] = byte(v >> 8)
	b[3] = byte(v)
	n, err := enc.w.Write(b[:])
	if err != nil {
		msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
		err := marshalError("EncodeInt", ErrIO, msg, b[:n], err)
		return n, err
	}
	return n, nil
}
func (enc *Encoder) EncodeUint(v uint32) (int, error) {
	var b [4]byte
	b[0] = byte(v >> 24)
	b[1] = byte(v >> 16)
	b[2] = byte(v >> 8)
	b[3] = byte(v)
	n, err := enc.w.Write(b[:])
	if err != nil {
		msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
		err := marshalError("EncodeUint", ErrIO, msg, b[:n], err)
		return n, err
	}
	return n, nil
}
func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (int, error) {
	if !validEnums[v] {
		err := marshalError("EncodeEnum", ErrBadEnumValue,
			"invalid enum", v, nil)
		return 0, err
	}
	return enc.EncodeInt(v)
}
func (enc *Encoder) EncodeBool(v bool) (int, error) {
	i := int32(0)
	if v == true {
		i = 1
	}
	return enc.EncodeInt(i)
}
func (enc *Encoder) EncodeHyper(v int64) (int, error) {
	var b [8]byte
	b[0] = byte(v >> 56)
	b[1] = byte(v >> 48)
	b[2] = byte(v >> 40)
	b[3] = byte(v >> 32)
	b[4] = byte(v >> 24)
	b[5] = byte(v >> 16)
	b[6] = byte(v >> 8)
	b[7] = byte(v)
	n, err := enc.w.Write(b[:])
	if err != nil {
		msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
		err := marshalError("EncodeHyper", ErrIO, msg, b[:n], err)
		return n, err
	}
	return n, nil
}
func (enc *Encoder) EncodeUhyper(v uint64) (int, error) {
	var b [8]byte
	b[0] = byte(v >> 56)
	b[1] = byte(v >> 48)
	b[2] = byte(v >> 40)
	b[3] = byte(v >> 32)
	b[4] = byte(v >> 24)
	b[5] = byte(v >> 16)
	b[6] = byte(v >> 8)
	b[7] = byte(v)
	n, err := enc.w.Write(b[:])
	if err != nil {
		msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
		err := marshalError("EncodeUhyper", ErrIO, msg, b[:n], err)
		return n, err
	}
	return n, nil
}
func (enc *Encoder) EncodeFloat(v float32) (int, error) {
	ui := math.Float32bits(v)
	return enc.EncodeUint(ui)
}
func (enc *Encoder) EncodeDouble(v float64) (int, error) {
	ui := math.Float64bits(v)
	return enc.EncodeUhyper(ui)
}
func (enc *Encoder) EncodeFixedOpaque(v []byte) (int, error) {
	l := len(v)
	pad := (4 - (l % 4)) % 4
	n, err := enc.w.Write(v)
	if err != nil {
		msg := fmt.Sprintf(errIOEncode, err.Error(), len(v))
		err := marshalError("EncodeFixedOpaque", ErrIO, msg, v[:n], err)
		return n, err
	}
	if pad > 0 {
		b := make([]byte, pad)
		n2, err := enc.w.Write(b)
		n += n2
		if err != nil {
			written := make([]byte, l+n2)
			copy(written, v)
			copy(written[l:], b[:n2])
			msg := fmt.Sprintf(errIOEncode, err.Error(), l+pad)
			err := marshalError("EncodeFixedOpaque", ErrIO, msg,
				written, err)
			return n, err
		}
	}
	return n, nil
}
func (enc *Encoder) EncodeOpaque(v []byte) (int, error) {
	n, err := enc.EncodeUint(uint32(len(v)))
	if err != nil {
		return n, err
	}
	n2, err := enc.EncodeFixedOpaque(v)
	n += n2
	return n, err
}
func (enc *Encoder) EncodeString(v string) (int, error) {
	n, err := enc.EncodeUint(uint32(len(v)))
	if err != nil {
		return n, err
	}
	n2, err := enc.EncodeFixedOpaque([]byte(v))
	n += n2
	return n, err
}
func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
	if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
		if v.CanAddr() {
			return enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
		}
		slice := make([]byte, v.Len(), v.Len())
		reflect.Copy(reflect.ValueOf(slice), v)
		return enc.EncodeFixedOpaque(slice)
	}
	var n int
	for i := 0; i < v.Len(); i++ {
		n2, err := enc.encode(v.Index(i))
		n += n2
		if err != nil {
			return n, err
		}
	}
	return n, nil
}
func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
	numItems := uint32(v.Len())
	n, err := enc.EncodeUint(numItems)
	if err != nil {
		return n, err
	}
	n2, err := enc.encodeFixedArray(v, ignoreOpaque)
	n += n2
	return n, err
}
func (enc *Encoder) encodeUnion(v reflect.Value) (int, error) {
	u := v.Interface().(Union)
	vs := v.FieldByName(u.SwitchFieldName())
	n, err := enc.encode(vs)
	if err != nil {
		return n, err
	}
	sw := int32(vs.Int())
	arm, ok := u.ArmForSwitch(sw)
	if arm == "" {
		return n, nil
	}
	vv := v.FieldByName(arm)
	if !vv.IsValid() || !ok {
		msg := fmt.Sprintf("invalid union switch: %d", sw)
		err := marshalError("encodeUnion", ErrBadUnionSwitch, msg, nil, nil)
		return n, err
	}
	if vv.Kind() != reflect.Ptr {
		msg := fmt.Sprintf("invalid union value field: %v", vv.Kind())
		err := marshalError("encodeUnion", ErrBadUnionValue, msg, nil, nil)
		return n, err
	}
	if vv.IsNil() {
		msg := fmt.Sprintf("can't encode nil union value")
		err := marshalError("encodeUnion", ErrBadUnionValue, msg, nil, nil)
		return n, err
	}
	n2, err := enc.encode(vv.Elem())
	n += n2
	return n, err
}
func (enc *Encoder) encodeStruct(v reflect.Value) (int, error) {
	var n int
	vt := v.Type()
	for i := 0; i < v.NumField(); i++ {
		vtf := vt.Field(i)
		if vtf.PkgPath != "" {
			continue
		}
		vf := v.Field(i)
		tag := vtf.Tag.Get("xdropaque")
		if tag == "false" {
			switch vf.Kind() {
			case reflect.Slice:
				n2, err := enc.encodeArray(vf, true)
				n += n2
				if err != nil {
					return n, err
				}
				continue
			case reflect.Array:
				n2, err := enc.encodeFixedArray(vf, true)
				n += n2
				if err != nil {
					return n, err
				}
				continue
			}
		}
		n2, err := enc.encode(vf)
		n += n2
		if err != nil {
			return n, err
		}
	}
	return n, nil
}
func (enc *Encoder) encodeMap(v reflect.Value) (int, error) {
	n, err := enc.EncodeUint(uint32(v.Len()))
	if err != nil {
		return n, err
	}
	for _, key := range v.MapKeys() {
		n2, err := enc.encode(key)
		n += n2
		if err != nil {
			return n, err
		}
		n2, err = enc.encode(v.MapIndex(key))
		n += n2
		if err != nil {
			return n, err
		}
	}
	return n, nil
}