diff --git a/README.md b/README.md
index 57e6026e..8d3ed524 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ CBOR is a [trusted alternative](https://www.rfc-editor.org/rfc/rfc8949.html#name
`fxamacker/cbor` is used in projects by Arm Ltd., Cisco, Dapper Labs, EdgeX Foundry, Fraunhofer‑AISEC, Linux Foundation, Microsoft, Mozilla, Oasis Protocol, Tailscale, Teleport, [and others](https://github.com/fxamacker/cbor#who-uses-fxamackercbor).
-See [Quick Start](#quick-start) if you have not yet used v2.5.0.
+See [Quick Start](#quick-start) and [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0). New funcs `UnmarshalFirst` and `DiagnoseFirst` return remaining bytes.
## fxamacker/cbor
@@ -23,24 +23,93 @@ See [Quick Start](#quick-start) if you have not yet used v2.5.0.
Features include full support for CBOR tags, [Core Deterministic Encoding](https://www.rfc-editor.org/rfc/rfc8949.html#name-core-deterministic-encoding), duplicate map key detection, etc.
-Struct tags (`toarray`, `keyasint`, `omitempty`) reduce encoded size of structs.
+Design balances trade-offs between security, speed, concurrency, encoded data size, usability, etc.
-![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags")
+Highlights
-API is mostly same as `encoding/json`, plus interfaces that simplify concurrency for CBOR options.
+__π Speed__
+
+Encoding and decoding is fast without using Go's `unsafe` package. Slower settings are opt-in. Default limits allow very fast and memory efficient rejection of malformed CBOR data.
+
+__π Security__
+
+Decoder has configurable limits that defend against malicious inputs. Duplicate map key detection is supported. By contrast, `encoding/gob` is [not designed to be hardened against adversarial inputs](https://pkg.go.dev/encoding/gob#hdr-Security).
+
+Codec passed multiple confidential security assessments in 2022. No vulnerabilities found in subset of codec in a [nonconfidential security assessment](https://github.com/veraison/go-cose/blob/v1.0.0-rc.1/reports/NCC_Microsoft-go-cose-Report_2022-05-26_v1.0.pdf) prepared by NCC Group for Microsoft Corporation.
+
+__ποΈ Data Size__
+
+Struct tags (`toarray`, `keyasint`, `omitempty`) automatically reduce size of encoded structs. Encoding optionally shrinks float64β32β16 when values fit.
+
+__:jigsaw: Usability__
+
+API is mostly same as `encoding/json` plus interfaces that simplify concurrency for CBOR options. Encoding and decoding modes can be created at startup and reused by any goroutines.
-#### CBOR Security
+Presets include Core Deterministic Encoding, Preferred Serialization, CTAP2 Canonical CBOR, etc.
+
+__π Extensibility__
-Decoder has configurable limits that defend against malicious inputs. Duplicate map key detection is supported.
+Features include CBOR [extension points](https://www.rfc-editor.org/rfc/rfc8949.html#section-7.1) (e.g. CBOR tags) and extensive settings. API has interfaces that allow users to create custom encoding and decoding without modifying this library.
+
+
+
+
+
+### Secure Decoding with Configurable Settings
+
+`fxamacker/cbor` has configurable limits, etc. that defend against malicious CBOR data.
By contrast, `encoding/gob` is [not designed to be hardened against adversarial inputs](https://pkg.go.dev/encoding/gob#hdr-Security).
-Decoding 10 bytes of malicious CBOR data directly into `[]byte` with default settings:
+Example decoding with encoding/gob π₯ fatal error (out of memory)
+
+```Go
+// Example of encoding/gob having "fatal error: runtime: out of memory"
+// while decoding 181 bytes.
+package main
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/hex"
+ "fmt"
+)
+
+// Example data is from https://github.com/golang/go/issues/24446
+// (shortened to 181 bytes).
+const data = "4dffb503010102303001ff30000109010130010800010130010800010130" +
+ "01ffb80001014a01ffb60001014b01ff860001013001ff860001013001ff" +
+ "860001013001ff860001013001ffb80000001eff850401010e3030303030" +
+ "30303030303030303001ff3000010c0104000016ffb70201010830303030" +
+ "3030303001ff3000010c000030ffb6040405fcff00303030303030303030" +
+ "303030303030303030303030303030303030303030303030303030303030" +
+ "30"
+
+type X struct {
+ J *X
+ K map[string]int
+}
+
+func main() {
+ raw, _ := hex.DecodeString(data)
+ decoder := gob.NewDecoder(bytes.NewReader(raw))
+
+ var x X
+ decoder.Decode(&x) // fatal error: runtime: out of memory
+ fmt.Println("Decoding finished.")
+}
+```
+
+
+
+
+
+`fxamacker/cbor` is fast at rejecting malformed CBOR data. E.g. attempts to
+decode 10 bytes of malicious CBOR data to `[]byte` (with default settings):
| Codec | Speed (ns/op) | Memory | Allocs |
| :---- | ------------: | -----: | -----: |
-| fxamacker/cbor 2.5.0 | 43.95n Β± 5% | 32 B/op | 2 allocs/op |
-| ugorji/go 1.2.11 | 5353261.00n Β± 4% | 67111321 B/op | 13 allocs/op |
+| fxamacker/cbor 2.5.0 | 44 Β± 5% | 32 B/op | 2 allocs/op |
+| ugorji/go 1.2.11 | 5353261 Β± 4% | 67111321 B/op | 13 allocs/op |
Benchmark details
@@ -62,40 +131,88 @@ Latest comparison used:
- go1.19.6, linux/amd64, i5-13600K (DDR4)
- go test -bench=. -benchmem -count=20
+
+
-#### Design and Feature Highlights
+### Smaller Encodings with Struct Tags
-Design balances tradeoffs between speed, security, memory, encoded data size, usability, etc.
+Struct tags (`toarray`, `keyasint`, `omitempty`) reduce encoded size of structs.
-Highlights
+Example encoding 3-level nested Go struct to 1 byte CBOR
-__π Speed__
+https://go.dev/play/p/YxwvfPdFQG2
-Encoding and decoding is fast without using Go's `unsafe` package. Slower settings are opt-in. Default limits allow very fast and memory efficient rejection of malformed CBOR data.
+```Go
+// Example encoding nested struct (with omitempty tag)
+// - encoding/json: 18 byte JSON
+// - fxamacker/cbor: 1 byte CBOR
+package main
-__π Security__
+import (
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
-Decoder has configurable limits that defend against malicious inputs. Duplicate map key detection is supported. By contrast, `encoding/gob` is [not designed to be hardened against adversarial inputs](https://pkg.go.dev/encoding/gob#hdr-Security).
+ "github.com/fxamacker/cbor/v2"
+)
-Codec passed multiple confidential security assessments in 2022. No vulnerabilities found in subset of codec in a [nonconfidential security assessment](https://github.com/veraison/go-cose/blob/v1.0.0-rc.1/reports/NCC_Microsoft-go-cose-Report_2022-05-26_v1.0.pdf) prepared by NCC Group for Microsoft Corporation.
+type GrandChild struct {
+ Quux int `json:",omitempty"`
+}
-__ποΈ Data Size__
+type Child struct {
+ Baz int `json:",omitempty"`
+ Qux GrandChild `json:",omitempty"`
+}
-Struct tags (`toarray`, `keyasint`, `omitempty`) automatically reduce size of encoded structs. Encoding optionally shrinks float64β32β16 when values fit.
+type Parent struct {
+ Foo Child `json:",omitempty"`
+ Bar int `json:",omitempty"`
+}
-__:jigsaw: Usability__
+func cb() {
+ results, _ := cbor.Marshal(Parent{})
+ fmt.Println("hex(CBOR): " + hex.EncodeToString(results))
-API is mostly same as `encoding/json` plus interfaces that simplify concurrency for CBOR options. Encoding and decoding modes can be created at startup and reused by any goroutines.
+ text, _ := cbor.Diagnose(results) // Diagnostic Notation
+ fmt.Println("DN: " + text)
+}
-Presets include Core Deterministic Encoding, Preferred Serialization, CTAP2 Canonical CBOR, etc.
+func js() {
+ results, _ := json.Marshal(Parent{})
+ fmt.Println("hex(JSON): " + hex.EncodeToString(results))
-__π Extensibility__
+ text := string(results) // JSON
+ fmt.Println("JSON: " + text)
+}
-Features include CBOR [extension points](https://www.rfc-editor.org/rfc/rfc8949.html#section-7.1) (e.g. CBOR tags) and extensive settings. API has interfaces that allow users to create custom encoding and decoding without modifying this library.
+func main() {
+ cb()
+ fmt.Println("-------------")
+ js()
+}
+```
+
+Output (DN is Diagnostic Notation):
+```
+hex(CBOR): a0
+DN: {}
+-------------
+hex(JSON): 7b22466f6f223a7b22517578223a7b7d7d7d
+JSON: {"Foo":{"Qux":{}}}
+```
+
+
+Example using different struct tags together:
+
+![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags")
+
+API is mostly same as `encoding/json`, plus interfaces that simplify concurrency for CBOR options.
+
## Quick Start
__Install__: `go get github.com/fxamacker/cbor/v2` and `import "github.com/fxamacker/cbor/v2"`.
@@ -112,22 +229,22 @@ Package level functions only use this library's default settings.
They provide the "default mode" of encoding and decoding.
```go
-// API matches encoding/json.
+// API matches encoding/json for Marshal, Unmarshal, Encode, Decode, etc.
b, err = cbor.Marshal(v) // encode v to []byte b
err = cbor.Unmarshal(b, &v) // decode []byte b to v
-encoder = cbor.NewEncoder(w) // create encoder with io.Writer w
decoder = cbor.NewDecoder(r) // create decoder with io.Reader r
-err = encoder.Encode(v) // encode v to a CBOR data item
err = decoder.Decode(&v) // decode a CBOR data item to v
-// v2.5.0 added new functions that can return remaining bytes.
+// v2.5.0 added new functions that return remaining bytes.
// UnmarshalFirst decodes first CBOR data item and returns remaining bytes.
-// Unlike Unmarshal, extraneous data is not treated as an error by UnmarshalFirst.
rest, err = cbor.UnmarshalFirst(b, &v) // decode []byte b to v
// DiagnoseFirst translates first CBOR data item to text and returns remaining bytes.
text, rest, err = cbor.DiagnoseFirst(b) // decode []byte b to Diagnostic Notation text
+
+// NOTE: Unmarshal returns ExtraneousDataError if there are remaining bytes,
+// but new funcs UnmarshalFirst and DiagnoseFirst do not.
```
__IMPORTANT__: π CBOR settings allow trade-offs between speed, security, encoding size, etc.
@@ -177,7 +294,75 @@ Default mode and custom modes automatically apply struct tags.
Struct tags (`toarray`, `keyasint`, `omitempty`) reduce encoded size of structs.
-Example using struct tags
+Example encoding 3-level nested Go struct to 1 byte CBOR
+
+https://go.dev/play/p/YxwvfPdFQG2
+
+```Go
+// Example encoding nested struct (with omitempty tag)
+// - encoding/json: 18 byte JSON
+// - fxamacker/cbor: 1 byte CBOR
+package main
+
+import (
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+
+ "github.com/fxamacker/cbor/v2"
+)
+
+type GrandChild struct {
+ Quux int `json:",omitempty"`
+}
+
+type Child struct {
+ Baz int `json:",omitempty"`
+ Qux GrandChild `json:",omitempty"`
+}
+
+type Parent struct {
+ Foo Child `json:",omitempty"`
+ Bar int `json:",omitempty"`
+}
+
+func cb() {
+ results, _ := cbor.Marshal(Parent{})
+ fmt.Println("hex(CBOR): " + hex.EncodeToString(results))
+
+ text, _ := cbor.Diagnose(results) // Diagnostic Notation
+ fmt.Println("DN: " + text)
+}
+
+func js() {
+ results, _ := json.Marshal(Parent{})
+ fmt.Println("hex(JSON): " + hex.EncodeToString(results))
+
+ text := string(results) // JSON
+ fmt.Println("JSON: " + text)
+}
+
+func main() {
+ cb()
+ fmt.Println("-------------")
+ js()
+}
+```
+
+Output (DN is Diagnostic Notation):
+```
+hex(CBOR): a0
+DN: {}
+-------------
+hex(JSON): 7b22466f6f223a7b22517578223a7b7d7d7d
+JSON: {"Foo":{"Qux":{}}}
+```
+
+
+
+
+
+Example using several struct tags
![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags")
@@ -267,12 +452,14 @@ Default limits may need to be increased for systems handling very large data (e.
## Status
-v2.5.0 was released on Sunday, August 13, 2023 with new features and important bug fixes. It is fuzz tested and production quality.
+v2.5.0 was released on Sunday, August 13, 2023 with new features and important bug fixes. It is fuzz tested and production quality after extended beta [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta) (Dec 2022) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Aug 2023).
__IMPORTANT__: π Before upgrading from v2.4 or older release, please read the notable changes highlighted in the release notes. v2.5.0 is a large release with bug fixes to error handling for extraneous data in `Unmarshal`, etc. that should be reviewed before upgrading.
See [v2.5.0 release notes](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) for list of new features, improvements, and bug fixes.
+See ["Version and API Changes"](https://github.com/fxamacker/cbor#versions-and-api-changes) section for more info about version numbering, etc.
+