1// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
2// Use of this source code is governed by a MIT license found in the LICENSE file.
3
4package codec
5
6import (
7	"encoding"
8	"errors"
9	"fmt"
10	"io"
11	"reflect"
12	"runtime"
13	"sort"
14	"strconv"
15	"time"
16)
17
18// defEncByteBufSize is the default size of []byte used
19// for bufio buffer or []byte (when nil passed)
20const defEncByteBufSize = 1 << 10 // 4:16, 6:64, 8:256, 10:1024
21
22var errEncoderNotInitialized = errors.New("Encoder not initialized")
23
24/*
25
26// encWriter abstracts writing to a byte array or to an io.Writer.
27//
28//
29// Deprecated: Use encWriterSwitch instead.
30type encWriter interface {
31	writeb([]byte)
32	writestr(string)
33	writen1(byte)
34	writen2(byte, byte)
35	end()
36}
37
38*/
39
40// encDriver abstracts the actual codec (binc vs msgpack, etc)
41type encDriver interface {
42	EncodeNil()
43	EncodeInt(i int64)
44	EncodeUint(i uint64)
45	EncodeBool(b bool)
46	EncodeFloat32(f float32)
47	EncodeFloat64(f float64)
48	// encodeExtPreamble(xtag byte, length int)
49	EncodeRawExt(re *RawExt, e *Encoder)
50	EncodeExt(v interface{}, xtag uint64, ext Ext, e *Encoder)
51	// Deprecated: use EncodeStringEnc instead
52	EncodeString(c charEncoding, v string)
53	// Deprecated: use EncodeStringBytesRaw instead
54	EncodeStringBytes(c charEncoding, v []byte)
55	EncodeStringEnc(c charEncoding, v string) // c cannot be cRAW
56	// EncodeSymbol(v string)
57	EncodeStringBytesRaw(v []byte)
58	EncodeTime(time.Time)
59	//encBignum(f *big.Int)
60	//encStringRunes(c charEncoding, v []rune)
61	WriteArrayStart(length int)
62	WriteArrayElem()
63	WriteArrayEnd()
64	WriteMapStart(length int)
65	WriteMapElemKey()
66	WriteMapElemValue()
67	WriteMapEnd()
68
69	reset()
70	atEndOfEncode()
71}
72
73type encDriverAsis interface {
74	EncodeAsis(v []byte)
75}
76
77type encodeError struct {
78	codecError
79}
80
81func (e encodeError) Error() string {
82	return fmt.Sprintf("%s encode error: %v", e.name, e.err)
83}
84
85type encDriverNoopContainerWriter struct{}
86
87func (encDriverNoopContainerWriter) WriteArrayStart(length int) {}
88func (encDriverNoopContainerWriter) WriteArrayElem()            {}
89func (encDriverNoopContainerWriter) WriteArrayEnd()             {}
90func (encDriverNoopContainerWriter) WriteMapStart(length int)   {}
91func (encDriverNoopContainerWriter) WriteMapElemKey()           {}
92func (encDriverNoopContainerWriter) WriteMapElemValue()         {}
93func (encDriverNoopContainerWriter) WriteMapEnd()               {}
94func (encDriverNoopContainerWriter) atEndOfEncode()             {}
95
96type encDriverTrackContainerWriter struct {
97	c containerState
98}
99
100func (e *encDriverTrackContainerWriter) WriteArrayStart(length int) { e.c = containerArrayStart }
101func (e *encDriverTrackContainerWriter) WriteArrayElem()            { e.c = containerArrayElem }
102func (e *encDriverTrackContainerWriter) WriteArrayEnd()             { e.c = containerArrayEnd }
103func (e *encDriverTrackContainerWriter) WriteMapStart(length int)   { e.c = containerMapStart }
104func (e *encDriverTrackContainerWriter) WriteMapElemKey()           { e.c = containerMapKey }
105func (e *encDriverTrackContainerWriter) WriteMapElemValue()         { e.c = containerMapValue }
106func (e *encDriverTrackContainerWriter) WriteMapEnd()               { e.c = containerMapEnd }
107func (e *encDriverTrackContainerWriter) atEndOfEncode()             {}
108
109// type ioEncWriterWriter interface {
110// 	WriteByte(c byte) error
111// 	WriteString(s string) (n int, err error)
112// 	Write(p []byte) (n int, err error)
113// }
114
115// EncodeOptions captures configuration options during encode.
116type EncodeOptions struct {
117	// WriterBufferSize is the size of the buffer used when writing.
118	//
119	// if > 0, we use a smart buffer internally for performance purposes.
120	WriterBufferSize int
121
122	// ChanRecvTimeout is the timeout used when selecting from a chan.
123	//
124	// Configuring this controls how we receive from a chan during the encoding process.
125	//   - If ==0, we only consume the elements currently available in the chan.
126	//   - if  <0, we consume until the chan is closed.
127	//   - If  >0, we consume until this timeout.
128	ChanRecvTimeout time.Duration
129
130	// StructToArray specifies to encode a struct as an array, and not as a map
131	StructToArray bool
132
133	// Canonical representation means that encoding a value will always result in the same
134	// sequence of bytes.
135	//
136	// This only affects maps, as the iteration order for maps is random.
137	//
138	// The implementation MAY use the natural sort order for the map keys if possible:
139	//
140	//     - If there is a natural sort order (ie for number, bool, string or []byte keys),
141	//       then the map keys are first sorted in natural order and then written
142	//       with corresponding map values to the strema.
143	//     - If there is no natural sort order, then the map keys will first be
144	//       encoded into []byte, and then sorted,
145	//       before writing the sorted keys and the corresponding map values to the stream.
146	//
147	Canonical bool
148
149	// CheckCircularRef controls whether we check for circular references
150	// and error fast during an encode.
151	//
152	// If enabled, an error is received if a pointer to a struct
153	// references itself either directly or through one of its fields (iteratively).
154	//
155	// This is opt-in, as there may be a performance hit to checking circular references.
156	CheckCircularRef bool
157
158	// RecursiveEmptyCheck controls whether we descend into interfaces, structs and pointers
159	// when checking if a value is empty.
160	//
161	// Note that this may make OmitEmpty more expensive, as it incurs a lot more reflect calls.
162	RecursiveEmptyCheck bool
163
164	// Raw controls whether we encode Raw values.
165	// This is a "dangerous" option and must be explicitly set.
166	// If set, we blindly encode Raw values as-is, without checking
167	// if they are a correct representation of a value in that format.
168	// If unset, we error out.
169	Raw bool
170
171	// StringToRaw controls how strings are encoded.
172	//
173	// As a go string is just an (immutable) sequence of bytes,
174	// it can be encoded either as raw bytes or as a UTF string.
175	//
176	// By default, strings are encoded as UTF-8.
177	// but can be treated as []byte during an encode.
178	//
179	// Note that things which we know (by definition) to be UTF-8
180	// are ALWAYS encoded as UTF-8 strings.
181	// These include encoding.TextMarshaler, time.Format calls, struct field names, etc.
182	StringToRaw bool
183
184	// // AsSymbols defines what should be encoded as symbols.
185	// //
186	// // Encoding as symbols can reduce the encoded size significantly.
187	// //
188	// // However, during decoding, each string to be encoded as a symbol must
189	// // be checked to see if it has been seen before. Consequently, encoding time
190	// // will increase if using symbols, because string comparisons has a clear cost.
191	// //
192	// // Sample values:
193	// //   AsSymbolNone
194	// //   AsSymbolAll
195	// //   AsSymbolMapStringKeys
196	// //   AsSymbolMapStringKeysFlag | AsSymbolStructFieldNameFlag
197	// AsSymbols AsSymbolFlag
198}
199
200// ---------------------------------------------
201
202/*
203
204type ioEncStringWriter interface {
205	WriteString(s string) (n int, err error)
206}
207
208// ioEncWriter implements encWriter and can write to an io.Writer implementation
209type ioEncWriter struct {
210	w  io.Writer
211	ww io.Writer
212	bw io.ByteWriter
213	sw ioEncStringWriter
214	fw ioFlusher
215	b  [8]byte
216}
217
218func (z *ioEncWriter) reset(w io.Writer) {
219	z.w = w
220	var ok bool
221	if z.bw, ok = w.(io.ByteWriter); !ok {
222		z.bw = z
223	}
224	if z.sw, ok = w.(ioEncStringWriter); !ok {
225		z.sw = z
226	}
227	z.fw, _ = w.(ioFlusher)
228	z.ww = w
229}
230
231func (z *ioEncWriter) WriteByte(b byte) (err error) {
232	z.b[0] = b
233	_, err = z.w.Write(z.b[:1])
234	return
235}
236
237func (z *ioEncWriter) WriteString(s string) (n int, err error) {
238	return z.w.Write(bytesView(s))
239}
240
241func (z *ioEncWriter) writeb(bs []byte) {
242	if _, err := z.ww.Write(bs); err != nil {
243		panic(err)
244	}
245}
246
247func (z *ioEncWriter) writestr(s string) {
248	if _, err := z.sw.WriteString(s); err != nil {
249		panic(err)
250	}
251}
252
253func (z *ioEncWriter) writen1(b byte) {
254	if err := z.bw.WriteByte(b); err != nil {
255		panic(err)
256	}
257}
258
259func (z *ioEncWriter) writen2(b1, b2 byte) {
260	var err error
261	if err = z.bw.WriteByte(b1); err == nil {
262		if err = z.bw.WriteByte(b2); err == nil {
263			return
264		}
265	}
266	panic(err)
267}
268
269// func (z *ioEncWriter) writen5(b1, b2, b3, b4, b5 byte) {
270// 	z.b[0], z.b[1], z.b[2], z.b[3], z.b[4] = b1, b2, b3, b4, b5
271// 	if _, err := z.ww.Write(z.b[:5]); err != nil {
272// 		panic(err)
273// 	}
274// }
275
276//go:noinline - so *encWriterSwitch.XXX has the bytesEncAppender.XXX inlined
277func (z *ioEncWriter) end() {
278	if z.fw != nil {
279		if err := z.fw.Flush(); err != nil {
280			panic(err)
281		}
282	}
283}
284
285*/
286
287// ---------------------------------------------
288
289// bufioEncWriter
290type bufioEncWriter struct {
291	buf []byte
292	w   io.Writer
293	n   int
294	sz  int // buf size
295
296	// Extensions can call Encode() within a current Encode() call.
297	// We need to know when the top level Encode() call returns,
298	// so we can decide whether to Release() or not.
299	calls uint16 // what depth in mustDecode are we in now.
300
301	_ [6]uint8 // padding
302
303	bytesBufPooler
304
305	_ [1]uint64 // padding
306	// a int
307	// b   [4]byte
308	// err
309}
310
311func (z *bufioEncWriter) reset(w io.Writer, bufsize int) {
312	z.w = w
313	z.n = 0
314	z.calls = 0
315	if bufsize <= 0 {
316		bufsize = defEncByteBufSize
317	}
318	z.sz = bufsize
319	if cap(z.buf) >= bufsize {
320		z.buf = z.buf[:cap(z.buf)]
321	} else {
322		z.buf = z.bytesBufPooler.get(bufsize)
323		// z.buf = make([]byte, bufsize)
324	}
325}
326
327func (z *bufioEncWriter) release() {
328	z.buf = nil
329	z.bytesBufPooler.end()
330}
331
332//go:noinline - flush only called intermittently
333func (z *bufioEncWriter) flushErr() (err error) {
334	n, err := z.w.Write(z.buf[:z.n])
335	z.n -= n
336	if z.n > 0 && err == nil {
337		err = io.ErrShortWrite
338	}
339	if n > 0 && z.n > 0 {
340		copy(z.buf, z.buf[n:z.n+n])
341	}
342	return err
343}
344
345func (z *bufioEncWriter) flush() {
346	if err := z.flushErr(); err != nil {
347		panic(err)
348	}
349}
350
351func (z *bufioEncWriter) writeb(s []byte) {
352LOOP:
353	a := len(z.buf) - z.n
354	if len(s) > a {
355		z.n += copy(z.buf[z.n:], s[:a])
356		s = s[a:]
357		z.flush()
358		goto LOOP
359	}
360	z.n += copy(z.buf[z.n:], s)
361}
362
363func (z *bufioEncWriter) writestr(s string) {
364	// z.writeb(bytesView(s)) // inlined below
365LOOP:
366	a := len(z.buf) - z.n
367	if len(s) > a {
368		z.n += copy(z.buf[z.n:], s[:a])
369		s = s[a:]
370		z.flush()
371		goto LOOP
372	}
373	z.n += copy(z.buf[z.n:], s)
374}
375
376func (z *bufioEncWriter) writen1(b1 byte) {
377	if 1 > len(z.buf)-z.n {
378		z.flush()
379	}
380	z.buf[z.n] = b1
381	z.n++
382}
383
384func (z *bufioEncWriter) writen2(b1, b2 byte) {
385	if 2 > len(z.buf)-z.n {
386		z.flush()
387	}
388	z.buf[z.n+1] = b2
389	z.buf[z.n] = b1
390	z.n += 2
391}
392
393func (z *bufioEncWriter) endErr() (err error) {
394	if z.n > 0 {
395		err = z.flushErr()
396	}
397	return
398}
399
400// ---------------------------------------------
401
402// bytesEncAppender implements encWriter and can write to an byte slice.
403type bytesEncAppender struct {
404	b   []byte
405	out *[]byte
406}
407
408func (z *bytesEncAppender) writeb(s []byte) {
409	z.b = append(z.b, s...)
410}
411func (z *bytesEncAppender) writestr(s string) {
412	z.b = append(z.b, s...)
413}
414func (z *bytesEncAppender) writen1(b1 byte) {
415	z.b = append(z.b, b1)
416}
417func (z *bytesEncAppender) writen2(b1, b2 byte) {
418	z.b = append(z.b, b1, b2)
419}
420func (z *bytesEncAppender) endErr() error {
421	*(z.out) = z.b
422	return nil
423}
424func (z *bytesEncAppender) reset(in []byte, out *[]byte) {
425	z.b = in[:0]
426	z.out = out
427}
428
429// ---------------------------------------------
430
431func (e *Encoder) rawExt(f *codecFnInfo, rv reflect.Value) {
432	e.e.EncodeRawExt(rv2i(rv).(*RawExt), e)
433}
434
435func (e *Encoder) ext(f *codecFnInfo, rv reflect.Value) {
436	e.e.EncodeExt(rv2i(rv), f.xfTag, f.xfFn, e)
437}
438
439func (e *Encoder) selferMarshal(f *codecFnInfo, rv reflect.Value) {
440	rv2i(rv).(Selfer).CodecEncodeSelf(e)
441}
442
443func (e *Encoder) binaryMarshal(f *codecFnInfo, rv reflect.Value) {
444	bs, fnerr := rv2i(rv).(encoding.BinaryMarshaler).MarshalBinary()
445	e.marshalRaw(bs, fnerr)
446}
447
448func (e *Encoder) textMarshal(f *codecFnInfo, rv reflect.Value) {
449	bs, fnerr := rv2i(rv).(encoding.TextMarshaler).MarshalText()
450	e.marshalUtf8(bs, fnerr)
451}
452
453func (e *Encoder) jsonMarshal(f *codecFnInfo, rv reflect.Value) {
454	bs, fnerr := rv2i(rv).(jsonMarshaler).MarshalJSON()
455	e.marshalAsis(bs, fnerr)
456}
457
458func (e *Encoder) raw(f *codecFnInfo, rv reflect.Value) {
459	e.rawBytes(rv2i(rv).(Raw))
460}
461
462func (e *Encoder) kInvalid(f *codecFnInfo, rv reflect.Value) {
463	e.e.EncodeNil()
464}
465
466func (e *Encoder) kErr(f *codecFnInfo, rv reflect.Value) {
467	e.errorf("unsupported kind %s, for %#v", rv.Kind(), rv)
468}
469
470func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
471	ti := f.ti
472	ee := e.e
473	// array may be non-addressable, so we have to manage with care
474	//   (don't call rv.Bytes, rv.Slice, etc).
475	// E.g. type struct S{B [2]byte};
476	//   Encode(S{}) will bomb on "panic: slice of unaddressable array".
477	if f.seq != seqTypeArray {
478		if rv.IsNil() {
479			ee.EncodeNil()
480			return
481		}
482		// If in this method, then there was no extension function defined.
483		// So it's okay to treat as []byte.
484		if ti.rtid == uint8SliceTypId {
485			ee.EncodeStringBytesRaw(rv.Bytes())
486			return
487		}
488	}
489	if f.seq == seqTypeChan && ti.chandir&uint8(reflect.RecvDir) == 0 {
490		e.errorf("send-only channel cannot be encoded")
491	}
492	elemsep := e.esep
493	rtelem := ti.elem
494	rtelemIsByte := uint8TypId == rt2id(rtelem) // NOT rtelem.Kind() == reflect.Uint8
495	var l int
496	// if a slice, array or chan of bytes, treat specially
497	if rtelemIsByte {
498		switch f.seq {
499		case seqTypeSlice:
500			ee.EncodeStringBytesRaw(rv.Bytes())
501		case seqTypeArray:
502			l = rv.Len()
503			if rv.CanAddr() {
504				ee.EncodeStringBytesRaw(rv.Slice(0, l).Bytes())
505			} else {
506				var bs []byte
507				if l <= cap(e.b) {
508					bs = e.b[:l]
509				} else {
510					bs = make([]byte, l)
511				}
512				reflect.Copy(reflect.ValueOf(bs), rv)
513				ee.EncodeStringBytesRaw(bs)
514			}
515		case seqTypeChan:
516			// do not use range, so that the number of elements encoded
517			// does not change, and encoding does not hang waiting on someone to close chan.
518			// for b := range rv2i(rv).(<-chan byte) { bs = append(bs, b) }
519			// ch := rv2i(rv).(<-chan byte) // fix error - that this is a chan byte, not a <-chan byte.
520
521			if rv.IsNil() {
522				ee.EncodeNil()
523				break
524			}
525			bs := e.b[:0]
526			irv := rv2i(rv)
527			ch, ok := irv.(<-chan byte)
528			if !ok {
529				ch = irv.(chan byte)
530			}
531
532		L1:
533			switch timeout := e.h.ChanRecvTimeout; {
534			case timeout == 0: // only consume available
535				for {
536					select {
537					case b := <-ch:
538						bs = append(bs, b)
539					default:
540						break L1
541					}
542				}
543			case timeout > 0: // consume until timeout
544				tt := time.NewTimer(timeout)
545				for {
546					select {
547					case b := <-ch:
548						bs = append(bs, b)
549					case <-tt.C:
550						// close(tt.C)
551						break L1
552					}
553				}
554			default: // consume until close
555				for b := range ch {
556					bs = append(bs, b)
557				}
558			}
559
560			ee.EncodeStringBytesRaw(bs)
561		}
562		return
563	}
564
565	// if chan, consume chan into a slice, and work off that slice.
566	if f.seq == seqTypeChan {
567		rvcs := reflect.Zero(reflect.SliceOf(rtelem))
568		timeout := e.h.ChanRecvTimeout
569		if timeout < 0 { // consume until close
570			for {
571				recv, recvOk := rv.Recv()
572				if !recvOk {
573					break
574				}
575				rvcs = reflect.Append(rvcs, recv)
576			}
577		} else {
578			cases := make([]reflect.SelectCase, 2)
579			cases[0] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: rv}
580			if timeout == 0 {
581				cases[1] = reflect.SelectCase{Dir: reflect.SelectDefault}
582			} else {
583				tt := time.NewTimer(timeout)
584				cases[1] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(tt.C)}
585			}
586			for {
587				chosen, recv, recvOk := reflect.Select(cases)
588				if chosen == 1 || !recvOk {
589					break
590				}
591				rvcs = reflect.Append(rvcs, recv)
592			}
593		}
594		rv = rvcs // TODO: ensure this doesn't mess up anywhere that rv of kind chan is expected
595	}
596
597	l = rv.Len()
598	if ti.mbs {
599		if l%2 == 1 {
600			e.errorf("mapBySlice requires even slice length, but got %v", l)
601			return
602		}
603		ee.WriteMapStart(l / 2)
604	} else {
605		ee.WriteArrayStart(l)
606	}
607
608	if l > 0 {
609		var fn *codecFn
610		for rtelem.Kind() == reflect.Ptr {
611			rtelem = rtelem.Elem()
612		}
613		// if kind is reflect.Interface, do not pre-determine the
614		// encoding type, because preEncodeValue may break it down to
615		// a concrete type and kInterface will bomb.
616		if rtelem.Kind() != reflect.Interface {
617			fn = e.h.fn(rtelem, true, true)
618		}
619		for j := 0; j < l; j++ {
620			if elemsep {
621				if ti.mbs {
622					if j%2 == 0 {
623						ee.WriteMapElemKey()
624					} else {
625						ee.WriteMapElemValue()
626					}
627				} else {
628					ee.WriteArrayElem()
629				}
630			}
631			e.encodeValue(rv.Index(j), fn, true)
632		}
633	}
634
635	if ti.mbs {
636		ee.WriteMapEnd()
637	} else {
638		ee.WriteArrayEnd()
639	}
640}
641
642func (e *Encoder) kStructNoOmitempty(f *codecFnInfo, rv reflect.Value) {
643	fti := f.ti
644	tisfi := fti.sfiSrc
645	toMap := !(fti.toArray || e.h.StructToArray)
646	if toMap {
647		tisfi = fti.sfiSort
648	}
649
650	ee := e.e
651
652	sfn := structFieldNode{v: rv, update: false}
653	if toMap {
654		ee.WriteMapStart(len(tisfi))
655		if e.esep {
656			for _, si := range tisfi {
657				ee.WriteMapElemKey()
658				e.kStructFieldKey(fti.keyType, si.encNameAsciiAlphaNum, si.encName)
659				ee.WriteMapElemValue()
660				e.encodeValue(sfn.field(si), nil, true)
661			}
662		} else {
663			for _, si := range tisfi {
664				e.kStructFieldKey(fti.keyType, si.encNameAsciiAlphaNum, si.encName)
665				e.encodeValue(sfn.field(si), nil, true)
666			}
667		}
668		ee.WriteMapEnd()
669	} else {
670		ee.WriteArrayStart(len(tisfi))
671		if e.esep {
672			for _, si := range tisfi {
673				ee.WriteArrayElem()
674				e.encodeValue(sfn.field(si), nil, true)
675			}
676		} else {
677			for _, si := range tisfi {
678				e.encodeValue(sfn.field(si), nil, true)
679			}
680		}
681		ee.WriteArrayEnd()
682	}
683}
684
685func (e *Encoder) kStructFieldKey(keyType valueType, encNameAsciiAlphaNum bool, encName string) {
686	encStructFieldKey(encName, e.e, e.w, keyType, encNameAsciiAlphaNum, e.js)
687}
688
689func (e *Encoder) kStruct(f *codecFnInfo, rv reflect.Value) {
690	fti := f.ti
691	elemsep := e.esep
692	tisfi := fti.sfiSrc
693	var newlen int
694	toMap := !(fti.toArray || e.h.StructToArray)
695	var mf map[string]interface{}
696	if f.ti.mf {
697		mf = rv2i(rv).(MissingFielder).CodecMissingFields()
698		toMap = true
699		newlen += len(mf)
700	} else if f.ti.mfp {
701		if rv.CanAddr() {
702			mf = rv2i(rv.Addr()).(MissingFielder).CodecMissingFields()
703		} else {
704			// make a new addressable value of same one, and use it
705			rv2 := reflect.New(rv.Type())
706			rv2.Elem().Set(rv)
707			mf = rv2i(rv2).(MissingFielder).CodecMissingFields()
708		}
709		toMap = true
710		newlen += len(mf)
711	}
712	// if toMap, use the sorted array. If toArray, use unsorted array (to match sequence in struct)
713	if toMap {
714		tisfi = fti.sfiSort
715	}
716	newlen += len(tisfi)
717	ee := e.e
718
719	// Use sync.Pool to reduce allocating slices unnecessarily.
720	// The cost of sync.Pool is less than the cost of new allocation.
721	//
722	// Each element of the array pools one of encStructPool(8|16|32|64).
723	// It allows the re-use of slices up to 64 in length.
724	// A performance cost of encoding structs was collecting
725	// which values were empty and should be omitted.
726	// We needed slices of reflect.Value and string to collect them.
727	// This shared pool reduces the amount of unnecessary creation we do.
728	// The cost is that of locking sometimes, but sync.Pool is efficient
729	// enough to reduce thread contention.
730
731	// fmt.Printf(">>>>>>>>>>>>>> encode.kStruct: newlen: %d\n", newlen)
732	var spool sfiRvPooler
733	var fkvs = spool.get(newlen)
734
735	var kv sfiRv
736	recur := e.h.RecursiveEmptyCheck
737	sfn := structFieldNode{v: rv, update: false}
738	newlen = 0
739	for _, si := range tisfi {
740		// kv.r = si.field(rv, false)
741		kv.r = sfn.field(si)
742		if toMap {
743			if si.omitEmpty() && isEmptyValue(kv.r, e.h.TypeInfos, recur, recur) {
744				continue
745			}
746			kv.v = si // si.encName
747		} else {
748			// use the zero value.
749			// if a reference or struct, set to nil (so you do not output too much)
750			if si.omitEmpty() && isEmptyValue(kv.r, e.h.TypeInfos, recur, recur) {
751				switch kv.r.Kind() {
752				case reflect.Struct, reflect.Interface, reflect.Ptr,
753					reflect.Array, reflect.Map, reflect.Slice:
754					kv.r = reflect.Value{} //encode as nil
755				}
756			}
757		}
758		fkvs[newlen] = kv
759		newlen++
760	}
761	fkvs = fkvs[:newlen]
762
763	var mflen int
764	for k, v := range mf {
765		if k == "" {
766			delete(mf, k)
767			continue
768		}
769		if fti.infoFieldOmitempty && isEmptyValue(reflect.ValueOf(v), e.h.TypeInfos, recur, recur) {
770			delete(mf, k)
771			continue
772		}
773		mflen++
774	}
775
776	var j int
777	if toMap {
778		ee.WriteMapStart(newlen + mflen)
779		if elemsep {
780			for j = 0; j < len(fkvs); j++ {
781				kv = fkvs[j]
782				ee.WriteMapElemKey()
783				e.kStructFieldKey(fti.keyType, kv.v.encNameAsciiAlphaNum, kv.v.encName)
784				ee.WriteMapElemValue()
785				e.encodeValue(kv.r, nil, true)
786			}
787		} else {
788			for j = 0; j < len(fkvs); j++ {
789				kv = fkvs[j]
790				e.kStructFieldKey(fti.keyType, kv.v.encNameAsciiAlphaNum, kv.v.encName)
791				e.encodeValue(kv.r, nil, true)
792			}
793		}
794		// now, add the others
795		for k, v := range mf {
796			ee.WriteMapElemKey()
797			e.kStructFieldKey(fti.keyType, false, k)
798			ee.WriteMapElemValue()
799			e.encode(v)
800		}
801		ee.WriteMapEnd()
802	} else {
803		ee.WriteArrayStart(newlen)
804		if elemsep {
805			for j = 0; j < len(fkvs); j++ {
806				ee.WriteArrayElem()
807				e.encodeValue(fkvs[j].r, nil, true)
808			}
809		} else {
810			for j = 0; j < len(fkvs); j++ {
811				e.encodeValue(fkvs[j].r, nil, true)
812			}
813		}
814		ee.WriteArrayEnd()
815	}
816
817	// do not use defer. Instead, use explicit pool return at end of function.
818	// defer has a cost we are trying to avoid.
819	// If there is a panic and these slices are not returned, it is ok.
820	spool.end()
821}
822
823func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
824	ee := e.e
825	if rv.IsNil() {
826		ee.EncodeNil()
827		return
828	}
829
830	l := rv.Len()
831	ee.WriteMapStart(l)
832	if l == 0 {
833		ee.WriteMapEnd()
834		return
835	}
836	// var asSymbols bool
837	// determine the underlying key and val encFn's for the map.
838	// This eliminates some work which is done for each loop iteration i.e.
839	// rv.Type(), ref.ValueOf(rt).Pointer(), then check map/list for fn.
840	//
841	// However, if kind is reflect.Interface, do not pre-determine the
842	// encoding type, because preEncodeValue may break it down to
843	// a concrete type and kInterface will bomb.
844	var keyFn, valFn *codecFn
845	ti := f.ti
846	rtkey0 := ti.key
847	rtkey := rtkey0
848	rtval0 := ti.elem
849	rtval := rtval0
850	// rtkeyid := rt2id(rtkey0)
851	for rtval.Kind() == reflect.Ptr {
852		rtval = rtval.Elem()
853	}
854	if rtval.Kind() != reflect.Interface {
855		valFn = e.h.fn(rtval, true, true)
856	}
857	mks := rv.MapKeys()
858
859	if e.h.Canonical {
860		e.kMapCanonical(rtkey, rv, mks, valFn)
861		ee.WriteMapEnd()
862		return
863	}
864
865	var keyTypeIsString = stringTypId == rt2id(rtkey0) // rtkeyid
866	if !keyTypeIsString {
867		for rtkey.Kind() == reflect.Ptr {
868			rtkey = rtkey.Elem()
869		}
870		if rtkey.Kind() != reflect.Interface {
871			// rtkeyid = rt2id(rtkey)
872			keyFn = e.h.fn(rtkey, true, true)
873		}
874	}
875
876	// for j, lmks := 0, len(mks); j < lmks; j++ {
877	for j := range mks {
878		if e.esep {
879			ee.WriteMapElemKey()
880		}
881		if keyTypeIsString {
882			if e.h.StringToRaw {
883				ee.EncodeStringBytesRaw(bytesView(mks[j].String()))
884			} else {
885				ee.EncodeStringEnc(cUTF8, mks[j].String())
886			}
887		} else {
888			e.encodeValue(mks[j], keyFn, true)
889		}
890		if e.esep {
891			ee.WriteMapElemValue()
892		}
893		e.encodeValue(rv.MapIndex(mks[j]), valFn, true)
894
895	}
896	ee.WriteMapEnd()
897}
898
899func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []reflect.Value, valFn *codecFn) {
900	ee := e.e
901	elemsep := e.esep
902	// we previously did out-of-band if an extension was registered.
903	// This is not necessary, as the natural kind is sufficient for ordering.
904
905	switch rtkey.Kind() {
906	case reflect.Bool:
907		mksv := make([]boolRv, len(mks))
908		for i, k := range mks {
909			v := &mksv[i]
910			v.r = k
911			v.v = k.Bool()
912		}
913		sort.Sort(boolRvSlice(mksv))
914		for i := range mksv {
915			if elemsep {
916				ee.WriteMapElemKey()
917			}
918			ee.EncodeBool(mksv[i].v)
919			if elemsep {
920				ee.WriteMapElemValue()
921			}
922			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
923		}
924	case reflect.String:
925		mksv := make([]stringRv, len(mks))
926		for i, k := range mks {
927			v := &mksv[i]
928			v.r = k
929			v.v = k.String()
930		}
931		sort.Sort(stringRvSlice(mksv))
932		for i := range mksv {
933			if elemsep {
934				ee.WriteMapElemKey()
935			}
936			if e.h.StringToRaw {
937				ee.EncodeStringBytesRaw(bytesView(mksv[i].v))
938			} else {
939				ee.EncodeStringEnc(cUTF8, mksv[i].v)
940			}
941			if elemsep {
942				ee.WriteMapElemValue()
943			}
944			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
945		}
946	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
947		mksv := make([]uintRv, len(mks))
948		for i, k := range mks {
949			v := &mksv[i]
950			v.r = k
951			v.v = k.Uint()
952		}
953		sort.Sort(uintRvSlice(mksv))
954		for i := range mksv {
955			if elemsep {
956				ee.WriteMapElemKey()
957			}
958			ee.EncodeUint(mksv[i].v)
959			if elemsep {
960				ee.WriteMapElemValue()
961			}
962			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
963		}
964	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
965		mksv := make([]intRv, len(mks))
966		for i, k := range mks {
967			v := &mksv[i]
968			v.r = k
969			v.v = k.Int()
970		}
971		sort.Sort(intRvSlice(mksv))
972		for i := range mksv {
973			if elemsep {
974				ee.WriteMapElemKey()
975			}
976			ee.EncodeInt(mksv[i].v)
977			if elemsep {
978				ee.WriteMapElemValue()
979			}
980			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
981		}
982	case reflect.Float32:
983		mksv := make([]floatRv, len(mks))
984		for i, k := range mks {
985			v := &mksv[i]
986			v.r = k
987			v.v = k.Float()
988		}
989		sort.Sort(floatRvSlice(mksv))
990		for i := range mksv {
991			if elemsep {
992				ee.WriteMapElemKey()
993			}
994			ee.EncodeFloat32(float32(mksv[i].v))
995			if elemsep {
996				ee.WriteMapElemValue()
997			}
998			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
999		}
1000	case reflect.Float64:
1001		mksv := make([]floatRv, len(mks))
1002		for i, k := range mks {
1003			v := &mksv[i]
1004			v.r = k
1005			v.v = k.Float()
1006		}
1007		sort.Sort(floatRvSlice(mksv))
1008		for i := range mksv {
1009			if elemsep {
1010				ee.WriteMapElemKey()
1011			}
1012			ee.EncodeFloat64(mksv[i].v)
1013			if elemsep {
1014				ee.WriteMapElemValue()
1015			}
1016			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
1017		}
1018	case reflect.Struct:
1019		if rv.Type() == timeTyp {
1020			mksv := make([]timeRv, len(mks))
1021			for i, k := range mks {
1022				v := &mksv[i]
1023				v.r = k
1024				v.v = rv2i(k).(time.Time)
1025			}
1026			sort.Sort(timeRvSlice(mksv))
1027			for i := range mksv {
1028				if elemsep {
1029					ee.WriteMapElemKey()
1030				}
1031				ee.EncodeTime(mksv[i].v)
1032				if elemsep {
1033					ee.WriteMapElemValue()
1034				}
1035				e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
1036			}
1037			break
1038		}
1039		fallthrough
1040	default:
1041		// out-of-band
1042		// first encode each key to a []byte first, then sort them, then record
1043		var mksv []byte = make([]byte, 0, len(mks)*16) // temporary byte slice for the encoding
1044		e2 := NewEncoderBytes(&mksv, e.hh)
1045		mksbv := make([]bytesRv, len(mks))
1046		for i, k := range mks {
1047			v := &mksbv[i]
1048			l := len(mksv)
1049			e2.MustEncode(k)
1050			v.r = k
1051			v.v = mksv[l:]
1052		}
1053		sort.Sort(bytesRvSlice(mksbv))
1054		for j := range mksbv {
1055			if elemsep {
1056				ee.WriteMapElemKey()
1057			}
1058			e.asis(mksbv[j].v)
1059			if elemsep {
1060				ee.WriteMapElemValue()
1061			}
1062			e.encodeValue(rv.MapIndex(mksbv[j].r), valFn, true)
1063		}
1064	}
1065}
1066
1067// // --------------------------------------------------
1068
1069type encWriterSwitch struct {
1070	// wi   *ioEncWriter
1071	wb bytesEncAppender
1072	wf *bufioEncWriter
1073	// typ  entryType
1074	bytes bool    // encoding to []byte
1075	esep  bool    // whether it has elem separators
1076	isas  bool    // whether e.as != nil
1077	js    bool    // is json encoder?
1078	be    bool    // is binary encoder?
1079	_     [2]byte // padding
1080	// _    [2]uint64 // padding
1081	// _    uint64    // padding
1082}
1083
1084func (z *encWriterSwitch) writeb(s []byte) {
1085	if z.bytes {
1086		z.wb.writeb(s)
1087	} else {
1088		z.wf.writeb(s)
1089	}
1090}
1091func (z *encWriterSwitch) writestr(s string) {
1092	if z.bytes {
1093		z.wb.writestr(s)
1094	} else {
1095		z.wf.writestr(s)
1096	}
1097}
1098func (z *encWriterSwitch) writen1(b1 byte) {
1099	if z.bytes {
1100		z.wb.writen1(b1)
1101	} else {
1102		z.wf.writen1(b1)
1103	}
1104}
1105func (z *encWriterSwitch) writen2(b1, b2 byte) {
1106	if z.bytes {
1107		z.wb.writen2(b1, b2)
1108	} else {
1109		z.wf.writen2(b1, b2)
1110	}
1111}
1112func (z *encWriterSwitch) endErr() error {
1113	if z.bytes {
1114		return z.wb.endErr()
1115	}
1116	return z.wf.endErr()
1117}
1118
1119func (z *encWriterSwitch) end() {
1120	if err := z.endErr(); err != nil {
1121		panic(err)
1122	}
1123}
1124
1125/*
1126
1127// ------------------------------------------
1128func (z *encWriterSwitch) writeb(s []byte) {
1129	switch z.typ {
1130	case entryTypeBytes:
1131		z.wb.writeb(s)
1132	case entryTypeIo:
1133		z.wi.writeb(s)
1134	default:
1135		z.wf.writeb(s)
1136	}
1137}
1138func (z *encWriterSwitch) writestr(s string) {
1139	switch z.typ {
1140	case entryTypeBytes:
1141		z.wb.writestr(s)
1142	case entryTypeIo:
1143		z.wi.writestr(s)
1144	default:
1145		z.wf.writestr(s)
1146	}
1147}
1148func (z *encWriterSwitch) writen1(b1 byte) {
1149	switch z.typ {
1150	case entryTypeBytes:
1151		z.wb.writen1(b1)
1152	case entryTypeIo:
1153		z.wi.writen1(b1)
1154	default:
1155		z.wf.writen1(b1)
1156	}
1157}
1158func (z *encWriterSwitch) writen2(b1, b2 byte) {
1159	switch z.typ {
1160	case entryTypeBytes:
1161		z.wb.writen2(b1, b2)
1162	case entryTypeIo:
1163		z.wi.writen2(b1, b2)
1164	default:
1165		z.wf.writen2(b1, b2)
1166	}
1167}
1168func (z *encWriterSwitch) end() {
1169	switch z.typ {
1170	case entryTypeBytes:
1171		z.wb.end()
1172	case entryTypeIo:
1173		z.wi.end()
1174	default:
1175		z.wf.end()
1176	}
1177}
1178
1179// ------------------------------------------
1180func (z *encWriterSwitch) writeb(s []byte) {
1181	if z.bytes {
1182		z.wb.writeb(s)
1183	} else {
1184		z.wi.writeb(s)
1185	}
1186}
1187func (z *encWriterSwitch) writestr(s string) {
1188	if z.bytes {
1189		z.wb.writestr(s)
1190	} else {
1191		z.wi.writestr(s)
1192	}
1193}
1194func (z *encWriterSwitch) writen1(b1 byte) {
1195	if z.bytes {
1196		z.wb.writen1(b1)
1197	} else {
1198		z.wi.writen1(b1)
1199	}
1200}
1201func (z *encWriterSwitch) writen2(b1, b2 byte) {
1202	if z.bytes {
1203		z.wb.writen2(b1, b2)
1204	} else {
1205		z.wi.writen2(b1, b2)
1206	}
1207}
1208func (z *encWriterSwitch) end() {
1209	if z.bytes {
1210		z.wb.end()
1211	} else {
1212		z.wi.end()
1213	}
1214}
1215
1216*/
1217
1218// Encoder writes an object to an output stream in a supported format.
1219//
1220// Encoder is NOT safe for concurrent use i.e. a Encoder cannot be used
1221// concurrently in multiple goroutines.
1222//
1223// However, as Encoder could be allocation heavy to initialize, a Reset method is provided
1224// so its state can be reused to decode new input streams repeatedly.
1225// This is the idiomatic way to use.
1226type Encoder struct {
1227	panicHdl
1228	// hopefully, reduce derefencing cost by laying the encWriter inside the Encoder
1229	e encDriver
1230
1231	// NOTE: Encoder shouldn't call it's write methods,
1232	// as the handler MAY need to do some coordination.
1233	w *encWriterSwitch
1234
1235	// bw *bufio.Writer
1236	as encDriverAsis
1237
1238	err error
1239
1240	h  *BasicHandle
1241	hh Handle
1242	// ---- cpu cache line boundary? + 3
1243	encWriterSwitch
1244
1245	ci set
1246
1247	b [(5 * 8)]byte // for encoding chan or (non-addressable) [N]byte
1248
1249	// ---- writable fields during execution --- *try* to keep in sep cache line
1250
1251	// ---- cpu cache line boundary?
1252	// b [scratchByteArrayLen]byte
1253	// _ [cacheLineSize - scratchByteArrayLen]byte // padding
1254	// b [cacheLineSize - (8 * 0)]byte // used for encoding a chan or (non-addressable) array of bytes
1255}
1256
1257// NewEncoder returns an Encoder for encoding into an io.Writer.
1258//
1259// For efficiency, Users are encouraged to configure WriterBufferSize on the handle
1260// OR pass in a memory buffered writer (eg bufio.Writer, bytes.Buffer).
1261func NewEncoder(w io.Writer, h Handle) *Encoder {
1262	e := newEncoder(h)
1263	e.Reset(w)
1264	return e
1265}
1266
1267// NewEncoderBytes returns an encoder for encoding directly and efficiently
1268// into a byte slice, using zero-copying to temporary slices.
1269//
1270// It will potentially replace the output byte slice pointed to.
1271// After encoding, the out parameter contains the encoded contents.
1272func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
1273	e := newEncoder(h)
1274	e.ResetBytes(out)
1275	return e
1276}
1277
1278func newEncoder(h Handle) *Encoder {
1279	e := &Encoder{h: basicHandle(h), err: errEncoderNotInitialized}
1280	e.bytes = true
1281	if useFinalizers {
1282		runtime.SetFinalizer(e, (*Encoder).finalize)
1283		// xdebugf(">>>> new(Encoder) with finalizer")
1284	}
1285	e.w = &e.encWriterSwitch
1286	e.hh = h
1287	e.esep = h.hasElemSeparators()
1288
1289	return e
1290}
1291
1292func (e *Encoder) resetCommon() {
1293	// e.w = &e.encWriterSwitch
1294	if e.e == nil || e.hh.recreateEncDriver(e.e) {
1295		e.e = e.hh.newEncDriver(e)
1296		e.as, e.isas = e.e.(encDriverAsis)
1297		// e.cr, _ = e.e.(containerStateRecv)
1298	}
1299	e.be = e.hh.isBinary()
1300	_, e.js = e.hh.(*JsonHandle)
1301	e.e.reset()
1302	e.err = nil
1303}
1304
1305// Reset resets the Encoder with a new output stream.
1306//
1307// This accommodates using the state of the Encoder,
1308// where it has "cached" information about sub-engines.
1309func (e *Encoder) Reset(w io.Writer) {
1310	if w == nil {
1311		return
1312	}
1313	// var ok bool
1314	e.bytes = false
1315	if e.wf == nil {
1316		e.wf = new(bufioEncWriter)
1317	}
1318	// e.typ = entryTypeUnset
1319	// if e.h.WriterBufferSize > 0 {
1320	// 	// bw := bufio.NewWriterSize(w, e.h.WriterBufferSize)
1321	// 	// e.wi.bw = bw
1322	// 	// e.wi.sw = bw
1323	// 	// e.wi.fw = bw
1324	// 	// e.wi.ww = bw
1325	// 	if e.wf == nil {
1326	// 		e.wf = new(bufioEncWriter)
1327	// 	}
1328	// 	e.wf.reset(w, e.h.WriterBufferSize)
1329	// 	e.typ = entryTypeBufio
1330	// } else {
1331	// 	if e.wi == nil {
1332	// 		e.wi = new(ioEncWriter)
1333	// 	}
1334	// 	e.wi.reset(w)
1335	// 	e.typ = entryTypeIo
1336	// }
1337	e.wf.reset(w, e.h.WriterBufferSize)
1338	// e.typ = entryTypeBufio
1339
1340	// e.w = e.wi
1341	e.resetCommon()
1342}
1343
1344// ResetBytes resets the Encoder with a new destination output []byte.
1345func (e *Encoder) ResetBytes(out *[]byte) {
1346	if out == nil {
1347		return
1348	}
1349	var in []byte = *out
1350	if in == nil {
1351		in = make([]byte, defEncByteBufSize)
1352	}
1353	e.bytes = true
1354	// e.typ = entryTypeBytes
1355	e.wb.reset(in, out)
1356	// e.w = &e.wb
1357	e.resetCommon()
1358}
1359
1360// Encode writes an object into a stream.
1361//
1362// Encoding can be configured via the struct tag for the fields.
1363// The key (in the struct tags) that we look at is configurable.
1364//
1365// By default, we look up the "codec" key in the struct field's tags,
1366// and fall bak to the "json" key if "codec" is absent.
1367// That key in struct field's tag value is the key name,
1368// followed by an optional comma and options.
1369//
1370// To set an option on all fields (e.g. omitempty on all fields), you
1371// can create a field called _struct, and set flags on it. The options
1372// which can be set on _struct are:
1373//    - omitempty: so all fields are omitted if empty
1374//    - toarray: so struct is encoded as an array
1375//    - int: so struct key names are encoded as signed integers (instead of strings)
1376//    - uint: so struct key names are encoded as unsigned integers (instead of strings)
1377//    - float: so struct key names are encoded as floats (instead of strings)
1378// More details on these below.
1379//
1380// Struct values "usually" encode as maps. Each exported struct field is encoded unless:
1381//    - the field's tag is "-", OR
1382//    - the field is empty (empty or the zero value) and its tag specifies the "omitempty" option.
1383//
1384// When encoding as a map, the first string in the tag (before the comma)
1385// is the map key string to use when encoding.
1386// ...
1387// This key is typically encoded as a string.
1388// However, there are instances where the encoded stream has mapping keys encoded as numbers.
1389// For example, some cbor streams have keys as integer codes in the stream, but they should map
1390// to fields in a structured object. Consequently, a struct is the natural representation in code.
1391// For these, configure the struct to encode/decode the keys as numbers (instead of string).
1392// This is done with the int,uint or float option on the _struct field (see above).
1393//
1394// However, struct values may encode as arrays. This happens when:
1395//    - StructToArray Encode option is set, OR
1396//    - the tag on the _struct field sets the "toarray" option
1397// Note that omitempty is ignored when encoding struct values as arrays,
1398// as an entry must be encoded for each field, to maintain its position.
1399//
1400// Values with types that implement MapBySlice are encoded as stream maps.
1401//
1402// The empty values (for omitempty option) are false, 0, any nil pointer
1403// or interface value, and any array, slice, map, or string of length zero.
1404//
1405// Anonymous fields are encoded inline except:
1406//    - the struct tag specifies a replacement name (first value)
1407//    - the field is of an interface type
1408//
1409// Examples:
1410//
1411//      // NOTE: 'json:' can be used as struct tag key, in place 'codec:' below.
1412//      type MyStruct struct {
1413//          _struct bool    `codec:",omitempty"`   //set omitempty for every field
1414//          Field1 string   `codec:"-"`            //skip this field
1415//          Field2 int      `codec:"myName"`       //Use key "myName" in encode stream
1416//          Field3 int32    `codec:",omitempty"`   //use key "Field3". Omit if empty.
1417//          Field4 bool     `codec:"f4,omitempty"` //use key "f4". Omit if empty.
1418//          io.Reader                              //use key "Reader".
1419//          MyStruct        `codec:"my1"           //use key "my1".
1420//          MyStruct                               //inline it
1421//          ...
1422//      }
1423//
1424//      type MyStruct struct {
1425//          _struct bool    `codec:",toarray"`     //encode struct as an array
1426//      }
1427//
1428//      type MyStruct struct {
1429//          _struct bool    `codec:",uint"`        //encode struct with "unsigned integer" keys
1430//          Field1 string   `codec:"1"`            //encode Field1 key using: EncodeInt(1)
1431//          Field2 string   `codec:"2"`            //encode Field2 key using: EncodeInt(2)
1432//      }
1433//
1434// The mode of encoding is based on the type of the value. When a value is seen:
1435//   - If a Selfer, call its CodecEncodeSelf method
1436//   - If an extension is registered for it, call that extension function
1437//   - If implements encoding.(Binary|Text|JSON)Marshaler, call Marshal(Binary|Text|JSON) method
1438//   - Else encode it based on its reflect.Kind
1439//
1440// Note that struct field names and keys in map[string]XXX will be treated as symbols.
1441// Some formats support symbols (e.g. binc) and will properly encode the string
1442// only once in the stream, and use a tag to refer to it thereafter.
1443func (e *Encoder) Encode(v interface{}) (err error) {
1444	// tried to use closure, as runtime optimizes defer with no params.
1445	// This seemed to be causing weird issues (like circular reference found, unexpected panic, etc).
1446	// Also, see https://github.com/golang/go/issues/14939#issuecomment-417836139
1447	// defer func() { e.deferred(&err) }() }
1448	// { x, y := e, &err; defer func() { x.deferred(y) }() }
1449	if e.err != nil {
1450		return e.err
1451	}
1452	if recoverPanicToErr {
1453		defer func() {
1454			// if error occurred during encoding, return that error;
1455			// else if error occurred on end'ing (i.e. during flush), return that error.
1456			err = e.w.endErr()
1457			x := recover()
1458			if x == nil {
1459				e.err = err
1460			} else {
1461				panicValToErr(e, x, &e.err)
1462				err = e.err
1463			}
1464		}()
1465	}
1466
1467	// defer e.deferred(&err)
1468	e.mustEncode(v)
1469	return
1470}
1471
1472// MustEncode is like Encode, but panics if unable to Encode.
1473// This provides insight to the code location that triggered the error.
1474func (e *Encoder) MustEncode(v interface{}) {
1475	if e.err != nil {
1476		panic(e.err)
1477	}
1478	e.mustEncode(v)
1479}
1480
1481func (e *Encoder) mustEncode(v interface{}) {
1482	if e.wf == nil {
1483		e.encode(v)
1484		e.e.atEndOfEncode()
1485		e.w.end()
1486		return
1487	}
1488
1489	if e.wf.buf == nil {
1490		e.wf.buf = e.wf.bytesBufPooler.get(e.wf.sz)
1491	}
1492	e.wf.calls++
1493
1494	e.encode(v)
1495
1496	e.wf.calls--
1497
1498	if e.wf.calls == 0 {
1499		e.e.atEndOfEncode()
1500		e.w.end()
1501		if !e.h.ExplicitRelease {
1502			e.wf.release()
1503		}
1504	}
1505}
1506
1507// func (e *Encoder) deferred(err1 *error) {
1508// 	e.w.end()
1509// 	if recoverPanicToErr {
1510// 		if x := recover(); x != nil {
1511// 			panicValToErr(e, x, err1)
1512// 			panicValToErr(e, x, &e.err)
1513// 		}
1514// 	}
1515// }
1516
1517//go:noinline -- as it is run by finalizer
1518func (e *Encoder) finalize() {
1519	// xdebugf("finalizing Encoder")
1520	e.Release()
1521}
1522
1523// Release releases shared (pooled) resources.
1524//
1525// It is important to call Release() when done with an Encoder, so those resources
1526// are released instantly for use by subsequently created Encoders.
1527func (e *Encoder) Release() {
1528	if e.wf != nil {
1529		e.wf.release()
1530	}
1531}
1532
1533func (e *Encoder) encode(iv interface{}) {
1534	// a switch with only concrete types can be optimized.
1535	// consequently, we deal with nil and interfaces outside the switch.
1536
1537	if iv == nil || definitelyNil(iv) {
1538		e.e.EncodeNil()
1539		return
1540	}
1541
1542	switch v := iv.(type) {
1543	// case nil:
1544	// case Selfer:
1545	case Raw:
1546		e.rawBytes(v)
1547	case reflect.Value:
1548		e.encodeValue(v, nil, true)
1549
1550	case string:
1551		if e.h.StringToRaw {
1552			e.e.EncodeStringBytesRaw(bytesView(v))
1553		} else {
1554			e.e.EncodeStringEnc(cUTF8, v)
1555		}
1556	case bool:
1557		e.e.EncodeBool(v)
1558	case int:
1559		e.e.EncodeInt(int64(v))
1560	case int8:
1561		e.e.EncodeInt(int64(v))
1562	case int16:
1563		e.e.EncodeInt(int64(v))
1564	case int32:
1565		e.e.EncodeInt(int64(v))
1566	case int64:
1567		e.e.EncodeInt(v)
1568	case uint:
1569		e.e.EncodeUint(uint64(v))
1570	case uint8:
1571		e.e.EncodeUint(uint64(v))
1572	case uint16:
1573		e.e.EncodeUint(uint64(v))
1574	case uint32:
1575		e.e.EncodeUint(uint64(v))
1576	case uint64:
1577		e.e.EncodeUint(v)
1578	case uintptr:
1579		e.e.EncodeUint(uint64(v))
1580	case float32:
1581		e.e.EncodeFloat32(v)
1582	case float64:
1583		e.e.EncodeFloat64(v)
1584	case time.Time:
1585		e.e.EncodeTime(v)
1586	case []uint8:
1587		e.e.EncodeStringBytesRaw(v)
1588
1589	case *Raw:
1590		e.rawBytes(*v)
1591
1592	case *string:
1593		if e.h.StringToRaw {
1594			e.e.EncodeStringBytesRaw(bytesView(*v))
1595		} else {
1596			e.e.EncodeStringEnc(cUTF8, *v)
1597		}
1598	case *bool:
1599		e.e.EncodeBool(*v)
1600	case *int:
1601		e.e.EncodeInt(int64(*v))
1602	case *int8:
1603		e.e.EncodeInt(int64(*v))
1604	case *int16:
1605		e.e.EncodeInt(int64(*v))
1606	case *int32:
1607		e.e.EncodeInt(int64(*v))
1608	case *int64:
1609		e.e.EncodeInt(*v)
1610	case *uint:
1611		e.e.EncodeUint(uint64(*v))
1612	case *uint8:
1613		e.e.EncodeUint(uint64(*v))
1614	case *uint16:
1615		e.e.EncodeUint(uint64(*v))
1616	case *uint32:
1617		e.e.EncodeUint(uint64(*v))
1618	case *uint64:
1619		e.e.EncodeUint(*v)
1620	case *uintptr:
1621		e.e.EncodeUint(uint64(*v))
1622	case *float32:
1623		e.e.EncodeFloat32(*v)
1624	case *float64:
1625		e.e.EncodeFloat64(*v)
1626	case *time.Time:
1627		e.e.EncodeTime(*v)
1628
1629	case *[]uint8:
1630		e.e.EncodeStringBytesRaw(*v)
1631
1632	default:
1633		if v, ok := iv.(Selfer); ok {
1634			v.CodecEncodeSelf(e)
1635		} else if !fastpathEncodeTypeSwitch(iv, e) {
1636			// checkfastpath=true (not false), as underlying slice/map type may be fast-path
1637			e.encodeValue(reflect.ValueOf(iv), nil, true)
1638		}
1639	}
1640}
1641
1642func (e *Encoder) encodeValue(rv reflect.Value, fn *codecFn, checkFastpath bool) {
1643	// if a valid fn is passed, it MUST BE for the dereferenced type of rv
1644	var sptr uintptr
1645	var rvp reflect.Value
1646	var rvpValid bool
1647TOP:
1648	switch rv.Kind() {
1649	case reflect.Ptr:
1650		if rv.IsNil() {
1651			e.e.EncodeNil()
1652			return
1653		}
1654		rvpValid = true
1655		rvp = rv
1656		rv = rv.Elem()
1657		if e.h.CheckCircularRef && rv.Kind() == reflect.Struct {
1658			// TODO: Movable pointers will be an issue here. Future problem.
1659			sptr = rv.UnsafeAddr()
1660			break TOP
1661		}
1662		goto TOP
1663	case reflect.Interface:
1664		if rv.IsNil() {
1665			e.e.EncodeNil()
1666			return
1667		}
1668		rv = rv.Elem()
1669		goto TOP
1670	case reflect.Slice, reflect.Map:
1671		if rv.IsNil() {
1672			e.e.EncodeNil()
1673			return
1674		}
1675	case reflect.Invalid, reflect.Func:
1676		e.e.EncodeNil()
1677		return
1678	}
1679
1680	if sptr != 0 && (&e.ci).add(sptr) {
1681		e.errorf("circular reference found: # %d", sptr)
1682	}
1683
1684	if fn == nil {
1685		rt := rv.Type()
1686		// always pass checkCodecSelfer=true, in case T or ****T is passed, where *T is a Selfer
1687		fn = e.h.fn(rt, checkFastpath, true)
1688	}
1689	if fn.i.addrE {
1690		if rvpValid {
1691			fn.fe(e, &fn.i, rvp)
1692		} else if rv.CanAddr() {
1693			fn.fe(e, &fn.i, rv.Addr())
1694		} else {
1695			rv2 := reflect.New(rv.Type())
1696			rv2.Elem().Set(rv)
1697			fn.fe(e, &fn.i, rv2)
1698		}
1699	} else {
1700		fn.fe(e, &fn.i, rv)
1701	}
1702	if sptr != 0 {
1703		(&e.ci).remove(sptr)
1704	}
1705}
1706
1707// func (e *Encoder) marshal(bs []byte, fnerr error, asis bool, c charEncoding) {
1708// 	if fnerr != nil {
1709// 		panic(fnerr)
1710// 	}
1711// 	if bs == nil {
1712// 		e.e.EncodeNil()
1713// 	} else if asis {
1714// 		e.asis(bs)
1715// 	} else {
1716// 		e.e.EncodeStringBytesRaw(bs)
1717// 	}
1718// }
1719
1720func (e *Encoder) marshalUtf8(bs []byte, fnerr error) {
1721	if fnerr != nil {
1722		panic(fnerr)
1723	}
1724	if bs == nil {
1725		e.e.EncodeNil()
1726	} else {
1727		e.e.EncodeStringEnc(cUTF8, stringView(bs))
1728	}
1729}
1730
1731func (e *Encoder) marshalAsis(bs []byte, fnerr error) {
1732	if fnerr != nil {
1733		panic(fnerr)
1734	}
1735	if bs == nil {
1736		e.e.EncodeNil()
1737	} else {
1738		e.asis(bs)
1739	}
1740}
1741
1742func (e *Encoder) marshalRaw(bs []byte, fnerr error) {
1743	if fnerr != nil {
1744		panic(fnerr)
1745	}
1746	if bs == nil {
1747		e.e.EncodeNil()
1748	} else {
1749		e.e.EncodeStringBytesRaw(bs)
1750	}
1751}
1752
1753func (e *Encoder) asis(v []byte) {
1754	if e.isas {
1755		e.as.EncodeAsis(v)
1756	} else {
1757		e.w.writeb(v)
1758	}
1759}
1760
1761func (e *Encoder) rawBytes(vv Raw) {
1762	v := []byte(vv)
1763	if !e.h.Raw {
1764		e.errorf("Raw values cannot be encoded: %v", v)
1765	}
1766	e.asis(v)
1767}
1768
1769func (e *Encoder) wrapErr(v interface{}, err *error) {
1770	*err = encodeError{codecError{name: e.hh.Name(), err: v}}
1771}
1772
1773func encStructFieldKey(encName string, ee encDriver, w *encWriterSwitch,
1774	keyType valueType, encNameAsciiAlphaNum bool, js bool) {
1775	var m must
1776	// use if-else-if, not switch (which compiles to binary-search)
1777	// since keyType is typically valueTypeString, branch prediction is pretty good.
1778	if keyType == valueTypeString {
1779		if js && encNameAsciiAlphaNum { // keyType == valueTypeString
1780			// w.writen1('"')
1781			// w.writestr(encName)
1782			// w.writen1('"')
1783			// ----
1784			// w.writestr(`"` + encName + `"`)
1785			// ----
1786			// do concat myself, so it is faster than the generic string concat
1787			b := make([]byte, len(encName)+2)
1788			copy(b[1:], encName)
1789			b[0] = '"'
1790			b[len(b)-1] = '"'
1791			w.writeb(b)
1792		} else { // keyType == valueTypeString
1793			ee.EncodeStringEnc(cUTF8, encName)
1794		}
1795	} else if keyType == valueTypeInt {
1796		ee.EncodeInt(m.Int(strconv.ParseInt(encName, 10, 64)))
1797	} else if keyType == valueTypeUint {
1798		ee.EncodeUint(m.Uint(strconv.ParseUint(encName, 10, 64)))
1799	} else if keyType == valueTypeFloat {
1800		ee.EncodeFloat64(m.Float(strconv.ParseFloat(encName, 64)))
1801	}
1802}
1803
1804// func encStringAsRawBytesMaybe(ee encDriver, s string, stringToRaw bool) {
1805// 	if stringToRaw {
1806// 		ee.EncodeStringBytesRaw(bytesView(s))
1807// 	} else {
1808// 		ee.EncodeStringEnc(cUTF8, s)
1809// 	}
1810// }
1811