Browse Source

Merge pull request #9494 from gyuho/ugorji/go

client: regenerate with latest "ugorji/go/codec"
Gyuho Lee 7 years ago
parent
commit
fe26434a89
36 changed files with 3950 additions and 4862 deletions
  1. 1 0
      CHANGELOG-3.4.md
  2. 2 1
      Gopkg.lock
  3. 159 305
      client/keys.generated.go
  4. 86 7
      vendor/github.com/ugorji/go/codec/0doc.go
  5. 319 97
      vendor/github.com/ugorji/go/codec/binc.go
  6. 204 79
      vendor/github.com/ugorji/go/codec/cbor.go
  7. 239 278
      vendor/github.com/ugorji/go/codec/decode.go
  8. 264 438
      vendor/github.com/ugorji/go/codec/encode.go
  9. 65 1716
      vendor/github.com/ugorji/go/codec/fast-path.generated.go
  10. 17 5
      vendor/github.com/ugorji/go/codec/fast-path.not.go
  11. 134 49
      vendor/github.com/ugorji/go/codec/gen-helper.generated.go
  12. 43 11
      vendor/github.com/ugorji/go/codec/gen.generated.go
  13. 407 278
      vendor/github.com/ugorji/go/codec/gen.go
  14. 1 1
      vendor/github.com/ugorji/go/codec/goversion_arrayof_gte_go15.go
  15. 1 1
      vendor/github.com/ugorji/go/codec/goversion_arrayof_lt_go15.go
  16. 1 1
      vendor/github.com/ugorji/go/codec/goversion_makemap_gte_go19.go
  17. 1 1
      vendor/github.com/ugorji/go/codec/goversion_makemap_lt_go19.go
  18. 8 0
      vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go
  19. 8 0
      vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go
  20. 1 1
      vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go
  21. 1 1
      vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go15.go
  22. 1 1
      vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go16.go
  23. 1 1
      vendor/github.com/ugorji/go/codec/goversion_vendor_gte_go17.go
  24. 1 1
      vendor/github.com/ugorji/go/codec/goversion_vendor_lt_go15.go
  25. 407 333
      vendor/github.com/ugorji/go/codec/helper.go
  26. 9 109
      vendor/github.com/ugorji/go/codec/helper_internal.go
  27. 155 39
      vendor/github.com/ugorji/go/codec/helper_not_unsafe.go
  28. 280 59
      vendor/github.com/ugorji/go/codec/helper_unsafe.go
  29. 435 324
      vendor/github.com/ugorji/go/codec/json.go
  30. 298 105
      vendor/github.com/ugorji/go/codec/msgpack.go
  31. 0 214
      vendor/github.com/ugorji/go/codec/noop.go
  32. 119 74
      vendor/github.com/ugorji/go/codec/rpc.go
  33. 175 64
      vendor/github.com/ugorji/go/codec/simple.go
  34. 0 220
      vendor/github.com/ugorji/go/codec/time.go
  35. 107 25
      vendor/github.com/ugorji/go/codec/xml.go
  36. 0 23
      vendor/github.com/ugorji/go/codec/z.go

+ 1 - 0
CHANGELOG-3.4.md

