1 | const lodash = require('lodash');
|
2 | const { assert, format } = require('../util');
|
3 | const BaseCoder = require('./BaseCoder');
|
4 | const { encodeUInt256, decodeUInt256, pack, unpack } = require('./util');
|
5 |
|
6 | class ArrayCoder extends BaseCoder {
|
7 | static from({ type, name, components }, abiCoder) {
|
8 | const match = type.match(/^(.*)\[([0-9]*)]$/);
|
9 | if (!match) {
|
10 | return undefined;
|
11 | }
|
12 |
|
13 | const [, subType, size] = match;
|
14 | return new this({
|
15 | name,
|
16 | coder: abiCoder({ type: subType, components }),
|
17 | size: size ? parseInt(size, 10) : undefined,
|
18 | });
|
19 | }
|
20 |
|
21 | constructor({ name, coder, size }) {
|
22 | if (size !== undefined) {
|
23 | assert(Number.isInteger(size) && 0 < size, {
|
24 | message: 'invalid size',
|
25 | expect: 'integer && >0',
|
26 | got: size,
|
27 | coder: { name },
|
28 | });
|
29 | }
|
30 |
|
31 | super({ name });
|
32 | this.type = `${coder.type}[${size > 0 ? size : ''}]`;
|
33 | this.size = size;
|
34 | this.coder = coder;
|
35 | this.dynamic = Boolean(size === undefined) || coder.dynamic;
|
36 | }
|
37 |
|
38 | |
39 |
|
40 |
|
41 |
|
42 | encode(array) {
|
43 | assert(Array.isArray(array), {
|
44 | message: 'unexpected type',
|
45 | expect: 'array',
|
46 | got: typeof array,
|
47 | coder: this,
|
48 | });
|
49 |
|
50 | if (this.size !== undefined) {
|
51 | assert(array.length === this.size, {
|
52 | message: 'length not match',
|
53 | expect: this.size,
|
54 | got: array.length,
|
55 | coder: this,
|
56 | });
|
57 | }
|
58 |
|
59 | const coders = lodash.range(array.length).map(() => this.coder);
|
60 | let buffer = pack(coders, array);
|
61 | if (this.size === undefined) {
|
62 | buffer = Buffer.concat([encodeUInt256(array.length), buffer]);
|
63 | }
|
64 | return buffer;
|
65 | }
|
66 |
|
67 | |
68 |
|
69 |
|
70 |
|
71 | decode(stream) {
|
72 | let length = this.size;
|
73 |
|
74 | if (length === undefined) {
|
75 | length = Number(decodeUInt256(stream));
|
76 | }
|
77 |
|
78 | const coders = lodash.range(length).map(() => this.coder);
|
79 | return unpack(coders, stream);
|
80 | }
|
81 |
|
82 | encodeIndex(value) {
|
83 | try {
|
84 | return format.hex64(value);
|
85 | } catch (e) {
|
86 | throw new Error('not supported encode array to index');
|
87 | }
|
88 | }
|
89 |
|
90 | decodeIndex(hex) {
|
91 | return hex;
|
92 | }
|
93 | }
|
94 |
|
95 | module.exports = ArrayCoder;
|