cborg 1.7.0 → 1.9.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 +16 -0
- package/cjs/browser-test/common.js +24 -0
- package/cjs/browser-test/node-test-bin.js +15 -0
- package/cjs/browser-test/test-6tag.js +5 -19
- package/cjs/browser-test/test-length.js +63 -0
- package/cjs/lib/3string.js +12 -8
- package/cjs/lib/4array.js +3 -0
- package/cjs/lib/5map.js +3 -0
- package/cjs/lib/6tag.js +3 -0
- package/cjs/lib/7float.js +1 -2
- package/cjs/lib/bl.js +3 -1
- package/cjs/lib/diagnostic.js +11 -4
- package/cjs/lib/encode.js +15 -9
- package/cjs/lib/length.js +36 -0
- package/cjs/lib/token.js +1 -0
- package/cjs/node-test/common.js +24 -0
- package/cjs/node-test/node-test-bin.js +15 -0
- package/cjs/node-test/test-6tag.js +5 -19
- package/cjs/node-test/test-length.js +63 -0
- package/esm/browser-test/common.js +19 -0
- package/esm/browser-test/node-test-bin.js +15 -0
- package/esm/browser-test/test-6tag.js +4 -15
- package/esm/browser-test/test-length.js +55 -0
- package/esm/lib/3string.js +16 -9
- package/esm/lib/4array.js +4 -1
- package/esm/lib/5map.js +4 -1
- package/esm/lib/6tag.js +4 -1
- package/esm/lib/7float.js +1 -2
- package/esm/lib/bl.js +3 -1
- package/esm/lib/diagnostic.js +11 -4
- package/esm/lib/encode.js +14 -9
- package/esm/lib/length.js +31 -0
- package/esm/lib/token.js +1 -0
- package/esm/node-test/common.js +19 -0
- package/esm/node-test/node-test-bin.js +15 -0
- package/esm/node-test/test-6tag.js +4 -15
- package/esm/node-test/test-length.js +55 -0
- package/interface.ts +2 -0
- package/length +1 -0
- package/lib/3string.js +15 -10
- package/lib/4array.js +8 -0
- package/lib/5map.js +8 -0
- package/lib/6tag.js +8 -0
- package/lib/7float.js +1 -2
- package/lib/bl.js +3 -1
- package/lib/diagnostic.js +13 -6
- package/lib/encode.js +16 -10
- package/lib/length.js +61 -0
- package/lib/token.js +2 -0
- package/package.json +11 -2
- package/test/common.js +18 -0
- package/test/node-test-bin.js +19 -0
- package/test/test-6tag.js +1 -17
- package/test/test-length.js +65 -0
- package/types/interface.d.ts +1 -0
- package/types/interface.d.ts.map +1 -1
- package/types/lib/3string.d.ts +2 -2
- package/types/lib/3string.d.ts.map +1 -1
- package/types/lib/4array.d.ts +5 -0
- package/types/lib/4array.d.ts.map +1 -1
- package/types/lib/5map.d.ts +5 -0
- package/types/lib/5map.d.ts.map +1 -1
- package/types/lib/6tag.d.ts +5 -0
- package/types/lib/6tag.d.ts.map +1 -1
- package/types/lib/7float.d.ts.map +1 -1
- package/types/lib/bl.d.ts.map +1 -1
- package/types/lib/diagnostic.d.ts.map +1 -1
- package/types/lib/encode.d.ts +2 -0
- package/types/lib/encode.d.ts.map +1 -1
- package/types/lib/length.d.ts +27 -0
- package/types/lib/length.d.ts.map +1 -0
- package/types/lib/token.d.ts +2 -0
- package/types/lib/token.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* [Options](#options)
|
|
28
28
|
* [`decode(data[, options])`](#decodedata-options)
|
|
29
29
|
* [Options](#options-1)
|
|
30
|
+
* [`encodedLength(data[, options])`](#encodedlengthdata-options)
|
|
30
31
|
* [Type encoders](#type-encoders)
|
|
31
32
|
* [Tag decoders](#tag-decoders)
|
|
32
33
|
* [Deterministic encoding recommendations](#deterministic-encoding-recommendations)
|
|
@@ -246,9 +247,24 @@ Decode valid CBOR bytes from a `Uint8Array` (or `Buffer`) and return a JavaScrip
|
|
|
246
247
|
* `strict` (boolean, default `false`): when decoding integers, including for lengths (arrays, maps, strings, bytes), values will be checked to see whether they were encoded in their smallest possible form. If not, an error will be thrown.
|
|
247
248
|
* Currently, this form of deterministic strictness cannot be enforced for float representations, or map key ordering (pull requests _very_ welcome).
|
|
248
249
|
* `useMaps` (boolean, default `false`): when decoding major 5 (map) entries, use a `Map` rather than a plain `Object`. This will nest for any encountered map. During encode, a `Map` will be interpreted as an `Object` and will round-trip as such unless `useMaps` is supplied, in which case, all `Map`s and `Object`s will round-trip as `Map`s. There is no way to retain the distinction during round-trip without using a custom tag.
|
|
250
|
+
* `retainStringBytes` (boolean, default `false`): when decoding strings, retain the original bytes on the `Token` object as `byteValue`. Since it is possible to encode non-UTF-8 characters in strings in CBOR, and JavaScript doesn't properly handle non-UTF-8 in its conversion from bytes (`TextEncoder` or `Buffer`), this can result in a loss of data (and an inability to round-trip). Where this is important, a token stream should be consumed instead of a plain `decode()` and the `byteValue` property on string tokens can be inspected (see [lib/diagnostic.js](lib/diagnostic.js) for an example of its use.)
|
|
249
251
|
* `tags` (array): a mapping of tag number to tag decoder function. By default no tags are supported. See [Tag decoders](#tag-decoders).
|
|
250
252
|
* `tokenizer` (object): an object with two methods, `next()` which returns a `Token` and `done()` which returns a `boolean`. Can be used to implement custom input decoding. See the source code for examples.
|
|
251
253
|
|
|
254
|
+
### `encodedLength(data[, options])`
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
import { encodedLength } from 'cborg/length'
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
const { encodedLength } = require('cborg/length')
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Calculate the byte length of the given data when encoded as CBOR with the options provided. The options are the same as for an `encode()` call. This calculation will be accurate if the same options are used as when performing a normal `encode()`. Some encode options can change the encoding output length.
|
|
265
|
+
|
|
266
|
+
A `tokensToLength()` function is available which deals directly with a tokenized form of the object, but this only recommended for advanced users.
|
|
267
|
+
|
|
252
268
|
### Type encoders
|
|
253
269
|
|
|
254
270
|
The `typeEncoders` property to the `options` argument to `encode()` allows you to add additional functionality to cborg, or override existing functionality.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var token = require('../lib/token.js');
|
|
6
|
+
|
|
7
|
+
function dateDecoder(obj) {
|
|
8
|
+
if (typeof obj !== 'string') {
|
|
9
|
+
throw new Error('expected string for tag 1');
|
|
10
|
+
}
|
|
11
|
+
return new Date(obj);
|
|
12
|
+
}
|
|
13
|
+
function dateEncoder(obj) {
|
|
14
|
+
if (!(obj instanceof Date)) {
|
|
15
|
+
throw new Error('expected Date for "Date" encoder');
|
|
16
|
+
}
|
|
17
|
+
return [
|
|
18
|
+
new token.Token(token.Type.tag, 0),
|
|
19
|
+
new token.Token(token.Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.dateDecoder = dateDecoder;
|
|
24
|
+
exports.dateEncoder = dateEncoder;
|
|
@@ -331,4 +331,19 @@ Input may either be supplied as an argument or piped via stdin
|
|
|
331
331
|
`);
|
|
332
332
|
});
|
|
333
333
|
});
|
|
334
|
+
it('diag non-utf8 and non-printable ascii', async () => {
|
|
335
|
+
const input = '7864f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c11e756338bd93865e645f1adec9b9c99ef407fbd4fc6859e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82f9f18c3d03418e35';
|
|
336
|
+
let {stdout, stderr} = await execBin(`hex2diag ${ input }`);
|
|
337
|
+
assert.strictEqual(stderr, '');
|
|
338
|
+
assert.strictEqual(stdout, `78 64 # string(86)
|
|
339
|
+
f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b # "õ_øñ%\\x08¶>ò¿ì§Uzé\\x0dö1\\x1a^Ác\\x1b"
|
|
340
|
+
4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c # "J\\x1f¨C1\\x0bÙç\\x10ê¬å¡½×*пàIw\\x1c"
|
|
341
|
+
11e756338bd93865e645f1adec9b9c99ef407fbd4fc685 # "\\x11çV3\\x8bÙ8eæEñ\\xadì\\x9b\\x9c\\x99ï@\\x7f½OÆ\\x85"
|
|
342
|
+
9e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82 # "\\x9ey\\x04Å\\xad}ɽ\\x10¥Ì\\x16\\x97=[(ì\\x1amÔ=\\x9f\\x82"
|
|
343
|
+
f9f18c3d03418e35 # "ùñ\\x8c=\\x03A\\x8e5"
|
|
344
|
+
`);
|
|
345
|
+
({stdout, stderr} = await execBin('diag2hex', stdout));
|
|
346
|
+
assert.strictEqual(stderr, '');
|
|
347
|
+
assert.strictEqual(stdout, `${ input }\n`);
|
|
348
|
+
});
|
|
334
349
|
});
|
|
@@ -4,6 +4,7 @@ var chai = require('chai');
|
|
|
4
4
|
var token = require('../lib/token.js');
|
|
5
5
|
require('../cborg.js');
|
|
6
6
|
var byteUtils = require('../lib/byte-utils.js');
|
|
7
|
+
var common = require('./common.js');
|
|
7
8
|
var encode = require('../lib/encode.js');
|
|
8
9
|
var decode = require('../lib/decode.js');
|
|
9
10
|
|
|
@@ -12,21 +13,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
12
13
|
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
|
|
13
14
|
|
|
14
15
|
const {assert} = chai__default["default"];
|
|
15
|
-
function dateDecoder(obj) {
|
|
16
|
-
if (typeof obj !== 'string') {
|
|
17
|
-
throw new Error('expected string for tag 1');
|
|
18
|
-
}
|
|
19
|
-
return new Date(obj);
|
|
20
|
-
}
|
|
21
|
-
function dateEncoder(obj) {
|
|
22
|
-
if (!(obj instanceof Date)) {
|
|
23
|
-
throw new Error('expected Date for "Date" encoder');
|
|
24
|
-
}
|
|
25
|
-
return [
|
|
26
|
-
new token.Token(token.Type.tag, 0),
|
|
27
|
-
new token.Token(token.Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
16
|
function Uint16ArrayDecoder(obj) {
|
|
31
17
|
if (typeof obj !== 'string') {
|
|
32
18
|
throw new Error('expected string for tag 23');
|
|
@@ -46,8 +32,8 @@ function Uint16ArrayEncoder(obj) {
|
|
|
46
32
|
describe('tag', () => {
|
|
47
33
|
it('date', () => {
|
|
48
34
|
assert.throws(() => encode.encode({ d: new Date() }), /unsupported type: Date/);
|
|
49
|
-
assert.equal(byteUtils.toHex(encode.encode(new Date('2013-03-21T20:04:00Z'), { typeEncoders: { Date: dateEncoder } })), 'c074323031332d30332d32315432303a30343a30305a');
|
|
50
|
-
const decodedDate = decode.decode(byteUtils.fromHex('c074323031332d30332d32315432303a30343a30305a'), { tags: { 0: dateDecoder } });
|
|
35
|
+
assert.equal(byteUtils.toHex(encode.encode(new Date('2013-03-21T20:04:00Z'), { typeEncoders: { Date: common.dateEncoder } })), 'c074323031332d30332d32315432303a30343a30305a');
|
|
36
|
+
const decodedDate = decode.decode(byteUtils.fromHex('c074323031332d30332d32315432303a30343a30305a'), { tags: { 0: common.dateDecoder } });
|
|
51
37
|
assert.instanceOf(decodedDate, Date);
|
|
52
38
|
assert.equal(decodedDate.toISOString(), new Date('2013-03-21T20:04:00Z').toISOString());
|
|
53
39
|
});
|
|
@@ -69,12 +55,12 @@ describe('tag', () => {
|
|
|
69
55
|
const verify = (hex, strict) => {
|
|
70
56
|
if (!strict) {
|
|
71
57
|
assert.throws(() => decode.decode(byteUtils.fromHex(hex), {
|
|
72
|
-
tags: { 8: dateDecoder },
|
|
58
|
+
tags: { 8: common.dateDecoder },
|
|
73
59
|
strict: true
|
|
74
60
|
}), /integer encoded in more bytes than necessary/);
|
|
75
61
|
}
|
|
76
62
|
const decodedDate = decode.decode(byteUtils.fromHex(hex), {
|
|
77
|
-
tags: { 8: dateDecoder },
|
|
63
|
+
tags: { 8: common.dateDecoder },
|
|
78
64
|
strict
|
|
79
65
|
});
|
|
80
66
|
assert.instanceOf(decodedDate, Date);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chai = require('chai');
|
|
4
|
+
var ipldGarbage = require('ipld-garbage');
|
|
5
|
+
var _0uint = require('../lib/0uint.js');
|
|
6
|
+
require('../cborg.js');
|
|
7
|
+
var length = require('../lib/length.js');
|
|
8
|
+
var common = require('./common.js');
|
|
9
|
+
var encode = require('../lib/encode.js');
|
|
10
|
+
|
|
11
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
|
+
|
|
13
|
+
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
|
|
14
|
+
|
|
15
|
+
const {assert} = chai__default["default"];
|
|
16
|
+
function verifyLength(object, options) {
|
|
17
|
+
const len = length.encodedLength(object, options);
|
|
18
|
+
const encoded = encode.encode(object, options);
|
|
19
|
+
const actual = encoded.length;
|
|
20
|
+
assert.strictEqual(actual, len, JSON.stringify(object));
|
|
21
|
+
}
|
|
22
|
+
describe('encodedLength', () => {
|
|
23
|
+
it('int boundaries', () => {
|
|
24
|
+
for (let ii = 0; ii < 4; ii++) {
|
|
25
|
+
verifyLength(_0uint.uintBoundaries[ii]);
|
|
26
|
+
verifyLength(_0uint.uintBoundaries[ii] - 1);
|
|
27
|
+
verifyLength(_0uint.uintBoundaries[ii] + 1);
|
|
28
|
+
verifyLength(-1 * _0uint.uintBoundaries[ii]);
|
|
29
|
+
verifyLength(-1 * _0uint.uintBoundaries[ii] - 1);
|
|
30
|
+
verifyLength(-1 * _0uint.uintBoundaries[ii] + 1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
it('tags', () => {
|
|
34
|
+
verifyLength({ date: new Date('2013-03-21T20:04:00Z') }, { typeEncoders: { Date: common.dateEncoder } });
|
|
35
|
+
});
|
|
36
|
+
it('floats', () => {
|
|
37
|
+
verifyLength(0.5);
|
|
38
|
+
verifyLength(0.5, { float64: true });
|
|
39
|
+
verifyLength(8.940696716308594e-8);
|
|
40
|
+
verifyLength(8.940696716308594e-8, { float64: true });
|
|
41
|
+
});
|
|
42
|
+
it('small garbage', function () {
|
|
43
|
+
this.timeout(10000);
|
|
44
|
+
for (let ii = 0; ii < 1000; ii++) {
|
|
45
|
+
const gbg = ipldGarbage.garbage(1 << 6, { weights: { CID: 0 } });
|
|
46
|
+
verifyLength(gbg);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
it('medium garbage', function () {
|
|
50
|
+
this.timeout(10000);
|
|
51
|
+
for (let ii = 0; ii < 100; ii++) {
|
|
52
|
+
const gbg = ipldGarbage.garbage(1 << 16, { weights: { CID: 0 } });
|
|
53
|
+
verifyLength(gbg);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
it('large garbage', function () {
|
|
57
|
+
this.timeout(10000);
|
|
58
|
+
for (let ii = 0; ii < 10; ii++) {
|
|
59
|
+
const gbg = ipldGarbage.garbage(1 << 20, { weights: { CID: 0 } });
|
|
60
|
+
verifyLength(gbg);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
package/cjs/lib/3string.js
CHANGED
|
@@ -8,29 +8,33 @@ var _0uint = require('./0uint.js');
|
|
|
8
8
|
var _2bytes = require('./2bytes.js');
|
|
9
9
|
var byteUtils = require('./byte-utils.js');
|
|
10
10
|
|
|
11
|
-
function toToken(data, pos, prefix, length) {
|
|
11
|
+
function toToken(data, pos, prefix, length, options) {
|
|
12
12
|
const totLength = prefix + length;
|
|
13
13
|
common.assertEnoughData(data, pos, totLength);
|
|
14
|
-
|
|
14
|
+
const tok = new token.Token(token.Type.string, byteUtils.toString(data, pos + prefix, pos + totLength), totLength);
|
|
15
|
+
if (options.retainStringBytes === true) {
|
|
16
|
+
tok.byteValue = byteUtils.slice(data, pos + prefix, pos + totLength);
|
|
17
|
+
}
|
|
18
|
+
return tok;
|
|
15
19
|
}
|
|
16
|
-
function decodeStringCompact(data, pos, minor,
|
|
17
|
-
return toToken(data, pos, 1, minor);
|
|
20
|
+
function decodeStringCompact(data, pos, minor, options) {
|
|
21
|
+
return toToken(data, pos, 1, minor, options);
|
|
18
22
|
}
|
|
19
23
|
function decodeString8(data, pos, _minor, options) {
|
|
20
|
-
return toToken(data, pos, 2, _0uint.readUint8(data, pos + 1, options));
|
|
24
|
+
return toToken(data, pos, 2, _0uint.readUint8(data, pos + 1, options), options);
|
|
21
25
|
}
|
|
22
26
|
function decodeString16(data, pos, _minor, options) {
|
|
23
|
-
return toToken(data, pos, 3, _0uint.readUint16(data, pos + 1, options));
|
|
27
|
+
return toToken(data, pos, 3, _0uint.readUint16(data, pos + 1, options), options);
|
|
24
28
|
}
|
|
25
29
|
function decodeString32(data, pos, _minor, options) {
|
|
26
|
-
return toToken(data, pos, 5, _0uint.readUint32(data, pos + 1, options));
|
|
30
|
+
return toToken(data, pos, 5, _0uint.readUint32(data, pos + 1, options), options);
|
|
27
31
|
}
|
|
28
32
|
function decodeString64(data, pos, _minor, options) {
|
|
29
33
|
const l = _0uint.readUint64(data, pos + 1, options);
|
|
30
34
|
if (typeof l === 'bigint') {
|
|
31
35
|
throw new Error(`${ common.decodeErrPrefix } 64-bit integer string lengths not supported`);
|
|
32
36
|
}
|
|
33
|
-
return toToken(data, pos, 9, l);
|
|
37
|
+
return toToken(data, pos, 9, l, options);
|
|
34
38
|
}
|
|
35
39
|
const encodeString = _2bytes.encodeBytes;
|
|
36
40
|
|
package/cjs/lib/4array.js
CHANGED
|
@@ -38,6 +38,9 @@ function encodeArray(buf, token$1) {
|
|
|
38
38
|
_0uint.encodeUintValue(buf, token.Type.array.majorEncoded, token$1.value);
|
|
39
39
|
}
|
|
40
40
|
encodeArray.compareTokens = _0uint.encodeUint.compareTokens;
|
|
41
|
+
encodeArray.encodedSize = function encodedSize(token) {
|
|
42
|
+
return _0uint.encodeUintValue.encodedSize(token.value);
|
|
43
|
+
};
|
|
41
44
|
|
|
42
45
|
exports.decodeArray16 = decodeArray16;
|
|
43
46
|
exports.decodeArray32 = decodeArray32;
|
package/cjs/lib/5map.js
CHANGED
|
@@ -38,6 +38,9 @@ function encodeMap(buf, token$1) {
|
|
|
38
38
|
_0uint.encodeUintValue(buf, token.Type.map.majorEncoded, token$1.value);
|
|
39
39
|
}
|
|
40
40
|
encodeMap.compareTokens = _0uint.encodeUint.compareTokens;
|
|
41
|
+
encodeMap.encodedSize = function encodedSize(token) {
|
|
42
|
+
return _0uint.encodeUintValue.encodedSize(token.value);
|
|
43
|
+
};
|
|
41
44
|
|
|
42
45
|
exports.decodeMap16 = decodeMap16;
|
|
43
46
|
exports.decodeMap32 = decodeMap32;
|
package/cjs/lib/6tag.js
CHANGED
|
@@ -24,6 +24,9 @@ function encodeTag(buf, token$1) {
|
|
|
24
24
|
_0uint.encodeUintValue(buf, token.Type.tag.majorEncoded, token$1.value);
|
|
25
25
|
}
|
|
26
26
|
encodeTag.compareTokens = _0uint.encodeUint.compareTokens;
|
|
27
|
+
encodeTag.encodedSize = function encodedSize(token) {
|
|
28
|
+
return _0uint.encodeUintValue.encodedSize(token.value);
|
|
29
|
+
};
|
|
27
30
|
|
|
28
31
|
exports.decodeTag16 = decodeTag16;
|
|
29
32
|
exports.decodeTag32 = decodeTag32;
|
package/cjs/lib/7float.js
CHANGED
|
@@ -87,10 +87,9 @@ encodeFloat.encodedSize = function encodedSize(token, options) {
|
|
|
87
87
|
if (float === false || float === true || float === null || float === undefined) {
|
|
88
88
|
return 1;
|
|
89
89
|
}
|
|
90
|
-
let decoded;
|
|
91
90
|
if (!options || options.float64 !== true) {
|
|
92
91
|
encodeFloat16(float);
|
|
93
|
-
decoded = readFloat16(ui8a, 1);
|
|
92
|
+
let decoded = readFloat16(ui8a, 1);
|
|
94
93
|
if (float === decoded || Number.isNaN(float)) {
|
|
95
94
|
return 3;
|
|
96
95
|
}
|
package/cjs/lib/bl.js
CHANGED
|
@@ -14,9 +14,11 @@ class Bl {
|
|
|
14
14
|
this._initReuseChunk = null;
|
|
15
15
|
}
|
|
16
16
|
reset() {
|
|
17
|
-
this.chunks = [];
|
|
18
17
|
this.cursor = 0;
|
|
19
18
|
this.maxCursor = -1;
|
|
19
|
+
if (this.chunks.length) {
|
|
20
|
+
this.chunks = [];
|
|
21
|
+
}
|
|
20
22
|
if (this._initReuseChunk !== null) {
|
|
21
23
|
this.chunks.push(this._initReuseChunk);
|
|
22
24
|
this.maxCursor = this._initReuseChunk.length - 1;
|
package/cjs/lib/diagnostic.js
CHANGED
|
@@ -9,7 +9,7 @@ var _0uint = require('./0uint.js');
|
|
|
9
9
|
const utf8Encoder = new TextEncoder();
|
|
10
10
|
const utf8Decoder = new TextDecoder();
|
|
11
11
|
function* tokensToDiagnostic(inp, width = 100) {
|
|
12
|
-
const tokeniser = new decode.Tokeniser(inp);
|
|
12
|
+
const tokeniser = new decode.Tokeniser(inp, { retainStringBytes: true });
|
|
13
13
|
let pos = 0;
|
|
14
14
|
const indent = [];
|
|
15
15
|
const slc = (start, length) => {
|
|
@@ -59,15 +59,22 @@ function* tokensToDiagnostic(inp, width = 100) {
|
|
|
59
59
|
}
|
|
60
60
|
yield outp;
|
|
61
61
|
if (str) {
|
|
62
|
+
let asString = token.type.name === 'string';
|
|
62
63
|
margin += ' ';
|
|
63
|
-
|
|
64
|
+
let repr = asString ? utf8Encoder.encode(token.value) : token.value;
|
|
65
|
+
if (asString && token.byteValue !== undefined) {
|
|
66
|
+
if (repr.length !== token.byteValue.length) {
|
|
67
|
+
repr = token.byteValue;
|
|
68
|
+
asString = false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
64
71
|
const wh = (width / 2 - margin.length - 1) / 2;
|
|
65
72
|
let snip = 0;
|
|
66
73
|
while (repr.length - snip > 0) {
|
|
67
74
|
const piece = repr.slice(snip, snip + wh);
|
|
68
75
|
snip += piece.length;
|
|
69
|
-
const st =
|
|
70
|
-
if (c < 32 || c ===
|
|
76
|
+
const st = asString ? utf8Decoder.decode(piece) : piece.reduce((p, c) => {
|
|
77
|
+
if (c < 32 || c >= 127 && c < 161 || c === 173) {
|
|
71
78
|
return `${ p }\\x${ c.toString(16).padStart(2, '0') }`;
|
|
72
79
|
}
|
|
73
80
|
return `${ p }${ String.fromCharCode(c) }`;
|
package/cjs/lib/encode.js
CHANGED
|
@@ -22,15 +22,19 @@ const defaultEncodeOptions = {
|
|
|
22
22
|
mapSorter,
|
|
23
23
|
quickEncodeToken: jump.quickEncodeToken
|
|
24
24
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
function makeCborEncoders() {
|
|
26
|
+
const encoders = [];
|
|
27
|
+
encoders[token.Type.uint.major] = _0uint.encodeUint;
|
|
28
|
+
encoders[token.Type.negint.major] = _1negint.encodeNegint;
|
|
29
|
+
encoders[token.Type.bytes.major] = _2bytes.encodeBytes;
|
|
30
|
+
encoders[token.Type.string.major] = _3string.encodeString;
|
|
31
|
+
encoders[token.Type.array.major] = _4array.encodeArray;
|
|
32
|
+
encoders[token.Type.map.major] = _5map.encodeMap;
|
|
33
|
+
encoders[token.Type.tag.major] = _6tag.encodeTag;
|
|
34
|
+
encoders[token.Type.float.major] = _7float.encodeFloat;
|
|
35
|
+
return encoders;
|
|
36
|
+
}
|
|
37
|
+
const cborEncoders = makeCborEncoders();
|
|
34
38
|
const buf = new bl.Bl();
|
|
35
39
|
class Ref {
|
|
36
40
|
constructor(obj, parent) {
|
|
@@ -228,6 +232,7 @@ function encodeCustom(data, encoders, options) {
|
|
|
228
232
|
return byteUtils.asU8A(buf.chunks[0]);
|
|
229
233
|
}
|
|
230
234
|
}
|
|
235
|
+
buf.reset();
|
|
231
236
|
tokensToEncoded(buf, tokens, encoders, options);
|
|
232
237
|
return buf.toBytes(true);
|
|
233
238
|
}
|
|
@@ -239,4 +244,5 @@ function encode(data, options) {
|
|
|
239
244
|
exports.Ref = Ref;
|
|
240
245
|
exports.encode = encode;
|
|
241
246
|
exports.encodeCustom = encodeCustom;
|
|
247
|
+
exports.makeCborEncoders = makeCborEncoders;
|
|
242
248
|
exports.objectToTokens = objectToTokens;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var encode = require('./encode.js');
|
|
6
|
+
var jump = require('./jump.js');
|
|
7
|
+
|
|
8
|
+
const cborEncoders = encode.makeCborEncoders();
|
|
9
|
+
const defaultEncodeOptions = {
|
|
10
|
+
float64: false,
|
|
11
|
+
quickEncodeToken: jump.quickEncodeToken
|
|
12
|
+
};
|
|
13
|
+
function encodedLength(data, options) {
|
|
14
|
+
options = Object.assign({}, defaultEncodeOptions, options);
|
|
15
|
+
options.mapSorter = undefined;
|
|
16
|
+
const tokens = encode.objectToTokens(data, options);
|
|
17
|
+
return tokensToLength(tokens, cborEncoders, options);
|
|
18
|
+
}
|
|
19
|
+
function tokensToLength(tokens, encoders = cborEncoders, options = defaultEncodeOptions) {
|
|
20
|
+
if (Array.isArray(tokens)) {
|
|
21
|
+
let len = 0;
|
|
22
|
+
for (const token of tokens) {
|
|
23
|
+
len += tokensToLength(token, encoders, options);
|
|
24
|
+
}
|
|
25
|
+
return len;
|
|
26
|
+
} else {
|
|
27
|
+
const encoder = encoders[tokens.type.major];
|
|
28
|
+
if (encoder.encodedSize === undefined || typeof encoder.encodedSize !== 'function') {
|
|
29
|
+
throw new Error(`Encoder for ${ tokens.type.name } does not have an encodedSize()`);
|
|
30
|
+
}
|
|
31
|
+
return encoder.encodedSize(tokens, options);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.encodedLength = encodedLength;
|
|
36
|
+
exports.tokensToLength = tokensToLength;
|
package/cjs/lib/token.js
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var token = require('../lib/token.js');
|
|
6
|
+
|
|
7
|
+
function dateDecoder(obj) {
|
|
8
|
+
if (typeof obj !== 'string') {
|
|
9
|
+
throw new Error('expected string for tag 1');
|
|
10
|
+
}
|
|
11
|
+
return new Date(obj);
|
|
12
|
+
}
|
|
13
|
+
function dateEncoder(obj) {
|
|
14
|
+
if (!(obj instanceof Date)) {
|
|
15
|
+
throw new Error('expected Date for "Date" encoder');
|
|
16
|
+
}
|
|
17
|
+
return [
|
|
18
|
+
new token.Token(token.Type.tag, 0),
|
|
19
|
+
new token.Token(token.Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.dateDecoder = dateDecoder;
|
|
24
|
+
exports.dateEncoder = dateEncoder;
|
|
@@ -331,4 +331,19 @@ Input may either be supplied as an argument or piped via stdin
|
|
|
331
331
|
`);
|
|
332
332
|
});
|
|
333
333
|
});
|
|
334
|
+
it('diag non-utf8 and non-printable ascii', async () => {
|
|
335
|
+
const input = '7864f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c11e756338bd93865e645f1adec9b9c99ef407fbd4fc6859e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82f9f18c3d03418e35';
|
|
336
|
+
let {stdout, stderr} = await execBin(`hex2diag ${ input }`);
|
|
337
|
+
assert.strictEqual(stderr, '');
|
|
338
|
+
assert.strictEqual(stdout, `78 64 # string(86)
|
|
339
|
+
f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b # "õ_øñ%\\x08¶>ò¿ì§Uzé\\x0dö1\\x1a^Ác\\x1b"
|
|
340
|
+
4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c # "J\\x1f¨C1\\x0bÙç\\x10ê¬å¡½×*пàIw\\x1c"
|
|
341
|
+
11e756338bd93865e645f1adec9b9c99ef407fbd4fc685 # "\\x11çV3\\x8bÙ8eæEñ\\xadì\\x9b\\x9c\\x99ï@\\x7f½OÆ\\x85"
|
|
342
|
+
9e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82 # "\\x9ey\\x04Å\\xad}ɽ\\x10¥Ì\\x16\\x97=[(ì\\x1amÔ=\\x9f\\x82"
|
|
343
|
+
f9f18c3d03418e35 # "ùñ\\x8c=\\x03A\\x8e5"
|
|
344
|
+
`);
|
|
345
|
+
({stdout, stderr} = await execBin('diag2hex', stdout));
|
|
346
|
+
assert.strictEqual(stderr, '');
|
|
347
|
+
assert.strictEqual(stdout, `${ input }\n`);
|
|
348
|
+
});
|
|
334
349
|
});
|
|
@@ -4,6 +4,7 @@ var chai = require('chai');
|
|
|
4
4
|
var token = require('../lib/token.js');
|
|
5
5
|
require('../cborg.js');
|
|
6
6
|
var byteUtils = require('../lib/byte-utils.js');
|
|
7
|
+
var common = require('./common.js');
|
|
7
8
|
var encode = require('../lib/encode.js');
|
|
8
9
|
var decode = require('../lib/decode.js');
|
|
9
10
|
|
|
@@ -12,21 +13,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
12
13
|
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
|
|
13
14
|
|
|
14
15
|
const {assert} = chai__default["default"];
|
|
15
|
-
function dateDecoder(obj) {
|
|
16
|
-
if (typeof obj !== 'string') {
|
|
17
|
-
throw new Error('expected string for tag 1');
|
|
18
|
-
}
|
|
19
|
-
return new Date(obj);
|
|
20
|
-
}
|
|
21
|
-
function dateEncoder(obj) {
|
|
22
|
-
if (!(obj instanceof Date)) {
|
|
23
|
-
throw new Error('expected Date for "Date" encoder');
|
|
24
|
-
}
|
|
25
|
-
return [
|
|
26
|
-
new token.Token(token.Type.tag, 0),
|
|
27
|
-
new token.Token(token.Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
16
|
function Uint16ArrayDecoder(obj) {
|
|
31
17
|
if (typeof obj !== 'string') {
|
|
32
18
|
throw new Error('expected string for tag 23');
|
|
@@ -46,8 +32,8 @@ function Uint16ArrayEncoder(obj) {
|
|
|
46
32
|
describe('tag', () => {
|
|
47
33
|
it('date', () => {
|
|
48
34
|
assert.throws(() => encode.encode({ d: new Date() }), /unsupported type: Date/);
|
|
49
|
-
assert.equal(byteUtils.toHex(encode.encode(new Date('2013-03-21T20:04:00Z'), { typeEncoders: { Date: dateEncoder } })), 'c074323031332d30332d32315432303a30343a30305a');
|
|
50
|
-
const decodedDate = decode.decode(byteUtils.fromHex('c074323031332d30332d32315432303a30343a30305a'), { tags: { 0: dateDecoder } });
|
|
35
|
+
assert.equal(byteUtils.toHex(encode.encode(new Date('2013-03-21T20:04:00Z'), { typeEncoders: { Date: common.dateEncoder } })), 'c074323031332d30332d32315432303a30343a30305a');
|
|
36
|
+
const decodedDate = decode.decode(byteUtils.fromHex('c074323031332d30332d32315432303a30343a30305a'), { tags: { 0: common.dateDecoder } });
|
|
51
37
|
assert.instanceOf(decodedDate, Date);
|
|
52
38
|
assert.equal(decodedDate.toISOString(), new Date('2013-03-21T20:04:00Z').toISOString());
|
|
53
39
|
});
|
|
@@ -69,12 +55,12 @@ describe('tag', () => {
|
|
|
69
55
|
const verify = (hex, strict) => {
|
|
70
56
|
if (!strict) {
|
|
71
57
|
assert.throws(() => decode.decode(byteUtils.fromHex(hex), {
|
|
72
|
-
tags: { 8: dateDecoder },
|
|
58
|
+
tags: { 8: common.dateDecoder },
|
|
73
59
|
strict: true
|
|
74
60
|
}), /integer encoded in more bytes than necessary/);
|
|
75
61
|
}
|
|
76
62
|
const decodedDate = decode.decode(byteUtils.fromHex(hex), {
|
|
77
|
-
tags: { 8: dateDecoder },
|
|
63
|
+
tags: { 8: common.dateDecoder },
|
|
78
64
|
strict
|
|
79
65
|
});
|
|
80
66
|
assert.instanceOf(decodedDate, Date);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chai = require('chai');
|
|
4
|
+
var ipldGarbage = require('ipld-garbage');
|
|
5
|
+
var _0uint = require('../lib/0uint.js');
|
|
6
|
+
require('../cborg.js');
|
|
7
|
+
var length = require('../lib/length.js');
|
|
8
|
+
var common = require('./common.js');
|
|
9
|
+
var encode = require('../lib/encode.js');
|
|
10
|
+
|
|
11
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
|
+
|
|
13
|
+
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
|
|
14
|
+
|
|
15
|
+
const {assert} = chai__default["default"];
|
|
16
|
+
function verifyLength(object, options) {
|
|
17
|
+
const len = length.encodedLength(object, options);
|
|
18
|
+
const encoded = encode.encode(object, options);
|
|
19
|
+
const actual = encoded.length;
|
|
20
|
+
assert.strictEqual(actual, len, JSON.stringify(object));
|
|
21
|
+
}
|
|
22
|
+
describe('encodedLength', () => {
|
|
23
|
+
it('int boundaries', () => {
|
|
24
|
+
for (let ii = 0; ii < 4; ii++) {
|
|
25
|
+
verifyLength(_0uint.uintBoundaries[ii]);
|
|
26
|
+
verifyLength(_0uint.uintBoundaries[ii] - 1);
|
|
27
|
+
verifyLength(_0uint.uintBoundaries[ii] + 1);
|
|
28
|
+
verifyLength(-1 * _0uint.uintBoundaries[ii]);
|
|
29
|
+
verifyLength(-1 * _0uint.uintBoundaries[ii] - 1);
|
|
30
|
+
verifyLength(-1 * _0uint.uintBoundaries[ii] + 1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
it('tags', () => {
|
|
34
|
+
verifyLength({ date: new Date('2013-03-21T20:04:00Z') }, { typeEncoders: { Date: common.dateEncoder } });
|
|
35
|
+
});
|
|
36
|
+
it('floats', () => {
|
|
37
|
+
verifyLength(0.5);
|
|
38
|
+
verifyLength(0.5, { float64: true });
|
|
39
|
+
verifyLength(8.940696716308594e-8);
|
|
40
|
+
verifyLength(8.940696716308594e-8, { float64: true });
|
|
41
|
+
});
|
|
42
|
+
it('small garbage', function () {
|
|
43
|
+
this.timeout(10000);
|
|
44
|
+
for (let ii = 0; ii < 1000; ii++) {
|
|
45
|
+
const gbg = ipldGarbage.garbage(1 << 6, { weights: { CID: 0 } });
|
|
46
|
+
verifyLength(gbg);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
it('medium garbage', function () {
|
|
50
|
+
this.timeout(10000);
|
|
51
|
+
for (let ii = 0; ii < 100; ii++) {
|
|
52
|
+
const gbg = ipldGarbage.garbage(1 << 16, { weights: { CID: 0 } });
|
|
53
|
+
verifyLength(gbg);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
it('large garbage', function () {
|
|
57
|
+
this.timeout(10000);
|
|
58
|
+
for (let ii = 0; ii < 10; ii++) {
|
|
59
|
+
const gbg = ipldGarbage.garbage(1 << 20, { weights: { CID: 0 } });
|
|
60
|
+
verifyLength(gbg);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Token,
|
|
3
|
+
Type
|
|
4
|
+
} from '../lib/token.js';
|
|
5
|
+
export function dateDecoder(obj) {
|
|
6
|
+
if (typeof obj !== 'string') {
|
|
7
|
+
throw new Error('expected string for tag 1');
|
|
8
|
+
}
|
|
9
|
+
return new Date(obj);
|
|
10
|
+
}
|
|
11
|
+
export function dateEncoder(obj) {
|
|
12
|
+
if (!(obj instanceof Date)) {
|
|
13
|
+
throw new Error('expected Date for "Date" encoder');
|
|
14
|
+
}
|
|
15
|
+
return [
|
|
16
|
+
new Token(Type.tag, 0),
|
|
17
|
+
new Token(Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
|
|
18
|
+
];
|
|
19
|
+
}
|
|
@@ -322,4 +322,19 @@ Input may either be supplied as an argument or piped via stdin
|
|
|
322
322
|
`);
|
|
323
323
|
});
|
|
324
324
|
});
|
|
325
|
+
it('diag non-utf8 and non-printable ascii', async () => {
|
|
326
|
+
const input = '7864f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c11e756338bd93865e645f1adec9b9c99ef407fbd4fc6859e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82f9f18c3d03418e35';
|
|
327
|
+
let {stdout, stderr} = await execBin(`hex2diag ${ input }`);
|
|
328
|
+
assert.strictEqual(stderr, '');
|
|
329
|
+
assert.strictEqual(stdout, `78 64 # string(86)
|
|
330
|
+
f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b # "õ_øñ%\\x08¶>ò¿ì§Uzé\\x0dö1\\x1a^Ác\\x1b"
|
|
331
|
+
4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c # "J\\x1f¨C1\\x0bÙç\\x10ê¬å¡½×*пàIw\\x1c"
|
|
332
|
+
11e756338bd93865e645f1adec9b9c99ef407fbd4fc685 # "\\x11çV3\\x8bÙ8eæEñ\\xadì\\x9b\\x9c\\x99ï@\\x7f½OÆ\\x85"
|
|
333
|
+
9e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82 # "\\x9ey\\x04Å\\xad}ɽ\\x10¥Ì\\x16\\x97=[(ì\\x1amÔ=\\x9f\\x82"
|
|
334
|
+
f9f18c3d03418e35 # "ùñ\\x8c=\\x03A\\x8e5"
|
|
335
|
+
`);
|
|
336
|
+
({stdout, stderr} = await execBin('diag2hex', stdout));
|
|
337
|
+
assert.strictEqual(stderr, '');
|
|
338
|
+
assert.strictEqual(stdout, `${ input }\n`);
|
|
339
|
+
});
|
|
325
340
|
});
|
|
@@ -11,22 +11,11 @@ import {
|
|
|
11
11
|
fromHex,
|
|
12
12
|
toHex
|
|
13
13
|
} from '../lib/byte-utils.js';
|
|
14
|
+
import {
|
|
15
|
+
dateDecoder,
|
|
16
|
+
dateEncoder
|
|
17
|
+
} from './common.js';
|
|
14
18
|
const {assert} = chai;
|
|
15
|
-
function dateDecoder(obj) {
|
|
16
|
-
if (typeof obj !== 'string') {
|
|
17
|
-
throw new Error('expected string for tag 1');
|
|
18
|
-
}
|
|
19
|
-
return new Date(obj);
|
|
20
|
-
}
|
|
21
|
-
function dateEncoder(obj) {
|
|
22
|
-
if (!(obj instanceof Date)) {
|
|
23
|
-
throw new Error('expected Date for "Date" encoder');
|
|
24
|
-
}
|
|
25
|
-
return [
|
|
26
|
-
new Token(Type.tag, 0),
|
|
27
|
-
new Token(Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
19
|
function Uint16ArrayDecoder(obj) {
|
|
31
20
|
if (typeof obj !== 'string') {
|
|
32
21
|
throw new Error('expected string for tag 23');
|