microcbor 0.2.1 → 0.4.0
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 +40 -40
- package/lib/decode.d.ts +18 -0
- package/lib/decode.js +33 -15
- package/lib/encode.d.ts +8 -6
- package/lib/encode.js +69 -22
- package/lib/encodeStream.d.ts +1 -0
- package/lib/encodingLength.d.ts +1 -0
- package/lib/encodingLength.js +4 -7
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/types.d.ts +1 -1
- package/lib/utils.d.ts +6 -0
- package/lib/utils.js +12 -0
- package/package.json +16 -9
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ microcbor is a minimal JavaScript [CBOR](https://cbor.io/) implementation featur
|
|
|
8
8
|
|
|
9
9
|
- a small footprint,
|
|
10
10
|
- fast performance, and
|
|
11
|
-
-
|
|
11
|
+
- `Iterable` and `AsyncIterable` streaming interfaces
|
|
12
12
|
|
|
13
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
14
|
|
|
@@ -58,40 +58,27 @@ console.log(decode(data))
|
|
|
58
58
|
## API
|
|
59
59
|
|
|
60
60
|
```ts
|
|
61
|
-
declare type CBORValue =
|
|
62
|
-
| undefined
|
|
63
|
-
| null
|
|
64
|
-
| boolean
|
|
65
|
-
| number
|
|
66
|
-
| string
|
|
67
|
-
| Uint8Array
|
|
68
|
-
| CBORArray
|
|
69
|
-
| CBORMap
|
|
61
|
+
declare type CBORValue = undefined | null | boolean | number | string | Uint8Array | CBORArray | CBORMap
|
|
70
62
|
|
|
71
63
|
interface CBORArray extends Array<CBORValue> {}
|
|
72
64
|
interface CBORMap {
|
|
73
|
-
|
|
65
|
+
[key: string]: CBORValue
|
|
74
66
|
}
|
|
75
67
|
|
|
76
68
|
// If not provided, chunkSize defaults to 512 bytes.
|
|
77
69
|
// It's only a guideline; `encodeStream` won't break up
|
|
78
70
|
// individual CBOR values like strings or byte arrays
|
|
79
71
|
// that are larger than the provided chunk size.
|
|
80
|
-
declare function encode(
|
|
81
|
-
value: CBORValue,
|
|
82
|
-
options?: { chunkSize?: number }
|
|
83
|
-
): Uint8Array
|
|
72
|
+
declare function encode(value: CBORValue, options?: { chunkSize?: number }): Uint8Array
|
|
84
73
|
|
|
85
74
|
declare function encodeStream(
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
source: AsyncIterable<CBORValue>,
|
|
76
|
+
options?: { chunkSize?: number },
|
|
88
77
|
): AsyncIterable<Uint8Array>
|
|
89
78
|
|
|
90
79
|
declare function decode(data: Uint8Array): CBORValue
|
|
91
80
|
|
|
92
|
-
declare function decodeStream(
|
|
93
|
-
source: AsyncIterable<Uint8Array>
|
|
94
|
-
): AsyncIterable<CBORValue>
|
|
81
|
+
declare function decodeStream(source: AsyncIterable<Uint8Array>): AsyncIterable<CBORValue>
|
|
95
82
|
|
|
96
83
|
// You can measure the byte length that a given value will
|
|
97
84
|
// serialize to without actually allocating anything.
|
|
@@ -105,8 +92,7 @@ declare function encodingLength(value: CBORValue): number
|
|
|
105
92
|
|
|
106
93
|
```typescript
|
|
107
94
|
declare class UnsafeIntegerError extends RangeError {
|
|
108
|
-
|
|
109
|
-
constructor(message: string, value: bigint)
|
|
95
|
+
readonly value: bigint
|
|
110
96
|
}
|
|
111
97
|
```
|
|
112
98
|
|
|
@@ -139,26 +125,40 @@ npm run test
|
|
|
139
125
|
- microcbor runs isomorphically on the web, in Node, and in Deno. node-cbor ships a separate cbor-web package.
|
|
140
126
|
- 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
127
|
- microcbor uses async iterables for its streaming API. node-cbor uses NodeJS streams.
|
|
142
|
-
- microcbor is about **
|
|
128
|
+
- microcbor is about **5x faster** than node-cbor at encoding, and comparable at decoding.
|
|
143
129
|
|
|
144
130
|
```
|
|
145
|
-
microcbor % npm run test -- test/benchmarks.test.
|
|
146
|
-
|
|
147
|
-
> microcbor@0.
|
|
148
|
-
> ava
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
131
|
+
microcbor % npm run test -- test/benchmarks.test.ts
|
|
132
|
+
|
|
133
|
+
> microcbor@0.3.0 test
|
|
134
|
+
> ava test/benchmarks.test.ts
|
|
135
|
+
|
|
136
|
+
✔ time encode() (196ms)
|
|
137
|
+
ℹ microcbor: {
|
|
138
|
+
avg: 0.20750288999999897,
|
|
139
|
+
std: 0.1599497238014431,
|
|
140
|
+
} (ms)
|
|
141
|
+
ℹ node-cbor: {
|
|
142
|
+
avg: 1.012210439999998,
|
|
143
|
+
std: 1.1648550529513988,
|
|
144
|
+
} (ms)
|
|
145
|
+
ℹ JSON.stringify: {
|
|
146
|
+
avg: 0.011432450000000358,
|
|
147
|
+
std: 0.0014736483187953618,
|
|
148
|
+
} (ms)
|
|
149
|
+
✔ time decode()
|
|
150
|
+
ℹ microcbor: {
|
|
151
|
+
avg: 0.3199704100000008,
|
|
152
|
+
std: 0.6562532760030573,
|
|
153
|
+
} (ms)
|
|
154
|
+
ℹ node-cbor: {
|
|
155
|
+
avg: 0.35316917000000214,
|
|
156
|
+
std: 0.32859580328312393,
|
|
157
|
+
} (ms)
|
|
158
|
+
ℹ JSON.parse: {
|
|
159
|
+
avg: 0.016885789999999474,
|
|
160
|
+
std: 0.0041605677456241505,
|
|
161
|
+
} (ms)
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
## Contributing
|
package/lib/decode.d.ts
CHANGED
|
@@ -1,2 +1,20 @@
|
|
|
1
1
|
import type { CBORValue } from "./types.js";
|
|
2
|
+
export declare class Decoder {
|
|
3
|
+
#private;
|
|
4
|
+
private readonly data;
|
|
5
|
+
constructor(data: Uint8Array);
|
|
6
|
+
getOffset(): number;
|
|
7
|
+
private constant;
|
|
8
|
+
private float16;
|
|
9
|
+
private float32;
|
|
10
|
+
private float64;
|
|
11
|
+
private uint8;
|
|
12
|
+
private uint16;
|
|
13
|
+
private uint32;
|
|
14
|
+
private uint64;
|
|
15
|
+
private decodeBytes;
|
|
16
|
+
private decodeString;
|
|
17
|
+
private getArgument;
|
|
18
|
+
decodeValue(): CBORValue;
|
|
19
|
+
}
|
|
2
20
|
export declare function decode(data: Uint8Array): CBORValue;
|
package/lib/decode.js
CHANGED
|
@@ -1,32 +1,49 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _Decoder_offset, _Decoder_view;
|
|
1
13
|
import { getFloat16 } from "fp16";
|
|
2
14
|
import { UnsafeIntegerError, maxSafeInteger, minSafeInteger } from "./utils.js";
|
|
3
|
-
class Decoder {
|
|
15
|
+
export class Decoder {
|
|
4
16
|
constructor(data) {
|
|
5
17
|
this.data = data;
|
|
18
|
+
_Decoder_offset.set(this, void 0);
|
|
19
|
+
_Decoder_view.set(this, void 0);
|
|
6
20
|
this.constant = (size, f) => () => {
|
|
7
21
|
const value = f();
|
|
8
|
-
this
|
|
22
|
+
__classPrivateFieldSet(this, _Decoder_offset, __classPrivateFieldGet(this, _Decoder_offset, "f") + size, "f");
|
|
9
23
|
return value;
|
|
10
24
|
};
|
|
11
|
-
this.float16 = this.constant(2, () => getFloat16(this
|
|
12
|
-
this.float32 = this.constant(4, () => this.
|
|
13
|
-
this.float64 = this.constant(8, () => this.
|
|
14
|
-
this.uint8 = this.constant(1, () => this.
|
|
15
|
-
this.uint16 = this.constant(2, () => this.
|
|
16
|
-
this.uint32 = this.constant(4, () => this.
|
|
17
|
-
this.uint64 = this.constant(8, () => this.
|
|
18
|
-
this
|
|
19
|
-
this
|
|
25
|
+
this.float16 = this.constant(2, () => getFloat16(__classPrivateFieldGet(this, _Decoder_view, "f"), __classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
26
|
+
this.float32 = this.constant(4, () => __classPrivateFieldGet(this, _Decoder_view, "f").getFloat32(__classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
27
|
+
this.float64 = this.constant(8, () => __classPrivateFieldGet(this, _Decoder_view, "f").getFloat64(__classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
28
|
+
this.uint8 = this.constant(1, () => __classPrivateFieldGet(this, _Decoder_view, "f").getUint8(__classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
29
|
+
this.uint16 = this.constant(2, () => __classPrivateFieldGet(this, _Decoder_view, "f").getUint16(__classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
30
|
+
this.uint32 = this.constant(4, () => __classPrivateFieldGet(this, _Decoder_view, "f").getUint32(__classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
31
|
+
this.uint64 = this.constant(8, () => __classPrivateFieldGet(this, _Decoder_view, "f").getBigUint64(__classPrivateFieldGet(this, _Decoder_offset, "f")));
|
|
32
|
+
__classPrivateFieldSet(this, _Decoder_offset, 0, "f");
|
|
33
|
+
__classPrivateFieldSet(this, _Decoder_view, new DataView(data.buffer, data.byteOffset, data.byteLength), "f");
|
|
34
|
+
}
|
|
35
|
+
getOffset() {
|
|
36
|
+
return __classPrivateFieldGet(this, _Decoder_offset, "f");
|
|
20
37
|
}
|
|
21
38
|
decodeBytes(length) {
|
|
22
39
|
const value = new Uint8Array(length);
|
|
23
|
-
value.set(this.data.subarray(this
|
|
24
|
-
this
|
|
40
|
+
value.set(this.data.subarray(__classPrivateFieldGet(this, _Decoder_offset, "f"), __classPrivateFieldGet(this, _Decoder_offset, "f") + length), 0);
|
|
41
|
+
__classPrivateFieldSet(this, _Decoder_offset, __classPrivateFieldGet(this, _Decoder_offset, "f") + length, "f");
|
|
25
42
|
return value;
|
|
26
43
|
}
|
|
27
44
|
decodeString(length) {
|
|
28
|
-
const value = new TextDecoder().decode(this.data.subarray(this
|
|
29
|
-
this
|
|
45
|
+
const value = new TextDecoder().decode(this.data.subarray(__classPrivateFieldGet(this, _Decoder_offset, "f"), __classPrivateFieldGet(this, _Decoder_offset, "f") + length));
|
|
46
|
+
__classPrivateFieldSet(this, _Decoder_offset, __classPrivateFieldGet(this, _Decoder_offset, "f") + length, "f");
|
|
30
47
|
return value;
|
|
31
48
|
}
|
|
32
49
|
getArgument(additionalInformation) {
|
|
@@ -136,6 +153,7 @@ class Decoder {
|
|
|
136
153
|
}
|
|
137
154
|
}
|
|
138
155
|
}
|
|
156
|
+
_Decoder_offset = new WeakMap(), _Decoder_view = new WeakMap();
|
|
139
157
|
export function decode(data) {
|
|
140
158
|
return new Decoder(data).decodeValue();
|
|
141
159
|
}
|
package/lib/encode.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { CBORValue } from "./types.js";
|
|
2
2
|
export declare class Encoder {
|
|
3
|
+
#private;
|
|
3
4
|
static defaultChunkSize: number;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
private view;
|
|
7
|
-
private offset;
|
|
5
|
+
readonly noCopy: boolean;
|
|
6
|
+
readonly chunkSize: number;
|
|
8
7
|
private readonly encoder;
|
|
9
|
-
private readonly
|
|
8
|
+
private readonly buffer;
|
|
9
|
+
private readonly view;
|
|
10
|
+
private offset;
|
|
10
11
|
constructor(options?: {
|
|
11
|
-
chunkSize?: number;
|
|
12
12
|
noCopy?: boolean;
|
|
13
|
+
chunkSize?: number;
|
|
13
14
|
});
|
|
15
|
+
get closed(): boolean;
|
|
14
16
|
private allocate;
|
|
15
17
|
private float16;
|
|
16
18
|
private float32;
|
package/lib/encode.js
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _Encoder_instances, _Encoder_closed, _Encoder_flush;
|
|
13
|
+
import { getFloat16Precision, getFloat32Precision, setFloat16, Precision } from "fp16";
|
|
14
|
+
import { getByteLength } from "./encodingLength.js";
|
|
15
|
+
import { assert } from "./utils.js";
|
|
2
16
|
export class Encoder {
|
|
3
17
|
constructor(options = {}) {
|
|
18
|
+
_Encoder_instances.add(this);
|
|
19
|
+
_Encoder_closed.set(this, void 0);
|
|
4
20
|
this.encoder = new TextEncoder();
|
|
5
|
-
this.
|
|
21
|
+
this.noCopy = options.noCopy ?? false;
|
|
22
|
+
this.chunkSize = options.chunkSize ?? Encoder.defaultChunkSize;
|
|
23
|
+
assert(this.chunkSize >= 8, "expected chunkSize >= 8");
|
|
6
24
|
this.buffer = new ArrayBuffer(this.chunkSize);
|
|
7
25
|
this.view = new DataView(this.buffer);
|
|
8
26
|
this.offset = 0;
|
|
9
|
-
this
|
|
27
|
+
__classPrivateFieldSet(this, _Encoder_closed, false, "f");
|
|
28
|
+
}
|
|
29
|
+
get closed() {
|
|
30
|
+
return __classPrivateFieldGet(this, _Encoder_closed, "f");
|
|
10
31
|
}
|
|
11
32
|
*allocate(size) {
|
|
33
|
+
assert(size <= 8, "expected size <= 8");
|
|
12
34
|
if (this.buffer.byteLength < this.offset + size) {
|
|
13
|
-
yield
|
|
14
|
-
const byteLength = Math.max(size, this.chunkSize);
|
|
15
|
-
this.buffer = new ArrayBuffer(byteLength);
|
|
16
|
-
this.view = new DataView(this.buffer);
|
|
17
|
-
this.offset = 0;
|
|
35
|
+
yield __classPrivateFieldGet(this, _Encoder_instances, "m", _Encoder_flush).call(this);
|
|
18
36
|
}
|
|
19
37
|
}
|
|
20
38
|
*float16(value) {
|
|
@@ -73,9 +91,7 @@ export class Encoder {
|
|
|
73
91
|
else if (Object.is(value, -0)) {
|
|
74
92
|
yield* this.encodeFloat(value);
|
|
75
93
|
}
|
|
76
|
-
else if (Math.floor(value) === value &&
|
|
77
|
-
Number.MIN_SAFE_INTEGER <= value &&
|
|
78
|
-
value <= Number.MAX_SAFE_INTEGER) {
|
|
94
|
+
else if (Math.floor(value) === value && Number.MIN_SAFE_INTEGER <= value && value <= Number.MAX_SAFE_INTEGER) {
|
|
79
95
|
yield* this.encodeInteger(value);
|
|
80
96
|
}
|
|
81
97
|
else {
|
|
@@ -105,20 +121,38 @@ export class Encoder {
|
|
|
105
121
|
}
|
|
106
122
|
}
|
|
107
123
|
*encodeString(value) {
|
|
108
|
-
const
|
|
109
|
-
yield* this.encodeTypeAndArgument(3,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
const byteLength = getByteLength(value);
|
|
125
|
+
yield* this.encodeTypeAndArgument(3, byteLength);
|
|
126
|
+
let start = 0;
|
|
127
|
+
while (start < value.length) {
|
|
128
|
+
if (this.offset + 4 > this.buffer.byteLength) {
|
|
129
|
+
yield __classPrivateFieldGet(this, _Encoder_instances, "m", _Encoder_flush).call(this);
|
|
130
|
+
}
|
|
131
|
+
const target = new Uint8Array(this.buffer, this.offset);
|
|
132
|
+
const result = this.encoder.encodeInto(value.slice(start), target);
|
|
133
|
+
start += result.read;
|
|
134
|
+
this.offset += result.written;
|
|
135
|
+
assert(this.offset <= this.buffer.byteLength, "expected this.offset <= this.buffer.byteLength");
|
|
136
|
+
}
|
|
113
137
|
}
|
|
114
138
|
*encodeBytes(value) {
|
|
115
139
|
yield* this.encodeTypeAndArgument(2, value.byteLength);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
140
|
+
const target = new Uint8Array(this.buffer, 0, this.buffer.byteLength);
|
|
141
|
+
let start = 0;
|
|
142
|
+
while (start < value.byteLength) {
|
|
143
|
+
if (this.offset >= this.buffer.byteLength) {
|
|
144
|
+
yield __classPrivateFieldGet(this, _Encoder_instances, "m", _Encoder_flush).call(this);
|
|
145
|
+
}
|
|
146
|
+
const capacity = this.buffer.byteLength - this.offset;
|
|
147
|
+
const remaining = value.byteLength - start;
|
|
148
|
+
const chunkLength = Math.min(capacity, remaining);
|
|
149
|
+
target.set(value.subarray(start, start + chunkLength), this.offset);
|
|
150
|
+
start += chunkLength;
|
|
151
|
+
this.offset += chunkLength;
|
|
152
|
+
}
|
|
119
153
|
}
|
|
120
154
|
*encodeValue(value) {
|
|
121
|
-
if (this
|
|
155
|
+
if (__classPrivateFieldGet(this, _Encoder_closed, "f")) {
|
|
122
156
|
return;
|
|
123
157
|
}
|
|
124
158
|
if (value === false) {
|
|
@@ -158,10 +192,10 @@ export class Encoder {
|
|
|
158
192
|
}
|
|
159
193
|
}
|
|
160
194
|
*flush() {
|
|
161
|
-
if (this
|
|
195
|
+
if (__classPrivateFieldGet(this, _Encoder_closed, "f")) {
|
|
162
196
|
return;
|
|
163
197
|
}
|
|
164
|
-
this
|
|
198
|
+
__classPrivateFieldSet(this, _Encoder_closed, true, "f");
|
|
165
199
|
if (this.offset > 0) {
|
|
166
200
|
yield new Uint8Array(this.buffer, 0, this.offset);
|
|
167
201
|
}
|
|
@@ -205,6 +239,19 @@ export class Encoder {
|
|
|
205
239
|
}
|
|
206
240
|
}
|
|
207
241
|
}
|
|
242
|
+
_Encoder_closed = new WeakMap(), _Encoder_instances = new WeakSet(), _Encoder_flush = function _Encoder_flush() {
|
|
243
|
+
if (this.noCopy) {
|
|
244
|
+
const chunk = new Uint8Array(this.buffer, 0, this.offset);
|
|
245
|
+
this.offset = 0;
|
|
246
|
+
return chunk;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
const chunk = new Uint8Array(this.offset);
|
|
250
|
+
chunk.set(new Uint8Array(this.buffer, 0, this.offset));
|
|
251
|
+
this.offset = 0;
|
|
252
|
+
return chunk;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
208
255
|
Encoder.defaultChunkSize = 512;
|
|
209
256
|
export function encode(value, options = {}) {
|
|
210
257
|
const encoder = new Encoder(options);
|
package/lib/encodeStream.d.ts
CHANGED
package/lib/encodingLength.d.ts
CHANGED
package/lib/encodingLength.js
CHANGED
|
@@ -70,9 +70,7 @@ function numberEncodingLength(value) {
|
|
|
70
70
|
else if (Object.is(value, -0)) {
|
|
71
71
|
return floatEncodingLength(value);
|
|
72
72
|
}
|
|
73
|
-
else if (Math.floor(value) === value &&
|
|
74
|
-
Number.MIN_SAFE_INTEGER <= value &&
|
|
75
|
-
value <= Number.MAX_SAFE_INTEGER) {
|
|
73
|
+
else if (Math.floor(value) === value && Number.MIN_SAFE_INTEGER <= value && value <= Number.MAX_SAFE_INTEGER) {
|
|
76
74
|
return integerEncodingLength(value);
|
|
77
75
|
}
|
|
78
76
|
else {
|
|
@@ -99,7 +97,7 @@ function floatEncodingLength(value) {
|
|
|
99
97
|
}
|
|
100
98
|
}
|
|
101
99
|
function stringEncodingLength(value) {
|
|
102
|
-
const length =
|
|
100
|
+
const length = getByteLength(value);
|
|
103
101
|
return argumentEncodingLength(length) + length;
|
|
104
102
|
}
|
|
105
103
|
function bytesEncodingLength(value) {
|
|
@@ -107,7 +105,7 @@ function bytesEncodingLength(value) {
|
|
|
107
105
|
return argumentEncodingLength(length) + length;
|
|
108
106
|
}
|
|
109
107
|
// https://github.com/feross/buffer/blob/57caad4450d241207066ca3832fb8e9095ad402f/index.js#L434
|
|
110
|
-
function
|
|
108
|
+
export function getByteLength(string) {
|
|
111
109
|
let codePoint;
|
|
112
110
|
const length = string.length;
|
|
113
111
|
let leadSurrogate = null;
|
|
@@ -140,8 +138,7 @@ function byteLength(string) {
|
|
|
140
138
|
continue;
|
|
141
139
|
}
|
|
142
140
|
// valid surrogate pair
|
|
143
|
-
codePoint =
|
|
144
|
-
(((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000;
|
|
141
|
+
codePoint = (((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000;
|
|
145
142
|
}
|
|
146
143
|
else if (leadSurrogate) {
|
|
147
144
|
// valid bmp char, but last char was a lead
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { CBORValue, CBORMap, CBORArray } from "./types.js";
|
|
2
2
|
export { encode, Encoder } from "./encode.js";
|
|
3
|
-
export { decode } from "./decode.js";
|
|
3
|
+
export { decode, Decoder } from "./decode.js";
|
|
4
4
|
export { encodeStream } from "./encodeStream.js";
|
|
5
5
|
export { decodeStream } from "./decodeStream.js";
|
|
6
6
|
export { encodingLength } from "./encodingLength.js";
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { encode, Encoder } from "./encode.js";
|
|
2
|
-
export { decode } from "./decode.js";
|
|
2
|
+
export { decode, Decoder } from "./decode.js";
|
|
3
3
|
export { encodeStream } from "./encodeStream.js";
|
|
4
4
|
export { decodeStream } from "./decodeStream.js";
|
|
5
5
|
export { encodingLength } from "./encodingLength.js";
|
package/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type CBORValue = undefined | null | boolean | number | string | Uint8Array | CBORArray | CBORMap;
|
|
2
2
|
export interface CBORArray extends Array<CBORValue> {
|
|
3
3
|
}
|
|
4
4
|
export interface CBORMap {
|
package/lib/utils.d.ts
CHANGED
|
@@ -4,3 +4,9 @@ export declare class UnsafeIntegerError extends RangeError {
|
|
|
4
4
|
readonly value: bigint;
|
|
5
5
|
constructor(message: string, value: bigint);
|
|
6
6
|
}
|
|
7
|
+
export declare class AssertError extends Error {
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly props?: any | undefined;
|
|
10
|
+
constructor(message: string, props?: any | undefined);
|
|
11
|
+
}
|
|
12
|
+
export declare function assert(condition: unknown, message?: string, props?: any): asserts condition;
|
package/lib/utils.js
CHANGED
|
@@ -6,3 +6,15 @@ export class UnsafeIntegerError extends RangeError {
|
|
|
6
6
|
this.value = value;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
+
export class AssertError extends Error {
|
|
10
|
+
constructor(message, props) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.message = message;
|
|
13
|
+
this.props = props;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function assert(condition, message = "assertion failed", props) {
|
|
17
|
+
if (!condition) {
|
|
18
|
+
throw new AssertError(message, props);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "microcbor",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Encode JavaScript values as canonical CBOR",
|
|
3
|
+
"version": "0.4.0",
|
|
5
4
|
"type": "module",
|
|
6
|
-
"main": "lib/index.js",
|
|
7
|
-
"types": "lib/index.d.ts",
|
|
8
5
|
"files": [
|
|
9
6
|
"lib"
|
|
10
7
|
],
|
|
8
|
+
"description": "Encode JavaScript values as canonical CBOR",
|
|
9
|
+
"main": "lib/index.js",
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./lib/index.js"
|
|
13
|
+
},
|
|
11
14
|
"scripts": {
|
|
12
|
-
"
|
|
15
|
+
"dev": "tsc --build tsconfig.json test/tsconfig.json --watch",
|
|
16
|
+
"build": "tsc --build tsconfig.json test/tsconfig.json",
|
|
17
|
+
"clean": "tsc --build tsconfig.json test/tsconfig.json --clean",
|
|
13
18
|
"test": "ava"
|
|
14
19
|
},
|
|
15
20
|
"repository": {
|
|
@@ -27,11 +32,13 @@
|
|
|
27
32
|
},
|
|
28
33
|
"homepage": "https://github.com/joeltg/microcbor#readme",
|
|
29
34
|
"devDependencies": {
|
|
30
|
-
"ava": "^
|
|
31
|
-
"
|
|
32
|
-
"
|
|
35
|
+
"@ava/typescript": "^5.0.0",
|
|
36
|
+
"@types/node": "^22.13.9",
|
|
37
|
+
"ava": "^6.2.0",
|
|
38
|
+
"cbor": "^8.1.0",
|
|
39
|
+
"typescript": "^5.6.0"
|
|
33
40
|
},
|
|
34
41
|
"dependencies": {
|
|
35
|
-
"fp16": "^0.
|
|
42
|
+
"fp16": "^1.0.0"
|
|
36
43
|
}
|
|
37
44
|
}
|