@@ -70,6 +70,7 @@ See [code changes](https://github.com/coreos/etcd/compare/v3.3.0...v3.4.0) and [
 ### Dependency
 ### Dependency
 
 
 - TODO: Upgrade [`google.golang.org/grpc`](https://github.com/grpc/grpc-go/releases) from [**`v1.7.5`**](https://github.com/grpc/grpc-go/releases/tag/v1.7.5) to [**`v1.11.1`**](https://github.com/grpc/grpc-go/releases/tag/v1.11.1).
 - TODO: Upgrade [`google.golang.org/grpc`](https://github.com/grpc/grpc-go/releases) from [**`v1.7.5`**](https://github.com/grpc/grpc-go/releases/tag/v1.7.5) to [**`v1.11.1`**](https://github.com/grpc/grpc-go/releases/tag/v1.11.1).
+- Upgrade [`github.com/ugorji/go/codec`](https://github.com/ugorji/go) to [**`v1.1.1`**](https://github.com/ugorji/go/releases/tag/v1.1.1), and [regenerate v2 `client`](https://github.com/coreos/etcd/pull/9494).
 - Upgrade [`github.com/soheilhy/cmux`](https://github.com/soheilhy/cmux/releases) from [**`v0.1.3`**](https://github.com/soheilhy/cmux/releases/tag/v0.1.3) to [**`v0.1.4`**](https://github.com/soheilhy/cmux/releases/tag/v0.1.4).
 - Upgrade [`github.com/soheilhy/cmux`](https://github.com/soheilhy/cmux/releases) from [**`v0.1.3`**](https://github.com/soheilhy/cmux/releases/tag/v0.1.3) to [**`v0.1.4`**](https://github.com/soheilhy/cmux/releases/tag/v0.1.4).
 
 
 ### Metrics, Monitoring
 ### Metrics, Monitoring

+ 2 - 1
Gopkg.lock

@@ -225,7 +225,8 @@
 [[projects]]
 [[projects]]
   name = "github.com/ugorji/go"
   name = "github.com/ugorji/go"
   packages = ["codec"]
   packages = ["codec"]
-  revision = "bdcc60b419d136a85cdf2e7cbcac34b3f1cd6e57"
+  revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab"
+  version = "v1.1.1"
 
 
 [[projects]]
 [[projects]]
   name = "github.com/urfave/cli"
   name = "github.com/urfave/cli"

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


+ 86 - 7
vendor/github.com/ugorji/go/codec/0doc.go

@@ -1,9 +1,10 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 /*
 /*
-High Performance, Feature-Rich Idiomatic Go 1.4+ codec/encoding library for
-binc, msgpack, cbor, json
+Package codec provides a
+High Performance, Feature-Rich Idiomatic Go 1.4+ codec/encoding library
+for binc, msgpack, cbor, json.
 
 
 Supported Serialization formats are:
 Supported Serialization formats are:
 
 
@@ -32,15 +33,14 @@ 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
   - Support for go1.4 and above, while selectively using newer APIs for later releases
-  - Good code coverage ( > 70% )
+  - Excellent code coverage ( > 90% )
   - 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.
   - Careful selected use of 'unsafe' for targeted performance gains.
     100% mode exists where 'unsafe' is not used at all.
     100% mode exists where 'unsafe' is not used at all.
   - Lock-free (sans mutex) concurrency for scaling to 100's of cores
   - Lock-free (sans mutex) concurrency for scaling to 100's of cores
-  - Multiple conversions:
-    Package coerces types where appropriate
-    e.g. decode an int in the stream into a float, etc.
+  - Coerce types where appropriate
+    e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
   - Corner Cases:
   - Corner Cases:
     Overflows, nil maps/slices, nil values in streams are handled correctly
     Overflows, nil maps/slices, nil values in streams are handled correctly
   - Standard field renaming via tags
   - Standard field renaming via tags
@@ -49,10 +49,16 @@ Rich Feature Set includes:
     (struct, slice, map, primitives, pointers, interface{}, etc)
     (struct, slice, map, primitives, pointers, interface{}, etc)
   - Extensions to support efficient encoding/decoding of any named types
   - Extensions to support efficient encoding/decoding of any named types
   - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
   - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
+  - Support IsZero() bool to determine if a value is a zero value.
+    Analogous to time.Time.IsZero() bool.
   - Decoding without a schema (into a interface{}).
   - Decoding without a schema (into a interface{}).
     Includes Options to configure what specific map or slice type to use
     Includes Options to configure what specific map or slice type to use
     when decoding an encoded list or map into a nil interface{}
     when decoding an encoded list or map into a nil interface{}
+  - Mapping a non-interface type to an interface, so we can decode appropriately
+    into any interface type with a correctly configured non-interface value.
   - Encode a struct as an array, and decode struct from an array in the data stream
   - Encode a struct as an array, and decode struct from an array in the data stream
+  - Option to encode struct keys as numbers (instead of strings)
+    (to support structured streams with fields encoded as numeric codes)
   - Comprehensive support for anonymous fields
   - Comprehensive support for anonymous fields
   - Fast (no-reflection) encoding/decoding of common maps and slices
   - Fast (no-reflection) encoding/decoding of common maps and slices
   - Code-generation for faster performance.
   - Code-generation for faster performance.
@@ -93,6 +99,27 @@ encoded as an empty map because it has no exported fields, while UUID
 would be encoded as a string. However, with extension support, you can
 would be encoded as a string. However, with extension support, you can
 encode any of these however you like.
 encode any of these however you like.
 
 
+Custom Encoding and Decoding
+
+This package maintains symmetry in the encoding and decoding halfs.
+We determine how to encode or decode by walking this decision tree
+
+  - is type a codec.Selfer?
+  - is there an extension registered for the type?
+  - is format binary, and is type a encoding.BinaryMarshaler and BinaryUnmarshaler?
+  - is format specifically json, and is type a encoding/json.Marshaler and Unmarshaler?
+  - is format text-based, and type an encoding.TextMarshaler?
+  - else we use a pair of functions based on the "kind" of the type e.g. map, slice, int64, etc
+
+This symmetry is important to reduce chances of issues happening because the
+encoding and decoding sides are out of sync e.g. decoded via very specific
+encoding.TextUnmarshaler but encoded via kind-specific generalized mode.
+
+Consequently, if a type only defines one-half of the symmetry
+(e.g. it implements UnmarshalJSON() but not MarshalJSON() ),
+then that type doesn't satisfy the check and we will continue walking down the
+decision tree.
+
 RPC
 RPC
 
 
 RPC Client and Server Codecs are implemented, so the codecs can be used
 RPC Client and Server Codecs are implemented, so the codecs can be used
@@ -180,6 +207,58 @@ Running Benchmarks
 
 
 Please see http://github.com/ugorji/go-codec-bench .
 Please see http://github.com/ugorji/go-codec-bench .
 
 
+Caveats
+
+Struct fields matching the following are ignored during encoding and decoding
+    - struct tag value set to -
+    - func, complex numbers, unsafe pointers
+    - unexported and not embedded
+    - unexported and embedded and not struct kind
+    - unexported and embedded pointers (from go1.10)
+
+Every other field in a struct will be encoded/decoded.
+
+Embedded fields are encoded as if they exist in the top-level struct,
+with some caveats. See Encode documentation.
+
 */
 */
 package codec
 package codec
 
 
+// TODO:
+//   - For Go 1.11, when mid-stack inlining is enabled,
+//     we should use committed functions for writeXXX and readXXX calls.
+//     This involves uncommenting the methods for decReaderSwitch and encWriterSwitch
+//     and using those (decReaderSwitch and encWriterSwitch) in all handles
+//     instead of encWriter and decReader.
+//     The benefit is that, for the (En|De)coder over []byte, the encWriter/decReader
+//     will be inlined, giving a performance bump for that typical case.
+//     However, it will only  be inlined if mid-stack inlining is enabled,
+//     as we call panic to raise errors, and panic currently prevents inlining.
+//
+// PUNTED:
+//   - To make Handle comparable, make extHandle in BasicHandle a non-embedded pointer,
+//     and use overlay methods on *BasicHandle to call through to extHandle after initializing
+//     the "xh *extHandle" to point to a real slice.
+//
+// BEFORE EACH RELEASE:
+//   - Look through and fix padding for each type, to eliminate false sharing
+//     - critical shared objects that are read many times
+//       TypeInfos
+//     - pooled objects:
+//       decNaked, decNakedContainers, codecFner, typeInfoLoadArray, 
+//     - small objects allocated independently, that we read/use much across threads:
+//       codecFn, typeInfo
+//     - Objects allocated independently and used a lot
+//       Decoder, Encoder,
+//       xxxHandle, xxxEncDriver, xxxDecDriver (xxx = json, msgpack, cbor, binc, simple)
+//     - In all above, arrange values modified together to be close to each other.
+//
+//     For all of these, either ensure that they occupy full cache lines,
+//     or ensure that the things just past the cache line boundary are hardly read/written
+//     e.g. JsonHandle.RawBytesExt - which is copied into json(En|De)cDriver at init
+//
+//     Occupying full cache lines means they occupy 8*N words (where N is an integer).
+//     Check this out by running: ./run.sh -z
+//     - look at those tagged ****, meaning they are not occupying full cache lines
+//     - look at those tagged <<<<, meaning they are larger than 32 words (something to watch)
+//   - Run "golint -min_confidence 0.81"

+ 319 - 97
vendor/github.com/ugorji/go/codec/binc.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 package codec
 package codec
@@ -55,40 +55,77 @@ const (
 	// others not currently supported
 	// others not currently supported
 )
 )
 
 
+func bincdesc(vd, vs byte) string {
+	switch vd {
+	case bincVdSpecial:
+		switch vs {
+		case bincSpNil:
+			return "nil"
+		case bincSpFalse:
+			return "false"
+		case bincSpTrue:
+			return "true"
+		case bincSpNan, bincSpPosInf, bincSpNegInf, bincSpZeroFloat:
+			return "float"
+		case bincSpZero:
+			return "uint"
+		case bincSpNegOne:
+			return "int"
+		default:
+			return "unknown"
+		}
+	case bincVdSmallInt, bincVdPosInt:
+		return "uint"
+	case bincVdNegInt:
+		return "int"
+	case bincVdFloat:
+		return "float"
+	case bincVdSymbol:
+		return "string"
+	case bincVdString:
+		return "string"
+	case bincVdByteArray:
+		return "bytes"
+	case bincVdTimestamp:
+		return "time"
+	case bincVdCustomExt:
+		return "ext"
+	case bincVdArray:
+		return "array"
+	case bincVdMap:
+		return "map"
+	default:
+		return "unknown"
+	}
+}
+
 type bincEncDriver struct {
 type bincEncDriver struct {
 	e *Encoder
 	e *Encoder
+	h *BincHandle
 	w encWriter
 	w encWriter
 	m map[string]uint16 // symbols
 	m map[string]uint16 // symbols
-	b [scratchByteArrayLen]byte
-	s uint16 // symbols sequencer
+	b [16]byte          // scratch, used for encoding numbers - bigendian style
+	s uint16            // symbols sequencer
+	// c containerState
+	encDriverTrackContainerWriter
+	noBuiltInTypes
 	// encNoSeparator
 	// encNoSeparator
-	encDriverNoopContainerWriter
 }
 }
 
 
-func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
-	return rt == timeTypId
+func (e *bincEncDriver) EncodeNil() {
+	e.w.writen1(bincVdSpecial<<4 | bincSpNil)
 }
 }
 
 
-func (e *bincEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {
-	if rt == timeTypId {
-		var bs []byte
-		switch x := v.(type) {
-		case time.Time:
-			bs = encodeTime(x)
-		case *time.Time:
-			bs = encodeTime(*x)
-		default:
-			e.e.errorf("binc error encoding builtin: expect time.Time, received %T", v)
-		}
+func (e *bincEncDriver) EncodeTime(t time.Time) {
+	if t.IsZero() {
+		e.EncodeNil()
+	} else {
+		bs := bincEncodeTime(t)
 		e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
 		e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
 		e.w.writeb(bs)
 		e.w.writeb(bs)
 	}
 	}
 }
 }
 
 
-func (e *bincEncDriver) EncodeNil() {
-	e.w.writen1(bincVdSpecial<<4 | bincSpNil)
-}
-
 func (e *bincEncDriver) EncodeBool(b bool) {
 func (e *bincEncDriver) EncodeBool(b bool) {
 	if b {
 	if b {
 		e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
 		e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
@@ -198,13 +235,19 @@ func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
 
 
 func (e *bincEncDriver) WriteArrayStart(length int) {
 func (e *bincEncDriver) WriteArrayStart(length int) {
 	e.encLen(bincVdArray<<4, uint64(length))
 	e.encLen(bincVdArray<<4, uint64(length))
+	e.c = containerArrayStart
 }
 }
 
 
 func (e *bincEncDriver) WriteMapStart(length int) {
 func (e *bincEncDriver) WriteMapStart(length int) {
 	e.encLen(bincVdMap<<4, uint64(length))
 	e.encLen(bincVdMap<<4, uint64(length))
+	e.c = containerMapStart
 }
 }
 
 
 func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
 func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
+	if e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 0 || e.h.AsSymbols == 1) {
+		e.EncodeSymbol(v)
+		return
+	}
 	l := uint64(len(v))
 	l := uint64(len(v))
 	e.encBytesLen(c, l)
 	e.encBytesLen(c, l)
 	if l > 0 {
 	if l > 0 {
@@ -214,7 +257,7 @@ func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
 
 
 func (e *bincEncDriver) EncodeSymbol(v string) {
 func (e *bincEncDriver) EncodeSymbol(v string) {
 	// if WriteSymbolsNoRefs {
 	// if WriteSymbolsNoRefs {
-	// 	e.encodeString(c_UTF8, v)
+	// 	e.encodeString(cUTF8, v)
 	// 	return
 	// 	return
 	// }
 	// }
 
 
@@ -224,10 +267,10 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
 
 
 	l := len(v)
 	l := len(v)
 	if l == 0 {
 	if l == 0 {
-		e.encBytesLen(c_UTF8, 0)
+		e.encBytesLen(cUTF8, 0)
 		return
 		return
 	} else if l == 1 {
 	} else if l == 1 {
-		e.encBytesLen(c_UTF8, 1)
+		e.encBytesLen(cUTF8, 1)
 		e.w.writen1(v[0])
 		e.w.writen1(v[0])
 		return
 		return
 	}
 	}
@@ -277,6 +320,10 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
 }
 }
 
 
 func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
 func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+	if v == nil {
+		e.EncodeNil()
+		return
+	}
 	l := uint64(len(v))
 	l := uint64(len(v))
 	e.encBytesLen(c, l)
 	e.encBytesLen(c, l)
 	if l > 0 {
 	if l > 0 {
@@ -286,7 +333,7 @@ func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
 
 
 func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
 func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
 	//TODO: support bincUnicodeOther (for now, just use string or bytearray)
 	//TODO: support bincUnicodeOther (for now, just use string or bytearray)
-	if c == c_RAW {
+	if c == cRAW {
 		e.encLen(bincVdByteArray<<4, length)
 		e.encLen(bincVdByteArray<<4, length)
 	} else {
 	} else {
 		e.encLen(bincVdString<<4, length)
 		e.encLen(bincVdString<<4, length)
@@ -325,6 +372,9 @@ type bincDecSymbol struct {
 }
 }
 
 
 type bincDecDriver struct {
 type bincDecDriver struct {
+	decDriverNoopContainerReader
+	noBuiltInTypes
+
 	d      *Decoder
 	d      *Decoder
 	h      *BincHandle
 	h      *BincHandle
 	r      decReader
 	r      decReader
@@ -333,14 +383,15 @@ type bincDecDriver struct {
 	bd     byte
 	bd     byte
 	vd     byte
 	vd     byte
 	vs     byte
 	vs     byte
-	// noStreamingCodec
-	// decNoSeparator
-	b [scratchByteArrayLen]byte
-
+	_      [3]byte // padding
 	// 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
+
+	// noStreamingCodec
+	// decNoSeparator
+
+	b [8 * 8]byte // scratch
 }
 }
 
 
 func (d *bincDecDriver) readNextBd() {
 func (d *bincDecDriver) readNextBd() {
@@ -371,9 +422,10 @@ func (d *bincDecDriver) ContainerType() (vt valueType) {
 		return valueTypeArray
 		return valueTypeArray
 	} else if d.vd == bincVdMap {
 	} else if d.vd == bincVdMap {
 		return valueTypeMap
 		return valueTypeMap
-	} else {
-		// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
 	}
 	}
+	// else {
+	// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+	// }
 	return valueTypeUnset
 	return valueTypeUnset
 }
 }
 
 
@@ -388,27 +440,24 @@ func (d *bincDecDriver) TryDecodeAsNil() bool {
 	return false
 	return false
 }
 }
 
 
-func (d *bincDecDriver) IsBuiltinType(rt uintptr) bool {
-	return rt == timeTypId
-}
-
-func (d *bincDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {
+func (d *bincDecDriver) DecodeTime() (t time.Time) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
-	if rt == timeTypId {
-		if d.vd != bincVdTimestamp {
-			d.d.errorf("Invalid d.vd. Expecting 0x%x. Received: 0x%x", bincVdTimestamp, d.vd)
-			return
-		}
-		tt, err := decodeTime(d.r.readx(int(d.vs)))
-		if err != nil {
-			panic(err)
-		}
-		var vt *time.Time = v.(*time.Time)
-		*vt = tt
+	if d.bd == bincVdSpecial<<4|bincSpNil {
 		d.bdRead = false
 		d.bdRead = false
+		return
+	}
+	if d.vd != bincVdTimestamp {
+		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(int(d.vs)))
+	if err != nil {
+		panic(err)
 	}
 	}
+	d.bdRead = false
+	return
 }
 }
 
 
 func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
 func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
@@ -417,7 +466,7 @@ func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
 	} else {
 	} else {
 		l := d.r.readn1()
 		l := d.r.readn1()
 		if l > 8 {
 		if l > 8 {
-			d.d.errorf("At most 8 bytes used to represent float. Received: %v bytes", l)
+			d.d.errorf("cannot read float - at most 8 bytes used to represent float - received %v bytes", l)
 			return
 			return
 		}
 		}
 		for i := l; i < 8; i++ {
 		for i := l; i < 8; i++ {
@@ -436,7 +485,7 @@ func (d *bincDecDriver) decFloat() (f float64) {
 		d.decFloatPre(d.vs, 8)
 		d.decFloatPre(d.vs, 8)
 		f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
 		f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
 	} else {
 	} else {
-		d.d.errorf("only float32 and float64 are supported. d.vd: 0x%x, d.vs: 0x%x", d.vd, d.vs)
+		d.d.errorf("read float - only float32 and float64 are supported - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	return
 	return
@@ -493,49 +542,38 @@ func (d *bincDecDriver) decCheckInteger() (ui uint64, neg bool) {
 			neg = true
 			neg = true
 			ui = 1
 			ui = 1
 		} else {
 		} else {
-			d.d.errorf("numeric decode fails for special value: d.vs: 0x%x", d.vs)
+			d.d.errorf("integer decode fails - invalid special value from descriptor %x-%x/%s",
+				d.vd, d.vs, bincdesc(d.vd, d.vs))
 			return
 			return
 		}
 		}
 	} else {
 	} else {
-		d.d.errorf("number can only be decoded from uint or int values. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
+		d.d.errorf("integer can only be decoded from int/uint. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
 		return
 		return
 	}
 	}
 	return
 	return
 }
 }
 
 
-func (d *bincDecDriver) DecodeInt(bitsize uint8) (i int64) {
+func (d *bincDecDriver) DecodeInt64() (i int64) {
 	ui, neg := d.decCheckInteger()
 	ui, neg := d.decCheckInteger()
-	i, overflow := chkOvf.SignedInt(ui)
-	if overflow {
-		d.d.errorf("simple: overflow converting %v to signed integer", ui)
-		return
-	}
+	i = chkOvf.SignedIntV(ui)
 	if neg {
 	if neg {
 		i = -i
 		i = -i
 	}
 	}
-	if chkOvf.Int(i, bitsize) {
-		d.d.errorf("binc: overflow integer: %v for num bits: %v", i, bitsize)
-		return
-	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
 
 
-func (d *bincDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
+func (d *bincDecDriver) DecodeUint64() (ui uint64) {
 	ui, neg := d.decCheckInteger()
 	ui, neg := d.decCheckInteger()
 	if neg {
 	if neg {
-		d.d.errorf("Assigning negative signed value to unsigned type")
-		return
-	}
-	if chkOvf.Uint(ui, bitsize) {
-		d.d.errorf("binc: overflow integer: %v", ui)
+		d.d.errorf("assigning negative signed value to unsigned integer type")
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
 
 
-func (d *bincDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
+func (d *bincDecDriver) DecodeFloat64() (f float64) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -551,17 +589,14 @@ func (d *bincDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
 		} else if vs == bincSpNegInf {
 		} else if vs == bincSpNegInf {
 			return math.Inf(-1)
 			return math.Inf(-1)
 		} else {
 		} else {
-			d.d.errorf("Invalid d.vs decoding float where d.vd=bincVdSpecial: %v", d.vs)
+			d.d.errorf("float - invalid special value from descriptor %x-%x/%s",
+				d.vd, d.vs, bincdesc(d.vd, d.vs))
 			return
 			return
 		}
 		}
 	} else if vd == bincVdFloat {
 	} else if vd == bincVdFloat {
 		f = d.decFloat()
 		f = d.decFloat()
 	} else {
 	} else {
-		f = float64(d.DecodeInt(64))
-	}
-	if chkOverflow32 && chkOvf.Float32(f) {
-		d.d.errorf("binc: float32 overflow: %v", f)
-		return
+		f = float64(d.DecodeInt64())
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
@@ -577,7 +612,7 @@ func (d *bincDecDriver) DecodeBool() (b bool) {
 	} else if bd == (bincVdSpecial | bincSpTrue) {
 	} else if bd == (bincVdSpecial | bincSpTrue) {
 		b = true
 		b = true
 	} else {
 	} else {
-		d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+		d.d.errorf("bool - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -589,7 +624,7 @@ func (d *bincDecDriver) ReadMapStart() (length int) {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 	if d.vd != bincVdMap {
 	if d.vd != bincVdMap {
-		d.d.errorf("Invalid d.vd for map. Expecting 0x%x. Got: 0x%x", bincVdMap, d.vd)
+		d.d.errorf("map - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	length = d.decLen()
 	length = d.decLen()
@@ -602,7 +637,7 @@ func (d *bincDecDriver) ReadArrayStart() (length int) {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 	if d.vd != bincVdArray {
 	if d.vd != bincVdArray {
-		d.d.errorf("Invalid d.vd for array. Expecting 0x%x. Got: 0x%x", bincVdArray, d.vd)
+		d.d.errorf("array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	length = d.decLen()
 	length = d.decLen()
@@ -633,7 +668,8 @@ func (d *bincDecDriver) decLenNumber() (v uint64) {
 	return
 	return
 }
 }
 
 
-func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (bs2 []byte, s string) {
+func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (
+	bs2 []byte, s string) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -641,7 +677,7 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
 		d.bdRead = false
 		d.bdRead = false
 		return
 		return
 	}
 	}
-	var slen int = -1
+	var slen = -1
 	// var ok bool
 	// var ok bool
 	switch d.vd {
 	switch d.vd {
 	case bincVdString, bincVdByteArray:
 	case bincVdString, bincVdByteArray:
@@ -714,8 +750,7 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
 			d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
 			d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
 		}
 		}
 	default:
 	default:
-		d.d.errorf("Invalid d.vd. Expecting string:0x%x, bytearray:0x%x or symbol: 0x%x. Got: 0x%x",
-			bincVdString, bincVdByteArray, bincVdSymbol, d.vd)
+		d.d.errorf("string/bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -743,12 +778,16 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		d.bdRead = false
 		d.bdRead = false
 		return nil
 		return nil
 	}
 	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.vd == bincVdArray {
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
 	var clen int
 	var clen int
 	if d.vd == bincVdString || d.vd == bincVdByteArray {
 	if d.vd == bincVdString || d.vd == bincVdByteArray {
 		clen = d.decLen()
 		clen = d.decLen()
 	} else {
 	} else {
-		d.d.errorf("Invalid d.vd for bytes. Expecting string:0x%x or bytearray:0x%x. Got: 0x%x",
-			bincVdString, bincVdByteArray, d.vd)
+		d.d.errorf("bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -764,7 +803,7 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 
 
 func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 	if xtag > 0xff {
 	if xtag > 0xff {
-		d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
+		d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
 		return
 		return
 	}
 	}
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
@@ -787,14 +826,14 @@ func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []b
 		l := d.decLen()
 		l := d.decLen()
 		xtag = d.r.readn1()
 		xtag = d.r.readn1()
 		if verifyTag && xtag != tag {
 		if verifyTag && xtag != tag {
-			d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+			d.d.errorf("wrong extension tag - got %b, expecting: %v", xtag, tag)
 			return
 			return
 		}
 		}
 		xbs = d.r.readx(l)
 		xbs = d.r.readx(l)
 	} else if d.vd == bincVdByteArray {
 	} else if d.vd == bincVdByteArray {
 		xbs = d.DecodeBytes(nil, true)
 		xbs = d.DecodeBytes(nil, true)
 	} else {
 	} else {
-		d.d.errorf("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.vd)
+		d.d.errorf("ext - expecting extensions or byte array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -839,7 +878,7 @@ func (d *bincDecDriver) DecodeNaked() {
 			n.v = valueTypeInt
 			n.v = valueTypeInt
 			n.i = int64(-1) // int8(-1)
 			n.i = int64(-1) // int8(-1)
 		default:
 		default:
-			d.d.errorf("decodeNaked: Unrecognized special value 0x%x", d.vs)
+			d.d.errorf("cannot infer value - unrecognized special value from descriptor %x-%x/%s", d.vd, d.vs, bincdesc(d.vd, d.vs))
 		}
 		}
 	case bincVdSmallInt:
 	case bincVdSmallInt:
 		n.v = valueTypeUint
 		n.v = valueTypeUint
@@ -863,8 +902,8 @@ func (d *bincDecDriver) DecodeNaked() {
 		n.v = valueTypeBytes
 		n.v = valueTypeBytes
 		n.l = d.DecodeBytes(nil, false)
 		n.l = d.DecodeBytes(nil, false)
 	case bincVdTimestamp:
 	case bincVdTimestamp:
-		n.v = valueTypeTimestamp
-		tt, err := decodeTime(d.r.readx(int(d.vs)))
+		n.v = valueTypeTime
+		tt, err := bincDecodeTime(d.r.readx(int(d.vs)))
 		if err != nil {
 		if err != nil {
 			panic(err)
 			panic(err)
 		}
 		}
@@ -881,7 +920,7 @@ func (d *bincDecDriver) DecodeNaked() {
 		n.v = valueTypeMap
 		n.v = valueTypeMap
 		decodeFurther = true
 		decodeFurther = true
 	default:
 	default:
-		d.d.errorf("decodeNaked: Unrecognized d.vd: 0x%x", d.vd)
+		d.d.errorf("cannot infer value - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
 	}
 	}
 
 
 	if !decodeFurther {
 	if !decodeFurther {
@@ -912,27 +951,50 @@ type BincHandle struct {
 	BasicHandle
 	BasicHandle
 	binaryEncodingType
 	binaryEncodingType
 	noElemSeparators
 	noElemSeparators
+
+	// AsSymbols defines what should be encoded as symbols.
+	//
+	// Encoding as symbols can reduce the encoded size significantly.
+	//
+	// However, during decoding, each string to be encoded as a symbol must
+	// be checked to see if it has been seen before. Consequently, encoding time
+	// will increase if using symbols, because string comparisons has a clear cost.
+	//
+	// Values:
+	// - 0: default: library uses best judgement
+	// - 1: use symbols
+	// - 2: do not use symbols
+	AsSymbols uint8
+
+	// AsSymbols: may later on introduce more options ...
+	// - m: map keys
+	// - s: struct fields
+	// - n: none
+	// - a: all: same as m, s, ...
+
+	// _ [1]uint64 // padding
 }
 }
 
 
+// Name returns the name of the handle: binc
+func (h *BincHandle) Name() string { return "binc" }
+
+// SetBytesExt sets an extension
 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) {
-	return h.SetExt(rt, tag, &setExtWrapper{b: ext})
+	return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
 }
 }
 
 
 func (h *BincHandle) newEncDriver(e *Encoder) encDriver {
 func (h *BincHandle) newEncDriver(e *Encoder) encDriver {
-	return &bincEncDriver{e: e, w: e.w}
+	return &bincEncDriver{e: e, h: h, w: e.w}
 }
 }
 
 
 func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
 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
+	e.c = 0
 	e.m = nil
 	e.m = nil
 }
 }
 
 
@@ -942,5 +1004,165 @@ func (d *bincDecDriver) reset() {
 	d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
 	d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
 }
 }
 
 
+// var timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
+
+// EncodeTime encodes a time.Time as a []byte, including
+// information on the instant in time and UTC offset.
+//
+// Format Description
+//
+//   A timestamp is composed of 3 components:
+//
+//   - secs: signed integer representing seconds since unix epoch
+//   - nsces: unsigned integer representing fractional seconds as a
+//     nanosecond offset within secs, in the range 0 <= nsecs < 1e9
+//   - tz: signed integer representing timezone offset in minutes east of UTC,
+//     and a dst (daylight savings time) flag
+//
+//   When encoding a timestamp, the first byte is the descriptor, which
+//   defines which components are encoded and how many bytes are used to
+//   encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it
+//   is not encoded in the byte array explicitly*.
+//
+//       Descriptor 8 bits are of the form `A B C DDD EE`:
+//           A:   Is secs component encoded? 1 = true
+//           B:   Is nsecs component encoded? 1 = true
+//           C:   Is tz component encoded? 1 = true
+//           DDD: Number of extra bytes for secs (range 0-7).
+//                If A = 1, secs encoded in DDD+1 bytes.
+//                    If A = 0, secs is not encoded, and is assumed to be 0.
+//                    If A = 1, then we need at least 1 byte to encode secs.
+//                    DDD says the number of extra bytes beyond that 1.
+//                    E.g. if DDD=0, then secs is represented in 1 byte.
+//                         if DDD=2, then secs is represented in 3 bytes.
+//           EE:  Number of extra bytes for nsecs (range 0-3).
+//                If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above)
+//
+//   Following the descriptor bytes, subsequent bytes are:
+//
+//       secs component encoded in `DDD + 1` bytes (if A == 1)
+//       nsecs component encoded in `EE + 1` bytes (if B == 1)
+//       tz component encoded in 2 bytes (if C == 1)
+//
+//   secs and nsecs components are integers encoded in a BigEndian
+//   2-complement encoding format.
+//
+//   tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to
+//   Least significant bit 0 are described below:
+//
+//       Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes).
+//       Bit 15 = have\_dst: set to 1 if we set the dst flag.
+//       Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not.
+//       Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format.
+//
+func bincEncodeTime(t time.Time) []byte {
+	//t := rv.Interface().(time.Time)
+	tsecs, tnsecs := t.Unix(), t.Nanosecond()
+	var (
+		bd   byte
+		btmp [8]byte
+		bs   [16]byte
+		i    int = 1
+	)
+	l := t.Location()
+	if l == time.UTC {
+		l = nil
+	}
+	if tsecs != 0 {
+		bd = bd | 0x80
+		bigen.PutUint64(btmp[:], uint64(tsecs))
+		f := pruneSignExt(btmp[:], tsecs >= 0)
+		bd = bd | (byte(7-f) << 2)
+		copy(bs[i:], btmp[f:])
+		i = i + (8 - f)
+	}
+	if tnsecs != 0 {
+		bd = bd | 0x40
+		bigen.PutUint32(btmp[:4], uint32(tnsecs))
+		f := pruneSignExt(btmp[:4], true)
+		bd = bd | byte(3-f)
+		copy(bs[i:], btmp[f:4])
+		i = i + (4 - f)
+	}
+	if l != nil {
+		bd = bd | 0x20
+		// Note that Go Libs do not give access to dst flag.
+		_, zoneOffset := t.Zone()
+		//zoneName, zoneOffset := t.Zone()
+		zoneOffset /= 60
+		z := uint16(zoneOffset)
+		bigen.PutUint16(btmp[:2], z)
+		// clear dst flags
+		bs[i] = btmp[0] & 0x3f
+		bs[i+1] = btmp[1]
+		i = i + 2
+	}
+	bs[0] = bd
+	return bs[0:i]
+}
+
+// bincDecodeTime decodes a []byte into a time.Time.
+func bincDecodeTime(bs []byte) (tt time.Time, err error) {
+	bd := bs[0]
+	var (
+		tsec  int64
+		tnsec uint32
+		tz    uint16
+		i     byte = 1
+		i2    byte
+		n     byte
+	)
+	if bd&(1<<7) != 0 {
+		var btmp [8]byte
+		n = ((bd >> 2) & 0x7) + 1
+		i2 = i + n
+		copy(btmp[8-n:], bs[i:i2])
+		//if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it)
+		if bs[i]&(1<<7) != 0 {
+			copy(btmp[0:8-n], bsAll0xff)
+			//for j,k := byte(0), 8-n; j < k; j++ {	btmp[j] = 0xff }
+		}
+		i = i2
+		tsec = int64(bigen.Uint64(btmp[:]))
+	}
+	if bd&(1<<6) != 0 {
+		var btmp [4]byte
+		n = (bd & 0x3) + 1
+		i2 = i + n
+		copy(btmp[4-n:], bs[i:i2])
+		i = i2
+		tnsec = bigen.Uint32(btmp[:])
+	}
+	if bd&(1<<5) == 0 {
+		tt = time.Unix(tsec, int64(tnsec)).UTC()
+		return
+	}
+	// In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
+	// However, we need name here, so it can be shown when time is printed.
+	// Zone name is in form: UTC-08:00.
+	// Note that Go Libs do not give access to dst flag, so we ignore dst bits
+
+	i2 = i + 2
+	tz = bigen.Uint16(bs[i:i2])
+	// i = i2
+	// sign extend sign bit into top 2 MSB (which were dst bits):
+	if tz&(1<<13) == 0 { // positive
+		tz = tz & 0x3fff //clear 2 MSBs: dst bits
+	} else { // negative
+		tz = tz | 0xc000 //set 2 MSBs: dst bits
+	}
+	tzint := int16(tz)
+	if tzint == 0 {
+		tt = time.Unix(tsec, int64(tnsec)).UTC()
+	} else {
+		// For Go Time, do not use a descriptive timezone.
+		// It's unnecessary, and makes it harder to do a reflect.DeepEqual.
+		// The Offset already tells what the offset should be, if not on UTC and unknown zone name.
+		// var zoneName = timeLocUTCName(tzint)
+		tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60))
+	}
+	return
+}
+
 var _ decDriver = (*bincDecDriver)(nil)
 var _ decDriver = (*bincDecDriver)(nil)
 var _ encDriver = (*bincEncDriver)(nil)
 var _ encDriver = (*bincEncDriver)(nil)

+ 204 - 79
vendor/github.com/ugorji/go/codec/cbor.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 package codec
 package codec
@@ -6,6 +6,7 @@ package codec
 import (
 import (
 	"math"
 	"math"
 	"reflect"
 	"reflect"
+	"time"
 )
 )
 
 
 const (
 const (
@@ -38,6 +39,8 @@ const (
 	cborBdBreak                 = 0xff
 	cborBdBreak                 = 0xff
 )
 )
 
 
+// These define some in-stream descriptors for
+// manual encoding e.g. when doing explicit indefinite-length
 const (
 const (
 	CborStreamBytes  byte = 0x5f
 	CborStreamBytes  byte = 0x5f
 	CborStreamString      = 0x7f
 	CborStreamString      = 0x7f
@@ -57,6 +60,46 @@ const (
 	cborBaseSimple      = 0xe0
 	cborBaseSimple      = 0xe0
 )
 )
 
 
+func cbordesc(bd byte) string {
+	switch bd {
+	case cborBdNil:
+		return "nil"
+	case cborBdFalse:
+		return "false"
+	case cborBdTrue:
+		return "true"
+	case cborBdFloat16, cborBdFloat32, cborBdFloat64:
+		return "float"
+	case cborBdIndefiniteBytes:
+		return "bytes*"
+	case cborBdIndefiniteString:
+		return "string*"
+	case cborBdIndefiniteArray:
+		return "array*"
+	case cborBdIndefiniteMap:
+		return "map*"
+	default:
+		switch {
+		case bd >= cborBaseUint && bd < cborBaseNegInt:
+			return "(u)int"
+		case bd >= cborBaseNegInt && bd < cborBaseBytes:
+			return "int"
+		case bd >= cborBaseBytes && bd < cborBaseString:
+			return "bytes"
+		case bd >= cborBaseString && bd < cborBaseArray:
+			return "string"
+		case bd >= cborBaseArray && bd < cborBaseMap:
+			return "array"
+		case bd >= cborBaseMap && bd < cborBaseTag:
+			return "map"
+		case bd >= cborBaseTag && bd < cborBaseSimple:
+			return "ext"
+		default:
+			return "unknown"
+		}
+	}
+}
+
 // -------------------
 // -------------------
 
 
 type cborEncDriver struct {
 type cborEncDriver struct {
@@ -67,6 +110,7 @@ type cborEncDriver struct {
 	w encWriter
 	w encWriter
 	h *CborHandle
 	h *CborHandle
 	x [8]byte
 	x [8]byte
+	_ [3]uint64 // padding
 }
 }
 
 
 func (e *cborEncDriver) EncodeNil() {
 func (e *cborEncDriver) EncodeNil() {
@@ -124,6 +168,24 @@ func (e *cborEncDriver) encLen(bd byte, length int) {
 	e.encUint(uint64(length), bd)
 	e.encUint(uint64(length), bd)
 }
 }
 
 
+func (e *cborEncDriver) EncodeTime(t time.Time) {
+	if t.IsZero() {
+		e.EncodeNil()
+	} else if e.h.TimeRFC3339 {
+		e.encUint(0, cborBaseTag)
+		e.EncodeString(cUTF8, t.Format(time.RFC3339Nano))
+	} else {
+		e.encUint(1, cborBaseTag)
+		t = t.UTC().Round(time.Microsecond)
+		sec, nsec := t.Unix(), uint64(t.Nanosecond())
+		if nsec == 0 {
+			e.EncodeInt(sec)
+		} else {
+			e.EncodeFloat64(float64(sec) + float64(nsec)/1e9)
+		}
+	}
+}
+
 func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
 func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
 	e.encUint(uint64(xtag), cborBaseTag)
 	e.encUint(uint64(xtag), cborBaseTag)
 	if v := ext.ConvertExt(rv); v == nil {
 	if v := ext.ConvertExt(rv); v == nil {
@@ -173,36 +235,65 @@ func (e *cborEncDriver) WriteArrayEnd() {
 }
 }
 
 
 func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
 func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
-	e.encLen(cborBaseString, len(v))
-	e.w.writestr(v)
+	e.encStringBytesS(cborBaseString, v)
 }
 }
 
 
-func (e *cborEncDriver) EncodeSymbol(v string) {
-	e.EncodeString(c_UTF8, v)
+func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+	if v == nil {
+		e.EncodeNil()
+	} else if c == cRAW {
+		e.encStringBytesS(cborBaseBytes, stringView(v))
+	} else {
+		e.encStringBytesS(cborBaseString, stringView(v))
+	}
 }
 }
 
 
-func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
-	if c == c_RAW {
-		e.encLen(cborBaseBytes, len(v))
+func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
+	if e.h.IndefiniteLength {
+		if bb == cborBaseBytes {
+			e.w.writen1(cborBdIndefiniteBytes)
+		} else {
+			e.w.writen1(cborBdIndefiniteString)
+		}
+		blen := len(v) / 4
+		if blen == 0 {
+			blen = 64
+		} else if blen > 1024 {
+			blen = 1024
+		}
+		for i := 0; i < len(v); {
+			var v2 string
+			i2 := i + blen
+			if i2 < len(v) {
+				v2 = v[i:i2]
+			} else {
+				v2 = v[i:]
+			}
+			e.encLen(bb, len(v2))
+			e.w.writestr(v2)
+			i = i2
+		}
+		e.w.writen1(cborBdBreak)
 	} else {
 	} else {
-		e.encLen(cborBaseString, len(v))
+		e.encLen(bb, len(v))
+		e.w.writestr(v)
 	}
 	}
-	e.w.writeb(v)
 }
 }
 
 
 // ----------------------
 // ----------------------
 
 
 type cborDecDriver struct {
 type cborDecDriver struct {
-	d      *Decoder
-	h      *CborHandle
-	r      decReader
-	b      [scratchByteArrayLen]byte
+	d *Decoder
+	h *CborHandle
+	r decReader
+	// b      [scratchByteArrayLen]byte
 	br     bool // bytes reader
 	br     bool // bytes reader
 	bdRead bool
 	bdRead bool
 	bd     byte
 	bd     byte
 	noBuiltInTypes
 	noBuiltInTypes
 	// decNoSeparator
 	// decNoSeparator
 	decDriverNoopContainerReader
 	decDriverNoopContainerReader
+	_ [3]uint64 // padding
 }
 }
 
 
 func (d *cborDecDriver) readNextBd() {
 func (d *cborDecDriver) readNextBd() {
@@ -231,9 +322,10 @@ func (d *cborDecDriver) ContainerType() (vt valueType) {
 		return valueTypeArray
 		return valueTypeArray
 	} else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) {
 	} else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) {
 		return valueTypeMap
 		return valueTypeMap
-	} else {
-		// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
 	}
 	}
+	// else {
+	// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+	// }
 	return valueTypeUnset
 	return valueTypeUnset
 }
 }
 
 
@@ -274,7 +366,7 @@ func (d *cborDecDriver) decUint() (ui uint64) {
 		} else if v == 0x1b {
 		} else if v == 0x1b {
 			ui = uint64(bigen.Uint64(d.r.readx(8)))
 			ui = uint64(bigen.Uint64(d.r.readx(8)))
 		} else {
 		} else {
-			d.d.errorf("decUint: Invalid descriptor: %v", d.bd)
+			d.d.errorf("invalid descriptor decoding uint: %x/%s", d.bd, cbordesc(d.bd))
 			return
 			return
 		}
 		}
 	}
 	}
@@ -290,52 +382,36 @@ func (d *cborDecDriver) decCheckInteger() (neg bool) {
 	} else if major == cborMajorNegInt {
 	} else if major == cborMajorNegInt {
 		neg = true
 		neg = true
 	} else {
 	} else {
-		d.d.errorf("invalid major: %v (bd: %v)", major, d.bd)
+		d.d.errorf("not an integer - invalid major %v from descriptor %x/%s", major, d.bd, cbordesc(d.bd))
 		return
 		return
 	}
 	}
 	return
 	return
 }
 }
 
 
-func (d *cborDecDriver) DecodeInt(bitsize uint8) (i int64) {
+func (d *cborDecDriver) DecodeInt64() (i int64) {
 	neg := d.decCheckInteger()
 	neg := d.decCheckInteger()
 	ui := d.decUint()
 	ui := d.decUint()
 	// check if this number can be converted to an int without overflow
 	// check if this number can be converted to an int without overflow
-	var overflow bool
 	if neg {
 	if neg {
-		if i, overflow = chkOvf.SignedInt(ui + 1); overflow {
-			d.d.errorf("cbor: overflow converting %v to signed integer", ui+1)
-			return
-		}
-		i = -i
+		i = -(chkOvf.SignedIntV(ui + 1))
 	} else {
 	} else {
-		if i, overflow = chkOvf.SignedInt(ui); overflow {
-			d.d.errorf("cbor: overflow converting %v to signed integer", ui)
-			return
-		}
-	}
-	if chkOvf.Int(i, bitsize) {
-		d.d.errorf("cbor: overflow integer: %v", i)
-		return
+		i = chkOvf.SignedIntV(ui)
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
 
 
-func (d *cborDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
+func (d *cborDecDriver) DecodeUint64() (ui uint64) {
 	if d.decCheckInteger() {
 	if d.decCheckInteger() {
-		d.d.errorf("Assigning negative signed value to unsigned type")
+		d.d.errorf("assigning negative signed value to unsigned type")
 		return
 		return
 	}
 	}
 	ui = d.decUint()
 	ui = d.decUint()
-	if chkOvf.Uint(ui, bitsize) {
-		d.d.errorf("cbor: overflow integer: %v", ui)
-		return
-	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
 
 
-func (d *cborDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
+func (d *cborDecDriver) DecodeFloat64() (f float64) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -346,13 +422,9 @@ func (d *cborDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
 	} else if bd == cborBdFloat64 {
 	} else if bd == cborBdFloat64 {
 		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
 		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
 	} else if bd >= cborBaseUint && bd < cborBaseBytes {
 	} else if bd >= cborBaseUint && bd < cborBaseBytes {
-		f = float64(d.DecodeInt(64))
+		f = float64(d.DecodeInt64())
 	} else {
 	} else {
-		d.d.errorf("Float only valid from float16/32/64: Invalid descriptor: %v", bd)
-		return
-	}
-	if chkOverflow32 && chkOvf.Float32(f) {
-		d.d.errorf("cbor: float32 overflow: %v", f)
+		d.d.errorf("float only valid from float16/32/64 - invalid descriptor %x/%s", bd, cbordesc(bd))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -368,7 +440,7 @@ func (d *cborDecDriver) DecodeBool() (b bool) {
 		b = true
 		b = true
 	} else if bd == cborBdFalse {
 	} else if bd == cborBdFalse {
 	} else {
 	} else {
-		d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+		d.d.errorf("not bool - %s %x/%s", msgBadDesc, d.bd, cbordesc(d.bd))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -408,7 +480,8 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
 			break
 			break
 		}
 		}
 		if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText {
 		if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText {
-			d.d.errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, d.bd)
+			d.d.errorf("expect bytes/string major type in indefinite string/bytes;"+
+				" got major %v from descriptor %x/%x", major, d.bd, cbordesc(d.bd))
 			return nil
 			return nil
 		}
 		}
 		n := d.decLen()
 		n := d.decLen()
@@ -438,29 +511,84 @@ func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		return nil
 		return nil
 	}
 	}
 	if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString {
 	if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString {
+		d.bdRead = false
 		if bs == nil {
 		if bs == nil {
-			return d.decAppendIndefiniteBytes(nil)
+			if zerocopy {
+				return d.decAppendIndefiniteBytes(d.d.b[:0])
+			}
+			return d.decAppendIndefiniteBytes(zeroByteSlice)
 		}
 		}
 		return d.decAppendIndefiniteBytes(bs[:0])
 		return d.decAppendIndefiniteBytes(bs[:0])
 	}
 	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.bd == cborBdIndefiniteArray || (d.bd >= cborBaseArray && d.bd < cborBaseMap) {
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
 	clen := d.decLen()
 	clen := d.decLen()
 	d.bdRead = false
 	d.bdRead = false
 	if zerocopy {
 	if zerocopy {
 		if d.br {
 		if d.br {
 			return d.r.readx(clen)
 			return d.r.readx(clen)
 		} else if len(bs) == 0 {
 		} else if len(bs) == 0 {
-			bs = d.b[:]
+			bs = d.d.b[:]
 		}
 		}
 	}
 	}
-	return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
+	return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
 }
 }
 
 
 func (d *cborDecDriver) DecodeString() (s string) {
 func (d *cborDecDriver) DecodeString() (s string) {
-	return string(d.DecodeBytes(d.b[:], true))
+	return string(d.DecodeBytes(d.d.b[:], true))
 }
 }
 
 
 func (d *cborDecDriver) DecodeStringAsBytes() (s []byte) {
 func (d *cborDecDriver) DecodeStringAsBytes() (s []byte) {
-	return d.DecodeBytes(d.b[:], true)
+	return d.DecodeBytes(d.d.b[:], true)
+}
+
+func (d *cborDecDriver) DecodeTime() (t time.Time) {
+	if !d.bdRead {
+		d.readNextBd()
+	}
+	if d.bd == cborBdNil || d.bd == cborBdUndefined {
+		d.bdRead = false
+		return
+	}
+	xtag := d.decUint()
+	d.bdRead = false
+	return d.decodeTime(xtag)
+}
+
+func (d *cborDecDriver) decodeTime(xtag uint64) (t time.Time) {
+	if !d.bdRead {
+		d.readNextBd()
+	}
+	switch xtag {
+	case 0:
+		var err error
+		if t, err = time.Parse(time.RFC3339, stringView(d.DecodeStringAsBytes())); err != nil {
+			d.d.errorv(err)
+		}
+	case 1:
+		// decode an int64 or a float, and infer time.Time from there.
+		// for floats, round to microseconds, as that is what is guaranteed to fit well.
+		switch {
+		case d.bd == cborBdFloat16, d.bd == cborBdFloat32:
+			f1, f2 := math.Modf(d.DecodeFloat64())
+			t = time.Unix(int64(f1), int64(f2*1e9))
+		case d.bd == cborBdFloat64:
+			f1, f2 := math.Modf(d.DecodeFloat64())
+			t = time.Unix(int64(f1), int64(f2*1e9))
+		case d.bd >= cborBaseUint && d.bd < cborBaseNegInt,
+			d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
+			t = time.Unix(d.DecodeInt64(), 0)
+		default:
+			d.d.errorf("time.Time can only be decoded from a number (or RFC3339 string)")
+		}
+	default:
+		d.d.errorf("invalid tag for time.Time - expecting 0 or 1, got 0x%x", xtag)
+	}
+	t = t.UTC().Round(time.Microsecond)
+	return
 }
 }
 
 
 func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
@@ -503,12 +631,9 @@ func (d *cborDecDriver) DecodeNaked() {
 	case cborBdTrue:
 	case cborBdTrue:
 		n.v = valueTypeBool
 		n.v = valueTypeBool
 		n.b = true
 		n.b = true
-	case cborBdFloat16, cborBdFloat32:
-		n.v = valueTypeFloat
-		n.f = d.DecodeFloat(true)
-	case cborBdFloat64:
+	case cborBdFloat16, cborBdFloat32, cborBdFloat64:
 		n.v = valueTypeFloat
 		n.v = valueTypeFloat
-		n.f = d.DecodeFloat(false)
+		n.f = d.DecodeFloat64()
 	case cborBdIndefiniteBytes:
 	case cborBdIndefiniteBytes:
 		n.v = valueTypeBytes
 		n.v = valueTypeBytes
 		n.l = d.DecodeBytes(nil, false)
 		n.l = d.DecodeBytes(nil, false)
@@ -526,14 +651,14 @@ func (d *cborDecDriver) DecodeNaked() {
 		case d.bd >= cborBaseUint && d.bd < cborBaseNegInt:
 		case d.bd >= cborBaseUint && d.bd < cborBaseNegInt:
 			if d.h.SignedInteger {
 			if d.h.SignedInteger {
 				n.v = valueTypeInt
 				n.v = valueTypeInt
-				n.i = d.DecodeInt(64)
+				n.i = d.DecodeInt64()
 			} else {
 			} else {
 				n.v = valueTypeUint
 				n.v = valueTypeUint
-				n.u = d.DecodeUint(64)
+				n.u = d.DecodeUint64()
 			}
 			}
 		case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
 		case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
 			n.v = valueTypeInt
 			n.v = valueTypeInt
-			n.i = d.DecodeInt(64)
+			n.i = d.DecodeInt64()
 		case d.bd >= cborBaseBytes && d.bd < cborBaseString:
 		case d.bd >= cborBaseBytes && d.bd < cborBaseString:
 			n.v = valueTypeBytes
 			n.v = valueTypeBytes
 			n.l = d.DecodeBytes(nil, false)
 			n.l = d.DecodeBytes(nil, false)
@@ -550,6 +675,11 @@ func (d *cborDecDriver) DecodeNaked() {
 			n.v = valueTypeExt
 			n.v = valueTypeExt
 			n.u = d.decUint()
 			n.u = d.decUint()
 			n.l = nil
 			n.l = nil
+			if n.u == 0 || n.u == 1 {
+				d.bdRead = false
+				n.v = valueTypeTime
+				n.t = d.decodeTime(n.u)
+			}
 			// d.bdRead = false
 			// d.bdRead = false
 			// d.d.decode(&re.Value) // handled by decode itself.
 			// d.d.decode(&re.Value) // handled by decode itself.
 			// decodeFurther = true
 			// decodeFurther = true
@@ -580,23 +710,8 @@ func (d *cborDecDriver) DecodeNaked() {
 //
 //
 // None of the optional extensions (with tags) defined in the spec are supported out-of-the-box.
 // None of the optional extensions (with tags) defined in the spec are supported out-of-the-box.
 // Users can implement them as needed (using SetExt), including spec-documented ones:
 // Users can implement them as needed (using SetExt), including spec-documented ones:
-//   - timestamp, BigNum, BigFloat, Decimals, Encoded Text (e.g. URL, regexp, base64, MIME Message), etc.
-//
-// To encode with indefinite lengths (streaming), users will use
-// (Must)Encode methods of *Encoder, along with writing CborStreamXXX constants.
-//
-// For example, to encode "one-byte" as an indefinite length string:
-//     var buf bytes.Buffer
-//     e := NewEncoder(&buf, new(CborHandle))
-//     buf.WriteByte(CborStreamString)
-//     e.MustEncode("one-")
-//     e.MustEncode("byte")
-//     buf.WriteByte(CborStreamBreak)
-//     encodedBytes := buf.Bytes()
-//     var vv interface{}
-//     NewDecoderBytes(buf.Bytes(), new(CborHandle)).MustDecode(&vv)
-//     // Now, vv contains the same string "one-byte"
-//
+//   - timestamp, BigNum, BigFloat, Decimals,
+//   - Encoded Text (e.g. URL, regexp, base64, MIME Message), etc.
 type CborHandle struct {
 type CborHandle struct {
 	binaryEncodingType
 	binaryEncodingType
 	noElemSeparators
 	noElemSeparators
@@ -604,10 +719,20 @@ type CborHandle struct {
 
 
 	// IndefiniteLength=true, means that we encode using indefinitelength
 	// IndefiniteLength=true, means that we encode using indefinitelength
 	IndefiniteLength bool
 	IndefiniteLength bool
+
+	// TimeRFC3339 says to encode time.Time using RFC3339 format.
+	// If unset, we encode time.Time using seconds past epoch.
+	TimeRFC3339 bool
+
+	// _ [1]uint64 // padding
 }
 }
 
 
+// Name returns the name of the handle: cbor
+func (h *CborHandle) Name() string { return "cbor" }
+
+// SetInterfaceExt sets an extension
 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) {
-	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
+	return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext})
 }
 }
 
 
 func (h *CborHandle) newEncDriver(e *Encoder) encDriver {
 func (h *CborHandle) newEncDriver(e *Encoder) encDriver {

File diff suppressed because it is too large
+ 239 - 278
vendor/github.com/ugorji/go/codec/decode.go


File diff suppressed because it is too large
+ 264 - 438
vendor/github.com/ugorji/go/codec/encode.go


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


+ 17 - 5
vendor/github.com/ugorji/go/codec/fast-path.not.go

@@ -1,3 +1,6 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
 // +build notfastpath
 // +build notfastpath
 
 
 package codec
 package codec
@@ -14,11 +17,11 @@ 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 fastpathDecodeSetZeroTypeSwitch(iv interface{}, d *Decoder) 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{}) bool           { return false }
 
 
 type fastpathT struct{}
 type fastpathT struct{}
 type fastpathE struct {
 type fastpathE struct {
@@ -31,5 +34,14 @@ type fastpathA [0]fastpathE
 
 
 func (x fastpathA) index(rtid uintptr) int { return -1 }
 func (x fastpathA) index(rtid uintptr) int { return -1 }
 
 
+func (_ fastpathT) DecSliceUint8V(v []uint8, canChange bool, d *Decoder) (_ []uint8, changed bool) {
+	fn := d.cfer().get(uint8SliceTyp, true, true)
+	d.kSlice(&fn.i, reflect.ValueOf(&v).Elem())
+	return v, true
+}
+
 var fastpathAV fastpathA
 var fastpathAV fastpathA
 var fastpathTV fastpathT
 var fastpathTV fastpathT
+
+// ----
+type TestMammoth2Wrapper struct{} // to allow testMammoth work in notfastpath mode

+ 134 - 49
vendor/github.com/ugorji/go/codec/gen-helper.generated.go

@@ -3,10 +3,7 @@
 // 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.
 
 
-// ************************************************************
-// DO NOT EDIT.
-// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
-// ************************************************************
+// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
 
 
 package codec
 package codec
 
 
@@ -31,30 +28,73 @@ const GenVersion = 8
 // GenHelperEncoder is exported so that it can be used externally by codecgen.
 // GenHelperEncoder is exported so that it can be used externally by codecgen.
 //
 //
 // 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 GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
-	return genHelperEncoder{e: e}, e.e
+func GenHelperEncoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
+	ge = genHelperEncoder{e: e}
+	ee = genHelperEncDriver{encDriver: e.e}
+	return
 }
 }
 
 
 // GenHelperDecoder is exported so that it can be used externally by codecgen.
 // GenHelperDecoder is exported so that it can be used externally by codecgen.
 //
 //
 // 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 GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
-	return genHelperDecoder{d: d}, d.d
+func GenHelperDecoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
+	gd = genHelperDecoder{d: d}
+	dd = genHelperDecDriver{decDriver: d.d}
+	return
 }
 }
 
 
-// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
-func BasicHandleDoNotUse(h Handle) *BasicHandle {
-	return h.getBasicHandle()
+type genHelperEncDriver struct {
+	encDriver
+}
+
+func (x genHelperEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {}
+func (x genHelperEncDriver) EncStructFieldKey(keyType valueType, s string) {
+	encStructFieldKey(x.encDriver, keyType, s)
+}
+func (x genHelperEncDriver) EncodeSymbol(s string) {
+	x.encDriver.EncodeString(cUTF8, s)
+}
+
+type genHelperDecDriver struct {
+	decDriver
+	C checkOverflow
+}
+
+func (x genHelperDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {}
+func (x genHelperDecDriver) DecStructFieldKey(keyType valueType, buf *[decScratchByteArrayLen]byte) []byte {
+	return decStructFieldKey(x.decDriver, keyType, buf)
+}
+func (x genHelperDecDriver) DecodeInt(bitsize uint8) (i int64) {
+	return x.C.IntV(x.decDriver.DecodeInt64(), bitsize)
+}
+func (x genHelperDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
+	return x.C.UintV(x.decDriver.DecodeUint64(), bitsize)
+}
+func (x genHelperDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
+	f = x.DecodeFloat64()
+	if chkOverflow32 && chkOvf.Float32(f) {
+		panicv.errorf("float32 overflow: %v", f)
+	}
+	return
+}
+func (x genHelperDecDriver) DecodeFloat32As64() (f float64) {
+	f = x.DecodeFloat64()
+	if chkOvf.Float32(f) {
+		panicv.errorf("float32 overflow: %v", f)
+	}
+	return
 }
 }
 
 
 // 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 {
+	M must
 	e *Encoder
 	e *Encoder
 	F fastpathT
 	F fastpathT
 }
 }
 
 
 // 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 genHelperDecoder struct {
 type genHelperDecoder struct {
+	C checkOverflow
 	d *Decoder
 	d *Decoder
 	F fastpathT
 	F fastpathT
 }
 }
@@ -66,7 +106,12 @@ 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.cf.be // f.e.hh.isBinaryEncoding()
+	return f.e.be // f.e.hh.isBinaryEncoding()
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) IsJSONHandle() bool {
+	return f.e.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*
@@ -79,52 +124,65 @@ func (f genHelperEncoder) EncFallback(iv interface{}) {
 // 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) EncTextMarshal(iv encoding.TextMarshaler) {
 func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
 	bs, fnerr := iv.MarshalText()
 	bs, fnerr := iv.MarshalText()
-	f.e.marshal(bs, fnerr, false, c_UTF8)
+	f.e.marshal(bs, fnerr, false, cUTF8)
 }
 }
 
 
 // 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) EncJSONMarshal(iv jsonMarshaler) {
 func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
 	bs, fnerr := iv.MarshalJSON()
 	bs, fnerr := iv.MarshalJSON()
-	f.e.marshal(bs, fnerr, true, c_UTF8)
+	f.e.marshal(bs, fnerr, true, cUTF8)
 }
 }
 
 
 // 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) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
 func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
 	bs, fnerr := iv.MarshalBinary()
 	bs, fnerr := iv.MarshalBinary()
-	f.e.marshal(bs, fnerr, false, c_RAW)
+	f.e.marshal(bs, fnerr, false, cRAW)
 }
 }
 
 
 // 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) {
-	f.e.rawBytes(iv)
+func (f genHelperEncoder) EncRaw(iv Raw) { f.e.rawBytes(iv) }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: builtin no longer supported - so we make this method a no-op,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperEncoder) TimeRtidIfBinc() (v uintptr) { return }
+
+// func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
+// 	if _, ok := f.e.hh.(*BincHandle); ok {
+// 		return timeTypId
+// 	}
+// }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) I2Rtid(v interface{}) uintptr {
+	return i2rtid(v)
 }
 }
 
 
 // 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) TimeRtidIfBinc() uintptr {
-	if _, ok := f.e.hh.(*BincHandle); ok {
-		return timeTypId
-	}
-	return 0
+func (f genHelperEncoder) Extension(rtid uintptr) (xfn *extTypeTagFn) {
+	return f.e.h.getExt(rtid)
 }
 }
 
 
 // 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 {
-	return f.e.cf.js
+func (f genHelperEncoder) EncExtension(v interface{}, xfFn *extTypeTagFn) {
+	f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
 }
 }
 
 
 // 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*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
 func (f genHelperEncoder) HasExtensions() bool {
 func (f genHelperEncoder) HasExtensions() bool {
 	return len(f.e.h.extHandle) != 0
 	return len(f.e.h.extHandle) != 0
 }
 }
 
 
 // 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*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
 func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
 func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
-	rt := reflect.TypeOf(v)
-	if rt.Kind() == reflect.Ptr {
-		rt = rt.Elem()
-	}
-	rtid := rt2id(rt)
-	if xfFn := f.e.h.getExt(rtid); xfFn != nil {
+	if xfFn := f.e.h.getExt(i2rtid(v)); xfFn != nil {
 		f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
 		f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
 		return true
 		return true
 	}
 	}
@@ -144,15 +202,18 @@ func (f genHelperDecoder) DecBinary() bool {
 }
 }
 
 
 // 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) DecSwallow() {
-	f.d.swallow()
-}
+func (f genHelperDecoder) DecSwallow() { f.d.swallow() }
 
 
 // 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) DecScratchBuffer() []byte {
 func (f genHelperDecoder) DecScratchBuffer() []byte {
 	return f.d.b[:]
 	return f.d.b[:]
 }
 }
 
 
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
+	return &f.d.b
+}
+
 // 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")
@@ -160,7 +221,7 @@ func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
 	if chkPtr {
 	if chkPtr {
 		rv = f.d.ensureDecodeable(rv)
 		rv = f.d.ensureDecodeable(rv)
 	}
 	}
-	f.d.decodeValue(rv, nil, false, false)
+	f.d.decodeValue(rv, nil, false)
 	// f.d.decodeValueFallback(rv)
 	// f.d.decodeValueFallback(rv)
 }
 }
 
 
@@ -206,17 +267,21 @@ 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 {
-	return f.d.rawBytes()
-}
+func (f genHelperDecoder) DecRaw() []byte { 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*
-func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
-	if _, ok := f.d.hh.(*BincHandle); ok {
-		return timeTypId
-	}
-	return 0
-}
+//
+// Deprecated: builtin no longer supported - so we make this method a no-op,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperDecoder) TimeRtidIfBinc() (v uintptr) { return }
+
+// func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
+// 	// Note: builtin is no longer supported - so make this a no-op
+// 	if _, ok := f.d.hh.(*BincHandle); ok {
+// 		return timeTypId
+// 	}
+// 	return 0
+// }
 
 
 // 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) IsJSONHandle() bool {
 func (f genHelperDecoder) IsJSONHandle() bool {
@@ -224,15 +289,34 @@ func (f genHelperDecoder) IsJSONHandle() bool {
 }
 }
 
 
 // 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) I2Rtid(v interface{}) uintptr {
+	return i2rtid(v)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) Extension(rtid uintptr) (xfn *extTypeTagFn) {
+	return f.d.h.getExt(rtid)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecExtension(v interface{}, xfFn *extTypeTagFn) {
+	f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
 func (f genHelperDecoder) HasExtensions() bool {
 func (f genHelperDecoder) HasExtensions() bool {
 	return len(f.d.h.extHandle) != 0
 	return len(f.d.h.extHandle) != 0
 }
 }
 
 
 // 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*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
 func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
 func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
-	rt := reflect.TypeOf(v).Elem()
-	rtid := rt2id(rt)
-	if xfFn := f.d.h.getExt(rtid); xfFn != nil {
+	if xfFn := f.d.h.getExt(i2rtid(v)); xfFn != nil {
 		f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
 		f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
 		return true
 		return true
 	}
 	}
@@ -245,6 +329,7 @@ func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
 }
 }
 
 
 // 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) StringView(v []byte) string {
-	return stringView(v)
-}
+//
+// Deprecated: no longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperDecoder) StringView(v []byte) string { return stringView(v) }

+ 43 - 11
vendor/github.com/ugorji/go/codec/gen.generated.go

@@ -1,3 +1,5 @@
+// +build codecgen.exec
+
 // 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.
 
 
@@ -62,13 +64,14 @@ if {{var "l"}} == 0 {
 	} else if len({{var "v"}}) != 0 {
 	} else if len({{var "v"}}) != 0 {
 		{{var "v"}} = {{var "v"}}[:0]
 		{{var "v"}} = {{var "v"}}[:0]
 		{{var "c"}} = true
 		{{var "c"}} = true
-	} {{end}} {{if isChan }}if {{var "v"}} == nil {
+	} {{else if isChan }}if {{var "v"}} == nil {
 		{{var "v"}} = make({{ .CTyp }}, 0)
 		{{var "v"}} = make({{ .CTyp }}, 0)
 		{{var "c"}} = true
 		{{var "c"}} = true
 	} {{end}}
 	} {{end}}
 } else {
 } else {
 	{{var "hl"}} := {{var "l"}} > 0
 	{{var "hl"}} := {{var "l"}} > 0
-	var {{var "rl"}} int; _ =  {{var "rl"}}
+	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 }})
@@ -86,25 +89,26 @@ if {{var "l"}} == 0 {
 	var {{var "j"}} int 
 	var {{var "j"}} int 
     // var {{var "dn"}} bool 
     // 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 not isArray}} if {{var "j"}} == 0 && len({{var "v"}}) == 0 {
+		{{if not isArray}} if {{var "j"}} == 0 && {{var "v"}} == nil {
 			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 {
-				{{var "rl"}} = 8
+				{{var "rl"}} = {{if isSlice}}8{{else if isChan}}64{{end}}
 			}
 			}
-			{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
+			{{var "v"}} = make({{if isSlice}}[]{{ .Typ }}{{else if isChan}}{{.CTyp}}{{end}}, {{var "rl"}})
 			{{var "c"}} = true 
 			{{var "c"}} = true 
 		}{{end}}
 		}{{end}}
 		{{var "h"}}.ElemContainerState({{var "j"}})
 		{{var "h"}}.ElemContainerState({{var "j"}})
