Browse Source

Merge pull request #8721 from andrewmeissner/feature/update-codecgen

client/v2: regenerate with latest ugorji/go/codec
Gyu-Ho Lee 8 years ago
parent
commit
f83ac25412

File diff suppressed because it is too large
+ 4637 - 298
client/keys.generated.go


+ 24 - 34
cmd/vendor/github.com/ugorji/go/codec/0doc.go

@@ -31,8 +31,13 @@ the standard library (ie json, xml, gob, etc).
 Rich Feature Set includes:
 Rich Feature Set includes:
 
 
   - Simple but extremely powerful and feature-rich API
   - Simple but extremely powerful and feature-rich API
+  - Support for go1.4 and above, while selectively using newer APIs for later releases
+  - Good code coverage ( > 70% )
   - Very High Performance.
   - Very High Performance.
     Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
     Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
+  - Careful selected use of 'unsafe' for targeted performance gains.
+    100% mode exists where 'unsafe' is not used at all.
+  - Lock-free (sans mutex) concurrency for scaling to 100's of cores
   - Multiple conversions:
   - Multiple conversions:
     Package coerces types where appropriate
     Package coerces types where appropriate
     e.g. decode an int in the stream into a float, etc.
     e.g. decode an int in the stream into a float, etc.
@@ -156,40 +161,25 @@ Sample usage model:
     //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
     //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
     client := rpc.NewClientWithCodec(rpcCodec)
     client := rpc.NewClientWithCodec(rpcCodec)
 
 
+Running Tests
+
+To run tests, use the following:
+
+    go test
+
+To run the full suite of tests, use the following:
+
+    go test -tags alltests -run Suite
+
+You can run the tag 'safe' to run tests or build in safe mode. e.g.
+
+    go test -tags safe -run Json
+    go test -tags "alltests safe" -run Suite
+
+Running Benchmarks
+
+Please see http://github.com/ugorji/go-codec-bench .
+
 */
 */
 package codec
 package codec
 
 
-// Benefits of go-codec:
-//
-//    - encoding/json always reads whole file into memory first.
-//      This makes it unsuitable for parsing very large files.
-//    - encoding/xml cannot parse into a map[string]interface{}
-//      I found this out on reading https://github.com/clbanning/mxj
-
-// TODO:
-//
-//   - optimization for codecgen:
-//     if len of entity is <= 3 words, then support a value receiver for encode.
-//   - (En|De)coder should store an error when it occurs.
-//     Until reset, subsequent calls return that error that was stored.
-//     This means that free panics must go away.
-//     All errors must be raised through errorf method.
-//   - Decoding using a chan is good, but incurs concurrency costs.
-//     This is because there's no fast way to use a channel without it
-//     having to switch goroutines constantly.
-//     Callback pattern is still the best. Maybe consider supporting something like:
-//        type X struct {
-//             Name string
-//             Ys []Y
-//             Ys chan <- Y
-//             Ys func(Y) -> call this function for each entry
-//        }
-//    - Consider adding a isZeroer interface { isZero() bool }
-//      It is used within isEmpty, for omitEmpty support.
-//    - Consider making Handle used AS-IS within the encoding/decoding session.
-//      This means that we don't cache Handle information within the (En|De)coder,
-//      except we really need it at Reset(...)
-//    - Consider adding math/big support
-//    - Consider reducing the size of the generated functions:
-//      Maybe use one loop, and put the conditionals in the loop.
-//      for ... { if cLen > 0 { if j == cLen { break } } else if dd.CheckBreak() { break } }

+ 14 - 7
cmd/vendor/github.com/ugorji/go/codec/binc.go

@@ -61,7 +61,8 @@ type bincEncDriver struct {
 	m map[string]uint16 // symbols
 	m map[string]uint16 // symbols
 	b [scratchByteArrayLen]byte
 	b [scratchByteArrayLen]byte
 	s uint16 // symbols sequencer
 	s uint16 // symbols sequencer
-	encNoSeparator
+	// encNoSeparator
+	encDriverNoopContainerWriter
 }
 }
 
 
 func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
 func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
@@ -195,11 +196,11 @@ func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
 	e.w.writen1(xtag)
 	e.w.writen1(xtag)
 }
 }
 
 
-func (e *bincEncDriver) EncodeArrayStart(length int) {
+func (e *bincEncDriver) WriteArrayStart(length int) {
 	e.encLen(bincVdArray<<4, uint64(length))
 	e.encLen(bincVdArray<<4, uint64(length))
 }
 }
 
 
-func (e *bincEncDriver) EncodeMapStart(length int) {
+func (e *bincEncDriver) WriteMapStart(length int) {
 	e.encLen(bincVdMap<<4, uint64(length))
 	e.encLen(bincVdMap<<4, uint64(length))
 }
 }
 
 
