Skip to content

Commit 4e5e2ad

Browse files
committed
Merge tag 'v2.9.0' into fxamacker/sync-stream-mode-branch-with-master
2 parents 6f932b0 + d29ad73 commit 4e5e2ad

25 files changed

Lines changed: 5474 additions & 2339 deletions

.github/workflows/ci-go-cover.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
- name: Checkout code
4343
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
4444
- name: Install Go
45-
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
45+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
4646
with:
4747
go-version: 1.24
4848
check-latest: true

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
go-version: ['1.20', 1.21, 1.22, 1.23, 1.24]
3535
steps:
3636
- name: Install Go
37-
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
37+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
3838
with:
3939
go-version: ${{ matrix.go-version }}
4040
check-latest: true

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535

3636
# Initializes the CodeQL tools for scanning.
3737
- name: Initialize CodeQL
38-
uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13
38+
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
3939
with:
4040
languages: ${{ matrix.language }}
4141

@@ -44,7 +44,7 @@ jobs:
4444
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
4545
# If this step fails, then you should remove it and run the build manually (see below)
4646
- name: Autobuild
47-
uses: github/codeql-action/autobuild@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13
47+
uses: github/codeql-action/autobuild@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
4848

4949
- name: Perform CodeQL Analysis
50-
uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13
50+
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2

.github/workflows/govulncheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
fetch-depth: 1
3434

3535
- name: Install Go and setup env
36-
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
36+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
3737
with:
3838
go-version: 1.23
3939
check-latest: true

.github/workflows/safer-golangci-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
fetch-depth: 1
4242

4343
- name: Setup Go
44-
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
44+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
4545
with:
4646
go-version: ${{ env.GO_VERSION }}
4747
check-latest: true

README.md

