microcbor
v0.3.0
Published
Encode JavaScript values as canonical CBOR
Downloads
10
Readme
microcbor
Encode JavaScript values as canonical CBOR.
microcbor is a minimal JavaScript CBOR implementation featuring
- a small footprint,
- fast performance, and
- an async iterable streaming API
microcbor follows the deterministic CBOR encoding requirements - all floating-point numbers are serialized in the smallest possible size without losing precision, and object entries are always sorted by key in byte-wise lexicographic order. NaN
is always serialized as 0xf97e00
. microcbor doesn't support tags, bigints, typed arrays, non-string keys, or indefinite-length collections.
This library is TypeScript-native, ESM-only, and has just one dependency joeltg/fp16 for half-precision floats. It works in Node, the browser, and Deno.
Table of Contents
Install
npm i microcbor
Or in Deno:
import { encode, decode } from "https://cdn.skypack.dev/microcbor"
Usage
import { encode, decode } from "microcbor"
const data = encode({ a: 5, b: "hello world" })
console.log(data)
// Uint8Array(18) [
// 162, 97, 97, 5, 97, 98,
// 107, 104, 101, 108, 108, 111,
// 32, 119, 111, 114, 108, 100
// ]
console.log(decode(data))
// { a: 5, b: 'hello world' }
API
declare type CBORValue =
| undefined
| null
| boolean
| number
| string
| Uint8Array
| CBORArray
| CBORMap
interface CBORArray extends Array<CBORValue> {}
interface CBORMap {
[key: string]: CBORValue
}
// If not provided, chunkSize defaults to 512 bytes.
// It's only a guideline; `encodeStream` won't break up
// individual CBOR values like strings or byte arrays
// that are larger than the provided chunk size.
declare function encode(
value: CBORValue,
options?: { chunkSize?: number }
): Uint8Array
declare function encodeStream(
source: AsyncIterable<CBORValue>,
options?: { chunkSize?: number }
): AsyncIterable<Uint8Array>
declare function decode(data: Uint8Array): CBORValue
declare function decodeStream(
source: AsyncIterable<Uint8Array>
): AsyncIterable<CBORValue>
// You can measure the byte length that a given value will
// serialize to without actually allocating anything.
declare function encodingLength(value: CBORValue): number
Unsafe integer handling
- JavaScript integers below
Number.MIN_SAFE_INTEGER
or greater thanNumber.MAX_SAFE_INTEGER
will encode as CBOR floating-point numbers, as per the suggestion in the CBOR spec. - decoding CBOR integers less than
Number.MIN_SAFE_INTEGER
(major type 1 with uint64 argument greater than2^53-2
) or greater thanNumber.MAX_SAFE_INTEGER
(major type 0 with uint64 argument greater than2^53-1
) will throw an error. The error will be an instance ofUnsafeIntegerError
and will have the out-of-range value as a readonly.value: bigint
property.
declare class UnsafeIntegerError extends RangeError {
readonly value: bigint
}
Value mapping
| CBOR major type | JavaScript | notes |
| ---------------------------- | --------------- | -------------------------------------------------------- |
| 0
(non-negative integer) | number
| decoding throws an UnsafeIntegerError
on unsafe values |
| 1
(negative integer) | number
| decoding throws an UnsafeIntegerError
on unsafe values |
| 2
(byte string) | Uint8Array
| |
| 3
(UTF-8 string) | string
| |
| 4
(array) | Array
| |
| 5
(map) | Object
| decoding throws an error on non-string keys |
| 6
(tagged item) | Unsupported | |
| 7
(floating-point numbers) | number
| |
| 7
(booleans) | boolean
| |
| 7
(null) | null
| |
| 7
(undefined) | undefined
| |
Testing
Tests use AVA and live in the test directory. Tests use node-cbor to validate encoding results. More tests are always welcome!
npm run test
Comparison to node-cbor
- microcbor runs isomorphically on the web, in Node, and in Deno. node-cbor ships a separate cbor-web package.
- microcbor encodes
Uint8Array
values as CBOR byte strings (major type 2). node-cbor encodesUint8Array
values as tagged type arrays (major type 6 / RFC 8746), and encodes NodeJSBuffer
values as CBOR byte strings (major type 2). - microcbor uses async iterables for its streaming API. node-cbor uses NodeJS streams.
- microcbor is about 2x faster than node-cbor at encoding and about 1.5x faster than node-cbor at decoding.
microcbor % npm run test -- test/benchmarks.test.js
> [email protected] test
> ava
✔ time encode() (390ms)
ℹ microcbor: 66.47262525558472 (ms)
ℹ node-cbor: 155.0249171257019 (ms)
ℹ JSON.stringify: 5.56374979019165 (ms)
✔ time decode() (161ms)
ℹ microcbor: 64.23729228973389 (ms)
ℹ node-cbor: 91.34658432006836 (ms)
ℹ JSON.parse: 2.7592921257019043 (ms)
─
2 tests passed
Contributing
I don't expect to add any additional features to this library. But if you have suggestions for better interfaces, find a bug, or would like to add more tests, please open an issue to discuss it!
License
MIT © 2021 Joel Gustafson