-        // {{var "dn"}} = r.TryDecodeAsNil()
-        {{if isChan}}{{ $x := printf "%[1]vv%[2]v" .TempVar .Rand }}var {{var $x}} {{ .Typ }}
+        {{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */}}
+        {{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
 		{{ decLineVar $x }}
 		{{ decLineVar $x }}
 		{{var "v"}} <- {{ $x }}
 		{{var "v"}} <- {{ $x }}
-        {{else}}
-		// if indefinite, etc, then expand the slice if necessary
+        // println(">>>> sending ", {{ $x }}, " into ", {{var "v"}}) // TODO: remove this
+        {{else}}{{/* // 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
 			{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
 			{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
 			{{end}}
 			{{end}}
 		}
 		}
@@ -127,6 +131,34 @@ if {{var "l"}} == 0 {
 {{if not isArray }}if {{var "c"}} { 
 {{if not isArray }}if {{var "c"}} { 
 	*{{ .Varname }} = {{var "v"}}
 	*{{ .Varname }} = {{var "v"}}
 }{{end}}
 }{{end}}
-
 `
 `
 
 
+const genEncChanTmpl = `
+{{.Label}}:
+switch timeout{{.Sfx}} :=  z.EncBasicHandle().ChanRecvTimeout; {
+case timeout{{.Sfx}} == 0: // only consume available
+	for {
+		select {
+		case b{{.Sfx}} := <-{{.Chan}}:
+			{{ .Slice }} = append({{.Slice}}, b{{.Sfx}})
+		default:
+			break {{.Label}}
+		}
+	}
+case timeout{{.Sfx}} > 0: // consume until timeout
+	tt{{.Sfx}} := time.NewTimer(timeout{{.Sfx}})
+	for {
+		select {
+		case b{{.Sfx}} := <-{{.Chan}}:
+			{{.Slice}} = append({{.Slice}}, b{{.Sfx}})
+		case <-tt{{.Sfx}}.C:
+			// close(tt.C)
+			break {{.Label}}
+		}
+	}
+default: // consume until close
+	for b{{.Sfx}} := range {{.Chan}} {
+		{{.Slice}} = append({{.Slice}}, b{{.Sfx}})
+	}
+}
+`

File diff suppressed because it is too large
+ 407 - 278
vendor/github.com/ugorji/go/codec/gen.go


+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_arrayof_gte_go15.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 go1.5
 // +build go1.5

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_arrayof_lt_go15.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 !go1.5
 // +build !go1.5

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_makemap_gte_go19.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 go1.9
 // +build go1.9

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_makemap_lt_go19.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 !go1.9
 // +build !go1.9

+ 8 - 0
vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go

@@ -0,0 +1,8 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.10
+
+package codec
+
+const allowSetUnexportedEmbeddedPtr = false

+ 8 - 0
vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go

@@ -0,0 +1,8 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.10
+
+package codec
+
+const allowSetUnexportedEmbeddedPtr = true

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 !go1.4
 // +build !go1.4

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go15.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 go1.5,!go1.6
 // +build go1.5,!go1.6

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go16.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 go1.6,!go1.7
 // +build go1.6,!go1.7

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_vendor_gte_go17.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 go1.7
 // +build go1.7

+ 1 - 1
vendor/github.com/ugorji/go/codec/goversion_vendor_lt_go15.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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 !go1.5
 // +build !go1.5

File diff suppressed because it is too large
+ 407 - 333
vendor/github.com/ugorji/go/codec/helper.go


+ 9 - 109
vendor/github.com/ugorji/go/codec/helper_internal.go

@@ -6,74 +6,6 @@ package codec
 // All non-std package dependencies live in this file,
 // All non-std package dependencies live in this file,
 // so porting to different environment is easy (just update functions).
 // so porting to different environment is easy (just update functions).
 
 
-import (
-	"errors"
-	"fmt"
-	"math"
-	"reflect"
-)
-
-func panicValToErr(panicVal interface{}, err *error) {
-	if panicVal == nil {
-		return
-	}
-	// case nil
-	switch xerr := panicVal.(type) {
-	case error:
-		*err = xerr
-	case string:
-		*err = errors.New(xerr)
-	default:
-		*err = fmt.Errorf("%v", panicVal)
-	}
-	return
-}
-
-func hIsEmptyValue(v reflect.Value, deref, checkStruct bool) bool {
-	switch v.Kind() {
-	case reflect.Invalid:
-		return true
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		if deref {
-			if v.IsNil() {
-				return true
-			}
-			return hIsEmptyValue(v.Elem(), deref, checkStruct)
-		} else {
-			return v.IsNil()
-		}
-	case reflect.Struct:
-		if !checkStruct {
-			return false
-		}
-		// return true if all fields are empty. else return false.
-		// we cannot use equality check, because some fields may be maps/slices/etc
-		// and consequently the structs are not comparable.
-		// return v.Interface() == reflect.Zero(v.Type()).Interface()
-		for i, n := 0, v.NumField(); i < n; i++ {
-			if !hIsEmptyValue(v.Field(i), deref, checkStruct) {
-				return false
-			}
-		}
-		return true
-	}
-	return false
-}
-
-func isEmptyValue(v reflect.Value, deref, checkStruct bool) bool {
-	return hIsEmptyValue(v, deref, checkStruct)
-}
-
 func pruneSignExt(v []byte, pos bool) (n int) {
 func pruneSignExt(v []byte, pos bool) (n int) {
 	if len(v) < 2 {
 	if len(v) < 2 {
 	} else if pos && v[0] == 0 {
 	} else if pos && v[0] == 0 {
@@ -86,37 +18,6 @@ func pruneSignExt(v []byte, pos bool) (n int) {
 	return
 	return
 }
 }
 
 
-func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) {
-	if typ == nil {
-		return
-	}
-	rt := typ
-	// The type might be a pointer and we need to keep
-	// dereferencing to the base type until we find an implementation.
-	for {
-		if rt.Implements(iTyp) {
-			return true, indir
-		}
-		if p := rt; p.Kind() == reflect.Ptr {
-			indir++
-			if indir >= math.MaxInt8 { // insane number of indirections
-				return false, 0
-			}
-			rt = p.Elem()
-			continue
-		}
-		break
-	}
-	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
-	if typ.Kind() != reflect.Ptr {
-		// Not a pointer, but does the pointer work?
-		if reflect.PtrTo(typ).Implements(iTyp) {
-			return true, -1
-		}
-	}
-	return false, 0
-}
-
 // validate that this function is correct ...
 // validate that this function is correct ...
 // culled from OGRE (Object-Oriented Graphics Rendering Engine)
 // culled from OGRE (Object-Oriented Graphics Rendering Engine)
 // function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
 // function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
@@ -129,21 +30,20 @@ func halfFloatToFloatBits(yy uint16) (d uint32) {
 	if e == 0 {
 	if e == 0 {
 		if m == 0 { // plu or minus 0
 		if m == 0 { // plu or minus 0
 			return s << 31
 			return s << 31
-		} else { // Denormalized number -- renormalize it
-			for (m & 0x00000400) == 0 {
-				m <<= 1
-				e -= 1
-			}
-			e += 1
-			const zz uint32 = 0x0400
-			m &= ^zz
 		}
 		}
+		// Denormalized number -- renormalize it
+		for (m & 0x00000400) == 0 {
+			m <<= 1
+			e -= 1
+		}
+		e += 1
+		const zz uint32 = 0x0400
+		m &= ^zz
 	} else if e == 31 {
 	} else if e == 31 {
 		if m == 0 { // Inf
 		if m == 0 { // Inf
 			return (s << 31) | 0x7f800000
 			return (s << 31) | 0x7f800000
-		} else { // NaN
-			return (s << 31) | 0x7f800000 | (m << 13)
 		}
 		}
+		return (s << 31) | 0x7f800000 | (m << 13) // NaN
 	}
 	}
 	e = e + (127 - 15)
 	e = e + (127 - 15)
 	m = m << 13
 	m = m << 13

+ 155 - 39
vendor/github.com/ugorji/go/codec/helper_not_unsafe.go

@@ -1,6 +1,6 @@
 // +build !go1.7 safe appengine
 // +build !go1.7 safe appengine
 
 
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 package codec
 package codec
@@ -8,8 +8,11 @@ package codec
 import (
 import (
 	"reflect"
 	"reflect"
 	"sync/atomic"
 	"sync/atomic"
+	"time"
 )
 )
 
 
+const safeMode = true
+
 // stringView returns a view of the []byte as a string.
 // stringView returns a view of the []byte as a string.
 // In unsafe mode, it doesn't incur allocation and copying caused by conversion.
 // In unsafe mode, it doesn't incur allocation and copying caused by conversion.
 // In regular safe mode, it is an allocation and copy.
 // In regular safe mode, it is an allocation and copy.
@@ -31,28 +34,11 @@ func bytesView(v string) []byte {
 }
 }
 
 
 func definitelyNil(v interface{}) bool {
 func definitelyNil(v interface{}) bool {
+	// this is a best-effort option.
+	// We just return false, so we don't unnecessarily incur the cost of reflection this early.
 	return false
 	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.
-// //
-// // Usage: call this at point where done with the bytes view.
-// func keepAlive4BytesView(v string) {}
-
-// // keepAlive4BytesView maintains a reference to the input parameter for stringView.
-// //
-// // Usage: call this at point where done with the string view.
-// func keepAlive4StringView(v []byte) {}
-
 func rv2i(rv reflect.Value) interface{} {
 func rv2i(rv reflect.Value) interface{} {
 	return rv.Interface()
 	return rv.Interface()
 }
 }
@@ -65,28 +51,62 @@ func rv2rtid(rv reflect.Value) uintptr {
 	return reflect.ValueOf(rv.Type()).Pointer()
 	return reflect.ValueOf(rv.Type()).Pointer()
 }
 }
 
 
+func i2rtid(i interface{}) uintptr {
+	return reflect.ValueOf(reflect.TypeOf(i)).Pointer()
+}
+
+// --------------------------
+
+func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
+	switch v.Kind() {
+	case reflect.Invalid:
+		return true
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		if deref {
+			if v.IsNil() {
+				return true
+			}
+			return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
+		}
+		return v.IsNil()
+	case reflect.Struct:
+		return isEmptyStruct(v, tinfos, deref, checkStruct)
+	}
+	return false
+}
+
 // --------------------------
 // --------------------------
 // type ptrToRvMap struct{}
 // type ptrToRvMap struct{}
 
 
-// func (_ *ptrToRvMap) init() {}
-// func (_ *ptrToRvMap) get(i interface{}) reflect.Value {
+// func (*ptrToRvMap) init() {}
+// func (*ptrToRvMap) get(i interface{}) reflect.Value {
 // 	return reflect.ValueOf(i).Elem()
 // 	return reflect.ValueOf(i).Elem()
 // }
 // }
 
 
 // --------------------------
 // --------------------------
-type atomicTypeInfoSlice struct {
+type atomicTypeInfoSlice struct { // expected to be 2 words
 	v atomic.Value
 	v atomic.Value
 }
 }
 
 
-func (x *atomicTypeInfoSlice) load() *[]rtid2ti {
+func (x *atomicTypeInfoSlice) load() []rtid2ti {
 	i := x.v.Load()
 	i := x.v.Load()
 	if i == nil {
 	if i == nil {
 		return nil
 		return nil
 	}
 	}
-	return i.(*[]rtid2ti)
+	return i.([]rtid2ti)
 }
 }
 
 
-func (x *atomicTypeInfoSlice) store(p *[]rtid2ti) {
+func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
 	x.v.Store(p)
 	x.v.Store(p)
 }
 }
 
 
@@ -103,54 +123,150 @@ func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
 	rv.SetBool(d.d.DecodeBool())
 	rv.SetBool(d.d.DecodeBool())
 }
 }
 
 
+func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
+	rv.Set(reflect.ValueOf(d.d.DecodeTime()))
+}
+
 func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
-	rv.SetFloat(d.d.DecodeFloat(true))
+	fv := d.d.DecodeFloat64()
+	if chkOvf.Float32(fv) {
+		d.errorf("float32 overflow: %v", fv)
+	}
+	rv.SetFloat(fv)
 }
 }
 
 
 func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
-	rv.SetFloat(d.d.DecodeFloat(false))
+	rv.SetFloat(d.d.DecodeFloat64())
 }
 }
 
 
 func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
-	rv.SetInt(d.d.DecodeInt(intBitsize))
+	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
 }
 }
 
 
 func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
-	rv.SetInt(d.d.DecodeInt(8))
+	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 8))
 }
 }
 
 
 func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
-	rv.SetInt(d.d.DecodeInt(16))
+	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 16))
 }
 }
 
 
 func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
-	rv.SetInt(d.d.DecodeInt(32))
+	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 32))
 }
 }
 
 
 func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
-	rv.SetInt(d.d.DecodeInt(64))
+	rv.SetInt(d.d.DecodeInt64())
 }
 }
 
 
 func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
-	rv.SetUint(d.d.DecodeUint(uintBitsize))
+	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
 }
 }
 
 
 func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
-	rv.SetUint(d.d.DecodeUint(uintBitsize))
+	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
 }
 }
 
 
 func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
-	rv.SetUint(d.d.DecodeUint(8))
+	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 8))
 }
 }
 
 
 func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
-	rv.SetUint(d.d.DecodeUint(16))
+	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 16))
 }
 }
 
 
 func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
-	rv.SetUint(d.d.DecodeUint(32))
+	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 32))
 }
 }
 
 
 func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
-	rv.SetUint(d.d.DecodeUint(64))
+	rv.SetUint(d.d.DecodeUint64())
 }
 }
+
+// ----------------
+
+func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeBool(rv.Bool())
+}
+
+func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeTime(rv2i(rv).(time.Time))
+}
+
+func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeString(cUTF8, rv.String())
+}
+
+func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeFloat64(rv.Float())
+}
+
+func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeFloat32(float32(rv.Float()))
+}
+
+func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+	e.e.EncodeUint(rv.Uint())
+}
+
+// // keepAlive4BytesView maintains a reference to the input parameter for bytesView.
+// //
+// // Usage: call this at point where done with the bytes view.
+// func keepAlive4BytesView(v string) {}
+
+// // keepAlive4BytesView maintains a reference to the input parameter for stringView.
+// //
+// // Usage: call this at point where done with the string view.
+// func keepAlive4StringView(v []byte) {}
+
+// func definitelyNil(v interface{}) bool {
+// 	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
+// 	}
+// }

+ 280 - 59
vendor/github.com/ugorji/go/codec/helper_unsafe.go

@@ -2,7 +2,7 @@
 // +build !appengine
 // +build !appengine
 // +build go1.7
 // +build go1.7
 
 
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 package codec
 package codec
@@ -10,6 +10,7 @@ package codec
 import (
 import (
 	"reflect"
 	"reflect"
 	"sync/atomic"
 	"sync/atomic"
+	"time"
 	"unsafe"
 	"unsafe"
 )
 )
 
 
@@ -18,15 +19,16 @@ import (
 
 
 // var zeroRTv [4]uintptr
 // var zeroRTv [4]uintptr
 
 
+const safeMode = false
 const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
 const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
 
 
 type unsafeString struct {
 type unsafeString struct {
-	Data uintptr
+	Data unsafe.Pointer
 	Len  int
 	Len  int
 }
 }
 
 
 type unsafeSlice struct {
 type unsafeSlice struct {
-	Data uintptr
+	Data unsafe.Pointer
 	Len  int
 	Len  int
 	Cap  int
 	Cap  int
 }
 }
@@ -46,50 +48,49 @@ func stringView(v []byte) string {
 	if len(v) == 0 {
 	if len(v) == 0 {
 		return ""
 		return ""
 	}
 	}
-
 	bx := (*unsafeSlice)(unsafe.Pointer(&v))
 	bx := (*unsafeSlice)(unsafe.Pointer(&v))
-	sx := unsafeString{bx.Data, bx.Len}
-	return *(*string)(unsafe.Pointer(&sx))
+	return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
 }
 }
 
 
 func bytesView(v string) []byte {
 func bytesView(v string) []byte {
 	if len(v) == 0 {
 	if len(v) == 0 {
 		return zeroByteSlice
 		return zeroByteSlice
 	}
 	}
-
 	sx := (*unsafeString)(unsafe.Pointer(&v))
 	sx := (*unsafeString)(unsafe.Pointer(&v))
-	bx := unsafeSlice{sx.Data, sx.Len, sx.Len}
-	return *(*[]byte)(unsafe.Pointer(&bx))
+	return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
 }
 }
 
 
 func definitelyNil(v interface{}) bool {
 func definitelyNil(v interface{}) bool {
-	return (*unsafeIntf)(unsafe.Pointer(&v)).word == nil
+	// There is no global way of checking if an interface is nil.
+	// For true references (map, ptr, func, chan), you can just look
+	// at the word of the interface. However, for slices, you have to dereference
+	// the word, and get a pointer to the 3-word interface value.
+	//
+	// However, the following are cheap calls
+	// - TypeOf(interface): cheap 2-line call.
+	// - ValueOf(interface{}): expensive
+	// - type.Kind: cheap call through an interface
+	// - Value.Type(): cheap call
+	//                 except it's a method value (e.g. r.Read, which implies that it is a Func)
+
+	return ((*unsafeIntf)(unsafe.Pointer(&v))).word == nil
 }
 }
 
 
-// func keepAlive4BytesView(v string) {
-// 	runtime.KeepAlive(v)
-// }
-
-// func keepAlive4StringView(v []byte) {
-// 	runtime.KeepAlive(v)
-// }
-
-// TODO: consider a more generally-known optimization for reflect.Value ==> Interface
-//
-// Currently, we use this fragile method that taps into implememtation details from
-// the source go stdlib reflect/value.go,
-// and trims the implementation.
 func rv2i(rv reflect.Value) interface{} {
 func rv2i(rv reflect.Value) interface{} {
-	if false {
-		return rv.Interface()
-	}
+	// TODO: consider a more generally-known optimization for reflect.Value ==> Interface
+	//
+	// Currently, we use this fragile method that taps into implememtation details from
+	// the source go stdlib reflect/value.go, and trims the implementation.
+
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	// references that are single-words (map, ptr) may be double-referenced as flagIndir
-	kk := urv.flag & (1<<5 - 1)
-	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}))
+	// true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
+	var ptr unsafe.Pointer
+	if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
+		ptr = *(*unsafe.Pointer)(urv.ptr)
+	} else {
+		ptr = urv.ptr
 	}
 	}
-	return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+	return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
 }
 }
 
 
 func rt2id(rt reflect.Type) uintptr {
 func rt2id(rt reflect.Type) uintptr {
@@ -100,32 +101,111 @@ func rv2rtid(rv reflect.Value) uintptr {
 	return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
 	return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
 }
 }
 
 
-// func rv0t(rt reflect.Type) reflect.Value {
-// 	ut := (*unsafeIntf)(unsafe.Pointer(&rt))
-// 	// we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
-// 	uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
-// 	return *(*reflect.Value)(unsafe.Pointer(&uv})
-// }
+func i2rtid(i interface{}) uintptr {
+	return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
+}
+
+// --------------------------
+
+func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
+	urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
+	if urv.flag == 0 {
+		return true
+	}
+	switch v.Kind() {
+	case reflect.Invalid:
+		return true
+	case reflect.String:
+		return (*unsafeString)(urv.ptr).Len == 0
+	case reflect.Slice:
+		return (*unsafeSlice)(urv.ptr).Len == 0
+	case reflect.Bool:
+		return !*(*bool)(urv.ptr)
+	case reflect.Int:
+		return *(*int)(urv.ptr) == 0
+	case reflect.Int8:
+		return *(*int8)(urv.ptr) == 0
+	case reflect.Int16:
+		return *(*int16)(urv.ptr) == 0
+	case reflect.Int32:
+		return *(*int32)(urv.ptr) == 0
+	case reflect.Int64:
+		return *(*int64)(urv.ptr) == 0
+	case reflect.Uint:
+		return *(*uint)(urv.ptr) == 0
+	case reflect.Uint8:
+		return *(*uint8)(urv.ptr) == 0
+	case reflect.Uint16:
+		return *(*uint16)(urv.ptr) == 0
+	case reflect.Uint32:
+		return *(*uint32)(urv.ptr) == 0
+	case reflect.Uint64:
+		return *(*uint64)(urv.ptr) == 0
+	case reflect.Uintptr:
+		return *(*uintptr)(urv.ptr) == 0
+	case reflect.Float32:
+		return *(*float32)(urv.ptr) == 0
+	case reflect.Float64:
+		return *(*float64)(urv.ptr) == 0
+	case reflect.Interface:
+		isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
+		if deref {
+			if isnil {
+				return true
+			}
+			return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
+		}
+		return isnil
+	case reflect.Ptr:
+		// isnil := urv.ptr == nil (not sufficient, as a pointer value encodes the type)
+		isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
+		if deref {
+			if isnil {
+				return true
+			}
+			return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
+		}
+		return isnil
+	case reflect.Struct:
+		return isEmptyStruct(v, tinfos, deref, checkStruct)
+	case reflect.Map, reflect.Array, reflect.Chan:
+		return v.Len() == 0
+	}
+	return false
+}
 
 
 // --------------------------
 // --------------------------
-type atomicTypeInfoSlice struct {
-	v unsafe.Pointer
+
+// atomicTypeInfoSlice contains length and pointer to the array for a slice.
+// It is expected to be 2 words.
+//
+// Previously, we atomically loaded and stored the length and array pointer separately,
+// which could lead to some races.
+// We now just atomically store and load the pointer to the value directly.
+
+type atomicTypeInfoSlice struct { // expected to be 2 words
+	l int            // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
+	v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
 }
 }
 
 
-func (x *atomicTypeInfoSlice) load() *[]rtid2ti {
-	return (*[]rtid2ti)(atomic.LoadPointer(&x.v))
+func (x *atomicTypeInfoSlice) load() []rtid2ti {
+	xp := unsafe.Pointer(x)
+	x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
+	if x2.l == 0 {
+		return nil
+	}
+	return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
 }
 }
 
 
-func (x *atomicTypeInfoSlice) store(p *[]rtid2ti) {
-	atomic.StorePointer(&x.v, unsafe.Pointer(p))
+func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
+	s := (*unsafeSlice)(unsafe.Pointer(&p))
+	xp := unsafe.Pointer(x)
+	atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
 }
 }
 
 
 // --------------------------
 // --------------------------
 func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	// if urv.flag&unsafeFlagIndir != 0 {
-	// 	urv.ptr = *(*unsafe.Pointer)(urv.ptr)
-	// }
 	*(*[]byte)(urv.ptr) = d.rawBytes()
 	*(*[]byte)(urv.ptr) = d.rawBytes()
 }
 }
 
 
@@ -139,73 +219,214 @@ func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
 	*(*bool)(urv.ptr) = d.d.DecodeBool()
 	*(*bool)(urv.ptr) = d.d.DecodeBool()
 }
 }
 
 
+func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
+	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	*(*time.Time)(urv.ptr) = d.d.DecodeTime()
+}
+
 func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
 func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+	fv := d.d.DecodeFloat64()
+	if chkOvf.Float32(fv) {
+		d.errorf("float32 overflow: %v", fv)
+	}
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
-	*(*float32)(urv.ptr) = float32(d.d.DecodeFloat(true))
+	*(*float32)(urv.ptr) = float32(fv)
 }
 }
 
 
 func (d *Decoder) kFloat64(f *codecFnInfo, 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) = d.d.DecodeFloat(false)
+	*(*float64)(urv.ptr) = d.d.DecodeFloat64()
 }
 }
 
 
 func (d *Decoder) kInt(f *codecFnInfo, 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(d.d.DecodeInt(intBitsize))
+	*(*int)(urv.ptr) = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
 }
 }
 
 
 func (d *Decoder) kInt8(f *codecFnInfo, 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(d.d.DecodeInt(8))
+	*(*int8)(urv.ptr) = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
 }
 }
 
 
 func (d *Decoder) kInt16(f *codecFnInfo, 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(d.d.DecodeInt(16))
+	*(*int16)(urv.ptr) = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
 }
 }
 
 
 func (d *Decoder) kInt32(f *codecFnInfo, 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(d.d.DecodeInt(32))
+	*(*int32)(urv.ptr) = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
 }
 }
 
 
 func (d *Decoder) kInt64(f *codecFnInfo, 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) = d.d.DecodeInt(64)
+	*(*int64)(urv.ptr) = d.d.DecodeInt64()
 }
 }
 
 
 func (d *Decoder) kUint(f *codecFnInfo, 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(d.d.DecodeUint(uintBitsize))
+	*(*uint)(urv.ptr) = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
 }
 }
 
 
 func (d *Decoder) kUintptr(f *codecFnInfo, 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(d.d.DecodeUint(uintBitsize))
+	*(*uintptr)(urv.ptr) = uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
 }
 }
 
 
 func (d *Decoder) kUint8(f *codecFnInfo, 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(d.d.DecodeUint(8))
+	*(*uint8)(urv.ptr) = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
 }
 }
 
 
 func (d *Decoder) kUint16(f *codecFnInfo, 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(d.d.DecodeUint(16))
+	*(*uint16)(urv.ptr) = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
 }
 }
 
 
 func (d *Decoder) kUint32(f *codecFnInfo, 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(d.d.DecodeUint(32))
+	*(*uint32)(urv.ptr) = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
 }
 }
 
 
 func (d *Decoder) kUint64(f *codecFnInfo, 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) = d.d.DecodeUint(64)
+	*(*uint64)(urv.ptr) = d.d.DecodeUint64()
+}
+
+// ------------
+
+func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeBool(*(*bool)(v.ptr))
+}
+
+func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeTime(*(*time.Time)(v.ptr))
+}
+
+func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeString(cUTF8, *(*string)(v.ptr))
+}
+
+func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeFloat64(*(*float64)(v.ptr))
+}
+
+func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeFloat32(*(*float32)(v.ptr))
+}
+
+func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeInt(int64(*(*int)(v.ptr)))
+}
+
+func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeInt(int64(*(*int8)(v.ptr)))
+}
+
+func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeInt(int64(*(*int16)(v.ptr)))
+}
+
+func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeInt(int64(*(*int32)(v.ptr)))
+}
+
+func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeInt(int64(*(*int64)(v.ptr)))
+}
+
+func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
+}
+
+func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
+}
+
+func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
+}
+
+func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
+}
+
+func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
+}
+
+func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+	v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+	e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
 }
 }
 
 
 // ------------
 // ------------
 
 
+// func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
+// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+// 	// if urv.flag&unsafeFlagIndir != 0 {
+// 	// 	urv.ptr = *(*unsafe.Pointer)(urv.ptr)
+// 	// }
+// 	*(*[]byte)(urv.ptr) = d.rawBytes()
+// }
+
+// func rv0t(rt reflect.Type) reflect.Value {
+// 	ut := (*unsafeIntf)(unsafe.Pointer(&rt))
+// 	// we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
+// 	uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
+// 	return *(*reflect.Value)(unsafe.Pointer(&uv})
+// }
+
+// func rv2i(rv reflect.Value) interface{} {
+// 	urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+// 	// true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
+// 	var ptr unsafe.Pointer
+// 	// kk := reflect.Kind(urv.flag & (1<<5 - 1))
+// 	// if (kk == reflect.Map || kk == reflect.Ptr || kk == reflect.Chan || kk == reflect.Func) && urv.flag&unsafeFlagIndir != 0 {
+// 	if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
+// 		ptr = *(*unsafe.Pointer)(urv.ptr)
+// 	} else {
+// 		ptr = urv.ptr
+// 	}
+// 	return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
+// 	// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
+// 	// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// }
+
+// func definitelyNil(v interface{}) bool {
+// 	var ui *unsafeIntf = (*unsafeIntf)(unsafe.Pointer(&v))
+// 	if ui.word == nil {
+// 		return true
+// 	}
+// 	var tk = reflect.TypeOf(v).Kind()
+// 	return (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.word) == nil
+// 	fmt.Printf(">>>> definitely nil: isnil: %v, TYPE: \t%T, word: %v, *word: %v, type: %v, nil: %v\n",
+// 	v == nil, v, word, *((*unsafe.Pointer)(word)), ui.typ, nil)
+// }
+
+// func keepAlive4BytesView(v string) {
+// 	runtime.KeepAlive(v)
+// }
+
+// func keepAlive4StringView(v []byte) {
+// 	runtime.KeepAlive(v)
+// }
+
 // 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)
 // 	// var i interface{} = rt
 // 	// var i interface{} = rt

File diff suppressed because it is too large
+ 435 - 324
vendor/github.com/ugorji/go/codec/json.go


+ 298 - 105
vendor/github.com/ugorji/go/codec/msgpack.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 /*
 /*
@@ -15,8 +15,8 @@ For compatibility with behaviour of msgpack-c reference implementation:
   - Go intX (<0)
   - Go intX (<0)
        IS ENCODED AS
        IS ENCODED AS
     msgpack -ve fixnum, signed
     msgpack -ve fixnum, signed
-
 */
 */
+
 package codec
 package codec
 
 
 import (
 import (
@@ -25,6 +25,7 @@ import (
 	"math"
 	"math"
 	"net/rpc"
 	"net/rpc"
 	"reflect"
 	"reflect"
+	"time"
 )
 )
 
 
 const (
 const (
@@ -78,6 +79,89 @@ const (
 	mpNegFixNumMax = 0xff
 	mpNegFixNumMax = 0xff
 )
 )
 
 
+var mpTimeExtTag int8 = -1
+var mpTimeExtTagU = uint8(mpTimeExtTag)
+
+// var mpdesc = map[byte]string{
+// 	mpPosFixNumMin: "PosFixNumMin",
+// 	mpPosFixNumMax: "PosFixNumMax",
+// 	mpFixMapMin:    "FixMapMin",
+// 	mpFixMapMax:    "FixMapMax",
+// 	mpFixArrayMin:  "FixArrayMin",
+// 	mpFixArrayMax:  "FixArrayMax",
+// 	mpFixStrMin:    "FixStrMin",
+// 	mpFixStrMax:    "FixStrMax",
+// 	mpNil:          "Nil",
+// 	mpFalse:        "False",
+// 	mpTrue:         "True",
+// 	mpFloat:        "Float",
+// 	mpDouble:       "Double",
+// 	mpUint8:        "Uint8",
+// 	mpUint16:       "Uint16",
+// 	mpUint32:       "Uint32",
+// 	mpUint64:       "Uint64",
+// 	mpInt8:         "Int8",
+// 	mpInt16:        "Int16",
+// 	mpInt32:        "Int32",
+// 	mpInt64:        "Int64",
+// 	mpBin8:         "Bin8",
+// 	mpBin16:        "Bin16",
+// 	mpBin32:        "Bin32",
+// 	mpExt8:         "Ext8",
+// 	mpExt16:        "Ext16",
+// 	mpExt32:        "Ext32",
+// 	mpFixExt1:      "FixExt1",
+// 	mpFixExt2:      "FixExt2",
+// 	mpFixExt4:      "FixExt4",
+// 	mpFixExt8:      "FixExt8",
+// 	mpFixExt16:     "FixExt16",
+// 	mpStr8:         "Str8",
+// 	mpStr16:        "Str16",
+// 	mpStr32:        "Str32",
+// 	mpArray16:      "Array16",
+// 	mpArray32:      "Array32",
+// 	mpMap16:        "Map16",
+// 	mpMap32:        "Map32",
+// 	mpNegFixNumMin: "NegFixNumMin",
+// 	mpNegFixNumMax: "NegFixNumMax",
+// }
+
+func mpdesc(bd byte) string {
+	switch bd {
+	case mpNil:
+		return "nil"
+	case mpFalse:
+		return "false"
+	case mpTrue:
+		return "true"
+	case mpFloat, mpDouble:
+		return "float"
+	case mpUint8, mpUint16, mpUint32, mpUint64:
+		return "uint"
+	case mpInt8, mpInt16, mpInt32, mpInt64:
+		return "int"
+	default:
+		switch {
+		case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax:
+			return "int"
+		case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax:
+			return "int"
+		case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax:
+			return "string|bytes"
+		case bd == mpBin8, bd == mpBin16, bd == mpBin32:
+			return "bytes"
+		case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
+			return "array"
+		case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax:
+			return "map"
+		case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
+			return "ext"
+		default:
+			return "unknown"
+		}
+	}
+}
+
 // MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec
 // MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec
 // that the backend RPC service takes multiple arguments, which have been arranged
 // that the backend RPC service takes multiple arguments, which have been arranged
 // in sequence in the slice.
 // in sequence in the slice.
@@ -94,10 +178,18 @@ type msgpackContainerType struct {
 }
 }
 
 
 var (
 var (
-	msgpackContainerStr  = msgpackContainerType{32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false}
-	msgpackContainerBin  = msgpackContainerType{0, 0, mpBin8, mpBin16, mpBin32, false, true, true}
-	msgpackContainerList = msgpackContainerType{16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false}
-	msgpackContainerMap  = msgpackContainerType{16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false}
+	msgpackContainerStr = msgpackContainerType{
+		32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false,
+	}
+	msgpackContainerBin = msgpackContainerType{
+		0, 0, mpBin8, mpBin16, mpBin32, false, true, true,
+	}
+	msgpackContainerList = msgpackContainerType{
+		16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false,
+	}
+	msgpackContainerMap = msgpackContainerType{
+		16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false,
+	}
 )
 )
 
 
 //---------------------------------------------
 //---------------------------------------------
@@ -110,6 +202,7 @@ type msgpackEncDriver struct {
 	w encWriter
 	w encWriter
 	h *MsgpackHandle
 	h *MsgpackHandle
 	x [8]byte
 	x [8]byte
+	_ [3]uint64 // padding
 }
 }
 
 
 func (e *msgpackEncDriver) EncodeNil() {
 func (e *msgpackEncDriver) EncodeNil() {
@@ -117,10 +210,26 @@ func (e *msgpackEncDriver) EncodeNil() {
 }
 }
 
 
 func (e *msgpackEncDriver) EncodeInt(i int64) {
 func (e *msgpackEncDriver) EncodeInt(i int64) {
-	if i >= 0 {
-		e.EncodeUint(uint64(i))
+	// if i >= 0 {
+	// 	e.EncodeUint(uint64(i))
+	// } else if false &&
+	if i > math.MaxInt8 {
+		if i <= math.MaxInt16 {
+			e.w.writen1(mpInt16)
+			bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+		} else if i <= math.MaxInt32 {
+			e.w.writen1(mpInt32)
+			bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+		} else {
+			e.w.writen1(mpInt64)
+			bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+		}
 	} else if i >= -32 {
 	} else if i >= -32 {
-		e.w.writen1(byte(i))
+		if e.h.NoFixedNum {
+			e.w.writen2(mpInt8, byte(i))
+		} else {
+			e.w.writen1(byte(i))
+		}
 	} else if i >= math.MinInt8 {
 	} else if i >= math.MinInt8 {
 		e.w.writen2(mpInt8, byte(i))
 		e.w.writen2(mpInt8, byte(i))
 	} else if i >= math.MinInt16 {
 	} else if i >= math.MinInt16 {
@@ -137,7 +246,11 @@ func (e *msgpackEncDriver) EncodeInt(i int64) {
 
 
 func (e *msgpackEncDriver) EncodeUint(i uint64) {
 func (e *msgpackEncDriver) EncodeUint(i uint64) {
 	if i <= math.MaxInt8 {
 	if i <= math.MaxInt8 {
-		e.w.writen1(byte(i))
+		if e.h.NoFixedNum {
+			e.w.writen2(mpUint8, byte(i))
+		} else {
+			e.w.writen1(byte(i))
+		}
 	} else if i <= math.MaxUint8 {
 	} else if i <= math.MaxUint8 {
 		e.w.writen2(mpUint8, byte(i))
 		e.w.writen2(mpUint8, byte(i))
 	} else if i <= math.MaxUint16 {
 	} else if i <= math.MaxUint16 {
@@ -170,6 +283,39 @@ func (e *msgpackEncDriver) EncodeFloat64(f float64) {
 	bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
 	bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
 }
 }
 
 
+func (e *msgpackEncDriver) EncodeTime(t time.Time) {
+	if t.IsZero() {
+		e.EncodeNil()
+		return
+	}
+	t = t.UTC()
+	sec, nsec := t.Unix(), uint64(t.Nanosecond())
+	var data64 uint64
+	var l = 4
+	if sec >= 0 && sec>>34 == 0 {
+		data64 = (nsec << 34) | uint64(sec)
+		if data64&0xffffffff00000000 != 0 {
+			l = 8
+		}
+	} else {
+		l = 12
+	}
+	if e.h.WriteExt {
+		e.encodeExtPreamble(mpTimeExtTagU, l)
+	} else {
+		e.writeContainerLen(msgpackContainerStr, l)
+	}
+	switch l {
+	case 4:
+		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(data64))
+	case 8:
+		bigenHelper{e.x[:8], e.w}.writeUint64(data64)
+	case 12:
+		bigenHelper{e.x[:4], e.w}.writeUint32(uint32(nsec))
+		bigenHelper{e.x[:8], e.w}.writeUint64(uint64(sec))
+	}
+}
+
 func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Encoder) {
 func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Encoder) {
 	bs := ext.WriteExt(v)
 	bs := ext.WriteExt(v)
 	if bs == nil {
 	if bs == nil {
@@ -180,7 +326,7 @@ func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Enc
 		e.encodeExtPreamble(uint8(xtag), len(bs))
 		e.encodeExtPreamble(uint8(xtag), len(bs))
 		e.w.writeb(bs)
 		e.w.writeb(bs)
 	} else {
 	} else {
-		e.EncodeStringBytes(c_RAW, bs)
+		e.EncodeStringBytes(cRAW, bs)
 	}
 	}
 }
 }
 
 
@@ -224,7 +370,7 @@ func (e *msgpackEncDriver) WriteMapStart(length int) {
 
 
 func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
 func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
 	slen := len(s)
 	slen := len(s)
-	if c == c_RAW && e.h.WriteExt {
+	if c == cRAW && e.h.WriteExt {
 		e.writeContainerLen(msgpackContainerBin, slen)
 		e.writeContainerLen(msgpackContainerBin, slen)
 	} else {
 	} else {
 		e.writeContainerLen(msgpackContainerStr, slen)
 		e.writeContainerLen(msgpackContainerStr, slen)
@@ -234,13 +380,13 @@ func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
 	}
 	}
 }
 }
 
 
-func (e *msgpackEncDriver) EncodeSymbol(v string) {
-	e.EncodeString(c_UTF8, v)
-}
-
 func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
 func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
+	if bs == nil {
+		e.EncodeNil()
+		return
+	}
 	slen := len(bs)
 	slen := len(bs)
-	if c == c_RAW && e.h.WriteExt {
+	if c == cRAW && e.h.WriteExt {
 		e.writeContainerLen(msgpackContainerBin, slen)
 		e.writeContainerLen(msgpackContainerBin, slen)
 	} else {
 	} else {
 		e.writeContainerLen(msgpackContainerStr, slen)
 		e.writeContainerLen(msgpackContainerStr, slen)
@@ -267,10 +413,10 @@ func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
 //---------------------------------------------
 //---------------------------------------------
 
 
 type msgpackDecDriver struct {
 type msgpackDecDriver struct {
-	d      *Decoder
-	r      decReader // *Decoder decReader decReaderT
-	h      *MsgpackHandle
-	b      [scratchByteArrayLen]byte
+	d *Decoder
+	r decReader // *Decoder decReader decReaderT
+	h *MsgpackHandle
+	// b      [scratchByteArrayLen]byte
 	bd     byte
 	bd     byte
 	bdRead bool
 	bdRead bool
 	br     bool // bytes reader
 	br     bool // bytes reader
@@ -278,6 +424,7 @@ type msgpackDecDriver struct {
 	// noStreamingCodec
 	// noStreamingCodec
 	// decNoSeparator
 	// decNoSeparator
 	decDriverNoopContainerReader
 	decDriverNoopContainerReader
+	_ [3]uint64 // padding
 }
 }
 
 
 // Note: This returns either a primitive (int, bool, etc) for non-containers,
 // Note: This returns either a primitive (int, bool, etc) for non-containers,
@@ -368,9 +515,14 @@ func (d *msgpackDecDriver) DecodeNaked() {
 			n.v = valueTypeExt
 			n.v = valueTypeExt
 			clen := d.readExtLen()
 			clen := d.readExtLen()
 			n.u = uint64(d.r.readn1())
 			n.u = uint64(d.r.readn1())
-			n.l = d.r.readx(clen)
+			if n.u == uint64(mpTimeExtTagU) {
+				n.v = valueTypeTime
+				n.t = d.decodeTime(clen)
+			} else {
+				n.l = d.r.readx(clen)
+			}
 		default:
 		default:
-			d.d.errorf("Nil-Deciphered DecodeValue: %s: hex: %x, dec: %d", msgBadDesc, bd, bd)
+			d.d.errorf("cannot infer value: %s: Ox%x/%d/%s", msgBadDesc, bd, bd, mpdesc(bd))
 		}
 		}
 	}
 	}
 	if !decodeFurther {
 	if !decodeFurther {
@@ -384,7 +536,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
 }
 }
 
 
 // int can be decoded from msgpack type: intXXX or uintXXX
 // int can be decoded from msgpack type: intXXX or uintXXX
-func (d *msgpackDecDriver) DecodeInt(bitsize uint8) (i int64) {
+func (d *msgpackDecDriver) DecodeInt64() (i int64) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -412,14 +564,7 @@ func (d *msgpackDecDriver) DecodeInt(bitsize uint8) (i int64) {
 		case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
 		case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
 			i = int64(int8(d.bd))
 			i = int64(int8(d.bd))
 		default:
 		default:
-			d.d.errorf("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd)
-			return
-		}
-	}
-	// check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
-	if bitsize > 0 {
-		if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc {
-			d.d.errorf("Overflow int value: %v", i)
+			d.d.errorf("cannot decode signed integer: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
 			return
 			return
 		}
 		}
 	}
 	}
@@ -428,7 +573,7 @@ func (d *msgpackDecDriver) DecodeInt(bitsize uint8) (i int64) {
 }
 }
 
 
 // uint can be decoded from msgpack type: intXXX or uintXXX
 // uint can be decoded from msgpack type: intXXX or uintXXX
-func (d *msgpackDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
+func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -445,28 +590,28 @@ func (d *msgpackDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
 		if i := int64(int8(d.r.readn1())); i >= 0 {
 		if i := int64(int8(d.r.readn1())); i >= 0 {
 			ui = uint64(i)
 			ui = uint64(i)
 		} else {
 		} else {
-			d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
+			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 			return
 		}
 		}
 	case mpInt16:
 	case mpInt16:
 		if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
 		if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
 			ui = uint64(i)
 			ui = uint64(i)
 		} else {
 		} else {
-			d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
+			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 			return
 		}
 		}
 	case mpInt32:
 	case mpInt32:
 		if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
 		if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
 			ui = uint64(i)
 			ui = uint64(i)
 		} else {
 		} else {
-			d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
+			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 			return
 		}
 		}
 	case mpInt64:
 	case mpInt64:
 		if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
 		if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
 			ui = uint64(i)
 			ui = uint64(i)
 		} else {
 		} else {
-			d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
+			d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
 			return
 			return
 		}
 		}
 	default:
 	default:
@@ -474,17 +619,10 @@ func (d *msgpackDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
 		case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
 		case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
 			ui = uint64(d.bd)
 			ui = uint64(d.bd)
 		case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
 		case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
-			d.d.errorf("Assigning negative signed value: %v, to unsigned type", int(d.bd))
+			d.d.errorf("assigning negative signed value: %v, to unsigned type", int(d.bd))
 			return
 			return
 		default:
 		default:
-			d.d.errorf("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd)
-			return
-		}
-	}
-	// check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
-	if bitsize > 0 {
-		if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc {
-			d.d.errorf("Overflow uint value: %v", ui)
+			d.d.errorf("cannot decode unsigned integer: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
 			return
 			return
 		}
 		}
 	}
 	}
@@ -493,7 +631,7 @@ func (d *msgpackDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
 }
 }
 
 
 // float can either be decoded from msgpack type: float, double or intX
 // float can either be decoded from msgpack type: float, double or intX
-func (d *msgpackDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
+func (d *msgpackDecDriver) DecodeFloat64() (f float64) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -502,11 +640,7 @@ func (d *msgpackDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
 	} else if d.bd == mpDouble {
 	} else if d.bd == mpDouble {
 		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
 		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
 	} else {
 	} else {
-		f = float64(d.DecodeInt(0))
-	}
-	if chkOverflow32 && chkOvf.Float32(f) {
-		d.d.errorf("msgpack: float32 overflow: %v", f)
-		return
+		f = float64(d.DecodeInt64())
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
@@ -522,7 +656,7 @@ func (d *msgpackDecDriver) DecodeBool() (b bool) {
 	} else if d.bd == mpTrue || d.bd == 1 {
 	} else if d.bd == mpTrue || d.bd == 1 {
 		b = true
 		b = true
 	} else {
 	} else {
-		d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+		d.d.errorf("cannot decode bool: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -534,13 +668,15 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 
 
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	bd := d.bd
 	// DecodeBytes could be from: bin str fixstr fixarray array ...
 	// DecodeBytes could be from: bin str fixstr fixarray array ...
 	var clen int
 	var clen int
 	vt := d.ContainerType()
 	vt := d.ContainerType()
 	switch vt {
 	switch vt {
 	case valueTypeBytes:
 	case valueTypeBytes:
 		// valueTypeBytes may be a mpBin or an mpStr container
 		// valueTypeBytes may be a mpBin or an mpStr container
-		if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
+		if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
 			clen = d.readContainerLen(msgpackContainerBin)
 			clen = d.readContainerLen(msgpackContainerBin)
 		} else {
 		} else {
 			clen = d.readContainerLen(msgpackContainerStr)
 			clen = d.readContainerLen(msgpackContainerStr)
@@ -548,28 +684,17 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 	case valueTypeString:
 	case valueTypeString:
 		clen = d.readContainerLen(msgpackContainerStr)
 		clen = d.readContainerLen(msgpackContainerStr)
 	case valueTypeArray:
 	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
-			}
+		if zerocopy && len(bs) == 0 {
+			bs = d.d.b[:]
 		}
 		}
-		d.bdRead = false
-		return bs
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
 	default:
 	default:
-		d.d.errorf("invalid container type: expecting bin|str|array")
+		d.d.errorf("invalid container type: expecting bin|str|array, got: 0x%x", uint8(vt))
 		return
 		return
 	}
 	}
 
 
 	// these are (bin|str)(8|16|32)
 	// these are (bin|str)(8|16|32)
-	// 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.
 	if clen < 0 {
 	if clen < 0 {
@@ -579,18 +704,18 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 		if d.br {
 		if d.br {
 			return d.r.readx(clen)
 			return d.r.readx(clen)
 		} else if len(bs) == 0 {
 		} else if len(bs) == 0 {
-			bs = d.b[:]
+			bs = d.d.b[:]
 		}
 		}
 	}
 	}
-	return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
+	return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
 }
 }
 
 
 func (d *msgpackDecDriver) DecodeString() (s string) {
 func (d *msgpackDecDriver) DecodeString() (s string) {
-	return string(d.DecodeBytes(d.b[:], true))
+	return string(d.DecodeBytes(d.d.b[:], true))
 }
 }
 
 
 func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
 func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
-	return d.DecodeBytes(d.b[:], true)
+	return d.DecodeBytes(d.d.b[:], true)
 }
 }
 
 
 func (d *msgpackDecDriver) readNextBd() {
 func (d *msgpackDecDriver) readNextBd() {
@@ -623,9 +748,10 @@ func (d *msgpackDecDriver) ContainerType() (vt valueType) {
 		return valueTypeArray
 		return valueTypeArray
 	} else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) {
 	} else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) {
 		return valueTypeMap
 		return valueTypeMap
-	} else {
-		// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
 	}
 	}
