@cbortech/set-map-extensions

Set (CBOR tag 258) and Map (CBOR tag 259) application-extensions for @cbortech/cbor


Keywords
cbor, cdn, cbor-edn, set, map
License
Apache-2.0
Install
npm install @cbortech/set-map-extensions@0.27.0

Documentation

@cbortech/set-map-extensions

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:

Installation

npm install @cbortech/cbor @cbortech/set-map-extensions

Usage

Both 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).

set extension

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"]>>

map extension

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] });

CDN Forms

set

  • 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

  • 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.

JavaScript Mapping

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.

License

Apache-2.0