func (f *encFnInfo) kInterface(rv reflect.Value) {
	if rv.IsNil() {
		f.ee.encodeNil()
		return
	}
	f.e.encodeValue(rv.Elem())
}
func (f *encFnInfo) kPtr(rv reflect.Value) {
debugf(">>>>>>> ??? encode kPtr called - shouldn't get called")
if rv.IsNil() {
f.ee.encodeNil()
return
}
f.e.encodeValue(rv.Elem())
}
package codec
import (
	"io"
	"reflect"
)
const (
	msgTagEnc         = "codec.encoder"
	defEncByteBufSize = 1 << 6  
)
type AsSymbolFlag uint8
const (
	AsSymbolDefault AsSymbolFlag = iota
	AsSymbolAll = 0xfe
	AsSymbolNone = 1 << iota
	AsSymbolMapStringKeysFlag
	AsSymbolStructFieldNameFlag
)
type encWriter interface {
	writeUint16(uint16)
	writeUint32(uint32)
	writeUint64(uint64)
	writeb([]byte)
	writestr(string)
	writen1(byte)
	writen2(byte, byte)
	atEndOfEncode()
}
type encDriver interface {
	isBuiltinType(rt uintptr) bool
	encodeBuiltin(rt uintptr, v interface{})
	encodeNil()
	encodeInt(i int64)
	encodeUint(i uint64)
	encodeBool(b bool)
	encodeFloat32(f float32)
	encodeFloat64(f float64)
	encodeExtPreamble(xtag byte, length int)
	encodeArrayPreamble(length int)
	encodeMapPreamble(length int)
	encodeString(c charEncoding, v string)
	encodeSymbol(v string)
	encodeStringBytes(c charEncoding, v []byte)
}
type ioEncWriterWriter interface {
	WriteByte(c byte) error
	WriteString(s string) (n int, err error)
	Write(p []byte) (n int, err error)
}
type ioEncStringWriter interface {
	WriteString(s string) (n int, err error)
}
type EncodeOptions struct {
	StructToArray bool
	AsSymbols AsSymbolFlag
}
type simpleIoEncWriterWriter struct {
	w  io.Writer
	bw io.ByteWriter
	sw ioEncStringWriter
}
func (o *simpleIoEncWriterWriter) WriteByte(c byte) (err error) {
	if o.bw != nil {
		return o.bw.WriteByte(c)
	}
	_, err = o.w.Write([]byte{c})
	return
}
func (o *simpleIoEncWriterWriter) WriteString(s string) (n int, err error) {
	if o.sw != nil {
		return o.sw.WriteString(s)
	}
	return o.w.Write([]byte(s))
}
func (o *simpleIoEncWriterWriter) Write(p []byte) (n int, err error) {
	return o.w.Write(p)
}
type ioEncWriter struct {
	w ioEncWriterWriter
	x [8]byte  
}
func (z *ioEncWriter) writeUint16(v uint16) {
	bigen.PutUint16(z.x[:2], v)
	z.writeb(z.x[:2])
}
func (z *ioEncWriter) writeUint32(v uint32) {
	bigen.PutUint32(z.x[:4], v)
	z.writeb(z.x[:4])
}
func (z *ioEncWriter) writeUint64(v uint64) {
	bigen.PutUint64(z.x[:8], v)
	z.writeb(z.x[:8])
}
func (z *ioEncWriter) writeb(bs []byte) {
	if len(bs) == 0 {
		return
	}
	n, err := z.w.Write(bs)
	if err != nil {
		panic(err)
	}
	if n != len(bs) {
		encErr("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", len(bs), n)
	}
}
func (z *ioEncWriter) writestr(s string) {
	n, err := z.w.WriteString(s)
	if err != nil {
		panic(err)
	}
	if n != len(s) {
		encErr("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", len(s), n)
	}
}
func (z *ioEncWriter) writen1(b byte) {
	if err := z.w.WriteByte(b); err != nil {
		panic(err)
	}
}
func (z *ioEncWriter) writen2(b1 byte, b2 byte) {
	z.writen1(b1)
	z.writen1(b2)
}
func (z *ioEncWriter) atEndOfEncode() {}
type bytesEncWriter struct {
	b   []byte
	c   int      
	out *[]byte  
}
func (z *bytesEncWriter) writeUint16(v uint16) {
	c := z.grow(2)
	z.b[c] = byte(v >> 8)
	z.b[c+1] = byte(v)
}
func (z *bytesEncWriter) writeUint32(v uint32) {
	c := z.grow(4)
	z.b[c] = byte(v >> 24)
	z.b[c+1] = byte(v >> 16)
	z.b[c+2] = byte(v >> 8)
	z.b[c+3] = byte(v)
}
func (z *bytesEncWriter) writeUint64(v uint64) {
	c := z.grow(8)
	z.b[c] = byte(v >> 56)
	z.b[c+1] = byte(v >> 48)
	z.b[c+2] = byte(v >> 40)
	z.b[c+3] = byte(v >> 32)
	z.b[c+4] = byte(v >> 24)
	z.b[c+5] = byte(v >> 16)
	z.b[c+6] = byte(v >> 8)
	z.b[c+7] = byte(v)
}
func (z *bytesEncWriter) writeb(s []byte) {
	if len(s) == 0 {
		return
	}
	c := z.grow(len(s))
	copy(z.b[c:], s)
}
func (z *bytesEncWriter) writestr(s string) {
	c := z.grow(len(s))
	copy(z.b[c:], s)
}
func (z *bytesEncWriter) writen1(b1 byte) {
	c := z.grow(1)
	z.b[c] = b1
}
func (z *bytesEncWriter) writen2(b1 byte, b2 byte) {
	c := z.grow(2)
	z.b[c] = b1
	z.b[c+1] = b2
}
func (z *bytesEncWriter) atEndOfEncode() {
	*(z.out) = z.b[:z.c]
}
func (z *bytesEncWriter) grow(n int) (oldcursor int) {
	oldcursor = z.c
	z.c = oldcursor + n
	if z.c > cap(z.b) {
		bs := make([]byte, 2*cap(z.b)+n)
		copy(bs, z.b[:oldcursor])
		z.b = bs
	} else if z.c > len(z.b) {
		z.b = z.b[:cap(z.b)]
	}
	return
}
type encFnInfo struct {
	ti    *typeInfo
	e     *Encoder
	ee    encDriver
	xfFn  func(reflect.Value) ([]byte, error)
	xfTag byte
}
func (f *encFnInfo) builtin(rv reflect.Value) {
	f.ee.encodeBuiltin(f.ti.rtid, rv.Interface())
}
func (f *encFnInfo) rawExt(rv reflect.Value) {
	f.e.encRawExt(rv.Interface().(RawExt))
}
func (f *encFnInfo) ext(rv reflect.Value) {
	bs, fnerr := f.xfFn(rv)
	if fnerr != nil {
		panic(fnerr)
	}
	if bs == nil {
		f.ee.encodeNil()
		return
	}
	if f.e.hh.writeExt() {
		f.ee.encodeExtPreamble(f.xfTag, len(bs))
		f.e.w.writeb(bs)
	} else {
		f.ee.encodeStringBytes(c_RAW, bs)
	}
}
func (f *encFnInfo) binaryMarshal(rv reflect.Value) {
	var bm binaryMarshaler
	if f.ti.mIndir == 0 {
		bm = rv.Interface().(binaryMarshaler)
	} else if f.ti.mIndir == -1 {
		bm = rv.Addr().Interface().(binaryMarshaler)
	} else {
		for j, k := int8(0), f.ti.mIndir; j < k; j++ {
			if rv.IsNil() {
				f.ee.encodeNil()
				return
			}
			rv = rv.Elem()
		}
		bm = rv.Interface().(binaryMarshaler)
	}
	bs, fnerr := bm.MarshalBinary()
	if fnerr != nil {
		panic(fnerr)
	}
	if bs == nil {
		f.ee.encodeNil()
	} else {
		f.ee.encodeStringBytes(c_RAW, bs)
	}
}
func (f *encFnInfo) kBool(rv reflect.Value) {
	f.ee.encodeBool(rv.Bool())
}
func (f *encFnInfo) kString(rv reflect.Value) {
	f.ee.encodeString(c_UTF8, rv.String())
}
func (f *encFnInfo) kFloat64(rv reflect.Value) {
	f.ee.encodeFloat64(rv.Float())
}
func (f *encFnInfo) kFloat32(rv reflect.Value) {
	f.ee.encodeFloat32(float32(rv.Float()))
}
func (f *encFnInfo) kInt(rv reflect.Value) {
	f.ee.encodeInt(rv.Int())
}
func (f *encFnInfo) kUint(rv reflect.Value) {
	f.ee.encodeUint(rv.Uint())
}
func (f *encFnInfo) kInvalid(rv reflect.Value) {
	f.ee.encodeNil()
}
func (f *encFnInfo) kErr(rv reflect.Value) {
	encErr("Unsupported kind: %s, for: %#v", rv.Kind(), rv)
}
func (f *encFnInfo) kSlice(rv reflect.Value) {
	if rv.IsNil() {
		f.ee.encodeNil()
		return
	}
	if shortCircuitReflectToFastPath {
		switch f.ti.rtid {
		case intfSliceTypId:
			f.e.encSliceIntf(rv.Interface().([]interface{}))
			return
		case strSliceTypId:
			f.e.encSliceStr(rv.Interface().([]string))
			return
		case uint64SliceTypId:
			f.e.encSliceUint64(rv.Interface().([]uint64))
			return
		case int64SliceTypId:
			f.e.encSliceInt64(rv.Interface().([]int64))
			return
		}
	}
	if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
		f.ee.encodeStringBytes(c_RAW, rv.Bytes())
		return
	}
	l := rv.Len()
	if f.ti.mbs {
		if l%2 == 1 {
			encErr("mapBySlice: invalid length (must be divisible by 2): %v", l)
		}
		f.ee.encodeMapPreamble(l / 2)
	} else {
		f.ee.encodeArrayPreamble(l)
	}
	if l == 0 {
		return
	}
	for j := 0; j < l; j++ {
		f.e.encodeValue(rv.Index(j))
	}
}
func (f *encFnInfo) kArray(rv reflect.Value) {
	l := rv.Len()
	if f.ti.rt.Elem().Kind() == reflect.Uint8 {
		if l == 0 {
			f.ee.encodeStringBytes(c_RAW, nil)
			return
		}
		var bs []byte
		if rv.CanAddr() {
			bs = rv.Slice(0, l).Bytes()
		} else {
			bs = make([]byte, l)
			for i := 0; i < l; i++ {
				bs[i] = byte(rv.Index(i).Uint())
			}
		}
		f.ee.encodeStringBytes(c_RAW, bs)
		return
	}
	if f.ti.mbs {
		if l%2 == 1 {
			encErr("mapBySlice: invalid length (must be divisible by 2): %v", l)
		}
		f.ee.encodeMapPreamble(l / 2)
	} else {
		f.ee.encodeArrayPreamble(l)
	}
	if l == 0 {
		return
	}
	for j := 0; j < l; j++ {
		f.e.encodeValue(rv.Index(j))
	}
}
func (f *encFnInfo) kStruct(rv reflect.Value) {
	fti := f.ti
	newlen := len(fti.sfi)
	rvals := make([]reflect.Value, newlen)
	var encnames []string
	e := f.e
	tisfi := fti.sfip
	toMap := !(fti.toArray || e.h.StructToArray)
	if toMap {
		tisfi = fti.sfi
		encnames = make([]string, newlen)
	}
	newlen = 0
	for _, si := range tisfi {
		if si.i != -1 {
			rvals[newlen] = rv.Field(int(si.i))
		} else {
			rvals[newlen] = rv.FieldByIndex(si.is)
		}
		if toMap {
			if si.omitEmpty && isEmptyValue(rvals[newlen]) {
				continue
			}
			encnames[newlen] = si.encName
		} else {
			if si.omitEmpty && isEmptyValue(rvals[newlen]) {
				rvals[newlen] = reflect.Value{}  
			}
		}
		newlen++
	}
	if toMap {
		ee := f.ee  
		ee.encodeMapPreamble(newlen)
		asSymbols := e.h.AsSymbols == AsSymbolDefault || e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
		for j := 0; j < newlen; j++ {
			if asSymbols {
				ee.encodeSymbol(encnames[j])
			} else {
				ee.encodeString(c_UTF8, encnames[j])
			}
			e.encodeValue(rvals[j])
		}
	} else {
		f.ee.encodeArrayPreamble(newlen)
		for j := 0; j < newlen; j++ {
			e.encodeValue(rvals[j])
		}
	}
}