+	// else {
+	// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+	// }
 	return valueTypeUnset
 	return valueTypeUnset
 }
 }
 
 
@@ -635,7 +761,7 @@ func (d *msgpackDecDriver) TryDecodeAsNil() (v bool) {
 	}
 	}
 	if d.bd == mpNil {
 	if d.bd == mpNil {
 		d.bdRead = false
 		d.bdRead = false
-		v = true
+		return true
 	}
 	}
 	return
 	return
 }
 }
@@ -653,7 +779,7 @@ func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int)
 	} else if (ct.bFixMin & bd) == ct.bFixMin {
 	} else if (ct.bFixMin & bd) == ct.bFixMin {
 		clen = int(ct.bFixMin ^ bd)
 		clen = int(ct.bFixMin ^ bd)
 	} else {
 	} else {
-		d.d.errorf("readContainerLen: %s: hex: %x, decimal: %d", msgBadDesc, bd, bd)
+		d.d.errorf("cannot read container length: %s: hex: %x, decimal: %d", msgBadDesc, bd, bd)
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -701,9 +827,60 @@ func (d *msgpackDecDriver) readExtLen() (clen int) {
 	return
 	return
 }
 }
 
 
+func (d *msgpackDecDriver) DecodeTime() (t time.Time) {
+	// decode time from string bytes or ext
+	if !d.bdRead {
+		d.readNextBd()
+	}
+	if d.bd == mpNil {
+		d.bdRead = false
+		return
+	}
+	var clen int
+	switch d.ContainerType() {
+	case valueTypeBytes, valueTypeString:
+		clen = d.readContainerLen(msgpackContainerStr)
+	default:
+		// expect to see mpFixExt4,-1 OR mpFixExt8,-1 OR mpExt8,12,-1
+		d.bdRead = false
+		b2 := d.r.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 {
+			clen = 12
+		} else {
+			d.d.errorf("invalid bytes for decoding time as extension: got 0x%x, 0x%x", d.bd, b2)
+			return
+		}
+	}
+	return d.decodeTime(clen)
+}
+
+func (d *msgpackDecDriver) decodeTime(clen int) (t time.Time) {
+	// bs = d.r.readx(clen)
+	d.bdRead = false
+	switch clen {
+	case 4:
+		t = time.Unix(int64(bigen.Uint32(d.r.readx(4))), 0).UTC()
+	case 8:
+		tv := bigen.Uint64(d.r.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))
+		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)
+		return
+	}
+	return
+}
+
 func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 	if xtag > 0xff {
 	if xtag > 0xff {
-		d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
+		d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
 		return
 		return
 	}
 	}
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
@@ -732,7 +909,7 @@ func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs
 		clen := d.readExtLen()
 		clen := d.readExtLen()
 		xtag = d.r.readn1()
 		xtag = d.r.readn1()
 		if verifyTag && xtag != tag {
 		if verifyTag && xtag != tag {
-			d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+			d.d.errorf("wrong extension tag - got %b, expecting %v", xtag, tag)
 			return
 			return
 		}
 		}
 		xbs = d.r.readx(clen)
 		xbs = d.r.readx(clen)
@@ -750,6 +927,9 @@ type MsgpackHandle struct {
 	// RawToString controls how raw bytes are decoded into a nil interface{}.
 	// RawToString controls how raw bytes are decoded into a nil interface{}.
 	RawToString bool
 	RawToString bool
 
 
+	// NoFixedNum says to output all signed integers as 2-bytes, never as 1-byte fixednum.
+	NoFixedNum bool
+
 	// WriteExt flag supports encoding configured extensions with extension tags.
 	// WriteExt flag supports encoding configured extensions with extension tags.
 	// It also controls whether other elements of the new spec are encoded (ie Str8).
 	// It also controls whether other elements of the new spec are encoded (ie Str8).
 	//
 	//
@@ -761,12 +941,19 @@ type MsgpackHandle struct {
 	// type is provided (e.g. decoding into a nil interface{}), you get back
 	// type is provided (e.g. decoding into a nil interface{}), you get back
 	// 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
 	noElemSeparators
+
+	// _ [1]uint64 // padding
 }
 }
 
 
+// Name returns the name of the handle: msgpack
+func (h *MsgpackHandle) Name() string { return "msgpack" }
+
+// SetBytesExt sets an extension
 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) {
-	return h.SetExt(rt, tag, &setExtWrapper{b: ext})
+	return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
 }
 }
 
 
 func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
 func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