@@ -332,13 +333,14 @@ type bincDecDriver struct {
 	bd     byte
 	bd     byte
 	vd     byte
 	vd     byte
 	vs     byte
 	vs     byte
-	noStreamingCodec
-	decNoSeparator
+	// noStreamingCodec
+	// decNoSeparator
 	b [scratchByteArrayLen]byte
 	b [scratchByteArrayLen]byte
 
 
 	// linear searching on this slice is ok,
 	// linear searching on this slice is ok,
 	// because we typically expect < 32 symbols in each stream.
 	// because we typically expect < 32 symbols in each stream.
 	s []bincDecSymbol
 	s []bincDecSymbol
+	decDriverNoopContainerReader
 }
 }
 
 
 func (d *bincDecDriver) readNextBd() {
 func (d *bincDecDriver) readNextBd() {
@@ -512,7 +514,7 @@ func (d *bincDecDriver) DecodeInt(bitsize uint8) (i int64) {
 		i = -i
 		i = -i
 	}
 	}
 	if chkOvf.Int(i, bitsize) {
 	if chkOvf.Int(i, bitsize) {
-		d.d.errorf("binc: overflow integer: %v", i)
+		d.d.errorf("binc: overflow integer: %v for num bits: %v", i, bitsize)
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -804,7 +806,7 @@ func (d *bincDecDriver) DecodeNaked() {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 
 
-	n := &d.d.n
+	n := d.d.n
 	var decodeFurther bool
 	var decodeFurther bool
 
 
 	switch d.vd {
 	switch d.vd {
@@ -909,6 +911,7 @@ func (d *bincDecDriver) DecodeNaked() {
 type BincHandle struct {
 type BincHandle struct {
 	BasicHandle
 	BasicHandle
 	binaryEncodingType
 	binaryEncodingType
+	noElemSeparators
 }
 }
 
 
 func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
 func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
@@ -923,6 +926,10 @@ func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
 	return &bincDecDriver{d: d, h: h, r: d.r, br: d.bytes}
 	return &bincDecDriver{d: d, h: h, r: d.r, br: d.bytes}
 }
 }
 
 
+func (_ *BincHandle) IsBuiltinType(rt uintptr) bool {
+	return rt == timeTypId
+}
+
 func (e *bincEncDriver) reset() {
 func (e *bincEncDriver) reset() {
 	e.w = e.e.w
 	e.w = e.e.w
 	e.s = 0
 	e.s = 0

+ 36 - 10
cmd/vendor/github.com/ugorji/go/codec/cbor.go

@@ -61,7 +61,8 @@ const (
 
 
 type cborEncDriver struct {
 type cborEncDriver struct {
 	noBuiltInTypes
 	noBuiltInTypes
-	encNoSeparator
+	encDriverNoopContainerWriter
+	// encNoSeparator
 	e *Encoder
 	e *Encoder
 	w encWriter
 	w encWriter
 	h *CborHandle
 	h *CborHandle
@@ -134,21 +135,41 @@ func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Enco
 
 
 func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
 func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
 	e.encUint(uint64(re.Tag), cborBaseTag)
 	e.encUint(uint64(re.Tag), cborBaseTag)
-	if re.Data != nil {
+	if false && re.Data != nil {
 		en.encode(re.Data)
 		en.encode(re.Data)
-	} else if re.Value == nil {
+	} else if re.Value != nil {
+		en.encode(re.Value)
+	} else {
 		e.EncodeNil()
 		e.EncodeNil()
+	}
+}
+
+func (e *cborEncDriver) WriteArrayStart(length int) {
+	if e.h.IndefiniteLength {
+		e.w.writen1(cborBdIndefiniteArray)
 	} else {
 	} else {
-		en.encode(re.Value)
+		e.encLen(cborBaseArray, length)
 	}
 	}
 }
 }
 
 
-func (e *cborEncDriver) EncodeArrayStart(length int) {
-	e.encLen(cborBaseArray, 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) EncodeMapStart(length int) {
-	e.encLen(cborBaseMap, length)
+func (e *cborEncDriver) WriteArrayEnd() {
+	if e.h.IndefiniteLength {
+		e.w.writen1(cborBdBreak)
+	}
 }
 }
 
 
 func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
 func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
@@ -180,7 +201,8 @@ type cborDecDriver struct {
 	bdRead bool
 	bdRead bool
 	bd     byte
 	bd     byte
 	noBuiltInTypes
 	noBuiltInTypes
-	decNoSeparator
+	// decNoSeparator
+	decDriverNoopContainerReader
 }
 }
 
 
 func (d *cborDecDriver) readNextBd() {
 func (d *cborDecDriver) readNextBd() {
@@ -469,7 +491,7 @@ func (d *cborDecDriver) DecodeNaked() {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 
 
-	n := &d.d.n
+	n := d.d.n
 	var decodeFurther bool
 	var decodeFurther bool
 
 
 	switch d.bd {
 	switch d.bd {
@@ -577,7 +599,11 @@ func (d *cborDecDriver) DecodeNaked() {
 //
 //
 type CborHandle struct {
 type CborHandle struct {
 	binaryEncodingType
 	binaryEncodingType
+	noElemSeparators
 	BasicHandle
 	BasicHandle
+
+	// IndefiniteLength=true, means that we encode using indefinitelength
+	IndefiniteLength bool
 }
 }
 
 
 func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
 func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {

File diff suppressed because it is too large
+ 639 - 226
cmd/vendor/github.com/ugorji/go/codec/decode.go


File diff suppressed because it is too large
+ 557 - 423
cmd/vendor/github.com/ugorji/go/codec/encode.go


File diff suppressed because it is too large
+ 823 - 820
cmd/vendor/github.com/ugorji/go/codec/fast-path.generated.go


+ 7 - 6
cmd/vendor/github.com/ugorji/go/codec/fast-path.not.go

@@ -14,17 +14,18 @@ const fastpathEnabled = false
 // This tag disables fastpath during build, allowing for faster build, test execution,
 // This tag disables fastpath during build, allowing for faster build, test execution,
 // short-program runs, etc.
 // short-program runs, etc.
 
 
-func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool      { return false }
-func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool      { return false }
-func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
-func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool   { return false }
+func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool        { return false }
+func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool        { return false }
+func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool   { return false }
+func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool     { return false }
+func fastpathDecodeSetZeroTypeSwitch(iv interface{}, d *Decoder) bool { return false }
 
 
 type fastpathT struct{}
 type fastpathT struct{}
 type fastpathE struct {
 type fastpathE struct {
 	rtid  uintptr
 	rtid  uintptr
 	rt    reflect.Type
 	rt    reflect.Type
-	encfn func(*encFnInfo, reflect.Value)
-	decfn func(*decFnInfo, reflect.Value)
+	encfn func(*Encoder, *codecFnInfo, reflect.Value)
+	decfn func(*Decoder, *codecFnInfo, reflect.Value)
 }
 }
 type fastpathA [0]fastpathE
 type fastpathA [0]fastpathE
 
 

+ 18 - 21
cmd/vendor/github.com/ugorji/go/codec/gen-helper.generated.go

@@ -16,7 +16,7 @@ import (
 )
 )
 
 
 // GenVersion is the current version of codecgen.
 // GenVersion is the current version of codecgen.
-const GenVersion = 6
+const GenVersion = 8
 
 
 // This file is used to generate helper code for codecgen.
 // This file is used to generate helper code for codecgen.
 // The values here i.e. genHelper(En|De)coder are not to be used directly by
 // The values here i.e. genHelper(En|De)coder are not to be used directly by
@@ -42,6 +42,11 @@ func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
 	return genHelperDecoder{d: d}, d.d
 	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*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 type genHelperEncoder struct {
 type genHelperEncoder struct {
 	e *Encoder
 	e *Encoder
@@ -61,13 +66,14 @@ func (f genHelperEncoder) EncBasicHandle() *BasicHandle {
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperEncoder) EncBinary() bool {
 func (f genHelperEncoder) EncBinary() bool {
-	return f.e.be // f.e.hh.isBinaryEncoding()
+	return f.e.cf.be // f.e.hh.isBinaryEncoding()
 }
 }
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperEncoder) EncFallback(iv interface{}) {
 func (f genHelperEncoder) EncFallback(iv interface{}) {
 	// println(">>>>>>>>> EncFallback")
 	// println(">>>>>>>>> EncFallback")
-	f.e.encodeI(iv, false, false)
+	// f.e.encodeI(iv, false, false)
+	f.e.encodeValue(reflect.ValueOf(iv), nil, false)
 }
 }
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -90,7 +96,7 @@ func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperEncoder) EncRaw(iv Raw) {
 func (f genHelperEncoder) EncRaw(iv Raw) {
-	f.e.raw(iv)
+	f.e.rawBytes(iv)
 }
 }
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -103,7 +109,7 @@ func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperEncoder) IsJSONHandle() bool {
 func (f genHelperEncoder) IsJSONHandle() bool {
-	return f.e.js
+	return f.e.cf.js
 }
 }
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -125,13 +131,6 @@ func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
 	return false
 	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 -----------------
 // ---------------- DECODER FOLLOWS -----------------
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -157,7 +156,12 @@ func (f genHelperDecoder) DecScratchBuffer() []byte {
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
 func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
 	// println(">>>>>>>>> DecFallback")
 	// println(">>>>>>>>> DecFallback")
-	f.d.decodeI(iv, chkPtr, false, false, false)
+	rv := reflect.ValueOf(iv)
+	if chkPtr {
+		rv = f.d.ensureDecodeable(rv)
+	}
+	f.d.decodeValue(rv, nil, false, false)
+	// f.d.decodeValueFallback(rv)
 }
 }
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -203,7 +207,7 @@ func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 func (f genHelperDecoder) DecRaw() []byte {
 func (f genHelperDecoder) DecRaw() []byte {
-	return f.d.raw()
+	return f.d.rawBytes()
 }
 }
 
 
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
 // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
@@ -244,10 +248,3 @@ func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
 func (f genHelperDecoder) StringView(v []byte) string {
 func (f genHelperDecoder) StringView(v []byte) string {
 	return stringView(v)
 	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)
-	}
-}

+ 22 - 12
cmd/vendor/github.com/ugorji/go/codec/gen.generated.go

@@ -16,7 +16,7 @@ if {{var "v"}} == nil {
 }
 }
 var {{var "mk"}} {{ .KTyp }}
 var {{var "mk"}} {{ .KTyp }}
 var {{var "mv"}} {{ .Typ }}
 var {{var "mv"}} {{ .Typ }}
-var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
+var {{var "mg"}}, {{var "mdn"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
 if {{var "bh"}}.MapValueReset {
 if {{var "bh"}}.MapValueReset {
 	{{if decElemKindPtr}}{{var "mg"}} = true
 	{{if decElemKindPtr}}{{var "mg"}} = true
 	{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
 	{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
@@ -25,7 +25,7 @@ if {{var "bh"}}.MapValueReset {
 if {{var "l"}} != 0 {
 if {{var "l"}} != 0 {
 {{var "hl"}} := {{var "l"}} > 0 
 {{var "hl"}} := {{var "l"}} > 0 
 	for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
 	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 }}
 	{{ $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"}} {
 {{ 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"}})
 		{{var "mk"}} = string({{var "bv"}})
@@ -37,14 +37,17 @@ if {{var "l"}} != 0 {
 			{{var "ms"}} = false
 			{{var "ms"}} = false
 		} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
 		} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
 	} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
 	} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
-	z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
-	{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
-	if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
+	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"}} {
+		if {{ var "bh" }}.DeleteOnNilMapValue { delete({{var "v"}}, {{var "mk"}}) } else { {{var "v"}}[{{var "mk"}}] = {{decElemZero}} }
+	} else if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
 		{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
 		{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
 	}
 	}
 }
 }
 } // else len==0: TODO: Should we clear map entries?
 } // else len==0: TODO: Should we clear map entries?
-z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
+r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
 `
 `
 
 
 const genDecListTmpl = `
 const genDecListTmpl = `
@@ -65,7 +68,7 @@ if {{var "l"}} == 0 {
 	} {{end}}
 	} {{end}}
 } else {
 } else {
 	{{var "hl"}} := {{var "l"}} > 0
 	{{var "hl"}} := {{var "l"}} > 0
-	var {{var "rl"}} int 
+	var {{var "rl"}} int; _ =  {{var "rl"}}
 	{{if isSlice }} if {{var "hl"}} {
 	{{if isSlice }} if {{var "hl"}} {
 	if {{var "l"}} > cap({{var "v"}}) {
 	if {{var "l"}} > cap({{var "v"}}) {
 		{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
 		{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
@@ -80,9 +83,10 @@ if {{var "l"}} == 0 {
 		{{var "c"}} = true
 		{{var "c"}} = true
 	}
 	}
 	} {{end}}
 	} {{end}}
-	{{var "j"}} := 0
+	var {{var "j"}} int 
+    // var {{var "dn"}} bool 
 	for ; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
 	for ; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
-		if {{var "j"}} == 0 && len({{var "v"}}) == 0 {
+		{{if not isArray}} if {{var "j"}} == 0 && len({{var "v"}}) == 0 {
 			if {{var "hl"}} {
 			if {{var "hl"}} {
 				{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
 				{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
 			} else {
 			} else {
@@ -90,20 +94,26 @@ if {{var "l"}} == 0 {
 			}
 			}
 			{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
 			{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
 			{{var "c"}} = true 
 			{{var "c"}} = true 
-		}
+		}{{end}}
+		{{var "h"}}.ElemContainerState({{var "j"}})
+        // {{var "dn"}} = r.TryDecodeAsNil()
+        {{if isChan}}{{ $x := printf "%[1]vv%[2]v" .TempVar .Rand }}var {{var $x}} {{ .Typ }}
+		{{ decLineVar $x }}
+		{{var "v"}} <- {{ $x }}
+        {{else}}
 		// if indefinite, etc, then expand the slice if necessary
 		// if indefinite, etc, then expand the slice if necessary
 		var {{var "db"}} bool
 		var {{var "db"}} bool
 		if {{var "j"}} >= len({{var "v"}}) {
 		if {{var "j"}} >= len({{var "v"}}) {
 			{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }}); {{var "c"}} = true
 			{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }}); {{var "c"}} = true
-			{{end}} {{if isArray}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
+			{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
 			{{end}}
 			{{end}}
 		}
 		}
-		{{var "h"}}.ElemContainerState({{var "j"}})
 		if {{var "db"}} {
 		if {{var "db"}} {
 			z.DecSwallow()
 			z.DecSwallow()
 		} else {
 		} else {
 			{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
 			{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
 		}
 		}
+        {{end}}
 	}
 	}
 	{{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
 	{{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
 		{{var "v"}} = {{var "v"}}[:{{var "j"}}]
 		{{var "v"}} = {{var "v"}}[:{{var "j"}}]

+ 128 - 109
cmd/vendor/github.com/ugorji/go/codec/gen.go

@@ -101,7 +101,7 @@ import (
 // v4: Removed separator support from (en|de)cDriver, and refactored codec(gen)
 // v4: Removed separator support from (en|de)cDriver, and refactored codec(gen)
 // v5: changes to support faster json decoding. Let encoder/decoder maintain state of collections.
 // v5: changes to support faster json decoding. Let encoder/decoder maintain state of collections.
 // v6: removed unsafe from gen, and now uses codecgen.exec tag
 // v6: removed unsafe from gen, and now uses codecgen.exec tag
-const genVersion = 6
+const genVersion = 8
 
 
 const (
 const (
 	genCodecPkg        = "codec1978"
 	genCodecPkg        = "codec1978"
@@ -163,13 +163,16 @@ type genRunner struct {
 
 
 	ti *TypeInfos
 	ti *TypeInfos
 	// rr *rand.Rand // random generator for file-specific types
 	// rr *rand.Rand // random generator for file-specific types
+
+	nx bool // no extensions
 }
 }
 
 
 // Gen will write a complete go file containing Selfer implementations for each
 // Gen will write a complete go file containing Selfer implementations for each
 // type passed. All the types must be in the same package.
 // type passed. All the types must be in the same package.
 //
 //
 // Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
 // Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
-func Gen(w io.Writer, buildTags, pkgName, uid string, ti *TypeInfos, typ ...reflect.Type) {
+func Gen(w io.Writer, buildTags, pkgName, uid string, noExtensions bool,
+	ti *TypeInfos, typ ...reflect.Type) {
 	// All types passed to this method do not have a codec.Selfer method implemented directly.
 	// All types passed to this method do not have a codec.Selfer method implemented directly.
 	// codecgen already checks the AST and skips any types that define the codec.Selfer methods.
 	// codecgen already checks the AST and skips any types that define the codec.Selfer methods.
 	// Consequently, there's no need to check and trim them if they implement codec.Selfer
 	// Consequently, there's no need to check and trim them if they implement codec.Selfer
@@ -190,6 +193,7 @@ func Gen(w io.Writer, buildTags, pkgName, uid string, ti *TypeInfos, typ ...refl
 		bp:  genImportPath(typ[0]),
 		bp:  genImportPath(typ[0]),
 		xs:  uid,
 		xs:  uid,
 		ti:  ti,
 		ti:  ti,
+		nx:  noExtensions,
 	}
 	}
 	if x.ti == nil {
 	if x.ti == nil {
 		x.ti = defTypeInfos
 		x.ti = defTypeInfos
@@ -713,7 +717,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
 		x.linef("r.EncodeBuiltin(%s, %s)", vrtid, varname)
 		x.linef("r.EncodeBuiltin(%s, %s)", vrtid, varname)
 	}
 	}
 	// only check for extensions if the type is named, and has a packagePath.
 	// only check for extensions if the type is named, and has a packagePath.
-	if genImportPath(t) != "" && t.Name() != "" {
+	if !x.nx && genImportPath(t) != "" && t.Name() != "" {
 		// first check if extensions are configued, before doing the interface conversion
 		// first check if extensions are configued, before doing the interface conversion
 		x.linef("} else if z.HasExtensions() && z.EncExt(%s) {", varname)
 		x.linef("} else if z.HasExtensions() && z.EncExt(%s) {", varname)
 	}
 	}
@@ -773,7 +777,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
 			x.line("r.EncodeStringBytes(codecSelferC_RAW" + x.xs + ", []byte(" + varname + "))")
 			x.line("r.EncodeStringBytes(codecSelferC_RAW" + x.xs + ", []byte(" + varname + "))")
 		} else if fastpathAV.index(rtid) != -1 {
 		} else if fastpathAV.index(rtid) != -1 {
 			g := x.newGenV(t)
 			g := x.newGenV(t)
-			x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", false, e)")
+			x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
 		} else {
 		} else {
 			x.xtraSM(varname, true, t)
 			x.xtraSM(varname, true, t)
 			// x.encListFallback(varname, rtid, t)
 			// x.encListFallback(varname, rtid, t)
@@ -787,7 +791,7 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
 		// x.line("if " + varname + " == nil { \nr.EncodeNil()\n } else { ")
 		// x.line("if " + varname + " == nil { \nr.EncodeNil()\n } else { ")
 		if fastpathAV.index(rtid) != -1 {
 		if fastpathAV.index(rtid) != -1 {
 			g := x.newGenV(t)
 			g := x.newGenV(t)
-			x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", false, e)")
+			x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
 		} else {
 		} else {
 			x.xtraSM(varname, true, t)
 			x.xtraSM(varname, true, t)
 			// x.encMapFallback(varname, rtid, t)
 			// x.encMapFallback(varname, rtid, t)
@@ -845,55 +849,64 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 	// number of non-empty things we write out first.
 	// number of non-empty things we write out first.
 	// This is required as we need to pre-determine the size of the container,
 	// This is required as we need to pre-determine the size of the container,
 	// to support length-prefixing.
 	// to support length-prefixing.
-	x.linef("var %s [%v]bool", numfieldsvar, len(tisfi))
-	x.linef("_, _, _ = %s, %s, %s", sepVarname, numfieldsvar, struct2arrvar)
+	if ti.anyOmitEmpty {
+		x.linef("var %s [%v]bool", numfieldsvar, len(tisfi))
+		x.linef("_ = %s", numfieldsvar)
+	}
+	x.linef("_, _ = %s, %s", sepVarname, struct2arrvar)
 	x.linef("const %s bool = %v", ti2arrayvar, ti.toArray)
 	x.linef("const %s bool = %v", ti2arrayvar, ti.toArray)
-	nn := 0
-	for j, si := range tisfi {
-		if !si.omitEmpty {
-			nn++
-			continue
-		}
-		var t2 reflect.StructField
-		var omitline string
-		if si.i != -1 {
-			t2 = t.Field(int(si.i))
-		} else {
-			t2typ := t
-			varname3 := varname
-			for _, ix := range si.is {
-				for t2typ.Kind() == reflect.Ptr {
-					t2typ = t2typ.Elem()
-				}
-				t2 = t2typ.Field(ix)
-				t2typ = t2.Type
-				varname3 = varname3 + "." + t2.Name
-				if t2typ.Kind() == reflect.Ptr {
-					omitline += varname3 + " != nil && "
+	var nn int
+	if ti.anyOmitEmpty {
+		for j, si := range tisfi {
+			if !si.omitEmpty {
+				nn++
+				continue
+			}
+			var t2 reflect.StructField
+			var omitline string
+			{
+				t2typ := t
+				varname3 := varname
+				for ij, ix := range si.is {
+					if uint8(ij) == si.nis {
+						break
+					}
+					for t2typ.Kind() == reflect.Ptr {
+						t2typ = t2typ.Elem()
+					}
+					t2 = t2typ.Field(int(ix))
+					t2typ = t2.Type
+					varname3 = varname3 + "." + t2.Name
+					if t2typ.Kind() == reflect.Ptr {
+						omitline += varname3 + " != nil && "
+					}
 				}
 				}
 			}
 			}
+			// never check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
+			// also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
+			switch t2.Type.Kind() {
+			case reflect.Struct:
+				omitline += " true"
+			case reflect.Map, reflect.Slice, reflect.Array, reflect.Chan:
+				omitline += "len(" + varname + "." + t2.Name + ") != 0"
+			default:
+				omitline += varname + "." + t2.Name + " != " + x.genZeroValueR(t2.Type)
+			}
+			x.linef("%s[%v] = %s", numfieldsvar, j, omitline)
 		}
 		}
-		// never check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
-		// also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
-		switch t2.Type.Kind() {
-		case reflect.Struct:
-			omitline += " true"
-		case reflect.Map, reflect.Slice, reflect.Array, reflect.Chan:
-			omitline += "len(" + varname + "." + t2.Name + ") != 0"
-		default:
-			omitline += varname + "." + t2.Name + " != " + x.genZeroValueR(t2.Type)
-		}
-		x.linef("%s[%v] = %s", numfieldsvar, j, omitline)
 	}
 	}
-	x.linef("var %snn%s int", genTempVarPfx, i)
+	// x.linef("var %snn%s int", genTempVarPfx, i)
 	x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
 	x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
-	x.line("r.EncodeArrayStart(" + strconv.FormatInt(int64(len(tisfi)), 10) + ")")
+	x.linef("r.WriteArrayStart(%d)", len(tisfi))
 	x.linef("} else {") // if not ti.toArray
 	x.linef("} else {") // if not ti.toArray
-	x.linef("%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("%snn%s = %v", genTempVarPfx, i, 0)
-	// x.line("r.EncodeMapStart(" + strconv.FormatInt(int64(len(tisfi)), 10) + ")")
+	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.WriteMapStart(%snn%s)", genTempVarPfx, i)
+		x.linef("%snn%s = %v", genTempVarPfx, i, 0)
+	} else {
+		x.linef("r.WriteMapStart(%d)", len(tisfi))
+	}
 	x.line("}") // close if not StructToArray
 	x.line("}") // close if not StructToArray
 
 
 	for j, si := range tisfi {
 	for j, si := range tisfi {
@@ -901,17 +914,18 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 		isNilVarName := genTempVarPfx + "n" + i
 		isNilVarName := genTempVarPfx + "n" + i
 		var labelUsed bool
 		var labelUsed bool
 		var t2 reflect.StructField
 		var t2 reflect.StructField
-		if si.i != -1 {
-			t2 = t.Field(int(si.i))
-		} else {
+		{
 			t2typ := t
 			t2typ := t
 			varname3 := varname
 			varname3 := varname
-			for _, ix := range si.is {
+			for ij, ix := range si.is {
+				if uint8(ij) == si.nis {
+					break
+				}
 				// fmt.Printf("%%%% %v, ix: %v\n", t2typ, ix)
 				// fmt.Printf("%%%% %v, ix: %v\n", t2typ, ix)
 				for t2typ.Kind() == reflect.Ptr {
 				for t2typ.Kind() == reflect.Ptr {
 					t2typ = t2typ.Elem()
 					t2typ = t2typ.Elem()
 				}
 				}
-				t2 = t2typ.Field(ix)
+				t2 = t2typ.Field(int(ix))
 				t2typ = t2.Type
 				t2typ = t2.Type
 				varname3 = varname3 + "." + t2.Name
 				varname3 = varname3 + "." + t2.Name
 				if t2typ.Kind() == reflect.Ptr {
 				if t2typ.Kind() == reflect.Ptr {
@@ -934,9 +948,10 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 
 
 		x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray
 		x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray
 		if labelUsed {
 		if labelUsed {
-			x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
+			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 {
 		if si.omitEmpty {
 			x.linef("if %s[%v] {", numfieldsvar, j)
 			x.linef("if %s[%v] {", numfieldsvar, j)
 		}
 		}
@@ -955,9 +970,9 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 		if si.omitEmpty {
 		if si.omitEmpty {
 			x.linef("if %s[%v] {", numfieldsvar, j)
 			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.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 {
 		if labelUsed {
 			x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
 			x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
 			x.encVar(varname+"."+t2.Name, t2.Type)
 			x.encVar(varname+"."+t2.Name, t2.Type)
@@ -971,9 +986,9 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
 		x.linef("} ") // end if/else ti.toArray
 		x.linef("} ") // end if/else ti.toArray
 	}
 	}
 	x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if 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.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("}")
 	x.line("}")
 
 
 }
 }
@@ -989,36 +1004,36 @@ func (x *genRunner) encListFallback(varname string, t reflect.Type) {
 	}
 	}
 	i := x.varsfx()
 	i := x.varsfx()
 	g := genTempVarPfx
 	g := genTempVarPfx
-	x.line("r.EncodeArrayStart(len(" + varname + "))")
+	x.line("r.WriteArrayStart(len(" + varname + "))")
 	if t.Kind() == reflect.Chan {
 	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("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)
 		x.linef("%sv%s := <-%s", g, i, varname)
 	} else {
 	} else {
 		// x.linef("for %si%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
 		// 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("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.encVar(genTempVarPfx+"v"+i, t.Elem())
 	x.line("}")
 	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) {
 func (x *genRunner) encMapFallback(varname string, t reflect.Type) {
 	// TODO: expand this to handle canonical.
 	// TODO: expand this to handle canonical.
 	i := x.varsfx()
 	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.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.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.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.encVar(genTempVarPfx+"v"+i, t.Elem())
 	x.line("}")
 	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 string, t reflect.Type, canBeNil bool) {
+func (x *genRunner) decVar(varname, decodedNilVarname string, t reflect.Type, canBeNil bool) {
 	// We only encode as nil if a nillable value.
 	// We only encode as nil if a nillable value.
 	// This removes some of the wasted checks for TryDecodeAsNil.
 	// This removes some of the wasted checks for TryDecodeAsNil.
 	// We need to think about this more, to see what happens if omitempty, etc
 	// We need to think about this more, to see what happens if omitempty, etc
@@ -1031,7 +1046,9 @@ func (x *genRunner) decVar(varname string, t reflect.Type, canBeNil bool) {
 	}
 	}
 	if canBeNil {
 	if canBeNil {
 		x.line("if r.TryDecodeAsNil() {")
 		x.line("if r.TryDecodeAsNil() {")
-		if t.Kind() == reflect.Ptr {
+		if decodedNilVarname != "" {
+			x.line(decodedNilVarname + " = true")
+		} else if t.Kind() == reflect.Ptr {
 			x.line("if " + varname + " != nil { ")
 			x.line("if " + varname + " != nil { ")
 
 
 			// if varname is a field of a struct (has a dot in it),
 			// if varname is a field of a struct (has a dot in it),
@@ -1149,7 +1166,7 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
 		x.linef("r.DecodeBuiltin(%s, %s)", vrtid, varname)
 		x.linef("r.DecodeBuiltin(%s, %s)", vrtid, varname)
 	}
 	}
 	// only check for extensions if the type is named, and has a packagePath.
 	// only check for extensions if the type is named, and has a packagePath.
-	if genImportPath(t) != "" && t.Name() != "" {
+	if !x.nx && genImportPath(t) != "" && t.Name() != "" {
 		// first check if extensions are configued, before doing the interface conversion
 		// first check if extensions are configued, before doing the interface conversion
 		x.linef("} else if z.HasExtensions() && z.DecExt(%s) {", varname)
 		x.linef("} else if z.HasExtensions() && z.DecExt(%s) {", varname)
 	}
 	}
@@ -1227,7 +1244,7 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
 			x.line("*" + varname + " = r.DecodeBytes(*(*[]byte)(" + varname + "), false)")
 			x.line("*" + varname + " = r.DecodeBytes(*(*[]byte)(" + varname + "), false)")
 		} else if fastpathAV.index(rtid) != -1 {
 		} else if fastpathAV.index(rtid) != -1 {
 			g := x.newGenV(t)
 			g := x.newGenV(t)
-			x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", false, d)")
+			x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", d)")
 		} else {
 		} else {
 			x.xtraSM(varname, false, t)
 			x.xtraSM(varname, false, t)
 			// x.decListFallback(varname, rtid, false, t)
 			// x.decListFallback(varname, rtid, false, t)
@@ -1239,7 +1256,7 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
 		// - else call Encoder.encode(XXX) on it.
 		// - else call Encoder.encode(XXX) on it.
 		if fastpathAV.index(rtid) != -1 {
 		if fastpathAV.index(rtid) != -1 {
 			g := x.newGenV(t)
 			g := x.newGenV(t)
-			x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", false, d)")
+			x.line("z.F." + g.MethodNamePfx("Dec", false) + "X(" + varname + ", d)")
 		} else {
 		} else {
 			x.xtraSM(varname, false, t)
 			x.xtraSM(varname, false, t)
 			// x.decMapFallback(varname, rtid, t)
 			// x.decMapFallback(varname, rtid, t)
@@ -1333,13 +1350,13 @@ func (x *genRunner) decListFallback(varname string, rtid uintptr, t reflect.Type
 	funcs := make(template.FuncMap)
 	funcs := make(template.FuncMap)
 
 
 	funcs["decLineVar"] = func(varname string) string {
 	funcs["decLineVar"] = func(varname string) string {
-		x.decVar(varname, telem, false)
-		return ""
-	}
-	funcs["decLine"] = func(pfx string) string {
-		x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false)
+		x.decVar(varname, "", telem, false)
 		return ""
 		return ""
 	}
 	}
+	// funcs["decLine"] = func(pfx string) string {
+	// 	x.decVar(ts.TempVar+pfx+ts.Rand, "", reflect.PtrTo(telem), false)
+	// 	return ""
+	// }
 	funcs["var"] = func(s string) string {
 	funcs["var"] = func(s string) string {
 		return ts.TempVar + s + ts.Rand
 		return ts.TempVar + s + ts.Rand
 	}
 	}
@@ -1395,21 +1412,21 @@ func (x *genRunner) decMapFallback(varname string, rtid uintptr, t reflect.Type)
 		return telem.Kind() == reflect.Interface
 		return telem.Kind() == reflect.Interface
 	}
 	}
 	funcs["decLineVarK"] = func(varname string) string {
 	funcs["decLineVarK"] = func(varname string) string {
-		x.decVar(varname, tkey, false)
+		x.decVar(varname, "", tkey, false)
 		return ""
 		return ""
 	}
 	}
-	funcs["decLineVar"] = func(varname string) string {
-		x.decVar(varname, telem, false)
-		return ""
-	}
-	funcs["decLineK"] = func(pfx string) string {
-		x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(tkey), false)
-		return ""
-	}
-	funcs["decLine"] = func(pfx string) string {
-		x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false)
+	funcs["decLineVar"] = func(varname, decodedNilVarname string) string {
+		x.decVar(varname, decodedNilVarname, telem, false)
 		return ""
 		return ""
 	}
 	}
+	// funcs["decLineK"] = func(pfx string) string {
+	// 	x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(tkey), false)
+	// 	return ""
+	// }
+	// funcs["decLine"] = func(pfx string) string {
+	// 	x.decVar(ts.TempVar+pfx+ts.Rand, reflect.PtrTo(telem), false)
+	// 	return ""
+	// }
 	funcs["var"] = func(s string) string {
 	funcs["var"] = func(s string) string {
 		return ts.TempVar + s + ts.Rand
 		return ts.TempVar + s + ts.Rand
 	}
 	}
@@ -1430,18 +1447,19 @@ func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintpt
 	for _, si := range tisfi {
 	for _, si := range tisfi {
 		x.line("case \"" + si.encName + "\":")
 		x.line("case \"" + si.encName + "\":")
 		var t2 reflect.StructField
 		var t2 reflect.StructField
-		if si.i != -1 {
-			t2 = t.Field(int(si.i))
-		} else {
+		{
 			//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
 			//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
 			// t2 = t.FieldByIndex(si.is)
 			// t2 = t.FieldByIndex(si.is)
 			t2typ := t
 			t2typ := t
 			varname3 := varname
 			varname3 := varname
-			for _, ix := range si.is {
+			for ij, ix := range si.is {
+				if uint8(ij) == si.nis {
+					break
+				}
 				for t2typ.Kind() == reflect.Ptr {
 				for t2typ.Kind() == reflect.Ptr {
 					t2typ = t2typ.Elem()
 					t2typ = t2typ.Elem()
 				}
 				}
-				t2 = t2typ.Field(ix)
+				t2 = t2typ.Field(int(ix))
 				t2typ = t2.Type
 				t2typ = t2.Type
 				varname3 = varname3 + "." + t2.Name
 				varname3 = varname3 + "." + t2.Name
 				if t2typ.Kind() == reflect.Ptr {
 				if t2typ.Kind() == reflect.Ptr {
@@ -1449,7 +1467,7 @@ func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintpt
 				}
 				}
 			}
 			}
 		}
 		}
-		x.decVar(varname+"."+t2.Name, t2.Type, false)
+		x.decVar(varname+"."+t2.Name, "", t2.Type, false)
 	}
 	}
 	x.line("default:")
 	x.line("default:")
 	// pass the slice here, so that the string will not escape, and maybe save allocation
 	// pass the slice here, so that the string will not escape, and maybe save allocation
@@ -1480,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.linef("if %shl%s { if %sj%s >= %s { break }", tpfx, i, tpfx, i, lenvarname)
 		x.line("} else { if r.CheckBreak() { break }; }")
 		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()")
 	x.line(kName + "Slc = r.DecodeStringAsBytes()")
 	// let string be scoped to this loop alone, so it doesn't escape.
 	// let string be scoped to this loop alone, so it doesn't escape.
 	x.line(kName + " := string(" + kName + "Slc)")
 	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.decStructMapSwitch(kName, varname, rtid, t)
 
 
 	x.line("} // end for " + tpfx + "j" + i)
 	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) {
 func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) {
@@ -1501,18 +1519,19 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
 	x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length
 	x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length
 	for _, si := range tisfi {
 	for _, si := range tisfi {
 		var t2 reflect.StructField
 		var t2 reflect.StructField
-		if si.i != -1 {
-			t2 = t.Field(int(si.i))
-		} else {
+		{
 			//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
 			//we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
 			// t2 = t.FieldByIndex(si.is)
 			// t2 = t.FieldByIndex(si.is)
 			t2typ := t
 			t2typ := t
 			varname3 := varname
 			varname3 := varname
-			for _, ix := range si.is {
+			for ij, ix := range si.is {
+				if uint8(ij) == si.nis {
+					break
+				}
 				for t2typ.Kind() == reflect.Ptr {
 				for t2typ.Kind() == reflect.Ptr {
 					t2typ = t2typ.Elem()
 					t2typ = t2typ.Elem()
 				}
 				}
-				t2 = t2typ.Field(ix)
+				t2 = t2typ.Field(int(ix))
 				t2typ = t2.Type
 				t2typ = t2.Type
 				varname3 = varname3 + "." + t2.Name
 				varname3 = varname3 + "." + t2.Name
 				if t2typ.Kind() == reflect.Ptr {
 				if t2typ.Kind() == reflect.Ptr {
@@ -1524,10 +1543,10 @@ 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() }",
 		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, tpfx, i, tpfx, i,
 			tpfx, i, lenvarname, 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.decVar(varname+"."+t2.Name, t2.Type, true)
+		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.
 	// read remaining values and throw away.
 	x.line("for {")
 	x.line("for {")
@@ -1535,10 +1554,10 @@ func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid
 		tpfx, i, tpfx, i, tpfx, i,
 		tpfx, i, tpfx, i, tpfx, i,
 		tpfx, i, lenvarname, tpfx, i)
 		tpfx, i, lenvarname, tpfx, i)
 	x.linef("if %sb%s { break }", 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.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i)
 	x.line("}")
 	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) {
 func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
@@ -1548,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.linef("if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs)
 	x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()")
 	x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()")
 	x.linef("if %sl%s == 0 {", genTempVarPfx, i)
 	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 {
 	if genUseOneFunctionForDecStructMap {
 		x.line("} else { ")
 		x.line("} else { ")
 		x.linef("x.codecDecodeSelfFromMap(%sl%s, d)", genTempVarPfx, i)
 		x.linef("x.codecDecodeSelfFromMap(%sl%s, d)", genTempVarPfx, i)
@@ -1564,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.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs)
 	x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()")
 	x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()")
 	x.linef("if %sl%s == 0 {", genTempVarPfx, i)
 	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.line("} else { ")
 	x.linef("x.codecDecodeSelfFromArray(%sl%s, d)", genTempVarPfx, i)
 	x.linef("x.codecDecodeSelfFromArray(%sl%s, d)", genTempVarPfx, i)
 	x.line("}")
 	x.line("}")

File diff suppressed because it is too large
+ 613 - 124
cmd/vendor/github.com/ugorji/go/codec/helper.go


+ 54 - 41
cmd/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go

@@ -30,6 +30,19 @@ func bytesView(v string) []byte {
 	return []byte(v)
 	return []byte(v)
 }
 }
 
 
+func definitelyNil(v interface{}) bool {
+	return false
+	// rv := reflect.ValueOf(v)
+	// switch rv.Kind() {
+	// case reflect.Invalid:
+	// 	return true
+	// case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Slice, reflect.Map, reflect.Func:
+	// 	return rv.IsNil()
+	// default:
+	// 	return false
+	// }
+}
+
 // // keepAlive4BytesView maintains a reference to the input parameter for bytesView.
 // // keepAlive4BytesView maintains a reference to the input parameter for bytesView.
 // //
 // //
 // // Usage: call this at point where done with the bytes view.
 // // Usage: call this at point where done with the bytes view.
@@ -48,13 +61,17 @@ func rt2id(rt reflect.Type) uintptr {
 	return reflect.ValueOf(rt).Pointer()
 	return reflect.ValueOf(rt).Pointer()
 }
 }
 
 
+func rv2rtid(rv reflect.Value) uintptr {
+	return reflect.ValueOf(rv.Type()).Pointer()
+}
+
 // --------------------------
 // --------------------------
-type ptrToRvMap struct{}
+// type ptrToRvMap struct{}
 
 
-func (_ *ptrToRvMap) init() {}
-func (_ *ptrToRvMap) get(i interface{}) reflect.Value {
-	return reflect.ValueOf(i).Elem()
-}
+// func (_ *ptrToRvMap) init() {}
+// func (_ *ptrToRvMap) get(i interface{}) reflect.Value {
+// 	return reflect.ValueOf(i).Elem()
+// }
 
 
 // --------------------------
 // --------------------------
 type atomicTypeInfoSlice struct {
 type atomicTypeInfoSlice struct {
@@ -74,70 +91,66 @@ func (x *atomicTypeInfoSlice) store(p *[]rtid2ti) {
 }
 }
 
 
 // --------------------------
 // --------------------------
-func (f *decFnInfo) raw(rv reflect.Value) {
-	rv.SetBytes(f.d.raw())
+func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
+	rv.SetBytes(d.rawBytes())
 }
 }
 
 
-func (f *decFnInfo) kString(rv reflect.Value) {
-	rv.SetString(f.d.d.DecodeString())
+func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
+	rv.SetString(d.d.DecodeString())
 }
 }
 
 
-func (f *decFnInfo) kBool(rv reflect.Value) {
-	rv.SetBool(f.d.d.DecodeBool())
+func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
+	rv.SetBool(d.d.DecodeBool())
 }
 }
 
 
-func (f *decFnInfo) kFloat32(rv reflect.Value) {
-	rv.SetFloat(f.d.d.DecodeFloat(true))
+func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+	rv.SetFloat(d.d.DecodeFloat(true))
 }
 }
 
 
-func (f *decFnInfo) kFloat64(rv reflect.Value) {
-	rv.SetFloat(f.d.d.DecodeFloat(false))
+func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+	rv.SetFloat(d.d.DecodeFloat(false))
 }
 }
 
 
-func (f *decFnInfo) kInt(rv reflect.Value) {
-	rv.SetInt(f.d.d.DecodeInt(intBitsize))
+func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
+	rv.SetInt(d.d.DecodeInt(intBitsize))
 }
 }
 
 
-func (f *decFnInfo) kInt8(rv reflect.Value) {
-	rv.SetInt(f.d.d.DecodeInt(8))
+func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+	rv.SetInt(d.d.DecodeInt(8))
 }
 }
 
 
-func (f *decFnInfo) kInt16(rv reflect.Value) {
-	rv.SetInt(f.d.d.DecodeInt(16))
+func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+	rv.SetInt(d.d.DecodeInt(16))
 }
 }
 
 
-func (f *decFnInfo) kInt32(rv reflect.Value) {
-	rv.SetInt(f.d.d.DecodeInt(32))
+func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+	rv.SetInt(d.d.DecodeInt(32))
 }
 }
 
 
-func (f *decFnInfo) kInt64(rv reflect.Value) {
-	rv.SetInt(f.d.d.DecodeInt(64))
+func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+	rv.SetInt(d.d.DecodeInt(64))
 }
 }
 
 
-func (f *decFnInfo) kUint(rv reflect.Value) {
-	rv.SetUint(f.d.d.DecodeUint(uintBitsize))
+func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
+	rv.SetUint(d.d.DecodeUint(uintBitsize))
 }
 }
 
 
-func (f *decFnInfo) kUintptr(rv reflect.Value) {
-	rv.SetUint(f.d.d.DecodeUint(uintBitsize))
+func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+	rv.SetUint(d.d.DecodeUint(uintBitsize))
 }
 }
 
 
-func (f *decFnInfo) kUint8(rv reflect.Value) {
-	rv.SetUint(f.d.d.DecodeUint(8))
+func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+	rv.SetUint(d.d.DecodeUint(8))
 }
 }
 
 
-func (f *decFnInfo) kUint16(rv reflect.Value) {
-	rv.SetUint(f.d.d.DecodeUint(16))
+func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+	rv.SetUint(d.d.DecodeUint(16))
 }
 }
 
 
-func (f *decFnInfo) kUint32(rv reflect.Value) {
-	rv.SetUint(f.d.d.DecodeUint(32))
+func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+	rv.SetUint(d.d.DecodeUint(32))
 }
 }
 
 
-func (f *decFnInfo) kUint64(rv reflect.Value) {
-	rv.SetUint(f.d.d.DecodeUint(64))
+func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+	rv.SetUint(d.d.DecodeUint(64))
 }
 }
-
-// func i2rv(i interface{}) reflect.Value {
-// 	return reflect.ValueOf(i)
-// }

+ 49 - 93
cmd/vendor/github.com/ugorji/go/codec/helper_unsafe.go

@@ -18,6 +18,8 @@ import (
 
 
 // var zeroRTv [4]uintptr
 // var zeroRTv [4]uintptr
 
 
+const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
+
 type unsafeString struct {
 type unsafeString struct {
 	Data uintptr
 	Data uintptr
 	Len  int
 	Len  int
@@ -60,6 +62,10 @@ func bytesView(v string) []byte {
 	return *(*[]byte)(unsafe.Pointer(&bx))
 	return *(*[]byte)(unsafe.Pointer(&bx))
 }
 }
 
 
+func definitelyNil(v interface{}) bool {
+	return (*unsafeIntf)(unsafe.Pointer(&v)).word == nil
+}
+
 // func keepAlive4BytesView(v string) {
 // func keepAlive4BytesView(v string) {
 // 	runtime.KeepAlive(v)
 // 	runtime.KeepAlive(v)
 // }
 // }
@@ -68,21 +74,19 @@ func bytesView(v string) []byte {
 // 	runtime.KeepAlive(v)
 // 	runtime.KeepAlive(v)
 // }
 // }
 
 
-const _unsafe_rv2i_is_safe = false
-
 // TODO: consider a more generally-known optimization for reflect.Value ==> Interface
 // TODO: consider a more generally-known optimization for reflect.Value ==> Interface
 //
 //
 // Currently, we use this fragile method that taps into implememtation details from
 // Currently, we use this fragile method that taps into implememtation details from
 // the source go stdlib reflect/value.go,
 // the source go stdlib reflect/value.go,
 // and trims the implementation.
 // and trims the implementation.
 func rv2i(rv reflect.Value) interface{} {
 func rv2i(rv reflect.Value) interface{} {
-	if _unsafe_rv2i_is_safe {
+	if false {
 		return rv.Interface()
 		return rv.Interface()
 	}
 	}
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	// references that are single-words (map, ptr) may be double-referenced as flagIndir
 	// references that are single-words (map, ptr) may be double-referenced as flagIndir
 	kk := urv.flag & (1<<5 - 1)
 	kk := urv.flag & (1<<5 - 1)
-	if (kk == uintptr(reflect.Map) || kk == uintptr(reflect.Ptr)) && urv.flag&(1<<7) != 0 {
+	if (kk == uintptr(reflect.Map) || kk == uintptr(reflect.Ptr)) && urv.flag&unsafeFlagIndir != 0 {
 		return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
 		return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
 	}
 	}
 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
@@ -92,6 +96,10 @@ func rt2id(rt reflect.Type) uintptr {
 	return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
 	return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
 }
 }
 
 
+func rv2rtid(rv reflect.Value) uintptr {
+	return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
+}
+
 // func rv0t(rt reflect.Type) reflect.Value {
 // func rv0t(rt reflect.Type) reflect.Value {
 // 	ut := (*unsafeIntf)(unsafe.Pointer(&rt))
 // 	ut := (*unsafeIntf)(unsafe.Pointer(&rt))
 // 	// we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
 // 	// we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
@@ -99,48 +107,6 @@ func rt2id(rt reflect.Type) uintptr {
 // 	return *(*reflect.Value)(unsafe.Pointer(&uv})
 // 	return *(*reflect.Value)(unsafe.Pointer(&uv})
 // }
 // }
 
 
-type ptrToRVKV struct {
-	k uintptr
-	v reflect.Value
-}
-
-type ptrToRvMap struct {
-	// m map[uintptr]reflect.Value
-	a [4]ptrToRVKV
-	v []ptrToRVKV
-}
-
-func (p *ptrToRvMap) init() {
-	// fmt.Printf(">>>> new ptr to rv map\n")
-	// p.m = make(map[uintptr]reflect.Value, 32)
-	p.v = p.a[:0]
-}
-
-func (p *ptrToRvMap) get(intf interface{}) (rv reflect.Value) {
-	word := uintptr(((*unsafeIntf)(unsafe.Pointer(&intf))).word)
-	// binary search. adapted from sort/search.go.
-	h, i, j := 0, 0, len(p.v)
-	for i < j {
-		h = i + (j-i)/2
-		if p.v[h].k < word {
-			i = h + 1
-		} else {
-			j = h
-		}
-	}
-	if i < len(p.v) && p.v[i].k == word {
-		return p.v[i].v
-	}
-
-	// insert into position i
-	// fmt.Printf(">>>> resetting rv for word: %x, interface: %v\n", word, intf)
-	rv = reflect.ValueOf(intf).Elem()
-	p.v = append(p.v, ptrToRVKV{})
-	copy(p.v[i+1:len(p.v)], p.v[i:len(p.v)-1])
-	p.v[i].k, p.v[i].v = word, rv
-	return
-}
-
 // --------------------------
 // --------------------------
 type atomicTypeInfoSlice struct {
 type atomicTypeInfoSlice struct {
 	v unsafe.Pointer
 	v unsafe.Pointer
@@ -155,95 +121,90 @@ func (x *atomicTypeInfoSlice) store(p *[]rtid2ti) {
 }
 }
 
 
 // --------------------------
 // --------------------------
-func (f *decFnInfo) raw(rv reflect.Value) {
+func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*[]byte)(urv.ptr) = f.d.raw()
+	// if urv.flag&unsafeFlagIndir != 0 {
+	// 	urv.ptr = *(*unsafe.Pointer)(urv.ptr)
+	// }
+	*(*[]byte)(urv.ptr) = d.rawBytes()
 }
 }
 
 
-func (f *decFnInfo) kString(rv reflect.Value) {
+func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*string)(urv.ptr) = f.d.d.DecodeString()
+	*(*string)(urv.ptr) = d.d.DecodeString()
 }
 }
 
 
-func (f *decFnInfo) kBool(rv reflect.Value) {
+func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*bool)(urv.ptr) = f.d.d.DecodeBool()
+	*(*bool)(urv.ptr) = d.d.DecodeBool()
 }
 }
 
 
-func (f *decFnInfo) kFloat32(rv reflect.Value) {
+func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*float32)(urv.ptr) = float32(f.d.d.DecodeFloat(true))
+	*(*float32)(urv.ptr) = float32(d.d.DecodeFloat(true))
 }
 }
 
 
-func (f *decFnInfo) kFloat64(rv reflect.Value) {
+func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*float64)(urv.ptr) = f.d.d.DecodeFloat(false)
+	*(*float64)(urv.ptr) = d.d.DecodeFloat(false)
 }
 }
 
 
-func (f *decFnInfo) kInt(rv reflect.Value) {
+func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*int)(urv.ptr) = int(f.d.d.DecodeInt(intBitsize))
+	*(*int)(urv.ptr) = int(d.d.DecodeInt(intBitsize))
 }
 }
 
 
-func (f *decFnInfo) kInt8(rv reflect.Value) {
+func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*int8)(urv.ptr) = int8(f.d.d.DecodeInt(8))
+	*(*int8)(urv.ptr) = int8(d.d.DecodeInt(8))
 }
 }
 
 
-func (f *decFnInfo) kInt16(rv reflect.Value) {
+func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*int16)(urv.ptr) = int16(f.d.d.DecodeInt(16))
+	*(*int16)(urv.ptr) = int16(d.d.DecodeInt(16))
 }
 }
 
 
-func (f *decFnInfo) kInt32(rv reflect.Value) {
+func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*int32)(urv.ptr) = int32(f.d.d.DecodeInt(32))
+	*(*int32)(urv.ptr) = int32(d.d.DecodeInt(32))
 }
 }
 
 
-func (f *decFnInfo) kInt64(rv reflect.Value) {
+func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*int64)(urv.ptr) = f.d.d.DecodeInt(64)
+	*(*int64)(urv.ptr) = d.d.DecodeInt(64)
 }
 }
 
 
-func (f *decFnInfo) kUint(rv reflect.Value) {
+func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*uint)(urv.ptr) = uint(f.d.d.DecodeUint(uintBitsize))
+	*(*uint)(urv.ptr) = uint(d.d.DecodeUint(uintBitsize))
 }
 }
 
 
-func (f *decFnInfo) kUintptr(rv reflect.Value) {
+func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*uintptr)(urv.ptr) = uintptr(f.d.d.DecodeUint(uintBitsize))
+	*(*uintptr)(urv.ptr) = uintptr(d.d.DecodeUint(uintBitsize))
 }
 }
 
 
-func (f *decFnInfo) kUint8(rv reflect.Value) {
+func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*uint8)(urv.ptr) = uint8(f.d.d.DecodeUint(8))
+	*(*uint8)(urv.ptr) = uint8(d.d.DecodeUint(8))
 }
 }
 
 
-func (f *decFnInfo) kUint16(rv reflect.Value) {
+func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*uint16)(urv.ptr) = uint16(f.d.d.DecodeUint(16))
+	*(*uint16)(urv.ptr) = uint16(d.d.DecodeUint(16))
 }
 }
 
 
-func (f *decFnInfo) kUint32(rv reflect.Value) {
+func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*uint32)(urv.ptr) = uint32(f.d.d.DecodeUint(32))
+	*(*uint32)(urv.ptr) = uint32(d.d.DecodeUint(32))
 }
 }
-func (f *decFnInfo) kUint64(rv reflect.Value) {
+
+func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*uint64)(urv.ptr) = f.d.d.DecodeUint(64)
+	*(*uint64)(urv.ptr) = d.d.DecodeUint(64)
 }
 }
 
 
