@qevm/abi 5.7.1 → 5.7.3
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 +3 -4
- package/lib/_version.d.ts +1 -1
- package/lib/_version.js +1 -1
- package/lib/abi-coder.d.ts.map +1 -1
- package/lib/abi-coder.js +12 -7
- package/lib/abi-coder.js.map +1 -1
- package/lib/coders/abstract-coder.d.ts.map +1 -1
- package/lib/coders/abstract-coder.js +20 -9
- package/lib/coders/abstract-coder.js.map +1 -1
- package/lib/coders/address.d.ts.map +1 -1
- package/lib/coders/address.js +2 -2
- package/lib/coders/address.js.map +1 -1
- package/lib/coders/array.d.ts.map +1 -1
- package/lib/coders/array.js +17 -11
- package/lib/coders/array.js.map +1 -1
- package/lib/coders/boolean.d.ts.map +1 -1
- package/lib/coders/boolean.js.map +1 -1
- package/lib/coders/bytes.js.map +1 -1
- package/lib/coders/fixed-bytes.d.ts.map +1 -1
- package/lib/coders/fixed-bytes.js +1 -1
- package/lib/coders/fixed-bytes.js.map +1 -1
- package/lib/coders/function.d.ts +8 -0
- package/lib/coders/function.d.ts.map +1 -0
- package/lib/coders/function.js +46 -0
- package/lib/coders/function.js.map +1 -0
- package/lib/coders/null.d.ts.map +1 -1
- package/lib/coders/null.js.map +1 -1
- package/lib/coders/number.js +1 -1
- package/lib/coders/number.js.map +1 -1
- package/lib/coders/string.d.ts.map +1 -1
- package/lib/coders/string.js +1 -1
- package/lib/coders/string.js.map +1 -1
- package/lib/coders/tuple.d.ts.map +1 -1
- package/lib/coders/tuple.js +1 -1
- package/lib/coders/tuple.js.map +1 -1
- package/lib/fragments.d.ts.map +1 -1
- package/lib/fragments.js +127 -65
- package/lib/fragments.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/interface.d.ts +1 -1
- package/lib/interface.d.ts.map +1 -1
- package/lib/interface.js +84 -44
- package/lib/interface.js.map +1 -1
- package/package.json +35 -31
- package/src.ts/_version.ts +1 -1
- package/src.ts/abi-coder.ts +64 -26
- package/src.ts/coders/abstract-coder.ts +78 -33
- package/src.ts/coders/address.ts +3 -5
- package/src.ts/coders/array.ts +90 -47
- package/src.ts/coders/boolean.ts +1 -3
- package/src.ts/coders/bytes.ts +1 -3
- package/src.ts/coders/fixed-bytes.ts +7 -2
- package/src.ts/coders/function.ts +64 -0
- package/src.ts/coders/null.ts +4 -3
- package/src.ts/coders/number.ts +1 -2
- package/src.ts/coders/string.ts +1 -2
- package/src.ts/coders/tuple.ts +31 -16
- package/src.ts/fragments.ts +411 -178
- package/src.ts/index.ts +20 -8
- package/src.ts/interface.ts +405 -153
package/src.ts/coders/array.ts
CHANGED
|
@@ -1,50 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { Logger } from "@
|
|
3
|
+
import { Logger } from "@qevm/logger";
|
|
4
4
|
import { version } from "../_version";
|
|
5
5
|
const logger = new Logger(version);
|
|
6
6
|
|
|
7
7
|
import { Coder, Reader, Result, Writer } from "./abstract-coder";
|
|
8
8
|
import { AnonymousCoder } from "./anonymous";
|
|
9
9
|
|
|
10
|
-
export function pack(
|
|
10
|
+
export function pack(
|
|
11
|
+
writer: Writer,
|
|
12
|
+
coders: ReadonlyArray<Coder>,
|
|
13
|
+
values: Array<any> | { [name: string]: any },
|
|
14
|
+
): number {
|
|
11
15
|
let arrayValues: Array<any> = null;
|
|
12
16
|
|
|
13
17
|
if (Array.isArray(values)) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let unique: { [ name: string ]: boolean } = { };
|
|
18
|
+
arrayValues = values;
|
|
19
|
+
} else if (values && typeof values === "object") {
|
|
20
|
+
let unique: { [name: string]: boolean } = {};
|
|
18
21
|
|
|
19
22
|
arrayValues = coders.map((coder) => {
|
|
20
23
|
const name = coder.localName;
|
|
21
24
|
if (!name) {
|
|
22
|
-
logger.throwError(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
logger.throwError(
|
|
26
|
+
"cannot encode object for signature with missing names",
|
|
27
|
+
Logger.errors.INVALID_ARGUMENT,
|
|
28
|
+
{
|
|
29
|
+
argument: "values",
|
|
30
|
+
coder: coder,
|
|
31
|
+
value: values,
|
|
32
|
+
},
|
|
33
|
+
);
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
if (unique[name]) {
|
|
30
|
-
logger.throwError(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
logger.throwError(
|
|
38
|
+
"cannot encode object for signature with duplicate names",
|
|
39
|
+
Logger.errors.INVALID_ARGUMENT,
|
|
40
|
+
{
|
|
41
|
+
argument: "values",
|
|
42
|
+
coder: coder,
|
|
43
|
+
value: values,
|
|
44
|
+
},
|
|
45
|
+
);
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
unique[name] = true;
|
|
38
49
|
|
|
39
50
|
return values[name];
|
|
40
51
|
});
|
|
41
|
-
|
|
42
52
|
} else {
|
|
43
53
|
logger.throwArgumentError("invalid tuple value", "tuple", values);
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
if (coders.length !== arrayValues.length) {
|
|
47
|
-
logger.throwArgumentError(
|
|
57
|
+
logger.throwArgumentError(
|
|
58
|
+
"types/value length mismatch",
|
|
59
|
+
"tuple",
|
|
60
|
+
values,
|
|
61
|
+
);
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
let staticWriter = new Writer(writer.wordSize);
|
|
@@ -66,14 +80,15 @@ export function pack(writer: Writer, coders: ReadonlyArray<Coder>, values: Array
|
|
|
66
80
|
updateFuncs.push((baseOffset: number) => {
|
|
67
81
|
updateFunc(baseOffset + dynamicOffset);
|
|
68
82
|
});
|
|
69
|
-
|
|
70
83
|
} else {
|
|
71
84
|
coder.encode(staticWriter, value);
|
|
72
85
|
}
|
|
73
86
|
});
|
|
74
87
|
|
|
75
88
|
// Backfill all the dynamic offsets, now that we know the static length
|
|
76
|
-
updateFuncs.forEach((func) => {
|
|
89
|
+
updateFuncs.forEach((func) => {
|
|
90
|
+
func(staticWriter.length);
|
|
91
|
+
});
|
|
77
92
|
|
|
78
93
|
let length = writer.appendWriter(staticWriter);
|
|
79
94
|
length += writer.appendWriter(dynamicWriter);
|
|
@@ -96,19 +111,22 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|
|
96
111
|
value = coder.decode(offsetReader);
|
|
97
112
|
} catch (error) {
|
|
98
113
|
// Cannot recover from this
|
|
99
|
-
if (error.code === Logger.errors.BUFFER_OVERRUN) {
|
|
114
|
+
if (error.code === Logger.errors.BUFFER_OVERRUN) {
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
100
117
|
value = error;
|
|
101
118
|
value.baseType = coder.name;
|
|
102
119
|
value.name = coder.localName;
|
|
103
120
|
value.type = coder.type;
|
|
104
121
|
}
|
|
105
|
-
|
|
106
122
|
} else {
|
|
107
123
|
try {
|
|
108
124
|
value = coder.decode(reader);
|
|
109
125
|
} catch (error) {
|
|
110
126
|
// Cannot recover from this
|
|
111
|
-
if (error.code === Logger.errors.BUFFER_OVERRUN) {
|
|
127
|
+
if (error.code === Logger.errors.BUFFER_OVERRUN) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
112
130
|
value = error;
|
|
113
131
|
value.baseType = coder.name;
|
|
114
132
|
value.name = coder.localName;
|
|
@@ -122,30 +140,43 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|
|
122
140
|
});
|
|
123
141
|
|
|
124
142
|
// We only output named properties for uniquely named coders
|
|
125
|
-
const uniqueNames = coders.reduce(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
143
|
+
const uniqueNames = coders.reduce(
|
|
144
|
+
(accum, coder) => {
|
|
145
|
+
const name = coder.localName;
|
|
146
|
+
if (name) {
|
|
147
|
+
if (!accum[name]) {
|
|
148
|
+
accum[name] = 0;
|
|
149
|
+
}
|
|
150
|
+
accum[name]++;
|
|
151
|
+
}
|
|
152
|
+
return accum;
|
|
153
|
+
},
|
|
154
|
+
<{ [name: string]: number }>{},
|
|
155
|
+
);
|
|
133
156
|
|
|
134
157
|
// Add any named parameters (i.e. tuples)
|
|
135
158
|
coders.forEach((coder: Coder, index: number) => {
|
|
136
159
|
let name = coder.localName;
|
|
137
|
-
if (!name || uniqueNames[name] !== 1) {
|
|
160
|
+
if (!name || uniqueNames[name] !== 1) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
138
163
|
|
|
139
|
-
if (name === "length") {
|
|
164
|
+
if (name === "length") {
|
|
165
|
+
name = "_length";
|
|
166
|
+
}
|
|
140
167
|
|
|
141
|
-
if (values[name] != null) {
|
|
168
|
+
if (values[name] != null) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
142
171
|
|
|
143
172
|
const value = values[index];
|
|
144
173
|
|
|
145
174
|
if (value instanceof Error) {
|
|
146
175
|
Object.defineProperty(values, name, {
|
|
147
176
|
enumerable: true,
|
|
148
|
-
get: () => {
|
|
177
|
+
get: () => {
|
|
178
|
+
throw value;
|
|
179
|
+
},
|
|
149
180
|
});
|
|
150
181
|
} else {
|
|
151
182
|
values[name] = value;
|
|
@@ -157,7 +188,9 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|
|
157
188
|
if (value instanceof Error) {
|
|
158
189
|
Object.defineProperty(values, i, {
|
|
159
190
|
enumerable: true,
|
|
160
|
-
get: () => {
|
|
191
|
+
get: () => {
|
|
192
|
+
throw value;
|
|
193
|
+
},
|
|
161
194
|
});
|
|
162
195
|
}
|
|
163
196
|
}
|
|
@@ -165,14 +198,13 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|
|
165
198
|
return Object.freeze(values);
|
|
166
199
|
}
|
|
167
200
|
|
|
168
|
-
|
|
169
201
|
export class ArrayCoder extends Coder {
|
|
170
202
|
readonly coder: Coder;
|
|
171
203
|
readonly length: number;
|
|
172
204
|
|
|
173
205
|
constructor(coder: Coder, length: number, localName: string) {
|
|
174
|
-
const type =
|
|
175
|
-
const dynamic =
|
|
206
|
+
const type = coder.type + "[" + (length >= 0 ? length : "") + "]";
|
|
207
|
+
const dynamic = length === -1 || coder.dynamic;
|
|
176
208
|
super("array", type, localName, dynamic);
|
|
177
209
|
|
|
178
210
|
this.coder = coder;
|
|
@@ -202,10 +234,16 @@ export class ArrayCoder extends Coder {
|
|
|
202
234
|
writer.writeValue(value.length);
|
|
203
235
|
}
|
|
204
236
|
|
|
205
|
-
logger.checkArgumentCount(
|
|
237
|
+
logger.checkArgumentCount(
|
|
238
|
+
value.length,
|
|
239
|
+
count,
|
|
240
|
+
"coder array" + (this.localName ? " " + this.localName : ""),
|
|
241
|
+
);
|
|
206
242
|
|
|
207
243
|
let coders = [];
|
|
208
|
-
for (let i = 0; i < value.length; i++) {
|
|
244
|
+
for (let i = 0; i < value.length; i++) {
|
|
245
|
+
coders.push(this.coder);
|
|
246
|
+
}
|
|
209
247
|
|
|
210
248
|
return pack(writer, coders, value);
|
|
211
249
|
}
|
|
@@ -221,16 +259,21 @@ export class ArrayCoder extends Coder {
|
|
|
221
259
|
// bytes as a link to the data). This could use a much
|
|
222
260
|
// tighter bound, but we are erroring on the side of safety.
|
|
223
261
|
if (count * 32 > reader._data.length) {
|
|
224
|
-
logger.throwError(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
262
|
+
logger.throwError(
|
|
263
|
+
"insufficient data length",
|
|
264
|
+
Logger.errors.BUFFER_OVERRUN,
|
|
265
|
+
{
|
|
266
|
+
length: reader._data.length,
|
|
267
|
+
count: count,
|
|
268
|
+
},
|
|
269
|
+
);
|
|
228
270
|
}
|
|
229
271
|
}
|
|
230
272
|
let coders = [];
|
|
231
|
-
for (let i = 0; i < count; i++) {
|
|
273
|
+
for (let i = 0; i < count; i++) {
|
|
274
|
+
coders.push(new AnonymousCoder(this.coder));
|
|
275
|
+
}
|
|
232
276
|
|
|
233
277
|
return reader.coerce(this.name, unpack(reader, coders));
|
|
234
278
|
}
|
|
235
279
|
}
|
|
236
|
-
|
package/src.ts/coders/boolean.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { Coder, Reader, Writer } from "./abstract-coder";
|
|
4
4
|
|
|
5
5
|
export class BooleanCoder extends Coder {
|
|
6
|
-
|
|
7
6
|
constructor(localName: string) {
|
|
8
7
|
super("bool", "bool", localName, false);
|
|
9
8
|
}
|
|
@@ -13,11 +12,10 @@ export class BooleanCoder extends Coder {
|
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
encode(writer: Writer, value: boolean): number {
|
|
16
|
-
return writer.writeValue(value ? 1: 0);
|
|
15
|
+
return writer.writeValue(value ? 1 : 0);
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
decode(reader: Reader): any {
|
|
20
19
|
return reader.coerce(this.type, !reader.readValue().isZero());
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
|
-
|
package/src.ts/coders/bytes.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Coder, Reader, Writer } from "./abstract-coder";
|
|
|
6
6
|
|
|
7
7
|
export class DynamicBytesCoder extends Coder {
|
|
8
8
|
constructor(type: string, localName: string) {
|
|
9
|
-
|
|
9
|
+
super(type, type, localName, true);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
defaultValue(): string {
|
|
@@ -34,5 +34,3 @@ export class BytesCoder extends DynamicBytesCoder {
|
|
|
34
34
|
return reader.coerce(this.name, hexlify(super.decode(reader)));
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
@@ -15,12 +15,17 @@ export class FixedBytesCoder extends Coder {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
defaultValue(): string {
|
|
18
|
-
return
|
|
18
|
+
return "0x0000000000000000000000000000000000000000000000000000000000000000".substring(
|
|
19
|
+
0,
|
|
20
|
+
2 + this.size * 2,
|
|
21
|
+
);
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
encode(writer: Writer, value: BytesLike): number {
|
|
22
25
|
let data = arrayify(value);
|
|
23
|
-
if (data.length !== this.size) {
|
|
26
|
+
if (data.length !== this.size) {
|
|
27
|
+
this._throwError("incorrect data length", value);
|
|
28
|
+
}
|
|
24
29
|
return writer.writeBytes(data);
|
|
25
30
|
}
|
|
26
31
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { hexZeroPad } from "@qevm/bytes";
|
|
4
|
+
import { getAddress } from "@qevm/address";
|
|
5
|
+
|
|
6
|
+
import { Coder, Reader, Writer } from "./abstract-coder";
|
|
7
|
+
|
|
8
|
+
export class FunctionCoder extends Coder {
|
|
9
|
+
constructor(localName: string) {
|
|
10
|
+
// type "function" is NOT dynamic, occupies 64 bytes (2 words)
|
|
11
|
+
super("function", "function", localName, false);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
defaultValue(): string {
|
|
15
|
+
// 32-byte zero address + 4-byte zero selector = 72 hex chars
|
|
16
|
+
return "0x" + "00".repeat(32) + "00000000";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
encode(writer: Writer, value: string): number {
|
|
20
|
+
// Expected format: "0x" + 64 hex (address) + 8 hex (selector)
|
|
21
|
+
// Total: 74 chars including "0x"
|
|
22
|
+
let hex = value;
|
|
23
|
+
if (hex.startsWith("0x")) {
|
|
24
|
+
hex = hex.substring(2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (hex.length !== 72) {
|
|
28
|
+
this._throwError(
|
|
29
|
+
"invalid function value (expected 72 hex chars after 0x)",
|
|
30
|
+
value,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const addressHex = "0x" + hex.substring(0, 64);
|
|
35
|
+
const selectorHex = "0x" + hex.substring(64, 72);
|
|
36
|
+
|
|
37
|
+
// Validate address
|
|
38
|
+
getAddress(addressHex);
|
|
39
|
+
|
|
40
|
+
// Word 0: full 32-byte address (right-aligned = as uint256)
|
|
41
|
+
writer.writeValue(addressHex);
|
|
42
|
+
|
|
43
|
+
// Word 1: 4-byte selector right-aligned in 32-byte word
|
|
44
|
+
writer.writeValue(selectorHex);
|
|
45
|
+
|
|
46
|
+
return writer.length;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
decode(reader: Reader): any {
|
|
50
|
+
// Read 2 words (64 bytes)
|
|
51
|
+
const addressValue = reader.readValue(); // word 0: address
|
|
52
|
+
const selectorValue = reader.readValue(); // word 1: selector (masked to 4 bytes)
|
|
53
|
+
|
|
54
|
+
const addressHex = hexZeroPad(addressValue.toHexString(), 32).substring(
|
|
55
|
+
2,
|
|
56
|
+
); // 64 hex chars
|
|
57
|
+
const selectorHex = hexZeroPad(
|
|
58
|
+
selectorValue.mask(32).toHexString(),
|
|
59
|
+
4,
|
|
60
|
+
).substring(2); // 8 hex chars
|
|
61
|
+
|
|
62
|
+
return reader.coerce(this.name, "0x" + addressHex + selectorHex);
|
|
63
|
+
}
|
|
64
|
+
}
|
package/src.ts/coders/null.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { Coder, Reader, Writer } from "./abstract-coder";
|
|
4
4
|
|
|
5
5
|
export class NullCoder extends Coder {
|
|
6
|
-
|
|
7
6
|
constructor(localName: string) {
|
|
8
7
|
super("null", "", localName, false);
|
|
9
8
|
}
|
|
@@ -13,8 +12,10 @@ export class NullCoder extends Coder {
|
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
encode(writer: Writer, value: any): number {
|
|
16
|
-
if (value != null) {
|
|
17
|
-
|
|
15
|
+
if (value != null) {
|
|
16
|
+
this._throwError("not null", value);
|
|
17
|
+
}
|
|
18
|
+
return writer.writeBytes([]);
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
decode(reader: Reader): any {
|
package/src.ts/coders/number.ts
CHANGED
|
@@ -10,7 +10,7 @@ export class NumberCoder extends Coder {
|
|
|
10
10
|
readonly signed: boolean;
|
|
11
11
|
|
|
12
12
|
constructor(size: number, signed: boolean, localName: string) {
|
|
13
|
-
const name = (
|
|
13
|
+
const name = (signed ? "int" : "uint") + size * 8;
|
|
14
14
|
super(name, name, localName, false);
|
|
15
15
|
|
|
16
16
|
this.size = size;
|
|
@@ -54,4 +54,3 @@ export class NumberCoder extends Coder {
|
|
|
54
54
|
return reader.coerce(this.name, value);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
|
package/src.ts/coders/string.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { toUtf8Bytes, toUtf8String } from "@
|
|
3
|
+
import { toUtf8Bytes, toUtf8String } from "@qevm/strings";
|
|
4
4
|
|
|
5
5
|
import { Reader, Writer } from "./abstract-coder";
|
|
6
6
|
import { DynamicBytesCoder } from "./bytes";
|
|
7
7
|
|
|
8
8
|
export class StringCoder extends DynamicBytesCoder {
|
|
9
|
-
|
|
10
9
|
constructor(localName: string) {
|
|
11
10
|
super("string", localName);
|
|
12
11
|
}
|
package/src.ts/coders/tuple.ts
CHANGED
|
@@ -10,39 +10,52 @@ export class TupleCoder extends Coder {
|
|
|
10
10
|
let dynamic = false;
|
|
11
11
|
const types: Array<string> = [];
|
|
12
12
|
coders.forEach((coder) => {
|
|
13
|
-
if (coder.dynamic) {
|
|
13
|
+
if (coder.dynamic) {
|
|
14
|
+
dynamic = true;
|
|
15
|
+
}
|
|
14
16
|
types.push(coder.type);
|
|
15
17
|
});
|
|
16
|
-
const type =
|
|
18
|
+
const type = "tuple(" + types.join(",") + ")";
|
|
17
19
|
|
|
18
20
|
super("tuple", type, localName, dynamic);
|
|
19
21
|
this.coders = coders;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
defaultValue(): any {
|
|
23
|
-
const values: any = [
|
|
25
|
+
const values: any = [];
|
|
24
26
|
this.coders.forEach((coder) => {
|
|
25
27
|
values.push(coder.defaultValue());
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
// We only output named properties for uniquely named coders
|
|
29
|
-
const uniqueNames = this.coders.reduce(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
const uniqueNames = this.coders.reduce(
|
|
32
|
+
(accum, coder) => {
|
|
33
|
+
const name = coder.localName;
|
|
34
|
+
if (name) {
|
|
35
|
+
if (!accum[name]) {
|
|
36
|
+
accum[name] = 0;
|
|
37
|
+
}
|
|
38
|
+
accum[name]++;
|
|
39
|
+
}
|
|
40
|
+
return accum;
|
|
41
|
+
},
|
|
42
|
+
<{ [name: string]: number }>{},
|
|
43
|
+
);
|
|
37
44
|
|
|
38
45
|
// Add named values
|
|
39
46
|
this.coders.forEach((coder: Coder, index: number) => {
|
|
40
47
|
let name = coder.localName;
|
|
41
|
-
if (!name || uniqueNames[name] !== 1) {
|
|
48
|
+
if (!name || uniqueNames[name] !== 1) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
42
51
|
|
|
43
|
-
if (name === "length") {
|
|
52
|
+
if (name === "length") {
|
|
53
|
+
name = "_length";
|
|
54
|
+
}
|
|
44
55
|
|
|
45
|
-
if (values[name] != null) {
|
|
56
|
+
if (values[name] != null) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
46
59
|
|
|
47
60
|
values[name] = values[index];
|
|
48
61
|
});
|
|
@@ -50,7 +63,10 @@ export class TupleCoder extends Coder {
|
|
|
50
63
|
return Object.freeze(values);
|
|
51
64
|
}
|
|
52
65
|
|
|
53
|
-
encode(
|
|
66
|
+
encode(
|
|
67
|
+
writer: Writer,
|
|
68
|
+
value: Array<any> | { [name: string]: any },
|
|
69
|
+
): number {
|
|
54
70
|
return pack(writer, this.coders, value);
|
|
55
71
|
}
|
|
56
72
|
|
|
@@ -58,4 +74,3 @@ export class TupleCoder extends Coder {
|
|
|
58
74
|
return reader.coerce(this.name, unpack(reader, this.coders));
|
|
59
75
|
}
|
|
60
76
|
}
|
|
61
|
-
|