@@ -804,7 +991,7 @@ func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) err
 		bodyArr = []interface{}{body}
 		bodyArr = []interface{}{body}
 	}
 	}
 	r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr}
 	r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr}
-	return c.write(r2, nil, false, true)
+	return c.write(r2, nil, false)
 }
 }
 
 
 func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
 func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
@@ -816,7 +1003,7 @@ func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) e
 		body = nil
 		body = nil
 	}
 	}
 	r2 := []interface{}{1, uint32(r.Seq), moe, body}
 	r2 := []interface{}{1, uint32(r.Seq), moe, body}
-	return c.write(r2, nil, false, true)
+	return c.write(r2, nil, false)
 }
 }
 
 
 func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error {
 func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error {
@@ -836,7 +1023,6 @@ func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
 }
 }
 
 
 func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
 func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
-
 	if c.isClosed() {
 	if c.isClosed() {
 		return io.EOF
 		return io.EOF
 	}
 	}
@@ -850,28 +1036,34 @@ func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint
 	// 	err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1)
 	// 	err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1)
 	// 	return
 	// 	return
 	// }
 	// }
-	var b byte
-	b, err = c.br.ReadByte()
-	if err != nil {
-		return
-	}
-	if b != fia {
-		err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, b)
-		return
+	var ba [1]byte
+	var n int
+	for {
+		n, err = c.r.Read(ba[:])
+		if err != nil {
+			return
+		}
+		if n == 1 {
+			break
+		}
 	}
 	}
 
 
-	if err = c.read(&b); err != nil {
-		return
-	}
-	if b != expectTypeByte {
-		err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b)
-		return
-	}
-	if err = c.read(msgid); err != nil {
-		return
-	}
-	if err = c.read(methodOrError); err != nil {
-		return
+	var b = ba[0]
+	if b != fia {
+		err = fmt.Errorf("not array - %s %x/%s", msgBadDesc, b, mpdesc(b))
+	} else {
+		err = c.read(&b)
+		if err == nil {
+			if b != expectTypeByte {
+				err = fmt.Errorf("%s - expecting %v but got %x/%s",
+					msgBadDesc, expectTypeByte, b, mpdesc(b))
+			} else {
+				err = c.read(msgid)
+				if err == nil {
+					err = c.read(methodOrError)
+				}
+			}
+		}
 	}
 	}
 	return
 	return
 }
 }
@@ -884,7 +1076,8 @@ type msgpackSpecRpc struct{}
 
 
 // MsgpackSpecRpc implements Rpc using the communication protocol defined in
 // MsgpackSpecRpc implements Rpc using the communication protocol defined in
 // the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
 // the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
-// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
+//
+// See GoRpc documentation, for information on buffering for better performance.
 var MsgpackSpecRpc msgpackSpecRpc
 var MsgpackSpecRpc msgpackSpecRpc
 
 
 func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
 func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {

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

@@ -1,214 +0,0 @@
-// 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.
-
-// +build ignore
-
-package codec
-
-import (
-	"math/rand"
-	"time"
-)
-
-// NoopHandle returns a no-op handle. It basically does nothing.
-// It is only useful for benchmarking, as it gives an idea of the
-// overhead from the codec framework.
-//
-// LIBRARY USERS: *** DO NOT USE ***
-func NoopHandle(slen int) *noopHandle {
-	h := noopHandle{}
-	h.rand = rand.New(rand.NewSource(time.Now().UnixNano()))
-	h.B = make([][]byte, slen)
-	h.S = make([]string, slen)
-	for i := 0; i < len(h.S); i++ {
-		b := make([]byte, i+1)
-		for j := 0; j < len(b); j++ {
-			b[j] = 'a' + byte(i)
-		}
-		h.B[i] = b
-		h.S[i] = string(b)
-	}
-	return &h
-}
-
-// noopHandle does nothing.
-// It is used to simulate the overhead of the codec framework.
-type noopHandle struct {
-	BasicHandle
-	binaryEncodingType
-	noopDrv // noopDrv is unexported here, so we can get a copy of it when needed.
-}
-
-type noopDrv struct {
-	d    *Decoder
-	e    *Encoder
-	i    int
-	S    []string
-	B    [][]byte
-	mks  []bool    // stack. if map (true), else if array (false)
-	mk   bool      // top of stack. what container are we on? map or array?
-	ct   valueType // last response for IsContainerType.
-	cb   int       // counter for ContainerType
-	rand *rand.Rand
-}
-
-func (h *noopDrv) r(v int) int { return h.rand.Intn(v) }
-func (h *noopDrv) m(v int) int { h.i++; return h.i % v }
-
-func (h *noopDrv) newEncDriver(e *Encoder) encDriver { h.e = e; return h }
-func (h *noopDrv) newDecDriver(d *Decoder) decDriver { h.d = d; return h }
-
-func (h *noopDrv) reset()       {}
-func (h *noopDrv) uncacheRead() {}
-
-// --- encDriver
-
-// stack functions (for map and array)
-func (h *noopDrv) start(b bool) {
-	// println("start", len(h.mks)+1)
-	h.mks = append(h.mks, b)
-	h.mk = b
-}
-func (h *noopDrv) end() {
-	// println("end: ", len(h.mks)-1)
-	h.mks = h.mks[:len(h.mks)-1]
-	if len(h.mks) > 0 {
-		h.mk = h.mks[len(h.mks)-1]
-	} else {
-		h.mk = false
-	}
-}
-
-func (h *noopDrv) EncodeBuiltin(rt uintptr, v interface{}) {}
-func (h *noopDrv) EncodeNil()                              {}
-func (h *noopDrv) EncodeInt(i int64)                       {}
-func (h *noopDrv) EncodeUint(i uint64)                     {}
-func (h *noopDrv) EncodeBool(b bool)                       {}
-func (h *noopDrv) EncodeFloat32(f float32)                 {}
-func (h *noopDrv) EncodeFloat64(f float64)                 {}
-func (h *noopDrv) EncodeRawExt(re *RawExt, e *Encoder)     {}
-func (h *noopDrv) EncodeArrayStart(length int)             { h.start(true) }
-func (h *noopDrv) EncodeMapStart(length int)               { h.start(false) }
-func (h *noopDrv) EncodeEnd()                              { h.end() }
-
-func (h *noopDrv) EncodeString(c charEncoding, v string)      {}
-func (h *noopDrv) EncodeSymbol(v string)                      {}
-func (h *noopDrv) EncodeStringBytes(c charEncoding, v []byte) {}
-
-func (h *noopDrv) EncodeExt(rv interface{}, xtag uint64, ext Ext, e *Encoder) {}
-
-// ---- decDriver
-func (h *noopDrv) initReadNext()                              {}
-func (h *noopDrv) CheckBreak() bool                           { return false }
-func (h *noopDrv) IsBuiltinType(rt uintptr) bool              { return false }
-func (h *noopDrv) DecodeBuiltin(rt uintptr, v interface{})    {}
-func (h *noopDrv) DecodeInt(bitsize uint8) (i int64)          { return int64(h.m(15)) }
-func (h *noopDrv) DecodeUint(bitsize uint8) (ui uint64)       { return uint64(h.m(35)) }
-func (h *noopDrv) DecodeFloat(chkOverflow32 bool) (f float64) { return float64(h.m(95)) }
-func (h *noopDrv) DecodeBool() (b bool)                       { return h.m(2) == 0 }
-func (h *noopDrv) DecodeString() (s string)                   { return h.S[h.m(8)] }
-func (h *noopDrv) DecodeStringAsBytes() []byte                { return h.DecodeBytes(nil, true) }
-
-func (h *noopDrv) DecodeBytes(bs []byte, zerocopy bool) []byte { return h.B[h.m(len(h.B))] }
-
-func (h *noopDrv) ReadEnd() { h.end() }
-
-// toggle map/slice
-func (h *noopDrv) ReadMapStart() int   { h.start(true); return h.m(10) }
-func (h *noopDrv) ReadArrayStart() int { h.start(false); return h.m(10) }
-
-func (h *noopDrv) ContainerType() (vt valueType) {
-	// return h.m(2) == 0
-	// handle kStruct, which will bomb is it calls this and doesn't get back a map or array.
-	// consequently, if the return value is not map or array, reset it to one of them based on h.m(7) % 2
-	// for kstruct: at least one out of every 2 times, return one of valueTypeMap or Array (else kstruct bombs)
-	// however, every 10th time it is called, we just return something else.
-	var vals = [...]valueType{valueTypeArray, valueTypeMap}
-	//  ------------ TAKE ------------
-	// if h.cb%2 == 0 {
-	// 	if h.ct == valueTypeMap || h.ct == valueTypeArray {
-	// 	} else {
-	// 		h.ct = vals[h.m(2)]
-	// 	}
-	// } else if h.cb%5 == 0 {
-	// 	h.ct = valueType(h.m(8))
-	// } else {
-	// 	h.ct = vals[h.m(2)]
-	// }
-	//  ------------ TAKE ------------
-	// if h.cb%16 == 0 {
-	// 	h.ct = valueType(h.cb % 8)
-	// } else {
-	// 	h.ct = vals[h.cb%2]
-	// }
-	h.ct = vals[h.cb%2]
-	h.cb++
-	return h.ct
-
-	// if h.ct == valueTypeNil || h.ct == valueTypeString || h.ct == valueTypeBytes {
-	// 	return h.ct
-	// }
-	// return valueTypeUnset
-	// TODO: may need to tweak this so it works.
-	// if h.ct == valueTypeMap && vt == valueTypeArray || h.ct == valueTypeArray && vt == valueTypeMap {
-	// 	h.cb = !h.cb
-	// 	h.ct = vt
-	// 	return h.cb
-	// }
-	// // go in a loop and check it.
-	// h.ct = vt
-	// h.cb = h.m(7) == 0
-	// return h.cb
-}
-func (h *noopDrv) TryDecodeAsNil() bool {
-	if h.mk {
-		return false
-	} else {
-		return h.m(8) == 0
-	}
-}
-func (h *noopDrv) DecodeExt(rv interface{}, xtag uint64, ext Ext) uint64 {
-	return 0
-}
-
-func (h *noopDrv) DecodeNaked() {
-	// use h.r (random) not h.m() because h.m() could cause the same value to be given.
-	var sk int
-	if h.mk {
-		// if mapkey, do not support values of nil OR bytes, array, map or rawext
-		sk = h.r(7) + 1
-	} else {
-		sk = h.r(12)
-	}
-	n := &h.d.n
-	switch sk {
-	case 0:
-		n.v = valueTypeNil
-	case 1:
-		n.v, n.b = valueTypeBool, false
-	case 2:
-		n.v, n.b = valueTypeBool, true
-	case 3:
-		n.v, n.i = valueTypeInt, h.DecodeInt(64)
-	case 4:
-		n.v, n.u = valueTypeUint, h.DecodeUint(64)
-	case 5:
-		n.v, n.f = valueTypeFloat, h.DecodeFloat(true)
-	case 6:
-		n.v, n.f = valueTypeFloat, h.DecodeFloat(false)
-	case 7:
-		n.v, n.s = valueTypeString, h.DecodeString()
-	case 8:
-		n.v, n.l = valueTypeBytes, h.B[h.m(len(h.B))]
-	case 9:
-		n.v = valueTypeArray
-	case 10:
-		n.v = valueTypeMap
-	default:
-		n.v = valueTypeExt
-		n.u = h.DecodeUint(64)
-		n.l = h.B[h.m(len(h.B))]
-	}
-	h.ct = n.v
-	return
-}

+ 119 - 74
vendor/github.com/ugorji/go/codec/rpc.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 package codec
 package codec
@@ -11,124 +11,142 @@ import (
 	"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
-// }
-
 // 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 {
 	ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
 	ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
 	ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
 	ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
 }
 }
 
 
-// RpcCodecBuffered allows access to the underlying bufio.Reader/Writer
-// used by the rpc connection. It accommodates use-cases where the connection
-// should be used by rpc and non-rpc functions, e.g. streaming a file after
-// sending an rpc response.
-type RpcCodecBuffered interface {
-	BufferedReader() *bufio.Reader
-	BufferedWriter() *bufio.Writer
+// RPCOptions holds options specific to rpc functionality
+type RPCOptions struct {
+	// RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
+	//
+	// Set RPCNoBuffer=true to turn buffering off.
+	// Buffering can still be done if buffered connections are passed in, or
+	// buffering is configured on the handle.
+	RPCNoBuffer bool
 }
 }
 
 
-// -------------------------------------
-
 // rpcCodec defines the struct members and common methods.
 // rpcCodec defines the struct members and common methods.
 type rpcCodec struct {
 type rpcCodec struct {
-	rwc io.ReadWriteCloser
+	c io.Closer
+	r io.Reader
+	w io.Writer
+	f ioFlusher
+
 	dec *Decoder
 	dec *Decoder
 	enc *Encoder
 	enc *Encoder
-	bw  *bufio.Writer
-	br  *bufio.Reader
-	mu  sync.Mutex
-	h   Handle
+	// bw  *bufio.Writer
+	// br  *bufio.Reader
+	mu sync.Mutex
+	h  Handle
 
 
-	cls   bool
-	clsmu sync.RWMutex
+	cls    bool
+	clsmu  sync.RWMutex
+	clsErr error
 }
 }
 
 
 func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
 func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
-	bw := bufio.NewWriter(conn)
-	br := bufio.NewReader(conn)
+	// return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
+	return newRPCCodec2(conn, conn, conn, h)
+}
 
 
+func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
 	// defensive: ensure that jsonH has TermWhitespace turned on.
 	// defensive: ensure that jsonH has TermWhitespace turned on.
 	if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
 	if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
 		panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
 		panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
 	}
 	}
-
+	// always ensure that we use a flusher, and always flush what was written to the connection.
+	// we lose nothing by using a buffered writer internally.
+	f, ok := w.(ioFlusher)
+	bh := h.getBasicHandle()
+	if !bh.RPCNoBuffer {
+		if bh.WriterBufferSize <= 0 {
+			if !ok {
+				bw := bufio.NewWriter(w)
+				f, w = bw, bw
+			}
+		}
+		if bh.ReaderBufferSize <= 0 {
+			if _, ok = w.(ioPeeker); !ok {
+				if _, ok = w.(ioBuffered); !ok {
+					br := bufio.NewReader(r)
+					r = br
+				}
+			}
+		}
+	}
 	return rpcCodec{
 	return rpcCodec{
-		rwc: conn,
-		bw:  bw,
-		br:  br,
-		enc: NewEncoder(bw, h),
-		dec: NewDecoder(br, h),
+		c:   c,
+		w:   w,
+		r:   r,
+		f:   f,
 		h:   h,
 		h:   h,
+		enc: NewEncoder(w, h),
+		dec: NewDecoder(r, h),
 	}
 	}
 }
 }
 
 
-func (c *rpcCodec) BufferedReader() *bufio.Reader {
-	return c.br
-}
-
-func (c *rpcCodec) BufferedWriter() *bufio.Writer {
-	return c.bw
-}
-
-func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2, doFlush bool) (err error) {
+func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
 	if c.isClosed() {
 	if c.isClosed() {
-		return io.EOF
-	}
-	if err = c.enc.Encode(obj1); err != nil {
-		return
+		return c.clsErr
 	}
 	}
-	// t, tOk := c.h.(rpcEncodeTerminator)
-	// if tOk {
-	// 	c.bw.Write(t.rpcEncodeTerminate())
-	// }
-	if writeObj2 {
-		if err = c.enc.Encode(obj2); err != nil {
-			return
+	err = c.enc.Encode(obj1)
+	if err == nil {
+		if writeObj2 {
+			err = c.enc.Encode(obj2)
 		}
 		}
-		// if tOk {
-		// 	c.bw.Write(t.rpcEncodeTerminate())
+		// if err == nil && c.f != nil {
+		// 	err = c.f.Flush()
 		// }
 		// }
 	}
 	}
-	if doFlush {
-		return c.bw.Flush()
+	if c.f != nil {
+		if err == nil {
+			err = c.f.Flush()
+		} else {
+			_ = c.f.Flush() // swallow flush error, so we maintain prior error on write
+		}
 	}
 	}
 	return
 	return
 }
 }
 
 
+func (c *rpcCodec) swallow(err *error) {
+	defer panicToErr(c.dec, err)
+	c.dec.swallow()
+}
+
 func (c *rpcCodec) read(obj interface{}) (err error) {
 func (c *rpcCodec) read(obj interface{}) (err error) {
 	if c.isClosed() {
 	if c.isClosed() {
-		return io.EOF
+		return c.clsErr
 	}
 	}
-	//If nil is passed in, we should still attempt to read content to nowhere.
+	//If nil is passed in, we should read and discard
 	if obj == nil {
 	if obj == nil {
-		var obj2 interface{}
-		return c.dec.Decode(&obj2)
+		// var obj2 interface{}
+		// return c.dec.Decode(&obj2)
+		c.swallow(&err)
+		return
 	}
 	}
 	return c.dec.Decode(obj)
 	return c.dec.Decode(obj)
 }
 }
 
 