Lines changed: 209 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
CBOR is a [trusted alternative](https://www.rfc-editor.org/rfc/rfc8949.html#name-comparison-of-other-binary-) to JSON, MessagePack, Protocol Buffers, etc.  CBOR is an Internet Standard defined by [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94) and is designed to be relevant for decades.
66

7-
`fxamacker/cbor` is used in projects by Arm Ltd., Cisco, EdgeX Foundry, Flow Foundation, Fraunhofer‑AISEC, Kubernetes, Let's Encrypt (ISRG), Linux Foundation, Microsoft, Mozilla, Oasis Protocol, Tailscale, Teleport, [etc](https://github.com/fxamacker/cbor#who-uses-fxamackercbor).
7+
`fxamacker/cbor` is used in projects by Arm Ltd., EdgeX Foundry, Flow Foundation, Fraunhofer‑AISEC, IBM, Kubernetes[*](https://github.com/search?q=org%3Akubernetes%20fxamacker%2Fcbor&type=code), Let's Encrypt, Linux Foundation, Microsoft, Oasis Protocol, Red Hat[*](https://github.com/search?q=org%3Aopenshift+fxamacker%2Fcbor&type=code), Tailscale[*](https://github.com/search?q=org%3Atailscale+fxamacker%2Fcbor&type=code), Veraison[*](https://github.com/search?q=org%3Averaison+fxamacker%2Fcbor&type=code), [etc](https://github.com/fxamacker/cbor#who-uses-fxamackercbor).
88

99
See [Quick Start](#quick-start) and [Releases](https://github.com/fxamacker/cbor/releases/). 🆕 `UnmarshalFirst` and `DiagnoseFirst` can decode CBOR Sequences. `MarshalToBuffer` and `UserBufferEncMode` accepts user-specified buffer.
1010

@@ -39,7 +39,7 @@ Codec passed multiple confidential security assessments in 2022. No vulnerabili
3939

4040
__🗜️  Data Size__
4141

42-
Struct tag options (`toarray`, `keyasint`, `omitempty`, `omitzero`) automatically reduce size of encoded structs. Encoding optionally shrinks float64→32→16 when values fit.
42+
Struct tag options (`toarray`, `keyasint`, `omitempty`, `omitzero`) and field tag "-" automatically reduce size of encoded structs. Encoding optionally shrinks float64→32→16 when values fit.
4343

4444
__:jigsaw:  Usability__
4545

@@ -146,8 +146,12 @@ Struct tags automatically reduce encoded size of structs and improve speed.
146146
We can write less code by using struct tag options:
147147
- `toarray`: encode without field names (decode back to original struct)
148148
- `keyasint`: encode field names as integers (decode back to original struct)
149-
- `omitempty`: omit empty fields when encoding
150-
- `omitzero`: omit zero-value fields when encoding
149+
- `omitempty`: omit empty field when encoding
150+
- `omitzero`: omit zero-value field when encoding
151+
152+
As a special case, struct field tag "-" omits the field.
153+
154+
NOTE: When a struct uses `toarray`, the encoder will ignore `omitempty` and `omitzero` to prevent position of encoded array elements from changing. This allows decoder to match encoded elements to their Go struct field.
151155
152156
![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")
153157
@@ -353,6 +357,60 @@ err = em.MarshalToBuffer(v, &buf) // encode v to provided buf
353357

354358
Struct tag options (`toarray`, `keyasint`, `omitempty`, `omitzero`) reduce encoded size of structs.
355359

360+
As a special case, struct field tag "-" omits the field.
361+
362+
<details><summary> 🔎&nbsp; Example encoding with struct field tag "-"</summary><p/>
363+
364+
https://go.dev/play/p/aWEIFxd7InX
365+
366+
```Go
367+
// https://github.com/fxamacker/cbor/issues/652
368+
package main
369+
370+
import (
371+
"encoding/json"
372+
"fmt"
373+
374+
"github.com/fxamacker/cbor/v2"
375+
)
376+
377+
// The `cbor:"-"` tag omits the Type field when encoding to CBOR.
378+
type Entity struct {
379+
_ struct{} `cbor:",toarray"`
380+
ID uint64 `json:"id"`
381+
Type string `cbor:"-" json:"typeOf"`
382+
Name string `json:"name"`
383+
}
384+
385+
func main() {
386+
entity := Entity{
387+
ID: 1,
388+
Type: "int64",
389+
Name: "Identifier",
390+
}
391+
392+
c, _ := cbor.Marshal(entity)
393+
diag, _ := cbor.Diagnose(c)
394+
fmt.Printf("CBOR in hex: %x\n", c)
395+
fmt.Printf("CBOR in edn: %s\n", diag)
396+
397+
j, _ := json.Marshal(entity)
398+
fmt.Printf("JSON: %s\n", string(j))
399+
400+
fmt.Printf("JSON encoding is %d bytes\n", len(j))
401+
fmt.Printf("CBOR encoding is %d bytes\n", len(c))
402+
403+
// Output:
404+
// CBOR in hex: 82016a4964656e746966696572
405+
// CBOR in edn: [1, "Identifier"]
406+
// JSON: {"id":1,"typeOf":"int64","name":"Identifier"}
407+
// JSON encoding is 45 bytes
408+
// CBOR encoding is 13 bytes
409+
}
410+
```
411+
412+
</details>
413+
356414
<details><summary> 🔎&nbsp; Example encoding 3-level nested Go struct to 1 byte CBOR</summary><p/>
357415

358416
https://go.dev/play/p/YxwvfPdFQG2
@@ -476,6 +534,139 @@ if data, err := em.Marshal(v); err != nil {
476534

477535
</details>
478536

537+
👉 `fxamacker/cbor` allows user apps to use almost any current or future CBOR tag number by implementing `cbor.Marshaler` and `cbor.Unmarshaler` interfaces.
538+
539+
Basically, `MarshalCBOR` and `UnmarshalCBOR` functions can be implemented by user apps and those functions will automatically be called by this CBOR codec's `Marshal`, `Unmarshal`, etc.
540+
541+
The following [example](https://github.com/fxamacker/cbor/blob/master/example_embedded_json_tag_for_cbor_test.go) shows how to encode and decode a tagged CBOR data item with tag number 262. The tag content is a JSON object "embedded" as a CBOR byte string (major type 2).
542+
543+
<details><summary> 🔎&nbsp; Example using Embedded JSON Tag for CBOR (tag 262)</summary>
544+
545+
```go
546+
// https://github.com/fxamacker/cbor/issues/657
547+
548+
package cbor_test
549+
550+
// NOTE: RFC 8949 does not mention tag number 262. IANA assigned
551+
// CBOR tag number 262 as "Embedded JSON Object" specified by the
552+
// document Embedded JSON Tag for CBOR:
553+
//
554+
// "Tag 262 can be applied to a byte string (major type 2) to indicate
555+
// that the byte string is a JSON Object. The length of the byte string
556+
// indicates the content."
557+
//
558+
// For more info, see Embedded JSON Tag for CBOR at:
559+
// https://github.com/toravir/CBOR-Tag-Specs/blob/master/embeddedJSON.md
560+
561+
import (
562+
"bytes"
563+
"encoding/json"
564+
"fmt"
565+
566+
"github.com/fxamacker/cbor/v2"
567+
)
568+
569+
// cborTagNumForEmbeddedJSON is the CBOR tag number 262.
570+
const cborTagNumForEmbeddedJSON = 262
571+
572+
// EmbeddedJSON represents a Go value to be encoded as a tagged CBOR data item
573+
// with tag number 262 and the tag content is a JSON object "embedded" as a
574+
// CBOR byte string (major type 2).
575+
type EmbeddedJSON struct {
576+
any
577+
}
578+
579+
func NewEmbeddedJSON(val any) EmbeddedJSON {
580+
return EmbeddedJSON{val}
581+
}
582+
583+
// MarshalCBOR encodes EmbeddedJSON to a tagged CBOR data item with the
584+
// tag number 262 and the tag content is a JSON object that is
585+
// "embedded" as a CBOR byte string.
586+
func (v EmbeddedJSON) MarshalCBOR() ([]byte, error) {
587+
// Encode v to JSON object.
588+
data, err := json.Marshal(v)
589+
if err != nil {
590+
return nil, err
591+
}
592+
593+
// Create cbor.Tag representing a tagged CBOR data item.
594+
tag := cbor.Tag{
595+
Number: cborTagNumForEmbeddedJSON,
596+
Content: data,
597+
}
598+
599+
// Marshal to a tagged CBOR data item.
600+
return cbor.Marshal(tag)
601+
}
602+
603+
// UnmarshalCBOR decodes a tagged CBOR data item to EmbeddedJSON.
604+
// The byte slice provided to this function must contain a single
605+
// tagged CBOR data item with the tag number 262 and tag content
606+
// must be a JSON object "embedded" as a CBOR byte string.
607+
func (v *EmbeddedJSON) UnmarshalCBOR(b []byte) error {
608+
// Unmarshal tagged CBOR data item.
609+
var tag cbor.Tag
610+
if err := cbor.Unmarshal(b, &tag); err != nil {
611+
return err
612+
}
613+
614+
// Check tag number.
615+
if tag.Number != cborTagNumForEmbeddedJSON {
616+
return fmt.Errorf("got tag number %d, expect tag number %d", tag.Number, cborTagNumForEmbeddedJSON)
617+
}
618+
619+
// Check tag content.
620+
jsonData, isByteString := tag.Content.([]byte)
621+
if !isByteString {
622+
return fmt.Errorf("got tag content type %T, expect tag content []byte", tag.Content)
623+
}
624+
625+
// Unmarshal JSON object.
626+
return json.Unmarshal(jsonData, v)
627+
}
628+
629+
// MarshalJSON encodes EmbeddedJSON to a JSON object.
630+
func (v EmbeddedJSON) MarshalJSON() ([]byte, error) {
631+
return json.Marshal(v.any)
632+
}
633+
634+
// UnmarshalJSON decodes a JSON object.
635+
func (v *EmbeddedJSON) UnmarshalJSON(b []byte) error {
636+
dec := json.NewDecoder(bytes.NewReader(b))
637+
dec.UseNumber()
638+
return dec.Decode(&v.any)
639+
}
640+
641+
func Example_embeddedJSONTagForCBOR() {
642+
value := NewEmbeddedJSON(map[string]any{
643+
"name": "gopher",
644+
"id": json.Number("42"),
645+
})
646+
647+
data, err := cbor.Marshal(value)
648+
if err != nil {
649+
panic(err)
650+
}
651+
652+
fmt.Printf("cbor: %x\n", data)
653+
654+
var v EmbeddedJSON
655+
err = cbor.Unmarshal(data, &v)
656+
if err != nil {
657+
panic(err)
658+
}
659+
660+
fmt.Printf("%+v\n", v.any)
661+
for k, v := range v.any.(map[string]any) {
662+
fmt.Printf(" %s: %v (%T)\n", k, v, v)
663+
}
664+
}
665+
```
666+
667+
</details>
668+
669+
479670
### Functions and Interfaces
480671

481672
<details><summary> 🔎&nbsp; Functions and interfaces at a glance</summary><p/>
@@ -492,7 +683,7 @@ because RFC 8949 treats CBOR data item with remaining bytes as malformed.
492683
Other useful functions:
493684
- `Diagnose`, `DiagnoseFirst` produce human-readable [Extended Diagnostic Notation](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G) from CBOR data.
494685
- `UnmarshalFirst` decodes first CBOR data item and return any remaining bytes.
495-
- `Wellformed` returns true if the the CBOR data item is well-formed.
686+
- `Wellformed` returns true if the CBOR data item is well-formed.
496687

497688
Interfaces identical or comparable to Go `encoding` packages include:
498689
`Marshaler`, `Unmarshaler`, `BinaryMarshaler`, and `BinaryUnmarshaler`.
@@ -511,28 +702,28 @@ Default limits may need to be increased for systems handling very large data (e.
511702

512703
## Status
513704

514-
v2.8.0 (March 30, 2025) is a small release primarily to add `omitzero` option to struct field tags and fix bugs. It passed fuzz tests (billions of executions) and is production quality.
515-
516-
v2.8.0 and v2.7.1 fixes these 3 functions (when called directly by user apps) to use same error handling on bad inputs as `cbor.Unmarshal()`:
517-
- `ByteString.UnmarshalCBOR()`
518-
- `RawTag.UnmarshalCBOR()`
519-
- `SimpleValue.UnmarshalCBOR()`
705+
[v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0) (Jul 13, 2025) improved interoperability/transcoding between CBOR & JSON, refactored tests, and improved docs.
706+
- Add opt-in support for `encoding.TextMarshaler` and `encoding.TextUnmarshaler` to encode and decode from CBOR text string.
707+
- Add opt-in support for `json.Marshaler` and `json.Unmarshaler` via user-provided transcoding function.
708+
- Update docs for TimeMode, Tag, RawTag, and add example for Embedded JSON Tag for CBOR.
520709

521-
The above 3 `UnmarshalCBOR()` functions were initially created for internal use and are deprecated now, so please use `Unmarshal()` or `UnmarshalFirst()` instead. To preserve backward compatibility, these deprecated functions were added to fuzz tests and will not be removed in v2.
710+
v2.9.0 passed fuzz tests and is production quality.
522711

523712
The minimum version of Go required to build:
524-
- v2.8.0 requires go 1.20.
525-
- v2.7.1 and older releases require go 1.17.
713+
- v2.8.0 and newer releases require go 1.20+.
714+
- v2.7.1 and older releases require go 1.17+.
526715

527716
For more details, see [release notes](https://github.com/fxamacker/cbor/releases).
528717

529718
### Prior Releases
530719

531-
v2.7.0 (June 23, 2024) adds features and improvements that help large projects (e.g. Kubernetes) use CBOR as an alternative to JSON and Protocol Buffers. Other improvements include speedups, improved memory use, bug fixes, new serialization options, etc. It passed fuzz tests (5+ billion executions) and is production quality.
720+
[v2.8.0](https://github.com/fxamacker/cbor/releases/tag/v2.8.0) (March 30, 2025) is a small release primarily to add `omitzero` option to struct field tags and fix bugs. It passed fuzz tests (billions of executions) and is production quality.
721+
722+
[v2.7.0](https://github.com/fxamacker/cbor/releases/tag/v2.7.0) (June 23, 2024) adds features and improvements that help large projects (e.g. Kubernetes) use CBOR as an alternative to JSON and Protocol Buffers. Other improvements include speedups, improved memory use, bug fixes, new serialization options, etc. It passed fuzz tests (5+ billion executions) and is production quality.
532723

533724
[v2.6.0](https://github.com/fxamacker/cbor/releases/tag/v2.6.0) (February 2024) adds important new features, optimizations, and bug fixes. It is especially useful to systems that need to convert data between CBOR and JSON. New options and optimizations improve handling of bignum, integers, maps, and strings.
534725

535-
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).
726+
[v2.5.0](https://github.com/fxamacker/cbor/releases/tag/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).
536727

537728
__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.
538729

@@ -601,9 +792,9 @@ geomean 2.782
601792

602793
## Who uses fxamacker/cbor
603794

604-
`fxamacker/cbor` is used in projects by Arm Ltd., Berlin Institute of Health at Charité, Chainlink, Cisco, Confidential&nbsp;Computing&nbsp;Consortium, ConsenSys, EdgeX&nbsp;Foundry, F5, Flow&nbsp;Foundation, Fraunhofer&#8209;AISEC, IBM, Kubernetes, Let's&nbsp;Encrypt&nbsp;(ISRG), Linux&nbsp;Foundation, Matrix.org, Microsoft, Mozilla, National&nbsp;Cybersecurity&nbsp;Agency&nbsp;of&nbsp;France&nbsp;(govt), Netherlands&nbsp;(govt), Oasis&nbsp;Protocol, Smallstep, Tailscale, Taurus SA, Teleport, TIBCO, and others.
795+
`fxamacker/cbor` is used in projects by Arm Ltd., Berlin Institute of Health at Charité, Chainlink, Confidential&nbsp;Computing&nbsp;Consortium, ConsenSys, EdgeX&nbsp;Foundry, F5, Flow&nbsp;Foundation, Fraunhofer&#8209;AISEC, IBM, Kubernetes, Let's&nbsp;Encrypt&nbsp;(ISRG), Linaro, Linux&nbsp;Foundation, Matrix.org, Microsoft, National&nbsp;Cybersecurity&nbsp;Agency&nbsp;of&nbsp;France&nbsp;(govt), Netherlands&nbsp;(govt), Oasis&nbsp;Protocol, Red Hat OpenShift, Smallstep, Tailscale, Taurus SA, TIBCO, Veraison, and others.
605796

606-
`fxamacker/cbor` passed multiple confidential security assessments. 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) includes a subset of fxamacker/cbor v2.4.0 in its scope.
797+
`fxamacker/cbor` passed multiple confidential security assessments in 2022. 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) assessed a subset of fxamacker/cbor v2.4.
607798

608799
## Standards
609800

0 commit comments

Comments
 (0)