@atcute/cbor 2.0.1 → 2.1.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/dist/decode.js +90 -77
- package/dist/decode.js.map +1 -1
- package/dist/encode.js +170 -141
- package/dist/encode.js.map +1 -1
- package/lib/decode.ts +96 -90
- package/lib/encode.ts +188 -161
- package/package.json +6 -5
package/dist/decode.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { CidLinkWrapper } from '@atcute/cid';
|
|
2
|
+
import { decodeUtf8From } from '@atcute/uint8array';
|
|
2
3
|
import { toBytes } from './bytes.js';
|
|
3
|
-
const utf8d = new TextDecoder();
|
|
4
4
|
const readArgument = (state, info) => {
|
|
5
5
|
if (info < 24) {
|
|
6
6
|
return info;
|
|
7
7
|
}
|
|
8
8
|
switch (info) {
|
|
9
|
-
case 24:
|
|
9
|
+
case 24: {
|
|
10
10
|
return readUint8(state);
|
|
11
|
-
|
|
11
|
+
}
|
|
12
|
+
case 25: {
|
|
12
13
|
return readUint16(state);
|
|
13
|
-
|
|
14
|
+
}
|
|
15
|
+
case 26: {
|
|
14
16
|
return readUint32(state);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
}
|
|
18
|
+
case 27: {
|
|
19
|
+
return readUint53(state);
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
throw new Error(`invalid argument encoding; got ${info}`);
|
|
19
23
|
};
|
|
@@ -23,39 +27,47 @@ const readFloat64 = (state) => {
|
|
|
23
27
|
return value;
|
|
24
28
|
};
|
|
25
29
|
const readUint8 = (state) => {
|
|
26
|
-
|
|
27
|
-
state.p += 1;
|
|
28
|
-
return value;
|
|
30
|
+
return state.b[state.p++];
|
|
29
31
|
};
|
|
30
32
|
const readUint16 = (state) => {
|
|
31
|
-
|
|
32
|
-
state.
|
|
33
|
+
let pos = state.p;
|
|
34
|
+
const buf = state.b;
|
|
35
|
+
const value = (buf[pos++] << 8) | buf[pos++];
|
|
36
|
+
state.p = pos;
|
|
33
37
|
return value;
|
|
34
38
|
};
|
|
35
39
|
const readUint32 = (state) => {
|
|
36
|
-
|
|
37
|
-
state.
|
|
40
|
+
let pos = state.p;
|
|
41
|
+
const buf = state.b;
|
|
42
|
+
const value = ((buf[pos++] << 24) | (buf[pos++] << 16) | (buf[pos++] << 8) | buf[pos++]) >>> 0;
|
|
43
|
+
state.p = pos;
|
|
38
44
|
return value;
|
|
39
45
|
};
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const
|
|
46
|
+
const readUint53 = (state) => {
|
|
47
|
+
let pos = state.p;
|
|
48
|
+
const buf = state.b;
|
|
49
|
+
const hi = ((buf[pos++] << 24) | (buf[pos++] << 16) | (buf[pos++] << 8) | buf[pos++]) >>> 0;
|
|
43
50
|
if (hi > 0x1fffff) {
|
|
44
51
|
throw new RangeError(`can't decode integers beyond safe integer range`);
|
|
45
52
|
}
|
|
46
|
-
|
|
47
|
-
const value =
|
|
48
|
-
state.p
|
|
53
|
+
const lo = ((buf[pos++] << 24) | (buf[pos++] << 16) | (buf[pos++] << 8) | buf[pos++]) >>> 0;
|
|
54
|
+
const value = hi * 2 ** 32 + lo;
|
|
55
|
+
state.p = pos;
|
|
49
56
|
return value;
|
|
50
57
|
};
|
|
51
58
|
const readString = (state, length) => {
|
|
52
|
-
const
|
|
53
|
-
|
|
59
|
+
const string = decodeUtf8From(state.b, state.p, length);
|
|
60
|
+
state.p += length;
|
|
61
|
+
return string;
|
|
54
62
|
};
|
|
55
63
|
const readBytes = (state, length) => {
|
|
56
64
|
const slice = state.b.subarray(state.p, (state.p += length));
|
|
57
65
|
return toBytes(slice);
|
|
58
66
|
};
|
|
67
|
+
const readTypeInfo = (state) => {
|
|
68
|
+
const prelude = readUint8(state);
|
|
69
|
+
return [prelude >> 5, prelude & 0x1f];
|
|
70
|
+
};
|
|
59
71
|
const readCid = (state, length) => {
|
|
60
72
|
// CID bytes are prefixed with 0x00 for historical reasons, apparently.
|
|
61
73
|
const slice = state.b.subarray(state.p + 1, (state.p += length));
|
|
@@ -65,68 +77,69 @@ const readValue = (state) => {
|
|
|
65
77
|
const prelude = readUint8(state);
|
|
66
78
|
const type = prelude >> 5;
|
|
67
79
|
const info = prelude & 0x1f;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (type === 1) {
|
|
73
|
-
const value = readArgument(state, info);
|
|
74
|
-
return -1 - value;
|
|
75
|
-
}
|
|
76
|
-
if (type === 2) {
|
|
77
|
-
const len = readArgument(state, info);
|
|
78
|
-
return readBytes(state, len);
|
|
79
|
-
}
|
|
80
|
-
if (type === 3) {
|
|
81
|
-
const len = readArgument(state, info);
|
|
82
|
-
return readString(state, len);
|
|
83
|
-
}
|
|
84
|
-
if (type === 4) {
|
|
85
|
-
const len = readArgument(state, info);
|
|
86
|
-
const array = new Array(len);
|
|
87
|
-
for (let idx = 0; idx < len; idx++) {
|
|
88
|
-
array[idx] = readValue(state);
|
|
80
|
+
const arg = type < 7 ? readArgument(state, info) : 0;
|
|
81
|
+
switch (type) {
|
|
82
|
+
case 0: {
|
|
83
|
+
return arg;
|
|
89
84
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
case 1: {
|
|
86
|
+
return -1 - arg;
|
|
87
|
+
}
|
|
88
|
+
case 2: {
|
|
89
|
+
return readBytes(state, arg);
|
|
90
|
+
}
|
|
91
|
+
case 3: {
|
|
92
|
+
return readString(state, arg);
|
|
93
|
+
}
|
|
94
|
+
case 4: {
|
|
95
|
+
const array = new Array(arg);
|
|
96
|
+
for (let idx = 0; idx < arg; idx++) {
|
|
97
|
+
array[idx] = readValue(state);
|
|
99
98
|
}
|
|
100
|
-
|
|
99
|
+
return array;
|
|
101
100
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
case 5: {
|
|
102
|
+
const object = {};
|
|
103
|
+
for (let idx = 0; idx < arg; idx++) {
|
|
104
|
+
const [type, info] = readTypeInfo(state);
|
|
105
|
+
if (type !== 3) {
|
|
106
|
+
throw new TypeError(`expected map to only have string keys; got type ${type}`);
|
|
107
|
+
}
|
|
108
|
+
const len = readArgument(state, info);
|
|
109
|
+
const key = readString(state, len);
|
|
110
|
+
if (key === '__proto__')
|
|
111
|
+
// Guard against prototype pollution. CWE-1321
|
|
112
|
+
Object.defineProperty(object, key, { enumerable: true, configurable: true, writable: true });
|
|
113
|
+
object[key] = readValue(state);
|
|
112
114
|
}
|
|
113
|
-
|
|
114
|
-
return readCid(state, len);
|
|
115
|
+
return object;
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
case 6: {
|
|
118
|
+
if (arg === 42) {
|
|
119
|
+
const [type, info] = readTypeInfo(state);
|
|
120
|
+
if (type !== 2) {
|
|
121
|
+
throw new TypeError(`expected cid-link to be type 2 (bytes); got type ${type}`);
|
|
122
|
+
}
|
|
123
|
+
const len = readArgument(state, info);
|
|
124
|
+
return readCid(state, len);
|
|
125
|
+
}
|
|
126
|
+
throw new TypeError(`unsupported tag; got ${arg}`);
|
|
127
|
+
}
|
|
128
|
+
case 7: {
|
|
129
|
+
switch (info) {
|
|
130
|
+
case 20:
|
|
131
|
+
case 21: {
|
|
132
|
+
return info === 21;
|
|
133
|
+
}
|
|
134
|
+
case 22: {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
case 27: {
|
|
138
|
+
return readFloat64(state);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
throw new Error(`invalid simple value; got ${info}`);
|
|
128
142
|
}
|
|
129
|
-
throw new Error(`invalid simple value; got ${info}`);
|
|
130
143
|
}
|
|
131
144
|
throw new TypeError(`invalid type; got ${type}`);
|
|
132
145
|
};
|
package/dist/decode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../lib/decode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../lib/decode.ts"],"names":[],"mappings":"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"}
|
package/dist/encode.js
CHANGED
|
@@ -1,77 +1,88 @@
|
|
|
1
1
|
import { CidLinkWrapper, fromString } from '@atcute/cid';
|
|
2
|
+
import { allocUnsafe, concat, encodeUtf8Into } from '@atcute/uint8array';
|
|
2
3
|
import { BytesWrapper, fromBytes } from './bytes.js';
|
|
4
|
+
const MAX_TYPE_ARG_LEN = 9;
|
|
3
5
|
const CHUNK_SIZE = 1024;
|
|
4
|
-
const
|
|
6
|
+
const _max = Math.max;
|
|
7
|
+
const _isInteger = Number.isInteger;
|
|
8
|
+
const _isNaN = Number.isNaN;
|
|
9
|
+
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
|
10
|
+
const MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER;
|
|
5
11
|
const resizeIfNeeded = (state, needed) => {
|
|
6
12
|
const buf = state.b;
|
|
7
13
|
const pos = state.p;
|
|
8
14
|
if (buf.byteLength < pos + needed) {
|
|
9
|
-
state.c.push(
|
|
10
|
-
state.
|
|
11
|
-
state.v = new DataView(state.b);
|
|
15
|
+
state.c.push(buf.subarray(0, pos));
|
|
16
|
+
state.l += pos;
|
|
17
|
+
state.v = new DataView((state.b = allocUnsafe(_max(CHUNK_SIZE, needed))).buffer);
|
|
12
18
|
state.p = 0;
|
|
13
19
|
}
|
|
14
20
|
};
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
return arg;
|
|
18
|
-
}
|
|
19
|
-
else if (arg < 0x100) {
|
|
20
|
-
return 24;
|
|
21
|
-
}
|
|
22
|
-
else if (arg < 0x10000) {
|
|
23
|
-
return 25;
|
|
24
|
-
}
|
|
25
|
-
else if (arg < 0x100000000) {
|
|
26
|
-
return 26;
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
return 27;
|
|
30
|
-
}
|
|
21
|
+
const getTypeInfoLength = (arg) => {
|
|
22
|
+
return arg < 24 ? 1 : arg < 0x100 ? 2 : arg < 0x10000 ? 3 : arg < 0x100000000 ? 5 : 9;
|
|
31
23
|
};
|
|
32
24
|
const writeFloat64 = (state, val) => {
|
|
33
|
-
resizeIfNeeded(state, 8);
|
|
34
25
|
state.v.setFloat64(state.p, val);
|
|
35
26
|
state.p += 8;
|
|
36
27
|
};
|
|
37
28
|
const writeUint8 = (state, val) => {
|
|
38
|
-
|
|
39
|
-
state.v.setUint8(state.p, val);
|
|
40
|
-
state.p += 1;
|
|
29
|
+
state.b[state.p++] = val;
|
|
41
30
|
};
|
|
42
31
|
const writeUint16 = (state, val) => {
|
|
43
|
-
|
|
44
|
-
state.
|
|
45
|
-
|
|
32
|
+
let pos = state.p;
|
|
33
|
+
const buf = state.b;
|
|
34
|
+
buf[pos++] = val >>> 8;
|
|
35
|
+
buf[pos++] = val & 0xff;
|
|
36
|
+
state.p = pos;
|
|
46
37
|
};
|
|
47
38
|
const writeUint32 = (state, val) => {
|
|
48
|
-
|
|
49
|
-
state.
|
|
50
|
-
|
|
39
|
+
let pos = state.p;
|
|
40
|
+
const buf = state.b;
|
|
41
|
+
buf[pos++] = val >>> 24;
|
|
42
|
+
buf[pos++] = (val >>> 16) & 0xff;
|
|
43
|
+
buf[pos++] = (val >>> 8) & 0xff;
|
|
44
|
+
buf[pos++] = val & 0xff;
|
|
45
|
+
state.p = pos;
|
|
51
46
|
};
|
|
52
|
-
const
|
|
47
|
+
const writeUint53 = (state, val) => {
|
|
48
|
+
let pos = state.p;
|
|
49
|
+
const buf = state.b;
|
|
53
50
|
const hi = (val / 2 ** 32) | 0;
|
|
54
51
|
const lo = val >>> 0;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
buf[pos++] = hi >>> 24;
|
|
53
|
+
buf[pos++] = (hi >>> 16) & 0xff;
|
|
54
|
+
buf[pos++] = (hi >>> 8) & 0xff;
|
|
55
|
+
buf[pos++] = hi & 0xff;
|
|
56
|
+
buf[pos++] = lo >>> 24;
|
|
57
|
+
buf[pos++] = (lo >>> 16) & 0xff;
|
|
58
|
+
buf[pos++] = (lo >>> 8) & 0xff;
|
|
59
|
+
buf[pos++] = lo & 0xff;
|
|
60
|
+
state.p = pos;
|
|
59
61
|
};
|
|
60
62
|
const writeTypeAndArgument = (state, type, arg) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
if (arg < 24) {
|
|
64
|
+
writeUint8(state, (type << 5) | arg);
|
|
65
|
+
}
|
|
66
|
+
else if (arg < 0x100) {
|
|
67
|
+
writeUint8(state, (type << 5) | 24);
|
|
68
|
+
writeUint8(state, arg);
|
|
69
|
+
}
|
|
70
|
+
else if (arg < 0x10000) {
|
|
71
|
+
writeUint8(state, (type << 5) | 25);
|
|
72
|
+
writeUint16(state, arg);
|
|
73
|
+
}
|
|
74
|
+
else if (arg < 0x100000000) {
|
|
75
|
+
writeUint8(state, (type << 5) | 26);
|
|
76
|
+
writeUint32(state, arg);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
writeUint8(state, (type << 5) | 27);
|
|
80
|
+
writeUint53(state, arg);
|
|
72
81
|
}
|
|
73
82
|
};
|
|
83
|
+
// --- Functions below MUST be cautious about ensuring there's enough room in the buffer!!
|
|
74
84
|
const writeInteger = (state, val) => {
|
|
85
|
+
resizeIfNeeded(state, MAX_TYPE_ARG_LEN);
|
|
75
86
|
if (val < 0) {
|
|
76
87
|
writeTypeAndArgument(state, 1, -val - 1);
|
|
77
88
|
}
|
|
@@ -80,154 +91,172 @@ const writeInteger = (state, val) => {
|
|
|
80
91
|
}
|
|
81
92
|
};
|
|
82
93
|
const writeFloat = (state, val) => {
|
|
94
|
+
resizeIfNeeded(state, 9);
|
|
83
95
|
writeUint8(state, 0xe0 | 27);
|
|
84
96
|
writeFloat64(state, val);
|
|
85
97
|
};
|
|
86
98
|
const writeNumber = (state, val) => {
|
|
87
|
-
if (
|
|
99
|
+
if (_isNaN(val)) {
|
|
88
100
|
throw new RangeError(`NaN values not supported`);
|
|
89
101
|
}
|
|
90
|
-
if (val >
|
|
102
|
+
if (val > MAX_SAFE_INTEGER || val < MIN_SAFE_INTEGER) {
|
|
91
103
|
throw new RangeError(`can't encode numbers beyond safe integer range`);
|
|
92
104
|
}
|
|
93
|
-
if (
|
|
105
|
+
if (_isInteger(val)) {
|
|
94
106
|
writeInteger(state, val);
|
|
95
107
|
}
|
|
96
108
|
else {
|
|
109
|
+
// Note: https://atproto.com/specs/data-model#:~:text=not%20allowed%20in%20atproto
|
|
97
110
|
writeFloat(state, val);
|
|
98
111
|
}
|
|
99
112
|
};
|
|
100
113
|
const writeString = (state, val) => {
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
// JS strings are UTF-16 (ECMA spec)
|
|
115
|
+
// Therefore, worst case length of UTF-8 is length * 3. (plus 9 bytes of CBOR header)
|
|
116
|
+
// Greatly overshoots in practice, but doesn't matter. (alloc is O(1)+ anyway)
|
|
117
|
+
const strLength = val.length;
|
|
118
|
+
resizeIfNeeded(state, strLength * 3 + MAX_TYPE_ARG_LEN);
|
|
119
|
+
// Credit: method used by cbor-x
|
|
120
|
+
// Rather than allocate a buffer and then copy it back to the destination buffer:
|
|
121
|
+
// - Estimate the length of the header based on the UTF-16 size of the string.
|
|
122
|
+
// Should be accurate most of the time, see last point for when it isn't.
|
|
123
|
+
// - Directly write the string at the estimated location, retrieving with it the actual length.
|
|
124
|
+
// - Write the header now that the length is available.
|
|
125
|
+
// - If the estimation happened to be wrong, correct the placement of the string.
|
|
126
|
+
// While it's costly, it's actually roughly the same cost as if we encoded it separately + copy.
|
|
127
|
+
const estimatedHeaderSize = getTypeInfoLength(strLength);
|
|
128
|
+
const estimatedPosition = state.p + estimatedHeaderSize;
|
|
129
|
+
const len = encodeUtf8Into(state.b, val, estimatedPosition);
|
|
130
|
+
const headerSize = getTypeInfoLength(len);
|
|
131
|
+
if (estimatedHeaderSize !== headerSize) {
|
|
132
|
+
// Estimation was incorrect, move the bytes to the real place.
|
|
133
|
+
state.b.copyWithin(state.p + headerSize, estimatedPosition, estimatedPosition + len);
|
|
134
|
+
}
|
|
103
135
|
writeTypeAndArgument(state, 3, len);
|
|
104
|
-
resizeIfNeeded(state, len);
|
|
105
|
-
new Uint8Array(state.b, state.p).set(buf);
|
|
106
136
|
state.p += len;
|
|
107
137
|
};
|
|
108
138
|
const writeBytes = (state, val) => {
|
|
109
139
|
const buf = fromBytes(val);
|
|
110
140
|
const len = buf.byteLength;
|
|
141
|
+
resizeIfNeeded(state, len + MAX_TYPE_ARG_LEN);
|
|
111
142
|
writeTypeAndArgument(state, 2, len);
|
|
112
|
-
|
|
113
|
-
new Uint8Array(state.b, state.p, len).set(buf);
|
|
143
|
+
state.b.set(buf, state.p);
|
|
114
144
|
state.p += len;
|
|
115
145
|
};
|
|
116
146
|
const writeCid = (state, val) => {
|
|
117
147
|
// CID bytes are prefixed with 0x00 for historical reasons, apparently.
|
|
118
148
|
const buf = val instanceof CidLinkWrapper ? val.bytes : fromString(val.$link).bytes;
|
|
119
149
|
const len = buf.byteLength + 1;
|
|
150
|
+
resizeIfNeeded(state, len + 2 * MAX_TYPE_ARG_LEN);
|
|
120
151
|
writeTypeAndArgument(state, 6, 42);
|
|
121
152
|
writeTypeAndArgument(state, 2, len);
|
|
122
|
-
|
|
123
|
-
|
|
153
|
+
state.b[state.p] = 0;
|
|
154
|
+
state.b.set(buf, state.p + 1);
|
|
124
155
|
state.p += len;
|
|
125
156
|
};
|
|
126
157
|
const writeValue = (state, val) => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return writeUint8(state, 0xf6);
|
|
132
|
-
}
|
|
133
|
-
if (val === false) {
|
|
134
|
-
return writeUint8(state, 0xf4);
|
|
135
|
-
}
|
|
136
|
-
if (val === true) {
|
|
137
|
-
return writeUint8(state, 0xf5);
|
|
138
|
-
}
|
|
139
|
-
if (typeof val === 'number') {
|
|
140
|
-
return writeNumber(state, val);
|
|
141
|
-
}
|
|
142
|
-
if (typeof val === 'string') {
|
|
143
|
-
return writeString(state, val);
|
|
144
|
-
}
|
|
145
|
-
if (typeof val === 'object') {
|
|
146
|
-
if (isArray(val)) {
|
|
147
|
-
const len = val.length;
|
|
148
|
-
writeTypeAndArgument(state, 4, len);
|
|
149
|
-
for (let idx = 0; idx < len; idx++) {
|
|
150
|
-
const v = val[idx];
|
|
151
|
-
writeValue(state, v);
|
|
152
|
-
}
|
|
153
|
-
return;
|
|
158
|
+
switch (typeof val) {
|
|
159
|
+
case 'boolean': {
|
|
160
|
+
resizeIfNeeded(state, 1);
|
|
161
|
+
return writeUint8(state, 0xf4 + +val);
|
|
154
162
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
throw new TypeError(`unexpected cid-link value`);
|
|
163
|
+
case 'number': {
|
|
164
|
+
return writeNumber(state, val);
|
|
165
|
+
}
|
|
166
|
+
case 'string': {
|
|
167
|
+
return writeString(state, val);
|
|
161
168
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
case 'object': {
|
|
170
|
+
// case: null
|
|
171
|
+
if (val === null) {
|
|
172
|
+
resizeIfNeeded(state, 1);
|
|
173
|
+
return writeUint8(state, 0xf6);
|
|
174
|
+
}
|
|
175
|
+
// case: array
|
|
176
|
+
if (Array.isArray(val)) {
|
|
177
|
+
const len = val.length;
|
|
178
|
+
resizeIfNeeded(state, MAX_TYPE_ARG_LEN);
|
|
179
|
+
writeTypeAndArgument(state, 4, len);
|
|
180
|
+
for (let idx = 0; idx < len; idx++) {
|
|
181
|
+
writeValue(state, val[idx]);
|
|
182
|
+
}
|
|
165
183
|
return;
|
|
166
184
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
// case: cid-link
|
|
186
|
+
if ('$link' in val) {
|
|
187
|
+
if (val instanceof CidLinkWrapper || typeof val.$link === 'string') {
|
|
188
|
+
writeCid(state, val);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
throw new TypeError(`unexpected cid-link value`);
|
|
192
|
+
}
|
|
193
|
+
// case: bytes
|
|
194
|
+
if ('$bytes' in val) {
|
|
195
|
+
if (val instanceof BytesWrapper || typeof val.$bytes === 'string') {
|
|
196
|
+
writeBytes(state, val);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
throw new TypeError(`unexpected bytes value`);
|
|
200
|
+
}
|
|
201
|
+
// case: POJO
|
|
202
|
+
if (val.constructor === Object) {
|
|
203
|
+
const keys = getOrderedObjectKeys(val);
|
|
204
|
+
const len = keys.length;
|
|
205
|
+
resizeIfNeeded(state, MAX_TYPE_ARG_LEN);
|
|
206
|
+
writeTypeAndArgument(state, 5, len);
|
|
207
|
+
for (let idx = 0; idx < len; idx++) {
|
|
208
|
+
const key = keys[idx];
|
|
209
|
+
writeString(state, key);
|
|
210
|
+
writeValue(state, val[key]);
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
179
213
|
}
|
|
180
|
-
return;
|
|
181
214
|
}
|
|
182
215
|
}
|
|
183
216
|
throw new TypeError(`unsupported type: ${val}`);
|
|
184
217
|
};
|
|
185
218
|
const createState = () => {
|
|
186
|
-
const buf =
|
|
219
|
+
const buf = allocUnsafe(CHUNK_SIZE);
|
|
187
220
|
return {
|
|
188
221
|
c: [],
|
|
189
222
|
b: buf,
|
|
190
|
-
v: new DataView(buf),
|
|
223
|
+
v: new DataView(buf.buffer),
|
|
191
224
|
p: 0,
|
|
225
|
+
l: 0,
|
|
192
226
|
};
|
|
193
227
|
};
|
|
194
228
|
export const encode = (value) => {
|
|
195
229
|
const state = createState();
|
|
196
|
-
const chunks = state.c;
|
|
197
230
|
writeValue(state, value);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let written = 0;
|
|
201
|
-
let len = chunks.length;
|
|
202
|
-
let idx;
|
|
203
|
-
for (idx = 0; idx < len; idx++) {
|
|
204
|
-
size += chunks[idx].byteLength;
|
|
205
|
-
}
|
|
206
|
-
const u8 = new Uint8Array(size);
|
|
207
|
-
for (idx = 0; idx < len; idx++) {
|
|
208
|
-
const chunk = chunks[idx];
|
|
209
|
-
u8.set(chunk, written);
|
|
210
|
-
written += chunk.byteLength;
|
|
211
|
-
}
|
|
212
|
-
return u8;
|
|
213
|
-
};
|
|
214
|
-
const isArray = Array.isArray;
|
|
215
|
-
const isPlainObject = (v) => {
|
|
216
|
-
if (typeof v !== 'object' || v === null) {
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
const proto = Object.getPrototypeOf(v);
|
|
220
|
-
return proto === Object.prototype || proto === null;
|
|
231
|
+
state.c.push(state.b.subarray(0, state.p));
|
|
232
|
+
return concat(state.c, state.l + state.p);
|
|
221
233
|
};
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
/** @internal */
|
|
235
|
+
export const getOrderedObjectKeys = (obj) => {
|
|
236
|
+
const keys = Object.keys(obj);
|
|
237
|
+
for (let i = 1, len = keys.length, j = 0; i < len; j = i++) {
|
|
238
|
+
const valA = keys[i];
|
|
239
|
+
// Tuck in undefined value filtering here to avoid extra iterations.
|
|
240
|
+
if (obj[valA] === undefined) {
|
|
241
|
+
// A lot of things are tucked in here xd
|
|
242
|
+
// - Pull the currently last item in the keys array at the current place
|
|
243
|
+
// - Update saved value of array length
|
|
244
|
+
// - Decrease i by 1
|
|
245
|
+
keys[i--] = keys[--len];
|
|
246
|
+
keys.length = len;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
for (; j >= 0; j--) {
|
|
250
|
+
const valB = keys[j];
|
|
251
|
+
// Note: Don't need to check for equality, keys are always distinct.
|
|
252
|
+
const cmp = valA.length - valB.length || +(valA > valB);
|
|
253
|
+
if (cmp > 0)
|
|
254
|
+
break;
|
|
255
|
+
keys[j + 1] = valB;
|
|
256
|
+
}
|
|
257
|
+
keys[j + 1] = valA;
|
|
258
|
+
}
|
|
231
259
|
}
|
|
260
|
+
return keys;
|
|
232
261
|
};
|
|
233
262
|
//# sourceMappingURL=encode.js.map
|