-// func (p *ptrToRvMap) get(i interface{}) (rv reflect.Value) {
-// 	word := uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).word)
-// 	rv, exists := p.m[word]
-// 	if !exists {
-// 		fmt.Printf(">>>> resetting rv for word: %x, interface: %v\n", word, i)
-// 		rv = reflect.ValueOf(i).Elem()
-// 		p.m[word] = rv
-// 	}
-// 	return
-// }
+// ------------
 
 
 // func rt2id(rt reflect.Type) uintptr {
 // func rt2id(rt reflect.Type) uintptr {
 // 	return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
 // 	return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
@@ -455,8 +416,3 @@ func (f *decFnInfo) kUint64(rv reflect.Value) {
 // 	return *(*interface{})(unsafe.Pointer(&ui))
 // 	return *(*interface{})(unsafe.Pointer(&ui))
 // 	// return i
 // 	// return i
 // }
 // }
-
-// func i2rv(i interface{}) reflect.Value {
-// 	// u := *(*unsafeIntf)(unsafe.Pointer(&i))
-// 	return reflect.ValueOf(i)
-// }

+ 439 - 219
cmd/vendor/github.com/ugorji/go/codec/json.go

@@ -43,26 +43,29 @@ import (
 //--------------------------------
 //--------------------------------
 
 
 var (
 var (
-	jsonLiterals = [...]byte{'t', 'r', 'u', 'e', 'f', 'a', 'l', 's', 'e', 'n', 'u', 'l', 'l'}
+	// jsonLiterals = [...]byte{'t', 'r', 'u', 'e', 'f', 'a', 'l', 's', 'e', 'n', 'u', 'l', 'l'}
 
 
-	jsonFloat64Pow10 = [...]float64{
-		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-		1e20, 1e21, 1e22,
-	}
+	// jsonFloat64Pow10 = [...]float64{
+	// 	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+	// 	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+	// 	1e20, 1e21, 1e22,
+	// }
 
 
-	jsonUint64Pow10 = [...]uint64{
-		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-	}
+	// jsonUint64Pow10 = [...]uint64{
+	// 	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+	// 	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+	// }
 
 
 	// jsonTabs and jsonSpaces are used as caches for indents
 	// jsonTabs and jsonSpaces are used as caches for indents
 	jsonTabs, jsonSpaces string
 	jsonTabs, jsonSpaces string
 
 
-	jsonCharHtmlSafeSet   [utf8.RuneSelf]bool
-	jsonCharSafeSet       [utf8.RuneSelf]bool
-	jsonCharWhitespaceSet [256]bool
-	jsonNumSet            [256]bool
+	jsonCharHtmlSafeSet   bitset128
+	jsonCharSafeSet       bitset128
+	jsonCharWhitespaceSet bitset256
+	jsonNumSet            bitset256
+	// jsonIsFloatSet        bitset256
+
+	jsonU4Set [256]byte
 )
 )
 
 
 const (
 const (
@@ -83,6 +86,8 @@ const (
 	jsonValidateSymbols = true
 	jsonValidateSymbols = true
 
 
 	jsonSpacesOrTabsLen = 128
 	jsonSpacesOrTabsLen = 128
+
+	jsonU4SetErrVal = 128
 )
 )
 
 
 func init() {
 func init() {
@@ -100,27 +105,42 @@ func init() {
 	// populate the safe values as true: note: ASCII control characters are (0-31)
 	// populate the safe values as true: note: ASCII control characters are (0-31)
 	// jsonCharSafeSet:     all true except (0-31) " \
 	// jsonCharSafeSet:     all true except (0-31) " \
 	// jsonCharHtmlSafeSet: all true except (0-31) " \ < > &
 	// jsonCharHtmlSafeSet: all true except (0-31) " \ < > &
-	for i := 32; i < utf8.RuneSelf; i++ {
+	var i byte
+	for i = 32; i < utf8.RuneSelf; i++ {
 		switch i {
 		switch i {
 		case '"', '\\':
 		case '"', '\\':
-			jsonCharSafeSet[i] = false
-			jsonCharHtmlSafeSet[i] = false
 		case '<', '>', '&':
 		case '<', '>', '&':
-			jsonCharHtmlSafeSet[i] = false
-			jsonCharSafeSet[i] = true
+			jsonCharSafeSet.set(i) // = true
 		default:
 		default:
-			jsonCharSafeSet[i] = true
-			jsonCharHtmlSafeSet[i] = true
+			jsonCharSafeSet.set(i)
+			jsonCharHtmlSafeSet.set(i)
 		}
 		}
 	}
 	}
-	for i := 0; i < 256; i++ {
+	for i = 0; i <= utf8.RuneSelf; i++ {
 		switch i {
 		switch i {
 		case ' ', '\t', '\r', '\n':
 		case ' ', '\t', '\r', '\n':
-			jsonCharWhitespaceSet[i] = true
+			jsonCharWhitespaceSet.set(i)
 		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-':
 		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-':
-			jsonNumSet[i] = true
+			jsonNumSet.set(i)
 		}
 		}
 	}
 	}
+	for j := range jsonU4Set {
+		switch i = byte(j); i {
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			jsonU4Set[i] = i - '0'
+		case 'a', 'b', 'c', 'd', 'e', 'f':
+			jsonU4Set[i] = i - 'a' + 10
+		case 'A', 'B', 'C', 'D', 'E', 'F':
+			jsonU4Set[i] = i - 'A' + 10
+		default:
+			jsonU4Set[i] = jsonU4SetErrVal
+		}
+		// switch i = byte(j); i {
+		// case 'e', 'E', '.':
+		// 	jsonIsFloatSet.set(i)
+		// }
+	}
+	// jsonU4Set[255] = jsonU4SetErrVal
 }
 }
 
 
 type jsonEncDriver struct {
 type jsonEncDriver struct {
@@ -143,48 +163,116 @@ type jsonEncDriver struct {
 //   - newline and indent are added before each ending,
 //   - newline and indent are added before each ending,
 //     except there was no entry (so we can have {} or [])
 //     except there was no entry (so we can have {} or [])
 
 
-func (e *jsonEncDriver) sendContainerState(c containerState) {
-	// determine whether to output separators
-	if c == containerMapKey {
-		if e.c != containerMapStart {
-			e.w.writen1(',')
-		}
-		if e.d {
-			e.writeIndent()
-		}
-	} else if c == containerMapValue {
-		if e.d {
-			e.w.writen2(':', ' ')
-		} else {
-			e.w.writen1(':')
-		}
-	} else if c == containerMapEnd {
-		if e.d {
-			e.dl--
-			if e.c != containerMapStart {
-				e.writeIndent()
-			}
-		}
-		e.w.writen1('}')
-	} else if c == 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 {
 		if e.c != containerArrayStart {
-			e.w.writen1(',')
-		}
-		if e.d {
 			e.writeIndent()
 			e.writeIndent()
 		}
 		}
-	} else if c == 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() {
 func (e *jsonEncDriver) writeIndent() {
 	e.w.writen1('\n')
 	e.w.writen1('\n')
 	if x := len(e.ds) * int(e.dl); x <= jsonSpacesOrTabsLen {
 	if x := len(e.ds) * int(e.dl); x <= jsonSpacesOrTabsLen {
@@ -201,14 +289,14 @@ func (e *jsonEncDriver) writeIndent() {
 }
 }
 
 
 func (e *jsonEncDriver) EncodeNil() {
 func (e *jsonEncDriver) EncodeNil() {
-	e.w.writeb(jsonLiterals[9:13]) // null
+	e.w.writen4('n', 'u', 'l', 'l') // e.w.writeb(jsonLiterals[9:13]) // null
 }
 }
 
 
 func (e *jsonEncDriver) EncodeBool(b bool) {
 func (e *jsonEncDriver) EncodeBool(b bool) {
 	if b {
 	if b {
-		e.w.writeb(jsonLiterals[0:4]) // true
+		e.w.writen4('t', 'r', 'u', 'e') // e.w.writeb(jsonLiterals[0:4]) // true
 	} else {
 	} else {
-		e.w.writeb(jsonLiterals[4:9]) // false
+		e.w.writen5('f', 'a', 'l', 's', 'e') // e.w.writeb(jsonLiterals[4:9]) // false
 	}
 	}
 }
 }
 
 
@@ -217,20 +305,19 @@ func (e *jsonEncDriver) EncodeFloat32(f float32) {
 }
 }
 
 
 func (e *jsonEncDriver) EncodeFloat64(f float64) {
 func (e *jsonEncDriver) EncodeFloat64(f float64) {
-	// e.w.writestr(strconv.FormatFloat(f, 'E', -1, 64))
 	e.encodeFloat(f, 64)
 	e.encodeFloat(f, 64)
 }
 }
 
 
 func (e *jsonEncDriver) encodeFloat(f float64, numbits int) {
 func (e *jsonEncDriver) encodeFloat(f float64, numbits int) {
 	x := strconv.AppendFloat(e.b[:0], f, 'G', -1, numbits)
 	x := strconv.AppendFloat(e.b[:0], f, 'G', -1, numbits)
-	e.w.writeb(x)
-	if bytes.IndexByte(x, 'E') == -1 && bytes.IndexByte(x, '.') == -1 {
-		e.w.writen2('.', '0')
+	// if bytes.IndexByte(x, 'E') == -1 && bytes.IndexByte(x, '.') == -1 {
+	if !jsonIsFloatBytesB2(x) {
+		x = append(x, '.', '0')
 	}
 	}
+	e.w.writeb(x)
 }
 }
 
 
 func (e *jsonEncDriver) EncodeInt(v int64) {
 func (e *jsonEncDriver) EncodeInt(v int64) {
-	// if e.h.IntegerAsString == 'A' || e.h.IntegerAsString == 'L' && (v > 1<<53 || v < -(1<<53)) {
 	if x := e.h.IntegerAsString; x == 'A' || x == 'L' && (v > 1<<53 || v < -(1<<53)) {
 	if x := e.h.IntegerAsString; x == 'A' || x == 'L' && (v > 1<<53 || v < -(1<<53)) {
 		e.w.writen1('"')
 		e.w.writen1('"')
 		e.w.writeb(strconv.AppendInt(e.b[:0], v, 10))
 		e.w.writeb(strconv.AppendInt(e.b[:0], v, 10))
@@ -241,7 +328,6 @@ func (e *jsonEncDriver) EncodeInt(v int64) {
 }
 }
 
 
 func (e *jsonEncDriver) EncodeUint(v uint64) {
 func (e *jsonEncDriver) EncodeUint(v uint64) {
-	// if e.h.IntegerAsString == 'A' || e.h.IntegerAsString == 'L' && v > 1<<53 {
 	if x := e.h.IntegerAsString; x == 'A' || x == 'L' && v > 1<<53 {
 	if x := e.h.IntegerAsString; x == 'A' || x == 'L' && v > 1<<53 {
 		e.w.writen1('"')
 		e.w.writen1('"')
 		e.w.writeb(strconv.AppendUint(e.b[:0], v, 10))
 		e.w.writeb(strconv.AppendUint(e.b[:0], v, 10))
@@ -253,7 +339,7 @@ func (e *jsonEncDriver) EncodeUint(v uint64) {
 
 
 func (e *jsonEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
 func (e *jsonEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
 	if v := ext.ConvertExt(rv); v == nil {
 	if v := ext.ConvertExt(rv); v == nil {
-		e.w.writeb(jsonLiterals[9:13]) // null // e.EncodeNil()
+		e.w.writen4('n', 'u', 'l', 'l') // e.w.writeb(jsonLiterals[9:13]) // null // e.EncodeNil()
 	} else {
 	} else {
 		en.encode(v)
 		en.encode(v)
 	}
 	}
@@ -262,35 +348,17 @@ func (e *jsonEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Enco
 func (e *jsonEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
 func (e *jsonEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
 	// only encodes re.Value (never re.Data)
 	// only encodes re.Value (never re.Data)
 	if re.Value == nil {
 	if re.Value == nil {
-		e.w.writeb(jsonLiterals[9:13]) // null // e.EncodeNil()
+		e.w.writen4('n', 'u', 'l', 'l') // e.w.writeb(jsonLiterals[9:13]) // null // e.EncodeNil()
 	} else {
 	} else {
 		en.encode(re.Value)
 		en.encode(re.Value)
 	}
 	}
 }
 }
 
 
-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) {
 func (e *jsonEncDriver) EncodeString(c charEncoding, v string) {
-	// e.w.writestr(strconv.Quote(v))
 	e.quoteStr(v)
 	e.quoteStr(v)
 }
 }
 
 
 func (e *jsonEncDriver) EncodeSymbol(v string) {
 func (e *jsonEncDriver) EncodeSymbol(v string) {
-	// e.EncodeString(c_UTF8, v)
 	e.quoteStr(v)
 	e.quoteStr(v)
 }
 }
 
 
@@ -312,7 +380,6 @@ func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
 		e.w.writeb(e.bs)
 		e.w.writeb(e.bs)
 		e.w.writen1('"')
 		e.w.writen1('"')
 	} else {
 	} else {
-		// e.EncodeString(c, string(v))
 		e.quoteStr(stringView(v))
 		e.quoteStr(stringView(v))
 	}
 	}
 }
 }
@@ -326,13 +393,13 @@ func (e *jsonEncDriver) quoteStr(s string) {
 	const hex = "0123456789abcdef"
 	const hex = "0123456789abcdef"
 	w := e.w
 	w := e.w
 	w.writen1('"')
 	w.writen1('"')
-	start := 0
-	for i := 0; i < len(s); {
+	var start int
+	for i, slen := 0, len(s); i < slen; {
 		// encode all bytes < 0x20 (except \r, \n).
 		// encode all bytes < 0x20 (except \r, \n).
 		// also encode < > & to prevent security holes when served to some browsers.
 		// also encode < > & to prevent security holes when served to some browsers.
 		if b := s[i]; b < utf8.RuneSelf {
 		if b := s[i]; b < utf8.RuneSelf {
 			// if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
 			// if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
-			if jsonCharHtmlSafeSet[b] || (e.h.HTMLCharsAsIs && jsonCharSafeSet[b]) {
+			if jsonCharHtmlSafeSet.isset(b) || (e.h.HTMLCharsAsIs && jsonCharSafeSet.isset(b)) {
 				i++
 				i++
 				continue
 				continue
 			}
 			}
@@ -390,6 +457,16 @@ func (e *jsonEncDriver) quoteStr(s string) {
 	w.writen1('"')
 	w.writen1('"')
 }
 }
 
 
+func (e *jsonEncDriver) atEndOfEncode() {
+	if e.h.TermWhitespace {
+		if e.d {
+			e.w.writen1('\n')
+		} else {
+			e.w.writen1(' ')
+		}
+	}
+}
+
 type jsonDecDriver struct {
 type jsonDecDriver struct {
 	noBuiltInTypes
 	noBuiltInTypes
 	d *Decoder
 	d *Decoder
@@ -400,6 +477,8 @@ type jsonDecDriver struct {
 	// tok is used to store the token read right after skipWhiteSpace.
 	// tok is used to store the token read right after skipWhiteSpace.
 	tok uint8
 	tok uint8
 
 
+	fnull bool // found null from appendStringAsBytes
+
 	bstr [8]byte  // scratch used for string \UXXX parsing
 	bstr [8]byte  // scratch used for string \UXXX parsing
 	b    [64]byte // scratch, used for parsing strings or numbers
 	b    [64]byte // scratch, used for parsing strings or numbers
 	b2   [64]byte // scratch, used only for decodeBytes (after base64)
 	b2   [64]byte // scratch, used only for decodeBytes (after base64)
@@ -412,7 +491,7 @@ type jsonDecDriver struct {
 
 
 func jsonIsWS(b byte) bool {
 func jsonIsWS(b byte) bool {
 	// return b == ' ' || b == '\t' || b == '\r' || b == '\n'
 	// return b == ' ' || b == '\t' || b == '\r' || b == '\n'
-	return jsonCharWhitespaceSet[b]
+	return jsonCharWhitespaceSet.isset(b)
 }
 }
 
 
 func (d *jsonDecDriver) uncacheRead() {
 func (d *jsonDecDriver) uncacheRead() {
@@ -422,47 +501,167 @@ func (d *jsonDecDriver) uncacheRead() {
 	}
 	}
 }
 }
 
 
-func (d *jsonDecDriver) sendContainerState(c containerState) {
+func (d *jsonDecDriver) ReadMapStart() int {
 	if d.tok == 0 {
 	if d.tok == 0 {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
 	}
-	var xc uint8 // char expected
-	if c == containerMapKey {
-		if d.c != containerMapStart {
-			xc = ','
-		}
-	} else if c == containerMapValue {
-		xc = ':'
-	} else if c == containerMapEnd {
-		xc = '}'
-	} else if c == 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)
 		}
 		}
-	} else if c == containerArrayEnd {
-		xc = ']'
+		d.tok = 0
 	}
 	}
-	if xc != 0 {
+	d.c = containerArrayElem
+}
+
+func (d *jsonDecDriver) ReadArrayEnd() {
+	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 = 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 {
 		if d.tok != xc {
 			d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
 			d.d.errorf("json: expect char '%c' but got char '%c'", xc, d.tok)
 		}
 		}
 		d.tok = 0
 		d.tok = 0
 	}
 	}
-	d.c = c
+	d.c = containerMapKey
 }
 }
 
 
-func (d *jsonDecDriver) CheckBreak() bool {
+func (d *jsonDecDriver) ReadMapElemValue() {
 	if d.tok == 0 {
 	if d.tok == 0 {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 		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
+// 	if jsonValidateSymbols && !bytes.Equal(bs, jsonLiterals[fromIdx:toIdx]) {
+// 		d.d.errorf("json: expecting %s: got %s", jsonLiterals[fromIdx:toIdx], bs)
+// 		return
+// 	}
+// }
+
+func (d *jsonDecDriver) readSymbol3(v1, v2, v3 uint8) {
+	b1, b2, b3 := d.r.readn3()
+	d.tok = 0
+	if jsonValidateSymbols && (b1 != v1 || b2 != v2 || b3 != v3) {
+		d.d.errorf("json: expecting %c, %c, %c: got %c, %c, %c", b1, b2, b3, v1, v2, v3)
+		return
+	}
 }
 }
 
 
-func (d *jsonDecDriver) readStrIdx(fromIdx, toIdx uint8) {
-	bs := d.r.readx(int(toIdx - fromIdx))
+func (d *jsonDecDriver) readSymbol4(v1, v2, v3, v4 uint8) {
+	b1, b2, b3, b4 := d.r.readn4()
 	d.tok = 0
 	d.tok = 0
-	if jsonValidateSymbols && !bytes.Equal(bs, jsonLiterals[fromIdx:toIdx]) {
-		d.d.errorf("json: expecting %s: got %s", jsonLiterals[fromIdx:toIdx], bs)
+	if jsonValidateSymbols && (b1 != v1 || b2 != v2 || b3 != v3 || b4 != v4) {
+		d.d.errorf("json: expecting %c, %c, %c, %c: got %c, %c, %c, %c", b1, b2, b3, b4, v1, v2, v3, v4)
 		return
 		return
 	}
 	}
 }
 }
@@ -472,7 +671,7 @@ func (d *jsonDecDriver) TryDecodeAsNil() bool {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
 	}
 	if d.tok == 'n' {
 	if d.tok == 'n' {
-		d.readStrIdx(10, 13) // ull
+		d.readSymbol3('u', 'l', 'l') // d.readLiteralIdx(10, 13) // ull
 		return true
 		return true
 	}
 	}
 	return false
 	return false
@@ -483,41 +682,17 @@ func (d *jsonDecDriver) DecodeBool() bool {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
 	}
 	if d.tok == 'f' {
 	if d.tok == 'f' {
-		d.readStrIdx(5, 9) // alse
+		d.readSymbol4('a', 'l', 's', 'e') // d.readLiteralIdx(5, 9) // alse
 		return false
 		return false
 	}
 	}
 	if d.tok == 't' {
 	if d.tok == 't' {
-		d.readStrIdx(1, 4) // rue
+		d.readSymbol3('r', 'u', 'e') // d.readLiteralIdx(1, 4) // rue
 		return true
 		return true
 	}
 	}
 	d.d.errorf("json: decode bool: got first char %c", d.tok)
 	d.d.errorf("json: decode bool: got first char %c", d.tok)
 	return false // "unreachable"
 	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) {
 func (d *jsonDecDriver) ContainerType() (vt valueType) {
 	// check container type by checking the first char
 	// check container type by checking the first char
 	if d.tok == 0 {
 	if d.tok == 0 {
@@ -548,10 +723,8 @@ func (d *jsonDecDriver) decNumBytes() (bs []byte) {
 	} else {
 	} else {
 		d.r.unreadn1()
 		d.r.unreadn1()
 		bs = d.r.readTo(d.bs[:0], &jsonNumSet)
 		bs = d.r.readTo(d.bs[:0], &jsonNumSet)
-		// bs = d.r.readbUntilAny(d.bs[:0], " \t\n:,{}[]")
 	}
 	}
 	d.tok = 0
 	d.tok = 0
-	// fmt.Printf(">>>> decNumBytes: returning: '%s'\n", bs)
 	return bs
 	return bs
 }
 }
 
 
@@ -567,10 +740,6 @@ func (d *jsonDecDriver) DecodeUint(bitsize uint8) (u uint64) {
 
 
 func (d *jsonDecDriver) DecodeInt(bitsize uint8) (i int64) {
 func (d *jsonDecDriver) DecodeInt(bitsize uint8) (i int64) {
 	bs := d.decNumBytes()
 	bs := d.decNumBytes()
-	// if bytes.ContainsAny(bs, ".eE") {
-	// 	d.d.errorf("json: decoding int, but found one or more of the chars: .eE: %s", bs)
-	// 	return
-	// }
 	i, err := strconv.ParseInt(stringView(bs), 10, int(bitsize))
 	i, err := strconv.ParseInt(stringView(bs), 10, int(bitsize))
 	if err != nil {
 	if err != nil {
 		d.d.errorf("json: decode int from %s: %v", bs, err)
 		d.d.errorf("json: decode int from %s: %v", bs, err)
@@ -614,10 +783,15 @@ func (d *jsonDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		return
 		return
 	}
 	}
 	d.appendStringAsBytes()
 	d.appendStringAsBytes()
-	// if appendStringAsBytes returned a zero-len slice, then treat as nil.
-	// This should only happen for null, and "".
+	// base64 encodes []byte{} as "", and we encode nil []byte as null.
+	// Consequently, base64 should decode null as a nil []byte, and "" as an empty []byte{}.
+	// appendStringAsBytes returns a zero-len slice for both, so as not to reset d.bs.
+	// However, it sets a fnull field to true, so we can check if a null was found.
 	if len(d.bs) == 0 {
 	if len(d.bs) == 0 {
-		return nil
+		if d.fnull {
+			return nil
+		}
+		return []byte{}
 	}
 	}
 	bs0 := d.bs
 	bs0 := d.bs
 	slen := base64.StdEncoding.DecodedLen(len(bs0))
 	slen := base64.StdEncoding.DecodedLen(len(bs0))
@@ -660,19 +834,21 @@ func (d *jsonDecDriver) appendStringAsBytes() {
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 		d.tok = d.r.skip(&jsonCharWhitespaceSet)
 	}
 	}
 
 
+	d.fnull = false
 	if d.tok != '"' {
 	if d.tok != '"' {
 		// d.d.errorf("json: expect char '%c' but got char '%c'", '"', d.tok)
 		// d.d.errorf("json: expect char '%c' but got char '%c'", '"', d.tok)
 		// handle non-string scalar: null, true, false or a number
 		// handle non-string scalar: null, true, false or a number
 		switch d.tok {
 		switch d.tok {
 		case 'n':
 		case 'n':
-			d.readStrIdx(10, 13) // ull
+			d.readSymbol3('u', 'l', 'l') // d.readLiteralIdx(10, 13) // ull
 			d.bs = d.bs[:0]
 			d.bs = d.bs[:0]
+			d.fnull = true
 		case 'f':
 		case 'f':
-			d.readStrIdx(5, 9) // alse
+			d.readSymbol4('a', 'l', 's', 'e') // d.readLiteralIdx(5, 9) // alse
 			d.bs = d.bs[:5]
 			d.bs = d.bs[:5]
 			copy(d.bs, "false")
 			copy(d.bs, "false")
 		case 't':
 		case 't':
-			d.readStrIdx(1, 4) // rue
+			d.readSymbol3('r', 'u', 'e') // d.readLiteralIdx(1, 4) // rue
 			d.bs = d.bs[:4]
 			d.bs = d.bs[:4]
 			copy(d.bs, "true")
 			copy(d.bs, "true")
 		default:
 		default:
@@ -686,26 +862,38 @@ func (d *jsonDecDriver) appendStringAsBytes() {
 
 
 	d.tok = 0
 	d.tok = 0
 	r := d.r
 	r := d.r
-	var cs []byte
+	var cs = r.readUntil(d.b2[:0], '"')
+	var cslen = len(cs)
+	var c uint8
 	v := d.bs[:0]
 	v := d.bs[:0]
-	// var c uint8
-	for i := 0; ; i++ {
-		if i == len(cs) {
+	// append on each byte seen can be expensive, so we just
+	// keep track of where we last read a contiguous set of
+	// non-special bytes (using cursor variable),
+	// and when we see a special byte
+	// e.g. end-of-slice, " or \,
+	// we will append the full range into the v slice before proceeding
+	for i, cursor := 0, 0; ; {
+		if i == cslen {
+			v = append(v, cs[cursor:]...)
 			cs = r.readUntil(d.b2[:0], '"')
 			cs = r.readUntil(d.b2[:0], '"')
-			i = 0
+			cslen = len(cs)
+			i, cursor = 0, 0
 		}
 		}
-		if cs[i] == '"' {
+		c = cs[i]
+		if c == '"' {
+			v = append(v, cs[cursor:i]...)
 			break
 			break
 		}
 		}
-		if cs[i] != '\\' {
-			v = append(v, cs[i])
+		if c != '\\' {
+			i++
 			continue
 			continue
 		}
 		}
-		// cs[i] == '\\'
+		v = append(v, cs[cursor:i]...)
 		i++
 		i++
-		switch cs[i] {
+		c = cs[i]
+		switch c {
 		case '"', '\\', '/', '\'':
 		case '"', '\\', '/', '\'':
-			v = append(v, cs[i])
+			v = append(v, c)
 		case 'b':
 		case 'b':
 			v = append(v, '\b')
 			v = append(v, '\b')
 		case 'f':
 		case 'f':
@@ -717,50 +905,68 @@ func (d *jsonDecDriver) appendStringAsBytes() {
 		case 't':
 		case 't':
 			v = append(v, '\t')
 			v = append(v, '\t')
 		case 'u':
 		case 'u':
-			rr := d.jsonU4Arr([4]byte{cs[i+1], cs[i+2], cs[i+3], cs[i+4]})
+			var r rune
+			var rr uint32
+			c = cs[i+4] // may help reduce bounds-checking
+			for j := 1; j < 5; j++ {
+				c = jsonU4Set[cs[i+j]]
+				if c == jsonU4SetErrVal {
+					d.d.errorf(`json: unquoteStr: invalid hex char in \u unicode sequence: %q`, c)
+				}
+				rr = rr*16 + uint32(c)
+			}
+			r = rune(rr)
 			i += 4
 			i += 4
-			// fmt.Printf("$$$$$$$$$: is surrogate: %v\n", utf16.IsSurrogate(rr))
-			if utf16.IsSurrogate(rr) {
-				// fmt.Printf(">>>> checking utf16 surrogate\n")
-				if !(cs[i+1] == '\\' && cs[i+2] == 'u') {
+			if utf16.IsSurrogate(r) {
+				if !(cs[i+2] == 'u' && cs[i+i] == '\\') {
 					d.d.errorf(`json: unquoteStr: invalid unicode sequence. Expecting \u`)
 					d.d.errorf(`json: unquoteStr: invalid unicode sequence. Expecting \u`)
 					return
 					return
 				}
 				}
 				i += 2
 				i += 2
-				rr = utf16.DecodeRune(rr, d.jsonU4Arr([4]byte{cs[i+1], cs[i+2], cs[i+3], cs[i+4]}))
+				c = cs[i+4] // may help reduce bounds-checking
+				var rr1 uint32
+				for j := 1; j < 5; j++ {
+					c = jsonU4Set[cs[i+j]]
+					if c == jsonU4SetErrVal {
+						d.d.errorf(`json: unquoteStr: invalid hex char in \u unicode sequence: %q`, c)
+					}
+					rr1 = rr1*16 + uint32(c)
+				}
+				r = utf16.DecodeRune(r, rune(rr1))
 				i += 4
 				i += 4
 			}
 			}
-			w2 := utf8.EncodeRune(d.bstr[:], rr)
+			w2 := utf8.EncodeRune(d.bstr[:], r)
 			v = append(v, d.bstr[:w2]...)
 			v = append(v, d.bstr[:w2]...)
 		default:
 		default:
-			d.d.errorf("json: unsupported escaped value: %c", cs[i])
+			d.d.errorf("json: unsupported escaped value: %c", c)
 		}
 		}
+		i++
+		cursor = i
 	}
 	}
 	d.bs = v
 	d.bs = v
 }
 }
 
 
-func (d *jsonDecDriver) jsonU4Arr(bs [4]byte) (r rune) {
-	// u, _ := strconv.ParseUint(string(d.bstr[:4]), 16, 64)
-	var u uint32
-	for _, v := range bs {
-		if '0' <= v && v <= '9' {
-			v = v - '0'
-		} else if 'a' <= v && v <= 'z' {
-			v = v - 'a' + 10
-		} else if 'A' <= v && v <= 'Z' {
-			v = v - 'A' + 10
-		} else {
-			d.d.errorf(`json: unquoteStr: invalid hex char in \u unicode sequence: %q`, v)
-			return 0
-		}
-		u = u*16 + uint32(v)
-	}
-	// fmt.Printf(">>>>>>>> jsonU4Arr: %v, %s\n", rune(u), string(rune(u)))
-	return rune(u)
-}
+// func (d *jsonDecDriver) jsonU4Arr(bs [4]byte) (r rune) {
+// 	// u, _ := strconv.ParseUint(string(d.bstr[:4]), 16, 64)
+// 	var u uint32
+// 	for _, v := range bs {
+// 		if '0' <= v && v <= '9' {
+// 			v = v - '0'
+// 		} else if 'a' <= v && v <= 'f' {
+// 			v = v - 'a' + 10
+// 		} else if 'A' <= v && v <= 'f' {
+// 			v = v - 'A' + 10
+// 		} else {
+// 			// d.d.errorf(`json: unquoteStr: invalid hex char in \u unicode sequence: %q`, v)
+// 			return utf8.RuneError
+// 		}
+// 		u = u*16 + uint32(v)
+// 	}
+// 	return rune(u)
+// }
 
 
 func (d *jsonDecDriver) DecodeNaked() {
 func (d *jsonDecDriver) DecodeNaked() {
-	z := &d.d.n
+	z := d.d.n
 	// var decodeFurther bool
 	// var decodeFurther bool
 
 
 	if d.tok == 0 {
 	if d.tok == 0 {
@@ -768,24 +974,20 @@ func (d *jsonDecDriver) DecodeNaked() {
 	}
 	}
 	switch d.tok {
 	switch d.tok {
 	case 'n':
 	case 'n':
-		d.readStrIdx(10, 13) // ull
+		d.readSymbol3('u', 'l', 'l') // d.readLiteralIdx(10, 13) // ull
 		z.v = valueTypeNil
 		z.v = valueTypeNil
 	case 'f':
 	case 'f':
-		d.readStrIdx(5, 9) // alse
+		d.readSymbol4('a', 'l', 's', 'e') // d.readLiteralIdx(5, 9) // alse
 		z.v = valueTypeBool
 		z.v = valueTypeBool
 		z.b = false
 		z.b = false
 	case 't':
 	case 't':
-		d.readStrIdx(1, 4) // rue
+		d.readSymbol3('r', 'u', 'e') // d.readLiteralIdx(1, 4) // rue
 		z.v = valueTypeBool
 		z.v = valueTypeBool
 		z.b = true
 		z.b = true
 	case '{':
 	case '{':
-		z.v = valueTypeMap
-		// d.tok = 0 // don't consume. kInterfaceNaked will call ReadMapStart
-		// decodeFurther = true
+		z.v = valueTypeMap // don't consume. kInterfaceNaked will call ReadMapStart
 	case '[':
 	case '[':
-		z.v = valueTypeArray
-		// d.tok = 0 // don't consume. kInterfaceNaked will call ReadArrayStart
-		// decodeFurther = true
+		z.v = valueTypeArray // don't consume. kInterfaceNaked will call ReadArrayStart
 	case '"':
 	case '"':
 		z.v = valueTypeString
 		z.v = valueTypeString
 		z.s = d.DecodeString()
 		z.s = d.DecodeString()
@@ -795,10 +997,7 @@ func (d *jsonDecDriver) DecodeNaked() {
 		if len(bs) == 0 {
 		if len(bs) == 0 {
 			d.d.errorf("json: decode number from empty string")
 			d.d.errorf("json: decode number from empty string")
 			return
 			return
-		} else if d.h.PreferFloat ||
-			bytes.IndexByte(bs, '.') != -1 ||
-			bytes.IndexByte(bs, 'e') != -1 ||
-			bytes.IndexByte(bs, 'E') != -1 {
+		} else if d.h.PreferFloat || jsonIsFloatBytesB3(bs) { // bytes.IndexByte(bs, '.') != -1 ||...
 			// } else if d.h.PreferFloat || bytes.ContainsAny(bs, ".eE") {
 			// } else if d.h.PreferFloat || bytes.ContainsAny(bs, ".eE") {
 			z.v = valueTypeFloat
 			z.v = valueTypeFloat
 			z.f, err = strconv.ParseFloat(stringView(bs), 64)
 			z.f, err = strconv.ParseFloat(stringView(bs), 64)
@@ -821,7 +1020,6 @@ func (d *jsonDecDriver) DecodeNaked() {
 				return
 				return
 			}
 			}
 		}
 		}
-		// fmt.Printf("DecodeNaked: Number: %T, %v\n", v, v)
 	}
 	}
 	// if decodeFurther {
 	// if decodeFurther {
 	// 	d.s.sc.retryRead()
 	// 	d.s.sc.retryRead()
@@ -829,14 +1027,6 @@ func (d *jsonDecDriver) DecodeNaked() {
 	return
 	return
 }
 }
 
 
-// func jsonAcceptNonWS(b byte) bool {
-// 	return !jsonCharWhitespaceSet[b]
-// }
-
-// func jsonAcceptDQuote(b byte) bool {
-// 	return b == '"'
-// }
-
 //----------------------
 //----------------------
 
 
 // JsonHandle is a handle for JSON encoding format.
 // JsonHandle is a handle for JSON encoding format.
@@ -891,8 +1081,17 @@ type JsonHandle struct {
 	// If not set, we will examine the characters of the number and decode as an
 	// If not set, we will examine the characters of the number and decode as an
 	// integer type if it doesn't have any of the characters [.eE].
 	// integer type if it doesn't have any of the characters [.eE].
 	PreferFloat bool
 	PreferFloat bool
+
+	// TermWhitespace says that we add a whitespace character
+	// at the end of an encoding.
+	//
+	// The whitespace is important, especially if using numbers in a context
+	// where multiple items are written to a stream.
+	TermWhitespace bool
 }
 }
 
 
+func (h *JsonHandle) hasElemSeparators() bool { return true }
+
 func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
 func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
 	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
 	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
 }
 }
@@ -942,11 +1141,32 @@ func (d *jsonDecDriver) reset() {
 	// d.n.reset()
 	// d.n.reset()
 }
 }
 
 
-var jsonEncodeTerminate = []byte{' '}
+// func jsonIsFloatBytes(bs []byte) bool {
+// 	for _, v := range bs {
+// 		// if v == '.' || v == 'e' || v == 'E' {
+// 		if jsonIsFloatSet.isset(v) {
+// 			return true
+// 		}
+// 	}
+// 	return false
+// }
+
+func jsonIsFloatBytesB2(bs []byte) bool {
+	return bytes.IndexByte(bs, '.') != -1 ||
+		bytes.IndexByte(bs, 'E') != -1
+}
 
 
-func (h *JsonHandle) rpcEncodeTerminate() []byte {
-	return jsonEncodeTerminate
+func jsonIsFloatBytesB3(bs []byte) bool {
+	return bytes.IndexByte(bs, '.') != -1 ||
+		bytes.IndexByte(bs, 'E') != -1 ||
+		bytes.IndexByte(bs, 'e') != -1
 }
 }
 
 
+// var jsonEncodeTerminate = []byte{' '}
+
+// func (h *JsonHandle) rpcEncodeTerminate() []byte {
+// 	return jsonEncodeTerminate
+// }
+
 var _ decDriver = (*jsonDecDriver)(nil)
 var _ decDriver = (*jsonDecDriver)(nil)
 var _ encDriver = (*jsonEncDriver)(nil)
 var _ encDriver = (*jsonEncDriver)(nil)

+ 50 - 15
cmd/vendor/github.com/ugorji/go/codec/msgpack.go

@@ -104,7 +104,8 @@ var (
 
 
 type msgpackEncDriver struct {
 type msgpackEncDriver struct {
 	noBuiltInTypes
 	noBuiltInTypes
-	encNoSeparator
+	encDriverNoopContainerWriter
+	// encNoSeparator
 	e *Encoder
 	e *Encoder
 	w encWriter
 	w encWriter
 	h *MsgpackHandle
 	h *MsgpackHandle
@@ -213,21 +214,22 @@ func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) {
 	}
 	}
 }
 }
 
 
-func (e *msgpackEncDriver) EncodeArrayStart(length int) {
+func (e *msgpackEncDriver) WriteArrayStart(length int) {
 	e.writeContainerLen(msgpackContainerList, length)
 	e.writeContainerLen(msgpackContainerList, length)
 }
 }
 
 
-func (e *msgpackEncDriver) EncodeMapStart(length int) {
+func (e *msgpackEncDriver) WriteMapStart(length int) {
 	e.writeContainerLen(msgpackContainerMap, length)
 	e.writeContainerLen(msgpackContainerMap, length)
 }
 }
 
 
 func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
 func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
+	slen := len(s)
 	if c == c_RAW && e.h.WriteExt {
 	if c == c_RAW && e.h.WriteExt {
-		e.writeContainerLen(msgpackContainerBin, len(s))
+		e.writeContainerLen(msgpackContainerBin, slen)
 	} else {
 	} else {
-		e.writeContainerLen(msgpackContainerStr, len(s))
+		e.writeContainerLen(msgpackContainerStr, slen)
 	}
 	}
-	if len(s) > 0 {
+	if slen > 0 {
 		e.w.writestr(s)
 		e.w.writestr(s)
 	}
 	}
 }
 }
@@ -237,12 +239,13 @@ func (e *msgpackEncDriver) EncodeSymbol(v string) {
 }
 }
 
 
 func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
 func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
+	slen := len(bs)
 	if c == c_RAW && e.h.WriteExt {
 	if c == c_RAW && e.h.WriteExt {
-		e.writeContainerLen(msgpackContainerBin, len(bs))
+		e.writeContainerLen(msgpackContainerBin, slen)
 	} else {
 	} else {
-		e.writeContainerLen(msgpackContainerStr, len(bs))
+		e.writeContainerLen(msgpackContainerStr, slen)
 	}
 	}
-	if len(bs) > 0 {
+	if slen > 0 {
 		e.w.writeb(bs)
 		e.w.writeb(bs)
 	}
 	}
 }
 }
@@ -272,8 +275,9 @@ type msgpackDecDriver struct {
 	bdRead bool
 	bdRead bool
 	br     bool // bytes reader
 	br     bool // bytes reader
 	noBuiltInTypes
 	noBuiltInTypes
-	noStreamingCodec
-	decNoSeparator
+	// noStreamingCodec
+	// decNoSeparator
+	decDriverNoopContainerReader
 }
 }
 
 
 // Note: This returns either a primitive (int, bool, etc) for non-containers,
 // Note: This returns either a primitive (int, bool, etc) for non-containers,
@@ -286,7 +290,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 	bd := d.bd
 	bd := d.bd
-	n := &d.d.n
+	n := d.d.n
 	var decodeFurther bool
 	var decodeFurther bool
 
 
 	switch bd {
 	switch bd {
@@ -529,12 +533,42 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
+
+	// DecodeBytes could be from: bin str fixstr fixarray array ...
 	var clen int
 	var clen int
-	if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
-		clen = d.readContainerLen(msgpackContainerBin)
-	} else {
+	vt := d.ContainerType()
+	switch vt {
+	case valueTypeBytes:
+		// valueTypeBytes may be a mpBin or an mpStr container
+		if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
+			clen = d.readContainerLen(msgpackContainerBin)
+		} else {
+			clen = d.readContainerLen(msgpackContainerStr)
+		}
+	case valueTypeString:
 		clen = d.readContainerLen(msgpackContainerStr)
 		clen = d.readContainerLen(msgpackContainerStr)
+	case valueTypeArray:
+		clen = d.readContainerLen(msgpackContainerList)
+		// ensure everything after is one byte each
+		for i := 0; i < clen; i++ {
+			d.readNextBd()
+			if d.bd == mpNil {
+				bs = append(bs, 0)
+			} else if d.bd == mpUint8 {
+				bs = append(bs, d.r.readn1())
+			} else {
+				d.d.errorf("cannot read non-byte into a byte array")
+				return
+			}
+		}
+		d.bdRead = false
+		return bs
+	default:
+		d.d.errorf("invalid container type: expecting bin|str|array")
+		return
 	}
 	}
+
+	// these are (bin|str)(8|16|32)
 	// println("DecodeBytes: clen: ", clen)
 	// println("DecodeBytes: clen: ", clen)
 	d.bdRead = false
 	d.bdRead = false
 	// bytes may be nil, so handle it. if nil, clen=-1.
 	// bytes may be nil, so handle it. if nil, clen=-1.
@@ -728,6 +762,7 @@ type MsgpackHandle struct {
 	// a []byte or string based on the setting of RawToString.
 	// a []byte or string based on the setting of RawToString.
 	WriteExt bool
 	WriteExt bool
 	binaryEncodingType
 	binaryEncodingType
+	noElemSeparators
 }
 }
 
 
 func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
 func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {

+ 2 - 0
cmd/vendor/github.com/ugorji/go/codec/noop.go

@@ -1,6 +1,8 @@
 // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
 // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
 // Use of this source code is governed by a MIT license found in the LICENSE file.
 // Use of this source code is governed by a MIT license found in the LICENSE file.
 
 
+// +build ignore
+
 package codec
 package codec
 
 
 import (
 import (

+ 21 - 14
cmd/vendor/github.com/ugorji/go/codec/rpc.go

@@ -5,18 +5,19 @@ package codec
 
 
 import (
 import (
 	"bufio"
 	"bufio"
+	"errors"
 	"io"
 	"io"
 	"net/rpc"
 	"net/rpc"
 	"sync"
 	"sync"
 )
 )
 
 
-// rpcEncodeTerminator allows a handler specify a []byte terminator to send after each Encode.
-//
-// Some codecs like json need to put a space after each encoded value, to serve as a
-// delimiter for things like numbers (else json codec will continue reading till EOF).
-type rpcEncodeTerminator interface {
-	rpcEncodeTerminate() []byte
-}
+// // rpcEncodeTerminator allows a handler specify a []byte terminator to send after each Encode.
+// //
+// // Some codecs like json need to put a space after each encoded value, to serve as a
+// // delimiter for things like numbers (else json codec will continue reading till EOF).
+// type rpcEncodeTerminator interface {
+// 	rpcEncodeTerminate() []byte
+// }
 
 
 // Rpc provides a rpc Server or Client Codec for rpc communication.
 // Rpc provides a rpc Server or Client Codec for rpc communication.
 type Rpc interface {
 type Rpc interface {
@@ -52,6 +53,12 @@ type rpcCodec struct {
 func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
 func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
 	bw := bufio.NewWriter(conn)
 	bw := bufio.NewWriter(conn)
 	br := bufio.NewReader(conn)
 	br := bufio.NewReader(conn)
+
+	// defensive: ensure that jsonH has TermWhitespace turned on.
+	if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
+		panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
+	}
+
 	return rpcCodec{
 	return rpcCodec{
 		rwc: conn,
 		rwc: conn,
 		bw:  bw,
 		bw:  bw,
@@ -77,17 +84,17 @@ func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2, doFlush bool) (err e
 	if err = c.enc.Encode(obj1); err != nil {
 	if err = c.enc.Encode(obj1); err != nil {
 		return
 		return
 	}
 	}
-	t, tOk := c.h.(rpcEncodeTerminator)
-	if tOk {
-		c.bw.Write(t.rpcEncodeTerminate())
-	}
+	// t, tOk := c.h.(rpcEncodeTerminator)
+	// if tOk {
+	// 	c.bw.Write(t.rpcEncodeTerminate())
+	// }
 	if writeObj2 {
 	if writeObj2 {
 		if err = c.enc.Encode(obj2); err != nil {
 		if err = c.enc.Encode(obj2); err != nil {
 			return
 			return
 		}
 		}
-		if tOk {
-			c.bw.Write(t.rpcEncodeTerminate())
-		}
+		// if tOk {
+		// 	c.bw.Write(t.rpcEncodeTerminate())
+		// }
 	}
 	}
 	if doFlush {
 	if doFlush {
 		return c.bw.Flush()
 		return c.bw.Flush()

+ 9 - 7
cmd/vendor/github.com/ugorji/go/codec/simple.go

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

+ 21 - 21
cmd/vendor/github.com/ugorji/go/codec/time.go

@@ -197,24 +197,24 @@ func decodeTime(bs []byte) (tt time.Time, err error) {
 	return
 	return
 }
 }
 
 
-func timeLocUTCName(tzint int16) string {
-	if tzint == 0 {
-		return "UTC"
-	}
-	var tzname = []byte("UTC+00:00")
-	//tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below.
-	//tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
-	var tzhr, tzmin int16
-	if tzint < 0 {
-		tzname[3] = '-' // (TODO: verify. this works here)
-		tzhr, tzmin = -tzint/60, (-tzint)%60
-	} else {
-		tzhr, tzmin = tzint/60, tzint%60
-	}
-	tzname[4] = timeDigits[tzhr/10]
-	tzname[5] = timeDigits[tzhr%10]
-	tzname[7] = timeDigits[tzmin/10]
-	tzname[8] = timeDigits[tzmin%10]
-	return string(tzname)
-	//return time.FixedZone(string(tzname), int(tzint)*60)
-}
+// func timeLocUTCName(tzint int16) string {
+// 	if tzint == 0 {
+// 		return "UTC"
+// 	}
+// 	var tzname = []byte("UTC+00:00")
+// 	//tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below.
+// 	//tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
+// 	var tzhr, tzmin int16
+// 	if tzint < 0 {
+// 		tzname[3] = '-' // (TODO: verify. this works here)
+// 		tzhr, tzmin = -tzint/60, (-tzint)%60
+// 	} else {
+// 		tzhr, tzmin = tzint/60, tzint%60
+// 	}
+// 	tzname[4] = timeDigits[tzhr/10]
+// 	tzname[5] = timeDigits[tzhr%10]
+// 	tzname[7] = timeDigits[tzmin/10]
+// 	tzname[8] = timeDigits[tzmin%10]
+// 	return string(tzname)
+// 	//return time.FixedZone(string(tzname), int(tzint)*60)
+// }

+ 23 - 0
cmd/vendor/github.com/ugorji/go/codec/z.go

@@ -0,0 +1,23 @@
+// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import "sort"
+
+// TODO: this is brittle, as it depends on z.go's init() being called last.
+// The current build tools all honor that files are passed in lexical order.
+// However, we should consider using an init_channel,
+// that each person doing init will write to.
+
+func init() {
+	if !useLookupRecognizedTypes {
+		return
+	}
+	sort.Sort(uintptrSlice(recognizedRtids))
+	sort.Sort(uintptrSlice(recognizedRtidPtrs))
+	recognizedRtidOrPtrs = make([]uintptr, len(recognizedRtids)+len(recognizedRtidPtrs))
+	copy(recognizedRtidOrPtrs, recognizedRtids)
+	copy(recognizedRtidOrPtrs[len(recognizedRtids):], recognizedRtidPtrs)
+	sort.Sort(uintptrSlice(recognizedRtidOrPtrs))
+}

+ 3 - 3
glide.lock

@@ -1,5 +1,5 @@
-hash: c93e1fcd25d4fc0c1c35583de5b660e9369ec23f19c229aa1ffc1158fe19616f
-updated: 2017-10-06T15:12:44.328716326-07:00
+hash: 80a7efc9ff8767f29e9a02c19337e00655b25cc19ffa0bb95adeb83e4776dedb
+updated: 2017-10-19T23:09:56.080605596-06:00
 imports:
 imports:
 - name: github.com/beorn7/perks
 - name: github.com/beorn7/perks
   version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
   version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
@@ -113,7 +113,7 @@ imports:
   subpackages:
   subpackages:
   - wsproxy
   - wsproxy
 - name: github.com/ugorji/go
 - name: github.com/ugorji/go
-  version: 54210f4e076c57f351166f0ed60e67d3fca57a36
+  version: bdcc60b419d136a85cdf2e7cbcac34b3f1cd6e57
   subpackages:
   subpackages:
   - codec
   - codec
 - name: github.com/urfave/cli
 - name: github.com/urfave/cli

+ 1 - 1
glide.yaml

@@ -68,7 +68,7 @@ import:
 - package: github.com/spf13/pflag
 - package: github.com/spf13/pflag
   version: v1.0.0
   version: v1.0.0
 - package: github.com/ugorji/go
 - package: github.com/ugorji/go
-  version: 54210f4e076c57f351166f0ed60e67d3fca57a36
+  version: bdcc60b419d136a85cdf2e7cbcac34b3f1cd6e57
   subpackages:
   subpackages:
   - codec
   - codec
 - package: github.com/urfave/cli
 - package: github.com/urfave/cli

Some files were not shown because too many files changed in this diff