Ver código fonte

codec: streamline library: refactor sendContainerState and clean up handle-specific test flags

refactor sendContainerState to be methods on (en|de)cDriver

    Basically, move from sendContainerState to roughly
    (Read|Write)(Array|Map)(Elem)(Key|Value)(Start|End)

Support IndefiniteLength in cbor during encoding

test: make testUseIoEncDec an int flag, which specifies buffer size

    It defaults to -1, which means do not use io.
    if >= 0, then we use io.Reader/io.Writer with a buffer in front.

test: do not use flags for handle-specific configuration

    Instead, create suite groups for each handle, and modify the configuration
    for the test group, and execute the handle-specific tests.
Ugorji Nwoke 8 anos atrás
pai
commit
c3953defa8

+ 8 - 5
codec/binc.go

@@ -61,7 +61,8 @@ type bincEncDriver struct {
 	m map[string]uint16 // symbols
 	b [scratchByteArrayLen]byte
 	s uint16 // symbols sequencer
-	encNoSeparator
+	// encNoSeparator
+	encDriverNoopContainerWriter
 }
 
 func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
@@ -195,11 +196,11 @@ func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
 	e.w.writen1(xtag)
 }
 
-func (e *bincEncDriver) EncodeArrayStart(length int) {
+func (e *bincEncDriver) WriteArrayStart(length int) {
 	e.encLen(bincVdArray<<4, uint64(length))
 }
 
-func (e *bincEncDriver) EncodeMapStart(length int) {
+func (e *bincEncDriver) WriteMapStart(length int) {
 	e.encLen(bincVdMap<<4, uint64(length))
 }
 
@@ -332,13 +333,14 @@ type bincDecDriver struct {
 	bd     byte
 	vd     byte
 	vs     byte
-	noStreamingCodec
-	decNoSeparator
+	// noStreamingCodec
+	// decNoSeparator
 	b [scratchByteArrayLen]byte
 
 	// linear searching on this slice is ok,
 	// because we typically expect < 32 symbols in each stream.
 	s []bincDecSymbol
+	decDriverNoopContainerReader
 }
 
 func (d *bincDecDriver) readNextBd() {
@@ -909,6 +911,7 @@ func (d *bincDecDriver) DecodeNaked() {
 type BincHandle struct {
 	BasicHandle
 	binaryEncodingType
+	noElemSeparators
 }
 
 func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {

+ 32 - 6
codec/cbor.go

@@ -61,7 +61,8 @@ const (
 
 type cborEncDriver struct {
 	noBuiltInTypes
-	encNoSeparator
+	encDriverNoopContainerWriter
+	// encNoSeparator
 	e *Encoder
 	w encWriter
 	h *CborHandle
@@ -143,12 +144,32 @@ func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
 	}
 }
 
-func (e *cborEncDriver) EncodeArrayStart(length int) {
-	e.encLen(cborBaseArray, length)
+func (e *cborEncDriver) WriteArrayStart(length int) {
+	if e.h.IndefiniteLength {
+		e.w.writen1(cborBdIndefiniteArray)
+	} else {
+		e.encLen(cborBaseArray, length)
+	}
 }
 
-func (e *cborEncDriver) EncodeMapStart(length int) {
-	e.encLen(cborBaseMap, length)
+func (e *cborEncDriver) WriteMapStart(length int) {
+	if e.h.IndefiniteLength {
+		e.w.writen1(cborBdIndefiniteMap)
+	} else {
+		e.encLen(cborBaseMap, length)
+	}
+}
+
+func (e *cborEncDriver) WriteMapEnd() {
+	if e.h.IndefiniteLength {
+		e.w.writen1(cborBdBreak)
+	}
+}
+
+func (e *cborEncDriver) WriteArrayEnd() {
+	if e.h.IndefiniteLength {
+		e.w.writen1(cborBdBreak)
+	}
 }
 
 func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
@@ -180,7 +201,8 @@ type cborDecDriver struct {
 	bdRead bool
 	bd     byte
 	noBuiltInTypes
-	decNoSeparator
+	// decNoSeparator
+	decDriverNoopContainerReader
 }
 
 func (d *cborDecDriver) readNextBd() {
@@ -577,7 +599,11 @@ func (d *cborDecDriver) DecodeNaked() {
 //
 type CborHandle struct {
 	binaryEncodingType
+	noElemSeparators
 	BasicHandle
+
+	// IndefiniteLength=true, means that we encode using indefinitelength
+	IndefiniteLength bool
 }
 
 func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {

+ 5 - 15
codec/codec_test.go

@@ -42,11 +42,11 @@ import (
 
 func init() {
 	testPreInitFns = append(testPreInitFns, testInit)
-	fmt.Printf("sizeof: Decoder: %v, Encoder: %v, decNaked: %v\n",
-		reflect.TypeOf((*Decoder)(nil)).Elem().Size(),
-		reflect.TypeOf((*Encoder)(nil)).Elem().Size(),
-		reflect.TypeOf((*decNaked)(nil)).Elem().Size(),
-	)
+	// fmt.Printf("sizeof: Decoder: %v, Encoder: %v, decNaked: %v\n",
+	// 	reflect.TypeOf((*Decoder)(nil)).Elem().Size(),
+	// 	reflect.TypeOf((*Encoder)(nil)).Elem().Size(),
+	// 	reflect.TypeOf((*decNaked)(nil)).Elem().Size(),
+	// )
 }
 
 // make this a mapbyslice
@@ -349,18 +349,8 @@ func testInit() {
 		bh.CheckCircularRef = testCheckCircRef
 		bh.StructToArray = testStructToArray
 		bh.MaxInitLen = testMaxInitLen
-		// mostly doing this for binc
-		if testWriteNoSymbols {
-			bh.AsSymbols = AsSymbolNone
-		} else {
-			bh.AsSymbols = AsSymbolAll
-		}
 	}
 
-	testJsonH.Indent = int8(testJsonIndent)
-	testJsonH.HTMLCharsAsIs = testJsonHTMLCharsAsIs
-	testJsonH.PreferFloat = testJsonPreferFloat
-
 	testMsgpackH.RawToString = true
 
 	// testMsgpackH.AddExt(byteSliceTyp, 0, testMsgpackH.BinaryEncodeExt, testMsgpackH.BinaryDecodeExt)

+ 67 - 77
codec/decode.go

@@ -104,17 +104,31 @@ type decDriver interface {
 	// decodeExt will decode into a *RawExt or into an extension.
 	DecodeExt(v interface{}, xtag uint64, ext Ext) (realxtag uint64)
 	// decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte)
-	ReadMapStart() int
 	ReadArrayStart() int
+	ReadArrayElem()
+	ReadArrayEnd()
+	ReadMapStart() int
+	ReadMapElemKey()
+	ReadMapElemValue()
+	ReadMapEnd()
 
 	reset()
 	uncacheRead()
 }
 
-type decNoSeparator struct {
-}
+// type decNoSeparator struct {}
+// func (_ decNoSeparator) ReadEnd() {}
+
+type decDriverNoopContainerReader struct{}
 
-func (_ decNoSeparator) ReadEnd() {}
+func (_ decDriverNoopContainerReader) ReadArrayStart() (v int) { return }
+func (_ decDriverNoopContainerReader) ReadArrayElem()          {}
+func (_ decDriverNoopContainerReader) ReadArrayEnd()           {}
+func (_ decDriverNoopContainerReader) ReadMapStart() (v int)   { return }
+func (_ decDriverNoopContainerReader) ReadMapElemKey()         {}
+func (_ decDriverNoopContainerReader) ReadMapElemValue()       {}
+func (_ decDriverNoopContainerReader) ReadMapEnd()             {}
+func (_ decDriverNoopContainerReader) CheckBreak() (v bool)    { return }
 
 // func (_ decNoSeparator) uncacheRead() {}
 
@@ -363,17 +377,17 @@ func (z *bufioDecReader) readb(bs []byte) {
 	}
 }
 
-func (z *bufioDecReader) readn1eof() (b uint8, eof bool) {
-	b, err := z.ReadByte()
-	if err != nil {
-		if err == io.EOF {
-			eof = true
-		} else {
-			panic(err)
-		}
-	}
-	return
-}
+// func (z *bufioDecReader) readn1eof() (b uint8, eof bool) {
+// 	b, err := z.ReadByte()
+// 	if err != nil {
+// 		if err == io.EOF {
+// 			eof = true
+// 		} else {
+// 			panic(err)
+// 		}
+// 	}
+// 	return
+// }
 
 func (z *bufioDecReader) readn1() (b uint8) {
 	b, err := z.ReadByte()
@@ -1181,15 +1195,13 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 
 	fti := f.ti
 	dd := d.d
-	cr := d.cr
+	elemsep := d.hh.hasElemSeparators()
 	sfn := structFieldNode{v: rv, update: true}
 	ctyp := dd.ContainerType()
 	if ctyp == valueTypeMap {
 		containerLen := dd.ReadMapStart()
 		if containerLen == 0 {
-			if cr != nil {
-				cr.sendContainerState(containerMapEnd)
-			}
+			dd.ReadMapEnd()
 			return
 		}
 		tisfi := fti.sfi
@@ -1197,14 +1209,14 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 
 		for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
 			// rvkencname := dd.DecodeString()
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				dd.ReadMapElemKey()
 			}
 			rvkencnameB := dd.DecodeStringAsBytes()
 			rvkencname := stringView(rvkencnameB)
 			// rvksi := ti.getForEncName(rvkencname)
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				dd.ReadMapElemValue()
 			}
 			if k := fti.indexForEncName(rvkencname); k > -1 {
 				si := tisfi[k]
@@ -1218,15 +1230,11 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 			}
 			// keepAlive4StringView(rvkencnameB) // maintain ref 4 stringView // not needed, as reference is outside loop
 		}
-		if cr != nil {
-			cr.sendContainerState(containerMapEnd)
-		}
+		dd.ReadMapEnd()
 	} else if ctyp == valueTypeArray {
 		containerLen := dd.ReadArrayStart()
 		if containerLen == 0 {
-			if cr != nil {
-				cr.sendContainerState(containerArrayEnd)
-			}
+			dd.ReadArrayEnd()
 			return
 		}
 		// Not much gain from doing it two ways for array.
@@ -1236,8 +1244,8 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 			if (hasLen && j == containerLen) || (!hasLen && dd.CheckBreak()) {
 				break
 			}
-			if cr != nil {
-				cr.sendContainerState(containerArrayElem)
+			if elemsep {
+				dd.ReadArrayElem()
 			}
 			if dd.TryDecodeAsNil() {
 				si.setToZeroValue(rv)
@@ -1248,15 +1256,13 @@ func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 		if containerLen > len(fti.sfip) {
 			// read remaining values and throw away
 			for j := len(fti.sfip); j < containerLen; j++ {
-				if cr != nil {
-					cr.sendContainerState(containerArrayElem)
+				if elemsep {
+					dd.ReadArrayElem()
 				}
 				d.structFieldNotFound(j, "")
 			}
 		}
-		if cr != nil {
-			cr.sendContainerState(containerArrayEnd)
-		}
+		dd.ReadArrayEnd()
 	} else {
 		d.error(onlyMapOrArrayCanDecodeIntoStructErr)
 		return
@@ -1492,16 +1498,14 @@ func (d *Decoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
 	dd := d.d
 	containerLen := dd.ReadMapStart()
-	cr := d.cr
+	elemsep := d.hh.hasElemSeparators()
 	ti := f.ti
 	if rv.IsNil() {
 		rv.Set(makeMapReflect(ti.rt, containerLen))
 	}
 
 	if containerLen == 0 {
-		if cr != nil {
-			cr.sendContainerState(containerMapEnd)
-		}
+		dd.ReadMapEnd()
 		return
 	}
 
@@ -1550,13 +1554,13 @@ func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
 	hasLen := containerLen > 0
 	var kstrbs []byte
 	for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
-		if cr != nil {
-			cr.sendContainerState(containerMapKey)
+		if elemsep {
+			dd.ReadMapElemKey()
 		}
 		// if a nil key, just ignore the mapped value and continue
 		if dd.TryDecodeAsNil() {
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				dd.ReadMapElemValue()
 			}
 			d.swallow()
 			continue
@@ -1591,8 +1595,8 @@ func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
 			}
 		}
 
-		if cr != nil {
-			cr.sendContainerState(containerMapValue)
+		if elemsep {
+			dd.ReadMapElemValue()
 		}
 
 		// Brittle, but OK per TryDecodeAsNil() contract.
@@ -1668,9 +1672,7 @@ func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
 		// }
 	}
 
-	if cr != nil {
-		cr.sendContainerState(containerMapEnd)
-	}
+	dd.ReadMapEnd()
 }
 
 // decNaked is used to keep track of the primitives decoded.
@@ -1799,7 +1801,7 @@ type Decoder struct {
 	ri ioDecReader
 	bi bufioDecReader
 
-	cr containerStateRecv
+	// cr containerStateRecv
 
 	n   *decNaked
 	nsp *sync.Pool
@@ -1852,7 +1854,7 @@ func newDecoder(h Handle) *Decoder {
 		d.is = make(map[string]string, 32)
 	}
 	d.d = h.newDecDriver(d)
-	d.cr, _ = d.d.(containerStateRecv)
+	// d.cr, _ = d.d.(containerStateRecv)
 	return d
 }
 
@@ -2012,37 +2014,33 @@ func (d *Decoder) swallow() {
 	if dd.TryDecodeAsNil() {
 		return
 	}
-	cr := d.cr
+	elemsep := d.hh.hasElemSeparators()
 	switch dd.ContainerType() {
 	case valueTypeMap:
 		containerLen := dd.ReadMapStart()
 		hasLen := containerLen >= 0
 		for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
 			// if clenGtEqualZero {if j >= containerLen {break} } else if dd.CheckBreak() {break}
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				dd.ReadMapElemKey()
 			}
 			d.swallow()
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				dd.ReadMapElemValue()
 			}
 			d.swallow()
 		}
-		if cr != nil {
-			cr.sendContainerState(containerMapEnd)
-		}
+		dd.ReadMapEnd()
 	case valueTypeArray:
 		containerLen := dd.ReadArrayStart()
 		hasLen := containerLen >= 0
 		for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
-			if cr != nil {
-				cr.sendContainerState(containerArrayElem)
+			if elemsep {
+				dd.ReadArrayElem()
 			}
 			d.swallow()
 		}
-		if cr != nil {
-			cr.sendContainerState(containerArrayEnd)
-		}
+		dd.ReadArrayEnd()
 	case valueTypeBytes:
 		dd.DecodeBytes(d.b[:], true)
 	case valueTypeString:
@@ -2389,29 +2387,21 @@ func (d *Decoder) decSliceHelperStart() (x decSliceHelper, clen int) {
 }
 
 func (x decSliceHelper) End() {
-	cr := x.d.cr
-	if cr == nil {
-		return
-	}
 	if x.array {
-		cr.sendContainerState(containerArrayEnd)
+		x.d.d.ReadArrayEnd()
 	} else {
-		cr.sendContainerState(containerMapEnd)
+		x.d.d.ReadMapEnd()
 	}
 }
 
 func (x decSliceHelper) ElemContainerState(index int) {
-	cr := x.d.cr
-	if cr == nil {
-		return
-	}
 	if x.array {
-		cr.sendContainerState(containerArrayElem)
+		x.d.d.ReadArrayElem()
 	} else {
 		if index%2 == 0 {
-			cr.sendContainerState(containerMapKey)
+			x.d.d.ReadMapElemKey()
 		} else {
-			cr.sendContainerState(containerMapValue)
+			x.d.d.ReadMapElemValue()
 		}
 	}
 }

+ 112 - 105
codec/encode.go

@@ -61,8 +61,13 @@ type encDriver interface {
 	// encodeExtPreamble(xtag byte, length int)
 	EncodeRawExt(re *RawExt, e *Encoder)
 	EncodeExt(v interface{}, xtag uint64, ext Ext, e *Encoder)
-	EncodeArrayStart(length int)
-	EncodeMapStart(length int)
+	WriteArrayStart(length int)
+	WriteArrayElem()
+	WriteArrayEnd()
+	WriteMapStart(length int)
+	WriteMapElemKey()
+	WriteMapElemValue()
+	WriteMapEnd()
 	EncodeString(c charEncoding, v string)
 	EncodeSymbol(v string)
 	EncodeStringBytes(c charEncoding, v []byte)
@@ -73,14 +78,6 @@ type encDriver interface {
 	reset()
 }
 
-type encDriverAsis interface {
-	EncodeAsis(v []byte)
-}
-
-type encNoSeparator struct{}
-
-func (_ encNoSeparator) EncodeEnd() {}
-
 type ioEncStringWriter interface {
 	WriteString(s string) (n int, err error)
 }
@@ -89,6 +86,23 @@ type ioEncFlusher interface {
 	Flush() error
 }
 
+type encDriverAsis interface {
+	EncodeAsis(v []byte)
+}
+
+// type encNoSeparator struct{}
+// func (_ encNoSeparator) EncodeEnd() {}
+
+type encDriverNoopContainerWriter struct{}
+
+func (_ encDriverNoopContainerWriter) WriteArrayStart(length int) {}
+func (_ encDriverNoopContainerWriter) WriteArrayElem()            {}
+func (_ encDriverNoopContainerWriter) WriteArrayEnd()             {}
+func (_ encDriverNoopContainerWriter) WriteMapStart(length int)   {}
+func (_ encDriverNoopContainerWriter) WriteMapElemKey()           {}
+func (_ encDriverNoopContainerWriter) WriteMapElemValue()         {}
+func (_ encDriverNoopContainerWriter) WriteMapEnd()               {}
+
 // type ioEncWriterWriter interface {
 // 	WriteByte(c byte) error
 // 	WriteString(s string) (n int, err error)
@@ -198,16 +212,16 @@ type ioEncWriter struct {
 	b  [8]byte
 }
 
-func (x *ioEncWriter) WriteByte(b byte) (err error) {
+func (z *ioEncWriter) WriteByte(b byte) (err error) {
 	// x.bs[0] = b
 	// _, err = x.ww.Write(x.bs[:])
-	var ba = [1]byte{b}
-	_, err = x.w.Write(ba[:])
+	z.b[0] = b
+	_, err = z.w.Write(z.b[:1])
 	return
 }
 
-func (x *ioEncWriter) WriteString(s string) (n int, err error) {
-	return x.w.Write(bytesView(s))
+func (z *ioEncWriter) WriteString(s string) (n int, err error) {
+	return z.w.Write(bytesView(s))
 }
 
 func (z *ioEncWriter) writeb(bs []byte) {
@@ -477,30 +491,31 @@ func (e *Encoder) kErr(f *codecFnInfo, rv reflect.Value) {
 
 func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 	ti := f.ti
+	ee := e.e
 	// array may be non-addressable, so we have to manage with care
 	//   (don't call rv.Bytes, rv.Slice, etc).
 	// E.g. type struct S{B [2]byte};
 	//   Encode(S{}) will bomb on "panic: slice of unaddressable array".
 	if f.seq != seqTypeArray {
 		if rv.IsNil() {
-			e.e.EncodeNil()
+			ee.EncodeNil()
 			return
 		}
 		// If in this method, then there was no extension function defined.
 		// So it's okay to treat as []byte.
 		if ti.rtid == uint8SliceTypId {
-			e.e.EncodeStringBytes(c_RAW, rv.Bytes())
+			ee.EncodeStringBytes(c_RAW, rv.Bytes())
 			return
 		}
 	}
-	cr := e.cr
+	elemsep := e.hh.hasElemSeparators()
 	rtelem := ti.rt.Elem()
 	l := rv.Len()
 	if ti.rtid == uint8SliceTypId || rtelem.Kind() == reflect.Uint8 {
 		switch f.seq {
 		case seqTypeArray:
 			if rv.CanAddr() {
-				e.e.EncodeStringBytes(c_RAW, rv.Slice(0, l).Bytes())
+				ee.EncodeStringBytes(c_RAW, rv.Slice(0, l).Bytes())
 			} else {
 				var bs []byte
 				if l <= cap(e.b) {
@@ -509,11 +524,11 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 					bs = make([]byte, l)
 				}
 				reflect.Copy(reflect.ValueOf(bs), rv)
-				e.e.EncodeStringBytes(c_RAW, bs)
+				ee.EncodeStringBytes(c_RAW, bs)
 			}
 			return
 		case seqTypeSlice:
-			e.e.EncodeStringBytes(c_RAW, rv.Bytes())
+			ee.EncodeStringBytes(c_RAW, rv.Bytes())
 			return
 		}
 	}
@@ -526,7 +541,7 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 		for i := 0; i < l; i++ {
 			bs = append(bs, <-ch)
 		}
-		e.e.EncodeStringBytes(c_RAW, bs)
+		ee.EncodeStringBytes(c_RAW, bs)
 		return
 	}
 
@@ -535,9 +550,9 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 			e.errorf("mapBySlice requires even slice length, but got %v", l)
 			return
 		}
-		e.e.EncodeMapStart(l / 2)
+		ee.WriteMapStart(l / 2)
 	} else {
-		e.e.EncodeArrayStart(l)
+		ee.WriteArrayStart(l)
 	}
 
 	if l > 0 {
@@ -556,15 +571,15 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 		}
 		// TODO: Consider perf implication of encoding odd index values as symbols if type is string
 		for j := 0; j < l; j++ {
-			if cr != nil {
+			if elemsep {
 				if ti.mbs {
 					if j%2 == 0 {
-						cr.sendContainerState(containerMapKey)
+						ee.WriteMapElemKey()
 					} else {
-						cr.sendContainerState(containerMapValue)
+						ee.WriteMapElemValue()
 					}
 				} else {
-					cr.sendContainerState(containerArrayElem)
+					ee.WriteArrayElem()
 				}
 			}
 			if f.seq == seqTypeChan {
@@ -575,7 +590,7 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 						e.encodeValue(rv2, fn, true)
 					}
 				} else {
-					e.e.EncodeNil() // WE HAVE TO DO SOMETHING, so nil if nothing received.
+					ee.EncodeNil() // WE HAVE TO DO SOMETHING, so nil if nothing received.
 				}
 			} else {
 				if useLookupRecognizedTypes && recognizedVtyp {
@@ -587,18 +602,16 @@ func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
 		}
 	}
 
-	if cr != nil {
-		if ti.mbs {
-			cr.sendContainerState(containerMapEnd)
-		} else {
-			cr.sendContainerState(containerArrayEnd)
-		}
+	if ti.mbs {
+		ee.WriteMapEnd()
+	} else {
+		ee.WriteArrayEnd()
 	}
 }
 
 func (e *Encoder) kStructNoOmitempty(f *codecFnInfo, rv reflect.Value) {
 	fti := f.ti
-	cr := e.cr
+	elemsep := e.hh.hasElemSeparators()
 	tisfi := fti.sfip
 	toMap := !(fti.toArray || e.h.StructToArray)
 	if toMap {
@@ -608,10 +621,10 @@ func (e *Encoder) kStructNoOmitempty(f *codecFnInfo, rv reflect.Value) {
 
 	sfn := structFieldNode{v: rv, update: false}
 	if toMap {
-		ee.EncodeMapStart(len(tisfi))
+		ee.WriteMapStart(len(tisfi))
 		// asSymbols := e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
 		asSymbols := e.h.AsSymbols == AsSymbolDefault || e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
-		if cr == nil {
+		if !elemsep {
 			for _, si := range tisfi {
 				if asSymbols {
 					ee.EncodeSymbol(si.encName)
@@ -622,36 +635,36 @@ func (e *Encoder) kStructNoOmitempty(f *codecFnInfo, rv reflect.Value) {
 			}
 		} else {
 			for _, si := range tisfi {
-				cr.sendContainerState(containerMapKey)
+				ee.WriteMapElemKey()
 				if asSymbols {
 					ee.EncodeSymbol(si.encName)
 				} else {
 					ee.EncodeString(c_UTF8, si.encName)
 				}
-				cr.sendContainerState(containerMapValue)
+				ee.WriteMapElemValue()
 				e.encodeValue(sfn.field(si), nil, true)
 			}
-			cr.sendContainerState(containerMapEnd)
 		}
+		ee.WriteMapEnd()
 	} else {
-		ee.EncodeArrayStart(len(tisfi))
-		if cr == nil {
+		ee.WriteArrayStart(len(tisfi))
+		if !elemsep {
 			for _, si := range tisfi {
 				e.encodeValue(sfn.field(si), nil, true)
 			}
 		} else {
 			for _, si := range tisfi {
-				cr.sendContainerState(containerArrayElem)
+				ee.WriteArrayElem()
 				e.encodeValue(sfn.field(si), nil, true)
 			}
-			cr.sendContainerState(containerArrayEnd)
 		}
+		ee.WriteArrayEnd()
 	}
 }
 
 func (e *Encoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 	fti := f.ti
-	cr := e.cr
+	elemsep := e.hh.hasElemSeparators()
 	tisfi := fti.sfip
 	toMap := !(fti.toArray || e.h.StructToArray)
 	// if toMap, use the sorted array. If toArray, use unsorted array (to match sequence in struct)
@@ -722,10 +735,10 @@ func (e *Encoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 	}
 
 	if toMap {
-		ee.EncodeMapStart(newlen)
+		ee.WriteMapStart(newlen)
 		// asSymbols := e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
 		asSymbols := e.h.AsSymbols == AsSymbolDefault || e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
-		if cr == nil {
+		if !elemsep {
 			for j := 0; j < newlen; j++ {
 				kv = fkvs[j]
 				if asSymbols {
@@ -738,30 +751,30 @@ func (e *Encoder) kStruct(f *codecFnInfo, rv reflect.Value) {
 		} else {
 			for j := 0; j < newlen; j++ {
 				kv = fkvs[j]
-				cr.sendContainerState(containerMapKey)
+				ee.WriteMapElemKey()
 				if asSymbols {
 					ee.EncodeSymbol(kv.v)
 				} else {
 					ee.EncodeString(c_UTF8, kv.v)
 				}
-				cr.sendContainerState(containerMapValue)
+				ee.WriteMapElemValue()
 				e.encodeValue(kv.r, nil, true)
 			}
-			cr.sendContainerState(containerMapEnd)
 		}
+		ee.WriteMapEnd()
 	} else {
-		ee.EncodeArrayStart(newlen)
-		if cr == nil {
+		ee.WriteArrayStart(newlen)
+		if !elemsep {
 			for j := 0; j < newlen; j++ {
 				e.encodeValue(fkvs[j].r, nil, true)
 			}
 		} else {
 			for j := 0; j < newlen; j++ {
-				cr.sendContainerState(containerArrayElem)
+				ee.WriteArrayElem()
 				e.encodeValue(fkvs[j].r, nil, true)
 			}
-			cr.sendContainerState(containerArrayEnd)
 		}
+		ee.WriteArrayEnd()
 	}
 
 	// do not use defer. Instead, use explicit pool return at end of function.
@@ -780,12 +793,10 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
 	}
 
 	l := rv.Len()
-	ee.EncodeMapStart(l)
-	cr := e.cr
+	ee.WriteMapStart(l)
+	elemsep := e.hh.hasElemSeparators()
 	if l == 0 {
-		if cr != nil {
-			cr.sendContainerState(containerMapEnd)
-		}
+		ee.WriteMapEnd()
 		return
 	}
 	var asSymbols bool
@@ -814,9 +825,7 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
 
 	if e.h.Canonical {
 		e.kMapCanonical(rtkey, rv, mks, valFn, asSymbols)
-		if cr != nil {
-			cr.sendContainerState(containerMapEnd)
-		}
+		ee.WriteMapEnd()
 		return
 	}
 
@@ -843,8 +852,8 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
 LABEL1:
 	recognizedVtyp = useLookupRecognizedTypes && isRecognizedRtidOrPtr(rtvalid)
 	for j := range mks {
-		if cr != nil {
-			cr.sendContainerState(containerMapKey)
+		if elemsep {
+			ee.WriteMapElemKey()
 		}
 		if keyTypeIsString {
 			if asSymbols {
@@ -857,8 +866,8 @@ LABEL1:
 		} else {
 			e.encodeValue(mks[j], keyFn, true)
 		}
-		if cr != nil {
-			cr.sendContainerState(containerMapValue)
+		if elemsep {
+			ee.WriteMapElemValue()
 		}
 		if useLookupRecognizedTypes && recognizedVtyp {
 			e.encode(rv2i(rv.MapIndex(mks[j])))
@@ -866,14 +875,12 @@ LABEL1:
 			e.encodeValue(rv.MapIndex(mks[j]), valFn, true)
 		}
 	}
-	if cr != nil {
-		cr.sendContainerState(containerMapEnd)
-	}
+	ee.WriteMapEnd()
 }
 
 func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []reflect.Value, valFn *codecFn, asSymbols bool) {
 	ee := e.e
-	cr := e.cr
+	elemsep := e.hh.hasElemSeparators()
 	// we previously did out-of-band if an extension was registered.
 	// This is not necessary, as the natural kind is sufficient for ordering.
 
@@ -887,12 +894,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 	// 	}
 	// 	sort.Sort(bytesRvSlice(mksv))
 	// 	for i := range mksv {
-	// 		if cr != nil {
-	// 			cr.sendContainerState(containerMapKey)
+	// 		if elemsep {
+	// 			ee.WriteMapElemKey()
 	// 		}
 	// 		ee.EncodeStringBytes(c_RAW, mksv[i].v)
-	// 		if cr != nil {
-	// 			cr.sendContainerState(containerMapValue)
+	// 		if elemsep {
+	// 			ee.WriteMapElemValue()
 	// 		}
 	// 		e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 	// 	}
@@ -909,12 +916,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(boolRvSlice(mksv))
 		for i := range mksv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			ee.EncodeBool(mksv[i].v)
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 		}
@@ -927,16 +934,16 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(stringRvSlice(mksv))
 		for i := range mksv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			if asSymbols {
 				ee.EncodeSymbol(mksv[i].v)
 			} else {
 				ee.EncodeString(c_UTF8, mksv[i].v)
 			}
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 		}
@@ -949,12 +956,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(uintRvSlice(mksv))
 		for i := range mksv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			ee.EncodeUint(mksv[i].v)
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 		}
@@ -967,12 +974,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(intRvSlice(mksv))
 		for i := range mksv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			ee.EncodeInt(mksv[i].v)
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 		}
@@ -985,12 +992,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(floatRvSlice(mksv))
 		for i := range mksv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			ee.EncodeFloat32(float32(mksv[i].v))
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 		}
@@ -1003,12 +1010,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(floatRvSlice(mksv))
 		for i := range mksv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			ee.EncodeFloat64(mksv[i].v)
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
 		}
@@ -1027,12 +1034,12 @@ func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []refl
 		}
 		sort.Sort(bytesRvSlice(mksbv))
 		for j := range mksbv {
-			if cr != nil {
-				cr.sendContainerState(containerMapKey)
+			if elemsep {
+				ee.WriteMapElemKey()
 			}
 			e.asis(mksbv[j].v)
-			if cr != nil {
-				cr.sendContainerState(containerMapValue)
+			if elemsep {
+				ee.WriteMapElemValue()
 			}
 			e.encodeValue(rv.MapIndex(mksbv[j].r), valFn, true)
 		}
@@ -1058,7 +1065,7 @@ type Encoder struct {
 	wb bytesEncWriter
 	bw bufio.Writer
 
-	cr containerStateRecv
+	// cr containerStateRecv
 	as encDriverAsis
 	// ---- cpu cache line boundary?
 
@@ -1094,7 +1101,7 @@ func newEncoder(h Handle) *Encoder {
 	e := &Encoder{hh: h, h: h.getBasicHandle()}
 	e.e = h.newEncDriver(e)
 	e.as, _ = e.e.(encDriverAsis)
-	e.cr, _ = e.e.(containerStateRecv)
+	// e.cr, _ = e.e.(containerStateRecv)
 	return e
 }
 

Diferenças do arquivo suprimidas por serem muito extensas
+ 222 - 292
codec/fast-path.generated.go


+ 24 - 24
codec/fast-path.go.tmpl

@@ -165,33 +165,33 @@ func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv r
 	}
 }
 func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, e *Encoder) {
-	ee, cr := e.e, e.cr 
-	ee.EncodeArrayStart(len(v))
+	ee, esep := e.e, e.hh.hasElemSeparators()
+	ee.WriteArrayStart(len(v))
 	for _, v2 := range v {
-		if cr != nil { cr.sendContainerState(containerArrayElem) }
+		if esep { ee.WriteArrayElem() }
 		{{ encmd .Elem "v2"}}
 	}
-	if cr != nil { cr.sendContainerState(containerArrayEnd) }{{/* ee.EncodeEnd() */}}
+	ee.WriteArrayEnd()
 }
 
 func (_ fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, e *Encoder) {
-	ee, cr := e.e, e.cr 
+	ee, esep := e.e, e.hh.hasElemSeparators()
 	if len(v)%2 == 1 {
 		e.errorf("mapBySlice requires even slice length, but got %v", len(v))
 		return
 	}
-	ee.EncodeMapStart(len(v) / 2)
+	ee.WriteMapStart(len(v) / 2)
 	for j, v2 := range v {
-		if cr != nil {
+		if esep {
 			if j%2 == 0 {
-				cr.sendContainerState(containerMapKey)
+				ee.WriteMapElemKey()
 			} else {
-				cr.sendContainerState(containerMapValue)
+				ee.WriteMapElemValue()
 			}
 		}
 		{{ encmd .Elem "v2"}}
 	}
-	if cr != nil { cr.sendContainerState(containerMapEnd) }
+	ee.WriteMapEnd()
 }
 
 {{end}}{{end}}{{end}}
@@ -202,8 +202,8 @@ func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv r
 	fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), e)
 }
 func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, e *Encoder) {
-	ee, cr := e.e, e.cr 
-	ee.EncodeMapStart(len(v))
+	ee, esep := e.e, e.hh.hasElemSeparators() 
+	ee.WriteMapStart(len(v))
 	{{if eq .MapKey "string"}}asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
 	{{end}}if e.h.Canonical {
 		{{if eq .MapKey "interface{}"}}{{/* out of band 
@@ -222,9 +222,9 @@ func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Ele
 		}
 		sort.Sort(bytesISlice(v2))
 		for j := range v2 {
-			if cr != nil { cr.sendContainerState(containerMapKey) }
+			if esep { ee.WriteMapElemKey() }
 			e.asis(v2[j].v)
-			if cr != nil { cr.sendContainerState(containerMapValue) }
+			if esep { ee.WriteMapElemValue() }
 			e.encode(v[v2[j].i])
 		} {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v))
 		var i int 
@@ -234,28 +234,28 @@ func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Ele
 		}
 		sort.Sort({{ sorttype .MapKey false}}(v2))
 		for _, k2 := range v2 {
-			if cr != nil { cr.sendContainerState(containerMapKey) }
+			if esep { ee.WriteMapElemKey() }
 			{{if eq .MapKey "string"}}if asSymbols {
 				ee.EncodeSymbol(k2)
 			} else {
 				ee.EncodeString(c_UTF8, k2)
 			}{{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
-			if cr != nil { cr.sendContainerState(containerMapValue) }
+			if esep { ee.WriteMapElemValue() }
 			{{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
 		} {{end}}
 	} else {
 		for k2, v2 := range v {
-			if cr != nil { cr.sendContainerState(containerMapKey) }
+			if esep { ee.WriteMapElemKey() }
 			{{if eq .MapKey "string"}}if asSymbols {
 				ee.EncodeSymbol(k2)
 			} else {
 				ee.EncodeString(c_UTF8, k2)
 			}{{else}}{{ encmd .MapKey "k2"}}{{end}}
-			if cr != nil { cr.sendContainerState(containerMapValue) }
+			if esep { ee.WriteMapElemValue() }
 			{{ encmd .Elem "v2"}}
 		}
 	}
-	if cr != nil { cr.sendContainerState(containerMapEnd) }{{/* ee.EncodeEnd() */}}
+	ee.WriteMapEnd()
 }
 
 {{end}}{{end}}{{end}}
@@ -421,7 +421,7 @@ func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .E
 }
 func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, canChange bool, 
 	d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) {
-	dd, cr := d.d, d.cr
+	dd, esep := d.d, d.hh.hasElemSeparators()
 	{{/* // if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil() */}}
 	containerLen := dd.ReadMapStart()
 	if canChange && v == nil {
@@ -430,7 +430,7 @@ func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Ele
 		changed = true
 	}
 	if containerLen == 0 {
-		if cr != nil { cr.sendContainerState(containerMapEnd) }
+		dd.ReadMapEnd()
 		return v, changed
 	}
 	{{ if eq .Elem "interface{}" }}mapGet := !d.h.MapValueReset && !d.h.InterfaceReset{{end}}
@@ -438,13 +438,13 @@ func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Ele
 	var mv {{ .Elem }}
 	hasLen := containerLen > 0
 	for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
-		if cr != nil { cr.sendContainerState(containerMapKey) }
+		if esep { dd.ReadMapElemKey() }
 		{{ if eq .MapKey "interface{}" }}mk = nil 
 		d.decode(&mk)
 		if bv, bok := mk.([]byte); bok {
 			mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
 		}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
-		if cr != nil { cr.sendContainerState(containerMapValue) }
+		if esep { dd.ReadMapElemValue() }
 		if dd.TryDecodeAsNil() {
 			if d.h.DeleteOnNilMapValue { delete(v, mk) } else { v[mk] = {{ zerocmd .Elem }} }
 			continue 
@@ -455,7 +455,7 @@ func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Ele
 			v[mk] = mv
 		}
 	}
-	if cr != nil { cr.sendContainerState(containerMapEnd) }
+	dd.ReadMapEnd()
 	return v, changed
 }
 

+ 3 - 3
codec/gen-dec-map.go.tmpl

@@ -17,7 +17,7 @@ if {{var "bh"}}.MapValueReset {
 if {{var "l"}} != 0 {
 {{var "hl"}} := {{var "l"}} > 0 
 	for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
-	z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
+	r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
 	{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
 {{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
 		{{var "mk"}} = string({{var "bv"}})
@@ -29,7 +29,7 @@ if {{var "l"}} != 0 {
 			{{var "ms"}} = false
 		} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
 	} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
-	z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
+	r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
 	{{var "mdn"}} = false
 	{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
 	if {{var "mdn"}} {
@@ -39,4 +39,4 @@ if {{var "l"}} != 0 {
 	}
 }
 } // else len==0: TODO: Should we clear map entries?
-z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
+r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}

+ 5 - 14
codec/gen-helper.generated.go

@@ -42,6 +42,11 @@ func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
 	return genHelperDecoder{d: d}, d.d
 }
 
+// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
+func BasicHandleDoNotUse(h Handle) *BasicHandle {
+	return h.getBasicHandle()
+}
+
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 type genHelperEncoder struct {
 	e *Encoder
@@ -126,13 +131,6 @@ func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
 	return false
 }
 
-// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
-func (f genHelperEncoder) EncSendContainerState(c containerState) {
-	if f.e.cr != nil {
-		f.e.cr.sendContainerState(c)
-	}
-}
-
 // ---------------- DECODER FOLLOWS -----------------
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -250,10 +248,3 @@ func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
 func (f genHelperDecoder) StringView(v []byte) string {
 	return stringView(v)
 }
-
-// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
-func (f genHelperDecoder) DecSendContainerState(c containerState) {
-	if f.d.cr != nil {
-		f.d.cr.sendContainerState(c)
-	}
-}

+ 9 - 0
codec/gen-helper.go.tmpl

@@ -42,6 +42,11 @@ func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
 	return genHelperDecoder{d:d}, d.d 
 }
 
+// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
+func BasicHandleDoNotUse(h Handle) *BasicHandle {
+     return h.getBasicHandle()
+}
+
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 type genHelperEncoder struct {
 	e *Encoder
@@ -116,12 +121,14 @@ func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
 	}
 	return false 
 }
+{{/*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperEncoder) EncSendContainerState(c containerState) {
 	if f.e.cr != nil {
 		f.e.cr.sendContainerState(c)
 	}
 }
+*/}}
 
 // ---------------- DECODER FOLLOWS -----------------
 
@@ -223,12 +230,14 @@ func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
 func (f genHelperDecoder) StringView(v []byte) string {
 	return stringView(v)
 }
+{{/*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperDecoder) DecSendContainerState(c containerState) {
 	if f.d.cr != nil {
 		f.d.cr.sendContainerState(c)
 	}
 }
+*/}}
 
 {{/*
 

+ 3 - 3
codec/gen.generated.go

@@ -25,7 +25,7 @@ if {{var "bh"}}.MapValueReset {
 if {{var "l"}} != 0 {
 {{var "hl"}} := {{var "l"}} > 0 
 	for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
-	z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
+	r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
 	{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
 {{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
 		{{var "mk"}} = string({{var "bv"}})
@@ -37,7 +37,7 @@ if {{var "l"}} != 0 {
 			{{var "ms"}} = false
 		} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
 	} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
-	z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
+	r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
 	{{var "mdn"}} = false
 	{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
 	if {{var "mdn"}} {
@@ -47,7 +47,7 @@ if {{var "l"}} != 0 {
 	}
 }
 } // else len==0: TODO: Should we clear map entries?
-z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
+r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
 `
 
 const genDecListTmpl = `

+ 28 - 27
codec/gen.go

@@ -897,15 +897,15 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 	}
 	// x.linef("var %snn%s int", genTempVarPfx, i)
 	x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
-	x.linef("r.EncodeArrayStart(%d)", len(tisfi))
+	x.linef("r.WriteArrayStart(%d)", len(tisfi))
 	x.linef("} else {") // if not ti.toArray
 	if ti.anyOmitEmpty {
 		x.linef("var %snn%s = %v", genTempVarPfx, i, nn)
 		x.linef("for _, b := range %s { if b { %snn%s++ } }", numfieldsvar, genTempVarPfx, i)
-		x.linef("r.EncodeMapStart(%snn%s)", genTempVarPfx, i)
+		x.linef("r.WriteMapStart(%snn%s)", genTempVarPfx, i)
 		x.linef("%snn%s = %v", genTempVarPfx, i, 0)
 	} else {
-		x.linef("r.EncodeMapStart(%d)", len(tisfi))
+		x.linef("r.WriteMapStart(%d)", len(tisfi))
 	}
 	x.line("}") // close if not StructToArray
 
@@ -948,9 +948,10 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 
 		x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray
 		if labelUsed {
-			x.linef("if %s { z.EncSendContainerState(codecSelfer_containerArrayElem%s); r.EncodeNil() } else { ", isNilVarName, x.xs)
+			x.linef("if %s { r.WriteArrayElem(); r.EncodeNil() } else { ", isNilVarName)
+			// x.linef("if %s { z.EncSendContainerState(codecSelfer_containerArrayElem%s); r.EncodeNil() } else { ", isNilVarName, x.xs)
 		}
-		x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
+		x.line("r.WriteArrayElem()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
 		if si.omitEmpty {
 			x.linef("if %s[%v] {", numfieldsvar, j)
 		}
@@ -969,9 +970,9 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 		if si.omitEmpty {
 			x.linef("if %s[%v] {", numfieldsvar, j)
 		}
-		x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
+		x.line("r.WriteMapElemKey()") // x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
 		x.line("r.EncodeString(codecSelferC_UTF8" + x.xs + ", string(\"" + si.encName + "\"))")
-		x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
+		x.line("r.WriteMapElemValue()") // x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
 		if labelUsed {
 			x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
 			x.encVar(varname+"."+t2.Name, t2.Type)
@@ -985,9 +986,9 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 		x.linef("} ") // end if/else ti.toArray
 	}
 	x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
-	x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
+	x.line("r.WriteArrayEnd()")                          // x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
 	x.line("} else {")
-	x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
+	x.line("r.WriteMapEnd()") // x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
 	x.line("}")
 
 }
@@ -1003,33 +1004,33 @@ func (x *genRunner) encListFallback(varname string, t reflect.Type) {
 	}
 	i := x.varsfx()
 	g := genTempVarPfx
-	x.line("r.EncodeArrayStart(len(" + varname + "))")
+	x.line("r.WriteArrayStart(len(" + varname + "))")
 	if t.Kind() == reflect.Chan {
 		x.linef("for %si%s, %si2%s := 0, len(%s); %si%s < %si2%s; %si%s++ {", g, i, g, i, varname, g, i, g, i, g, i)
-		x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
+		x.line("r.WriteArrayElem()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
 		x.linef("%sv%s := <-%s", g, i, varname)
 	} else {
 		// x.linef("for %si%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
 		x.linef("for _, %sv%s := range %s {", genTempVarPfx, i, varname)
-		x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
+		x.line("r.WriteArrayElem()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
 	}
 	x.encVar(genTempVarPfx+"v"+i, t.Elem())
 	x.line("}")
-	x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
+	x.line("r.WriteArrayEnd()") // x.linef("z.EncSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
 }
 
 func (x *genRunner) encMapFallback(varname string, t reflect.Type) {
 	// TODO: expand this to handle canonical.
 	i := x.varsfx()
-	x.line("r.EncodeMapStart(len(" + varname + "))")
+	x.line("r.WriteMapStart(len(" + varname + "))")
 	x.linef("for %sk%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
 	// x.line("for " + genTempVarPfx + "k" + i + ", " + genTempVarPfx + "v" + i + " := range " + varname + " {")
-	x.linef("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
+	x.line("r.WriteMapElemKey()") // f("z.EncSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
 	x.encVar(genTempVarPfx+"k"+i, t.Key())
-	x.linef("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
+	x.line("r.WriteMapElemValue()") // f("z.EncSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
 	x.encVar(genTempVarPfx+"v"+i, t.Elem())
 	x.line("}")
-	x.linef("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
+	x.line("r.WriteMapEnd()") // f("z.EncSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
 }
 
 func (x *genRunner) decVar(varname, decodedNilVarname string, t reflect.Type, canBeNil bool) {
@@ -1497,15 +1498,15 @@ func (x *genRunner) decStructMap(varname, lenvarname string, rtid uintptr, t ref
 		x.linef("if %shl%s { if %sj%s >= %s { break }", tpfx, i, tpfx, i, lenvarname)
 		x.line("} else { if r.CheckBreak() { break }; }")
 	}
-	x.linef("z.DecSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
+	x.line("r.ReadMapElemKey()") // f("z.DecSendContainerState(codecSelfer_containerMapKey%s)", x.xs)
 	x.line(kName + "Slc = r.DecodeStringAsBytes()")
 	// let string be scoped to this loop alone, so it doesn't escape.
 	x.line(kName + " := string(" + kName + "Slc)")
-	x.linef("z.DecSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
+	x.line("r.ReadMapElemValue()") // f("z.DecSendContainerState(codecSelfer_containerMapValue%s)", x.xs)
 	x.decStructMapSwitch(kName, varname, rtid, t)
 
 	x.line("} // end for " + tpfx + "j" + i)
-	x.linef("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
+	x.line("r.ReadMapEnd()") // f("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
 }
 
 func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) {
@@ -1542,9 +1543,9 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
 		x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }",
 			tpfx, i, tpfx, i, tpfx, i,
 			tpfx, i, lenvarname, tpfx, i)
-		x.linef("if %sb%s { z.DecSendContainerState(codecSelfer_containerArrayEnd%s); %s }",
-			tpfx, i, x.xs, breakString)
-		x.linef("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
+		x.linef("if %sb%s { r.ReadArrayEnd(); %s }", tpfx, i, breakString)
+		// x.linef("if %sb%s { z.DecSendContainerState(codecSelfer_containerArrayEnd%s); %s }", tpfx, i, x.xs, breakString)
+		x.line("r.ReadArrayElem()") // f("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
 		x.decVar(varname+"."+t2.Name, "", t2.Type, true)
 	}
 	// read remaining values and throw away.
@@ -1553,10 +1554,10 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
 		tpfx, i, tpfx, i, tpfx, i,
 		tpfx, i, lenvarname, tpfx, i)
 	x.linef("if %sb%s { break }", tpfx, i)
-	x.linef("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
+	x.line("r.ReadArrayElem()") // f("z.DecSendContainerState(codecSelfer_containerArrayElem%s)", x.xs)
 	x.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i)
 	x.line("}")
-	x.linef("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
+	x.line("r.ReadArrayEnd()") // f("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
 }
 
 func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
@@ -1566,7 +1567,7 @@ func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
 	x.linef("if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs)
 	x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()")
 	x.linef("if %sl%s == 0 {", genTempVarPfx, i)
-	x.linef("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
+	x.line("r.ReadMapEnd()") // f("z.DecSendContainerState(codecSelfer_containerMapEnd%s)", x.xs)
 	if genUseOneFunctionForDecStructMap {
 		x.line("} else { ")
 		x.linef("x.codecDecodeSelfFromMap(%sl%s, d)", genTempVarPfx, i)
@@ -1582,7 +1583,7 @@ func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
 	x.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs)
 	x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()")
 	x.linef("if %sl%s == 0 {", genTempVarPfx, i)
-	x.linef("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
+	x.line("r.ReadArrayEnd()") // f("z.DecSendContainerState(codecSelfer_containerArrayEnd%s)", x.xs)
 	x.line("} else { ")
 	x.linef("x.codecDecodeSelfFromArray(%sl%s, d)", genTempVarPfx, i)
 	x.line("}")

+ 10 - 5
codec/helper.go

@@ -303,9 +303,9 @@ type typeInfoLoadArray struct {
 	sfiidx   [typeInfoLoadArrayLen]sfiIdx
 }
 
-type containerStateRecv interface {
-	sendContainerState(containerState)
-}
+// type containerStateRecv interface {
+// 	sendContainerState(containerState)
+// }
 
 // mirror json.Marshaler and json.Unmarshaler here,
 // so we don't import the encoding/json package
@@ -521,6 +521,7 @@ type Handle interface {
 	newEncDriver(w *Encoder) encDriver
 	newDecDriver(r *Decoder) decDriver
 	isBinary() bool
+	hasElemSeparators() bool
 	IsBuiltinType(rtid uintptr) bool
 }
 
@@ -659,9 +660,13 @@ type noBuiltInTypes struct{ noBuiltInTypeChecker }
 func (_ noBuiltInTypes) EncodeBuiltin(rt uintptr, v interface{}) {}
 func (_ noBuiltInTypes) DecodeBuiltin(rt uintptr, v interface{}) {}
 
-type noStreamingCodec struct{}
+// type noStreamingCodec struct{}
+// func (_ noStreamingCodec) CheckBreak() bool { return false }
+// func (_ noStreamingCodec) hasElemSeparators() bool { return false }
+
+type noElemSeparators struct{}
 
-func (_ noStreamingCodec) CheckBreak() bool { return false }
+func (_ noElemSeparators) hasElemSeparators() (v bool) { return }
 
 // bigenHelper.
 // Users must already slice the x completely, because we will not reslice.

+ 226 - 96
codec/json.go

@@ -158,49 +158,116 @@ type jsonEncDriver struct {
 //   - newline and indent are added before each ending,
 //     except there was no entry (so we can have {} or [])
 
-func (e *jsonEncDriver) sendContainerState(c containerState) {
-	// determine whether to output separators
-	switch c {
-	case containerMapKey:
-		if e.c != containerMapStart {
-			e.w.writen1(',')
-		}
-		if e.d {
-			e.writeIndent()
-		}
-	case containerMapValue:
-		if e.d {
-			e.w.writen2(':', ' ')
-		} else {
-			e.w.writen1(':')
-		}
-	case containerMapEnd:
-		if e.d {
-			e.dl--
-			if e.c != containerMapStart {
-				e.writeIndent()
-			}
-		}
-		e.w.writen1('}')
-	case containerArrayElem:
+func (e *jsonEncDriver) WriteArrayStart(length int) {
+	if e.d {
+		e.dl++
+	}
+	e.w.writen1('[')
+	e.c = containerArrayStart
+}
+
+func (e *jsonEncDriver) WriteArrayElem() {
+	if e.c != containerArrayStart {
+		e.w.writen1(',')
+	}
+	if e.d {
+		e.writeIndent()
+	}
+	e.c = containerArrayElem
+}
+
+func (e *jsonEncDriver) WriteArrayEnd() {
+	if e.d {
+		e.dl--
 		if e.c != containerArrayStart {
-			e.w.writen1(',')
-		}
-		if e.d {
 			e.writeIndent()
 		}
-	case containerArrayEnd:
-		if e.d {
-			e.dl--
-			if e.c != containerArrayStart {
-				e.writeIndent()
-			}
+	}
+	e.w.writen1(']')
+	e.c = containerArrayEnd
+}
+
+func (e *jsonEncDriver) WriteMapStart(length int) {
+	if e.d {
+		e.dl++
+	}
+	e.w.writen1('{')
+	e.c = containerMapStart
+}
+
+func (e *jsonEncDriver) WriteMapElemKey() {
+	if e.c != containerMapStart {
+		e.w.writen1(',')
+	}
+	if e.d {
+		e.writeIndent()
+	}
+	e.c = containerMapKey
+}
+
+func (e *jsonEncDriver) WriteMapElemValue() {
+	if e.d {
+		e.w.writen2(':', ' ')
+	} else {
+		e.w.writen1(':')
+	}
+	e.c = containerMapValue
+}
+
+func (e *jsonEncDriver) WriteMapEnd() {
+	if e.d {
+		e.dl--
+		if e.c != containerMapStart {
+			e.writeIndent()
 		}
-		e.w.writen1(']')
 	}
-	e.c = c
+	e.w.writen1('}')
+	e.c = containerMapEnd
 }
 
+// func (e *jsonEncDriver) sendContainerState(c containerState) {
+// 	// determine whether to output separators
+// 	switch c {
+// 	case containerMapKey:
+// 		if e.c != containerMapStart {
+// 			e.w.writen1(',')
+// 		}
+// 		if e.d {
+// 			e.writeIndent()
+// 		}
+// 	case containerMapValue:
+// 		if e.d {
+// 			e.w.writen2(':', ' ')
+// 		} else {
+// 			e.w.writen1(':')
+// 		}
+// 	case containerMapEnd:
+// 		if e.d {
+// 			e.dl--
+// 			if e.c != containerMapStart {
+// 				e.writeIndent()
+// 			}
+// 		}
+// 		e.w.writen1('}')
+// 	case containerArrayElem:
+// 		if e.c != containerArrayStart {
+// 			e.w.writen1(',')
+// 		}
+// 		if e.d {
+// 			e.writeIndent()
+// 		}
+// 	case containerArrayEnd:
+// 		if e.d {
+// 			e.dl--
+// 			if e.c != containerArrayStart {
+// 				e.writeIndent()
+// 			}
+// 		}
+// 		e.w.writen1(']')
+// 	}
+// 	e.c = c
+// }
+
 func (e *jsonEncDriver) writeIndent() {
 	e.w.writen1('\n')
 	if x := len(e.ds) * int(e.dl); x <= jsonSpacesOrTabsLen {
@@ -281,22 +348,6 @@ func (e *jsonEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
 	}
 }
 
-func (e *jsonEncDriver) EncodeArrayStart(length int) {
-	if e.d {
-		e.dl++
-	}
-	e.w.writen1('[')
-	e.c = containerArrayStart
-}
-
-func (e *jsonEncDriver) EncodeMapStart(length int) {
-	if e.d {
-		e.dl++
-	}
-	e.w.writen1('{')
-	e.c = containerMapStart
-}
-
 func (e *jsonEncDriver) EncodeString(c charEncoding, v string) {
 	e.quoteStr(v)
 }
@@ -434,43 +485,144 @@ func (d *jsonDecDriver) uncacheRead() {
 	}
 }
 
-func (d *jsonDecDriver) sendContainerState(c containerState) {
+func (d *jsonDecDriver) ReadMapStart() int {
 	if d.tok == 0 {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
-	var xc uint8 // char expected
-	switch c {
-	case containerMapKey:
-		if d.c != containerMapStart {
-			xc = ','
-		}
-	case containerMapValue:
-		xc = ':'
-	case containerMapEnd:
-		xc = '}'
-	case containerArrayElem:
-		if d.c != containerArrayStart {
-			xc = ','
+	if d.tok != '{' {
+		d.d.errorf("json: expect char '%c' but got char '%c'", '{', d.tok)
+	}
+	d.tok = 0
+	d.c = containerMapStart
+	return -1
+}
+
+func (d *jsonDecDriver) ReadArrayStart() int {
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+	}
+	if d.tok != '[' {
+		d.d.errorf("json: expect char '%c' but got char '%c'", '[', d.tok)
+	}
+	d.tok = 0
+	d.c = containerArrayStart
+	return -1
+}
+
+func (d *jsonDecDriver) CheckBreak() bool {
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+	}
+	return d.tok == '}' || d.tok == ']'
+}
+
+func (d *jsonDecDriver) ReadArrayElem() {
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+	}
+	if d.c != containerArrayStart {
+		const xc uint8 = ','
+		if d.tok != xc {
+			d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
 		}
-	case containerArrayEnd:
-		xc = ']'
+		d.tok = 0
+	}
+	d.c = containerArrayElem
+}
+
+func (d *jsonDecDriver) ReadArrayEnd() {
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
-	if xc != 0 {
+	const xc uint8 = ']'
+	if d.tok != xc {
+		d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
+	}
+	d.tok = 0
+	d.c = containerArrayEnd
+}
+
+func (d *jsonDecDriver) ReadMapElemKey() {
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+	}
+	if d.c != containerMapStart {
+		const xc uint8 = ','
 		if d.tok != xc {
 			d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
 		}
 		d.tok = 0
 	}
-	d.c = c
+	d.c = containerMapKey
 }
 
-func (d *jsonDecDriver) CheckBreak() bool {
+func (d *jsonDecDriver) ReadMapElemValue() {
 	if d.tok == 0 {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
-	return d.tok == '}' || d.tok == ']'
+	const xc uint8 = ':'
+	if d.tok != xc {
+		d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
+	}
+	d.tok = 0
+	d.c = containerMapValue
 }
 
+func (d *jsonDecDriver) ReadMapEnd() {
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+	}
+	const xc uint8 = '}'
+	if d.tok != xc {
+		d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
+	}
+	d.tok = 0
+	d.c = containerMapEnd
+}
+
+// func (d *jsonDecDriver) readContainerState(c containerState, xc uint8, check bool) {
+// 	if d.tok == 0 {
+// 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+// 	}
+// 	if check {
+// 		if d.tok != xc {
+// 			d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
+// 		}
+// 		d.tok = 0
+// 	}
+// 	d.c = c
+// }
+
+// func (d *jsonDecDriver) sendContainerState(c containerState) {
+// 	if d.tok == 0 {
+// 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+// 	}
+// 	var xc uint8 // char expected
+// 	switch c {
+// 	case containerMapKey:
+// 		if d.c != containerMapStart {
+// 			xc = ','
+// 		}
+// 	case containerMapValue:
+// 		xc = ':'
+// 	case containerMapEnd:
+// 		xc = '}'
+// 	case containerArrayElem:
+// 		if d.c != containerArrayStart {
+// 			xc = ','
+// 		}
+// 	case containerArrayEnd:
+// 		xc = ']'
+// 	}
+// 	if xc != 0 {
+// 		if d.tok != xc {
+// 			d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
+// 		}
+// 		d.tok = 0
+// 	}
+// 	d.c = c
+// }
+
 // func (d *jsonDecDriver) readLiteralIdx(fromIdx, toIdx uint8) {
 // 	bs := d.r.readx(int(toIdx - fromIdx))
 // 	d.tok = 0
@@ -525,30 +677,6 @@ func (d *jsonDecDriver) DecodeBool() bool {
 	return false // "unreachable"
 }
 
-func (d *jsonDecDriver) ReadMapStart() int {
-	if d.tok == 0 {
-		d.tok = d.r.skip(&jsonCharWhitespaceSet)
-	}
-	if d.tok != '{' {
-		d.d.errorf("json: expect char '%c' but got char '%c'", '{', d.tok)
-	}
-	d.tok = 0
-	d.c = containerMapStart
-	return -1
-}
-
-func (d *jsonDecDriver) ReadArrayStart() int {
-	if d.tok == 0 {
-		d.tok = d.r.skip(&jsonCharWhitespaceSet)
-	}
-	if d.tok != '[' {
-		d.d.errorf("json: expect char '%c' but got char '%c'", '[', d.tok)
-	}
-	d.tok = 0
-	d.c = containerArrayStart
-	return -1
-}
-
 func (d *jsonDecDriver) ContainerType() (vt valueType) {
 	// check container type by checking the first char
 	if d.tok == 0 {
@@ -939,6 +1067,8 @@ type JsonHandle struct {
 	PreferFloat bool
 }
 
+func (h *JsonHandle) hasElemSeparators() bool { return true }
+
 func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
 	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
 }

+ 8 - 5
codec/msgpack.go

@@ -104,7 +104,8 @@ var (
 
 type msgpackEncDriver struct {
 	noBuiltInTypes
-	encNoSeparator
+	encDriverNoopContainerWriter
+	// encNoSeparator
 	e *Encoder
 	w encWriter
 	h *MsgpackHandle
@@ -213,11 +214,11 @@ func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) {
 	}
 }
 
-func (e *msgpackEncDriver) EncodeArrayStart(length int) {
+func (e *msgpackEncDriver) WriteArrayStart(length int) {
 	e.writeContainerLen(msgpackContainerList, length)
 }
 
-func (e *msgpackEncDriver) EncodeMapStart(length int) {
+func (e *msgpackEncDriver) WriteMapStart(length int) {
 	e.writeContainerLen(msgpackContainerMap, length)
 }
 
@@ -274,8 +275,9 @@ type msgpackDecDriver struct {
 	bdRead bool
 	br     bool // bytes reader
 	noBuiltInTypes
-	noStreamingCodec
-	decNoSeparator
+	// noStreamingCodec
+	// decNoSeparator
+	decDriverNoopContainerReader
 }
 
 // Note: This returns either a primitive (int, bool, etc) for non-containers,
@@ -760,6 +762,7 @@ type MsgpackHandle struct {
 	// a []byte or string based on the setting of RawToString.
 	WriteExt bool
 	binaryEncodingType
+	noElemSeparators
 }
 
 func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {

+ 28 - 25
codec/shared_test.go

@@ -92,26 +92,21 @@ var (
 var (
 	testDepth int
 
-	testVerbose        bool
-	testInitDebug      bool
-	testStructToArray  bool
-	testCanonical      bool
-	testUseReset       bool
-	testWriteNoSymbols bool
-	testSkipIntf       bool
-	testInternStr      bool
-	testUseMust        bool
-	testCheckCircRef   bool
-
-	testUseIoEncDec  bool
+	testVerbose       bool
+	testInitDebug     bool
+	testStructToArray bool
+	testCanonical     bool
+	testUseReset      bool
+	testSkipIntf      bool
+	testInternStr     bool
+	testUseMust       bool
+	testCheckCircRef  bool
+
+	testUseIoEncDec  int
 	testUseIoWrapper bool
 
-	testJsonIndent int
 	testMaxInitLen int
 
-	testJsonHTMLCharsAsIs bool
-	testJsonPreferFloat   bool
-
 	testNumRepeatString int
 )
 
@@ -148,21 +143,17 @@ func testInitFlags() {
 	flag.IntVar(&testDepth, "tsd", 0, "Test Struc Depth")
 	flag.BoolVar(&testVerbose, "tv", false, "Test Verbose")
 	flag.BoolVar(&testInitDebug, "tg", false, "Test Init Debug")
-	flag.BoolVar(&testUseIoEncDec, "ti", false, "Use IO Reader/Writer for Marshal/Unmarshal")
+	flag.IntVar(&testUseIoEncDec, "ti", -1, "Use IO Reader/Writer for Marshal/Unmarshal ie >= 0")
 	flag.BoolVar(&testUseIoWrapper, "tiw", false, "Wrap the IO Reader/Writer with a base pass-through reader/writer")
 	flag.BoolVar(&testStructToArray, "ts", false, "Set StructToArray option")
-	flag.BoolVar(&testWriteNoSymbols, "tn", false, "Set NoSymbols option")
 	flag.BoolVar(&testCanonical, "tc", false, "Set Canonical option")
 	flag.BoolVar(&testInternStr, "te", false, "Set InternStr option")
 	flag.BoolVar(&testSkipIntf, "tf", false, "Skip Interfaces")
 	flag.BoolVar(&testUseReset, "tr", false, "Use Reset")
-	flag.IntVar(&testJsonIndent, "td", 0, "Use JSON Indent")
 	flag.IntVar(&testNumRepeatString, "trs", 8, "Create string variables by repeating a string N times")
 	flag.IntVar(&testMaxInitLen, "tx", 0, "Max Init Len")
 	flag.BoolVar(&testUseMust, "tm", true, "Use Must(En|De)code")
 	flag.BoolVar(&testCheckCircRef, "tl", false, "Use Check Circular Ref")
-	flag.BoolVar(&testJsonHTMLCharsAsIs, "tas", false, "Set JSON HTMLCharsAsIs")
-	flag.BoolVar(&testJsonPreferFloat, "tjf", false, "Prefer Float in json")
 }
 
 func benchInitFlags() {
@@ -194,7 +185,6 @@ func testInitAll() {
 	// only parse it once.
 	if !flag.Parsed() {
 		flag.Parse()
-		testNumRepeatStringMirror = testNumRepeatString
 	}
 	for _, f := range testPreInitFns {
 		f()
@@ -214,8 +204,13 @@ func testCodecEncode(ts interface{}, bsIn []byte,
 	} else {
 		e = NewEncoder(nil, h)
 	}
-	if testUseIoEncDec {
+	bh := BasicHandleDoNotUse(h)
+	var oldWriteBufferSize int
+	if testUseIoEncDec >= 0 {
 		buf = fn(bsIn)
+		// set the encode options for using a buffer
+		oldWriteBufferSize = bh.WriterBufferSize
+		bh.WriterBufferSize = testUseIoEncDec
 		if testUseIoWrapper {
 			e.Reset(ioWriterWrapper{buf})
 		} else {
@@ -230,8 +225,9 @@ func testCodecEncode(ts interface{}, bsIn []byte,
 	} else {
 		err = e.Encode(ts)
 	}
-	if testUseIoEncDec {
+	if testUseIoEncDec >= 0 {
 		bs = buf.Bytes()
+		bh.WriterBufferSize = oldWriteBufferSize
 	}
 	return
 }
@@ -244,8 +240,12 @@ func testCodecDecode(bs []byte, ts interface{}, h Handle) (err error) {
 	} else {
 		d = NewDecoder(nil, h)
 	}
-	if testUseIoEncDec {
+	bh := BasicHandleDoNotUse(h)
+	var oldReadBufferSize int
+	if testUseIoEncDec >= 0 {
 		buf := bytes.NewReader(bs)
+		oldReadBufferSize = bh.ReaderBufferSize
+		bh.ReaderBufferSize = testUseIoEncDec
 		if testUseIoWrapper {
 			d.Reset(ioReaderWrapper{buf})
 		} else {
@@ -259,6 +259,9 @@ func testCodecDecode(bs []byte, ts interface{}, h Handle) (err error) {
 	} else {
 		err = d.Decode(ts)
 	}
+	if testUseIoEncDec >= 0 {
+		bh.ReaderBufferSize = oldReadBufferSize
+	}
 	return
 }
 

+ 8 - 6
codec/simple.go

@@ -30,7 +30,8 @@ const (
 
 type simpleEncDriver struct {
 	noBuiltInTypes
-	encNoSeparator
+	encDriverNoopContainerWriter
+	// encNoSeparator
 	e *Encoder
 	h *SimpleHandle
 	w encWriter
@@ -124,11 +125,11 @@ func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
 	e.w.writen1(xtag)
 }
 
-func (e *simpleEncDriver) EncodeArrayStart(length int) {
+func (e *simpleEncDriver) WriteArrayStart(length int) {
 	e.encLen(simpleVdArray, length)
 }
 
-func (e *simpleEncDriver) EncodeMapStart(length int) {
+func (e *simpleEncDriver) WriteMapStart(length int) {
 	e.encLen(simpleVdMap, length)
 }
 
@@ -155,10 +156,10 @@ type simpleDecDriver struct {
 	bdRead bool
 	bd     byte
 	br     bool // bytes reader
+	b      [scratchByteArrayLen]byte
 	noBuiltInTypes
-	noStreamingCodec
-	decNoSeparator
-	b [scratchByteArrayLen]byte
+	// noStreamingCodec
+	decDriverNoopContainerReader
 }
 
 func (d *simpleDecDriver) readNextBd() {
@@ -512,6 +513,7 @@ func (d *simpleDecDriver) DecodeNaked() {
 type SimpleHandle struct {
 	BasicHandle
 	binaryEncodingType
+	noElemSeparators
 }
 
 func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {

+ 0 - 2
codec/values_test.go

@@ -206,8 +206,6 @@ type Sinterface interface {
 
 var testStrucTime = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC).UTC()
 
-var testNumRepeatStringMirror int = 8
-
 func populateTestStrucCommon(ts *testStrucCommon, n int, bench, useInterface, useStringKeyOnly bool) {
 	var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464
 

+ 4 - 4
codec/x_bench_gen_test.go

@@ -44,7 +44,7 @@ func fnEasyjsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
 	if _, ok := ts.(easyjson.Marshaler); !ok {
 		return nil, errors.New("easyjson: input is not a easyjson.Marshaler")
 	}
-	if testUseIoEncDec {
+	if testUseIoEncDec >= 0 {
 		buf := new(bytes.Buffer)
 		_, err := easyjson.MarshalToWriter(ts.(easyjson.Marshaler), buf)
 		return buf.Bytes(), err
@@ -57,7 +57,7 @@ func fnEasyjsonDecodeFn(buf []byte, ts interface{}) error {
 	if _, ok := ts.(easyjson.Unmarshaler); !ok {
 		return errors.New("easyjson: input is not a easyjson.Unmarshaler")
 	}
-	if testUseIoEncDec {
+	if testUseIoEncDec >= 0 {
 		return easyjson.UnmarshalFromReader(bytes.NewReader(buf), ts.(easyjson.Unmarshaler))
 	}
 	return easyjson.Unmarshal(buf, ts.(easyjson.Unmarshaler))
@@ -78,7 +78,7 @@ func fnMsgpEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
 	if _, ok := ts.(msgp.Encodable); !ok {
 		return nil, fmt.Errorf("msgp: input of type %T is not a msgp.Encodable", ts)
 	}
-	if testUseIoEncDec {
+	if testUseIoEncDec >= 0 {
 		buf := fnBenchmarkByteBuf(bsIn)
 		err := ts.(msgp.Encodable).EncodeMsg(msgp.NewWriter(buf))
 		return buf.Bytes(), err
@@ -90,7 +90,7 @@ func fnMsgpDecodeFn(buf []byte, ts interface{}) (err error) {
 	if _, ok := ts.(msgp.Decodable); !ok {
 		return fmt.Errorf("msgp: input of type %T is not a msgp.Decodable", ts)
 	}
-	if testUseIoEncDec {
+	if testUseIoEncDec >= 0 {
 		err = ts.(msgp.Decodable).DecodeMsg(msgp.NewReader(bytes.NewReader(buf)))
 		return
 	}

+ 106 - 32
codec/z_all_test.go

@@ -29,52 +29,40 @@ import "testing"
 // 	os.Exit(exitcode)
 // }
 
-func testSuite(t *testing.T, f func(t *testing.T)) {
-	// find . -name "*_test.go" | xargs grep -e 'flag.' | cut -d '&' -f 2 | cut -d ',' -f 1 | grep -e '^test'
-	// Disregard the following: testVerbose, testInitDebug, testSkipIntf, testJsonIndent (Need a test for it)
-
-	testReinit() // so flag.Parse() is called first, and never called again
-
-	testDecodeOptions = DecodeOptions{}
-	testEncodeOptions = EncodeOptions{}
-
+func testGroupResetFlags() {
 	testUseMust = false
 	testCanonical = false
 	testUseMust = false
 	testInternStr = false
-	testUseIoEncDec = false
+	testUseIoEncDec = -1
 	testStructToArray = false
-	testWriteNoSymbols = false
 	testCheckCircRef = false
-	testJsonHTMLCharsAsIs = false
 	testUseReset = false
 	testMaxInitLen = 0
-	testJsonIndent = 0
 	testUseIoWrapper = false
 	testNumRepeatString = 8
+}
 
-	testReinit()
-	t.Run("optionsFalse", f)
+func testSuite(t *testing.T, f func(t *testing.T)) {
+	// find . -name "*_test.go" | xargs grep -e 'flag.' | cut -d '&' -f 2 | cut -d ',' -f 1 | grep -e '^test'
+	// Disregard the following: testVerbose, testInitDebug, testSkipIntf, testJsonIndent (Need a test for it)
 
-	testMaxInitLen = 10
-	testJsonIndent = 8
-	testReinit()
-	t.Run("initLen10-jsonSpaces", f)
+	testReinit() // so flag.Parse() is called first, and never called again
+
+	testDecodeOptions = DecodeOptions{}
+	testEncodeOptions = EncodeOptions{}
+
+	testGroupResetFlags()
 
 	testReinit()
-	testMaxInitLen = 10
-	testJsonIndent = -1
-	testReinit()
-	t.Run("initLen10-jsonTabs", f)
+	t.Run("optionsFalse", f)
 
 	testCanonical = true
 	testUseMust = true
 	testInternStr = true
-	testUseIoEncDec = true
+	testUseIoEncDec = 0
 	testStructToArray = true
-	testWriteNoSymbols = true
 	testCheckCircRef = true
-	testJsonHTMLCharsAsIs = true
 	testUseReset = true
 	testDecodeOptions.MapValueReset = true
 	testReinit()
@@ -84,19 +72,22 @@ func testSuite(t *testing.T, f func(t *testing.T)) {
 	testReinit()
 	t.Run("optionsTrue-ioWrapper", f)
 
+	testUseIoEncDec = -1
+
 	testDepth = 6
 	testReinit()
 	t.Run("optionsTrue-deepstruct", f)
 
 	// make buffer small enough so that we have to re-fill multiple times.
 	testSkipRPCTests = true
-	testUseIoEncDec = true
-	testDecodeOptions.ReaderBufferSize = 128
-	testEncodeOptions.WriterBufferSize = 128
+	testUseIoEncDec = 128
+	// testDecodeOptions.ReaderBufferSize = 128
+	// testEncodeOptions.WriterBufferSize = 128
 	testReinit()
 	t.Run("optionsTrue-bufio", f)
-	testDecodeOptions.ReaderBufferSize = 0
-	testEncodeOptions.WriterBufferSize = 0
+	// testDecodeOptions.ReaderBufferSize = 0
+	// testEncodeOptions.WriterBufferSize = 0
+	testUseIoEncDec = -1
 	testSkipRPCTests = false
 
 	testNumRepeatString = 32
@@ -113,6 +104,8 @@ func testSuite(t *testing.T, f func(t *testing.T)) {
 	// .... however, update deepEqual to take this option
 	// testReinit()
 	// t.Run("optionsTrue-resetOptions", f)
+
+	testGroupResetFlags()
 }
 
 /*
@@ -174,7 +167,88 @@ func testCodecGroup(t *testing.T) {
 	// <tear-down code>
 }
 
-func TestCodecSuite(t *testing.T) { testSuite(t, testCodecGroup) }
+func testJsonGroup(t *testing.T) {
+	t.Run("TestJsonCodecsTable", TestJsonCodecsTable)
+	t.Run("TestJsonCodecsMisc", TestJsonCodecsMisc)
+	t.Run("TestJsonCodecsEmbeddedPointer", TestJsonCodecsEmbeddedPointer)
+	t.Run("TestJsonCodecChan", TestJsonCodecChan)
+	t.Run("TestJsonStdEncIntf", TestJsonStdEncIntf)
+	t.Run("TestJsonMammoth", TestJsonMammoth)
+	t.Run("TestJsonRaw", TestJsonRaw)
+	t.Run("TestJsonRpcGo", TestJsonRpcGo)
+	t.Run("TestJsonLargeInteger", TestJsonLargeInteger)
+	t.Run("TestJsonDecodeNonStringScalarInStringContext", TestJsonDecodeNonStringScalarInStringContext)
+	t.Run("TestJsonEncodeIndent", TestJsonEncodeIndent)
+}
+
+func testBincGroup(t *testing.T) {
+	t.Run("TestBincCodecsTable", TestBincCodecsTable)
+	t.Run("TestBincCodecsMisc", TestBincCodecsMisc)
+	t.Run("TestBincCodecsEmbeddedPointer", TestBincCodecsEmbeddedPointer)
+	t.Run("TestBincStdEncIntf", TestBincStdEncIntf)
+	t.Run("TestBincMammoth", TestBincMammoth)
+	t.Run("TestBincRaw", TestBincRaw)
+	t.Run("TestSimpleRpcGo", TestSimpleRpcGo)
+	t.Run("TestBincUnderlyingType", TestBincUnderlyingType)
+}
+
+func testCborGroup(t *testing.T) {
+	t.Run("TestCborCodecsTable", TestCborCodecsTable)
+	t.Run("TestCborCodecsMisc", TestCborCodecsMisc)
+	t.Run("TestCborCodecsEmbeddedPointer", TestCborCodecsEmbeddedPointer)
+	t.Run("TestCborMapEncodeForCanonical", TestCborMapEncodeForCanonical)
+	t.Run("TestCborCodecChan", TestCborCodecChan)
+	t.Run("TestCborStdEncIntf", TestCborStdEncIntf)
+	t.Run("TestCborMammoth", TestCborMammoth)
+	t.Run("TestCborRaw", TestCborRaw)
+	t.Run("TestCborRpcGo", TestCborRpcGo)
+}
+
+func TestCodecSuite(t *testing.T) {
+	testSuite(t, testCodecGroup)
+
+	testGroupResetFlags()
+
+	oldIndent, oldCharsAsis, oldPreferFloat := testJsonH.Indent, testJsonH.HTMLCharsAsIs, testJsonH.PreferFloat
+
+	testMaxInitLen = 10
+	testJsonH.Indent = 8
+	testJsonH.HTMLCharsAsIs = true
+	// testJsonH.PreferFloat = true
+	testReinit()
+	t.Run("json-spaces-htmlcharsasis-initLen10", testJsonGroup)
+
+	testMaxInitLen = 10
+	testJsonH.Indent = -1
+	testJsonH.HTMLCharsAsIs = false
+	// testJsonH.PreferFloat = false
+	testReinit()
+	t.Run("json-tabs-initLen10", testJsonGroup)
+
+	testJsonH.Indent, testJsonH.HTMLCharsAsIs, testJsonH.PreferFloat = oldIndent, oldCharsAsis, oldPreferFloat
+
+	oldIndefLen := testCborH.IndefiniteLength
+
+	testCborH.IndefiniteLength = true
+	testReinit()
+	t.Run("cbor-indefinitelength", testCborGroup)
+
+	testCborH.IndefiniteLength = oldIndefLen
+
+	oldSymbols := testBincH.getBasicHandle().AsSymbols
+
+	testBincH.getBasicHandle().AsSymbols = AsSymbolNone
+	testReinit()
+	t.Run("binc-no-symbols", testBincGroup)
+
+	testBincH.getBasicHandle().AsSymbols = AsSymbolAll
+	testReinit()
+	t.Run("binc-all-symbols", testBincGroup)
+
+	testBincH.getBasicHandle().AsSymbols = oldSymbols
+
+	testGroupResetFlags()
+}
 
 // func TestCodecSuite(t *testing.T) { testSuite2(t, testCodecGroup2) }
 // func testCodecGroup2(t *testing.T) {

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff