Procházet zdrojové kódy

codec: move Enc/Decoder into enc/decDriver for better memory arrangement

We reduce some pointer chasing by having the Encoder and Decoder be part of the
drivers respectively.

This should allow the referencing of the decoder/encoder from the driver without
dereferencing/loading some other value from memory.

This required some re-architecture of the data structures to support the usage model.
For example, New Encoder(writer, handle) now does:

    var e = handle.newEncDriver().encoder()
    e.Reset(w)
    return e

It resulted in some but not much of a performance difference, but I like the new
usage model and data structures better.
Ugorji Nwoke před 6 roky
rodič
revize
6393644481
8 změnil soubory, kde provedl 460 přidání a 409 odebrání
  1. 116 104
      codec/binc.go
  2. 67 56
      codec/cbor.go
  3. 12 21
      codec/decode.go
  4. 6 11
      codec/encode.go
  5. 7 2
      codec/helper.go
  6. 32 17
      codec/json.go
  7. 137 126
      codec/msgpack.go
  8. 83 72
      codec/simple.go

+ 116 - 104
codec/binc.go

@@ -101,9 +101,7 @@ func bincdesc(vd, vs byte) string {
 type bincEncDriver struct {
 	noBuiltInTypes
 	encDriverNoopContainerWriter
-	e *Encoder
 	h *BincHandle
-	w *encWr
 	m map[string]uint16 // symbols
 	b [8]byte           // scratch, used for encoding numbers - bigendian style
 	s uint16            // symbols sequencer
@@ -111,10 +109,15 @@ type bincEncDriver struct {
 	// encDriverTrackContainerWriter
 	// encNoSeparator
 	// _ [1]uint64 // padding
+	e Encoder
+}
+
+func (e *bincEncDriver) encoder() *Encoder {
+	return &e.e
 }
 
 func (e *bincEncDriver) EncodeNil() {
-	e.w.writen1(bincVdSpecial<<4 | bincSpNil)
+	e.e.encWr.writen1(bincVdSpecial<<4 | bincSpNil)
 }
 
 func (e *bincEncDriver) EncodeTime(t time.Time) {
@@ -122,31 +125,31 @@ func (e *bincEncDriver) EncodeTime(t time.Time) {
 		e.EncodeNil()
 	} else {
 		bs := bincEncodeTime(t)
-		e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
-		e.w.writeb(bs)
+		e.e.encWr.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
+		e.e.encWr.writeb(bs)
 	}
 }
 
 func (e *bincEncDriver) EncodeBool(b bool) {
 	if b {
-		e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
+		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpTrue)
 	} else {
-		e.w.writen1(bincVdSpecial<<4 | bincSpFalse)
+		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpFalse)
 	}
 }
 
 func (e *bincEncDriver) EncodeFloat32(f float32) {
 	if f == 0 {
-		e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
+		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
 		return
 	}
-	e.w.writen1(bincVdFloat<<4 | bincFlBin32)
-	bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
+	e.e.encWr.writen1(bincVdFloat<<4 | bincFlBin32)
+	bigenHelper{e.b[:4], e.e.w()}.writeUint32(math.Float32bits(f))
 }
 
 func (e *bincEncDriver) EncodeFloat64(f float64) {
 	if f == 0 {
-		e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
+		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
 		return
 	}
 	bigen.PutUint64(e.b[:8], math.Float64bits(f))
@@ -156,14 +159,14 @@ func (e *bincEncDriver) EncodeFloat64(f float64) {
 		}
 		i++
 		if i <= 6 {
-			e.w.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64)
-			e.w.writen1(byte(i))
-			e.w.writeb(e.b[:i])
+			e.e.encWr.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64)
+			e.e.encWr.writen1(byte(i))
+			e.e.encWr.writeb(e.b[:i])
 			return
 		}
 	}
-	e.w.writen1(bincVdFloat<<4 | bincFlBin64)
-	e.w.writeb(e.b[:8])
+	e.e.encWr.writen1(bincVdFloat<<4 | bincFlBin64)
+	e.e.encWr.writeb(e.b[:8])
 }
 
 func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8) {
@@ -174,11 +177,11 @@ func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8)
 	}
 	if bincDoPrune {
 		i := pruneSignExt(e.b[:lim], pos)
-		e.w.writen1(bd | lim - 1 - byte(i))
-		e.w.writeb(e.b[i:lim])
+		e.e.encWr.writen1(bd | lim - 1 - byte(i))
+		e.e.encWr.writeb(e.b[i:lim])
 	} else {
-		e.w.writen1(bd | lim - 1)
-		e.w.writeb(e.b[:lim])
+		e.e.encWr.writen1(bd | lim - 1)
+		e.e.encWr.writeb(e.b[:lim])
 	}
 }
 
@@ -187,7 +190,7 @@ func (e *bincEncDriver) EncodeInt(v int64) {
 	if v >= 0 {
 		e.encUint(bincVdPosInt<<4, true, uint64(v))
 	} else if v == -1 {
-		e.w.writen1(bincVdSpecial<<4 | bincSpNegOne)
+		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpNegOne)
 	} else {
 		e.encUint(bincVdNegInt<<4, false, uint64(-v))
 	}
@@ -199,14 +202,14 @@ func (e *bincEncDriver) EncodeUint(v uint64) {
 
 func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) {
 	if v == 0 {
-		e.w.writen1(bincVdSpecial<<4 | bincSpZero)
+		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpZero)
 	} else if pos && v >= 1 && v <= 16 {
-		e.w.writen1(bincVdSmallInt<<4 | byte(v-1))
+		e.e.encWr.writen1(bincVdSmallInt<<4 | byte(v-1))
 	} else if v <= math.MaxUint8 {
-		e.w.writen2(bd|0x0, byte(v))
+		e.e.encWr.writen2(bd|0x0, byte(v))
 	} else if v <= math.MaxUint16 {
-		e.w.writen1(bd | 0x01)
-		bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v))
+		e.e.encWr.writen1(bd | 0x01)
+		bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(v))
 	} else if v <= math.MaxUint32 {
 		e.encIntegerPrune(bd, pos, v, 4)
 	} else {
@@ -228,7 +231,7 @@ func (e *bincEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
 		return
 	}
 	e.encodeExtPreamble(uint8(xtag), len(bs))
-	e.w.writeb(bs)
+	e.e.encWr.writeb(bs)
 	if ext == SelfExt {
 		e.e.blist.put(bs) // bufp.end()
 	}
@@ -236,12 +239,12 @@ func (e *bincEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
 
 func (e *bincEncDriver) EncodeRawExt(re *RawExt) {
 	e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
-	e.w.writeb(re.Data)
+	e.e.encWr.writeb(re.Data)
 }
 
 func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
 	e.encLen(bincVdCustomExt<<4, uint64(length))
-	e.w.writen1(xtag)
+	e.e.encWr.writen1(xtag)
 }
 
 func (e *bincEncDriver) WriteArrayStart(length int) {
@@ -268,7 +271,7 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
 		return
 	} else if l == 1 {
 		e.encBytesLen(cUTF8, 1)
-		e.w.writen1(v[0])
+		e.e.encWr.writen1(v[0])
 		return
 	}
 	if e.m == nil {
@@ -278,10 +281,10 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
 	ui, ok := e.m[v]
 	if ok {
 		if ui <= math.MaxUint8 {
-			e.w.writen2(bincVdSymbol<<4, byte(ui))
+			e.e.encWr.writen2(bincVdSymbol<<4, byte(ui))
 		} else {
-			e.w.writen1(bincVdSymbol<<4 | 0x8)
-			bigenHelper{e.b[:2], e.w}.writeUint16(ui)
+			e.e.encWr.writen1(bincVdSymbol<<4 | 0x8)
+			bigenHelper{e.b[:2], e.e.w()}.writeUint16(ui)
 		}
 	} else {
 		e.s++
@@ -299,21 +302,21 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
 			lenprec = 3
 		}
 		if ui <= math.MaxUint8 {
-			e.w.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui))
+			e.e.encWr.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui))
 		} else {
-			e.w.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec)
-			bigenHelper{e.b[:2], e.w}.writeUint16(ui)
+			e.e.encWr.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec)
+			bigenHelper{e.b[:2], e.e.w()}.writeUint16(ui)
 		}
 		if lenprec == 0 {
-			e.w.writen1(byte(l))
+			e.e.encWr.writen1(byte(l))
 		} else if lenprec == 1 {
-			bigenHelper{e.b[:2], e.w}.writeUint16(uint16(l))
+			bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(l))
 		} else if lenprec == 2 {
-			bigenHelper{e.b[:4], e.w}.writeUint32(uint32(l))
+			bigenHelper{e.b[:4], e.e.w()}.writeUint32(uint32(l))
 		} else {
-			bigenHelper{e.b[:8], e.w}.writeUint64(uint64(l))
+			bigenHelper{e.b[:8], e.e.w()}.writeUint64(uint64(l))
 		}
-		e.w.writestr(v)
+		e.e.encWr.writestr(v)
 	}
 }
 
@@ -325,7 +328,7 @@ func (e *bincEncDriver) EncodeStringEnc(c charEncoding, v string) {
 	l := uint64(len(v))
 	e.encLen(bincVdString<<4, l) // e.encBytesLen(c, l)
 	if l > 0 {
-		e.w.writestr(v)
+		e.e.encWr.writestr(v)
 	}
 
 }
@@ -338,7 +341,7 @@ func (e *bincEncDriver) EncodeStringBytesRaw(v []byte) {
 	l := uint64(len(v))
 	e.encLen(bincVdByteArray<<4, l) // e.encBytesLen(c, l)
 	if l > 0 {
-		e.w.writeb(v)
+		e.e.encWr.writeb(v)
 	}
 }
 
@@ -353,7 +356,7 @@ func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
 
 func (e *bincEncDriver) encLen(bd byte, l uint64) {
 	if l < 12 {
-		e.w.writen1(bd | uint8(l+4))
+		e.e.encWr.writen1(bd | uint8(l+4))
 	} else {
 		e.encLenNumber(bd, l)
 	}
@@ -361,16 +364,16 @@ func (e *bincEncDriver) encLen(bd byte, l uint64) {
 
 func (e *bincEncDriver) encLenNumber(bd byte, v uint64) {
 	if v <= math.MaxUint8 {
-		e.w.writen2(bd, byte(v))
+		e.e.encWr.writen2(bd, byte(v))
 	} else if v <= math.MaxUint16 {
-		e.w.writen1(bd | 0x01)
-		bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v))
+		e.e.encWr.writen1(bd | 0x01)
+		bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(v))
 	} else if v <= math.MaxUint32 {
-		e.w.writen1(bd | 0x02)
-		bigenHelper{e.b[:4], e.w}.writeUint32(uint32(v))
+		e.e.encWr.writen1(bd | 0x02)
+		bigenHelper{e.b[:4], e.e.w()}.writeUint32(uint32(v))
 	} else {
-		e.w.writen1(bd | 0x03)
-		bigenHelper{e.b[:8], e.w}.writeUint64(uint64(v))
+		e.e.encWr.writen1(bd | 0x03)
+		bigenHelper{e.b[:8], e.e.w()}.writeUint64(uint64(v))
 	}
 }
 
@@ -386,10 +389,7 @@ type bincDecDriver struct {
 	decDriverNoopContainerReader
 	noBuiltInTypes
 
-	d      *Decoder
 	h      *BincHandle
-	r      *decRd
-	br     bool // bytes reader
 	bdRead bool
 	bd     byte
 	vd     byte
@@ -405,10 +405,16 @@ type bincDecDriver struct {
 	// decNoSeparator
 
 	b [8]byte // scratch for decoding numbers - big endian style
+
+	d Decoder
+}
+
+func (d *bincDecDriver) decoder() *Decoder {
+	return &d.d
 }
 
 func (d *bincDecDriver) readNextBd() {
-	d.bd = d.r.readn1()
+	d.bd = d.d.decRd.readn1()
 	d.vd = d.bd >> 4
 	d.vs = d.bd & 0x0f
 	d.bdRead = true
@@ -416,7 +422,7 @@ func (d *bincDecDriver) readNextBd() {
 
 func (d *bincDecDriver) uncacheRead() {
 	if d.bdRead {
-		d.r.unreadn1()
+		d.d.decRd.unreadn1()
 		d.bdRead = false
 	}
 }
@@ -475,7 +481,7 @@ func (d *bincDecDriver) DecodeTime() (t time.Time) {
 		d.d.errorf("cannot decode time - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 	}
-	t, err := bincDecodeTime(d.r.readx(uint(d.vs)))
+	t, err := bincDecodeTime(d.d.decRd.readx(uint(d.vs)))
 	if err != nil {
 		panic(err)
 	}
@@ -485,9 +491,9 @@ func (d *bincDecDriver) DecodeTime() (t time.Time) {
 
 func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
 	if vs&0x8 == 0 {
-		d.r.readb(d.b[0:defaultLen])
+		d.d.decRd.readb(d.b[0:defaultLen])
 	} else {
-		l := d.r.readn1()
+		l := d.d.decRd.readn1()
 		if l > 8 {
 			d.d.errorf("cannot read float - at most 8 bytes used to represent float - received %v bytes", l)
 			return
@@ -495,12 +501,12 @@ func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
 		for i := l; i < 8; i++ {
 			d.b[i] = 0
 		}
-		d.r.readb(d.b[0:l])
+		d.d.decRd.readb(d.b[0:l])
 	}
 }
 
 func (d *bincDecDriver) decFloat() (f float64) {
-	//if true { f = math.Float64frombits(bigen.Uint64(d.r.readx(8))); break; }
+	//if true { f = math.Float64frombits(bigen.Uint64(d.d.decRd.readx(8))); break; }
 	if x := d.vs & 0x7; x == bincFlBin32 {
 		d.decFloatPre(d.vs, 4)
 		f = float64(math.Float32frombits(bigen.Uint32(d.b[0:4])))
@@ -519,26 +525,26 @@ func (d *bincDecDriver) decUint() (v uint64) {
 	// need to inline the code (interface conversion and type assertion expensive)
 	switch d.vs {
 	case 0:
-		v = uint64(d.r.readn1())
+		v = uint64(d.d.decRd.readn1())
 	case 1:
-		d.r.readb(d.b[6:8])
+		d.d.decRd.readb(d.b[6:8])
 		v = uint64(bigen.Uint16(d.b[6:8]))
 	case 2:
 		d.b[4] = 0
-		d.r.readb(d.b[5:8])
+		d.d.decRd.readb(d.b[5:8])
 		v = uint64(bigen.Uint32(d.b[4:8]))
 	case 3:
-		d.r.readb(d.b[4:8])
+		d.d.decRd.readb(d.b[4:8])
 		v = uint64(bigen.Uint32(d.b[4:8]))
 	case 4, 5, 6:
 		lim := 7 - d.vs
-		d.r.readb(d.b[lim:8])
+		d.d.decRd.readb(d.b[lim:8])
 		for i := uint8(0); i < lim; i++ {
 			d.b[i] = 0
 		}
 		v = uint64(bigen.Uint64(d.b[:8]))
 	case 7:
-		d.r.readb(d.b[:8])
+		d.d.decRd.readb(d.b[:8])
 		v = uint64(bigen.Uint64(d.b[:8]))
 	default:
 		d.d.errorf("unsigned integers with greater than 64 bits of precision not supported")
@@ -681,15 +687,15 @@ func (d *bincDecDriver) decLen() int {
 
 func (d *bincDecDriver) decLenNumber() (v uint64) {
 	if x := d.vs; x == 0 {
-		v = uint64(d.r.readn1())
+		v = uint64(d.d.decRd.readn1())
 	} else if x == 1 {
-		d.r.readb(d.b[6:8])
+		d.d.decRd.readb(d.b[6:8])
 		v = uint64(bigen.Uint16(d.b[6:8]))
 	} else if x == 2 {
-		d.r.readb(d.b[4:8])
+		d.d.decRd.readb(d.b[4:8])
 		v = uint64(bigen.Uint32(d.b[4:8]))
 	} else {
-		d.r.readb(d.b[:8])
+		d.d.decRd.readb(d.b[:8])
 		v = bigen.Uint64(d.b[:8])
 	}
 	return
@@ -705,15 +711,15 @@ func (d *bincDecDriver) decStringBytes(bs []byte, zerocopy bool) (bs2 []byte) {
 	case bincVdString, bincVdByteArray:
 		slen = d.decLen()
 		if zerocopy {
-			if d.br {
-				bs2 = d.r.readx(uint(slen))
+			if d.d.bytes {
+				bs2 = d.d.decRd.readx(uint(slen))
 			} else if len(bs) == 0 {
-				bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, d.d.b[:])
+				bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, d.d.b[:])
 			} else {
-				bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
+				bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, bs)
 			}
 		} else {
-			bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
+			bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, bs)
 		}
 	case bincVdSymbol:
 		// zerocopy doesn't apply for symbols,
@@ -726,9 +732,9 @@ func (d *bincDecDriver) decStringBytes(bs []byte, zerocopy bool) (bs2 []byte) {
 		var symbol uint16
 		vs := d.vs
 		if vs&0x8 == 0 {
-			symbol = uint16(d.r.readn1())
+			symbol = uint16(d.d.decRd.readn1())
 		} else {
-			symbol = uint16(bigen.Uint16(d.r.readx(2)))
+			symbol = uint16(bigen.Uint16(d.d.decRd.readx(2)))
 		}
 		if d.s == nil {
 			// d.s = pool4mapU16Bytes.Get().(map[uint16][]byte) // make([]bincDecSymbol, 0, 16)
@@ -740,18 +746,18 @@ func (d *bincDecDriver) decStringBytes(bs []byte, zerocopy bool) (bs2 []byte) {
 		} else {
 			switch vs & 0x3 {
 			case 0:
-				slen = int(d.r.readn1())
+				slen = int(d.d.decRd.readn1())
 			case 1:
-				slen = int(bigen.Uint16(d.r.readx(2)))
+				slen = int(bigen.Uint16(d.d.decRd.readx(2)))
 			case 2:
-				slen = int(bigen.Uint32(d.r.readx(4)))
+				slen = int(bigen.Uint32(d.d.decRd.readx(4)))
 			case 3:
-				slen = int(bigen.Uint64(d.r.readx(8)))
+				slen = int(bigen.Uint64(d.d.decRd.readx(8)))
 			}
 			// since using symbols, do not store any part of
 			// the parameter bs in the map, as it might be a shared buffer.
-			// bs2 = decByteSlice(d.r, slen, bs)
-			bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, nil)
+			// bs2 = decByteSlice(d.d.r(), slen, bs)
+			bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, nil)
 			d.s[symbol] = bs2
 			// d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
 		}
@@ -793,13 +799,13 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 	}
 	d.bdRead = false
 	if zerocopy {
-		if d.br {
-			return d.r.readx(uint(clen))
+		if d.d.bytes {
+			return d.d.decRd.readx(uint(clen))
 		} else if len(bs) == 0 {
 			bs = d.d.b[:]
 		}
 	}
-	return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
+	return decByteSlice(d.d.r(), clen, d.d.h.MaxInitLen, bs)
 }
 
 func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
@@ -815,7 +821,7 @@ func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
 	if ext == nil {
 		re := rv.(*RawExt)
 		re.Tag = realxtag
-		re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
+		re.Data = detachZeroCopyBytes(d.d.bytes, re.Data, xbs)
 	} else if ext == SelfExt {
 		d.d.sideDecode(rv, xbs)
 	} else {
@@ -826,15 +832,15 @@ func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
 func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
 	if d.vd == bincVdCustomExt {
 		l := d.decLen()
-		xtag = d.r.readn1()
+		xtag = d.d.decRd.readn1()
 		if verifyTag && xtag != tag {
 			d.d.errorf("wrong extension tag - got %b, expecting: %v", xtag, tag)
 			return
 		}
-		if d.br {
-			xbs = d.r.readx(uint(l))
+		if d.d.bytes {
+			xbs = d.d.decRd.readx(uint(l))
 		} else {
-			xbs = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
+			xbs = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
 		}
 	} else if d.vd == bincVdByteArray {
 		xbs = d.DecodeBytes(nil, true)
@@ -909,10 +915,10 @@ func (d *bincDecDriver) DecodeNaked() {
 		n.v = valueTypeString
 		n.s = string(d.DecodeStringAsBytes())
 	case bincVdByteArray:
-		decNakedReadRawBytes(d, d.d, n, d.h.RawToString)
+		decNakedReadRawBytes(d, &d.d, n, d.h.RawToString)
 	case bincVdTimestamp:
 		n.v = valueTypeTime
-		tt, err := bincDecodeTime(d.r.readx(uint(d.vs)))
+		tt, err := bincDecodeTime(d.d.decRd.readx(uint(d.vs)))
 		if err != nil {
 			panic(err)
 		}
@@ -920,11 +926,11 @@ func (d *bincDecDriver) DecodeNaked() {
 	case bincVdCustomExt:
 		n.v = valueTypeExt
 		l := d.decLen()
-		n.u = uint64(d.r.readn1())
-		if d.br {
-			n.l = d.r.readx(uint(l))
+		n.u = uint64(d.d.decRd.readn1())
+		if d.d.bytes {
+			n.l = d.d.decRd.readx(uint(l))
 		} else {
-			n.l = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
+			n.l = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
 		}
 	case bincVdArray:
 		n.v = valueTypeArray
@@ -990,16 +996,23 @@ type BincHandle struct {
 // Name returns the name of the handle: binc
 func (h *BincHandle) Name() string { return "binc" }
 
-func (h *BincHandle) newEncDriver(e *Encoder) encDriver {
-	return &bincEncDriver{e: e, h: h, w: e.w()}
+func (h *BincHandle) newEncDriver() encDriver {
+	var e = &bincEncDriver{h: h}
+	e.e.e = e
+	e.e.init(h)
+	e.reset()
+	return e
 }
 
-func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
-	return &bincDecDriver{d: d, h: h, r: d.r(), br: d.bytes}
+func (h *BincHandle) newDecDriver() decDriver {
+	d := &bincDecDriver{h: h}
+	d.d.d = d
+	d.d.init(h)
+	d.reset()
+	return d
 }
 
 func (e *bincEncDriver) reset() {
-	e.w = e.e.w()
 	e.s = 0
 	e.m = nil
 }
@@ -1015,7 +1028,6 @@ func (e *bincEncDriver) atEndOfEncode() {
 }
 
 func (d *bincDecDriver) reset() {
-	d.r, d.br = d.d.r(), d.d.bytes
 	d.s = nil
 	d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
 	d.fnil = false

+ 67 - 56
codec/cbor.go

@@ -115,49 +115,52 @@ func cbordesc(bd byte) string {
 type cborEncDriver struct {
 	noBuiltInTypes
 	encDriverNoopContainerWriter
-	e *Encoder
-	w *encWr
 	h *CborHandle
 	x [8]byte
 	// _ [3]uint64 // padding
+	e Encoder
+}
+
+func (e *cborEncDriver) encoder() *Encoder {
+	return &e.e
 }
 
 func (e *cborEncDriver) EncodeNil() {
-	e.w.writen1(cborBdNil)
+	e.e.encWr.writen1(cborBdNil)
 }
 
 func (e *cborEncDriver) EncodeBool(b bool) {
 	if b {
-		e.w.writen1(cborBdTrue)
+		e.e.encWr.writen1(cborBdTrue)
 	} else {
-		e.w.writen1(cborBdFalse)
+		e.e.encWr.writen1(cborBdFalse)
 	}
 }
 
 func (e *cborEncDriver) EncodeFloat32(f float32) {
-	e.w.writen1(cborBdFloat32)
-	bigenHelper{e.x[:4], e.w}.writeUint32(math.Float32bits(f))
+	e.e.encWr.writen1(cborBdFloat32)
+	bigenHelper{e.x[:4], e.e.w()}.writeUint32(math.Float32bits(f))
 }
 
 func (e *cborEncDriver) EncodeFloat64(f float64) {
-	e.w.writen1(cborBdFloat64)
-	bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
+	e.e.encWr.writen1(cborBdFloat64)
+	bigenHelper{e.x[:8], e.e.w()}.writeUint64(math.Float64bits(f))
 }
 
 func (e *cborEncDriver) encUint(v uint64, bd byte) {
 	if v <= 0x17 {
-		e.w.writen1(byte(v) + bd)
+		e.e.encWr.writen1(byte(v) + bd)
 	} else if v <= math.MaxUint8 {
-		e.w.writen2(bd+0x18, uint8(v))
+		e.e.encWr.writen2(bd+0x18, uint8(v))
 	} else if v <= math.MaxUint16 {
-		e.w.writen1(bd + 0x19)
-		bigenHelper{e.x[:2], e.w}.writeUint16(uint16(v))
+		e.e.encWr.writen1(bd + 0x19)
+		bigenHelper{e.x[:2], e.e.w()}.writeUint16(uint16(v))
 	} else if v <= math.MaxUint32 {
-		e.w.writen1(bd + 0x1a)
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(v))
+		e.e.encWr.writen1(bd + 0x1a)
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(v))
 	} else { // if v <= math.MaxUint64 {
-		e.w.writen1(bd + 0x1b)
-		bigenHelper{e.x[:8], e.w}.writeUint64(v)
+		e.e.encWr.writen1(bd + 0x1b)
+		bigenHelper{e.x[:8], e.e.w()}.writeUint64(v)
 	}
 }
 
@@ -222,7 +225,7 @@ func (e *cborEncDriver) EncodeRawExt(re *RawExt) {
 
 func (e *cborEncDriver) WriteArrayStart(length int) {
 	if e.h.IndefiniteLength {
-		e.w.writen1(cborBdIndefiniteArray)
+		e.e.encWr.writen1(cborBdIndefiniteArray)
 	} else {
 		e.encLen(cborBaseArray, length)
 	}
@@ -230,7 +233,7 @@ func (e *cborEncDriver) WriteArrayStart(length int) {
 
 func (e *cborEncDriver) WriteMapStart(length int) {
 	if e.h.IndefiniteLength {
-		e.w.writen1(cborBdIndefiniteMap)
+		e.e.encWr.writen1(cborBdIndefiniteMap)
 	} else {
 		e.encLen(cborBaseMap, length)
 	}
@@ -238,13 +241,13 @@ func (e *cborEncDriver) WriteMapStart(length int) {
 
 func (e *cborEncDriver) WriteMapEnd() {
 	if e.h.IndefiniteLength {
-		e.w.writen1(cborBdBreak)
+		e.e.encWr.writen1(cborBdBreak)
 	}
 }
 
 func (e *cborEncDriver) WriteArrayEnd() {
 	if e.h.IndefiniteLength {
-		e.w.writen1(cborBdBreak)
+		e.e.encWr.writen1(cborBdBreak)
 	}
 }
 
@@ -263,9 +266,9 @@ func (e *cborEncDriver) EncodeStringBytesRaw(v []byte) {
 func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
 	if e.h.IndefiniteLength {
 		if bb == cborBaseBytes {
-			e.w.writen1(cborBdIndefiniteBytes)
+			e.e.encWr.writen1(cborBdIndefiniteBytes)
 		} else {
-			e.w.writen1(cborBdIndefiniteString)
+			e.e.encWr.writen1(cborBdIndefiniteString)
 		}
 		var vlen uint = uint(len(v))
 		blen := vlen / 4
@@ -283,46 +286,44 @@ func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
 				v2 = v[i:]
 			}
 			e.encLen(bb, len(v2))
-			e.w.writestr(v2)
+			e.e.encWr.writestr(v2)
 			i = i2
 		}
-		e.w.writen1(cborBdBreak)
+		e.e.encWr.writen1(cborBdBreak)
 	} else {
 		e.encLen(bb, len(v))
-		e.w.writestr(v)
+		e.e.encWr.writestr(v)
 	}
 }
 
 // ----------------------
 
 type cborDecDriver struct {
-	d      *Decoder
+	decDriverNoopContainerReader
 	h      *CborHandle
-	r      *decRd
-	br     bool // bytes reader
 	bdRead bool
 	bd     byte
 	st     bool // skip tags
 	fnil   bool // found nil
 	noBuiltInTypes
 	// decNoSeparator
-	decDriverNoopContainerReader
 	// _ [3]uint64 // padding
+	d Decoder
 }
 
 // func (d *cborDecDriver) readNextBdSkipTags() {
-// 	d.bd = d.r.readn1()
+// 	d.bd = d.d.decRd.readn1()
 // 	if d.h.SkipUnexpectedTags {
 // 		for d.bd >= cborBaseTag && d.bd < cborBaseSimple {
 // 			d.decUint()
-// 			d.bd = d.r.readn1()
+// 			d.bd = d.d.decRd.readn1()
 // 		}
 // 	}
 // 	d.bdRead = true
 // }
 
 // func (d *cborDecDriver) readNextBd() {
-// 	d.bd = d.r.readn1()
+// 	d.bd = d.d.decRd.readn1()
 // 	if d.handleCborSelfDesc && d.bd == cborSelfDesrTag {
 // 		if x := d.readn1(); x == cborSelfDesrTag2 {
 // 			if x = d.readn1(); x != cborSelfDesrTag3 {
@@ -335,8 +336,12 @@ type cborDecDriver struct {
 // 	d.bdRead = true
 // }
 
+func (d *cborDecDriver) decoder() *Decoder {
+	return &d.d
+}
+
 func (d *cborDecDriver) readNextBd() {
-	d.bd = d.r.readn1()
+	d.bd = d.d.decRd.readn1()
 	d.bdRead = true
 }
 
@@ -363,13 +368,13 @@ func (d *cborDecDriver) advanceNil() (null bool) {
 func (d *cborDecDriver) skipTags() {
 	for d.bd>>5 == cborMajorTag {
 		d.decUint()
-		d.bd = d.r.readn1()
+		d.bd = d.d.decRd.readn1()
 	}
 }
 
 func (d *cborDecDriver) uncacheRead() {
 	if d.bdRead {
-		d.r.unreadn1()
+		d.d.decRd.unreadn1()
 		d.bdRead = false
 	}
 }
@@ -426,13 +431,13 @@ func (d *cborDecDriver) decUint() (ui uint64) {
 		ui = uint64(v)
 	} else {
 		if v == 0x18 {
-			ui = uint64(d.r.readn1())
+			ui = uint64(d.d.decRd.readn1())
 		} else if v == 0x19 {
-			ui = uint64(bigen.Uint16(d.r.readx(2)))
+			ui = uint64(bigen.Uint16(d.d.decRd.readx(2)))
 		} else if v == 0x1a {
-			ui = uint64(bigen.Uint32(d.r.readx(4)))
+			ui = uint64(bigen.Uint32(d.d.decRd.readx(4)))
 		} else if v == 0x1b {
-			ui = uint64(bigen.Uint64(d.r.readx(8)))
+			ui = uint64(bigen.Uint64(d.d.decRd.readx(8)))
 		} else {
 			d.d.errorf("invalid descriptor decoding uint: %x/%s", d.bd, cbordesc(d.bd))
 			return
@@ -487,8 +492,8 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
 		} else {
 			bs = bs[:newLen]
 		}
-		d.r.readb(bs[oldLen:newLen])
-		// bs = append(bs, d.r.readn()...)
+		d.d.decRd.readb(bs[oldLen:newLen])
+		// bs = append(bs, d.d.decRd.readn()...)
 		d.bdRead = false
 	}
 	d.bdRead = false
@@ -526,11 +531,11 @@ func (d *cborDecDriver) DecodeFloat64() (f float64) {
 	}
 	switch d.bd {
 	case cborBdFloat16:
-		f = float64(math.Float32frombits(halfFloatToFloatBits(bigen.Uint16(d.r.readx(2)))))
+		f = float64(math.Float32frombits(halfFloatToFloatBits(bigen.Uint16(d.d.decRd.readx(2)))))
 	case cborBdFloat32:
-		f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+		f = float64(math.Float32frombits(bigen.Uint32(d.d.decRd.readx(4))))
 	case cborBdFloat64:
-		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+		f = math.Float64frombits(bigen.Uint64(d.d.decRd.readx(8)))
 	default:
 		major := d.bd >> 5
 		if major == cborMajorUint {
@@ -653,13 +658,13 @@ func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 	clen := d.decLen()
 	d.bdRead = false
 	if zerocopy {
-		if d.br {
-			return d.r.readx(uint(clen))
+		if d.d.bytes {
+			return d.d.decRd.readx(uint(clen))
 		} else if len(bs) == 0 {
 			bs = d.d.b[:]
 		}
 	}
-	return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
+	return decByteSlice(d.d.r(), clen, d.h.MaxInitLen, bs)
 }
 
 func (d *cborDecDriver) DecodeStringAsBytes() (s []byte) {
@@ -759,7 +764,7 @@ func (d *cborDecDriver) DecodeNaked() {
 		n.v = valueTypeInt
 		n.i = d.DecodeInt64()
 	case cborMajorBytes:
-		decNakedReadRawBytes(d, d.d, n, d.h.RawToString)
+		decNakedReadRawBytes(d, &d.d, n, d.h.RawToString)
 	case cborMajorString:
 		n.v = valueTypeString
 		n.s = string(d.DecodeStringAsBytes())
@@ -801,7 +806,7 @@ func (d *cborDecDriver) DecodeNaked() {
 			n.v = valueTypeFloat
 			n.f = d.DecodeFloat64()
 		case cborBdIndefiniteBytes:
-			decNakedReadRawBytes(d, d.d, n, d.h.RawToString)
+			decNakedReadRawBytes(d, &d.d, n, d.h.RawToString)
 		case cborBdIndefiniteString:
 			n.v = valueTypeString
 			n.s = string(d.DecodeStringAsBytes())
@@ -863,20 +868,26 @@ type CborHandle struct {
 // Name returns the name of the handle: cbor
 func (h *CborHandle) Name() string { return "cbor" }
 
-func (h *CborHandle) newEncDriver(e *Encoder) encDriver {
-	return &cborEncDriver{e: e, w: e.w(), h: h}
+func (h *CborHandle) newEncDriver() encDriver {
+	var e = &cborEncDriver{h: h}
+	e.e.e = e
+	e.e.init(h)
+	e.reset()
+	return e
 }
 
-func (h *CborHandle) newDecDriver(d *Decoder) decDriver {
-	return &cborDecDriver{d: d, h: h, r: d.r(), br: d.bytes, st: h.SkipUnexpectedTags}
+func (h *CborHandle) newDecDriver() decDriver {
+	d := &cborDecDriver{h: h, st: h.SkipUnexpectedTags}
+	d.d.d = d
+	d.d.init(h)
+	d.reset()
+	return d
 }
 
 func (e *cborEncDriver) reset() {
-	e.w = e.e.w()
 }
 
 func (d *cborDecDriver) reset() {
-	d.r, d.br = d.d.r(), d.d.bytes
 	d.bd = 0
 	d.bdRead = false
 	d.fnil = false

+ 12 - 21
codec/decode.go

@@ -149,6 +149,8 @@ type decDriver interface {
 	reset()
 	atEndOfDecode()
 	uncacheRead()
+
+	decoder() *Decoder
 }
 
 type decDriverContainerTracker interface {
@@ -1392,7 +1394,7 @@ type Decoder struct {
 // For efficiency, Users are encouraged to configure ReaderBufferSize on the handle
 // OR pass in a memory buffered reader (eg bufio.Reader, bytes.Buffer).
 func NewDecoder(r io.Reader, h Handle) *Decoder {
-	d := newDecoder(h)
+	d := h.newDecDriver().decoder()
 	d.Reset(r)
 	return d
 }
@@ -1400,43 +1402,32 @@ func NewDecoder(r io.Reader, h Handle) *Decoder {
 // NewDecoderBytes returns a Decoder which efficiently decodes directly
 // from a byte slice with zero copying.
 func NewDecoderBytes(in []byte, h Handle) *Decoder {
-	d := newDecoder(h)
+	d := h.newDecDriver().decoder()
 	d.ResetBytes(in)
 	return d
 }
 
 // var defaultDecNaked decNaked
 
-func newDecoder(h Handle) *Decoder {
-	d := &Decoder{h: basicHandle(h), err: errDecoderNotInitialized}
-	d.bytes = true
+func (d *Decoder) r() *decRd {
+	return &d.decRd
+}
+
+func (d *Decoder) init(h Handle) {
 	if useFinalizers {
 		// runtime.SetFinalizer(d, (*Decoder).finalize)
 	}
+	d.bytes = true
+	d.err = errDecoderNotInitialized
 	// d.r = &d.decRd
+	d.h = basicHandle(h)
 	d.hh = h
 	d.be = h.isBinary()
 	// NOTE: do not initialize d.n here. It is lazily initialized in d.naked()
-	var jh *JsonHandle
-	jh, d.js = h.(*JsonHandle)
-	d.jdec = nil
-	if d.js {
-		d.jsms = jh.MapKeyAsString
-	}
 	// d.esep = d.hh.hasElemSeparators()
 	if d.h.InternString {
 		d.is = make(map[string]string, 32)
 	}
-	d.d = h.newDecDriver(d)
-	if d.js {
-		d.jdec = d.d.(*jsonDecDriver)
-	}
-	// d.cr, _ = d.d.(containerStateRecv)
-	return d
-}
-
-func (d *Decoder) r() *decRd {
-	return &d.decRd
 }
 
 func (d *Decoder) resetCommon() {

+ 6 - 11
codec/encode.go

@@ -44,6 +44,7 @@ type encDriver interface {
 
 	reset()
 	atEndOfEncode()
+	encoder() *Encoder
 }
 
 type encDriverContainerTracker interface {
@@ -883,7 +884,7 @@ type Encoder struct {
 // For efficiency, Users are encouraged to configure WriterBufferSize on the handle
 // OR pass in a memory buffered writer (eg bufio.Writer, bytes.Buffer).
 func NewEncoder(w io.Writer, h Handle) *Encoder {
-	e := newEncoder(h)
+	e := h.newEncDriver().encoder()
 	e.Reset(w)
 	return e
 }
@@ -894,29 +895,23 @@ func NewEncoder(w io.Writer, h Handle) *Encoder {
 // It will potentially replace the output byte slice pointed to.
 // After encoding, the out parameter contains the encoded contents.
 func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
-	e := newEncoder(h)
+	e := h.newEncDriver().encoder()
 	e.ResetBytes(out)
 	return e
 }
 
-func newEncoder(h Handle) *Encoder {
-	e := &Encoder{h: basicHandle(h), err: errEncoderNotInitialized}
+func (e *Encoder) init(h Handle) {
+	e.err = errEncoderNotInitialized
 	e.bytes = true
 	if useFinalizers {
 		// runtime.SetFinalizer(e, (*Encoder).finalize)
 	}
 	// e.w = &e.encWr
 	e.hh = h
+	e.h = basicHandle(h)
 	// e.esep = h.hasElemSeparators()
-	e.e = e.hh.newEncDriver(e)
 	e.as, e.isas = e.e.(encDriverAsis)
 	e.be = e.hh.isBinary()
-	e.jenc = nil
-	_, e.js = e.hh.(*JsonHandle)
-	if e.js {
-		e.jenc = e.e.(*jsonEncDriver)
-	}
-	return e
 }
 
 func (e *Encoder) w() *encWr {

+ 7 - 2
codec/helper.go

@@ -97,11 +97,16 @@ package codec
 //    - Pointer chasing
 // This package tries hard to manage the performance impact of these.
 //
+// ------------------------------------------
 // To alleviate performance due to pointer-chasing:
 //    - Prefer non-pointer values in a struct field
 //    - Refer to these directly within helper classes
 //      e.g. json.go refers directly to d.d.decRd
 //
+// We made the changes to embed En/Decoder in en/decDriver,
+// but we had to explicitly reference the fields as opposed to using a function
+// to get the better performance that we were looking for.
+// For example, we explicitly call d.d.decRd.fn() instead of d.d.r().fn().
 
 import (
 	"bytes"
@@ -1049,8 +1054,8 @@ type Handle interface {
 	// Prefer to use basicHandle() helper function that ensures it has been inited.
 	getBasicHandle() *BasicHandle
 	// recreateEncDriver(encDriver) bool
-	newEncDriver(w *Encoder) encDriver
-	newDecDriver(r *Decoder) decDriver
+	newEncDriver() encDriver
+	newDecDriver() decDriver
 	isBinary() bool
 	// hasElemSeparators() bool
 	// IsBuiltinType(rtid uintptr) bool

+ 32 - 17
codec/json.go

@@ -131,7 +131,6 @@ func init() {
 type jsonEncDriver struct {
 	noBuiltInTypes
 	// w *encWr
-	e *Encoder
 	h *JsonHandle
 
 	// bs []byte // for encoding strings
@@ -150,13 +149,15 @@ type jsonEncDriver struct {
 
 	s *bitset256 // safe set for characters (taking h.HTMLAsIs into consideration)
 	// scratch: encode time, numbers, etc. Note: leave 1 byte for containerState
-	b [cacheLineSize + 16]byte // buffer for encoding numbers and time
+	b [cacheLineSize + 24]byte // buffer for encoding numbers and time
+
+	e Encoder
 }
 
 // Keep writeIndent, WriteArrayElem, WriteMapElemKey, WriteMapElemValue
 // in jsonEncDriver, so that *Encoder can directly call them
 
-// func (e *jsonEncDriver) getJsonEncDriver() *jsonEncDriver { return e }
+func (e *jsonEncDriver) encoder() *Encoder { return &e.e }
 
 func (e *jsonEncDriver) writeIndent() {
 	e.e.encWr.writen1('\n')
@@ -407,7 +408,7 @@ func (e *jsonEncDriver) WriteMapEnd() {
 func (e *jsonEncDriver) quoteStr(s string) {
 	// adapted from std pkg encoding/json
 	const hex = "0123456789abcdef"
-	w := &e.e.encWr
+	w := e.e.w()
 	w.writen1('"')
 	var start int
 	for i := 0; i < len(s); {
@@ -578,7 +579,6 @@ func (e *jsonEncDriverTypical) EncodeFloat32(f float32) {
 
 type jsonDecDriver struct {
 	noBuiltInTypes
-	d *Decoder
 	h *JsonHandle
 	// r *decRd
 
@@ -597,13 +597,16 @@ type jsonDecDriver struct {
 	buf []byte
 	se  interfaceExtWrapper
 
-	// _ [4]uint64 // padding
+	_ uint64 // padding
 
 	// ---- cpu cache line boundary?
 
 	// b2 [cacheLineSize + 32]byte // scratch 2, used only for readUntil, decNumBytes
 
 	// n jsonNum
+
+	// ---- cpu cache line boundary?
+	d Decoder
 }
 
 // func jsonIsWS(b byte) bool {
@@ -611,6 +614,10 @@ type jsonDecDriver struct {
 // 	return jsonCharWhitespaceSet.isset(b)
 // }
 
+func (d *jsonDecDriver) decoder() *Decoder {
+	return &d.d
+}
+
 func (d *jsonDecDriver) uncacheRead() {
 	if d.tok != 0 {
 		d.d.decRd.unreadn1()
@@ -1462,17 +1469,25 @@ func (h *JsonHandle) typical() bool {
 // 	return
 // }
 
-func (h *JsonHandle) newEncDriver(e *Encoder) (ee encDriver) {
-	hd := jsonEncDriver{e: e, h: h}
-	hd.reset()
-	return &hd
-}
-
-func (h *JsonHandle) newDecDriver(d *Decoder) decDriver {
-	// d := jsonDecDriver{r: r.(*bytesDecReader), h: h}
-	hd := jsonDecDriver{d: d, h: h}
-	hd.reset()
-	return &hd
+func (h *JsonHandle) newEncDriver() encDriver {
+	var e = &jsonEncDriver{h: h}
+	e.e.e = e
+	e.e.jenc = e
+	e.e.js = true
+	e.e.init(h)
+	e.reset()
+	return e
+}
+
+func (h *JsonHandle) newDecDriver() decDriver {
+	var d = &jsonDecDriver{h: h}
+	d.d.d = d
+	d.d.jdec = d
+	d.d.js = true
+	d.d.jsms = h.MapKeyAsString
+	d.d.init(h)
+	d.reset()
+	return d
 }
 
 func (e *jsonEncDriver) reset() {

+ 137 - 126
codec/msgpack.go

@@ -200,15 +200,18 @@ type msgpackEncDriver struct {
 	noBuiltInTypes
 	encDriverNoopContainerWriter
 	// encNoSeparator
-	e *Encoder
-	w *encWr
 	h *MsgpackHandle
 	x [8]byte
 	// _ [3]uint64 // padding
+	e Encoder
+}
+
+func (e *msgpackEncDriver) encoder() *Encoder {
+	return &e.e
 }
 
 func (e *msgpackEncDriver) EncodeNil() {
-	e.w.writen1(mpNil)
+	e.e.encWr.writen1(mpNil)
 }
 
 func (e *msgpackEncDriver) EncodeInt(i int64) {
@@ -216,72 +219,72 @@ func (e *msgpackEncDriver) EncodeInt(i int64) {
 		e.EncodeUint(uint64(i))
 	} else if i > math.MaxInt8 {
 		if i <= math.MaxInt16 {
-			e.w.writen1(mpInt16)
-			bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+			e.e.encWr.writen1(mpInt16)
+			bigenHelper{e.x[:2], e.e.w()}.writeUint16(uint16(i))
 		} else if i <= math.MaxInt32 {
-			e.w.writen1(mpInt32)
-			bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+			e.e.encWr.writen1(mpInt32)
+			bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(i))
 		} else {
-			e.w.writen1(mpInt64)
-			bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+			e.e.encWr.writen1(mpInt64)
+			bigenHelper{e.x[:8], e.e.w()}.writeUint64(uint64(i))
 		}
 	} else if i >= -32 {
 		if e.h.NoFixedNum {
-			e.w.writen2(mpInt8, byte(i))
+			e.e.encWr.writen2(mpInt8, byte(i))
 		} else {
-			e.w.writen1(byte(i))
+			e.e.encWr.writen1(byte(i))
 		}
 	} else if i >= math.MinInt8 {
-		e.w.writen2(mpInt8, byte(i))
+		e.e.encWr.writen2(mpInt8, byte(i))
 	} else if i >= math.MinInt16 {
-		e.w.writen1(mpInt16)
-		bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+		e.e.encWr.writen1(mpInt16)
+		bigenHelper{e.x[:2], e.e.w()}.writeUint16(uint16(i))
 	} else if i >= math.MinInt32 {
-		e.w.writen1(mpInt32)
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+		e.e.encWr.writen1(mpInt32)
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(i))
 	} else {
-		e.w.writen1(mpInt64)
-		bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+		e.e.encWr.writen1(mpInt64)
+		bigenHelper{e.x[:8], e.e.w()}.writeUint64(uint64(i))
 	}
 }
 
 func (e *msgpackEncDriver) EncodeUint(i uint64) {
 	if i <= math.MaxInt8 {
 		if e.h.NoFixedNum {
-			e.w.writen2(mpUint8, byte(i))
+			e.e.encWr.writen2(mpUint8, byte(i))
 		} else {
-			e.w.writen1(byte(i))
+			e.e.encWr.writen1(byte(i))
 		}
 	} else if i <= math.MaxUint8 {
-		e.w.writen2(mpUint8, byte(i))
+		e.e.encWr.writen2(mpUint8, byte(i))
 	} else if i <= math.MaxUint16 {
-		e.w.writen1(mpUint16)
-		bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+		e.e.encWr.writen1(mpUint16)
+		bigenHelper{e.x[:2], e.e.w()}.writeUint16(uint16(i))
 	} else if i <= math.MaxUint32 {
-		e.w.writen1(mpUint32)
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+		e.e.encWr.writen1(mpUint32)
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(i))
 	} else {
-		e.w.writen1(mpUint64)
-		bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+		e.e.encWr.writen1(mpUint64)
+		bigenHelper{e.x[:8], e.e.w()}.writeUint64(uint64(i))
 	}
 }
 
 func (e *msgpackEncDriver) EncodeBool(b bool) {
 	if b {
-		e.w.writen1(mpTrue)
+		e.e.encWr.writen1(mpTrue)
 	} else {
-		e.w.writen1(mpFalse)
+		e.e.encWr.writen1(mpFalse)
 	}
 }
 
 func (e *msgpackEncDriver) EncodeFloat32(f float32) {
-	e.w.writen1(mpFloat)
-	bigenHelper{e.x[:4], e.w}.writeUint32(math.Float32bits(f))
+	e.e.encWr.writen1(mpFloat)
+	bigenHelper{e.x[:4], e.e.w()}.writeUint32(math.Float32bits(f))
 }
 
 func (e *msgpackEncDriver) EncodeFloat64(f float64) {
-	e.w.writen1(mpDouble)
-	bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
+	e.e.encWr.writen1(mpDouble)
+	bigenHelper{e.x[:8], e.e.w()}.writeUint64(math.Float64bits(f))
 }
 
 func (e *msgpackEncDriver) EncodeTime(t time.Time) {
@@ -308,12 +311,12 @@ func (e *msgpackEncDriver) EncodeTime(t time.Time) {
 	}
 	switch l {
 	case 4:
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(data64))
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(data64))
 	case 8:
-		bigenHelper{e.x[:8], e.w}.writeUint64(data64)
+		bigenHelper{e.x[:8], e.e.w()}.writeUint64(data64)
 	case 12:
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(nsec))
-		bigenHelper{e.x[:8], e.w}.writeUint64(uint64(sec))
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(nsec))
+		bigenHelper{e.x[:8], e.e.w()}.writeUint64(uint64(sec))
 	}
 }
 
@@ -332,7 +335,7 @@ func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
 	}
 	if e.h.WriteExt {
 		e.encodeExtPreamble(uint8(xtag), len(bs))
-		e.w.writeb(bs)
+		e.e.encWr.writeb(bs)
 	} else {
 		e.EncodeStringBytesRaw(bs)
 	}
@@ -343,31 +346,31 @@ func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
 
 func (e *msgpackEncDriver) EncodeRawExt(re *RawExt) {
 	e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
-	e.w.writeb(re.Data)
+	e.e.encWr.writeb(re.Data)
 }
 
 func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) {
 	if l == 1 {
-		e.w.writen2(mpFixExt1, xtag)
+		e.e.encWr.writen2(mpFixExt1, xtag)
 	} else if l == 2 {
-		e.w.writen2(mpFixExt2, xtag)
+		e.e.encWr.writen2(mpFixExt2, xtag)
 	} else if l == 4 {
-		e.w.writen2(mpFixExt4, xtag)
+		e.e.encWr.writen2(mpFixExt4, xtag)
 	} else if l == 8 {
-		e.w.writen2(mpFixExt8, xtag)
+		e.e.encWr.writen2(mpFixExt8, xtag)
 	} else if l == 16 {
-		e.w.writen2(mpFixExt16, xtag)
+		e.e.encWr.writen2(mpFixExt16, xtag)
 	} else if l < 256 {
-		e.w.writen2(mpExt8, byte(l))
-		e.w.writen1(xtag)
+		e.e.encWr.writen2(mpExt8, byte(l))
+		e.e.encWr.writen1(xtag)
 	} else if l < 65536 {
-		e.w.writen1(mpExt16)
-		bigenHelper{e.x[:2], e.w}.writeUint16(uint16(l))
-		e.w.writen1(xtag)
+		e.e.encWr.writen1(mpExt16)
+		bigenHelper{e.x[:2], e.e.w()}.writeUint16(uint16(l))
+		e.e.encWr.writen1(xtag)
 	} else {
-		e.w.writen1(mpExt32)
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(l))
-		e.w.writen1(xtag)
+		e.e.encWr.writen1(mpExt32)
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(l))
+		e.e.encWr.writen1(xtag)
 	}
 }
 
@@ -387,7 +390,7 @@ func (e *msgpackEncDriver) EncodeStringEnc(c charEncoding, s string) {
 		e.writeContainerLen(msgpackContainerRawLegacy, slen)
 	}
 	if slen > 0 {
-		e.w.writestr(s)
+		e.e.encWr.writestr(s)
 	}
 }
 
@@ -403,40 +406,42 @@ func (e *msgpackEncDriver) EncodeStringBytesRaw(bs []byte) {
 		e.writeContainerLen(msgpackContainerRawLegacy, slen)
 	}
 	if slen > 0 {
-		e.w.writeb(bs)
+		e.e.encWr.writeb(bs)
 	}
 }
 
 func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
 	if ct.fixCutoff > 0 && l < int(ct.fixCutoff) {
-		e.w.writen1(ct.bFixMin | byte(l))
+		e.e.encWr.writen1(ct.bFixMin | byte(l))
 	} else if ct.b8 > 0 && l < 256 {
-		e.w.writen2(ct.b8, uint8(l))
+		e.e.encWr.writen2(ct.b8, uint8(l))
 	} else if l < 65536 {
-		e.w.writen1(ct.b16)
-		bigenHelper{e.x[:2], e.w}.writeUint16(uint16(l))
+		e.e.encWr.writen1(ct.b16)
+		bigenHelper{e.x[:2], e.e.w()}.writeUint16(uint16(l))
 	} else {
-		e.w.writen1(ct.b32)
-		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(l))
+		e.e.encWr.writen1(ct.b32)
+		bigenHelper{e.x[:4], e.e.w()}.writeUint32(uint32(l))
 	}
 }
 
 //---------------------------------------------
 
 type msgpackDecDriver struct {
-	d *Decoder
-	r *decRd
+	decDriverNoopContainerReader
 	h *MsgpackHandle
 	// b      [scratchByteArrayLen]byte
 	bd     byte
 	bdRead bool
-	br     bool // bytes reader
 	fnil   bool
 	noBuiltInTypes
 	// noStreamingCodec
 	// decNoSeparator
-	decDriverNoopContainerReader
 	// _ [3]uint64 // padding
+	d Decoder
+}
+
+func (d *msgpackDecDriver) decoder() *Decoder {
+	return &d.d
 }
 
 // Note: This returns either a primitive (int, bool, etc) for non-containers,
@@ -467,36 +472,36 @@ func (d *msgpackDecDriver) DecodeNaked() {
 
 	case mpFloat:
 		n.v = valueTypeFloat
-		n.f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+		n.f = float64(math.Float32frombits(bigen.Uint32(d.d.decRd.readx(4))))
 	case mpDouble:
 		n.v = valueTypeFloat
-		n.f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+		n.f = math.Float64frombits(bigen.Uint64(d.d.decRd.readx(8)))
 
 	case mpUint8:
 		n.v = valueTypeUint
-		n.u = uint64(d.r.readn1())
+		n.u = uint64(d.d.decRd.readn1())
 	case mpUint16:
 		n.v = valueTypeUint
-		n.u = uint64(bigen.Uint16(d.r.readx(2)))
+		n.u = uint64(bigen.Uint16(d.d.decRd.readx(2)))
 	case mpUint32:
 		n.v = valueTypeUint
-		n.u = uint64(bigen.Uint32(d.r.readx(4)))
+		n.u = uint64(bigen.Uint32(d.d.decRd.readx(4)))
 	case mpUint64:
 		n.v = valueTypeUint
-		n.u = uint64(bigen.Uint64(d.r.readx(8)))
+		n.u = uint64(bigen.Uint64(d.d.decRd.readx(8)))
 
 	case mpInt8:
 		n.v = valueTypeInt
-		n.i = int64(int8(d.r.readn1()))
+		n.i = int64(int8(d.d.decRd.readn1()))
 	case mpInt16:
 		n.v = valueTypeInt
-		n.i = int64(int16(bigen.Uint16(d.r.readx(2))))
+		n.i = int64(int16(bigen.Uint16(d.d.decRd.readx(2))))
 	case mpInt32:
 		n.v = valueTypeInt
-		n.i = int64(int32(bigen.Uint32(d.r.readx(4))))
+		n.i = int64(int32(bigen.Uint32(d.d.decRd.readx(4))))
 	case mpInt64:
 		n.v = valueTypeInt
-		n.i = int64(int64(bigen.Uint64(d.r.readx(8))))
+		n.i = int64(int64(bigen.Uint64(d.d.decRd.readx(8))))
 
 	default:
 		switch {
@@ -517,7 +522,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
 				n.l = d.DecodeBytes(nil, false)
 			}
 		case bd == mpBin8, bd == mpBin16, bd == mpBin32:
-			decNakedReadRawBytes(d, d.d, n, d.h.RawToString)
+			decNakedReadRawBytes(d, &d.d, n, d.h.RawToString)
 		case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
 			n.v = valueTypeArray
 			decodeFurther = true
@@ -527,14 +532,14 @@ func (d *msgpackDecDriver) DecodeNaked() {
 		case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
 			n.v = valueTypeExt
 			clen := d.readExtLen()
-			n.u = uint64(d.r.readn1())
+			n.u = uint64(d.d.decRd.readn1())
 			if n.u == uint64(mpTimeExtTagU) {
 				n.v = valueTypeTime
 				n.t = d.decodeTime(clen)
-			} else if d.br {
-				n.l = d.r.readx(uint(clen))
+			} else if d.d.bytes {
+				n.l = d.d.decRd.readx(uint(clen))
 			} else {
-				n.l = decByteSlice(d.r, clen, d.d.h.MaxInitLen, d.d.b[:])
+				n.l = decByteSlice(d.d.r(), clen, d.d.h.MaxInitLen, d.d.b[:])
 			}
 		default:
 			d.d.errorf("cannot infer value: %s: Ox%x/%d/%s", msgBadDesc, bd, bd, mpdesc(bd))
@@ -556,21 +561,21 @@ func (d *msgpackDecDriver) DecodeInt64() (i int64) {
 	}
 	switch d.bd {
 	case mpUint8:
-		i = int64(uint64(d.r.readn1()))
+		i = int64(uint64(d.d.decRd.readn1()))
 	case mpUint16:
-		i = int64(uint64(bigen.Uint16(d.r.readx(2))))
+		i = int64(uint64(bigen.Uint16(d.d.decRd.readx(2))))
 	case mpUint32:
-		i = int64(uint64(bigen.Uint32(d.r.readx(4))))
+		i = int64(uint64(bigen.Uint32(d.d.decRd.readx(4))))
 	case mpUint64:
-		i = int64(bigen.Uint64(d.r.readx(8)))
+		i = int64(bigen.Uint64(d.d.decRd.readx(8)))
 	case mpInt8:
-		i = int64(int8(d.r.readn1()))
+		i = int64(int8(d.d.decRd.readn1()))
 	case mpInt16:
-		i = int64(int16(bigen.Uint16(d.r.readx(2))))
+		i = int64(int16(bigen.Uint16(d.d.decRd.readx(2))))
 	case mpInt32:
-		i = int64(int32(bigen.Uint32(d.r.readx(4))))
+		i = int64(int32(bigen.Uint32(d.d.decRd.readx(4))))
 	case mpInt64:
-		i = int64(bigen.Uint64(d.r.readx(8)))
+		i = int64(bigen.Uint64(d.d.decRd.readx(8)))
 	default:
 		switch {
 		case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
@@ -593,36 +598,36 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
 	}
 	switch d.bd {
 	case mpUint8:
-		ui = uint64(d.r.readn1())
+		ui = uint64(d.d.decRd.readn1())
 	case mpUint16:
-		ui = uint64(bigen.Uint16(d.r.readx(2)))
+		ui = uint64(bigen.Uint16(d.d.decRd.readx(2)))
 	case mpUint32:
-		ui = uint64(bigen.Uint32(d.r.readx(4)))
+		ui = uint64(bigen.Uint32(d.d.decRd.readx(4)))
 	case mpUint64:
-		ui = bigen.Uint64(d.r.readx(8))
+		ui = bigen.Uint64(d.d.decRd.readx(8))
 	case mpInt8:
-		if i := int64(int8(d.r.readn1())); i >= 0 {
+		if i := int64(int8(d.d.decRd.readn1())); i >= 0 {
 			ui = uint64(i)
 		} else {
 			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 		}
 	case mpInt16:
-		if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
+		if i := int64(int16(bigen.Uint16(d.d.decRd.readx(2)))); i >= 0 {
 			ui = uint64(i)
 		} else {
 			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 		}
 	case mpInt32:
-		if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
+		if i := int64(int32(bigen.Uint32(d.d.decRd.readx(4)))); i >= 0 {
 			ui = uint64(i)
 		} else {
 			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 		}
 	case mpInt64:
-		if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
+		if i := int64(bigen.Uint64(d.d.decRd.readx(8))); i >= 0 {
 			ui = uint64(i)
 		} else {
 			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
@@ -650,9 +655,9 @@ func (d *msgpackDecDriver) DecodeFloat64() (f float64) {
 		return
 	}
 	if d.bd == mpFloat {
-		f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+		f = float64(math.Float32frombits(bigen.Uint32(d.d.decRd.readx(4))))
 	} else if d.bd == mpDouble {
-		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+		f = math.Float64frombits(bigen.Uint64(d.d.decRd.readx(8)))
 	} else {
 		f = float64(d.DecodeInt64())
 	}
@@ -709,13 +714,13 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 
 	d.bdRead = false
 	if zerocopy {
-		if d.br {
-			return d.r.readx(uint(clen))
+		if d.d.bytes {
+			return d.d.decRd.readx(uint(clen))
 		} else if len(bs) == 0 {
 			bs = d.d.b[:]
 		}
 	}
-	return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
+	return decByteSlice(d.d.r(), clen, d.h.MaxInitLen, bs)
 }
 
 func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
@@ -723,13 +728,13 @@ func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
 }
 
 func (d *msgpackDecDriver) readNextBd() {
-	d.bd = d.r.readn1()
+	d.bd = d.d.decRd.readn1()
 	d.bdRead = true
 }
 
 func (d *msgpackDecDriver) uncacheRead() {
 	if d.bdRead {
-		d.r.unreadn1()
+		d.d.decRd.unreadn1()
 		d.bdRead = false
 	}
 }
@@ -787,11 +792,11 @@ func (d *msgpackDecDriver) TryNil() (v bool) {
 func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int) {
 	bd := d.bd
 	if bd == ct.b8 {
-		clen = int(d.r.readn1())
+		clen = int(d.d.decRd.readn1())
 	} else if bd == ct.b16 {
-		clen = int(bigen.Uint16(d.r.readx(2)))
+		clen = int(bigen.Uint16(d.d.decRd.readx(2)))
 	} else if bd == ct.b32 {
-		clen = int(bigen.Uint32(d.r.readx(4)))
+		clen = int(bigen.Uint32(d.d.decRd.readx(4)))
 	} else if (ct.bFixMin & bd) == ct.bFixMin {
 		clen = int(ct.bFixMin ^ bd)
 	} else {
@@ -829,11 +834,11 @@ func (d *msgpackDecDriver) readExtLen() (clen int) {
 	case mpFixExt16:
 		clen = 16
 	case mpExt8:
-		clen = int(d.r.readn1())
+		clen = int(d.d.decRd.readn1())
 	case mpExt16:
-		clen = int(bigen.Uint16(d.r.readx(2)))
+		clen = int(bigen.Uint16(d.d.decRd.readx(2)))
 	case mpExt32:
-		clen = int(bigen.Uint32(d.r.readx(4)))
+		clen = int(bigen.Uint32(d.d.decRd.readx(4)))
 	default:
 		d.d.errorf("decoding ext bytes: found unexpected byte: %x", d.bd)
 		return
@@ -856,12 +861,12 @@ func (d *msgpackDecDriver) DecodeTime() (t time.Time) {
 	} else {
 		// expect to see mpFixExt4,-1 OR mpFixExt8,-1 OR mpExt8,12,-1
 		d.bdRead = false
-		b2 := d.r.readn1()
+		b2 := d.d.decRd.readn1()
 		if d.bd == mpFixExt4 && b2 == mpTimeExtTagU {
 			clen = 4
 		} else if d.bd == mpFixExt8 && b2 == mpTimeExtTagU {
 			clen = 8
-		} else if d.bd == mpExt8 && b2 == 12 && d.r.readn1() == mpTimeExtTagU {
+		} else if d.bd == mpExt8 && b2 == 12 && d.d.decRd.readn1() == mpTimeExtTagU {
 			clen = 12
 		} else {
 			d.d.errorf("invalid stream for decoding time as extension: got 0x%x, 0x%x", d.bd, b2)
@@ -872,17 +877,17 @@ func (d *msgpackDecDriver) DecodeTime() (t time.Time) {
 }
 
 func (d *msgpackDecDriver) decodeTime(clen int) (t time.Time) {
-	// bs = d.r.readx(clen)
+	// bs = d.d.decRd.readx(clen)
 	d.bdRead = false
 	switch clen {
 	case 4:
-		t = time.Unix(int64(bigen.Uint32(d.r.readx(4))), 0).UTC()
+		t = time.Unix(int64(bigen.Uint32(d.d.decRd.readx(4))), 0).UTC()
 	case 8:
-		tv := bigen.Uint64(d.r.readx(8))
+		tv := bigen.Uint64(d.d.decRd.readx(8))
 		t = time.Unix(int64(tv&0x00000003ffffffff), int64(tv>>34)).UTC()
 	case 12:
-		nsec := bigen.Uint32(d.r.readx(4))
-		sec := bigen.Uint64(d.r.readx(8))
+		nsec := bigen.Uint32(d.d.decRd.readx(4))
+		sec := bigen.Uint64(d.d.decRd.readx(8))
 		t = time.Unix(int64(sec), int64(nsec)).UTC()
 	default:
 		d.d.errorf("invalid length of bytes for decoding time - expecting 4 or 8 or 12, got %d", clen)
@@ -904,7 +909,7 @@ func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
 	if ext == nil {
 		re := rv.(*RawExt)
 		re.Tag = realxtag
-		re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
+		re.Data = detachZeroCopyBytes(d.d.bytes, re.Data, xbs)
 	} else if ext == SelfExt {
 		d.d.sideDecode(rv, xbs)
 	} else {
@@ -921,15 +926,15 @@ func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs
 		xbs = d.DecodeStringAsBytes()
 	} else {
 		clen := d.readExtLen()
-		xtag = d.r.readn1()
+		xtag = d.d.decRd.readn1()
 		if verifyTag && xtag != tag {
 			d.d.errorf("wrong extension tag - got %b, expecting %v", xtag, tag)
 			return
 		}
-		if d.br {
-			xbs = d.r.readx(uint(clen))
+		if d.d.bytes {
+			xbs = d.d.decRd.readx(uint(clen))
 		} else {
-			xbs = decByteSlice(d.r, clen, d.d.h.MaxInitLen, d.d.b[:])
+			xbs = decByteSlice(d.d.r(), clen, d.d.h.MaxInitLen, d.d.b[:])
 		}
 	}
 	d.bdRead = false
@@ -970,20 +975,26 @@ type MsgpackHandle struct {
 // Name returns the name of the handle: msgpack
 func (h *MsgpackHandle) Name() string { return "msgpack" }
 
-func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
-	return &msgpackEncDriver{e: e, w: e.w(), h: h}
+func (h *MsgpackHandle) newEncDriver() encDriver {
+	var e = &msgpackEncDriver{h: h}
+	e.e.e = e
+	e.e.init(h)
+	e.reset()
+	return e
 }
 
-func (h *MsgpackHandle) newDecDriver(d *Decoder) decDriver {
-	return &msgpackDecDriver{d: d, h: h, r: d.r(), br: d.bytes}
+func (h *MsgpackHandle) newDecDriver() decDriver {
+	d := &msgpackDecDriver{h: h}
+	d.d.d = d
+	d.d.init(h)
+	d.reset()
+	return d
 }
 
 func (e *msgpackEncDriver) reset() {
-	e.w = e.e.w()
 }
 
 func (d *msgpackDecDriver) reset() {
-	d.r, d.br = d.d.r(), d.d.bytes
 	d.bd, d.bdRead = 0, false
 	d.fnil = false
 }

+ 83 - 72
codec/simple.go

@@ -34,17 +34,20 @@ type simpleEncDriver struct {
 	noBuiltInTypes
 	encDriverNoopContainerWriter
 	// encNoSeparator
-	e *Encoder
 	h *SimpleHandle
-	w *encWr
 	b [8]byte
 	// c containerState
 	// encDriverTrackContainerWriter
 	// _ [2]uint64 // padding (cache-aligned)
+	e Encoder
+}
+
+func (e *simpleEncDriver) encoder() *Encoder {
+	return &e.e
 }
 
 func (e *simpleEncDriver) EncodeNil() {
-	e.w.writen1(simpleVdNil)
+	e.e.encWr.writen1(simpleVdNil)
 }
 
 func (e *simpleEncDriver) EncodeBool(b bool) {
@@ -53,9 +56,9 @@ func (e *simpleEncDriver) EncodeBool(b bool) {
 		return
 	}
 	if b {
-		e.w.writen1(simpleVdTrue)
+		e.e.encWr.writen1(simpleVdTrue)
 	} else {
-		e.w.writen1(simpleVdFalse)
+		e.e.encWr.writen1(simpleVdFalse)
 	}
 }
 
@@ -64,8 +67,8 @@ func (e *simpleEncDriver) EncodeFloat32(f float32) {
 		e.EncodeNil()
 		return
 	}
-	e.w.writen1(simpleVdFloat32)
-	bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
+	e.e.encWr.writen1(simpleVdFloat32)
+	bigenHelper{e.b[:4], e.e.w()}.writeUint32(math.Float32bits(f))
 }
 
 func (e *simpleEncDriver) EncodeFloat64(f float64) {
@@ -73,8 +76,8 @@ func (e *simpleEncDriver) EncodeFloat64(f float64) {
 		e.EncodeNil()
 		return
 	}
-	e.w.writen1(simpleVdFloat64)
-	bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
+	e.e.encWr.writen1(simpleVdFloat64)
+	bigenHelper{e.b[:8], e.e.w()}.writeUint64(math.Float64bits(f))
 }
 
 func (e *simpleEncDriver) EncodeInt(v int64) {
@@ -95,34 +98,34 @@ func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
 		return
 	}
 	if v <= math.MaxUint8 {
-		e.w.writen2(bd, uint8(v))
+		e.e.encWr.writen2(bd, uint8(v))
 	} else if v <= math.MaxUint16 {
-		e.w.writen1(bd + 1)
-		bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v))
+		e.e.encWr.writen1(bd + 1)
+		bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(v))
 	} else if v <= math.MaxUint32 {
-		e.w.writen1(bd + 2)
-		bigenHelper{e.b[:4], e.w}.writeUint32(uint32(v))
+		e.e.encWr.writen1(bd + 2)
+		bigenHelper{e.b[:4], e.e.w()}.writeUint32(uint32(v))
 	} else { // if v <= math.MaxUint64 {
-		e.w.writen1(bd + 3)
-		bigenHelper{e.b[:8], e.w}.writeUint64(v)
+		e.e.encWr.writen1(bd + 3)
+		bigenHelper{e.b[:8], e.e.w()}.writeUint64(v)
 	}
 }
 
 func (e *simpleEncDriver) encLen(bd byte, length int) {
 	if length == 0 {
-		e.w.writen1(bd)
+		e.e.encWr.writen1(bd)
 	} else if length <= math.MaxUint8 {
-		e.w.writen1(bd + 1)
-		e.w.writen1(uint8(length))
+		e.e.encWr.writen1(bd + 1)
+		e.e.encWr.writen1(uint8(length))
 	} else if length <= math.MaxUint16 {
-		e.w.writen1(bd + 2)
-		bigenHelper{e.b[:2], e.w}.writeUint16(uint16(length))
+		e.e.encWr.writen1(bd + 2)
+		bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(length))
 	} else if int64(length) <= math.MaxUint32 {
-		e.w.writen1(bd + 3)
-		bigenHelper{e.b[:4], e.w}.writeUint32(uint32(length))
+		e.e.encWr.writen1(bd + 3)
+		bigenHelper{e.b[:4], e.e.w()}.writeUint32(uint32(length))
 	} else {
-		e.w.writen1(bd + 4)
-		bigenHelper{e.b[:8], e.w}.writeUint64(uint64(length))
+		e.e.encWr.writen1(bd + 4)
+		bigenHelper{e.b[:8], e.e.w()}.writeUint64(uint64(length))
 	}
 }
 
@@ -139,7 +142,7 @@ func (e *simpleEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
 		return
 	}
 	e.encodeExtPreamble(uint8(xtag), len(bs))
-	e.w.writeb(bs)
+	e.e.encWr.writeb(bs)
 	if ext == SelfExt {
 		e.e.blist.put(bs)
 	}
@@ -147,12 +150,12 @@ func (e *simpleEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
 
 func (e *simpleEncDriver) EncodeRawExt(re *RawExt) {
 	e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
-	e.w.writeb(re.Data)
+	e.e.encWr.writeb(re.Data)
 }
 
 func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
 	e.encLen(simpleVdExt, length)
-	e.w.writen1(xtag)
+	e.e.encWr.writen1(xtag)
 }
 
 func (e *simpleEncDriver) WriteArrayStart(length int) {
@@ -173,7 +176,7 @@ func (e *simpleEncDriver) EncodeStringEnc(c charEncoding, v string) {
 		return
 	}
 	e.encLen(simpleVdString, len(v))
-	e.w.writestr(v)
+	e.e.encWr.writestr(v)
 }
 
 func (e *simpleEncDriver) EncodeStringBytesRaw(v []byte) {
@@ -183,7 +186,7 @@ func (e *simpleEncDriver) EncodeStringBytesRaw(v []byte) {
 		return
 	}
 	e.encLen(simpleVdByteArray, len(v))
-	e.w.writeb(v)
+	e.e.encWr.writeb(v)
 }
 
 func (e *simpleEncDriver) EncodeTime(t time.Time) {
@@ -198,19 +201,16 @@ func (e *simpleEncDriver) EncodeTime(t time.Time) {
 		return
 	}
 	// time.Time marshalbinary takes about 14 bytes.
-	e.w.writen2(simpleVdTime, uint8(len(v)))
-	e.w.writeb(v)
+	e.e.encWr.writen2(simpleVdTime, uint8(len(v)))
+	e.e.encWr.writeb(v)
 }
 
 //------------------------------------
 
 type simpleDecDriver struct {
-	d      *Decoder
 	h      *SimpleHandle
-	r      *decRd
 	bdRead bool
 	bd     byte
-	br     bool // a bytes reader?
 	fnil   bool
 	// c      containerState
 	// b      [scratchByteArrayLen]byte
@@ -218,16 +218,21 @@ type simpleDecDriver struct {
 	// noStreamingCodec
 	decDriverNoopContainerReader
 	// _ [3]uint64 // padding
+	d Decoder
+}
+
+func (d *simpleDecDriver) decoder() *Decoder {
+	return &d.d
 }
 
 func (d *simpleDecDriver) readNextBd() {
-	d.bd = d.r.readn1()
+	d.bd = d.d.decRd.readn1()
 	d.bdRead = true
 }
 
 func (d *simpleDecDriver) uncacheRead() {
 	if d.bdRead {
-		d.r.unreadn1()
+		d.d.decRd.unreadn1()
 		d.bdRead = false
 	}
 }
@@ -287,24 +292,24 @@ func (d *simpleDecDriver) TryNil() bool {
 func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
 	switch d.bd {
 	case simpleVdPosInt:
-		ui = uint64(d.r.readn1())
+		ui = uint64(d.d.decRd.readn1())
 	case simpleVdPosInt + 1:
-		ui = uint64(bigen.Uint16(d.r.readx(2)))
+		ui = uint64(bigen.Uint16(d.d.decRd.readx(2)))
 	case simpleVdPosInt + 2:
-		ui = uint64(bigen.Uint32(d.r.readx(4)))
+		ui = uint64(bigen.Uint32(d.d.decRd.readx(4)))
 	case simpleVdPosInt + 3:
-		ui = uint64(bigen.Uint64(d.r.readx(8)))
+		ui = uint64(bigen.Uint64(d.d.decRd.readx(8)))
 	case simpleVdNegInt:
-		ui = uint64(d.r.readn1())
+		ui = uint64(d.d.decRd.readn1())
 		neg = true
 	case simpleVdNegInt + 1:
-		ui = uint64(bigen.Uint16(d.r.readx(2)))
+		ui = uint64(bigen.Uint16(d.d.decRd.readx(2)))
 		neg = true
 	case simpleVdNegInt + 2:
-		ui = uint64(bigen.Uint32(d.r.readx(4)))
+		ui = uint64(bigen.Uint32(d.d.decRd.readx(4)))
 		neg = true
 	case simpleVdNegInt + 3:
-		ui = uint64(bigen.Uint64(d.r.readx(8)))
+		ui = uint64(bigen.Uint64(d.d.decRd.readx(8)))
 		neg = true
 	default:
 		d.d.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
@@ -349,9 +354,9 @@ func (d *simpleDecDriver) DecodeFloat64() (f float64) {
 		return
 	}
 	if d.bd == simpleVdFloat32 {
-		f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+		f = float64(math.Float32frombits(bigen.Uint32(d.d.decRd.readx(4))))
 	} else if d.bd == simpleVdFloat64 {
-		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+		f = math.Float64frombits(bigen.Uint64(d.d.decRd.readx(8)))
 	} else {
 		if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
 			f = float64(d.DecodeInt64())
@@ -401,18 +406,18 @@ func (d *simpleDecDriver) decLen() int {
 	case 0:
 		return 0
 	case 1:
-		return int(d.r.readn1())
+		return int(d.d.decRd.readn1())
 	case 2:
-		return int(bigen.Uint16(d.r.readx(2)))
+		return int(bigen.Uint16(d.d.decRd.readx(2)))
 	case 3:
-		ui := uint64(bigen.Uint32(d.r.readx(4)))
+		ui := uint64(bigen.Uint32(d.d.decRd.readx(4)))
 		if chkOvf.Uint(ui, intBitsize) {
 			d.d.errorf("overflow integer: %v", ui)
 			return 0
 		}
 		return int(ui)
 	case 4:
-		ui := bigen.Uint64(d.r.readx(8))
+		ui := bigen.Uint64(d.d.decRd.readx(8))
 		if chkOvf.Uint(ui, intBitsize) {
 			d.d.errorf("overflow integer: %v", ui)
 			return 0
@@ -448,13 +453,13 @@ func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 	clen := d.decLen()
 	d.bdRead = false
 	if zerocopy {
-		if d.br {
-			return d.r.readx(uint(clen))
+		if d.d.bytes {
+			return d.d.decRd.readx(uint(clen))
 		} else if len(bs) == 0 {
 			bs = d.d.b[:]
 		}
 	}
-	return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
+	return decByteSlice(d.d.r(), clen, d.d.h.MaxInitLen, bs)
 }
 
 func (d *simpleDecDriver) DecodeTime() (t time.Time) {
@@ -466,8 +471,8 @@ func (d *simpleDecDriver) DecodeTime() (t time.Time) {
 		return
 	}
 	d.bdRead = false
-	clen := int(d.r.readn1())
-	b := d.r.readx(uint(clen))
+	clen := int(d.d.decRd.readn1())
+	b := d.d.decRd.readx(uint(clen))
 	if err := (&t).UnmarshalBinary(b); err != nil {
 		d.d.errorv(err)
 	}
@@ -487,7 +492,7 @@ func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
 	if ext == nil {
 		re := rv.(*RawExt)
 		re.Tag = realxtag
-		re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
+		re.Data = detachZeroCopyBytes(d.d.bytes, re.Data, xbs)
 	} else if ext == SelfExt {
 		d.d.sideDecode(rv, xbs)
 	} else {
@@ -499,15 +504,15 @@ func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs [
 	switch d.bd {
 	case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
 		l := d.decLen()
-		xtag = d.r.readn1()
+		xtag = d.d.decRd.readn1()
 		if verifyTag && xtag != tag {
 			d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
 			return
 		}
-		if d.br {
-			xbs = d.r.readx(uint(l))
+		if d.d.bytes {
+			xbs = d.d.decRd.readx(uint(l))
 		} else {
-			xbs = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
+			xbs = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
 		}
 	case simpleVdByteArray, simpleVdByteArray + 1,
 		simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
@@ -565,15 +570,15 @@ func (d *simpleDecDriver) DecodeNaked() {
 		n.s = string(d.DecodeStringAsBytes())
 	case simpleVdByteArray, simpleVdByteArray + 1,
 		simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
-		decNakedReadRawBytes(d, d.d, n, d.h.RawToString)
+		decNakedReadRawBytes(d, &d.d, n, d.h.RawToString)
 	case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
 		n.v = valueTypeExt
 		l := d.decLen()
-		n.u = uint64(d.r.readn1())
-		if d.br {
-			n.l = d.r.readx(uint(l))
+		n.u = uint64(d.d.decRd.readn1())
+		if d.d.bytes {
+			n.l = d.d.decRd.readx(uint(l))
 		} else {
-			n.l = decByteSlice(d.r, l, d.d.h.MaxInitLen, d.d.b[:])
+			n.l = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
 		}
 	case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
 		simpleVdArray + 3, simpleVdArray + 4:
@@ -627,20 +632,26 @@ func (h *SimpleHandle) Name() string { return "simple" }
 
 // func (h *SimpleHandle) hasElemSeparators() bool { return true } // as it implements Write(Map|Array)XXX
 
-func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
-	return &simpleEncDriver{e: e, w: e.w(), h: h}
+func (h *SimpleHandle) newEncDriver() encDriver {
+	var e = &simpleEncDriver{h: h}
+	e.e.e = e
+	e.e.init(h)
+	e.reset()
+	return e
 }
 
-func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
-	return &simpleDecDriver{d: d, h: h, r: d.r(), br: d.bytes}
+func (h *SimpleHandle) newDecDriver() decDriver {
+	d := &simpleDecDriver{h: h}
+	d.d.d = d
+	d.d.init(h)
+	d.reset()
+	return d
 }
 
 func (e *simpleEncDriver) reset() {
-	e.w = e.e.w()
 }
 
 func (d *simpleDecDriver) reset() {
-	d.r, d.br = d.d.r(), d.d.bytes
 	d.bd, d.bdRead = 0, false
 	d.fnil = false
 }