microcbor 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -84
- package/lib/decode.d.ts +2 -8
- package/lib/decode.js +124 -157
- package/lib/decodeStream.d.ts +2 -0
- package/lib/decodeStream.js +205 -0
- package/lib/encode.d.ts +34 -4
- package/lib/encode.js +205 -176
- package/lib/encodeStream.d.ts +4 -0
- package/lib/encodeStream.js +8 -0
- package/lib/encodingLength.d.ts +2 -0
- package/lib/encodingLength.js +169 -0
- package/lib/index.d.ts +7 -2
- package/lib/index.js +6 -2
- package/lib/types.d.ts +6 -0
- package/lib/types.js +1 -0
- package/lib/utils.d.ts +6 -0
- package/lib/utils.js +8 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -2,24 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/RichardLitt/standard-readme) [](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/microcbor)  
|
|
4
4
|
|
|
5
|
-
Encode
|
|
5
|
+
Encode JavaScript values as canonical CBOR.
|
|
6
6
|
|
|
7
|
-
microcbor is a [CBOR](https://cbor.io/) implementation
|
|
7
|
+
microcbor is a minimal JavaScript [CBOR](https://cbor.io/) implementation featuring
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- a small footprint,
|
|
10
|
+
- fast performance, and
|
|
11
|
+
- an async iterable streaming API
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
microcbor follows the [deterministic CBOR encoding requirements](https://www.rfc-editor.org/rfc/rfc8949.html#core-det) - 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.**
|
|
14
|
+
|
|
15
|
+
This library is TypeScript-native, ESM-only, and has just one dependency [joeltg/fp16](https://github.com/joeltg/fp16) for half-precision floats. It works in Node, the browser, and Deno.
|
|
12
16
|
|
|
13
17
|
## Table of Contents
|
|
14
18
|
|
|
15
19
|
- [Install](#install)
|
|
16
20
|
- [Usage](#usage)
|
|
17
21
|
- [API](#api)
|
|
18
|
-
|
|
19
|
-
- [Decoding](#decoding)
|
|
20
|
-
- [Strict mode](#strict-mode)
|
|
21
|
-
- [Limitations](#limitations)
|
|
22
|
+
- [Value mapping](#value-mapping)
|
|
22
23
|
- [Testing](#testing)
|
|
24
|
+
- [Benchmarks](#benchmarks)
|
|
23
25
|
- [Contributing](#contributing)
|
|
24
26
|
- [License](#license)
|
|
25
27
|
|
|
@@ -55,105 +57,108 @@ console.log(decode(data))
|
|
|
55
57
|
|
|
56
58
|
## API
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
```ts
|
|
61
|
+
declare type CBORValue =
|
|
62
|
+
| undefined
|
|
63
|
+
| null
|
|
64
|
+
| boolean
|
|
65
|
+
| number
|
|
66
|
+
| string
|
|
67
|
+
| Uint8Array
|
|
68
|
+
| CBORArray
|
|
69
|
+
| CBORMap
|
|
70
|
+
|
|
71
|
+
interface CBORArray extends Array<CBORValue> {}
|
|
72
|
+
interface CBORMap {
|
|
73
|
+
[key: string]: CBORValue
|
|
64
74
|
}
|
|
65
75
|
|
|
66
|
-
|
|
76
|
+
// If not provided, chunkSize defaults to 512 bytes.
|
|
77
|
+
// It's only a guideline; `encodeStream` won't break up
|
|
78
|
+
// individual CBOR values like strings or byte arrays
|
|
79
|
+
// that are larger than the provided chunk size.
|
|
80
|
+
declare function encode(
|
|
81
|
+
value: CBORValue,
|
|
82
|
+
options?: { chunkSize?: number }
|
|
83
|
+
): Uint8Array
|
|
84
|
+
|
|
85
|
+
declare function encodeStream(
|
|
86
|
+
source: AsyncIterable<CBORValue>,
|
|
87
|
+
options?: { chunkSize?: number }
|
|
88
|
+
): AsyncIterable<Uint8Array>
|
|
89
|
+
|
|
90
|
+
declare function decode(data: Uint8Array): CBORValue
|
|
91
|
+
|
|
92
|
+
declare function decodeStream(
|
|
93
|
+
source: AsyncIterable<Uint8Array>
|
|
94
|
+
): AsyncIterable<CBORValue>
|
|
95
|
+
|
|
96
|
+
// You can measure the byte length that a given value will
|
|
97
|
+
// serialize to without actually allocating anything.
|
|
98
|
+
declare function encodingLength(value: CBORValue): number
|
|
67
99
|
```
|
|
68
100
|
|
|
69
|
-
|
|
101
|
+
## Unsafe integer handling
|
|
70
102
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
| `strictJSON` | boolean | false |
|
|
74
|
-
| `chunkSize` | number | 512 |
|
|
75
|
-
|
|
76
|
-
### Decoding
|
|
103
|
+
- JavaScript integers below `Number.MIN_SAFE_INTEGER` or greater than `Number.MAX_SAFE_INTEGER` will encode as CBOR floating-point numbers, as per the [suggestion in the CBOR spec](https://www.rfc-editor.org/rfc/rfc8949.html#name-converting-from-json-to-cbo).
|
|
104
|
+
- decoding **CBOR integers** less than `Number.MIN_SAFE_INTEGER` (major type 1 with uint64 argument greater than `2^53-2`) or greater than `Number.MAX_SAFE_INTEGER` (major type 0 with uint64 argument greater than `2^53-1`) **will throw an error**. The error will be an instance of `UnsafeIntegerError` and will have the out-of-range value as a readonly `.value: bigint` property.
|
|
77
105
|
|
|
78
106
|
```typescript
|
|
79
|
-
|
|
80
|
-
|
|
107
|
+
declare class UnsafeIntegerError extends RangeError {
|
|
108
|
+
readonly value: bigint
|
|
109
|
+
constructor(message: string, value: bigint)
|
|
81
110
|
}
|
|
82
|
-
|
|
83
|
-
declare function decode<T = any>(
|
|
84
|
-
data: Uint8Array,
|
|
85
|
-
decode: DecodeOptions = {}
|
|
86
|
-
): T
|
|
87
111
|
```
|
|
88
112
|
|
|
89
|
-
|
|
113
|
+
## Value mapping
|
|
114
|
+
|
|
115
|
+
| CBOR major type | JavaScript | notes |
|
|
116
|
+
| ---------------------------- | --------------- | -------------------------------------------------------- |
|
|
117
|
+
| `0` (non-negative integer) | `number` | decoding throws an `UnsafeIntegerError` on unsafe values |
|
|
118
|
+
| `1` (negative integer) | `number` | decoding throws an `UnsafeIntegerError` on unsafe values |
|
|
119
|
+
| `2` (byte string) | `Uint8Array` | |
|
|
120
|
+
| `3` (UTF-8 string) | `string` | |
|
|
121
|
+
| `4` (array) | `Array` | |
|
|
122
|
+
| `5` (map) | `Object` | decoding throws an error on non-string keys |
|
|
123
|
+
| `6` (tagged item) | **Unsupported** | |
|
|
124
|
+
| `7` (floating-point numbers) | `number` | |
|
|
125
|
+
| `7` (booleans) | `boolean` | |
|
|
126
|
+
| `7` (null) | `null` | |
|
|
127
|
+
| `7` (undefined) | `undefined` | |
|
|
90
128
|
|
|
91
|
-
|
|
92
|
-
| ------------ | ------- | ------- |
|
|
93
|
-
| `strictJSON` | boolean | false |
|
|
94
|
-
|
|
95
|
-
### Strict mode
|
|
96
|
-
|
|
97
|
-
Technically, neither `NaN` nor `+/- Infinity` are valid JSON numbers. But microcbor functions as a direct interface between JavaScript and CBOR, so by default, you can encode them...
|
|
129
|
+
## Testing
|
|
98
130
|
|
|
99
|
-
|
|
100
|
-
import { encode } from "microcbor"
|
|
131
|
+
Tests use [AVA](https://github.com/avajs/ava) and live in the [test](./test/) directory. Tests use [node-cbor](https://github.com/hildjj/node-cbor/) to validate encoding results. More tests are always welcome!
|
|
101
132
|
|
|
102
|
-
encode(NaN) // Uint8Array(3) [ 249, 126, 0 ]
|
|
103
|
-
encode(Infinity) // Uint8Array(3) [ 249, 124, 0 ]
|
|
104
|
-
encode(-Infinity) // Uint8Array(3) [ 249, 252, 0 ]
|
|
105
133
|
```
|
|
106
|
-
|
|
107
|
-
... and decode them...
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
import { decode } from "microcbor"
|
|
111
|
-
|
|
112
|
-
decode(new Uint8Array([249, 126, 0])) // NaN
|
|
113
|
-
decode(new Uint8Array([249, 124, 0])) // Infinity
|
|
114
|
-
decode(new Uint8Array([249, 252, 0])) // -Infinity
|
|
134
|
+
npm run test
|
|
115
135
|
```
|
|
116
136
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
```javascript
|
|
120
|
-
import { encode } from "microcbor"
|
|
137
|
+
## Comparison to node-cbor
|
|
121
138
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```javascript
|
|
127
|
-
import { decode } from "microcbor"
|
|
139
|
+
- microcbor runs isomorphically on the web, in Node, and in Deno. node-cbor ships a separate cbor-web package.
|
|
140
|
+
- microcbor encodes `Uint8Array` values as CBOR byte strings (major type 2). node-cbor encodes `Uint8Array` values as tagged type arrays (major type 6 / RFC 8746), and encodes NodeJS `Buffer` values as CBOR byte strings (major type 2).
|
|
141
|
+
- microcbor uses async iterables for its streaming API. node-cbor uses NodeJS streams.
|
|
142
|
+
- microcbor is about **2x faster** than node-cbor at encoding and about **1.5x faster** than node-cbor at decoding.
|
|
128
143
|
|
|
129
|
-
decode(new Uint8Array([249, 126, 0]), { strictJSON: true })
|
|
130
|
-
// Uncaught Error: cannot decode NaN when strict mode is enabled
|
|
131
144
|
```
|
|
145
|
+
microcbor % npm run test -- test/benchmarks.test.js
|
|
132
146
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
## Limitations
|
|
147
|
+
> microcbor@0.2.0 test
|
|
148
|
+
> ava
|
|
136
149
|
|
|
137
|
-
JSON numbers can be arbitrarly large and have unlimited decimal precision. CBOR has explicit types for the standard fixed-size integer and float formats, and separate tags for [arbitrarily large integers](https://www.rfc-editor.org/rfc/rfc8949.html#name-bignums) and [unlimited-precision decimal values](https://www.rfc-editor.org/rfc/rfc8949.html#name-decimal-fractions-and-bigfl). Meanwhile, JavaScript can only represent numbers as 64-bit floats or BigInts. This means there are always tradeoffs in interfacing between JSON, CBOR, and JavaScript.
|
|
138
150
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
-
|
|
142
|
-
|
|
151
|
+
✔ time encode() (390ms)
|
|
152
|
+
ℹ microcbor: 66.47262525558472 (ms)
|
|
153
|
+
ℹ node-cbor: 155.0249171257019 (ms)
|
|
154
|
+
ℹ JSON.stringify: 5.56374979019165 (ms)
|
|
155
|
+
✔ time decode() (161ms)
|
|
156
|
+
ℹ microcbor: 64.23729228973389 (ms)
|
|
157
|
+
ℹ node-cbor: 91.34658432006836 (ms)
|
|
158
|
+
ℹ JSON.parse: 2.7592921257019043 (ms)
|
|
159
|
+
─
|
|
143
160
|
|
|
144
|
-
|
|
145
|
-
declare class UnsafeIntegerError extends RangeError {
|
|
146
|
-
readonly value: bigint
|
|
147
|
-
constructor(message: string, value: bigint)
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Testing
|
|
152
|
-
|
|
153
|
-
Tests use [AVA 4](https://github.com/avajs/ava) (currently in alpha) and live in the [test](./test/) directory. Tests use [node-cbor](https://github.com/hildjj/node-cbor/) to validate encoding results. More tests are always welcome!
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
npm run test
|
|
161
|
+
2 tests passed
|
|
157
162
|
```
|
|
158
163
|
|
|
159
164
|
## Contributing
|
package/lib/decode.d.ts
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
export declare class UnsafeIntegerError extends RangeError {
|
|
5
|
-
readonly value: bigint;
|
|
6
|
-
constructor(message: string, value: bigint);
|
|
7
|
-
}
|
|
8
|
-
export declare function decode<T = any>(data: Uint8Array, options?: DecodeOptions): T;
|
|
1
|
+
import type { CBORValue } from "./types.js";
|
|
2
|
+
export declare function decode(data: Uint8Array): CBORValue;
|
package/lib/decode.js
CHANGED
|
@@ -1,174 +1,141 @@
|
|
|
1
1
|
import { getFloat16 } from "fp16";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const value =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return value;
|
|
26
|
-
},
|
|
27
|
-
float64(state) {
|
|
28
|
-
const value = state.view.getFloat64(state.offset);
|
|
29
|
-
validateFloat(state, value);
|
|
30
|
-
state.offset += 8;
|
|
31
|
-
return value;
|
|
32
|
-
},
|
|
33
|
-
uint8(state) {
|
|
34
|
-
const value = state.view.getUint8(state.offset);
|
|
35
|
-
state.offset += 1;
|
|
36
|
-
return value;
|
|
37
|
-
},
|
|
38
|
-
uint16(state) {
|
|
39
|
-
const value = state.view.getUint16(state.offset);
|
|
40
|
-
state.offset += 2;
|
|
41
|
-
return value;
|
|
42
|
-
},
|
|
43
|
-
uint32(state) {
|
|
44
|
-
const value = state.view.getUint32(state.offset);
|
|
45
|
-
state.offset += 4;
|
|
46
|
-
return value;
|
|
47
|
-
},
|
|
48
|
-
uint64(state) {
|
|
49
|
-
const value = state.view.getBigUint64(state.offset);
|
|
50
|
-
state.offset += 8;
|
|
2
|
+
import { UnsafeIntegerError, maxSafeInteger, minSafeInteger } from "./utils.js";
|
|
3
|
+
class Decoder {
|
|
4
|
+
constructor(data) {
|
|
5
|
+
this.data = data;
|
|
6
|
+
this.constant = (size, f) => () => {
|
|
7
|
+
const value = f();
|
|
8
|
+
this.offset += size;
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
this.float16 = this.constant(2, () => getFloat16(this.view, this.offset));
|
|
12
|
+
this.float32 = this.constant(4, () => this.view.getFloat32(this.offset));
|
|
13
|
+
this.float64 = this.constant(8, () => this.view.getFloat64(this.offset));
|
|
14
|
+
this.uint8 = this.constant(1, () => this.view.getUint8(this.offset));
|
|
15
|
+
this.uint16 = this.constant(2, () => this.view.getUint16(this.offset));
|
|
16
|
+
this.uint32 = this.constant(4, () => this.view.getUint32(this.offset));
|
|
17
|
+
this.uint64 = this.constant(8, () => this.view.getBigUint64(this.offset));
|
|
18
|
+
this.offset = 0;
|
|
19
|
+
this.view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
20
|
+
}
|
|
21
|
+
decodeBytes(length) {
|
|
22
|
+
const value = new Uint8Array(length);
|
|
23
|
+
value.set(this.data.subarray(this.offset, this.offset + length), 0);
|
|
24
|
+
this.offset += length;
|
|
51
25
|
return value;
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
function decodeString(state, length) {
|
|
55
|
-
const view = new DataView(state.view.buffer, state.view.byteOffset + state.offset, length);
|
|
56
|
-
state.offset += length;
|
|
57
|
-
return new TextDecoder().decode(view);
|
|
58
|
-
}
|
|
59
|
-
function getArgument(state, additionalInformation) {
|
|
60
|
-
if (additionalInformation < 24) {
|
|
61
|
-
return { value: additionalInformation };
|
|
62
|
-
}
|
|
63
|
-
else if (additionalInformation === 24) {
|
|
64
|
-
return { value: constants.uint8(state) };
|
|
65
26
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return { value: constants.uint32(state) };
|
|
71
|
-
}
|
|
72
|
-
else if (additionalInformation === 27) {
|
|
73
|
-
const uint64 = constants.uint64(state);
|
|
74
|
-
const value = maxSafeInteger < uint64 ? Infinity : Number(uint64);
|
|
75
|
-
return { value, uint64 };
|
|
76
|
-
}
|
|
77
|
-
else if (additionalInformation === 31) {
|
|
78
|
-
throw new Error("microcbor does not support decoding indefinite-length items");
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
throw new Error("invalid argument encoding");
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
export class UnsafeIntegerError extends RangeError {
|
|
85
|
-
constructor(message, value) {
|
|
86
|
-
super(message);
|
|
87
|
-
this.value = value;
|
|
27
|
+
decodeString(length) {
|
|
28
|
+
const value = new TextDecoder().decode(this.data.subarray(this.offset, this.offset + length));
|
|
29
|
+
this.offset += length;
|
|
30
|
+
return value;
|
|
88
31
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const majorType = initialByte >> 5;
|
|
93
|
-
const additionalInformation = initialByte & 0x1f;
|
|
94
|
-
if (majorType === 0) {
|
|
95
|
-
const { value, uint64 } = getArgument(state, additionalInformation);
|
|
96
|
-
if (uint64 !== undefined && maxSafeInteger < uint64) {
|
|
97
|
-
throw new UnsafeIntegerError("cannot decode integers greater than 2^53-1", uint64);
|
|
32
|
+
getArgument(additionalInformation) {
|
|
33
|
+
if (additionalInformation < 24) {
|
|
34
|
+
return { value: additionalInformation };
|
|
98
35
|
}
|
|
99
|
-
else {
|
|
100
|
-
return value;
|
|
36
|
+
else if (additionalInformation === 24) {
|
|
37
|
+
return { value: this.uint8() };
|
|
101
38
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (
|
|
106
|
-
|
|
39
|
+
else if (additionalInformation === 25) {
|
|
40
|
+
return { value: this.uint16() };
|
|
41
|
+
}
|
|
42
|
+
else if (additionalInformation === 26) {
|
|
43
|
+
return { value: this.uint32() };
|
|
44
|
+
}
|
|
45
|
+
else if (additionalInformation === 27) {
|
|
46
|
+
const uint64 = this.uint64();
|
|
47
|
+
const value = maxSafeInteger < uint64 ? Infinity : Number(uint64);
|
|
48
|
+
return { value, uint64 };
|
|
49
|
+
}
|
|
50
|
+
else if (additionalInformation === 31) {
|
|
51
|
+
throw new Error("microcbor does not support decoding indefinite-length items");
|
|
107
52
|
}
|
|
108
53
|
else {
|
|
109
|
-
|
|
54
|
+
throw new Error("invalid argument encoding");
|
|
110
55
|
}
|
|
111
56
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
57
|
+
decodeValue() {
|
|
58
|
+
const initialByte = this.uint8();
|
|
59
|
+
const majorType = initialByte >> 5;
|
|
60
|
+
const additionalInformation = initialByte & 0x1f;
|
|
61
|
+
if (majorType === 0) {
|
|
62
|
+
const { value, uint64 } = this.getArgument(additionalInformation);
|
|
63
|
+
if (uint64 !== undefined && maxSafeInteger < uint64) {
|
|
64
|
+
throw new UnsafeIntegerError("cannot decode integers greater than 2^53-1", uint64);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
124
69
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (typeof key !== "string") {
|
|
133
|
-
throw new Error("microcbor only supports string keys in objects");
|
|
70
|
+
else if (majorType === 1) {
|
|
71
|
+
const { value, uint64 } = this.getArgument(additionalInformation);
|
|
72
|
+
if (uint64 !== undefined && -1n - uint64 < minSafeInteger) {
|
|
73
|
+
throw new UnsafeIntegerError("cannot decode integers less than -2^53+1", -1n - uint64);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return -1 - value;
|
|
134
77
|
}
|
|
135
|
-
value[key] = decodeValue(state);
|
|
136
78
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
79
|
+
else if (majorType === 2) {
|
|
80
|
+
const { value: length } = this.getArgument(additionalInformation);
|
|
81
|
+
return this.decodeBytes(length);
|
|
82
|
+
}
|
|
83
|
+
else if (majorType === 3) {
|
|
84
|
+
const { value: length } = this.getArgument(additionalInformation);
|
|
85
|
+
return this.decodeString(length);
|
|
86
|
+
}
|
|
87
|
+
else if (majorType === 4) {
|
|
88
|
+
const { value: length } = this.getArgument(additionalInformation);
|
|
89
|
+
const value = new Array(length);
|
|
90
|
+
for (let i = 0; i < length; i++) {
|
|
91
|
+
value[i] = this.decodeValue();
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
else if (majorType === 5) {
|
|
96
|
+
const { value: length } = this.getArgument(additionalInformation);
|
|
97
|
+
const value = {};
|
|
98
|
+
for (let i = 0; i < length; i++) {
|
|
99
|
+
const key = this.decodeValue();
|
|
100
|
+
if (typeof key !== "string") {
|
|
101
|
+
throw new Error("microcbor only supports string keys in objects");
|
|
102
|
+
}
|
|
103
|
+
value[key] = this.decodeValue();
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
else if (majorType === 6) {
|
|
108
|
+
throw new Error("microcbor does not support tagged data items");
|
|
109
|
+
}
|
|
110
|
+
else if (majorType === 7) {
|
|
111
|
+
switch (additionalInformation) {
|
|
112
|
+
case 20:
|
|
113
|
+
return false;
|
|
114
|
+
case 21:
|
|
115
|
+
return true;
|
|
116
|
+
case 22:
|
|
117
|
+
return null;
|
|
118
|
+
case 23:
|
|
119
|
+
return undefined;
|
|
120
|
+
case 24:
|
|
121
|
+
throw new Error("microcbor does not support decoding unassigned simple values");
|
|
122
|
+
case 25:
|
|
123
|
+
return this.float16();
|
|
124
|
+
case 26:
|
|
125
|
+
return this.float32();
|
|
126
|
+
case 27:
|
|
127
|
+
return this.float64();
|
|
128
|
+
case 31:
|
|
129
|
+
throw new Error("microcbor does not support decoding indefinite-length items");
|
|
130
|
+
default:
|
|
131
|
+
throw new Error("invalid simple value");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
throw new Error("invalid major type");
|
|
164
136
|
}
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
throw new Error("invalid major type");
|
|
168
137
|
}
|
|
169
138
|
}
|
|
170
|
-
export function decode(data
|
|
171
|
-
|
|
172
|
-
const state = { options, offset: 0, view };
|
|
173
|
-
return decodeValue(state);
|
|
139
|
+
export function decode(data) {
|
|
140
|
+
return new Decoder(data).decodeValue();
|
|
174
141
|
}
|