-func (c *rpcCodec) isClosed() bool {
-	c.clsmu.RLock()
-	x := c.cls
-	c.clsmu.RUnlock()
-	return x
+func (c *rpcCodec) isClosed() (b bool) {
+	if c.c != nil {
+		c.clsmu.RLock()
+		b = c.cls
+		c.clsmu.RUnlock()
+	}
+	return
 }
 }
 
 
 func (c *rpcCodec) Close() error {
 func (c *rpcCodec) Close() error {
-	if c.isClosed() {
-		return io.EOF
+	if c.c == nil || c.isClosed() {
+		return c.clsErr
 	}
 	}
 	c.clsmu.Lock()
 	c.clsmu.Lock()
 	c.cls = true
 	c.cls = true
+	c.clsErr = c.c.Close()
 	c.clsmu.Unlock()
 	c.clsmu.Unlock()
-	return c.rwc.Close()
+	return c.clsErr
 }
 }
 
 
 func (c *rpcCodec) ReadResponseBody(body interface{}) error {
 func (c *rpcCodec) ReadResponseBody(body interface{}) error {
@@ -145,13 +163,13 @@ func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
 	// Must protect for concurrent access as per API
 	// Must protect for concurrent access as per API
 	c.mu.Lock()
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	defer c.mu.Unlock()
-	return c.write(r, body, true, true)
+	return c.write(r, body, true)
 }
 }
 
 
 func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
 func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
 	c.mu.Lock()
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	defer c.mu.Unlock()
-	return c.write(r, body, true, true)
+	return c.write(r, body, true)
 }
 }
 
 
 func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
 func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
@@ -173,7 +191,36 @@ func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
 type goRpc struct{}
 type goRpc struct{}
 
 
 // GoRpc implements Rpc using the communication protocol defined in net/rpc package.
 // GoRpc implements Rpc using the communication protocol defined in net/rpc package.
-// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
+//
+// Note: network connection (from net.Dial, of type io.ReadWriteCloser) is not buffered.
+//
+// For performance, you should configure WriterBufferSize and ReaderBufferSize on the handle.
+// This ensures we use an adequate buffer during reading and writing.
+// If not configured, we will internally initialize and use a buffer during reads and writes.
+// This can be turned off via the RPCNoBuffer option on the Handle.
+//   var handle codec.JsonHandle
+//   handle.RPCNoBuffer = true // turns off attempt by rpc module to initialize a buffer
+//
+// Example 1: one way of configuring buffering explicitly:
+//   var handle codec.JsonHandle // codec handle
+//   handle.ReaderBufferSize = 1024
+//   handle.WriterBufferSize = 1024
+//   var conn io.ReadWriteCloser // connection got from a socket
+//   var serverCodec = GoRpc.ServerCodec(conn, handle)
+//   var clientCodec = GoRpc.ClientCodec(conn, handle)
+//
+// Example 2: you can also explicitly create a buffered connection yourself,
+// and not worry about configuring the buffer sizes in the Handle.
+//   var handle codec.Handle     // codec handle
+//   var conn io.ReadWriteCloser // connection got from a socket
+//   var bufconn = struct {      // bufconn here is a buffered io.ReadWriteCloser
+//       io.Closer
+//       *bufio.Reader
+//       *bufio.Writer
+//   }{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
+//   var serverCodec = GoRpc.ServerCodec(bufconn, handle)
+//   var clientCodec = GoRpc.ClientCodec(bufconn, handle)
+//
 var GoRpc goRpc
 var GoRpc goRpc
 
 
 func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
 func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
@@ -183,5 +230,3 @@ func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
 func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
 func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
 	return &goRpcCodec{newRPCCodec(conn, h)}
 	return &goRpcCodec{newRPCCodec(conn, h)}
 }
 }
-
-var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered

+ 175 - 64
vendor/github.com/ugorji/go/codec/simple.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Copyright (c) 2012-2018 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.
 
 
 package codec
 package codec
@@ -6,6 +6,7 @@ package codec
 import (
 import (
 	"math"
 	"math"
 	"reflect"
 	"reflect"
+	"time"
 )
 )
 
 
 const (
 const (
@@ -20,6 +21,8 @@ const (
 	simpleVdPosInt = 8
 	simpleVdPosInt = 8
 	simpleVdNegInt = 12
 	simpleVdNegInt = 12
 
 
+	simpleVdTime = 24
+
 	// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
 	// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
 	simpleVdString    = 216
 	simpleVdString    = 216
 	simpleVdByteArray = 224
 	simpleVdByteArray = 224
@@ -30,12 +33,15 @@ const (
 
 
 type simpleEncDriver struct {
 type simpleEncDriver struct {
 	noBuiltInTypes
 	noBuiltInTypes
-	encDriverNoopContainerWriter
 	// encNoSeparator
 	// encNoSeparator
 	e *Encoder
 	e *Encoder
 	h *SimpleHandle
 	h *SimpleHandle
 	w encWriter
 	w encWriter
 	b [8]byte
 	b [8]byte
+	// c containerState
+	encDriverTrackContainerWriter
+	// encDriverNoopContainerWriter
+	_ [2]uint64 // padding
 }
 }
 
 
 func (e *simpleEncDriver) EncodeNil() {
 func (e *simpleEncDriver) EncodeNil() {
@@ -43,6 +49,10 @@ func (e *simpleEncDriver) EncodeNil() {
 }
 }
 
 
 func (e *simpleEncDriver) EncodeBool(b bool) {
 func (e *simpleEncDriver) EncodeBool(b bool) {
+	if e.h.EncZeroValuesAsNil && e.c != containerMapKey && !b {
+		e.EncodeNil()
+		return
+	}
 	if b {
 	if b {
 		e.w.writen1(simpleVdTrue)
 		e.w.writen1(simpleVdTrue)
 	} else {
 	} else {
@@ -51,11 +61,19 @@ func (e *simpleEncDriver) EncodeBool(b bool) {
 }
 }
 
 
 func (e *simpleEncDriver) EncodeFloat32(f float32) {
 func (e *simpleEncDriver) EncodeFloat32(f float32) {
+	if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
+		e.EncodeNil()
+		return
+	}
 	e.w.writen1(simpleVdFloat32)
 	e.w.writen1(simpleVdFloat32)
 	bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
 	bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
 }
 }
 
 
 func (e *simpleEncDriver) EncodeFloat64(f float64) {
 func (e *simpleEncDriver) EncodeFloat64(f float64) {
+	if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
+		e.EncodeNil()
+		return
+	}
 	e.w.writen1(simpleVdFloat64)
 	e.w.writen1(simpleVdFloat64)
 	bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
 	bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
 }
 }
@@ -73,6 +91,10 @@ func (e *simpleEncDriver) EncodeUint(v uint64) {
 }
 }
 
 
 func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
 func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
+	if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == 0 {
+		e.EncodeNil()
+		return
+	}
 	if v <= math.MaxUint8 {
 	if v <= math.MaxUint8 {
 		e.w.writen2(bd, uint8(v))
 		e.w.writen2(bd, uint8(v))
 	} else if v <= math.MaxUint16 {
 	} else if v <= math.MaxUint16 {
@@ -126,27 +148,54 @@ func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
 }
 }
 
 
 func (e *simpleEncDriver) WriteArrayStart(length int) {
 func (e *simpleEncDriver) WriteArrayStart(length int) {
+	e.c = containerArrayStart
 	e.encLen(simpleVdArray, length)
 	e.encLen(simpleVdArray, length)
 }
 }
 
 
 func (e *simpleEncDriver) WriteMapStart(length int) {
 func (e *simpleEncDriver) WriteMapStart(length int) {
+	e.c = containerMapStart
 	e.encLen(simpleVdMap, length)
 	e.encLen(simpleVdMap, length)
 }
 }
 
 
 func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
 func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
+	if false && e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == "" {
+		e.EncodeNil()
+		return
+	}
 	e.encLen(simpleVdString, len(v))
 	e.encLen(simpleVdString, len(v))
 	e.w.writestr(v)
 	e.w.writestr(v)
 }
 }
 
 
-func (e *simpleEncDriver) EncodeSymbol(v string) {
-	e.EncodeString(c_UTF8, v)
-}
+// func (e *simpleEncDriver) EncodeSymbol(v string) {
+// 	e.EncodeString(cUTF8, v)
+// }
 
 
 func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
 func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+	// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
+	if v == nil {
+		e.EncodeNil()
+		return
+	}
 	e.encLen(simpleVdByteArray, len(v))
 	e.encLen(simpleVdByteArray, len(v))
 	e.w.writeb(v)
 	e.w.writeb(v)
 }
 }
 
 
+func (e *simpleEncDriver) EncodeTime(t time.Time) {
+	// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && t.IsZero() {
+	if t.IsZero() {
+		e.EncodeNil()
+		return
+	}
+	v, err := t.MarshalBinary()
+	if err != nil {
+		e.e.errorv(err)
+		return
+	}
+	// time.Time marshalbinary takes about 14 bytes.
+	e.w.writen2(simpleVdTime, uint8(len(v)))
+	e.w.writeb(v)
+}
+
 //------------------------------------
 //------------------------------------
 
 
 type simpleDecDriver struct {
 type simpleDecDriver struct {
@@ -155,11 +204,13 @@ type simpleDecDriver struct {
 	r      decReader
 	r      decReader
 	bdRead bool
 	bdRead bool
 	bd     byte
 	bd     byte
-	br     bool // bytes reader
-	b      [scratchByteArrayLen]byte
+	br     bool // a bytes reader?
+	c      containerState
+	// b      [scratchByteArrayLen]byte
 	noBuiltInTypes
 	noBuiltInTypes
 	// noStreamingCodec
 	// noStreamingCodec
 	decDriverNoopContainerReader
 	decDriverNoopContainerReader
+	_ [3]uint64 // padding
 }
 }
 
 
 func (d *simpleDecDriver) readNextBd() {
 func (d *simpleDecDriver) readNextBd() {
@@ -178,23 +229,27 @@ func (d *simpleDecDriver) ContainerType() (vt valueType) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
-	if d.bd == simpleVdNil {
+	switch d.bd {
+	case simpleVdNil:
 		return valueTypeNil
 		return valueTypeNil
-	} else if d.bd == simpleVdByteArray || d.bd == simpleVdByteArray+1 ||
-		d.bd == simpleVdByteArray+2 || d.bd == simpleVdByteArray+3 || d.bd == simpleVdByteArray+4 {
+	case simpleVdByteArray, simpleVdByteArray + 1,
+		simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
 		return valueTypeBytes
 		return valueTypeBytes
-	} else if d.bd == simpleVdString || d.bd == simpleVdString+1 ||
-		d.bd == simpleVdString+2 || d.bd == simpleVdString+3 || d.bd == simpleVdString+4 {
+	case simpleVdString, simpleVdString + 1,
+		simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
 		return valueTypeString
 		return valueTypeString
-	} else if d.bd == simpleVdArray || d.bd == simpleVdArray+1 ||
-		d.bd == simpleVdArray+2 || d.bd == simpleVdArray+3 || d.bd == simpleVdArray+4 {
+	case simpleVdArray, simpleVdArray + 1,
+		simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
 		return valueTypeArray
 		return valueTypeArray
-	} else if d.bd == simpleVdMap || d.bd == simpleVdMap+1 ||
-		d.bd == simpleVdMap+2 || d.bd == simpleVdMap+3 || d.bd == simpleVdMap+4 {
+	case simpleVdMap, simpleVdMap + 1,
+		simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
 		return valueTypeMap
 		return valueTypeMap
-	} else {
-		// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+		// case simpleVdTime:
+		// 	return valueTypeTime
 	}
 	}
+	// else {
+	// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+	// }
 	return valueTypeUnset
 	return valueTypeUnset
 }
 }
 
 
@@ -235,7 +290,7 @@ func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
 		ui = uint64(bigen.Uint64(d.r.readx(8)))
 		ui = uint64(bigen.Uint64(d.r.readx(8)))
 		neg = true
 		neg = true
 	default:
 	default:
-		d.d.errorf("decIntAny: Integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
+		d.d.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
 		return
 		return
 	}
 	}
 	// don't do this check, because callers may only want the unsigned value.
 	// don't do this check, because callers may only want the unsigned value.
@@ -246,39 +301,27 @@ func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
 	return
 	return
 }
 }
 
 
-func (d *simpleDecDriver) DecodeInt(bitsize uint8) (i int64) {
+func (d *simpleDecDriver) DecodeInt64() (i int64) {
 	ui, neg := d.decCheckInteger()
 	ui, neg := d.decCheckInteger()
-	i, overflow := chkOvf.SignedInt(ui)
-	if overflow {
-		d.d.errorf("simple: overflow converting %v to signed integer", ui)
-		return
-	}
+	i = chkOvf.SignedIntV(ui)
 	if neg {
 	if neg {
 		i = -i
 		i = -i
 	}
 	}
-	if chkOvf.Int(i, bitsize) {
-		d.d.errorf("simple: overflow integer: %v", i)
-		return
-	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
 
 
-func (d *simpleDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
+func (d *simpleDecDriver) DecodeUint64() (ui uint64) {
 	ui, neg := d.decCheckInteger()
 	ui, neg := d.decCheckInteger()
 	if neg {
 	if neg {
-		d.d.errorf("Assigning negative signed value to unsigned type")
-		return
-	}
-	if chkOvf.Uint(ui, bitsize) {
-		d.d.errorf("simple: overflow integer: %v", ui)
+		d.d.errorf("assigning negative signed value to unsigned type")
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
 
 
-func (d *simpleDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
+func (d *simpleDecDriver) DecodeFloat64() (f float64) {
 	if !d.bdRead {
 	if !d.bdRead {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
@@ -288,16 +331,12 @@ func (d *simpleDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
 		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
 		f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
 	} else {
 	} else {
 		if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
 		if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
-			f = float64(d.DecodeInt(64))
+			f = float64(d.DecodeInt64())
 		} else {
 		} else {
-			d.d.errorf("Float only valid from float32/64: Invalid descriptor: %v", d.bd)
+			d.d.errorf("float only valid from float32/64: Invalid descriptor: %v", d.bd)
 			return
 			return
 		}
 		}
 	}
 	}
-	if chkOverflow32 && chkOvf.Float32(f) {
-		d.d.errorf("msgpack: float32 overflow: %v", f)
-		return
-	}
 	d.bdRead = false
 	d.bdRead = false
 	return
 	return
 }
 }
@@ -311,7 +350,7 @@ func (d *simpleDecDriver) DecodeBool() (b bool) {
 		b = true
 		b = true
 	} else if d.bd == simpleVdFalse {
 	} else if d.bd == simpleVdFalse {
 	} else {
 	} else {
-		d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+		d.d.errorf("cannot decode bool - %s: %x", msgBadDesc, d.bd)
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -323,6 +362,7 @@ func (d *simpleDecDriver) ReadMapStart() (length int) {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
+	d.c = containerMapStart
 	return d.decLen()
 	return d.decLen()
 }
 }
 
 
@@ -331,9 +371,30 @@ func (d *simpleDecDriver) ReadArrayStart() (length int) {
 		d.readNextBd()
 		d.readNextBd()
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
+	d.c = containerArrayStart
 	return d.decLen()
 	return d.decLen()
 }
 }
 
 
+func (d *simpleDecDriver) ReadArrayElem() {
+	d.c = containerArrayElem
+}
+
+func (d *simpleDecDriver) ReadArrayEnd() {
+	d.c = containerArrayEnd
+}
+
+func (d *simpleDecDriver) ReadMapElemKey() {
+	d.c = containerMapKey
+}
+
+func (d *simpleDecDriver) ReadMapElemValue() {
+	d.c = containerMapValue
+}
+
+func (d *simpleDecDriver) ReadMapEnd() {
+	d.c = containerMapEnd
+}
+
 func (d *simpleDecDriver) decLen() int {
 func (d *simpleDecDriver) decLen() int {
 	switch d.bd % 8 {
 	switch d.bd % 8 {
 	case 0:
 	case 0:
@@ -345,28 +406,28 @@ func (d *simpleDecDriver) decLen() int {
 	case 3:
 	case 3:
 		ui := uint64(bigen.Uint32(d.r.readx(4)))
 		ui := uint64(bigen.Uint32(d.r.readx(4)))
 		if chkOvf.Uint(ui, intBitsize) {
 		if chkOvf.Uint(ui, intBitsize) {
-			d.d.errorf("simple: overflow integer: %v", ui)
+			d.d.errorf("overflow integer: %v", ui)
 			return 0
 			return 0
 		}
 		}
 		return int(ui)
 		return int(ui)
 	case 4:
 	case 4:
 		ui := bigen.Uint64(d.r.readx(8))
 		ui := bigen.Uint64(d.r.readx(8))
 		if chkOvf.Uint(ui, intBitsize) {
 		if chkOvf.Uint(ui, intBitsize) {
-			d.d.errorf("simple: overflow integer: %v", ui)
+			d.d.errorf("overflow integer: %v", ui)
 			return 0
 			return 0
 		}
 		}
 		return int(ui)
 		return int(ui)
 	}
 	}
-	d.d.errorf("decLen: Cannot read length: bd%%8 must be in range 0..4. Got: %d", d.bd%8)
+	d.d.errorf("cannot read length: bd%%8 must be in range 0..4. Got: %d", d.bd%8)
 	return -1
 	return -1
 }
 }
 
 
 func (d *simpleDecDriver) DecodeString() (s string) {
 func (d *simpleDecDriver) DecodeString() (s string) {
-	return string(d.DecodeBytes(d.b[:], true))
+	return string(d.DecodeBytes(d.d.b[:], true))
 }
 }
 
 
 func (d *simpleDecDriver) DecodeStringAsBytes() (s []byte) {
 func (d *simpleDecDriver) DecodeStringAsBytes() (s []byte) {
-	return d.DecodeBytes(d.b[:], true)
+	return d.DecodeBytes(d.d.b[:], true)
 }
 }
 
 
 func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
@@ -377,21 +438,51 @@ func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		d.bdRead = false
 		d.bdRead = false
 		return
 		return
 	}
 	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.bd >= simpleVdArray && d.bd <= simpleVdMap+4 {
+		if len(bs) == 0 && zerocopy {
+			bs = d.d.b[:]
+		}
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
+
 	clen := d.decLen()
 	clen := d.decLen()
 	d.bdRead = false
 	d.bdRead = false
 	if zerocopy {
 	if zerocopy {
 		if d.br {
 		if d.br {
 			return d.r.readx(clen)
 			return d.r.readx(clen)
 		} else if len(bs) == 0 {
 		} else if len(bs) == 0 {
-			bs = d.b[:]
+			bs = d.d.b[:]
 		}
 		}
 	}
 	}
 	return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
 	return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
 }
 }
 
 
+func (d *simpleDecDriver) DecodeTime() (t time.Time) {
+	if !d.bdRead {
+		d.readNextBd()
+	}
+	if d.bd == simpleVdNil {
+		d.bdRead = false
+		return
+	}
+	if d.bd != simpleVdTime {
+		d.d.errorf("invalid descriptor for time.Time - expect 0x%x, received 0x%x", simpleVdTime, d.bd)
+		return
+	}
+	d.bdRead = false
+	clen := int(d.r.readn1())
+	b := d.r.readx(clen)
+	if err := (&t).UnmarshalBinary(b); err != nil {
+		d.d.errorv(err)
+	}
+	return
+}
+
 func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
 	if xtag > 0xff {
 	if xtag > 0xff {
-		d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
+		d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
 		return
 		return
 	}
 	}
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
@@ -415,14 +506,15 @@ func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs [
 		l := d.decLen()
 		l := d.decLen()
 		xtag = d.r.readn1()
 		xtag = d.r.readn1()
 		if verifyTag && xtag != tag {
 		if verifyTag && xtag != tag {
-			d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+			d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
 			return
 			return
 		}
 		}
 		xbs = d.r.readx(l)
 		xbs = d.r.readx(l)
-	case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+	case simpleVdByteArray, simpleVdByteArray + 1,
+		simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
 		xbs = d.DecodeBytes(nil, true)
 		xbs = d.DecodeBytes(nil, true)
 	default:
 	default:
-		d.d.errorf("Invalid d.bd for extensions (Expecting extensions or byte array). Got: 0x%x", d.bd)
+		d.d.errorf("ext - %s - expecting extensions/bytearray, got: 0x%x", msgBadDesc, d.bd)
 		return
 		return
 	}
 	}
 	d.bdRead = false
 	d.bdRead = false
@@ -449,24 +541,29 @@ func (d *simpleDecDriver) DecodeNaked() {
 	case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
 	case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
 		if d.h.SignedInteger {
 		if d.h.SignedInteger {
 			n.v = valueTypeInt
 			n.v = valueTypeInt
-			n.i = d.DecodeInt(64)
+			n.i = d.DecodeInt64()
 		} else {
 		} else {
 			n.v = valueTypeUint
 			n.v = valueTypeUint
-			n.u = d.DecodeUint(64)
+			n.u = d.DecodeUint64()
 		}
 		}
 	case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
 	case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
 		n.v = valueTypeInt
 		n.v = valueTypeInt
-		n.i = d.DecodeInt(64)
+		n.i = d.DecodeInt64()
 	case simpleVdFloat32:
 	case simpleVdFloat32:
 		n.v = valueTypeFloat
 		n.v = valueTypeFloat
-		n.f = d.DecodeFloat(true)
+		n.f = d.DecodeFloat64()
 	case simpleVdFloat64:
 	case simpleVdFloat64:
 		n.v = valueTypeFloat
 		n.v = valueTypeFloat
-		n.f = d.DecodeFloat(false)
-	case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
+		n.f = d.DecodeFloat64()
+	case simpleVdTime:
+		n.v = valueTypeTime
+		n.t = d.DecodeTime()
+	case simpleVdString, simpleVdString + 1,
+		simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
 		n.v = valueTypeString
 		n.v = valueTypeString
 		n.s = d.DecodeString()
 		n.s = d.DecodeString()
-	case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+	case simpleVdByteArray, simpleVdByteArray + 1,
+		simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
 		n.v = valueTypeBytes
 		n.v = valueTypeBytes
 		n.l = d.DecodeBytes(nil, false)
 		n.l = d.DecodeBytes(nil, false)
 	case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
 	case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
@@ -474,14 +571,15 @@ func (d *simpleDecDriver) DecodeNaked() {
 		l := d.decLen()
 		l := d.decLen()
 		n.u = uint64(d.r.readn1())
 		n.u = uint64(d.r.readn1())
 		n.l = d.r.readx(l)
 		n.l = d.r.readx(l)
-	case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
+	case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
+		simpleVdArray + 3, simpleVdArray + 4:
 		n.v = valueTypeArray
 		n.v = valueTypeArray
 		decodeFurther = true
 		decodeFurther = true
 	case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
 	case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
 		n.v = valueTypeMap
 		n.v = valueTypeMap
 		decodeFurther = true
 		decodeFurther = true
 	default:
 	default:
-		d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd)
+		d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
 	}
 	}
 
 
 	if !decodeFurther {
 	if !decodeFurther {
@@ -500,7 +598,7 @@ func (d *simpleDecDriver) DecodeNaked() {
 //   - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte).
 //   - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte).
 //     There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
 //     There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
 //   - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
 //   - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
-//   - Lenght of containers (strings, bytes, array, map, extensions)
+//   - Length of containers (strings, bytes, array, map, extensions)
 //     are encoded in 0, 1, 2, 4 or 8 bytes.
 //     are encoded in 0, 1, 2, 4 or 8 bytes.
 //     Zero-length containers have no length encoded.
 //     Zero-length containers have no length encoded.
 //     For others, the number of bytes is given by pow(2, bd%3)
 //     For others, the number of bytes is given by pow(2, bd%3)
@@ -508,18 +606,29 @@ func (d *simpleDecDriver) DecodeNaked() {
 //   - arrays are encoded as [bd] [length] [value]...
 //   - arrays are encoded as [bd] [length] [value]...
 //   - extensions are encoded as [bd] [length] [tag] [byte]...
 //   - extensions are encoded as [bd] [length] [tag] [byte]...
 //   - strings/bytearrays are encoded as [bd] [length] [byte]...
 //   - strings/bytearrays are encoded as [bd] [length] [byte]...
+//   - time.Time are encoded as [bd] [length] [byte]...
 //
 //
 // The full spec will be published soon.
 // The full spec will be published soon.
 type SimpleHandle struct {
 type SimpleHandle struct {
 	BasicHandle
 	BasicHandle
 	binaryEncodingType
 	binaryEncodingType
 	noElemSeparators
 	noElemSeparators
+	// EncZeroValuesAsNil says to encode zero values for numbers, bool, string, etc as nil
+	EncZeroValuesAsNil bool
+
+	// _ [1]uint64 // padding
 }
 }
 
 
+// Name returns the name of the handle: simple
+func (h *SimpleHandle) Name() string { return "simple" }
+
+// SetBytesExt sets an extension
 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) {
-	return h.SetExt(rt, tag, &setExtWrapper{b: ext})
+	return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
 }
 }
 
 
+func (h *SimpleHandle) hasElemSeparators() bool { return true } // as it implements Write(Map|Array)XXX
+
 func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
 func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
 	return &simpleEncDriver{e: e, w: e.w, h: h}
 	return &simpleEncDriver{e: e, w: e.w, h: h}
 }
 }
@@ -529,10 +638,12 @@ func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
 }
 }
 
 
 func (e *simpleEncDriver) reset() {
 func (e *simpleEncDriver) reset() {
+	e.c = 0
 	e.w = e.e.w
 	e.w = e.e.w
 }
 }
 
 
 func (d *simpleDecDriver) reset() {
 func (d *simpleDecDriver) reset() {
+	d.c = 0
 	d.r, d.br = d.d.r, d.d.bytes
 	d.r, d.br = d.d.r, d.d.bytes
 	d.bd, d.bdRead = 0, false
 	d.bd, d.bdRead = 0, false
 }
 }

