Sfoglia il codice sorgente

codec: expand tag to uint64, and move cbor specific tests to cbor_test.go

Ugorji Nwoke 11 anni fa
parent
commit
d3bbf953c5
11 ha cambiato i file con 859 aggiunte e 107 eliminazioni
  1. 1 1
      codec/0doc.go
  2. 7 4
      codec/binc.go
  3. 6 11
      codec/cbor.go
  4. 178 0
      codec/cbor_test.go
  5. 0 73
      codec/codecs_test.go
  6. 9 2
      codec/decode.go
  7. 2 2
      codec/encode.go
  8. 6 6
      codec/helper.go
  9. 7 4
      codec/msgpack.go
  10. 7 4
      codec/simple.go
  11. 636 0
      codec/test-cbor-goldens.json

+ 1 - 1
codec/0doc.go

@@ -8,7 +8,7 @@ Supported Serialization formats are:
 
   - msgpack: [https://github.com/msgpack/msgpack]
   - binc:    [http://github.com/ugorji/binc]
-  - cbor:    [http://cbor.io]
+  - cbor:    [http://cbor.io] [http://tools.ietf.org/html/rfc7049]
   - simple:  
 
 To install:

+ 7 - 4
codec/binc.go

@@ -173,7 +173,7 @@ func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) {
 	}
 }
 
-func (e *bincEncDriver) encodeExt(rv reflect.Value, xtag uint16, ext Ext, _ *Encoder) {
+func (e *bincEncDriver) encodeExt(rv reflect.Value, xtag uint64, ext Ext, _ *Encoder) {
 	bs := ext.WriteExt(rv)
 	if bs == nil {
 		e.encodeNil()
@@ -688,9 +688,12 @@ func (d *bincDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) {
 	return
 }
 
-func (d *bincDecDriver) decodeExt(rv reflect.Value, xtag uint16, ext Ext, _ *Decoder) (realxtag uint16) {
+func (d *bincDecDriver) decodeExt(rv reflect.Value, xtag uint64, ext Ext, _ *Decoder) (realxtag uint64) {
+	if xtag > 0xff {
+		decErr("decodeExt: tag must be <= 0xff; got: %v", xtag)
+	}
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
-	realxtag = uint16(realxtag1)
+	realxtag = uint64(realxtag1)
 	if ext == nil {
 		re := rv.Interface().(*RawExt)
 		re.Tag = realxtag
@@ -786,7 +789,7 @@ func (d *bincDecDriver) decodeNaked(_ *Decoder) (v interface{}, vt valueType, de
 		vt = valueTypeExt
 		l := d.decLen()
 		var re RawExt
-		re.Tag = uint16(d.r.readn1())
+		re.Tag = uint64(d.r.readn1())
 		re.Data = d.r.readn(l)
 		v = &re
 		vt = valueTypeExt

+ 6 - 11
codec/cbor.go

@@ -121,7 +121,7 @@ func (e *cborEncDriver) encLen(bd byte, length int) {
 	e.encUint(uint64(length), bd)
 }
 
-func (e *cborEncDriver) encodeExt(rv reflect.Value, xtag uint16, ext Ext, en *Encoder) {
+func (e *cborEncDriver) encodeExt(rv reflect.Value, xtag uint64, ext Ext, en *Encoder) {
 	e.encUint(uint64(xtag), cborBaseTag)
 	if v := ext.ConvertExt(rv); v == nil {
 		e.encodeNil()
@@ -406,13 +406,10 @@ func (d *cborDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) {
 	return
 }
 
-func (d *cborDecDriver) decodeExt(rv reflect.Value, xtag uint16, ext Ext, de *Decoder) (realxtag uint16) {
+func (d *cborDecDriver) decodeExt(rv reflect.Value, xtag uint64, ext Ext, de *Decoder) (realxtag uint64) {
 	u := d.decUint()
 	d.bdRead = false
-	if u > math.MaxInt16 {
-		decErr("decodeExt: tag must be <= 0xffff; got: %v", u)
-	}
-	realxtag = uint16(u)
+	realxtag = u
 	if ext == nil {
 		re := rv.Interface().(*RawExt)
 		re.Tag = realxtag
@@ -490,10 +487,7 @@ func (d *cborDecDriver) decodeNaked(de *Decoder) (v interface{}, vt valueType, d
 			var re RawExt
 			ui := d.decUint()
 			d.bdRead = false
-			if ui > math.MaxInt16 {
-				decErr("decodeExt: tag must be <= 0xffff; got: %v", ui)
-			}
-			re.Tag = uint16(ui)
+			re.Tag = ui
 			de.decode(&re.Value)
 			v = &re
 			// decodeFurther = true
@@ -510,7 +504,8 @@ func (d *cborDecDriver) decodeNaked(de *Decoder) (v interface{}, vt valueType, d
 
 // -------------------------
 
-// CborHandle is a Handle for the CBOR encoding format, defined at http://cbor.io .
+// CborHandle is a Handle for the CBOR encoding format,
+// defined at http://tools.ietf.org/html/rfc7049 and documented further at http://cbor.io .
 //
 // CBOR is comprehensively supported, including support for:
 //   - indefinite-length arrays/maps/bytes/strings

+ 178 - 0
codec/cbor_test.go

@@ -0,0 +1,178 @@
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+	"bytes"
+	"encoding/hex"
+	"encoding/json"
+	"os"
+	"strconv"
+	"testing"
+)
+
+func TestCborIndefiniteLength(t *testing.T) {
+	oldMapType := testCborH.MapType
+	defer func() {
+		testCborH.MapType = oldMapType
+	}()
+	testCborH.MapType = testMapStrIntfTyp
+	// var (
+	// 	M1 map[string][]byte
+	// 	M2 map[uint64]bool
+	// 	L1 []interface{}
+	// 	S1 []string
+	// 	B1 []byte
+	// )
+	var v, vv interface{}
+	// define it (v), encode it using indefinite lengths, decode it (vv), compare v to vv
+	v = map[string]interface{}{
+		"one-byte-key":   []byte{1, 2, 3, 4, 5, 6},
+		"two-string-key": "two-value",
+		"three-list-key": []interface{}{true, false, uint64(1), int64(-1)},
+	}
+	var buf bytes.Buffer
+	// buf.Reset()
+	e := NewEncoder(&buf, testCborH)
+	buf.WriteByte(cborBdIndefiniteMap)
+	//----
+	buf.WriteByte(cborBdIndefiniteString)
+	e.MustEncode("one-")
+	e.MustEncode("byte-")
+	e.MustEncode("key")
+	buf.WriteByte(cborBdBreak)
+
+	buf.WriteByte(cborBdIndefiniteBytes)
+	e.MustEncode([]byte{1, 2, 3})
+	e.MustEncode([]byte{4, 5, 6})
+	buf.WriteByte(cborBdBreak)
+
+	//----
+	buf.WriteByte(cborBdIndefiniteString)
+	e.MustEncode("two-")
+	e.MustEncode("string-")
+	e.MustEncode("key")
+	buf.WriteByte(cborBdBreak)
+
+	buf.WriteByte(cborBdIndefiniteString)
+	e.MustEncode([]byte("two-")) // encode as bytes, to check robustness of code
+	e.MustEncode([]byte("value"))
+	buf.WriteByte(cborBdBreak)
+
+	//----
+	buf.WriteByte(cborBdIndefiniteString)
+	e.MustEncode("three-")
+	e.MustEncode("list-")
+	e.MustEncode("key")
+	buf.WriteByte(cborBdBreak)
+
+	buf.WriteByte(cborBdIndefiniteArray)
+	e.MustEncode(true)
+	e.MustEncode(false)
+	e.MustEncode(uint64(1))
+	e.MustEncode(int64(-1))
+	buf.WriteByte(cborBdBreak)
+
+	buf.WriteByte(cborBdBreak) // close map
+
+	NewDecoderBytes(buf.Bytes(), testCborH).MustDecode(&vv)
+	if err := deepEqual(v, vv); err != nil {
+		logT(t, "-------- Before and After marshal do not match: Error: %v", err)
+		logT(t, "    ....... GOLDEN:  (%T) %#v", v, v)
+		logT(t, "    ....... DECODED: (%T) %#v", vv, vv)
+		failT(t)
+	}
+}
+
+type testCborGolden struct {
+	Base64    string      `json:"cbor"`
+	Hex       string      `json:"hex"`
+	Roundtrip bool        `json:"roundtrip"`
+	Decoded   interface{} `json:"decoded"`
+}
+
+// __TestCborGoldens is disabled because it includes numbers outside the range of int64/uint64
+// and it doesn't support diagnostic checking.
+func __TestCborGoldens(t *testing.T) {
+	// decode test-cbor-goldens.json into a list of []*testCborGolden
+	// for each one,
+	// - decode hex into []byte bs
+	// - decode bs into interface{} v
+	// - compare both using deepequal
+	// - for any miss, record it
+	var gs []*testCborGolden
+	f, err := os.Open("test-cbor-goldens.json")
+	if err != nil {
+		logT(t, "error opening test-cbor-goldens.json: %v", err)
+		failT(t)
+	}
+	d := json.NewDecoder(f)
+	d.UseNumber()
+	err = d.Decode(&gs)
+	if err != nil {
+		logT(t, "error json decoding test-cbor-goldens.json: %v", err)
+		failT(t)
+	}
+	for i, g := range gs {
+		bs, err := hex.DecodeString(g.Hex)
+		if err != nil {
+			logT(t, "[%v] error hex decoding %s [%v]: %v", i, g.Hex, err)
+			failT(t)
+		}
+		var v interface{}
+		NewDecoderBytes(bs, testCborH).MustDecode(&v)
+		if _, ok := v.(RawExt); ok {
+			continue
+		}
+		if x, ok := g.Decoded.(json.Number); ok {
+			var doContinue bool
+			js := x.String()
+
+			switch v2 := v.(type) {
+			case float64:
+				xx, err := strconv.ParseFloat(js, 64)
+				if err != nil {
+					logT(t, "[%v] cannot parse decoded value as float64 (expect %v): %v", i, v2, err)
+					failT(t)
+				}
+				if xx != v2 {
+					logT(t, "[%v] float64 value mismatch: golden: %v, decoded: %v", i, xx, v2)
+					failT(t)
+				}
+				doContinue = true
+			case int64:
+				xx, err := strconv.ParseInt(js, 10, 64)
+				if err != nil {
+					logT(t, "[%v] cannot parse decoded value as int64 (expect %v): %v", i, v2, err)
+					failT(t)
+				}
+				if xx != v2 {
+					logT(t, "[%v] int64 value mismatch: golden: %v, decoded: %v", i, xx, v2)
+					failT(t)
+				}
+				doContinue = true
+			case uint64:
+				xx, err := strconv.ParseUint(js, 10, 64)
+				if err != nil {
+					logT(t, "[%v] cannot parse decoded value as uint64 (expect %v): %v", i, v2, err)
+					failT(t)
+				}
+				if xx != v2 {
+					logT(t, "[%v] uint64 value mismatch: golden: %v, decoded: %v", i, xx, v2)
+					failT(t)
+				}
+				doContinue = true
+			}
+			if doContinue {
+				continue
+			}
+		}
+		if err = deepEqual(g.Decoded, v); err != nil {
+			logT(t, "[%v] deepEqual error: %v", i, err)
+			logT(t, "    ....... GOLDEN:  (%T) %#v", g.Decoded, g.Decoded)
+			logT(t, "    ....... DECODED: (%T) %#v", v, v)
+			failT(t)
+		}
+	}
+}

+ 0 - 73
codec/codecs_test.go

@@ -1079,79 +1079,6 @@ func TestCodecUnderlyingType(t *testing.T) {
 	}
 }
 
-func TestCborIndefiniteLength(t *testing.T) {
-	oldMapType := testCborH.MapType
-	defer func() {
-		testCborH.MapType = oldMapType
-	}()
-	testCborH.MapType = testMapStrIntfTyp
-	// var (
-	// 	M1 map[string][]byte
-	// 	M2 map[uint64]bool
-	// 	L1 []interface{}
-	// 	S1 []string
-	// 	B1 []byte
-	// )
-	var v, vv interface{}
-	// define it (v), encode it using indefinite lengths, decode it (vv), compare v to vv
-	v = map[string]interface{}{
-		"one-byte-key":   []byte{1, 2, 3, 4, 5, 6},
-		"two-string-key": "two-value",
-		"three-list-key": []interface{}{true, false, uint64(1), int64(-1)},
-	}
-	var buf bytes.Buffer
-	// buf.Reset()
-	e := NewEncoder(&buf, testCborH)
-	buf.WriteByte(cborBdIndefiniteMap)
-	//----
-	buf.WriteByte(cborBdIndefiniteString)
-	e.MustEncode("one-")
-	e.MustEncode("byte-")
-	e.MustEncode("key")
-	buf.WriteByte(cborBdBreak)
-
-	buf.WriteByte(cborBdIndefiniteBytes)
-	e.MustEncode([]byte{1, 2, 3})
-	e.MustEncode([]byte{4, 5, 6})
-	buf.WriteByte(cborBdBreak)
-
-	//----
-	buf.WriteByte(cborBdIndefiniteString)
-	e.MustEncode("two-")
-	e.MustEncode("string-")
-	e.MustEncode("key")
-	buf.WriteByte(cborBdBreak)
-
-	buf.WriteByte(cborBdIndefiniteString)
-	e.MustEncode([]byte("two-")) // encode as bytes, to check robustness of code
-	e.MustEncode([]byte("value"))
-	buf.WriteByte(cborBdBreak)
-
-	//----
-	buf.WriteByte(cborBdIndefiniteString)
-	e.MustEncode("three-")
-	e.MustEncode("list-")
-	e.MustEncode("key")
-	buf.WriteByte(cborBdBreak)
-
-	buf.WriteByte(cborBdIndefiniteArray)
-	e.MustEncode(true)
-	e.MustEncode(false)
-	e.MustEncode(uint64(1))
-	e.MustEncode(int64(-1))
-	buf.WriteByte(cborBdBreak)
-
-	buf.WriteByte(cborBdBreak) // close map
-
-	NewDecoderBytes(buf.Bytes(), testCborH).MustDecode(&vv)
-	if err := deepEqual(v, vv); err != nil {
-		logT(t, "-------- Before and After marshal do not match: Error: %v", err)
-		logT(t, "    ....... GOLDEN:  (%T) %#v", v, v)
-		logT(t, "    ....... DECODED: (%T) %#v", vv, vv)
-		failT(t)
-	}
-}
-
 // TODO:
 //   Add Tests for:
 //   - decoding empty list/map in stream into a nil slice/map

+ 9 - 2
codec/decode.go

@@ -49,7 +49,7 @@ type decDriver interface {
 	decodeString() (s string)
 	decodeBytes(bs []byte) (bsOut []byte, changed bool)
 	// decodeExt will decode into a *RawExt or into an extension.
-	decodeExt(rv reflect.Value, xtag uint16, ext Ext, d *Decoder) (realxtag uint16)
+	decodeExt(rv reflect.Value, xtag uint64, ext Ext, d *Decoder) (realxtag uint64)
 	// decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte)
 	readMapLen() int
 	readArrayLen() int
@@ -191,7 +191,7 @@ type decFnInfo struct {
 	d     *Decoder
 	dd    decDriver
 	xfFn  Ext
-	xfTag uint16
+	xfTag uint64
 	array bool
 }
 
@@ -922,6 +922,13 @@ func decContLens(dd decDriver, currEncodedType valueType) (containerLen, contain
 	return
 }
 
+// func decToInt64(ui uint64) int64 {
+// 	if ui2 := ui & 0x7fffffffffffffff; ui2 > math.MaxInt64 {
+// 		decErr("uint64 value greater than max int64; got %v", ui2)
+// 	}
+// 	return int64(ui)
+// }
+
 func decErr(format string, params ...interface{}) {
 	doPanic(msgTagDec, format, params...)
 }

+ 2 - 2
codec/encode.go

@@ -64,7 +64,7 @@ type encDriver interface {
 	encodeFloat64(f float64)
 	// encodeExtPreamble(xtag byte, length int)
 	encodeRawExt(re *RawExt, e *Encoder)
-	encodeExt(rv reflect.Value, xtag uint16, ext Ext, e *Encoder)
+	encodeExt(rv reflect.Value, xtag uint64, ext Ext, e *Encoder)
 	encodeArrayPreamble(length int)
 	encodeMapPreamble(length int)
 	encodeString(c charEncoding, v string)
@@ -278,7 +278,7 @@ type encFnInfo struct {
 	e     *Encoder
 	ee    encDriver
 	xfFn  Ext
-	xfTag uint16
+	xfTag uint64
 }
 
 func (f *encFnInfo) builtin(rv reflect.Value) {

+ 6 - 6
codec/helper.go

@@ -154,7 +154,7 @@ type Handle interface {
 //
 // Only one of Data or Value is nil. If Data is nil, then the content of the RawExt is in the Value.
 type RawExt struct {
-	Tag uint16
+	Tag uint64
 	// Data is the []byte which represents the raw ext. If Data is nil, ext is exposed in Value.
 	// Data is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types
 	Data []byte
@@ -225,7 +225,7 @@ func (_ noStreamingCodec) checkBreak() bool { return false }
 type extTypeTagFn struct {
 	rtid uintptr
 	rt   reflect.Type
-	tag  uint16
+	tag  uint64
 	ext  Ext
 }
 
@@ -241,9 +241,9 @@ func (o *extHandle) AddExt(
 	encfn func(reflect.Value) ([]byte, error), decfn func(reflect.Value, []byte) error,
 ) (err error) {
 	if encfn == nil || decfn == nil {
-		return o.SetExt(rt, uint16(tag), nil)
+		return o.SetExt(rt, uint64(tag), nil)
 	}
-	return o.SetExt(rt, uint16(tag), bytesExt{encfn, decfn})
+	return o.SetExt(rt, uint64(tag), bytesExt{encfn, decfn})
 }
 
 // SetExt registers a tag and Ext for a reflect.Type.
@@ -252,7 +252,7 @@ func (o *extHandle) AddExt(
 // a pointer or Interface. An error is returned if that is not honored.
 //
 // To Deregister an ext, call SetExt with nil Ext
-func (o *extHandle) SetExt(rt reflect.Type, tag uint16, ext Ext) (err error) {
+func (o *extHandle) SetExt(rt reflect.Type, tag uint64, ext Ext) (err error) {
 	// o is a pointer, because we may need to initialize it
 	if rt.PkgPath() == "" || rt.Kind() == reflect.Interface {
 		err = fmt.Errorf("codec.Handle.AddExt: Takes named type, especially not a pointer or interface: %T",
@@ -281,7 +281,7 @@ func (o extHandle) getExt(rtid uintptr) *extTypeTagFn {
 	return nil
 }
 
-func (o extHandle) getExtForTag(tag uint16) *extTypeTagFn {
+func (o extHandle) getExtForTag(tag uint64) *extTypeTagFn {
 	for _, v := range o {
 		if v.tag == tag {
 			return v

+ 7 - 4
codec/msgpack.go

@@ -169,7 +169,7 @@ func (e *msgpackEncDriver) encodeFloat64(f float64) {
 	e.w.writeUint64(math.Float64bits(f))
 }
 
-func (e *msgpackEncDriver) encodeExt(rv reflect.Value, xtag uint16, ext Ext, _ *Encoder) {
+func (e *msgpackEncDriver) encodeExt(rv reflect.Value, xtag uint64, ext Ext, _ *Encoder) {
 	bs := ext.WriteExt(rv)
 	if bs == nil {
 		e.encodeNil()
@@ -363,7 +363,7 @@ func (d *msgpackDecDriver) decodeNaked(_ *Decoder) (v interface{}, vt valueType,
 		case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
 			clen := d.readExtLen()
 			var re RawExt
-			re.Tag = uint16(d.r.readn1())
+			re.Tag = uint64(d.r.readn1())
 			re.Data = d.r.readn(clen)
 			v = &re
 			vt = valueTypeExt
@@ -663,9 +663,12 @@ func (d *msgpackDecDriver) readExtLen() (clen int) {
 	return
 }
 
-func (d *msgpackDecDriver) decodeExt(rv reflect.Value, xtag uint16, ext Ext, _ *Decoder) (realxtag uint16) {
+func (d *msgpackDecDriver) decodeExt(rv reflect.Value, xtag uint64, ext Ext, _ *Decoder) (realxtag uint64) {
+	if xtag > 0xff {
+		decErr("decodeExt: tag must be <= 0xff; got: %v", xtag)
+	}
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
-	realxtag = uint16(realxtag1)
+	realxtag = uint64(realxtag1)
 	if ext == nil {
 		re := rv.Interface().(*RawExt)
 		re.Tag = realxtag

+ 7 - 4
codec/simple.go

@@ -104,7 +104,7 @@ func (e *simpleEncDriver) encLen(bd byte, length int) {
 	}
 }
 
-func (e *simpleEncDriver) encodeExt(rv reflect.Value, xtag uint16, ext Ext, _ *Encoder) {
+func (e *simpleEncDriver) encodeExt(rv reflect.Value, xtag uint64, ext Ext, _ *Encoder) {
 	bs := ext.WriteExt(rv)
 	if bs == nil {
 		e.encodeNil()
@@ -354,9 +354,12 @@ func (d *simpleDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) {
 	return
 }
 
-func (d *simpleDecDriver) decodeExt(rv reflect.Value, xtag uint16, ext Ext, _ *Decoder) (realxtag uint16) {
+func (d *simpleDecDriver) decodeExt(rv reflect.Value, xtag uint64, ext Ext, _ *Decoder) (realxtag uint64) {
+	if xtag > 0xff {
+		decErr("decodeExt: tag must be <= 0xff; got: %v", xtag)
+	}
 	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
-	realxtag = uint16(realxtag1)
+	realxtag = uint64(realxtag1)
 	if ext == nil {
 		re := rv.Interface().(*RawExt)
 		re.Tag = realxtag
@@ -426,7 +429,7 @@ func (d *simpleDecDriver) decodeNaked(_ *Decoder) (v interface{}, vt valueType,
 		vt = valueTypeExt
 		l := d.decLen()
 		var re RawExt
-		re.Tag = uint16(d.r.readn1())
+		re.Tag = uint64(d.r.readn1())
 		re.Data = d.r.readn(l)
 		v = &re
 	case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:

+ 636 - 0
codec/test-cbor-goldens.json

@@ -0,0 +1,636 @@
+[
+  {
+    "cbor": "AA==",
+    "hex": "00",
+    "roundtrip": true,
+    "decoded": 0
+  },
+  {
+    "cbor": "AQ==",
+    "hex": "01",
+    "roundtrip": true,
+    "decoded": 1
+  },
+  {
+    "cbor": "Cg==",
+    "hex": "0a",
+    "roundtrip": true,
+    "decoded": 10
+  },
+  {
+    "cbor": "Fw==",
+    "hex": "17",
+    "roundtrip": true,
+    "decoded": 23
+  },
+  {
+    "cbor": "GBg=",
+    "hex": "1818",
+    "roundtrip": true,
+    "decoded": 24
+  },
+  {
+    "cbor": "GBk=",
+    "hex": "1819",
+    "roundtrip": true,
+    "decoded": 25
+  },
+  {
+    "cbor": "GGQ=",
+    "hex": "1864",
+    "roundtrip": true,
+    "decoded": 100
+  },
+  {
+    "cbor": "GQPo",
+    "hex": "1903e8",
+    "roundtrip": true,
+    "decoded": 1000
+  },
+  {
+    "cbor": "GgAPQkA=",
+    "hex": "1a000f4240",
+    "roundtrip": true,
+    "decoded": 1000000
+  },
+  {
+    "cbor": "GwAAAOjUpRAA",
+    "hex": "1b000000e8d4a51000",
+    "roundtrip": true,
+    "decoded": 1000000000000
+  },
+  {
+    "cbor": "G///////////",
+    "hex": "1bffffffffffffffff",
+    "roundtrip": true,
+    "decoded": 18446744073709551615
+  },
+  {
+    "cbor": "wkkBAAAAAAAAAAA=",
+    "hex": "c249010000000000000000",
+    "roundtrip": true,
+    "decoded": 18446744073709551616
+  },
+  {
+    "cbor": "O///////////",
+    "hex": "3bffffffffffffffff",
+    "roundtrip": true,
+    "decoded": -18446744073709551616
+  },
+  {
+    "cbor": "w0kBAAAAAAAAAAA=",
+    "hex": "c349010000000000000000",
+    "roundtrip": true,
+    "decoded": -18446744073709551617
+  },
+  {
+    "cbor": "IA==",
+    "hex": "20",
+    "roundtrip": true,
+    "decoded": -1
+  },
+  {
+    "cbor": "KQ==",
+    "hex": "29",
+    "roundtrip": true,
+    "decoded": -10
+  },
+  {
+    "cbor": "OGM=",
+    "hex": "3863",
+    "roundtrip": true,
+    "decoded": -100
+  },
+  {
+    "cbor": "OQPn",
+    "hex": "3903e7",
+    "roundtrip": true,
+    "decoded": -1000
+  },
+  {
+    "cbor": "+QAA",
+    "hex": "f90000",
+    "roundtrip": true,
+    "decoded": 0.0
+  },
+  {
+    "cbor": "+YAA",
+    "hex": "f98000",
+    "roundtrip": true,
+    "decoded": -0.0
+  },
+  {
+    "cbor": "+TwA",
+    "hex": "f93c00",
+    "roundtrip": true,
+    "decoded": 1.0
+  },
+  {
+    "cbor": "+z/xmZmZmZma",
+    "hex": "fb3ff199999999999a",
+    "roundtrip": true,
+    "decoded": 1.1
+  },
+  {
+    "cbor": "+T4A",
+    "hex": "f93e00",
+    "roundtrip": true,
+    "decoded": 1.5
+  },
+  {
+    "cbor": "+Xv/",
+    "hex": "f97bff",
+    "roundtrip": true,
+    "decoded": 65504.0
+  },
+  {
+    "cbor": "+kfDUAA=",
+    "hex": "fa47c35000",
+    "roundtrip": true,
+    "decoded": 100000.0
+  },
+  {
+    "cbor": "+n9///8=",
+    "hex": "fa7f7fffff",
+    "roundtrip": true,
+    "decoded": 3.4028234663852886e+38
+  },
+  {
+    "cbor": "+3435DyIAHWc",
+    "hex": "fb7e37e43c8800759c",
+    "roundtrip": true,
+    "decoded": 1.0e+300
+  },
+  {
+    "cbor": "+QAB",
+    "hex": "f90001",
+    "roundtrip": true,
+    "decoded": 5.960464477539063e-08
+  },
+  {
+    "cbor": "+QQA",
+    "hex": "f90400",
+    "roundtrip": true,
+    "decoded": 6.103515625e-05
+  },
+  {
+    "cbor": "+cQA",
+    "hex": "f9c400",
+    "roundtrip": true,
+    "decoded": -4.0
+  },
+  {
+    "cbor": "+8AQZmZmZmZm",
+    "hex": "fbc010666666666666",
+    "roundtrip": true,
+    "decoded": -4.1
+  },
+  {
+    "cbor": "+XwA",
+    "hex": "f97c00",
+    "roundtrip": true,
+    "diagnostic": "Infinity"
+  },
+  {
+    "cbor": "+X4A",
+    "hex": "f97e00",
+    "roundtrip": true,
+    "diagnostic": "NaN"
+  },
+  {
+    "cbor": "+fwA",
+    "hex": "f9fc00",
+    "roundtrip": true,
+    "diagnostic": "-Infinity"
+  },
+  {
+    "cbor": "+n+AAAA=",
+    "hex": "fa7f800000",
+    "roundtrip": false,
+    "diagnostic": "Infinity"
+  },
+  {
+    "cbor": "+n/AAAA=",
+    "hex": "fa7fc00000",
+    "roundtrip": false,
+    "diagnostic": "NaN"
+  },
+  {
+    "cbor": "+v+AAAA=",
+    "hex": "faff800000",
+    "roundtrip": false,
+    "diagnostic": "-Infinity"
+  },
+  {
+    "cbor": "+3/wAAAAAAAA",
+    "hex": "fb7ff0000000000000",
+    "roundtrip": false,
+    "diagnostic": "Infinity"
+  },
+  {
+    "cbor": "+3/4AAAAAAAA",
+    "hex": "fb7ff8000000000000",
+    "roundtrip": false,
+    "diagnostic": "NaN"
+  },
+  {
+    "cbor": "+//wAAAAAAAA",
+    "hex": "fbfff0000000000000",
+    "roundtrip": false,
+    "diagnostic": "-Infinity"
+  },
+  {
+    "cbor": "9A==",
+    "hex": "f4",
+    "roundtrip": true,
+    "decoded": false
+  },
+  {
+    "cbor": "9Q==",
+    "hex": "f5",
+    "roundtrip": true,
+    "decoded": true
+  },
+  {
+    "cbor": "9g==",
+    "hex": "f6",
+    "roundtrip": true,
+    "decoded": null
+  },
+  {
+    "cbor": "9w==",
+    "hex": "f7",
+    "roundtrip": true,
+    "diagnostic": "undefined"
+  },
+  {
+    "cbor": "8A==",
+    "hex": "f0",
+    "roundtrip": true,
+    "diagnostic": "simple(16)"
+  },
+  {
+    "cbor": "+Bg=",
+    "hex": "f818",
+    "roundtrip": true,
+    "diagnostic": "simple(24)"
+  },
+  {
+    "cbor": "+P8=",
+    "hex": "f8ff",
+    "roundtrip": true,
+    "diagnostic": "simple(255)"
+  },
+  {
+    "cbor": "wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg==",
+    "hex": "c074323031332d30332d32315432303a30343a30305a",
+    "roundtrip": true,
+    "diagnostic": "0(\"2013-03-21T20:04:00Z\")"
+  },
+  {
+    "cbor": "wRpRS2ew",
+    "hex": "c11a514b67b0",
+    "roundtrip": true,
+    "diagnostic": "1(1363896240)"
+  },
+  {
+    "cbor": "wftB1FLZ7CAAAA==",
+    "hex": "c1fb41d452d9ec200000",
+    "roundtrip": true,
+    "diagnostic": "1(1363896240.5)"
+  },
+  {
+    "cbor": "10QBAgME",
+    "hex": "d74401020304",
+    "roundtrip": true,
+    "diagnostic": "23(h'01020304')"
+  },
+  {
+    "cbor": "2BhFZElFVEY=",
+    "hex": "d818456449455446",
+    "roundtrip": true,
+    "diagnostic": "24(h'6449455446')"
+  },
+  {
+    "cbor": "2CB2aHR0cDovL3d3dy5leGFtcGxlLmNvbQ==",
+    "hex": "d82076687474703a2f2f7777772e6578616d706c652e636f6d",
+    "roundtrip": true,
+    "diagnostic": "32(\"http://www.example.com\")"
+  },
+  {
+    "cbor": "QA==",
+    "hex": "40",
+    "roundtrip": true,
+    "diagnostic": "h''"
+  },
+  {
+    "cbor": "RAECAwQ=",
+    "hex": "4401020304",
+    "roundtrip": true,
+    "diagnostic": "h'01020304'"
+  },
+  {
+    "cbor": "YA==",
+    "hex": "60",
+    "roundtrip": true,
+    "decoded": ""
+  },
+  {
+    "cbor": "YWE=",
+    "hex": "6161",
+    "roundtrip": true,
+    "decoded": "a"
+  },
+  {
+    "cbor": "ZElFVEY=",
+    "hex": "6449455446",
+    "roundtrip": true,
+    "decoded": "IETF"
+  },
+  {
+    "cbor": "YiJc",
+    "hex": "62225c",
+    "roundtrip": true,
+    "decoded": "\"\\"
+  },
+  {
+    "cbor": "YsO8",
+    "hex": "62c3bc",
+    "roundtrip": true,
+    "decoded": "ü"
+  },
+  {
+    "cbor": "Y+awtA==",
+    "hex": "63e6b0b4",
+    "roundtrip": true,
+    "decoded": "水"
+  },
+  {
+    "cbor": "ZPCQhZE=",
+    "hex": "64f0908591",
+    "roundtrip": true,
+    "decoded": "𐅑"
+  },
+  {
+    "cbor": "gA==",
+    "hex": "80",
+    "roundtrip": true,
+    "decoded": [
+
+    ]
+  },
+  {
+    "cbor": "gwECAw==",
+    "hex": "83010203",
+    "roundtrip": true,
+    "decoded": [
+      1,
+      2,
+      3
+    ]
+  },
+  {
+    "cbor": "gwGCAgOCBAU=",
+    "hex": "8301820203820405",
+    "roundtrip": true,
+    "decoded": [
+      1,
+      [
+        2,
+        3
+      ],
+      [
+        4,
+        5
+      ]
+    ]
+  },
+  {
+    "cbor": "mBkBAgMEBQYHCAkKCwwNDg8QERITFBUWFxgYGBk=",
+    "hex": "98190102030405060708090a0b0c0d0e0f101112131415161718181819",
+    "roundtrip": true,
+    "decoded": [
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9,
+      10,
+      11,
+      12,
+      13,
+      14,
+      15,
+      16,
+      17,
+      18,
+      19,
+      20,
+      21,
+      22,
+      23,
+      24,
+      25
+    ]
+  },
+  {
+    "cbor": "oA==",
+    "hex": "a0",
+    "roundtrip": true,
+    "decoded": {
+    }
+  },
+  {
+    "cbor": "ogECAwQ=",
+    "hex": "a201020304",
+    "roundtrip": true,
+    "diagnostic": "{1: 2, 3: 4}"
+  },
+  {
+    "cbor": "omFhAWFiggID",
+    "hex": "a26161016162820203",
+    "roundtrip": true,
+    "decoded": {
+      "a": 1,
+      "b": [
+        2,
+        3
+      ]
+    }
+  },
+  {
+    "cbor": "gmFhoWFiYWM=",
+    "hex": "826161a161626163",
+    "roundtrip": true,
+    "decoded": [
+      "a",
+      {
+        "b": "c"
+      }
+    ]
+  },
+  {
+    "cbor": "pWFhYUFhYmFCYWNhQ2FkYURhZWFF",
+    "hex": "a56161614161626142616361436164614461656145",
+    "roundtrip": true,
+    "decoded": {
+      "a": "A",
+      "b": "B",
+      "c": "C",
+      "d": "D",
+      "e": "E"
+    }
+  },
+  {
+    "cbor": "X0IBAkMDBAX/",
+    "hex": "5f42010243030405ff",
+    "roundtrip": false,
+    "diagnostic": "(_ h'0102', h'030405')"
+  },
+  {
+    "cbor": "f2VzdHJlYWRtaW5n/w==",
+    "hex": "7f657374726561646d696e67ff",
+    "roundtrip": false,
+    "decoded": "streaming"
+  },
+  {
+    "cbor": "n/8=",
+    "hex": "9fff",
+    "roundtrip": false,
+    "decoded": [
+
+    ]
+  },
+  {
+    "cbor": "nwGCAgOfBAX//w==",
+    "hex": "9f018202039f0405ffff",
+    "roundtrip": false,
+    "decoded": [
+      1,
+      [
+        2,
+        3
+      ],
+      [
+        4,
+        5
+      ]
+    ]
+  },
+  {
+    "cbor": "nwGCAgOCBAX/",
+    "hex": "9f01820203820405ff",
+    "roundtrip": false,
+    "decoded": [
+      1,
+      [
+        2,
+        3
+      ],
+      [
+        4,
+        5
+      ]
+    ]
+  },
+  {
+    "cbor": "gwGCAgOfBAX/",
+    "hex": "83018202039f0405ff",
+    "roundtrip": false,
+    "decoded": [
+      1,
+      [
+        2,
+        3
+      ],
+      [
+        4,
+        5
+      ]
+    ]
+  },
+  {
+    "cbor": "gwGfAgP/ggQF",
+    "hex": "83019f0203ff820405",
+    "roundtrip": false,
+    "decoded": [
+      1,
+      [
+        2,
+        3
+      ],
+      [
+        4,
+        5
+      ]
+    ]
+  },
+  {
+    "cbor": "nwECAwQFBgcICQoLDA0ODxAREhMUFRYXGBgYGf8=",
+    "hex": "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff",
+    "roundtrip": false,
+    "decoded": [
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9,
+      10,
+      11,
+      12,
+      13,
+      14,
+      15,
+      16,
+      17,
+      18,
+      19,
+      20,
+      21,
+      22,
+      23,
+      24,
+      25
+    ]
+  },
+  {
+    "cbor": "v2FhAWFinwID//8=",
+    "hex": "bf61610161629f0203ffff",
+    "roundtrip": false,
+    "decoded": {
+      "a": 1,
+      "b": [
+        2,
+        3
+      ]
+    }
+  },
+  {
+    "cbor": "gmFhv2FiYWP/",
+    "hex": "826161bf61626163ff",
+    "roundtrip": false,
+    "decoded": [
+      "a",
+      {
+        "b": "c"
+      }
+    ]
+  },
+  {
+    "cbor": "v2NGdW71Y0FtdCH/",
+    "hex": "bf6346756ef563416d7421ff",
+    "roundtrip": false,
+    "decoded": {
+      "Fun": true,
+      "Amt": -2
+    }
+  }
+]