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
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import chai from 'chai';
|
|
2
|
+
import { garbage } from 'ipld-garbage';
|
|
3
|
+
import { uintBoundaries } from '../lib/0uint.js';
|
|
4
|
+
import { encode } from '../cborg.js';
|
|
5
|
+
import { encodedLength } from '../lib/length.js';
|
|
6
|
+
import { dateEncoder } from './common.js';
|
|
7
|
+
const {assert} = chai;
|
|
8
|
+
function verifyLength(object, options) {
|
|
9
|
+
const len = encodedLength(object, options);
|
|
10
|
+
const encoded = encode(object, options);
|
|
11
|
+
const actual = encoded.length;
|
|
12
|
+
assert.strictEqual(actual, len, JSON.stringify(object));
|
|
13
|
+
}
|
|
14
|
+
describe('encodedLength', () => {
|
|
15
|
+
it('int boundaries', () => {
|
|
16
|
+
for (let ii = 0; ii < 4; ii++) {
|
|
17
|
+
verifyLength(uintBoundaries[ii]);
|
|
18
|
+
verifyLength(uintBoundaries[ii] - 1);
|
|
19
|
+
verifyLength(uintBoundaries[ii] + 1);
|
|
20
|
+
verifyLength(-1 * uintBoundaries[ii]);
|
|
21
|
+
verifyLength(-1 * uintBoundaries[ii] - 1);
|
|
22
|
+
verifyLength(-1 * uintBoundaries[ii] + 1);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
it('tags', () => {
|
|
26
|
+
verifyLength({ date: new Date('2013-03-21T20:04:00Z') }, { typeEncoders: { Date: dateEncoder } });
|
|
27
|
+
});
|
|
28
|
+
it('floats', () => {
|
|
29
|
+
verifyLength(0.5);
|
|
30
|
+
verifyLength(0.5, { float64: true });
|
|
31
|
+
verifyLength(8.940696716308594e-8);
|
|
32
|
+
verifyLength(8.940696716308594e-8, { float64: true });
|
|
33
|
+
});
|
|
34
|
+
it('small garbage', function () {
|
|
35
|
+
this.timeout(10000);
|
|
36
|
+
for (let ii = 0; ii < 1000; ii++) {
|
|
37
|
+
const gbg = garbage(1 << 6, { weights: { CID: 0 } });
|
|
38
|
+
verifyLength(gbg);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
it('medium garbage', function () {
|
|
42
|
+
this.timeout(10000);
|
|
43
|
+
for (let ii = 0; ii < 100; ii++) {
|
|
44
|
+
const gbg = garbage(1 << 16, { weights: { CID: 0 } });
|
|
45
|
+
verifyLength(gbg);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
it('large garbage', function () {
|
|
49
|
+
this.timeout(10000);
|
|
50
|
+
for (let ii = 0; ii < 10; ii++) {
|
|
51
|
+
const gbg = garbage(1 << 20, { weights: { CID: 0 } });
|
|
52
|
+
verifyLength(gbg);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
package/esm/lib/3string.js
CHANGED
|
@@ -8,29 +8,36 @@ import {
|
|
|
8
8
|
} from './common.js';
|
|
9
9
|
import * as uint from './0uint.js';
|
|
10
10
|
import { encodeBytes } from './2bytes.js';
|
|
11
|
-
import {
|
|
12
|
-
|
|
11
|
+
import {
|
|
12
|
+
toString,
|
|
13
|
+
slice
|
|
14
|
+
} from './byte-utils.js';
|
|
15
|
+
function toToken(data, pos, prefix, length, options) {
|
|
13
16
|
const totLength = prefix + length;
|
|
14
17
|
assertEnoughData(data, pos, totLength);
|
|
15
|
-
|
|
18
|
+
const tok = new Token(Type.string, toString(data, pos + prefix, pos + totLength), totLength);
|
|
19
|
+
if (options.retainStringBytes === true) {
|
|
20
|
+
tok.byteValue = slice(data, pos + prefix, pos + totLength);
|
|
21
|
+
}
|
|
22
|
+
return tok;
|
|
16
23
|
}
|
|
17
|
-
export function decodeStringCompact(data, pos, minor,
|
|
18
|
-
return toToken(data, pos, 1, minor);
|
|
24
|
+
export function decodeStringCompact(data, pos, minor, options) {
|
|
25
|
+
return toToken(data, pos, 1, minor, options);
|
|
19
26
|
}
|
|
20
27
|
export function decodeString8(data, pos, _minor, options) {
|
|
21
|
-
return toToken(data, pos, 2, uint.readUint8(data, pos + 1, options));
|
|
28
|
+
return toToken(data, pos, 2, uint.readUint8(data, pos + 1, options), options);
|
|
22
29
|
}
|
|
23
30
|
export function decodeString16(data, pos, _minor, options) {
|
|
24
|
-
return toToken(data, pos, 3, uint.readUint16(data, pos + 1, options));
|
|
31
|
+
return toToken(data, pos, 3, uint.readUint16(data, pos + 1, options), options);
|
|
25
32
|
}
|
|
26
33
|
export function decodeString32(data, pos, _minor, options) {
|
|
27
|
-
return toToken(data, pos, 5, uint.readUint32(data, pos + 1, options));
|
|
34
|
+
return toToken(data, pos, 5, uint.readUint32(data, pos + 1, options), options);
|
|
28
35
|
}
|
|
29
36
|
export function decodeString64(data, pos, _minor, options) {
|
|
30
37
|
const l = uint.readUint64(data, pos + 1, options);
|
|
31
38
|
if (typeof l === 'bigint') {
|
|
32
39
|
throw new Error(`${ decodeErrPrefix } 64-bit integer string lengths not supported`);
|
|
33
40
|
}
|
|
34
|
-
return toToken(data, pos, 9, l);
|
|
41
|
+
return toToken(data, pos, 9, l, options);
|
|
35
42
|
}
|
|
36
43
|
export const encodeString = encodeBytes;
|
package/esm/lib/4array.js
CHANGED
|
@@ -35,4 +35,7 @@ export function decodeArrayIndefinite(data, pos, _minor, options) {
|
|
|
35
35
|
export function encodeArray(buf, token) {
|
|
36
36
|
uint.encodeUintValue(buf, Type.array.majorEncoded, token.value);
|
|
37
37
|
}
|
|
38
|
-
encodeArray.compareTokens = uint.encodeUint.compareTokens;
|
|
38
|
+
encodeArray.compareTokens = uint.encodeUint.compareTokens;
|
|
39
|
+
encodeArray.encodedSize = function encodedSize(token) {
|
|
40
|
+
return uint.encodeUintValue.encodedSize(token.value);
|
|
41
|
+
};
|
package/esm/lib/5map.js
CHANGED
|
@@ -35,4 +35,7 @@ export function decodeMapIndefinite(data, pos, _minor, options) {
|
|
|
35
35
|
export function encodeMap(buf, token) {
|
|
36
36
|
uint.encodeUintValue(buf, Type.map.majorEncoded, token.value);
|
|
37
37
|
}
|
|
38
|
-
encodeMap.compareTokens = uint.encodeUint.compareTokens;
|
|
38
|
+
encodeMap.compareTokens = uint.encodeUint.compareTokens;
|
|
39
|
+
encodeMap.encodedSize = function encodedSize(token) {
|
|
40
|
+
return uint.encodeUintValue.encodedSize(token.value);
|
|
41
|
+
};
|
package/esm/lib/6tag.js
CHANGED
|
@@ -21,4 +21,7 @@ export function decodeTag64(data, pos, _minor, options) {
|
|
|
21
21
|
export function encodeTag(buf, token) {
|
|
22
22
|
uint.encodeUintValue(buf, Type.tag.majorEncoded, token.value);
|
|
23
23
|
}
|
|
24
|
-
encodeTag.compareTokens = uint.encodeUint.compareTokens;
|
|
24
|
+
encodeTag.compareTokens = uint.encodeUint.compareTokens;
|
|
25
|
+
encodeTag.encodedSize = function encodedSize(token) {
|
|
26
|
+
return uint.encodeUintValue.encodedSize(token.value);
|
|
27
|
+
};
|
package/esm/lib/7float.js
CHANGED
|
@@ -85,10 +85,9 @@ encodeFloat.encodedSize = function encodedSize(token, options) {
|
|
|
85
85
|
if (float === false || float === true || float === null || float === undefined) {
|
|
86
86
|
return 1;
|
|
87
87
|
}
|
|
88
|
-
let decoded;
|
|
89
88
|
if (!options || options.float64 !== true) {
|
|
90
89
|
encodeFloat16(float);
|
|
91
|
-
decoded = readFloat16(ui8a, 1);
|
|
90
|
+
let decoded = readFloat16(ui8a, 1);
|
|
92
91
|
if (float === decoded || Number.isNaN(float)) {
|
|
93
92
|
return 3;
|
|
94
93
|
}
|
package/esm/lib/bl.js
CHANGED
|
@@ -13,9 +13,11 @@ export class Bl {
|
|
|
13
13
|
this._initReuseChunk = null;
|
|
14
14
|
}
|
|
15
15
|
reset() {
|
|
16
|
-
this.chunks = [];
|
|
17
16
|
this.cursor = 0;
|
|
18
17
|
this.maxCursor = -1;
|
|
18
|
+
if (this.chunks.length) {
|
|
19
|
+
this.chunks = [];
|
|
20
|
+
}
|
|
19
21
|
if (this._initReuseChunk !== null) {
|
|
20
22
|
this.chunks.push(this._initReuseChunk);
|
|
21
23
|
this.maxCursor = this._initReuseChunk.length - 1;
|
package/esm/lib/diagnostic.js
CHANGED
|
@@ -7,7 +7,7 @@ import { uintBoundaries } from './0uint.js';
|
|
|
7
7
|
const utf8Encoder = new TextEncoder();
|
|
8
8
|
const utf8Decoder = new TextDecoder();
|
|
9
9
|
function* tokensToDiagnostic(inp, width = 100) {
|
|
10
|
-
const tokeniser = new Tokeniser(inp);
|
|
10
|
+
const tokeniser = new Tokeniser(inp, { retainStringBytes: true });
|
|
11
11
|
let pos = 0;
|
|
12
12
|
const indent = [];
|
|
13
13
|
const slc = (start, length) => {
|
|
@@ -57,15 +57,22 @@ function* tokensToDiagnostic(inp, width = 100) {
|
|
|
57
57
|
}
|
|
58
58
|
yield outp;
|
|
59
59
|
if (str) {
|
|
60
|
+
let asString = token.type.name === 'string';
|
|
60
61
|
margin += ' ';
|
|
61
|
-
|
|
62
|
+
let repr = asString ? utf8Encoder.encode(token.value) : token.value;
|
|
63
|
+
if (asString && token.byteValue !== undefined) {
|
|
64
|
+
if (repr.length !== token.byteValue.length) {
|
|
65
|
+
repr = token.byteValue;
|
|
66
|
+
asString = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
62
69
|
const wh = (width / 2 - margin.length - 1) / 2;
|
|
63
70
|
let snip = 0;
|
|
64
71
|
while (repr.length - snip > 0) {
|
|
65
72
|
const piece = repr.slice(snip, snip + wh);
|
|
66
73
|
snip += piece.length;
|
|
67
|
-
const st =
|
|
68
|
-
if (c < 32 || c ===
|
|
74
|
+
const st = asString ? utf8Decoder.decode(piece) : piece.reduce((p, c) => {
|
|
75
|
+
if (c < 32 || c >= 127 && c < 161 || c === 173) {
|
|
69
76
|
return `${ p }\\x${ c.toString(16).padStart(2, '0') }`;
|
|
70
77
|
}
|
|
71
78
|
return `${ p }${ String.fromCharCode(c) }`;
|
package/esm/lib/encode.js
CHANGED
|
@@ -20,15 +20,19 @@ const defaultEncodeOptions = {
|
|
|
20
20
|
mapSorter,
|
|
21
21
|
quickEncodeToken
|
|
22
22
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
export function makeCborEncoders() {
|
|
24
|
+
const encoders = [];
|
|
25
|
+
encoders[Type.uint.major] = encodeUint;
|
|
26
|
+
encoders[Type.negint.major] = encodeNegint;
|
|
27
|
+
encoders[Type.bytes.major] = encodeBytes;
|
|
28
|
+
encoders[Type.string.major] = encodeString;
|
|
29
|
+
encoders[Type.array.major] = encodeArray;
|
|
30
|
+
encoders[Type.map.major] = encodeMap;
|
|
31
|
+
encoders[Type.tag.major] = encodeTag;
|
|
32
|
+
encoders[Type.float.major] = encodeFloat;
|
|
33
|
+
return encoders;
|
|
34
|
+
}
|
|
35
|
+
const cborEncoders = makeCborEncoders();
|
|
32
36
|
const buf = new Bl();
|
|
33
37
|
class Ref {
|
|
34
38
|
constructor(obj, parent) {
|
|
@@ -226,6 +230,7 @@ function encodeCustom(data, encoders, options) {
|
|
|
226
230
|
return asU8A(buf.chunks[0]);
|
|
227
231
|
}
|
|
228
232
|
}
|
|
233
|
+
buf.reset();
|
|
229
234
|
tokensToEncoded(buf, tokens, encoders, options);
|
|
230
235
|
return buf.toBytes(true);
|
|
231
236
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
makeCborEncoders,
|
|
3
|
+
objectToTokens
|
|
4
|
+
} from './encode.js';
|
|
5
|
+
import { quickEncodeToken } from './jump.js';
|
|
6
|
+
const cborEncoders = makeCborEncoders();
|
|
7
|
+
const defaultEncodeOptions = {
|
|
8
|
+
float64: false,
|
|
9
|
+
quickEncodeToken
|
|
10
|
+
};
|
|
11
|
+
export function encodedLength(data, options) {
|
|
12
|
+
options = Object.assign({}, defaultEncodeOptions, options);
|
|
13
|
+
options.mapSorter = undefined;
|
|
14
|
+
const tokens = objectToTokens(data, options);
|
|
15
|
+
return tokensToLength(tokens, cborEncoders, options);
|
|
16
|
+
}
|
|
17
|
+
export function tokensToLength(tokens, encoders = cborEncoders, options = defaultEncodeOptions) {
|
|
18
|
+
if (Array.isArray(tokens)) {
|
|
19
|
+
let len = 0;
|
|
20
|
+
for (const token of tokens) {
|
|
21
|
+
len += tokensToLength(token, encoders, options);
|
|
22
|
+
}
|
|
23
|
+
return len;
|
|
24
|
+
} else {
|
|
25
|
+
const encoder = encoders[tokens.type.major];
|
|
26
|
+
if (encoder.encodedSize === undefined || typeof encoder.encodedSize !== 'function') {
|
|
27
|
+
throw new Error(`Encoder for ${ tokens.type.name } does not have an encodedSize()`);
|
|
28
|
+
}
|
|
29
|
+
return encoder.encodedSize(tokens, options);
|
|
30
|
+
}
|
|
31
|
+
}
|
package/esm/lib/token.js
CHANGED
|
@@ -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');
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import chai from 'chai';
|
|
2
|
+
import { garbage } from 'ipld-garbage';
|
|
3
|
+
import { uintBoundaries } from '../lib/0uint.js';
|
|
4
|
+
import { encode } from '../cborg.js';
|
|
5
|
+
import { encodedLength } from '../lib/length.js';
|
|
6
|
+
import { dateEncoder } from './common.js';
|
|
7
|
+
const {assert} = chai;
|
|
8
|
+
function verifyLength(object, options) {
|
|
9
|
+
const len = encodedLength(object, options);
|
|
10
|
+
const encoded = encode(object, options);
|
|
11
|
+
const actual = encoded.length;
|
|
12
|
+
assert.strictEqual(actual, len, JSON.stringify(object));
|
|
13
|
+
}
|
|
14
|
+
describe('encodedLength', () => {
|
|
15
|
+
it('int boundaries', () => {
|
|
16
|
+
for (let ii = 0; ii < 4; ii++) {
|
|
17
|
+
verifyLength(uintBoundaries[ii]);
|
|
18
|
+
verifyLength(uintBoundaries[ii] - 1);
|
|
19
|
+
verifyLength(uintBoundaries[ii] + 1);
|
|
20
|
+
verifyLength(-1 * uintBoundaries[ii]);
|
|
21
|
+
verifyLength(-1 * uintBoundaries[ii] - 1);
|
|
22
|
+
verifyLength(-1 * uintBoundaries[ii] + 1);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
it('tags', () => {
|
|
26
|
+
verifyLength({ date: new Date('2013-03-21T20:04:00Z') }, { typeEncoders: { Date: dateEncoder } });
|
|
27
|
+
});
|
|
28
|
+
it('floats', () => {
|
|
29
|
+
verifyLength(0.5);
|
|
30
|
+
verifyLength(0.5, { float64: true });
|
|
31
|
+
verifyLength(8.940696716308594e-8);
|
|
32
|
+
verifyLength(8.940696716308594e-8, { float64: true });
|
|
33
|
+
});
|
|
34
|
+
it('small garbage', function () {
|
|
35
|
+
this.timeout(10000);
|
|
36
|
+
for (let ii = 0; ii < 1000; ii++) {
|
|
37
|
+
const gbg = garbage(1 << 6, { weights: { CID: 0 } });
|
|
38
|
+
verifyLength(gbg);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
it('medium garbage', function () {
|
|
42
|
+
this.timeout(10000);
|
|
43
|
+
for (let ii = 0; ii < 100; ii++) {
|
|
44
|
+
const gbg = garbage(1 << 16, { weights: { CID: 0 } });
|
|
45
|
+
verifyLength(gbg);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
it('large garbage', function () {
|
|
49
|
+
this.timeout(10000);
|
|
50
|
+
for (let ii = 0; ii < 10; ii++) {
|
|
51
|
+
const gbg = garbage(1 << 20, { weights: { CID: 0 } });
|
|
52
|
+
verifyLength(gbg);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
package/interface.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type StrictTypeEncoder = (data: any, typ: string, options: EncodeOptions,
|
|
|
16
16
|
export type TokenTypeEncoder = {
|
|
17
17
|
(buf: Bl, token: Token, options?: EncodeOptions): void;
|
|
18
18
|
compareTokens(t1: Token, t2: Token): number;
|
|
19
|
+
// TODO: make this non-optional as a breaking change and remove the throw in length.js
|
|
19
20
|
encodedSize?(token: Token, options?: EncodeOptions): number;
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -39,6 +40,7 @@ export interface DecodeOptions {
|
|
|
39
40
|
allowBigInt?: boolean
|
|
40
41
|
strict?: boolean
|
|
41
42
|
useMaps?: boolean
|
|
43
|
+
retainStringBytes?: boolean
|
|
42
44
|
tags?: TagDecoder[],
|
|
43
45
|
tokenizer?: DecodeTokenizer
|
|
44
46
|
}
|
package/length
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./cjs/lib/length.js')
|
package/lib/3string.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Token, Type } from './token.js'
|
|
|
2
2
|
import { assertEnoughData, decodeErrPrefix } from './common.js'
|
|
3
3
|
import * as uint from './0uint.js'
|
|
4
4
|
import { encodeBytes } from './2bytes.js'
|
|
5
|
-
import { toString } from './byte-utils.js'
|
|
5
|
+
import { toString, slice } from './byte-utils.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @typedef {import('./bl.js').Bl} Bl
|
|
@@ -14,23 +14,28 @@ import { toString } from './byte-utils.js'
|
|
|
14
14
|
* @param {number} pos
|
|
15
15
|
* @param {number} prefix
|
|
16
16
|
* @param {number} length
|
|
17
|
+
* @param {DecodeOptions} options
|
|
17
18
|
* @returns {Token}
|
|
18
19
|
*/
|
|
19
|
-
function toToken (data, pos, prefix, length) {
|
|
20
|
+
function toToken (data, pos, prefix, length, options) {
|
|
20
21
|
const totLength = prefix + length
|
|
21
22
|
assertEnoughData(data, pos, totLength)
|
|
22
|
-
|
|
23
|
+
const tok = new Token(Type.string, toString(data, pos + prefix, pos + totLength), totLength)
|
|
24
|
+
if (options.retainStringBytes === true) {
|
|
25
|
+
tok.byteValue = slice(data, pos + prefix, pos + totLength)
|
|
26
|
+
}
|
|
27
|
+
return tok
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
31
|
* @param {Uint8Array} data
|
|
27
32
|
* @param {number} pos
|
|
28
33
|
* @param {number} minor
|
|
29
|
-
* @param {DecodeOptions}
|
|
34
|
+
* @param {DecodeOptions} options
|
|
30
35
|
* @returns {Token}
|
|
31
36
|
*/
|
|
32
|
-
export function decodeStringCompact (data, pos, minor,
|
|
33
|
-
return toToken(data, pos, 1, minor)
|
|
37
|
+
export function decodeStringCompact (data, pos, minor, options) {
|
|
38
|
+
return toToken(data, pos, 1, minor, options)
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
/**
|
|
@@ -41,7 +46,7 @@ export function decodeStringCompact (data, pos, minor, _options) {
|
|
|
41
46
|
* @returns {Token}
|
|
42
47
|
*/
|
|
43
48
|
export function decodeString8 (data, pos, _minor, options) {
|
|
44
|
-
return toToken(data, pos, 2, uint.readUint8(data, pos + 1, options))
|
|
49
|
+
return toToken(data, pos, 2, uint.readUint8(data, pos + 1, options), options)
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
/**
|
|
@@ -52,7 +57,7 @@ export function decodeString8 (data, pos, _minor, options) {
|
|
|
52
57
|
* @returns {Token}
|
|
53
58
|
*/
|
|
54
59
|
export function decodeString16 (data, pos, _minor, options) {
|
|
55
|
-
return toToken(data, pos, 3, uint.readUint16(data, pos + 1, options))
|
|
60
|
+
return toToken(data, pos, 3, uint.readUint16(data, pos + 1, options), options)
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
/**
|
|
@@ -63,7 +68,7 @@ export function decodeString16 (data, pos, _minor, options) {
|
|
|
63
68
|
* @returns {Token}
|
|
64
69
|
*/
|
|
65
70
|
export function decodeString32 (data, pos, _minor, options) {
|
|
66
|
-
return toToken(data, pos, 5, uint.readUint32(data, pos + 1, options))
|
|
71
|
+
return toToken(data, pos, 5, uint.readUint32(data, pos + 1, options), options)
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
// TODO: maybe we shouldn't support this ..
|
|
@@ -79,7 +84,7 @@ export function decodeString64 (data, pos, _minor, options) {
|
|
|
79
84
|
if (typeof l === 'bigint') {
|
|
80
85
|
throw new Error(`${decodeErrPrefix} 64-bit integer string lengths not supported`)
|
|
81
86
|
}
|
|
82
|
-
return toToken(data, pos, 9, l)
|
|
87
|
+
return toToken(data, pos, 9, l, options)
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
export const encodeString = encodeBytes
|
package/lib/4array.js
CHANGED
|
@@ -103,3 +103,11 @@ export function encodeArray (buf, token) {
|
|
|
103
103
|
// using an array as a map key, are you sure about this? we can only sort
|
|
104
104
|
// by map length here, it's up to the encoder to decide to look deeper
|
|
105
105
|
encodeArray.compareTokens = uint.encodeUint.compareTokens
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {Token} token
|
|
109
|
+
* @returns {number}
|
|
110
|
+
*/
|
|
111
|
+
encodeArray.encodedSize = function encodedSize (token) {
|
|
112
|
+
return uint.encodeUintValue.encodedSize(token.value)
|
|
113
|
+
}
|
package/lib/5map.js
CHANGED
|
@@ -103,3 +103,11 @@ export function encodeMap (buf, token) {
|
|
|
103
103
|
// using a map as a map key, are you sure about this? we can only sort
|
|
104
104
|
// by map length here, it's up to the encoder to decide to look deeper
|
|
105
105
|
encodeMap.compareTokens = uint.encodeUint.compareTokens
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {Token} token
|
|
109
|
+
* @returns {number}
|
|
110
|
+
*/
|
|
111
|
+
encodeMap.encodedSize = function encodedSize (token) {
|
|
112
|
+
return uint.encodeUintValue.encodedSize(token.value)
|
|
113
|
+
}
|
package/lib/6tag.js
CHANGED
|
@@ -70,3 +70,11 @@ export function encodeTag (buf, token) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
encodeTag.compareTokens = uint.encodeUint.compareTokens
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {Token} token
|
|
76
|
+
* @returns {number}
|
|
77
|
+
*/
|
|
78
|
+
encodeTag.encodedSize = function encodedSize (token) {
|
|
79
|
+
return uint.encodeUintValue.encodedSize(token.value)
|
|
80
|
+
}
|
package/lib/7float.js
CHANGED
|
@@ -154,10 +154,9 @@ encodeFloat.encodedSize = function encodedSize (token, options) {
|
|
|
154
154
|
return 1
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
let decoded
|
|
158
157
|
if (!options || options.float64 !== true) {
|
|
159
158
|
encodeFloat16(float)
|
|
160
|
-
decoded = readFloat16(ui8a, 1)
|
|
159
|
+
let decoded = readFloat16(ui8a, 1)
|
|
161
160
|
if (float === decoded || Number.isNaN(float)) {
|
|
162
161
|
return 3
|
|
163
162
|
}
|
package/lib/bl.js
CHANGED
|
@@ -42,9 +42,11 @@ export class Bl {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
reset () {
|
|
45
|
-
this.chunks = []
|
|
46
45
|
this.cursor = 0
|
|
47
46
|
this.maxCursor = -1
|
|
47
|
+
if (this.chunks.length) {
|
|
48
|
+
this.chunks = []
|
|
49
|
+
}
|
|
48
50
|
if (this._initReuseChunk !== null) {
|
|
49
51
|
this.chunks.push(this._initReuseChunk)
|
|
50
52
|
this.maxCursor = this._initReuseChunk.length - 1
|
package/lib/diagnostic.js
CHANGED
|
@@ -10,7 +10,7 @@ const utf8Decoder = new TextDecoder()
|
|
|
10
10
|
* @param {number} [width]
|
|
11
11
|
*/
|
|
12
12
|
function * tokensToDiagnostic (inp, width = 100) {
|
|
13
|
-
const tokeniser = new Tokeniser(inp)
|
|
13
|
+
const tokeniser = new Tokeniser(inp, { retainStringBytes: true })
|
|
14
14
|
let pos = 0
|
|
15
15
|
const indent = []
|
|
16
16
|
|
|
@@ -77,19 +77,26 @@ function * tokensToDiagnostic (inp, width = 100) {
|
|
|
77
77
|
yield outp
|
|
78
78
|
|
|
79
79
|
if (str) {
|
|
80
|
+
let asString = token.type.name === 'string'
|
|
80
81
|
margin += ' '
|
|
81
|
-
|
|
82
|
+
let repr = asString ? utf8Encoder.encode(token.value) : token.value
|
|
83
|
+
if (asString && token.byteValue !== undefined) {
|
|
84
|
+
if (repr.length !== token.byteValue.length) {
|
|
85
|
+
// bail on printing this as a string, it's probably not utf8, so treat it as bytes
|
|
86
|
+
// (you can probably blame a Go programmer for this)
|
|
87
|
+
repr = token.byteValue
|
|
88
|
+
asString = false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
82
91
|
const wh = ((width / 2) - margin.length - 1) / 2
|
|
83
92
|
let snip = 0
|
|
84
93
|
while (repr.length - snip > 0) {
|
|
85
94
|
const piece = repr.slice(snip, snip + wh)
|
|
86
95
|
snip += piece.length
|
|
87
|
-
|
|
88
|
-
// we could be slicing in the middle of a multi-byte character
|
|
89
|
-
const st = token.type.name === 'string'
|
|
96
|
+
const st = asString
|
|
90
97
|
? utf8Decoder.decode(piece)
|
|
91
98
|
: piece.reduce((/** @type {string} */ p, /** @type {number} */ c) => {
|
|
92
|
-
if (c < 0x20 || c
|
|
99
|
+
if (c < 0x20 || (c >= 0x7f && c < 0xa1) || c === 0xad) {
|
|
93
100
|
return `${p}\\x${c.toString(16).padStart(2, '0')}`
|
|
94
101
|
}
|
|
95
102
|
return `${p}${String.fromCharCode(c)}`
|
package/lib/encode.js
CHANGED
|
@@ -30,16 +30,21 @@ const defaultEncodeOptions = {
|
|
|
30
30
|
quickEncodeToken
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
/** @
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
/** @returns {TokenTypeEncoder[]} */
|
|
34
|
+
export function makeCborEncoders () {
|
|
35
|
+
const encoders = []
|
|
36
|
+
encoders[Type.uint.major] = encodeUint
|
|
37
|
+
encoders[Type.negint.major] = encodeNegint
|
|
38
|
+
encoders[Type.bytes.major] = encodeBytes
|
|
39
|
+
encoders[Type.string.major] = encodeString
|
|
40
|
+
encoders[Type.array.major] = encodeArray
|
|
41
|
+
encoders[Type.map.major] = encodeMap
|
|
42
|
+
encoders[Type.tag.major] = encodeTag
|
|
43
|
+
encoders[Type.float.major] = encodeFloat
|
|
44
|
+
return encoders
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const cborEncoders = makeCborEncoders()
|
|
43
48
|
|
|
44
49
|
const buf = new Bl()
|
|
45
50
|
|
|
@@ -441,6 +446,7 @@ function encodeCustom (data, encoders, options) {
|
|
|
441
446
|
return asU8A(buf.chunks[0])
|
|
442
447
|
}
|
|
443
448
|
}
|
|
449
|
+
buf.reset()
|
|
444
450
|
tokensToEncoded(buf, tokens, encoders, options)
|
|
445
451
|
return buf.toBytes(true)
|
|
446
452
|
}
|