+ 0 - 220
vendor/github.com/ugorji/go/codec/time.go

@@ -1,220 +0,0 @@
-// 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 (
-	"fmt"
-	"time"
-)
-
-var timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
-
-type timeExt struct{}
-
-func (x timeExt) WriteExt(v interface{}) (bs []byte) {
-	switch v2 := v.(type) {
-	case time.Time:
-		bs = encodeTime(v2)
-	case *time.Time:
-		bs = encodeTime(*v2)
-	default:
-		panic(fmt.Errorf("unsupported format for time conversion: expecting time.Time; got %T", v2))
-	}
-	return
-}
-func (x timeExt) ReadExt(v interface{}, bs []byte) {
-	tt, err := decodeTime(bs)
-	if err != nil {
-		panic(err)
-	}
-	*(v.(*time.Time)) = tt
-}
-
-func (x timeExt) ConvertExt(v interface{}) interface{} {
-	return x.WriteExt(v)
-}
-func (x timeExt) UpdateExt(v interface{}, src interface{}) {
-	x.ReadExt(v, src.([]byte))
-}
-
-// EncodeTime encodes a time.Time as a []byte, including
-// information on the instant in time and UTC offset.
-//
-// Format Description
-//
-//   A timestamp is composed of 3 components:
-//
-//   - secs: signed integer representing seconds since unix epoch
-//   - nsces: unsigned integer representing fractional seconds as a
-//     nanosecond offset within secs, in the range 0 <= nsecs < 1e9
-//   - tz: signed integer representing timezone offset in minutes east of UTC,
-//     and a dst (daylight savings time) flag
-//
-//   When encoding a timestamp, the first byte is the descriptor, which
-//   defines which components are encoded and how many bytes are used to
-//   encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it
-//   is not encoded in the byte array explicitly*.
-//
-//       Descriptor 8 bits are of the form `A B C DDD EE`:
-//           A:   Is secs component encoded? 1 = true
-//           B:   Is nsecs component encoded? 1 = true
-//           C:   Is tz component encoded? 1 = true
-//           DDD: Number of extra bytes for secs (range 0-7).
-//                If A = 1, secs encoded in DDD+1 bytes.
-//                    If A = 0, secs is not encoded, and is assumed to be 0.
-//                    If A = 1, then we need at least 1 byte to encode secs.
-//                    DDD says the number of extra bytes beyond that 1.
-//                    E.g. if DDD=0, then secs is represented in 1 byte.
-//                         if DDD=2, then secs is represented in 3 bytes.
-//           EE:  Number of extra bytes for nsecs (range 0-3).
-//                If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above)
-//
-//   Following the descriptor bytes, subsequent bytes are:
-//
-//       secs component encoded in `DDD + 1` bytes (if A == 1)
-//       nsecs component encoded in `EE + 1` bytes (if B == 1)
-//       tz component encoded in 2 bytes (if C == 1)
-//
-//   secs and nsecs components are integers encoded in a BigEndian
-//   2-complement encoding format.
-//
-//   tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to
-//   Least significant bit 0 are described below:
-//
-//       Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes).
-//       Bit 15 = have\_dst: set to 1 if we set the dst flag.
-//       Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not.
-//       Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format.
-//
-func encodeTime(t time.Time) []byte {
-	//t := rv.Interface().(time.Time)
-	tsecs, tnsecs := t.Unix(), t.Nanosecond()
-	var (
-		bd   byte
-		btmp [8]byte
-		bs   [16]byte
-		i    int = 1
-	)
-	l := t.Location()
-	if l == time.UTC {
-		l = nil
-	}
-	if tsecs != 0 {
-		bd = bd | 0x80
-		bigen.PutUint64(btmp[:], uint64(tsecs))
-		f := pruneSignExt(btmp[:], tsecs >= 0)
-		bd = bd | (byte(7-f) << 2)
-		copy(bs[i:], btmp[f:])
-		i = i + (8 - f)
-	}
-	if tnsecs != 0 {
-		bd = bd | 0x40
-		bigen.PutUint32(btmp[:4], uint32(tnsecs))
-		f := pruneSignExt(btmp[:4], true)
-		bd = bd | byte(3-f)
-		copy(bs[i:], btmp[f:4])
-		i = i + (4 - f)
-	}
-	if l != nil {
-		bd = bd | 0x20
-		// Note that Go Libs do not give access to dst flag.
-		_, zoneOffset := t.Zone()
-		//zoneName, zoneOffset := t.Zone()
-		zoneOffset /= 60
-		z := uint16(zoneOffset)
-		bigen.PutUint16(btmp[:2], z)
-		// clear dst flags
-		bs[i] = btmp[0] & 0x3f
-		bs[i+1] = btmp[1]
-		i = i + 2
-	}
-	bs[0] = bd
-	return bs[0:i]
-}
-
-// DecodeTime decodes a []byte into a time.Time.
-func decodeTime(bs []byte) (tt time.Time, err error) {
-	bd := bs[0]
-	var (
-		tsec  int64
-		tnsec uint32
-		tz    uint16
-		i     byte = 1
-		i2    byte
-		n     byte
-	)
-	if bd&(1<<7) != 0 {
-		var btmp [8]byte
-		n = ((bd >> 2) & 0x7) + 1
-		i2 = i + n
-		copy(btmp[8-n:], bs[i:i2])
-		//if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it)
-		if bs[i]&(1<<7) != 0 {
-			copy(btmp[0:8-n], bsAll0xff)
-			//for j,k := byte(0), 8-n; j < k; j++ {	btmp[j] = 0xff }
-		}
-		i = i2
-		tsec = int64(bigen.Uint64(btmp[:]))
-	}
-	if bd&(1<<6) != 0 {
-		var btmp [4]byte
-		n = (bd & 0x3) + 1
-		i2 = i + n
-		copy(btmp[4-n:], bs[i:i2])
-		i = i2
-		tnsec = bigen.Uint32(btmp[:])
-	}
-	if bd&(1<<5) == 0 {
-		tt = time.Unix(tsec, int64(tnsec)).UTC()
-		return
-	}
-	// In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
-	// However, we need name here, so it can be shown when time is printed.
-	// Zone name is in form: UTC-08:00.
-	// Note that Go Libs do not give access to dst flag, so we ignore dst bits
-
-	i2 = i + 2
-	tz = bigen.Uint16(bs[i:i2])
-	i = i2
-	// sign extend sign bit into top 2 MSB (which were dst bits):
-	if tz&(1<<13) == 0 { // positive
-		tz = tz & 0x3fff //clear 2 MSBs: dst bits
-	} else { // negative
-		tz = tz | 0xc000 //set 2 MSBs: dst bits
-		//tzname[3] = '-' (TODO: verify. this works here)
-	}
-	tzint := int16(tz)
-	if tzint == 0 {
-		tt = time.Unix(tsec, int64(tnsec)).UTC()
-	} else {
-		// For Go Time, do not use a descriptive timezone.
-		// It's unnecessary, and makes it harder to do a reflect.DeepEqual.
-		// The Offset already tells what the offset should be, if not on UTC and unknown zone name.
-		// var zoneName = timeLocUTCName(tzint)
-		tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60))
-	}
-	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)
-// }

+ 107 - 25
vendor/github.com/ugorji/go/codec/xml.go

@@ -1,3 +1,6 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
 // +build ignore
 // +build ignore
 
 
 package codec
 package codec
@@ -24,7 +27,6 @@ It is a replacement, based on the simplicity and performance of codec.
 Look at it like JAXB for Go.
 Look at it like JAXB for Go.
 
 
 Challenges:
 Challenges:
-
   - Need to output XML preamble, with all namespaces at the right location in the output.
   - Need to output XML preamble, with all namespaces at the right location in the output.
   - Each "end" block is dynamic, so we need to maintain a context-aware stack
   - Each "end" block is dynamic, so we need to maintain a context-aware stack
   - How to decide when to use an attribute VS an element
   - How to decide when to use an attribute VS an element
@@ -34,24 +36,26 @@ Challenges:
 
 
 Extend the struct tag. See representative example:
 Extend the struct tag. See representative example:
   type X struct {
   type X struct {
-    ID uint8 codec:"xid|http://ugorji.net/x-namespace id,omitempty,toarray,attr,cdata"
+    ID uint8 `codec:"http://ugorji.net/x-namespace xid id,omitempty,toarray,attr,cdata"`
+    // format: [namespace-uri ][namespace-prefix ]local-name, ...
   }
   }
 
 
 Based on this, we encode
 Based on this, we encode
-  - fields as elements, BUT encode as attributes if struct tag contains ",attr".
+  - fields as elements, BUT
+    encode as attributes if struct tag contains ",attr" and is a scalar (bool, number or string)
   - text as entity-escaped text, BUT encode as CDATA if struct tag contains ",cdata".
   - text as entity-escaped text, BUT encode as CDATA if struct tag contains ",cdata".
 
 
-In this mode, we only encode as attribute if ",attr" is found, and only encode as CDATA
-if ",cdata" is found in the struct tag.
-
 To handle namespaces:
 To handle namespaces:
   - XMLHandle is denoted as being namespace-aware.
   - XMLHandle is denoted as being namespace-aware.
     Consequently, we WILL use the ns:name pair to encode and decode if defined, else use the plain name.
     Consequently, we WILL use the ns:name pair to encode and decode if defined, else use the plain name.
   - *Encoder and *Decoder know whether the Handle "prefers" namespaces.
   - *Encoder and *Decoder know whether the Handle "prefers" namespaces.
   - add *Encoder.getEncName(*structFieldInfo).
   - add *Encoder.getEncName(*structFieldInfo).
     No one calls *structFieldInfo.indexForEncName directly anymore
     No one calls *structFieldInfo.indexForEncName directly anymore
+  - OR better yet: indexForEncName is namespace-aware, and helper.go is all namespace-aware
+    indexForEncName takes a parameter of the form namespace:local-name OR local-name
   - add *Decoder.getStructFieldInfo(encName string) // encName here is either like abc, or h1:nsabc
   - add *Decoder.getStructFieldInfo(encName string) // encName here is either like abc, or h1:nsabc
-    No one accesses .encName anymore except in
+    by being a method on *Decoder, or maybe a method on the Handle itself.
+    No one accesses .encName anymore
   - let encode.go and decode.go use these (for consistency)
   - let encode.go and decode.go use these (for consistency)
   - only problem exists for gen.go, where we create a big switch on encName.
   - only problem exists for gen.go, where we create a big switch on encName.
     Now, we also have to add a switch on strings.endsWith(kName, encNsName)
     Now, we also have to add a switch on strings.endsWith(kName, encNsName)
@@ -62,13 +66,14 @@ To handle namespaces:
         default {
         default {
           switch {
           switch {
             case !nsAware: panic(...)
             case !nsAware: panic(...)
-            case strings.endsWith("nsabc"): x.abc()
+            case strings.endsWith(":abc"): x.abc()
+            case strings.endsWith(":def"): x.def()
             default: panic(...)
             default: panic(...)
           }
           }
         }
         }
      }
      }
 
 
-The structure below accomodates this:
+The structure below accommodates this:
 
 
   type typeInfo struct {
   type typeInfo struct {
     sfi []*structFieldInfo // sorted by encName
     sfi []*structFieldInfo // sorted by encName
@@ -88,7 +93,10 @@ indexForEncName is now an internal helper function that takes a sorted array
 (one of ti.sfins or ti.sfi). It is only used by *Encoder.getStructFieldInfo(...)
 (one of ti.sfins or ti.sfi). It is only used by *Encoder.getStructFieldInfo(...)
 
 
 There will be a separate parser from the builder.
 There will be a separate parser from the builder.
-The parser will have a method: next() xmlToken method.
+The parser will have a method: next() xmlToken method. It has lookahead support,
+so you can pop multiple tokens, make a determination, and push them back in the order popped.
+This will be needed to determine whether we are "nakedly" decoding a container or not.
+The stack will be implemented using a slice and push/pop happens at the [0] element.
 
 
 xmlToken has fields:
 xmlToken has fields:
   - type uint8: 0 | ElementStart | ElementEnd | AttrKey | AttrVal | Text
   - type uint8: 0 | ElementStart | ElementEnd | AttrKey | AttrVal | Text
@@ -132,7 +140,7 @@ At decode time, a structure containing the following is kept
   - all internal entities (<>&"' and others written in the document)
   - all internal entities (<>&"' and others written in the document)
 
 
 When decode starts, it parses XML namespace declarations and creates a map in the
 When decode starts, it parses XML namespace declarations and creates a map in the
-xmlDecDriver. While parsing, that map continously gets updated.
+xmlDecDriver. While parsing, that map continuously gets updated.
 The only problem happens when a namespace declaration happens on the node that it defines.
 The only problem happens when a namespace declaration happens on the node that it defines.
 e.g. <hn:name xmlns:hn="http://www.ugorji.net" >
 e.g. <hn:name xmlns:hn="http://www.ugorji.net" >
 To handle this, each Element must be fully parsed at a time,
 To handle this, each Element must be fully parsed at a time,
@@ -144,7 +152,7 @@ xmlns is a special attribute name.
   *We may decide later to allow user to use it e.g. you want to parse the xmlns mappings into a field.*
   *We may decide later to allow user to use it e.g. you want to parse the xmlns mappings into a field.*
 
 
 Number, bool, null, mapKey, etc can all be decoded from any xmlToken.
 Number, bool, null, mapKey, etc can all be decoded from any xmlToken.
-This accomodates map[int]string for example.
+This accommodates map[int]string for example.
 
 
 It should be possible to create a schema from the types,
 It should be possible to create a schema from the types,
 or vice versa (generate types from schema with appropriate tags).
 or vice versa (generate types from schema with appropriate tags).
@@ -178,8 +186,8 @@ An XML document is a name, a map of attributes and a list of children.
 Consequently, we cannot "DecodeNaked" into a map[string]interface{} (for example).
 Consequently, we cannot "DecodeNaked" into a map[string]interface{} (for example).
 We have to "DecodeNaked" into something that resembles XML data.
 We have to "DecodeNaked" into something that resembles XML data.
 
 
-To support DecodeNaked (decode into nil interface{}) we have to define some "supporting" types:
-    type Name struct { // Prefered. Less allocations due to conversions.
+To support DecodeNaked (decode into nil interface{}), we have to define some "supporting" types:
+    type Name struct { // Preferred. Less allocations due to conversions.
       Local string
       Local string
       Space string
       Space string
     }
     }
@@ -190,6 +198,8 @@ To support DecodeNaked (decode into nil interface{}) we have to define some "sup
     }
     }
 Only two "supporting" types are exposed for XML: Name and Element.
 Only two "supporting" types are exposed for XML: Name and Element.
 
 
+// ------------------
+
 We considered 'type Name string' where Name is like "Space Local" (space-separated).
 We considered 'type Name string' where Name is like "Space Local" (space-separated).
 We decided against it, because each creation of a name would lead to
 We decided against it, because each creation of a name would lead to
 double allocation (first convert []byte to string, then concatenate them into a string).
 double allocation (first convert []byte to string, then concatenate them into a string).
@@ -215,16 +225,16 @@ intelligent accessor methods to extract information and for performance.
     }
     }
     func (x *Element) child(i) interface{} // returns string or *Element
     func (x *Element) child(i) interface{} // returns string or *Element
 
 
-Per XML spec and our default handling, white space is insignificant between elements,
-specifically between parent-child or siblings. White space occuring alone between start
-and end element IS significant. However, if xml:space='preserve', then we 'preserve'
-all whitespace. This is more critical when doing a DecodeNaked, but MAY not be as critical
-when decoding into a typed value.
+// ------------------
+
+Per XML spec and our default handling, white space is always treated as
+insignificant between elements, except in a text node. The xml:space='preserve'
+attribute is ignored.
 
 
 **Note: there is no xml: namespace. The xml: attributes were defined before namespaces.**
 **Note: there is no xml: namespace. The xml: attributes were defined before namespaces.**
 **So treat them as just "directives" that should be interpreted to mean something**.
 **So treat them as just "directives" that should be interpreted to mean something**.
 
 
-On encoding, we don't add any prettifying markup (indenting, etc).
+On encoding, we support indenting aka prettifying markup in the same way we support it for json.
 
 
 A document or element can only be encoded/decoded from/to a struct. In this mode:
 A document or element can only be encoded/decoded from/to a struct. In this mode:
   - struct name maps to element name (or tag-info from _struct field)
   - struct name maps to element name (or tag-info from _struct field)
@@ -258,15 +268,14 @@ the struct tag signifying it should be attr, then all its fields are encoded as
 e.g.
 e.g.
 
 
     type X struct {
     type X struct {
-       M map[string]int `codec:"m,attr"` // encode as attributes
+       M map[string]int `codec:"m,attr"` // encode keys as attributes named
     }
     }
 
 
 Question:
 Question:
   - if encoding a map, what if map keys have spaces in them???
   - if encoding a map, what if map keys have spaces in them???
     Then they cannot be attributes or child elements. Error.
     Then they cannot be attributes or child elements. Error.
 
 
-Misc:
-
+Options to consider adding later:
   - For attribute values, normalize by trimming beginning and ending white space,
   - For attribute values, normalize by trimming beginning and ending white space,
     and converting every white space sequence to a single space.
     and converting every white space sequence to a single space.
   - ATTLIST restrictions are enforced.
   - ATTLIST restrictions are enforced.
@@ -284,6 +293,8 @@ Misc:
       CheckName bool
       CheckName bool
     }
     }
 
 
+Misc:
+
 ROADMAP (1 weeks):
 ROADMAP (1 weeks):
   - build encoder (1 day)
   - build encoder (1 day)
   - build decoder (based off xmlParser) (1 day)
   - build decoder (based off xmlParser) (1 day)
@@ -292,7 +303,78 @@ ROADMAP (1 weeks):
   - integrate and TEST (1 days)
   - integrate and TEST (1 days)
   - write article and post it (1 day)
   - write article and post it (1 day)
 
 
-
+// ---------- MORE NOTES FROM 2017-11-30 ------------
+
+when parsing
+- parse the attributes first
+- then parse the nodes
+
+basically:
+- if encoding a field: we use the field name for the wrapper
+- if encoding a non-field, then just use the element type name
+
+  map[string]string ==> <map><key>abc</key><value>val</value></map>... or
+                        <map key="abc">val</map>... OR
+                        <key1>val1</key1><key2>val2</key2>...                <- PREFERED
+  []string  ==> <string>v1</string><string>v2</string>...
+  string v1 ==> <string>v1</string>
+  bool true ==> <bool>true</bool>
+  float 1.0 ==> <float>1.0</float>
+  ...
+
+  F1 map[string]string ==> <F1><key>abc</key><value>val</value></F1>... OR
+                           <F1 key="abc">val</F1>... OR
+                           <F1><abc>val</abc>...</F1>                        <- PREFERED
+  F2 []string          ==> <F2>v1</F2><F2>v2</F2>...
+  F3 bool              ==> <F3>true</F3>
+  ...
+
+- a scalar is encoded as:
+  (value) of type T  ==> <T><value/></T>
+  (value) of field F ==> <F><value/></F>
+- A kv-pair is encoded as:
+  (key,value) ==> <map><key><value/></key></map> OR <map key="value">
+  (key,value) of field F ==> <F><key><value/></key></F> OR <F key="value">
+- A map or struct is just a list of kv-pairs
+- A list is encoded as sequences of same node e.g.
+  <F1 key1="value11">
+  <F1 key2="value12">
+  <F2>value21</F2>
+  <F2>value22</F2>
+- we may have to singularize the field name, when entering into xml,
+  and pluralize them when encoding.
+- bi-directional encode->decode->encode is not a MUST.
+  even encoding/xml cannot decode correctly what was encoded:
+
+  see https://play.golang.org/p/224V_nyhMS
+  func main() {
+	fmt.Println("Hello, playground")
+	v := []interface{}{"hello", 1, true, nil, time.Now()}
+	s, err := xml.Marshal(v)
+	fmt.Printf("err: %v, \ns: %s\n", err, s)
+	var v2 []interface{}
+	err = xml.Unmarshal(s, &v2)
+	fmt.Printf("err: %v, \nv2: %v\n", err, v2)
+	type T struct {
+	    V []interface{}
+	}
+	v3 := T{V: v}
+	s, err = xml.Marshal(v3)
+	fmt.Printf("err: %v, \ns: %s\n", err, s)
+	var v4 T
+	err = xml.Unmarshal(s, &v4)
+	fmt.Printf("err: %v, \nv4: %v\n", err, v4)
+  }
+  Output:
+    err: <nil>,
+    s: <string>hello</string><int>1</int><bool>true</bool><Time>2009-11-10T23:00:00Z</Time>
+    err: <nil>,
+    v2: [<nil>]
+    err: <nil>,
+    s: <T><V>hello</V><V>1</V><V>true</V><V>2009-11-10T23:00:00Z</V></T>
+    err: <nil>,
+    v4: {[<nil> <nil> <nil> <nil>]}
+-
 */
 */
 
 
 // ----------- PARSER  -------------------
 // ----------- PARSER  -------------------
@@ -419,7 +501,7 @@ func (h *XMLHandle) newDecDriver(d *Decoder) decDriver {
 }
 }
 
 
 func (h *XMLHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
 func (h *XMLHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
-	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
+	return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext})
 }
 }
 
 
 var _ decDriver = (*xmlDecDriver)(nil)
 var _ decDriver = (*xmlDecDriver)(nil)

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

@@ -1,23 +0,0 @@
-// 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))
-}

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