1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const tslib_1 = require("tslib");
|
4 | const client_common_1 = require("@neo-one/client-common");
|
5 | const bn_js_1 = require("bn.js");
|
6 | const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
7 | class BinaryReader {
|
8 | constructor(buffer, index = 0) {
|
9 | this.buffer = buffer;
|
10 | this.mutableIndex = index;
|
11 | }
|
12 | get index() {
|
13 | return this.mutableIndex;
|
14 | }
|
15 | get remaining() {
|
16 | return this.buffer.length - this.mutableIndex;
|
17 | }
|
18 | get remainingBuffer() {
|
19 | return this.buffer.slice(this.mutableIndex);
|
20 | }
|
21 | hasMore() {
|
22 | return this.mutableIndex < this.buffer.byteLength;
|
23 | }
|
24 | clone() {
|
25 | return new BinaryReader(this.buffer, this.mutableIndex);
|
26 | }
|
27 | readBytes(numBytes) {
|
28 | this.checkRead(numBytes);
|
29 | const result = this.buffer.slice(this.mutableIndex, this.mutableIndex + numBytes);
|
30 | this.mutableIndex += numBytes;
|
31 | return result;
|
32 | }
|
33 | readInt8() {
|
34 | this.checkRead(1);
|
35 | const result = this.buffer.readInt8(this.mutableIndex);
|
36 | this.mutableIndex += 1;
|
37 | return result;
|
38 | }
|
39 | readUInt8() {
|
40 | this.checkRead(1);
|
41 | const result = this.buffer.readUInt8(this.mutableIndex);
|
42 | this.mutableIndex += 1;
|
43 | return result;
|
44 | }
|
45 | readBoolean() {
|
46 | return this.readBytes(1)[0] !== 0;
|
47 | }
|
48 | readInt16LE() {
|
49 | this.checkRead(2);
|
50 | const result = this.buffer.readInt16LE(this.mutableIndex);
|
51 | this.mutableIndex += 2;
|
52 | return result;
|
53 | }
|
54 | readUInt16LE() {
|
55 | this.checkRead(2);
|
56 | const result = this.buffer.readUInt16LE(this.mutableIndex);
|
57 | this.mutableIndex += 2;
|
58 | return result;
|
59 | }
|
60 | readUInt16BE() {
|
61 | this.checkRead(2);
|
62 | const result = this.buffer.readUInt16BE(this.mutableIndex);
|
63 | this.mutableIndex += 2;
|
64 | return result;
|
65 | }
|
66 | readInt32LE() {
|
67 | this.checkRead(4);
|
68 | const result = this.buffer.readInt32LE(this.mutableIndex);
|
69 | this.mutableIndex += 4;
|
70 | return result;
|
71 | }
|
72 | readUInt32LE() {
|
73 | this.checkRead(4);
|
74 | const result = this.buffer.readUInt32LE(this.mutableIndex);
|
75 | this.mutableIndex += 4;
|
76 | return result;
|
77 | }
|
78 | readUInt64LE() {
|
79 | return new bn_js_1.BN(this.readBytes(8), 'le');
|
80 | }
|
81 | readInt64LE() {
|
82 | const buffer = this.readBytes(8);
|
83 | return new bn_js_1.BN(buffer, 'le').fromTwos(buffer.length * 8);
|
84 | }
|
85 | readUInt160() {
|
86 | return client_common_1.common.bufferToUInt160(this.readBytes(client_common_1.common.UINT160_BUFFER_BYTES));
|
87 | }
|
88 | readUInt256() {
|
89 | return client_common_1.common.bufferToUInt256(this.readBytes(client_common_1.common.UINT256_BUFFER_BYTES));
|
90 | }
|
91 | readFixed8() {
|
92 | return this.readInt64LE();
|
93 | }
|
94 | readFixedString(length) {
|
95 | const values = lodash_1.default.takeWhile([...this.readBytes(length)], (value) => value !== 0);
|
96 | return Buffer.from(values).toString('utf8');
|
97 | }
|
98 | readArray(read, max = 0x1000000) {
|
99 | const count = this.readVarUIntLE(new bn_js_1.BN(max)).toNumber();
|
100 | return lodash_1.default.range(count).map(read);
|
101 | }
|
102 | readObject(read, max = 0x1000000) {
|
103 | const count = this.readVarUIntLE(new bn_js_1.BN(max)).toNumber();
|
104 | return lodash_1.default.range(count).reduce((acc) => {
|
105 | const { key, value } = read();
|
106 | return Object.assign(Object.assign({}, acc), { [key]: value });
|
107 | }, {});
|
108 | }
|
109 | readVarBytesLE(max = 0x1000000) {
|
110 | return this.readBytes(this.readVarUIntLE(new bn_js_1.BN(max)).toNumber());
|
111 | }
|
112 | readVarUIntLE(max = new bn_js_1.BN('18446744073709551615', 10)) {
|
113 | const fb = this.readUInt8();
|
114 | let value;
|
115 | switch (fb) {
|
116 | case 0xfd:
|
117 | value = new bn_js_1.BN(this.readUInt16LE());
|
118 | break;
|
119 | case 0xfe:
|
120 | value = new bn_js_1.BN(this.readUInt32LE());
|
121 | break;
|
122 | case 0xff:
|
123 | value = this.readUInt64LE();
|
124 | break;
|
125 | default:
|
126 | value = new bn_js_1.BN(fb);
|
127 | }
|
128 | if (value.gt(max)) {
|
129 | throw new client_common_1.InvalidFormatError(`Integer too large: ${value.toString(10)} > ${max.toString(10)}`);
|
130 | }
|
131 | return value;
|
132 | }
|
133 | readVarString(max = 0x1000000) {
|
134 | return this.readVarBytesLE(max).toString('utf8');
|
135 | }
|
136 | readECPoint() {
|
137 | const firstByte = this.readBytes(1);
|
138 | if (firstByte[0] === client_common_1.common.ECPOINT_INFINITY_BYTE) {
|
139 | return client_common_1.common.ECPOINT_INFINITY;
|
140 | }
|
141 | return client_common_1.common.bufferToECPoint(Buffer.concat([firstByte, this.readBytes(client_common_1.common.ECPOINT_BUFFER_BYTES - 1)]));
|
142 | }
|
143 | checkRead(numBytes) {
|
144 | if (this.remaining < numBytes) {
|
145 | throw new client_common_1.InvalidFormatError(`Insufficient bytes remaining (${this.remaining}): ${numBytes}`);
|
146 | }
|
147 | }
|
148 | }
|
149 | exports.BinaryReader = BinaryReader;
|
150 |
|
151 |
|