Set (CBOR tag 258) and Map (CBOR tag 259) application-extensions for @cbortech/cbor.
@cbortech/cbor is a TypeScript library for converting between CBOR, CDN, and JavaScript values.
The playground is published at https://cbor.tech/cbor/.
This package bundles two independent extensions, each adding its own CDN notation:
-
set— CBOR tag 258 (mathematical finite set, defined by the CBOR Sets specification), written asSET<<[...]>>. See docs/cdn-set-notation.md for the full notation specification. -
map— CBOR tag 259 (explicitMapdatatype, defined by the js-cbor-codec explicit-map specification), written asMAP<<...>>. See docs/cdn-map-notation.md for the full notation specification.
npm install @cbortech/cbor @cbortech/set-map-extensionsBoth extensions support the same six conversions, following the CBOR
instance API (parse/stringify mirror JSON.parse/JSON.stringify; see
@cbortech/cbor for the full
API).
import { CBOR } from '@cbortech/cbor';
import { set } from '@cbortech/set-map-extensions';
const cbor = new CBOR({ extensions: [set] });
// CDN -> JS: SET<<[...]>> becomes a Set.
console.log(cbor.parse('SET<<["a","b","c"]>>'));
// Set(3) { 'a', 'b', 'c' }
// JS -> CDN: a Set becomes SET<<[...]>>.
console.log(cbor.stringify(new Set(['a', 'b', 'c'])));
// SET<<["a","b","c"]>>
// JS -> CBOR: a Set is encoded as tag 258 (toHex() renders an annotated dump).
const encoded = cbor.encode(new Set(['a', 'b', 'c']));
console.log(cbor.toHex(encoded));
// D9 01 02 -- Tag 258
// 83 -- Array of length 3
// 61 61 -- "a"
// 61 62 -- "b"
// 61 63 -- "c"
// CBOR -> JS: tag 258 decodes back to a Set.
console.log(cbor.decode(encoded));
// Set(3) { 'a', 'b', 'c' }
// CDN -> CBOR: SET<<[...]>> compiles to the same tag 258 bytes.
const compiled = cbor.compile('SET<<["a","b","c"]>>');
console.log(cbor.toHex(compiled));
// D9 01 02 -- Tag 258
// 83 -- Array of length 3
// 61 61 -- "a"
// 61 62 -- "b"
// 61 63 -- "c"
// CBOR -> CDN: tag 258 decompiles back to SET<<[...]>>.
console.log(cbor.decompile(compiled));
// SET<<["a","b","c"]>>import { CBOR } from '@cbortech/cbor';
import { map } from '@cbortech/set-map-extensions';
const cbor = new CBOR({ extensions: [map] });
// CDN -> JS: MAP<<{...}>> becomes a Map.
console.log(cbor.parse('MAP<<{"a": 1, "b": 2}>>'));
// Map(2) { 'a' => 1, 'b' => 2 }
// JS -> CDN: a Map becomes MAP<<{...}>>.
console.log(
cbor.stringify(
new Map([
['a', 1],
['b', 2],
])
)
);
// MAP<<{"a":1,"b":2}>>
// JS -> CBOR: a Map is encoded as tag 259 (toHex() renders an annotated dump).
const encoded = cbor.encode(
new Map([
['a', 1],
['b', 2],
])
);
console.log(cbor.toHex(encoded));
// D9 01 03 -- Tag 259
// A2 -- Map of length 2
// 61 61 -- "a"
// 01 -- 1
// 61 62 -- "b"
// 02 -- 2
// CBOR -> JS: tag 259 decodes back to a Map.
console.log(cbor.decode(encoded));
// Map(2) { 'a' => 1, 'b' => 2 }
// CDN -> CBOR: MAP<<{...}>> compiles to the same tag 259 bytes.
const compiled = cbor.compile('MAP<<{"a": 1, "b": 2}>>');
console.log(cbor.toHex(compiled));
// D9 01 03 -- Tag 259
// A2 -- Map of length 2
// 61 61 -- "a"
// 01 -- 1
// 61 62 -- "b"
// 02 -- 2
// CBOR -> CDN: tag 259 decompiles back to MAP<<{...}>>.
console.log(cbor.decompile(compiled));
// MAP<<{"a":1,"b":2}>>
// Map keys aren't limited to strings — the map form accepts non-text keys
// such as numbers directly.
console.log(cbor.parse('MAP<<{1: true, 2: false}>>'));
// Map(2) { 1 => true, 2 => false }Both set and map can be combined in a single CBOR instance:
import { CBOR } from '@cbortech/cbor';
import { set, map } from '@cbortech/set-map-extensions';
const cbor = new CBOR({ extensions: [set, map] });-
SET<<[1, 2, 3]>>produces tag 258 over the array[1, 2, 3]. -
SET<<[]>>produces the empty set. -
258([1, 2, 3])generic tag notation is equivalent. - An encoding-indicator suffix controls the tag head:
SET<<[1, 2]>>_2. - The
SET'...'app-string form is not supported.
The app-sequence must contain exactly one array; its elements are the members
of the set. Duplicate elements (compared byte-wise on their CBOR encoding) are
a SyntaxError in strict mode and are removed with a warning when parsing with
strict: false. See docs/cdn-set-notation.md for
the complete rules, including how duplicates in binary CBOR input are handled.
-
MAP<<{"key": "value", ...}>>produces tag 259 over a CBOR map. -
MAP<<{}>>produces the empty map. - Keys may be arbitrary CBOR data items, not just text strings.
See docs/cdn-map-notation.md for the full notation specification.
| Extension | toJS() |
fromJS() |
|---|---|---|
set |
JavaScript Set (insertion order preserved; duplicates collapse) |
Set → tag 258 array in insertion order |
map |
JavaScript Map (insertion order preserved; duplicate keys keep the last occurrence) |
every Map instance → tag 259 over a CBOR map |
To encode an untagged CBOR map with non-text keys, use MapEntries from @cbortech/cbor instead of Map.
Duplicate map keys are only collapsed by toJS()/fromJS(). The CDN/AST form can still contain duplicate keys exactly as written, and a strict binary CBOR decode rejects a map that contains duplicate keys instead of collapsing them.
Apache-2.0