@jsprismarine/binaryutils 0.15.0-unstable-20261024002035
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/CHANGELOG.md +24 -0
- package/LICENSE +373 -0
- package/README.md +186 -0
- package/dist/BinaryStream.cjs.cjs +839 -0
- package/dist/BinaryStream.d.ts +488 -0
- package/dist/BinaryStream.d.ts.map +1 -0
- package/dist/BinaryStream.es.js +831 -0
- package/dist/_virtual/_rolldown/runtime.cjs.cjs +24 -0
- package/dist/index.cjs.cjs +8 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +2 -0
- package/package.json +69 -0
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, {
|
|
3
|
+
__esModule: { value: true },
|
|
4
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
5
|
+
});
|
|
6
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.cjs.cjs");
|
|
7
|
+
let assert = require("assert");
|
|
8
|
+
assert = require_runtime.__toESM(assert, 1);
|
|
9
|
+
//#region src/BinaryStream.ts
|
|
10
|
+
/**
|
|
11
|
+
* A high-performance binary stream for reading and writing binary data.
|
|
12
|
+
*
|
|
13
|
+
* Unlike Node.js native buffers which have fixed size, BinaryStream uses dynamic
|
|
14
|
+
* buffers that grow automatically during write operations. This eliminates the need
|
|
15
|
+
* for manual resizing or inefficient `Buffer.concat()` calls.
|
|
16
|
+
*
|
|
17
|
+
* @example Reading data
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const stream = new BinaryStream(buffer);
|
|
20
|
+
* const value = stream.readInt();
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example Writing data
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const stream = new BinaryStream();
|
|
26
|
+
* stream.writeInt(42);
|
|
27
|
+
* stream.write(Buffer.from('Hello')); // Buffer grows automatically
|
|
28
|
+
* const buffer = stream.getWriteBuffer();
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example Encoding many packets without allocating
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const stream = new BinaryStream(undefined, 0, 4096);
|
|
34
|
+
* for (const packet of queue) {
|
|
35
|
+
* stream.resetWrite();
|
|
36
|
+
* packet.encode(stream);
|
|
37
|
+
* offset = stream.copyInto(arena, offset);
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
var BinaryStream = class {
|
|
42
|
+
writeBuffer = null;
|
|
43
|
+
readBuffer = null;
|
|
44
|
+
readIndex;
|
|
45
|
+
writeIndex = 0;
|
|
46
|
+
writeCapacity = 0;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new BinaryStream instance.
|
|
49
|
+
* @param {Buffer|null|undefined} buffer - The array or Buffer containing binary data.
|
|
50
|
+
* @param {number} offset - The initial pointer position.
|
|
51
|
+
* @param {number} initialCapacity - Pre-allocates the write buffer to this size. Use it when
|
|
52
|
+
* the encoded size is known up front: it skips the 256 -> 512 -> 1024 ... growth ladder, and
|
|
53
|
+
* with {@link resetWrite} it lets a long-lived encoder run without allocating at all.
|
|
54
|
+
*/
|
|
55
|
+
constructor(buffer, offset = 0, initialCapacity = 0) {
|
|
56
|
+
this.readBuffer = buffer ?? null;
|
|
57
|
+
this.readIndex = offset;
|
|
58
|
+
if (initialCapacity > 0) this.reserve(initialCapacity);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reads a slice of buffer by the given length.
|
|
62
|
+
* @param {number} len
|
|
63
|
+
*/
|
|
64
|
+
read(len) {
|
|
65
|
+
this.doReadAssertions(len);
|
|
66
|
+
return this.readBuffer.subarray(this.readIndex, this.readIndex += len);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Appends a buffer to the main buffer.
|
|
70
|
+
* @param {Buffer|Uint8Array} buf
|
|
71
|
+
*/
|
|
72
|
+
write(buf) {
|
|
73
|
+
const len = buf.byteLength;
|
|
74
|
+
this.ensureCapacity(len);
|
|
75
|
+
this.writeBuffer.set(buf, this.writeIndex);
|
|
76
|
+
this.writeIndex += len;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Reads an unsigned byte (0 to 255).
|
|
80
|
+
* @returns {number}
|
|
81
|
+
*/
|
|
82
|
+
readByte() {
|
|
83
|
+
this.doReadAssertions(1);
|
|
84
|
+
return this.readBuffer[this.readIndex++];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Writes an unsigned byte (0 to 255).
|
|
88
|
+
* @param {number} v
|
|
89
|
+
*/
|
|
90
|
+
writeByte(v) {
|
|
91
|
+
this.ensureCapacity(1);
|
|
92
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Reads a signed byte (-128 to 127).
|
|
96
|
+
* @returns {number}
|
|
97
|
+
*/
|
|
98
|
+
readSignedByte() {
|
|
99
|
+
this.doReadAssertions(1);
|
|
100
|
+
return this.readBuffer[this.readIndex++] << 24 >> 24;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Writes a signed byte (-128 to 127).
|
|
104
|
+
* @param {number} v
|
|
105
|
+
*/
|
|
106
|
+
writeSignedByte(v) {
|
|
107
|
+
this.ensureCapacity(1);
|
|
108
|
+
this.writeBuffer[this.writeIndex++] = (v < 0 ? 255 + v + 1 : v) & 255;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Reads a boolean (true or false).
|
|
112
|
+
* @returns {boolean}
|
|
113
|
+
*/
|
|
114
|
+
readBoolean() {
|
|
115
|
+
this.doReadAssertions(1);
|
|
116
|
+
return this.readBuffer[this.readIndex++] !== 0;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Writes a boolean (true or false).
|
|
120
|
+
* @param {boolean} v
|
|
121
|
+
*/
|
|
122
|
+
writeBoolean(v) {
|
|
123
|
+
this.ensureCapacity(1);
|
|
124
|
+
this.writeBuffer[this.writeIndex++] = v ? 1 : 0;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Reads a 16 bit (2 bytes) signed big-endian number.
|
|
128
|
+
* @returns {number}
|
|
129
|
+
*/
|
|
130
|
+
readShort() {
|
|
131
|
+
this.doReadAssertions(2);
|
|
132
|
+
return this.readBuffer.readInt16BE(this.addOffset(2));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Writes a 16 bit (2 bytes) signed big-endian number.
|
|
136
|
+
* @param {number} v
|
|
137
|
+
*/
|
|
138
|
+
writeShort(v) {
|
|
139
|
+
this.doWriteAssertions(v, -32768, 32767);
|
|
140
|
+
this.ensureCapacity(2);
|
|
141
|
+
this.writeBuffer[this.writeIndex++] = v >> 8 & 255;
|
|
142
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Reads a 16 bit (2 bytes) signed little-endian number.
|
|
146
|
+
* @returns {number}
|
|
147
|
+
*/
|
|
148
|
+
readShortLE() {
|
|
149
|
+
this.doReadAssertions(2);
|
|
150
|
+
return this.readBuffer.readInt16LE(this.addOffset(2));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Writes a 16 bit (2 bytes) signed little-endian number.
|
|
154
|
+
* @param {number} v
|
|
155
|
+
*/
|
|
156
|
+
writeShortLE(v) {
|
|
157
|
+
this.doWriteAssertions(v, -32768, 32767);
|
|
158
|
+
this.ensureCapacity(2);
|
|
159
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
160
|
+
this.writeBuffer[this.writeIndex++] = v >> 8 & 255;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Reads a 16 bit (2 bytes) unsigned big-endian number.
|
|
164
|
+
* @returns {number}
|
|
165
|
+
*/
|
|
166
|
+
readUnsignedShort() {
|
|
167
|
+
this.doReadAssertions(2);
|
|
168
|
+
return this.readBuffer.readUInt16BE(this.addOffset(2));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Writes a 16 bit (2 bytes) unsigned big-endian number.
|
|
172
|
+
* @param {number} v
|
|
173
|
+
*/
|
|
174
|
+
writeUnsignedShort(v) {
|
|
175
|
+
this.doWriteAssertions(v, 0, 65535);
|
|
176
|
+
this.ensureCapacity(2);
|
|
177
|
+
this.writeBuffer[this.writeIndex++] = v >>> 8 & 255;
|
|
178
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Reads a 16 bit (2 bytes) unsigned little-endian number.
|
|
182
|
+
* @returns {number}
|
|
183
|
+
*/
|
|
184
|
+
readUnsignedShortLE() {
|
|
185
|
+
this.doReadAssertions(2);
|
|
186
|
+
return this.readBuffer.readUInt16LE(this.addOffset(2));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Writes a 16 bit (2 bytes) unsigned little-endian number.
|
|
190
|
+
* @param {number} v
|
|
191
|
+
*/
|
|
192
|
+
writeUnsignedShortLE(v) {
|
|
193
|
+
this.doWriteAssertions(v, 0, 65535);
|
|
194
|
+
this.ensureCapacity(2);
|
|
195
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
196
|
+
this.writeBuffer[this.writeIndex++] = v >>> 8 & 255;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Reads a 24 bit (3 bytes) signed big-endian number.
|
|
200
|
+
* @returns {number}
|
|
201
|
+
*/
|
|
202
|
+
readTriad() {
|
|
203
|
+
this.doReadAssertions(3);
|
|
204
|
+
return this.readBuffer.readIntBE(this.addOffset(3), 3);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Writes a 24 bit (3 bytes) signed big-endian number.
|
|
208
|
+
* @param {number} v
|
|
209
|
+
*/
|
|
210
|
+
writeTriad(v) {
|
|
211
|
+
this.doWriteAssertions(v, -8388608, 8388607);
|
|
212
|
+
this.ensureCapacity(3);
|
|
213
|
+
this.writeBuffer[this.writeIndex++] = v >> 16 & 255;
|
|
214
|
+
this.writeBuffer[this.writeIndex++] = v >> 8 & 255;
|
|
215
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Reads a 24 bit (3 bytes) little-endian number.
|
|
219
|
+
* @returns {number}
|
|
220
|
+
*/
|
|
221
|
+
readTriadLE() {
|
|
222
|
+
this.doReadAssertions(3);
|
|
223
|
+
return this.readBuffer.readIntLE(this.addOffset(3), 3);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Writes a 24 bit (3 bytes) signed little-endian number.
|
|
227
|
+
* @param {number} v
|
|
228
|
+
*/
|
|
229
|
+
writeTriadLE(v) {
|
|
230
|
+
this.doWriteAssertions(v, -8388608, 8388607);
|
|
231
|
+
this.ensureCapacity(3);
|
|
232
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
233
|
+
this.writeBuffer[this.writeIndex++] = v >> 8 & 255;
|
|
234
|
+
this.writeBuffer[this.writeIndex++] = v >> 16 & 255;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Reads a 24 bit (3 bytes) unsigned big-endian number.
|
|
238
|
+
* @returns {number}
|
|
239
|
+
*/
|
|
240
|
+
readUnsignedTriad() {
|
|
241
|
+
this.doReadAssertions(3);
|
|
242
|
+
return this.readBuffer.readUIntBE(this.addOffset(3), 3);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Writes a 24 bit (3 bytes) unsigned big-endian number.
|
|
246
|
+
* @param {number} v
|
|
247
|
+
*/
|
|
248
|
+
writeUnsignedTriad(v) {
|
|
249
|
+
this.doWriteAssertions(v, 0, 16777215);
|
|
250
|
+
this.ensureCapacity(3);
|
|
251
|
+
this.writeBuffer[this.writeIndex++] = v >>> 16 & 255;
|
|
252
|
+
this.writeBuffer[this.writeIndex++] = v >>> 8 & 255;
|
|
253
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Reads a 24 bit (3 bytes) unsigned little-endian number.
|
|
257
|
+
* @returns {number}
|
|
258
|
+
*/
|
|
259
|
+
readUnsignedTriadLE() {
|
|
260
|
+
this.doReadAssertions(3);
|
|
261
|
+
return this.readBuffer.readUIntLE(this.addOffset(3), 3);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Writes a 24 bit (3 bytes) unsigned little-endian number.
|
|
265
|
+
* @param {number} v
|
|
266
|
+
*/
|
|
267
|
+
writeUnsignedTriadLE(v) {
|
|
268
|
+
this.doWriteAssertions(v, 0, 16777215);
|
|
269
|
+
this.ensureCapacity(3);
|
|
270
|
+
this.writeBuffer[this.writeIndex++] = v & 255;
|
|
271
|
+
this.writeBuffer[this.writeIndex++] = v >>> 8 & 255;
|
|
272
|
+
this.writeBuffer[this.writeIndex++] = v >>> 16 & 255;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Reads a 32 bit (4 bytes) big-endian signed number.
|
|
276
|
+
* @returns {number}
|
|
277
|
+
*/
|
|
278
|
+
readInt() {
|
|
279
|
+
this.doReadAssertions(4);
|
|
280
|
+
return this.readBuffer.readInt32BE(this.addOffset(4));
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Writes a 32 bit (4 bytes) big-endian signed number.
|
|
284
|
+
* @param {number} v
|
|
285
|
+
*/
|
|
286
|
+
writeInt(v) {
|
|
287
|
+
this.doWriteAssertions(v, -2147483648, 2147483647);
|
|
288
|
+
this.ensureCapacity(4);
|
|
289
|
+
this.writeBuffer.writeInt32BE(v, this.writeIndex);
|
|
290
|
+
this.writeIndex += 4;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Reads a 32 bit (4 bytes) signed number.
|
|
294
|
+
* @returns {number}
|
|
295
|
+
*/
|
|
296
|
+
readIntLE() {
|
|
297
|
+
this.doReadAssertions(4);
|
|
298
|
+
return this.readBuffer.readIntLE(this.addOffset(4), 4);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Writes a 32 bit (4 bytes) little-endian signed number.
|
|
302
|
+
* @param {number} v
|
|
303
|
+
*/
|
|
304
|
+
writeIntLE(v) {
|
|
305
|
+
this.doWriteAssertions(v, -2147483648, 2147483647);
|
|
306
|
+
this.ensureCapacity(4);
|
|
307
|
+
this.writeBuffer.writeInt32LE(v, this.writeIndex);
|
|
308
|
+
this.writeIndex += 4;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Reads a 32 bit (4 bytes) big-endian unsigned number.
|
|
312
|
+
* @returns {number}
|
|
313
|
+
*/
|
|
314
|
+
readUnsignedInt() {
|
|
315
|
+
this.doReadAssertions(4);
|
|
316
|
+
return this.readBuffer.readUInt32BE(this.addOffset(4));
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Writes a 32 bit (4 bytes) big-endian unsigned number.
|
|
320
|
+
* @param {number} v
|
|
321
|
+
*/
|
|
322
|
+
writeUnsignedInt(v) {
|
|
323
|
+
this.doWriteAssertions(v, 0, 4294967295);
|
|
324
|
+
this.ensureCapacity(4);
|
|
325
|
+
this.writeBuffer.writeUInt32BE(v, this.writeIndex);
|
|
326
|
+
this.writeIndex += 4;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Reads a 32 bit (4 bytes) little-endian unsigned number.
|
|
330
|
+
* @returns {number}
|
|
331
|
+
*/
|
|
332
|
+
readUnsignedIntLE() {
|
|
333
|
+
this.doReadAssertions(4);
|
|
334
|
+
return this.readBuffer.readUInt32LE(this.addOffset(4));
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Writes a 32 bit (4 bytes) little-endian unsigned number.
|
|
338
|
+
* @param {number} v
|
|
339
|
+
*/
|
|
340
|
+
writeUnsignedIntLE(v) {
|
|
341
|
+
this.doWriteAssertions(v, 0, 4294967295);
|
|
342
|
+
this.ensureCapacity(4);
|
|
343
|
+
this.writeBuffer.writeUInt32LE(v, this.writeIndex);
|
|
344
|
+
this.writeIndex += 4;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Returns a 32 bit (4 bytes) big-endian flating point number.
|
|
348
|
+
* @returns {number}
|
|
349
|
+
*/
|
|
350
|
+
readFloat() {
|
|
351
|
+
this.doReadAssertions(4);
|
|
352
|
+
return this.readBuffer.readFloatBE(this.addOffset(4));
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Writes a 32 bit (4 bytes) big-endian floating point number.
|
|
356
|
+
* @param {number} v
|
|
357
|
+
*/
|
|
358
|
+
writeFloat(v) {
|
|
359
|
+
this.doWriteAssertions(v, -34028234663852886e22, 34028234663852886e22);
|
|
360
|
+
this.ensureCapacity(4);
|
|
361
|
+
this.writeBuffer.writeFloatBE(v, this.writeIndex);
|
|
362
|
+
this.writeIndex += 4;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Returns a 32 bit (4 bytes) big-endian flating point number.
|
|
366
|
+
* @returns {number}
|
|
367
|
+
*/
|
|
368
|
+
readFloatLE() {
|
|
369
|
+
this.doReadAssertions(4);
|
|
370
|
+
return this.readBuffer.readFloatLE(this.addOffset(4));
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Writes a 32 bit (4 bytes) little-endian floating point number.
|
|
374
|
+
* @param {number} v
|
|
375
|
+
*/
|
|
376
|
+
writeFloatLE(v) {
|
|
377
|
+
this.doWriteAssertions(v, -34028234663852886e22, 34028234663852886e22);
|
|
378
|
+
this.ensureCapacity(4);
|
|
379
|
+
this.writeBuffer.writeFloatLE(v, this.writeIndex);
|
|
380
|
+
this.writeIndex += 4;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Returns a 64 bit (8 bytes) big-endian flating point number.
|
|
384
|
+
* @returns {number}
|
|
385
|
+
*/
|
|
386
|
+
readDouble() {
|
|
387
|
+
this.doReadAssertions(8);
|
|
388
|
+
return this.readBuffer.readDoubleBE(this.addOffset(8));
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Writes a 64 bit (8 bytes) big-endian floating point number.
|
|
392
|
+
* @param {number} v
|
|
393
|
+
*/
|
|
394
|
+
writeDouble(v) {
|
|
395
|
+
this.doWriteAssertions(v, -17976931348623157e292, 17976931348623157e292);
|
|
396
|
+
this.ensureCapacity(8);
|
|
397
|
+
this.writeBuffer.writeDoubleBE(v, this.writeIndex);
|
|
398
|
+
this.writeIndex += 8;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Returns a 64 bit (8 bytes) little-endian flating point number.
|
|
402
|
+
* @returns {number}
|
|
403
|
+
*/
|
|
404
|
+
readDoubleLE() {
|
|
405
|
+
this.doReadAssertions(8);
|
|
406
|
+
return this.readBuffer.readDoubleLE(this.addOffset(8));
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Writes a 64 bit (8 bytes) little-endian floating point number.
|
|
410
|
+
* @param {number} v
|
|
411
|
+
*/
|
|
412
|
+
writeDoubleLE(v) {
|
|
413
|
+
this.doWriteAssertions(v, -17976931348623157e292, 17976931348623157e292);
|
|
414
|
+
this.ensureCapacity(8);
|
|
415
|
+
this.writeBuffer.writeDoubleLE(v, this.writeIndex);
|
|
416
|
+
this.writeIndex += 8;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Returns a 64 bit (8 bytes) signed big-endian number.
|
|
420
|
+
* @returns {bigint}
|
|
421
|
+
*/
|
|
422
|
+
readLong() {
|
|
423
|
+
this.doReadAssertions(8);
|
|
424
|
+
return this.readBuffer.readBigInt64BE(this.addOffset(8));
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Writes a 64 bit (8 bytes) signed big-endian number.
|
|
428
|
+
* @param {bigint} v
|
|
429
|
+
*/
|
|
430
|
+
writeLong(v) {
|
|
431
|
+
this.ensureCapacity(8);
|
|
432
|
+
this.writeBuffer.writeBigInt64BE(v, this.writeIndex);
|
|
433
|
+
this.writeIndex += 8;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Returns a 64 bit (8 bytes) signed little-endian number.
|
|
437
|
+
* @returns {bigint}
|
|
438
|
+
*/
|
|
439
|
+
readLongLE() {
|
|
440
|
+
this.doReadAssertions(8);
|
|
441
|
+
return this.readBuffer.readBigInt64LE(this.addOffset(8));
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Writes a 64 bit (8 bytes) signed little-endian number.
|
|
445
|
+
* @param {bigint} v
|
|
446
|
+
*/
|
|
447
|
+
writeLongLE(v) {
|
|
448
|
+
this.ensureCapacity(8);
|
|
449
|
+
this.writeBuffer.writeBigInt64LE(v, this.writeIndex);
|
|
450
|
+
this.writeIndex += 8;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Returns a 64 bit (8 bytes) unsigned big-endian number.
|
|
454
|
+
* @returns {bigint}
|
|
455
|
+
*/
|
|
456
|
+
readUnsignedLong() {
|
|
457
|
+
this.doReadAssertions(8);
|
|
458
|
+
return this.readBuffer.readBigUInt64BE(this.addOffset(8));
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Writes a 64 bit (8 bytes) unsigned big-endian number.
|
|
462
|
+
* @param {bigint} v
|
|
463
|
+
*/
|
|
464
|
+
writeUnsignedLong(v) {
|
|
465
|
+
this.ensureCapacity(8);
|
|
466
|
+
this.writeBuffer.writeBigUInt64BE(v, this.writeIndex);
|
|
467
|
+
this.writeIndex += 8;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Returns a 64 bit (8 bytes) unsigned little-endian number.
|
|
471
|
+
* @returns {bigint}
|
|
472
|
+
*/
|
|
473
|
+
readUnsignedLongLE() {
|
|
474
|
+
this.doReadAssertions(8);
|
|
475
|
+
return this.readBuffer.readBigUInt64LE(this.addOffset(8));
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Writes a 64 bit (8 bytes) unsigned little-endian number.
|
|
479
|
+
* @param {bigint} v
|
|
480
|
+
*/
|
|
481
|
+
writeUnsignedLongLE(v) {
|
|
482
|
+
this.ensureCapacity(8);
|
|
483
|
+
this.writeBuffer.writeBigUInt64LE(v, this.writeIndex);
|
|
484
|
+
this.writeIndex += 8;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Reads a 32 bit (4 bytes) zigzag-encoded number.
|
|
488
|
+
* @returns {number}
|
|
489
|
+
*/
|
|
490
|
+
readVarInt() {
|
|
491
|
+
const raw = this.readUnsignedVarInt();
|
|
492
|
+
return raw >>> 1 ^ -(raw & 1);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Writes a 32 bit (4 bytes) zigzag-encoded number.
|
|
496
|
+
* @param {number} v
|
|
497
|
+
*/
|
|
498
|
+
writeVarInt(v) {
|
|
499
|
+
return this.writeUnsignedVarInt(v << 1 ^ v >> 31);
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Reads a 32 bit unsigned number.
|
|
503
|
+
* @returns {number}
|
|
504
|
+
*/
|
|
505
|
+
readUnsignedVarInt() {
|
|
506
|
+
const buf = this.readBuffer;
|
|
507
|
+
if (buf === null) assert.default.fail("Reading on empty buffer!");
|
|
508
|
+
const len = buf.byteLength;
|
|
509
|
+
let value = 0;
|
|
510
|
+
for (let i = 0; i <= 28; i += 7) {
|
|
511
|
+
if (this.readIndex >= len) throw new Error("No bytes left in buffer");
|
|
512
|
+
const b = buf[this.readIndex++];
|
|
513
|
+
value |= (b & 127) << i;
|
|
514
|
+
if ((b & 128) === 0) {
|
|
515
|
+
if (i === 28 && (b & 112) !== 0) throw new Error("VarInt overflows 32 bits!");
|
|
516
|
+
return value >>> 0;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
throw new Error("VarInt did not terminate after 5 bytes!");
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Writes a 32 bit unsigned number with variable-length.
|
|
523
|
+
* @param {number} v
|
|
524
|
+
*/
|
|
525
|
+
writeUnsignedVarInt(v) {
|
|
526
|
+
this.ensureCapacity(5);
|
|
527
|
+
const buf = this.writeBuffer;
|
|
528
|
+
let i = this.writeIndex;
|
|
529
|
+
while ((v & 4294967168) !== 0) {
|
|
530
|
+
buf[i++] = v & 127 | 128;
|
|
531
|
+
v >>>= 7;
|
|
532
|
+
}
|
|
533
|
+
buf[i++] = v & 127;
|
|
534
|
+
this.writeIndex = i;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Reads a 64 bit zigzag-encoded variable-length number.
|
|
538
|
+
* @returns {bigint}
|
|
539
|
+
*/
|
|
540
|
+
readVarLong() {
|
|
541
|
+
const raw = this.readUnsignedVarLong();
|
|
542
|
+
return raw >> 1n ^ -(raw & 1n);
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Writes a 64 bit unsigned zigzag-encoded number.
|
|
546
|
+
* @param {bigint} v
|
|
547
|
+
*/
|
|
548
|
+
writeVarLong(v) {
|
|
549
|
+
const n = BigInt.asIntN(64, v);
|
|
550
|
+
return this.writeUnsignedVarLong(n << 1n ^ n >> 63n);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Reads a 64 bit unsigned variable-length number.
|
|
554
|
+
* @returns {bigint}
|
|
555
|
+
*/
|
|
556
|
+
readUnsignedVarLong() {
|
|
557
|
+
const buf = this.readBuffer;
|
|
558
|
+
if (buf === null) throw new Error("Buffer is write only!");
|
|
559
|
+
const len = buf.byteLength;
|
|
560
|
+
let lo = 0;
|
|
561
|
+
let hi = 0;
|
|
562
|
+
for (let i = 0; i <= 63; i += 7) {
|
|
563
|
+
if (this.readIndex >= len) throw new Error("No bytes left in buffer");
|
|
564
|
+
const b = buf[this.readIndex++];
|
|
565
|
+
if (i < 28) lo |= (b & 127) << i;
|
|
566
|
+
else if (i === 28) {
|
|
567
|
+
lo = (lo | (b & 15) << 28) >>> 0;
|
|
568
|
+
hi = (b & 127) >>> 4;
|
|
569
|
+
} else hi |= (b & 127) << i - 32;
|
|
570
|
+
if ((b & 128) === 0) {
|
|
571
|
+
if (i === 63 && (b & 126) !== 0) throw new Error("VarLong overflows 64 bits!");
|
|
572
|
+
return BigInt(hi >>> 0) << 32n | BigInt(lo >>> 0);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
throw new Error("VarLong did not terminate after 10 bytes!");
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Writes a 64 bit unsigned variable-length number.
|
|
579
|
+
* @param {bigint} v
|
|
580
|
+
*/
|
|
581
|
+
writeUnsignedVarLong(v) {
|
|
582
|
+
this.ensureCapacity(10);
|
|
583
|
+
const buf = this.writeBuffer;
|
|
584
|
+
let i = this.writeIndex;
|
|
585
|
+
const u = BigInt.asUintN(64, v);
|
|
586
|
+
let lo = Number(u & 4294967295n) >>> 0;
|
|
587
|
+
let hi = Number(u >> 32n) >>> 0;
|
|
588
|
+
while (hi !== 0 || lo > 127) {
|
|
589
|
+
buf[i++] = lo & 127 | 128;
|
|
590
|
+
lo = (lo >>> 7 | hi << 25) >>> 0;
|
|
591
|
+
hi >>>= 7;
|
|
592
|
+
}
|
|
593
|
+
buf[i++] = lo;
|
|
594
|
+
this.writeIndex = i;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Ensures write buffer has enough capacity, grows if needed.
|
|
598
|
+
* @param {number} needed
|
|
599
|
+
*/
|
|
600
|
+
ensureCapacity(needed) {
|
|
601
|
+
const required = this.writeIndex + needed;
|
|
602
|
+
if (required > this.writeCapacity) {
|
|
603
|
+
const newCapacity = this.writeCapacity === 0 ? Math.max(256, required) : Math.max(required, this.writeCapacity << 1);
|
|
604
|
+
const newBuffer = Buffer.allocUnsafe(newCapacity);
|
|
605
|
+
if (this.writeBuffer !== null && this.writeIndex > 0) this.writeBuffer.copy(newBuffer, 0, 0, this.writeIndex);
|
|
606
|
+
this.writeBuffer = newBuffer;
|
|
607
|
+
this.writeCapacity = newCapacity;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Grows the write buffer so that at least `capacity` bytes can be written without any
|
|
612
|
+
* further allocation, and returns this stream.
|
|
613
|
+
*
|
|
614
|
+
* Pre-sizing skips the 256 -> 512 -> 1024 ... growth ladder, each step of which copies the
|
|
615
|
+
* whole payload; a 3 KB packet starting from the 256-byte floor performs five allocations
|
|
616
|
+
* and memcpy's 1.25x its own size before it is done.
|
|
617
|
+
* @param {number} capacity
|
|
618
|
+
*/
|
|
619
|
+
reserve(capacity) {
|
|
620
|
+
if (capacity > this.writeCapacity) {
|
|
621
|
+
const newBuffer = Buffer.allocUnsafe(capacity);
|
|
622
|
+
if (this.writeBuffer !== null && this.writeIndex > 0) this.writeBuffer.copy(newBuffer, 0, 0, this.writeIndex);
|
|
623
|
+
this.writeBuffer = newBuffer;
|
|
624
|
+
this.writeCapacity = capacity;
|
|
625
|
+
}
|
|
626
|
+
return this;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Rewinds the write cursor while keeping the allocated capacity, so a long-lived encoder
|
|
630
|
+
* reaches a steady state where it never allocates again. This is the intended way to reuse
|
|
631
|
+
* a stream for many packets.
|
|
632
|
+
*
|
|
633
|
+
* Note the aliasing contract, which it shares with {@link clear} and {@link reuse}: any
|
|
634
|
+
* buffer previously handed out by {@link getWriteBuffer} is a *view* over this stream's
|
|
635
|
+
* memory and is invalidated by this call. Use {@link copyOut} or {@link copyInto} for
|
|
636
|
+
* output you intend to keep.
|
|
637
|
+
*/
|
|
638
|
+
resetWrite() {
|
|
639
|
+
this.writeIndex = 0;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Returns the encoded bytes as an exactly-sized, standalone Buffer.
|
|
643
|
+
*
|
|
644
|
+
* Unlike {@link getWriteBuffer} the result does not alias this stream, so it survives
|
|
645
|
+
* {@link resetWrite}, and it does not pin a pool chunk: because `Buffer.allocUnsafe` is
|
|
646
|
+
* pool-backed (`Buffer.poolSize` is 64 KB on current Node), holding on to a handful of
|
|
647
|
+
* small slices from {@link getWriteBuffer} can keep megabytes alive.
|
|
648
|
+
* @returns {Buffer}
|
|
649
|
+
*/
|
|
650
|
+
copyOut() {
|
|
651
|
+
const out = Buffer.allocUnsafeSlow(this.writeIndex);
|
|
652
|
+
if (this.writeIndex > 0) this.writeBuffer.copy(out, 0, 0, this.writeIndex);
|
|
653
|
+
return out;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Copies the encoded bytes into a caller-owned buffer at `offset` and returns the offset
|
|
657
|
+
* just past them. Lets many packets be encoded into one arena with no per-packet
|
|
658
|
+
* allocation at all.
|
|
659
|
+
* @param {Buffer} target
|
|
660
|
+
* @param {number} offset
|
|
661
|
+
* @returns {number} the new offset
|
|
662
|
+
*/
|
|
663
|
+
copyInto(target, offset = 0) {
|
|
664
|
+
if (this.writeIndex > 0) this.writeBuffer.copy(target, offset, 0, this.writeIndex);
|
|
665
|
+
return offset + this.writeIndex;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Increases the write offset by the given length.
|
|
669
|
+
* @param {number} length
|
|
670
|
+
*/
|
|
671
|
+
addOffset(length) {
|
|
672
|
+
return (this.readIndex += length) - length;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Returns whatever or not the read offset is at end of line.
|
|
676
|
+
* @returns {number}
|
|
677
|
+
*/
|
|
678
|
+
feof() {
|
|
679
|
+
const buf = this.readBuffer;
|
|
680
|
+
if (buf === null) throw new Error("Buffer is write only!");
|
|
681
|
+
return this.readIndex >= buf.byteLength;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Reads the remaining bytes and returns the buffer slice.
|
|
685
|
+
* @returns {Buffer}
|
|
686
|
+
*/
|
|
687
|
+
readRemaining() {
|
|
688
|
+
if (!this.readBuffer) throw new Error("Buffer is write only!");
|
|
689
|
+
const buf = this.readBuffer.subarray(this.readIndex);
|
|
690
|
+
this.readIndex = this.readBuffer.byteLength;
|
|
691
|
+
return buf;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Skips len bytes on the buffer.
|
|
695
|
+
* @param {number} len
|
|
696
|
+
*/
|
|
697
|
+
skip(len) {
|
|
698
|
+
(0, assert.default)(Number.isInteger(len), "Cannot skip a float amount of bytes");
|
|
699
|
+
this.readIndex += len;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Returns the encoded buffer.
|
|
703
|
+
*
|
|
704
|
+
* Beware: when a read buffer is present this returns *that*, discarding everything
|
|
705
|
+
* written. On a stream used for both reading and writing it never returns your output.
|
|
706
|
+
* @returns {Buffer}
|
|
707
|
+
* @deprecated See {@link getReadBuffer} and {@link getWriteBuffer}.
|
|
708
|
+
*/
|
|
709
|
+
getBuffer() {
|
|
710
|
+
return this.readBuffer !== null ? this.readBuffer : this.writeBuffer.subarray(0, this.writeIndex);
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Returns the read buffer if available.
|
|
714
|
+
* @returns {Buffer}
|
|
715
|
+
*/
|
|
716
|
+
getReadBuffer() {
|
|
717
|
+
return this.readBuffer;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Returns the encoded bytes as a *view* over this stream's internal buffer.
|
|
721
|
+
*
|
|
722
|
+
* The view is only valid until the next write: {@link resetWrite}, {@link clear} and
|
|
723
|
+
* {@link reuse} all rewind the cursor without reallocating, so a previously returned
|
|
724
|
+
* buffer is silently overwritten by the next packet. If you queue the result - a send
|
|
725
|
+
* queue, a resend window - use {@link copyOut} or {@link copyInto} instead.
|
|
726
|
+
*
|
|
727
|
+
* It also keeps the whole pooled 64 KB chunk it was carved from alive; retaining a
|
|
728
|
+
* scattered handful of small packets this way can pin megabytes.
|
|
729
|
+
* @returns {Buffer}
|
|
730
|
+
*/
|
|
731
|
+
getWriteBuffer() {
|
|
732
|
+
return this.writeBuffer.subarray(0, this.writeIndex);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Sets the buffer for reading.
|
|
736
|
+
* make sure to reset the reading index!
|
|
737
|
+
* @param buf - The new Buffer.
|
|
738
|
+
* @deprecated See {@link setReadBuffer} and {@link setWriteBuffer}.
|
|
739
|
+
*/
|
|
740
|
+
setBuffer(buf) {
|
|
741
|
+
this.readBuffer = buf;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Sets the buffer for reading.
|
|
745
|
+
* @param buf - The new Buffer.
|
|
746
|
+
* @param rIndex - The new read index (default: 0, pass -1 to keep current).
|
|
747
|
+
*/
|
|
748
|
+
setReadBuffer(buf, rIndex = 0) {
|
|
749
|
+
this.readBuffer = buf;
|
|
750
|
+
if (rIndex >= 0) this.readIndex = rIndex;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Sets the buffer for writing.
|
|
754
|
+
* @param buf - The new Buffer.
|
|
755
|
+
* @param wIndex - The new write index (default: 0, pass -1 to keep current).
|
|
756
|
+
*/
|
|
757
|
+
setWriteBuffer(buf, wIndex = 0) {
|
|
758
|
+
this.writeBuffer = buf;
|
|
759
|
+
if (wIndex >= 0) this.writeIndex = wIndex;
|
|
760
|
+
this.writeCapacity = buf.byteLength;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Clears the whole BinaryStream instance.
|
|
764
|
+
*
|
|
765
|
+
* The write buffer and its capacity are kept, so any view previously returned by
|
|
766
|
+
* {@link getWriteBuffer} is invalidated. See {@link resetWrite}.
|
|
767
|
+
*/
|
|
768
|
+
clear() {
|
|
769
|
+
this.readBuffer = null;
|
|
770
|
+
this.readIndex = 0;
|
|
771
|
+
this.writeIndex = 0;
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Conventional method to reuse the stream
|
|
775
|
+
* without having to create a new BinaryStream instance.
|
|
776
|
+
*
|
|
777
|
+
* The write buffer and its capacity are kept, so any view previously returned by
|
|
778
|
+
* {@link getWriteBuffer} is invalidated. See {@link resetWrite}.
|
|
779
|
+
* @param buf - The new buffer instance.
|
|
780
|
+
*/
|
|
781
|
+
reuse(buf) {
|
|
782
|
+
this.readBuffer = buf;
|
|
783
|
+
this.readIndex = 0;
|
|
784
|
+
this.writeIndex = 0;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Sets the reading index.
|
|
788
|
+
* @param index - The new read index.
|
|
789
|
+
*/
|
|
790
|
+
setReadIndex(index) {
|
|
791
|
+
(0, assert.default)(index >= 0, "Index must be non-negative");
|
|
792
|
+
this.readIndex = index;
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Sets the new writing index.
|
|
796
|
+
* @param index - The new write index.
|
|
797
|
+
*/
|
|
798
|
+
setWriteIndex(index) {
|
|
799
|
+
(0, assert.default)(index >= 0, "Index must be non-negative");
|
|
800
|
+
this.writeIndex = index;
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Retuns the read index.
|
|
804
|
+
* @returns {number}
|
|
805
|
+
*/
|
|
806
|
+
getReadIndex() {
|
|
807
|
+
return this.readIndex;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Returns the write index.
|
|
811
|
+
* @returns {number}
|
|
812
|
+
*/
|
|
813
|
+
getWriteIndex() {
|
|
814
|
+
return this.writeIndex;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Do read assertions, check if the read buffer is null.
|
|
818
|
+
* @param {number} byteLength
|
|
819
|
+
*/
|
|
820
|
+
doReadAssertions(byteLength) {
|
|
821
|
+
const buf = this.readBuffer;
|
|
822
|
+
if (buf === null) assert.default.fail("Cannot read without buffer data!");
|
|
823
|
+
if (this.readIndex + byteLength > buf.byteLength) assert.default.fail(`Cannot read ${byteLength} byte(s) at offset ${this.readIndex}: only ${Math.max(0, buf.byteLength - this.readIndex)} left in buffer`);
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Do read assertions, check if the read buffer is null.
|
|
827
|
+
* @param {number|bigint} num
|
|
828
|
+
* @param {number|bigint} minVal
|
|
829
|
+
* @param {number|bigint} maxVal
|
|
830
|
+
*/
|
|
831
|
+
doWriteAssertions(num, minVal, maxVal) {
|
|
832
|
+
if (!(num >= minVal && num <= maxVal)) assert.default.fail(`Value out of bounds: value=${num}, min=${minVal}, max=${maxVal}`);
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
//#endregion
|
|
836
|
+
exports.BinaryStream = BinaryStream;
|
|
837
|
+
exports.default = BinaryStream;
|
|
838
|
+
|
|
839
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmluYXJ5U3RyZWFtLmNqcy5janMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL0JpbmFyeVN0cmVhbS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5cbi8qKlxuICogQSBoaWdoLXBlcmZvcm1hbmNlIGJpbmFyeSBzdHJlYW0gZm9yIHJlYWRpbmcgYW5kIHdyaXRpbmcgYmluYXJ5IGRhdGEuXG4gKlxuICogVW5saWtlIE5vZGUuanMgbmF0aXZlIGJ1ZmZlcnMgd2hpY2ggaGF2ZSBmaXhlZCBzaXplLCBCaW5hcnlTdHJlYW0gdXNlcyBkeW5hbWljXG4gKiBidWZmZXJzIHRoYXQgZ3JvdyBhdXRvbWF0aWNhbGx5IGR1cmluZyB3cml0ZSBvcGVyYXRpb25zLiBUaGlzIGVsaW1pbmF0ZXMgdGhlIG5lZWRcbiAqIGZvciBtYW51YWwgcmVzaXppbmcgb3IgaW5lZmZpY2llbnQgYEJ1ZmZlci5jb25jYXQoKWAgY2FsbHMuXG4gKlxuICogQGV4YW1wbGUgUmVhZGluZyBkYXRhXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBzdHJlYW0gPSBuZXcgQmluYXJ5U3RyZWFtKGJ1ZmZlcik7XG4gKiBjb25zdCB2YWx1ZSA9IHN0cmVhbS5yZWFkSW50KCk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZSBXcml0aW5nIGRhdGFcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHN0cmVhbSA9IG5ldyBCaW5hcnlTdHJlYW0oKTtcbiAqIHN0cmVhbS53cml0ZUludCg0Mik7XG4gKiBzdHJlYW0ud3JpdGUoQnVmZmVyLmZyb20oJ0hlbGxvJykpOyAgLy8gQnVmZmVyIGdyb3dzIGF1dG9tYXRpY2FsbHlcbiAqIGNvbnN0IGJ1ZmZlciA9IHN0cmVhbS5nZXRXcml0ZUJ1ZmZlcigpO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGUgRW5jb2RpbmcgbWFueSBwYWNrZXRzIHdpdGhvdXQgYWxsb2NhdGluZ1xuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3Qgc3RyZWFtID0gbmV3IEJpbmFyeVN0cmVhbSh1bmRlZmluZWQsIDAsIDQwOTYpO1xuICogZm9yIChjb25zdCBwYWNrZXQgb2YgcXVldWUpIHtcbiAqICAgICBzdHJlYW0ucmVzZXRXcml0ZSgpO1xuICogICAgIHBhY2tldC5lbmNvZGUoc3RyZWFtKTtcbiAqICAgICBvZmZzZXQgPSBzdHJlYW0uY29weUludG8oYXJlbmEsIG9mZnNldCk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIEJpbmFyeVN0cmVhbSB7XG4gICAgcHJpdmF0ZSB3cml0ZUJ1ZmZlcjogQnVmZmVyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWFkQnVmZmVyOiBCdWZmZXIgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIHJlYWRJbmRleDogbnVtYmVyO1xuICAgIHByaXZhdGUgd3JpdGVJbmRleCA9IDA7XG4gICAgcHJpdmF0ZSB3cml0ZUNhcGFjaXR5ID0gMDtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQmluYXJ5U3RyZWFtIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSB7QnVmZmVyfG51bGx8dW5kZWZpbmVkfSBidWZmZXIgLSBUaGUgYXJyYXkgb3IgQnVmZmVyIGNvbnRhaW5pbmcgYmluYXJ5IGRhdGEuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCAtIFRoZSBpbml0aWFsIHBvaW50ZXIgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGluaXRpYWxDYXBhY2l0eSAtIFByZS1hbGxvY2F0ZXMgdGhlIHdyaXRlIGJ1ZmZlciB0byB0aGlzIHNpemUuIFVzZSBpdCB3aGVuXG4gICAgICogdGhlIGVuY29kZWQgc2l6ZSBpcyBrbm93biB1cCBmcm9udDogaXQgc2tpcHMgdGhlIDI1NiAtPiA1MTIgLT4gMTAyNCAuLi4gZ3Jvd3RoIGxhZGRlciwgYW5kXG4gICAgICogd2l0aCB7QGxpbmsgcmVzZXRXcml0ZX0gaXQgbGV0cyBhIGxvbmctbGl2ZWQgZW5jb2RlciBydW4gd2l0aG91dCBhbGxvY2F0aW5nIGF0IGFsbC5cbiAgICAgKi9cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoYnVmZmVyPzogQnVmZmVyLCBvZmZzZXQ6IG51bWJlciA9IDAsIGluaXRpYWxDYXBhY2l0eTogbnVtYmVyID0gMCkge1xuICAgICAgICB0aGlzLnJlYWRCdWZmZXIgPSBidWZmZXIgPz8gbnVsbDsgLy8gS2VlcCB0aGlzIGluc3RhbmNlIGZvciByZWFkaW5nXG4gICAgICAgIHRoaXMucmVhZEluZGV4ID0gb2Zmc2V0O1xuICAgICAgICBpZiAoaW5pdGlhbENhcGFjaXR5ID4gMCkge1xuICAgICAgICAgICAgdGhpcy5yZXNlcnZlKGluaXRpYWxDYXBhY2l0eSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIHNsaWNlIG9mIGJ1ZmZlciBieSB0aGUgZ2l2ZW4gbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZChsZW46IG51bWJlcik6IEJ1ZmZlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyhsZW4pO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5zdWJhcnJheSh0aGlzLnJlYWRJbmRleCwgKHRoaXMucmVhZEluZGV4ICs9IGxlbikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGVuZHMgYSBidWZmZXIgdG8gdGhlIG1haW4gYnVmZmVyLlxuICAgICAqIEBwYXJhbSB7QnVmZmVyfFVpbnQ4QXJyYXl9IGJ1ZlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZShidWY6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbGVuID0gYnVmLmJ5dGVMZW5ndGg7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkobGVuKTtcbiAgICAgICAgLy8gVGhpcyB1c2VkIHRvIGNhbGwgYGJ1Zi5jb3B5KC4uLilgLCB3aGljaCBvbmx5IGV4aXN0cyBvbiBCdWZmZXIsIHNvIHBhc3NpbmcgdGhlIHBsYWluXG4gICAgICAgIC8vIFVpbnQ4QXJyYXkgdGhpcyBzaWduYXR1cmUgYWR2ZXJ0aXNlcyB0aHJldyBgVHlwZUVycm9yOiBidWYuY29weSBpcyBub3QgYSBmdW5jdGlvbmAuXG4gICAgICAgIC8vIGBzZXRgIGFjY2VwdHMgYm90aCwgaXMgc3BlYy1yZXF1aXJlZCB0byBoYW5kbGUgb3ZlcmxhcHBpbmcgcmFuZ2VzLCBhbmQgaXMgY2hlYXBlclxuICAgICAgICAvLyBmb3IgdGhlIHNtYWxsIHBheWxvYWRzIChVVUlEcywgc2hvcnQgYmxvYnMpIHRoYXQgZG9taW5hdGUgcGFja2V0IGVuY29kaW5nLlxuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIS5zZXQoYnVmLCB0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggKz0gbGVuO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlYWRzIGFuIHVuc2lnbmVkIGJ5dGUgKDAgdG8gMjU1KS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkQnl0ZSgpOiBudW1iZXIge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoMSk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhW3RoaXMucmVhZEluZGV4KytdITtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYW4gdW5zaWduZWQgYnl0ZSAoMCB0byAyNTUpLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlQnl0ZSh2OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgxKTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gdiAmIDB4ZmY7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSBzaWduZWQgYnl0ZSAoLTEyOCB0byAxMjcpLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRTaWduZWRCeXRlKCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucygxKTtcbiAgICAgICAgcmV0dXJuICh0aGlzLnJlYWRCdWZmZXIhW3RoaXMucmVhZEluZGV4KytdISA8PCAyNCkgPj4gMjQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGVzIGEgc2lnbmVkIGJ5dGUgKC0xMjggdG8gMTI3KS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZVNpZ25lZEJ5dGUodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoMSk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhW3RoaXMud3JpdGVJbmRleCsrXSA9ICh2IDwgMCA/IDB4ZmYgKyB2ICsgMSA6IHYpICYgMHhmZjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIGJvb2xlYW4gKHRydWUgb3IgZmFsc2UpLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkQm9vbGVhbigpOiBib29sZWFuIHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIVt0aGlzLnJlYWRJbmRleCsrXSAhPT0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSBib29sZWFuICh0cnVlIG9yIGZhbHNlKS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVCb29sZWFuKHY6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgxKTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gdiA/IDEgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlYWRzIGEgMTYgYml0ICgyIGJ5dGVzKSBzaWduZWQgYmlnLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFNob3J0KCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucygyKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZEludDE2QkUodGhpcy5hZGRPZmZzZXQoMikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDE2IGJpdCAoMiBieXRlcykgc2lnbmVkIGJpZy1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlU2hvcnQodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZG9Xcml0ZUFzc2VydGlvbnModiwgLTMyXzc2OCwgMzJfNzY3KTtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgyKTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4gOCkgJiAweGZmO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSB2ICYgMHhmZjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIDE2IGJpdCAoMiBieXRlcykgc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRTaG9ydExFKCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucygyKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZEludDE2TEUodGhpcy5hZGRPZmZzZXQoMikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDE2IGJpdCAoMiBieXRlcykgc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlU2hvcnRMRSh2OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kb1dyaXRlQXNzZXJ0aW9ucyh2LCAtMzJfNzY4LCAzMl83NjcpO1xuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDIpO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSB2ICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4gOCkgJiAweGZmO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlYWRzIGEgMTYgYml0ICgyIGJ5dGVzKSB1bnNpZ25lZCBiaWctZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkVW5zaWduZWRTaG9ydCgpOiBudW1iZXIge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoMik7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhLnJlYWRVSW50MTZCRSh0aGlzLmFkZE9mZnNldCgyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGVzIGEgMTYgYml0ICgyIGJ5dGVzKSB1bnNpZ25lZCBiaWctZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZVVuc2lnbmVkU2hvcnQodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZG9Xcml0ZUFzc2VydGlvbnModiwgMCwgNjVfNTM1KTtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgyKTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gdiAmIDB4ZmY7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSAxNiBiaXQgKDIgYnl0ZXMpIHVuc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRVbnNpZ25lZFNob3J0TEUoKTogbnVtYmVyIHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDIpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5yZWFkVUludDE2TEUodGhpcy5hZGRPZmZzZXQoMikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDE2IGJpdCAoMiBieXRlcykgdW5zaWduZWQgbGl0dGxlLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVVbnNpZ25lZFNob3J0TEUodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZG9Xcml0ZUFzc2VydGlvbnModiwgMCwgNjVfNTM1KTtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgyKTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gdiAmIDB4ZmY7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhW3RoaXMud3JpdGVJbmRleCsrXSA9ICh2ID4+PiA4KSAmIDB4ZmY7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSAyNCBiaXQgKDMgYnl0ZXMpIHNpZ25lZCBiaWctZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkVHJpYWQoKTogbnVtYmVyIHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDMpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5yZWFkSW50QkUodGhpcy5hZGRPZmZzZXQoMyksIDMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDI0IGJpdCAoMyBieXRlcykgc2lnbmVkIGJpZy1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVHJpYWQodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZG9Xcml0ZUFzc2VydGlvbnModiwgLThfMzg4XzYwOCwgOF8zODhfNjA3KTtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgzKTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4gMTYpICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4gOCkgJiAweGZmO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSB2ICYgMHhmZjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIDI0IGJpdCAoMyBieXRlcykgbGl0dGxlLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFRyaWFkTEUoKTogbnVtYmVyIHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDMpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5yZWFkSW50TEUodGhpcy5hZGRPZmZzZXQoMyksIDMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDI0IGJpdCAoMyBieXRlcykgc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVHJpYWRMRSh2OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kb1dyaXRlQXNzZXJ0aW9ucyh2LCAtOF8zODhfNjA4LCA4XzM4OF82MDcpO1xuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDMpO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSB2ICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4gOCkgJiAweGZmO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSAodiA+PiAxNikgJiAweGZmO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlYWRzIGEgMjQgYml0ICgzIGJ5dGVzKSB1bnNpZ25lZCBiaWctZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkVW5zaWduZWRUcmlhZCgpOiBudW1iZXIge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoMyk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhLnJlYWRVSW50QkUodGhpcy5hZGRPZmZzZXQoMyksIDMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDI0IGJpdCAoMyBieXRlcykgdW5zaWduZWQgYmlnLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVVbnNpZ25lZFRyaWFkKHY6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRvV3JpdGVBc3NlcnRpb25zKHYsIDAsIDE2Xzc3N18yMTUpO1xuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDMpO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSAodiA+Pj4gMTYpICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gdiAmIDB4ZmY7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSAyNCBiaXQgKDMgYnl0ZXMpIHVuc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRVbnNpZ25lZFRyaWFkTEUoKTogbnVtYmVyIHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDMpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5yZWFkVUludExFKHRoaXMuYWRkT2Zmc2V0KDMpLCAzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSAyNCBiaXQgKDMgYnl0ZXMpIHVuc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVW5zaWduZWRUcmlhZExFKHY6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRvV3JpdGVBc3NlcnRpb25zKHYsIDAsIDE2Xzc3N18yMTUpO1xuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDMpO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIVt0aGlzLndyaXRlSW5kZXgrK10gPSB2ICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciFbdGhpcy53cml0ZUluZGV4KytdID0gKHYgPj4+IDE2KSAmIDB4ZmY7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSAzMiBiaXQgKDQgYnl0ZXMpIGJpZy1lbmRpYW4gc2lnbmVkIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkSW50KCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyg0KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZEludDMyQkUodGhpcy5hZGRPZmZzZXQoNCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDMyIGJpdCAoNCBieXRlcykgYmlnLWVuZGlhbiBzaWduZWQgbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlSW50KHY6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRvV3JpdGVBc3NlcnRpb25zKHYsIC0yXzE0N180ODNfNjQ4LCAyXzE0N180ODNfNjQ3KTtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSg0KTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciEud3JpdGVJbnQzMkJFKHYsIHRoaXMud3JpdGVJbmRleCk7XG4gICAgICAgIHRoaXMud3JpdGVJbmRleCArPSA0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlYWRzIGEgMzIgYml0ICg0IGJ5dGVzKSBzaWduZWQgbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRJbnRMRSgpOiBudW1iZXIge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoNCk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhLnJlYWRJbnRMRSh0aGlzLmFkZE9mZnNldCg0KSwgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGVzIGEgMzIgYml0ICg0IGJ5dGVzKSBsaXR0bGUtZW5kaWFuIHNpZ25lZCBudW1iZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVJbnRMRSh2OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5kb1dyaXRlQXNzZXJ0aW9ucyh2LCAtMl8xNDdfNDgzXzY0OCwgMl8xNDdfNDgzXzY0Nyk7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoNCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlSW50MzJMRSh2LCB0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIDMyIGJpdCAoNCBieXRlcykgYmlnLWVuZGlhbiB1bnNpZ25lZCBudW1iZXIuXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFVuc2lnbmVkSW50KCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyg0KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZFVJbnQzMkJFKHRoaXMuYWRkT2Zmc2V0KDQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSAzMiBiaXQgKDQgYnl0ZXMpIGJpZy1lbmRpYW4gdW5zaWduZWQgbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVW5zaWduZWRJbnQodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZG9Xcml0ZUFzc2VydGlvbnModiwgMCwgNF8yOTRfOTY3XzI5NSk7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoNCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlVUludDMyQkUodiwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ICs9IDQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSAzMiBiaXQgKDQgYnl0ZXMpIGxpdHRsZS1lbmRpYW4gdW5zaWduZWQgbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRVbnNpZ25lZEludExFKCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyg0KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZFVJbnQzMkxFKHRoaXMuYWRkT2Zmc2V0KDQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSAzMiBiaXQgKDQgYnl0ZXMpIGxpdHRsZS1lbmRpYW4gdW5zaWduZWQgbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVW5zaWduZWRJbnRMRSh2OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kb1dyaXRlQXNzZXJ0aW9ucyh2LCAwLCA0XzI5NF85NjdfMjk1KTtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSg0KTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciEud3JpdGVVSW50MzJMRSh2LCB0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgMzIgYml0ICg0IGJ5dGVzKSBiaWctZW5kaWFuIGZsYXRpbmcgcG9pbnQgbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRGbG9hdCgpOiBudW1iZXIge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoNCk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhLnJlYWRGbG9hdEJFKHRoaXMuYWRkT2Zmc2V0KDQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSAzMiBiaXQgKDQgYnl0ZXMpIGJpZy1lbmRpYW4gZmxvYXRpbmcgcG9pbnQgbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlRmxvYXQodjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZG9Xcml0ZUFzc2VydGlvbnModiwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUzOCwgKzMuNDAyODIzNDY2Mzg1Mjg4NmUzOCk7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoNCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlRmxvYXRCRSh2LCB0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggKz0gNDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgMzIgYml0ICg0IGJ5dGVzKSBiaWctZW5kaWFuIGZsYXRpbmcgcG9pbnQgbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRGbG9hdExFKCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyg0KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZEZsb2F0TEUodGhpcy5hZGRPZmZzZXQoNCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDMyIGJpdCAoNCBieXRlcykgbGl0dGxlLWVuZGlhbiBmbG9hdGluZyBwb2ludCBudW1iZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVGbG9hdExFKHY6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRvV3JpdGVBc3NlcnRpb25zKHYsIC0zLjQwMjgyMzQ2NjM4NTI4ODZlMzgsICszLjQwMjgyMzQ2NjM4NTI4ODZlMzgpO1xuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDQpO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIS53cml0ZUZsb2F0TEUodiwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ICs9IDQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIDY0IGJpdCAoOCBieXRlcykgYmlnLWVuZGlhbiBmbGF0aW5nIHBvaW50IG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkRG91YmxlKCk6IG51bWJlciB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyg4KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZERvdWJsZUJFKHRoaXMuYWRkT2Zmc2V0KDgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSA2NCBiaXQgKDggYnl0ZXMpIGJpZy1lbmRpYW4gZmxvYXRpbmcgcG9pbnQgbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlRG91YmxlKHY6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRvV3JpdGVBc3NlcnRpb25zKHYsIC0xLjc5NzY5MzEzNDg2MjMxNTdlMzA4LCArMS43OTc2OTMxMzQ4NjIzMTU3ZTMwOCk7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoOCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlRG91YmxlQkUodiwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ICs9IDg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIDY0IGJpdCAoOCBieXRlcykgbGl0dGxlLWVuZGlhbiBmbGF0aW5nIHBvaW50IG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkRG91YmxlTEUoKTogbnVtYmVyIHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDgpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5yZWFkRG91YmxlTEUodGhpcy5hZGRPZmZzZXQoOCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDY0IGJpdCAoOCBieXRlcykgbGl0dGxlLWVuZGlhbiBmbG9hdGluZyBwb2ludCBudW1iZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVEb3VibGVMRSh2OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kb1dyaXRlQXNzZXJ0aW9ucyh2LCAtMS43OTc2OTMxMzQ4NjIzMTU3ZTMwOCwgKzEuNzk3NjkzMTM0ODYyMzE1N2UzMDgpO1xuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDgpO1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyIS53cml0ZURvdWJsZUxFKHYsIHRoaXMud3JpdGVJbmRleCk7XG4gICAgICAgIHRoaXMud3JpdGVJbmRleCArPSA4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSA2NCBiaXQgKDggYnl0ZXMpIHNpZ25lZCBiaWctZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7YmlnaW50fVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkTG9uZygpOiBiaWdpbnQge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoOCk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhLnJlYWRCaWdJbnQ2NEJFKHRoaXMuYWRkT2Zmc2V0KDgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSA2NCBiaXQgKDggYnl0ZXMpIHNpZ25lZCBiaWctZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcGFyYW0ge2JpZ2ludH0gdlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZUxvbmcodjogYmlnaW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoOCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlQmlnSW50NjRCRSh2LCB0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggKz0gODtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgNjQgYml0ICg4IGJ5dGVzKSBzaWduZWQgbGl0dGxlLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHJldHVybnMge2JpZ2ludH1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZExvbmdMRSgpOiBiaWdpbnQge1xuICAgICAgICB0aGlzLmRvUmVhZEFzc2VydGlvbnMoOCk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIhLnJlYWRCaWdJbnQ2NExFKHRoaXMuYWRkT2Zmc2V0KDgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSA2NCBiaXQgKDggYnl0ZXMpIHNpZ25lZCBsaXR0bGUtZW5kaWFuIG51bWJlci5cbiAgICAgKiBAcGFyYW0ge2JpZ2ludH0gdlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZUxvbmdMRSh2OiBiaWdpbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSg4KTtcbiAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciEud3JpdGVCaWdJbnQ2NExFKHYsIHRoaXMud3JpdGVJbmRleCk7XG4gICAgICAgIHRoaXMud3JpdGVJbmRleCArPSA4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSA2NCBiaXQgKDggYnl0ZXMpIHVuc2lnbmVkIGJpZy1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtiaWdpbnR9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRVbnNpZ25lZExvbmcoKTogYmlnaW50IHtcbiAgICAgICAgdGhpcy5kb1JlYWRBc3NlcnRpb25zKDgpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyIS5yZWFkQmlnVUludDY0QkUodGhpcy5hZGRPZmZzZXQoOCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDY0IGJpdCAoOCBieXRlcykgdW5zaWduZWQgYmlnLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHBhcmFtIHtiaWdpbnR9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVVbnNpZ25lZExvbmcodjogYmlnaW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoOCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlQmlnVUludDY0QkUodiwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ICs9IDg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIDY0IGJpdCAoOCBieXRlcykgdW5zaWduZWQgbGl0dGxlLWVuZGlhbiBudW1iZXIuXG4gICAgICogQHJldHVybnMge2JpZ2ludH1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFVuc2lnbmVkTG9uZ0xFKCk6IGJpZ2ludCB7XG4gICAgICAgIHRoaXMuZG9SZWFkQXNzZXJ0aW9ucyg4KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZEJ1ZmZlciEucmVhZEJpZ1VJbnQ2NExFKHRoaXMuYWRkT2Zmc2V0KDgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSA2NCBiaXQgKDggYnl0ZXMpIHVuc2lnbmVkIGxpdHRsZS1lbmRpYW4gbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7YmlnaW50fSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVW5zaWduZWRMb25nTEUodjogYmlnaW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkoOCk7XG4gICAgICAgIHRoaXMud3JpdGVCdWZmZXIhLndyaXRlQmlnVUludDY0TEUodiwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ICs9IDg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZHMgYSAzMiBiaXQgKDQgYnl0ZXMpIHppZ3phZy1lbmNvZGVkIG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkVmFySW50KCk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IHJhdyA9IHRoaXMucmVhZFVuc2lnbmVkVmFySW50KCk7XG4gICAgICAgIC8vIFRoZSBwcmV2aW91cyBleHByZXNzaW9uIHdhcyBgKCgocmF3IDw8IDYzKSA+PiA2MykgXiByYXcpID4+IDEgXiAocmF3ICYgKDEgPDwgNjMpKWAsXG4gICAgICAgIC8vIGEgSmF2YSBwb3J0IHRoYXQgcmVsaWVkIG9uIEpTIHNoaWZ0IGNvdW50cyBiZWluZyB0YWtlbiBtb2QgMzIuIEl0IHdhcyB2ZXJpZmllZFxuICAgICAgICAvLyBjb3JyZWN0IG92ZXIgNy4yTSB2YWx1ZXMsIGJ1dCB0aGlzIGlzIHRoZSBzYW1lIGZ1bmN0aW9uIHdyaXR0ZW4gbGVnaWJseS5cbiAgICAgICAgcmV0dXJuIChyYXcgPj4+IDEpIF4gLShyYXcgJiAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYSAzMiBiaXQgKDQgYnl0ZXMpIHppZ3phZy1lbmNvZGVkIG51bWJlci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZVZhckludCh2OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gVGhlIGB2ID0gKHYgPDwgMzIpID4+IDMyYCB0aGF0IHVzZWQgdG8gc2l0IGhlcmUgd2FzIGEgbm8tb3A6IEpTIHNoaWZ0IGNvdW50cyBhcmVcbiAgICAgICAgLy8gdGFrZW4gbW9kIDMyLCBzbyBpdCBzaGlmdGVkIGJ5IDAuIFRoZSBgPDwgMWAgYmVsb3cgYWxyZWFkeSBjb2VyY2VzIHRvIGludDMyLlxuICAgICAgICByZXR1cm4gdGhpcy53cml0ZVVuc2lnbmVkVmFySW50KCh2IDw8IDEpIF4gKHYgPj4gMzEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIDMyIGJpdCB1bnNpZ25lZCBudW1iZXIuXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFVuc2lnbmVkVmFySW50KCk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IGJ1ZiA9IHRoaXMucmVhZEJ1ZmZlcjtcbiAgICAgICAgaWYgKGJ1ZiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgYXNzZXJ0LmZhaWwoJ1JlYWRpbmcgb24gZW1wdHkgYnVmZmVyIScpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxlbiA9IGJ1Zi5ieXRlTGVuZ3RoO1xuICAgICAgICBsZXQgdmFsdWUgPSAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8PSAyODsgaSArPSA3KSB7XG4gICAgICAgICAgICAvLyBBIG51bWVyaWMgY29tcGFyZSByYXRoZXIgdGhhbiBgdHlwZW9mIGJ1ZltpZHhdID09PSAndW5kZWZpbmVkJ2A6IHRoZSBsYXR0ZXIgaXMgYW5cbiAgICAgICAgICAgIC8vIG91dC1vZi1ib3VuZHMgZWxlbWVudCBsb2FkLCB3aGljaCBtYWtlcyBWOCBkaXNjYXJkIHRoZSBvcHRpbWl6ZWQgY29kZSBmb3IgdGhpc1xuICAgICAgICAgICAgLy8gZnVuY3Rpb24gdGhlIGZpcnN0IHRpbWUgYSBzdHJlYW0gaXMgcmVhZCB0byBpdHMgZW5kLlxuICAgICAgICAgICAgaWYgKHRoaXMucmVhZEluZGV4ID49IGxlbikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYnl0ZXMgbGVmdCBpbiBidWZmZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGIgPSBidWZbdGhpcy5yZWFkSW5kZXgrK10hO1xuICAgICAgICAgICAgdmFsdWUgfD0gKGIgJiAweDdmKSA8PCBpO1xuXG4gICAgICAgICAgICBpZiAoKGIgJiAweDgwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmIChpID09PSAyOCAmJiAoYiAmIDB4NzApICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEJpdHMgYWJvdmUgdGhlIDMybmQgdXNlZCB0byBiZSBzaGlmdGVkIG9mZiBhbmQgZGlzY2FyZGVkLCBzbyBhblxuICAgICAgICAgICAgICAgICAgICAvLyBvdmVyLWxvbmcgZW5jb2Rpbmcgc3VjaCBhcyBgZmYgZmYgZmYgZmYgN2ZgIHNpbGVudGx5IGRlY29kZWQgdG8gdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIHNhbWUgdmFsdWUgYXMgdGhlIGNhbm9uaWNhbCBgZmYgZmYgZmYgZmYgMGZgLlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ZhckludCBvdmVyZmxvd3MgMzIgYml0cyEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gYD4+PiAwYCBiZWNhdXNlIHRoZSBhY2N1bXVsYXRvciBhYm92ZSBpcyBpbnQzMjogd2l0aG91dCBpdCBldmVyeSB2YWx1ZVxuICAgICAgICAgICAgICAgIC8vIGZyb20gMl4zMSB1cCBjYW1lIGJhY2sgbmVnYXRpdmUsIHNvIHdyaXRlVW5zaWduZWRWYXJJbnQoMHhmZmZmZmZmZilcbiAgICAgICAgICAgICAgICAvLyByb3VuZC10cmlwcGVkIHRvIC0xLlxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZSA+Pj4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVmFySW50IGRpZCBub3QgdGVybWluYXRlIGFmdGVyIDUgYnl0ZXMhJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGVzIGEgMzIgYml0IHVuc2lnbmVkIG51bWJlciB3aXRoIHZhcmlhYmxlLWxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdlxuICAgICAqL1xuICAgIHB1YmxpYyB3cml0ZVVuc2lnbmVkVmFySW50KHY6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBPbmUgY2FwYWNpdHkgY2hlY2sgZm9yIHRoZSB3aG9sZSB2YXJpbnQgaW5zdGVhZCBvZiBvbmUgcGVyIGJ5dGUgKHZpYSB3cml0ZUJ5dGUpLFxuICAgICAgICAvLyB3aXRoIHRoZSBidWZmZXIgYW5kIGN1cnNvciBob2lzdGVkIGludG8gbG9jYWxzIHNvIGVhY2ggYnl0ZSBpcyBhIHBsYWluIHN0b3JlLlxuICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KDUpO1xuICAgICAgICBjb25zdCBidWYgPSB0aGlzLndyaXRlQnVmZmVyITtcbiAgICAgICAgbGV0IGkgPSB0aGlzLndyaXRlSW5kZXg7XG4gICAgICAgIHdoaWxlICgodiAmIDB4ZmZmZmZmODApICE9PSAwKSB7XG4gICAgICAgICAgICBidWZbaSsrXSA9ICh2ICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgdiA+Pj49IDc7XG4gICAgICAgIH1cbiAgICAgICAgYnVmW2krK10gPSB2ICYgMHg3ZjtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ID0gaTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyBhIDY0IGJpdCB6aWd6YWctZW5jb2RlZCB2YXJpYWJsZS1sZW5ndGggbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtiaWdpbnR9XG4gICAgICovXG4gICAgcHVibGljIHJlYWRWYXJMb25nKCk6IGJpZ2ludCB7XG4gICAgICAgIGNvbnN0IHJhdyA9IHRoaXMucmVhZFVuc2lnbmVkVmFyTG9uZygpO1xuICAgICAgICAvLyBUaGUgemlnemFnIHNpZ24gWE9SIHdhcyBtaXNzaW5nLCBzbyB0aGlzIHVzZWQgdG8gcmV0dXJuIGByYXcgPj4gMW5gOiBldmVyeSBuZWdhdGl2ZVxuICAgICAgICAvLyB2YWx1ZSBkZWNvZGVkIHdyb25nICgtMjBuIGNhbWUgYmFjayBhcyAxOW4sIC0xbiBhcyAwbikgYW5kIGFueXRoaW5nIGF0IG9yIGFib3ZlXG4gICAgICAgIC8vIDJeNTQgY29sbGFwc2VkIHRvIDBuLiBQb3NpdGl2ZSBzbWFsbCB2YWx1ZXMgd2VyZSB1bmFmZmVjdGVkLCB3aGljaCBpcyB3aHkgdGhlXG4gICAgICAgIC8vIHNoaXBwZWQgdGVzdCBzdWl0ZSBuZXZlciBjYXVnaHQgaXQuXG4gICAgICAgIHJldHVybiAocmF3ID4+IDFuKSBeIC0ocmF3ICYgMW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDY0IGJpdCB1bnNpZ25lZCB6aWd6YWctZW5jb2RlZCBudW1iZXIuXG4gICAgICogQHBhcmFtIHtiaWdpbnR9IHZcbiAgICAgKi9cbiAgICBwdWJsaWMgd3JpdGVWYXJMb25nKHY6IGJpZ2ludCkge1xuICAgICAgICBjb25zdCBuID0gQmlnSW50LmFzSW50Tig2NCwgdik7XG4gICAgICAgIHJldHVybiB0aGlzLndyaXRlVW5zaWduZWRWYXJMb25nKChuIDw8IDFuKSBeIChuID4+IDYzbikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlYWRzIGEgNjQgYml0IHVuc2lnbmVkIHZhcmlhYmxlLWxlbmd0aCBudW1iZXIuXG4gICAgICogQHJldHVybnMge2JpZ2ludH1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFVuc2lnbmVkVmFyTG9uZygpOiBiaWdpbnQge1xuICAgICAgICBjb25zdCBidWYgPSB0aGlzLnJlYWRCdWZmZXI7XG4gICAgICAgIGlmIChidWYgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQnVmZmVyIGlzIHdyaXRlIG9ubHkhJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbGVuID0gYnVmLmJ5dGVMZW5ndGg7XG4gICAgICAgIC8vIFRoZSBhY2N1bXVsYXRvciBpcyBrZXB0IGluIHR3byBpbnQzMiBoYWx2ZXMgYW5kIG1hdGVyaWFsaXNlZCBhcyBhIHNpbmdsZSBCaWdJbnQgYXRcbiAgICAgICAgLy8gdGhlIGVuZC4gVGhlIHByZXZpb3VzIHZlcnNpb24gYWxsb2NhdGVkIGZpdmUgQmlnSW50cyBwZXIgZGVjb2RlZCBieXRlXG4gICAgICAgIC8vIChCaWdJbnQoYiksIHRoZSBtYXNrLCBCaWdJbnQoaSksIHRoZSBzaGlmdCBhbmQgdGhlIG9yKS5cbiAgICAgICAgbGV0IGxvID0gMDtcbiAgICAgICAgbGV0IGhpID0gMDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gNjM7IGkgKz0gNykge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZEluZGV4ID49IGxlbikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYnl0ZXMgbGVmdCBpbiBidWZmZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGIgPSBidWZbdGhpcy5yZWFkSW5kZXgrK10hO1xuICAgICAgICAgICAgaWYgKGkgPCAyOCkge1xuICAgICAgICAgICAgICAgIGxvIHw9IChiICYgMHg3ZikgPDwgaTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaSA9PT0gMjgpIHtcbiAgICAgICAgICAgICAgICBsbyA9IChsbyB8ICgoYiAmIDB4MGYpIDw8IDI4KSkgPj4+IDA7XG4gICAgICAgICAgICAgICAgaGkgPSAoYiAmIDB4N2YpID4+PiA0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBoaSB8PSAoYiAmIDB4N2YpIDw8IChpIC0gMzIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoKGIgJiAweDgwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmIChpID09PSA2MyAmJiAoYiAmIDB4N2UpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVmFyTG9uZyBvdmVyZmxvd3MgNjQgYml0cyEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIChCaWdJbnQoaGkgPj4+IDApIDw8IDMybikgfCBCaWdJbnQobG8gPj4+IDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdWYXJMb25nIGRpZCBub3QgdGVybWluYXRlIGFmdGVyIDEwIGJ5dGVzIScpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBhIDY0IGJpdCB1bnNpZ25lZCB2YXJpYWJsZS1sZW5ndGggbnVtYmVyLlxuICAgICAqIEBwYXJhbSB7YmlnaW50fSB2XG4gICAgICovXG4gICAgcHVibGljIHdyaXRlVW5zaWduZWRWYXJMb25nKHY6IGJpZ2ludCkge1xuICAgICAgICAvLyBUaGUgdmFsdWUgaXMgc3BsaXQgaW50byB0d28gdWludDMyIGhhbHZlcyBvbmNlLCB0aGVuIHRoZSBzaGlmdC9tYXNrIGxvb3AgcnVuc1xuICAgICAgICAvLyBlbnRpcmVseSBpbiBpbnQzMiBzcGFjZS4gVGhlIHByZXZpb3VzIHZlcnNpb24gZGlkIHRocmVlIEJpZ0ludCBhbGxvY2F0aW9ucyBwbHVzIGFcbiAgICAgICAgLy8gTnVtYmVyKCkgY29udmVyc2lvbiBwZXIgZW1pdHRlZCBieXRlLCBhbmQgY29tcHV0ZWQgYHYgPj4gN25gIHR3aWNlIHBlciBieXRlLlxuICAgICAgICAvL1xuICAgICAgICAvLyBJdCB3YXMgYWxzbyB3cm9uZzogYE51bWJlcih2IHwgMHg4MG4pYCBjb252ZXJ0ZWQgdG8gYSBkb3VibGUgKmJlZm9yZSogd3JpdGVCeXRlJ3NcbiAgICAgICAgLy8gYCYgMHhmZmAgbWFzaywgc28gYWJvdmUgMl41NCB0aGUgbG93IGJpdHMgd2VyZSBhbHJlYWR5IHJvdW5kZWQgYXdheS5cbiAgICAgICAgLy8gd3JpdGVVbnNpZ25lZFZhckxvbmcoOTAwNzE5OTI1NDc0MTExOW4pIGVtaXR0ZWQgYSBsZWFkaW5nIDB4MDAgLSBhIHRlcm1pbmF0b3IgLVxuICAgICAgICAvLyBhbmQgdGhlIHZhbHVlIHJlYWQgYmFjayBhcyAwbi4gTmVnYXRpdmUgaW5wdXRzIGVtaXR0ZWQgdGVuIHVudGVybWluYXRlZCBieXRlcztcbiAgICAgICAgLy8gdGhleSBhcmUgbm93IHdlbGwtZGVmaW5lZCBhcyB0aGVpciB0d28ncyBjb21wbGVtZW50LCBtYXRjaGluZyBwcm90b2J1Zi5cbiAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSgxMCk7XG4gICAgICAgIGNvbnN0IGJ1ZiA9IHRoaXMud3JpdGVCdWZmZXIhO1xuICAgICAgICBsZXQgaSA9IHRoaXMud3JpdGVJbmRleDtcbiAgICAgICAgY29uc3QgdSA9IEJpZ0ludC5hc1VpbnROKDY0LCB2KTtcbiAgICAgICAgbGV0IGxvID0gTnVtYmVyKHUgJiAweGZmZmZmZmZmbikgPj4+IDA7XG4gICAgICAgIGxldCBoaSA9IE51bWJlcih1ID4+IDMybikgPj4+IDA7XG4gICAgICAgIHdoaWxlIChoaSAhPT0gMCB8fCBsbyA+IDB4N2YpIHtcbiAgICAgICAgICAgIGJ1ZltpKytdID0gKGxvICYgMHg3ZikgfCAweDgwO1xuICAgICAgICAgICAgbG8gPSAoKGxvID4+PiA3KSB8IChoaSA8PCAyNSkpID4+PiAwO1xuICAgICAgICAgICAgaGkgPj4+PSA3O1xuICAgICAgICB9XG4gICAgICAgIGJ1ZltpKytdID0gbG87XG4gICAgICAgIHRoaXMud3JpdGVJbmRleCA9IGk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5zdXJlcyB3cml0ZSBidWZmZXIgaGFzIGVub3VnaCBjYXBhY2l0eSwgZ3Jvd3MgaWYgbmVlZGVkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuZWVkZWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGVuc3VyZUNhcGFjaXR5KG5lZWRlZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJlcXVpcmVkID0gdGhpcy53cml0ZUluZGV4ICsgbmVlZGVkO1xuICAgICAgICBpZiAocmVxdWlyZWQgPiB0aGlzLndyaXRlQ2FwYWNpdHkpIHtcbiAgICAgICAgICAgIC8vIEluaXRpYWwgYWxsb2NhdGlvbiBvciBncm93dGhcbiAgICAgICAgICAgIGNvbnN0IG5ld0NhcGFjaXR5ID1cbiAgICAgICAgICAgICAgICB0aGlzLndyaXRlQ2FwYWNpdHkgPT09IDBcbiAgICAgICAgICAgICAgICAgICAgPyBNYXRoLm1heCgyNTYsIHJlcXVpcmVkKSAvLyBJbml0aWFsOiAyNTYgb3IgcmVxdWlyZWQgc2l6ZVxuICAgICAgICAgICAgICAgICAgICA6IE1hdGgubWF4KHJlcXVpcmVkLCB0aGlzLndyaXRlQ2FwYWNpdHkgPDwgMSk7IC8vIEdyb3d0aDogMnhcbiAgICAgICAgICAgIGNvbnN0IG5ld0J1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZShuZXdDYXBhY2l0eSk7XG5cbiAgICAgICAgICAgIC8vIENvcHkgZXhpc3RpbmcgZGF0YSBpZiBhbnlcbiAgICAgICAgICAgIGlmICh0aGlzLndyaXRlQnVmZmVyICE9PSBudWxsICYmIHRoaXMud3JpdGVJbmRleCA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLndyaXRlQnVmZmVyIS5jb3B5KG5ld0J1ZmZlciwgMCwgMCwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciA9IG5ld0J1ZmZlcjtcbiAgICAgICAgICAgIHRoaXMud3JpdGVDYXBhY2l0eSA9IG5ld0NhcGFjaXR5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR3Jvd3MgdGhlIHdyaXRlIGJ1ZmZlciBzbyB0aGF0IGF0IGxlYXN0IGBjYXBhY2l0eWAgYnl0ZXMgY2FuIGJlIHdyaXR0ZW4gd2l0aG91dCBhbnlcbiAgICAgKiBmdXJ0aGVyIGFsbG9jYXRpb24sIGFuZCByZXR1cm5zIHRoaXMgc3RyZWFtLlxuICAgICAqXG4gICAgICogUHJlLXNpemluZyBza2lwcyB0aGUgMjU2IC0+IDUxMiAtPiAxMDI0IC4uLiBncm93dGggbGFkZGVyLCBlYWNoIHN0ZXAgb2Ygd2hpY2ggY29waWVzIHRoZVxuICAgICAqIHdob2xlIHBheWxvYWQ7IGEgMyBLQiBwYWNrZXQgc3RhcnRpbmcgZnJvbSB0aGUgMjU2LWJ5dGUgZmxvb3IgcGVyZm9ybXMgZml2ZSBhbGxvY2F0aW9uc1xuICAgICAqIGFuZCBtZW1jcHkncyAxLjI1eCBpdHMgb3duIHNpemUgYmVmb3JlIGl0IGlzIGRvbmUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNhcGFjaXR5XG4gICAgICovXG4gICAgcHVibGljIHJlc2VydmUoY2FwYWNpdHk6IG51bWJlcik6IHRoaXMge1xuICAgICAgICBpZiAoY2FwYWNpdHkgPiB0aGlzLndyaXRlQ2FwYWNpdHkpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0J1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZShjYXBhY2l0eSk7XG4gICAgICAgICAgICBpZiAodGhpcy53cml0ZUJ1ZmZlciAhPT0gbnVsbCAmJiB0aGlzLndyaXRlSW5kZXggPiAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53cml0ZUJ1ZmZlci5jb3B5KG5ld0J1ZmZlciwgMCwgMCwgdGhpcy53cml0ZUluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud3JpdGVCdWZmZXIgPSBuZXdCdWZmZXI7XG4gICAgICAgICAgICB0aGlzLndyaXRlQ2FwYWNpdHkgPSBjYXBhY2l0eTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXdpbmRzIHRoZSB3cml0ZSBjdXJzb3Igd2hpbGUga2VlcGluZyB0aGUgYWxsb2NhdGVkIGNhcGFjaXR5LCBzbyBhIGxvbmctbGl2ZWQgZW5jb2RlclxuICAgICAqIHJlYWNoZXMgYSBzdGVhZHkgc3RhdGUgd2hlcmUgaXQgbmV2ZXIgYWxsb2NhdGVzIGFnYWluLiBUaGlzIGlzIHRoZSBpbnRlbmRlZCB3YXkgdG8gcmV1c2VcbiAgICAgKiBhIHN0cmVhbSBmb3IgbWFueSBwYWNrZXRzLlxuICAgICAqXG4gICAgICogTm90ZSB0aGUgYWxpYXNpbmcgY29udHJhY3QsIHdoaWNoIGl0IHNoYXJlcyB3aXRoIHtAbGluayBjbGVhcn0gYW5kIHtAbGluayByZXVzZX06IGFueVxuICAgICAqIGJ1ZmZlciBwcmV2aW91c2x5IGhhbmRlZCBvdXQgYnkge0BsaW5rIGdldFdyaXRlQnVmZmVyfSBpcyBhICp2aWV3KiBvdmVyIHRoaXMgc3RyZWFtJ3NcbiAgICAgKiBtZW1vcnkgYW5kIGlzIGludmFsaWRhdGVkIGJ5IHRoaXMgY2FsbC4gVXNlIHtAbGluayBjb3B5T3V0fSBvciB7QGxpbmsgY29weUludG99IGZvclxuICAgICAqIG91dHB1dCB5b3UgaW50ZW5kIHRvIGtlZXAuXG4gICAgICovXG4gICAgcHVibGljIHJlc2V0V3JpdGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud3JpdGVJbmRleCA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZW5jb2RlZCBieXRlcyBhcyBhbiBleGFjdGx5LXNpemVkLCBzdGFuZGFsb25lIEJ1ZmZlci5cbiAgICAgKlxuICAgICAqIFVubGlrZSB7QGxpbmsgZ2V0V3JpdGVCdWZmZXJ9IHRoZSByZXN1bHQgZG9lcyBub3QgYWxpYXMgdGhpcyBzdHJlYW0sIHNvIGl0IHN1cnZpdmVzXG4gICAgICoge0BsaW5rIHJlc2V0V3JpdGV9LCBhbmQgaXQgZG9lcyBub3QgcGluIGEgcG9vbCBjaHVuazogYmVjYXVzZSBgQnVmZmVyLmFsbG9jVW5zYWZlYCBpc1xuICAgICAqIHBvb2wtYmFja2VkIChgQnVmZmVyLnBvb2xTaXplYCBpcyA2NCBLQiBvbiBjdXJyZW50IE5vZGUpLCBob2xkaW5nIG9uIHRvIGEgaGFuZGZ1bCBvZlxuICAgICAqIHNtYWxsIHNsaWNlcyBmcm9tIHtAbGluayBnZXRXcml0ZUJ1ZmZlcn0gY2FuIGtlZXAgbWVnYWJ5dGVzIGFsaXZlLlxuICAgICAqIEByZXR1cm5zIHtCdWZmZXJ9XG4gICAgICovXG4gICAgcHVibGljIGNvcHlPdXQoKTogQnVmZmVyIHtcbiAgICAgICAgY29uc3Qgb3V0ID0gQnVmZmVyLmFsbG9jVW5zYWZlU2xvdyh0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICBpZiAodGhpcy53cml0ZUluZGV4ID4gMCkge1xuICAgICAgICAgICAgdGhpcy53cml0ZUJ1ZmZlciEuY29weShvdXQsIDAsIDAsIHRoaXMud3JpdGVJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgdGhlIGVuY29kZWQgYnl0ZXMgaW50byBhIGNhbGxlci1vd25lZCBidWZmZXIgYXQgYG9mZnNldGAgYW5kIHJldHVybnMgdGhlIG9mZnNldFxuICAgICAqIGp1c3QgcGFzdCB0aGVtLiBMZXRzIG1hbnkgcGFja2V0cyBiZSBlbmNvZGVkIGludG8gb25lIGFyZW5hIHdpdGggbm8gcGVyLXBhY2tldFxuICAgICAqIGFsbG9jYXRpb24gYXQgYWxsLlxuICAgICAqIEBwYXJhbSB7QnVmZmVyfSB0YXJnZXRcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gICAgICogQHJldHVybnMge251bWJlcn0gdGhlIG5ldyBvZmZzZXRcbiAgICAgKi9cbiAgICBwdWJsaWMgY29weUludG8odGFyZ2V0OiBCdWZmZXIsIG9mZnNldDogbnVtYmVyID0gMCk6IG51bWJlciB7XG4gICAgICAgIGlmICh0aGlzLndyaXRlSW5kZXggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLndyaXRlQnVmZmVyIS5jb3B5KHRhcmdldCwgb2Zmc2V0LCAwLCB0aGlzLndyaXRlSW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvZmZzZXQgKyB0aGlzLndyaXRlSW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5jcmVhc2VzIHRoZSB3cml0ZSBvZmZzZXQgYnkgdGhlIGdpdmVuIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoXG4gICAgICovXG4gICAgcHJpdmF0ZSBhZGRPZmZzZXQobGVuZ3RoOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gKHRoaXMucmVhZEluZGV4ICs9IGxlbmd0aCkgLSBsZW5ndGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGF0ZXZlciBvciBub3QgdGhlIHJlYWQgb2Zmc2V0IGlzIGF0IGVuZCBvZiBsaW5lLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIGZlb2YoKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGJ1ZiA9IHRoaXMucmVhZEJ1ZmZlcjtcbiAgICAgICAgaWYgKGJ1ZiA9PT0gbnVsbCkgdGhyb3cgbmV3IEVycm9yKCdCdWZmZXIgaXMgd3JpdGUgb25seSEnKTtcbiAgICAgICAgLy8gQSBudW1lcmljIGNvbXBhcmUgcmF0aGVyIHRoYW4gYHR5cGVvZiBidWZbaV0gPT09ICd1bmRlZmluZWQnYC4gVGhlIGxhdHRlciBpcyBhblxuICAgICAgICAvLyBvdXQtb2YtYm91bmRzIGVsZW1lbnQgbG9hZCwgYW5kIFY4IGJhaWxzIG91dCBvZiB0aGUgb3B0aW1pemVkIGNvZGUgZm9yIHRoaXNcbiAgICAgICAgLy8gZnVuY3Rpb24gdGhlIGZpcnN0IHRpbWUgaXQgaGFwcGVucyAtIHdoaWNoIGlzIGV2ZXJ5IHBhY2tldCBkZWNvZGVkIHRvIGl0cyBlbmQuXG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRJbmRleCA+PSBidWYuYnl0ZUxlbmd0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkcyB0aGUgcmVtYWluaW5nIGJ5dGVzIGFuZCByZXR1cm5zIHRoZSBidWZmZXIgc2xpY2UuXG4gICAgICogQHJldHVybnMge0J1ZmZlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZFJlbWFpbmluZygpOiBCdWZmZXIge1xuICAgICAgICBpZiAoIXRoaXMucmVhZEJ1ZmZlcikgdGhyb3cgbmV3IEVycm9yKCdCdWZmZXIgaXMgd3JpdGUgb25seSEnKTtcbiAgICAgICAgY29uc3QgYnVmID0gdGhpcy5yZWFkQnVmZmVyIS5zdWJhcnJheSh0aGlzLnJlYWRJbmRleCk7XG4gICAgICAgIHRoaXMucmVhZEluZGV4ID0gdGhpcy5yZWFkQnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIHJldHVybiBidWY7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2tpcHMgbGVuIGJ5dGVzIG9uIHRoZSBidWZmZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxlblxuICAgICAqL1xuICAgIHB1YmxpYyBza2lwKGxlbjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGFzc2VydChOdW1iZXIuaXNJbnRlZ2VyKGxlbiksICdDYW5ub3Qgc2tpcCBhIGZsb2F0IGFtb3VudCBvZiBieXRlcycpO1xuICAgICAgICB0aGlzLnJlYWRJbmRleCArPSBsZW47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZW5jb2RlZCBidWZmZXIuXG4gICAgICpcbiAgICAgKiBCZXdhcmU6IHdoZW4gYSByZWFkIGJ1ZmZlciBpcyBwcmVzZW50IHRoaXMgcmV0dXJucyAqdGhhdCosIGRpc2NhcmRpbmcgZXZlcnl0aGluZ1xuICAgICAqIHdyaXR0ZW4uIE9uIGEgc3RyZWFtIHVzZWQgZm9yIGJvdGggcmVhZGluZyBhbmQgd3JpdGluZyBpdCBuZXZlciByZXR1cm5zIHlvdXIgb3V0cHV0LlxuICAgICAqIEByZXR1cm5zIHtCdWZmZXJ9XG4gICAgICogQGRlcHJlY2F0ZWQgU2VlIHtAbGluayBnZXRSZWFkQnVmZmVyfSBhbmQge0BsaW5rIGdldFdyaXRlQnVmZmVyfS5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0QnVmZmVyKCk6IEJ1ZmZlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRCdWZmZXIgIT09IG51bGwgPyB0aGlzLnJlYWRCdWZmZXIgOiB0aGlzLndyaXRlQnVmZmVyIS5zdWJhcnJheSgwLCB0aGlzLndyaXRlSW5kZXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHJlYWQgYnVmZmVyIGlmIGF2YWlsYWJsZS5cbiAgICAgKiBAcmV0dXJucyB7QnVmZmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRSZWFkQnVmZmVyKCk6IEJ1ZmZlciB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkQnVmZmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGVuY29kZWQgYnl0ZXMgYXMgYSAqdmlldyogb3ZlciB0aGlzIHN0cmVhbSdzIGludGVybmFsIGJ1ZmZlci5cbiAgICAgKlxuICAgICAqIFRoZSB2aWV3IGlzIG9ubHkgdmFsaWQgdW50aWwgdGhlIG5leHQgd3JpdGU6IHtAbGluayByZXNldFdyaXRlfSwge0BsaW5rIGNsZWFyfSBhbmRcbiAgICAgKiB7QGxpbmsgcmV1c2V9IGFsbCByZXdpbmQgdGhlIGN1cnNvciB3aXRob3V0IHJlYWxsb2NhdGluZywgc28gYSBwcmV2aW91c2x5IHJldHVybmVkXG4gICAgICogYnVmZmVyIGlzIHNpbGVudGx5IG92ZXJ3cml0dGVuIGJ5IHRoZSBuZXh0IHBhY2tldC4gSWYgeW91IHF1ZXVlIHRoZSByZXN1bHQgLSBhIHNlbmRcbiAgICAgKiBxdWV1ZSwgYSByZXNlbmQgd2luZG93IC0gdXNlIHtAbGluayBjb3B5T3V0fSBvciB7QGxpbmsgY29weUludG99IGluc3RlYWQuXG4gICAgICpcbiAgICAgKiBJdCBhbHNvIGtlZXBzIHRoZSB3aG9sZSBwb29sZWQgNjQgS0IgY2h1bmsgaXQgd2FzIGNhcnZlZCBmcm9tIGFsaXZlOyByZXRhaW5pbmcgYVxuICAgICAqIHNjYXR0ZXJlZCBoYW5kZnVsIG9mIHNtYWxsIHBhY2tldHMgdGhpcyB3YXkgY2FuIHBpbiBtZWdhYnl0ZXMuXG4gICAgICogQHJldHVybnMge0J1ZmZlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0V3JpdGVCdWZmZXIoKTogQnVmZmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JpdGVCdWZmZXIhLnN1YmFycmF5KDAsIHRoaXMud3JpdGVJbmRleCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYnVmZmVyIGZvciByZWFkaW5nLlxuICAgICAqIG1ha2Ugc3VyZSB0byByZXNldCB0aGUgcmVhZGluZyBpbmRleCFcbiAgICAgKiBAcGFyYW0gYnVmIC0gVGhlIG5ldyBCdWZmZXIuXG4gICAgICogQGRlcHJlY2F0ZWQgU2VlIHtAbGluayBzZXRSZWFkQnVmZmVyfSBhbmQge0BsaW5rIHNldFdyaXRlQnVmZmVyfS5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0QnVmZmVyKGJ1ZjogQnVmZmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVhZEJ1ZmZlciA9IGJ1ZjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBidWZmZXIgZm9yIHJlYWRpbmcuXG4gICAgICogQHBhcmFtIGJ1ZiAtIFRoZSBuZXcgQnVmZmVyLlxuICAgICAqIEBwYXJhbSBySW5kZXggLSBUaGUgbmV3IHJlYWQgaW5kZXggKGRlZmF1bHQ6IDAsIHBhc3MgLTEgdG8ga2VlcCBjdXJyZW50KS5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0UmVhZEJ1ZmZlcihidWY6IEJ1ZmZlciwgckluZGV4ID0gMCk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlYWRCdWZmZXIgPSBidWY7XG4gICAgICAgIGlmIChySW5kZXggPj0gMCkgdGhpcy5yZWFkSW5kZXggPSBySW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYnVmZmVyIGZvciB3cml0aW5nLlxuICAgICAqIEBwYXJhbSBidWYgLSBUaGUgbmV3IEJ1ZmZlci5cbiAgICAgKiBAcGFyYW0gd0luZGV4IC0gVGhlIG5ldyB3cml0ZSBpbmRleCAoZGVmYXVsdDogMCwgcGFzcyAtMSB0byBrZWVwIGN1cnJlbnQpLlxuICAgICAqL1xuICAgIHB1YmxpYyBzZXRXcml0ZUJ1ZmZlcihidWY6IEJ1ZmZlciwgd0luZGV4ID0gMCk6IHZvaWQge1xuICAgICAgICB0aGlzLndyaXRlQnVmZmVyID0gYnVmO1xuICAgICAgICBpZiAod0luZGV4ID49IDApIHRoaXMud3JpdGVJbmRleCA9IHdJbmRleDtcbiAgICAgICAgdGhpcy53cml0ZUNhcGFjaXR5ID0gYnVmLmJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXJzIHRoZSB3aG9sZSBCaW5hcnlTdHJlYW0gaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBUaGUgd3JpdGUgYnVmZmVyIGFuZCBpdHMgY2FwYWNpdHkgYXJlIGtlcHQsIHNvIGFueSB2aWV3IHByZXZpb3VzbHkgcmV0dXJuZWQgYnlcbiAgICAgKiB7QGxpbmsgZ2V0V3JpdGVCdWZmZXJ9IGlzIGludmFsaWRhdGVkLiBTZWUge0BsaW5rIHJlc2V0V3JpdGV9LlxuICAgICAqL1xuICAgIHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZWFkQnVmZmVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWFkSW5kZXggPSAwO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggPSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlbnRpb25hbCBtZXRob2QgdG8gcmV1c2UgdGhlIHN0cmVhbVxuICAgICAqIHdpdGhvdXQgaGF2aW5nIHRvIGNyZWF0ZSBhIG5ldyBCaW5hcnlTdHJlYW0gaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBUaGUgd3JpdGUgYnVmZmVyIGFuZCBpdHMgY2FwYWNpdHkgYXJlIGtlcHQsIHNvIGFueSB2aWV3IHByZXZpb3VzbHkgcmV0dXJuZWQgYnlcbiAgICAgKiB7QGxpbmsgZ2V0V3JpdGVCdWZmZXJ9IGlzIGludmFsaWRhdGVkLiBTZWUge0BsaW5rIHJlc2V0V3JpdGV9LlxuICAgICAqIEBwYXJhbSBidWYgLSBUaGUgbmV3IGJ1ZmZlciBpbnN0YW5jZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmV1c2UoYnVmOiBCdWZmZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZWFkQnVmZmVyID0gYnVmO1xuICAgICAgICB0aGlzLnJlYWRJbmRleCA9IDA7XG4gICAgICAgIHRoaXMud3JpdGVJbmRleCA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgcmVhZGluZyBpbmRleC5cbiAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgbmV3IHJlYWQgaW5kZXguXG4gICAgICovXG4gICAgcHVibGljIHNldFJlYWRJbmRleChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGFzc2VydChpbmRleCA+PSAwLCAnSW5kZXggbXVzdCBiZSBub24tbmVnYXRpdmUnKTtcbiAgICAgICAgdGhpcy5yZWFkSW5kZXggPSBpbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBuZXcgd3JpdGluZyBpbmRleC5cbiAgICAgKiBAcGFyYW0gaW5kZXggLSBUaGUgbmV3IHdyaXRlIGluZGV4LlxuICAgICAqL1xuICAgIHB1YmxpYyBzZXRXcml0ZUluZGV4KGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgYXNzZXJ0KGluZGV4ID49IDAsICdJbmRleCBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpO1xuICAgICAgICB0aGlzLndyaXRlSW5kZXggPSBpbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1bnMgdGhlIHJlYWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0UmVhZEluZGV4KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRJbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB3cml0ZSBpbmRleC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRXcml0ZUluZGV4KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndyaXRlSW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRG8gcmVhZCBhc3NlcnRpb25zLCBjaGVjayBpZiB0aGUgcmVhZCBidWZmZXIgaXMgbnVsbC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYnl0ZUxlbmd0aFxuICAgICAqL1xuICAgIHByaXZhdGUgZG9SZWFkQXNzZXJ0aW9ucyhieXRlTGVuZ3RoOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgYnVmID0gdGhpcy5yZWFkQnVmZmVyO1xuICAgICAgICBpZiAoYnVmID09PSBudWxsKSB7XG4gICAgICAgICAgICBhc3NlcnQuZmFpbCgnQ2Fubm90IHJlYWQgd2l0aG91dCBidWZmZXIgZGF0YSEnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGlzIHVzZWQgdG8gY29tcGFyZSB0aGUgKnRvdGFsKiBidWZmZXIgbGVuZ3RoIGFnYWluc3QgdGhlIHJlcXVlc3RlZCBsZW5ndGggYW5kXG4gICAgICAgIC8vIGlnbm9yZSByZWFkSW5kZXggZW50aXJlbHksIHNvIGl0IGNhdWdodCBhbG1vc3Qgbm90aGluZzogcmVhZCg0KSBhdCBvZmZzZXQgOTk4IG9mIGFcbiAgICAgICAgLy8gMTAwMC1ieXRlIGJ1ZmZlciByZXR1cm5lZCAyIGJ5dGVzIHdpdGggbm8gZXJyb3IsIHJlYWRCb29sZWFuIHBhc3QgdGhlIGVuZCByZXR1cm5lZFxuICAgICAgICAvLyB0cnVlLCBhbmQgdGhlIGZpeGVkLXdpZHRoIHJlYWRlcnMgYmxldyB1cCB3aXRoIGFuIEVSUl9PVVRfT0ZfUkFOR0UgcmFpc2VkIGZyb21cbiAgICAgICAgLy8gaW5zaWRlIEJ1ZmZlciByYXRoZXIgdGhhbiBhbiBBc3NlcnRpb25FcnJvciByYWlzZWQgaGVyZS5cbiAgICAgICAgaWYgKHRoaXMucmVhZEluZGV4ICsgYnl0ZUxlbmd0aCA+IGJ1Zi5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICBhc3NlcnQuZmFpbChcbiAgICAgICAgICAgICAgICBgQ2Fubm90IHJlYWQgJHtieXRlTGVuZ3RofSBieXRlKHMpIGF0IG9mZnNldCAke3RoaXMucmVhZEluZGV4fTogYCArXG4gICAgICAgICAgICAgICAgICAgIGBvbmx5ICR7TWF0aC5tYXgoMCwgYnVmLmJ5dGVMZW5ndGggLSB0aGlzLnJlYWRJbmRleCl9IGxlZnQgaW4gYnVmZmVyYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERvIHJlYWQgYXNzZXJ0aW9ucywgY2hlY2sgaWYgdGhlIHJlYWQgYnVmZmVyIGlzIG51bGwuXG4gICAgICogQHBhcmFtIHtudW1iZXJ8YmlnaW50fSBudW1cbiAgICAgKiBAcGFyYW0ge251bWJlcnxiaWdpbnR9IG1pblZhbFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfGJpZ2ludH0gbWF4VmFsXG4gICAgICovXG4gICAgcHJpdmF0ZSBkb1dyaXRlQXNzZXJ0aW9ucyhudW06IG51bWJlciwgbWluVmFsOiBudW1iZXIsIG1heFZhbDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIC8vIEFyZ3VtZW50IGV4cHJlc3Npb25zIGFyZSBldmFsdWF0ZWQgKmJlZm9yZSogdGhlIGNhbGwsIHNvIHRoZSB0ZW1wbGF0ZSBsaXRlcmFsIHVzZWRcbiAgICAgICAgLy8gdG8gYmUgYnVpbHQgb24gZXZlcnkgc3VjY2Vzc2Z1bCB3cml0ZSAtIHNpeHRlZW4gd3JpdGUgbWV0aG9kcyByb3V0ZSB0aHJvdWdoIGhlcmUuXG4gICAgICAgIC8vIEZvciB3cml0ZUZsb2F0L3dyaXRlRG91YmxlIHRoZSBib3VuZHMgYXJlIGRvdWJsZXMsIHNvIGVhY2ggY2FsbCByYW4gdGhyZWVcbiAgICAgICAgLy8gZG91YmxlLXRvLXN0cmluZyBjb252ZXJzaW9ucyBhbmQgdGhyZXcgdGhlIHJlc3VsdCBhd2F5LiBCdWlsZGluZyB0aGUgbWVzc2FnZSBvbmx5XG4gICAgICAgIC8vIG9uIGZhaWx1cmUgaXMgd29ydGggfjIuM3ggb24gYSBtaXhlZCBwYWNrZXQtZW5jb2Rpbmcgd29ya2xvYWQuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGAhKGEgJiYgYilgIHJhdGhlciB0aGFuIGBhIDwgbWluIHx8IGEgPiBtYXhgOiB0aGUgbGF0dGVyIHNpbGVudGx5IGFjY2VwdHMgTmFOLFxuICAgICAgICAvLyB3aGljaCB0aGlzIG1ldGhvZCBoYXMgYWx3YXlzIHJlamVjdGVkLlxuICAgICAgICBpZiAoIShudW0gPj0gbWluVmFsICYmIG51bSA8PSBtYXhWYWwpKSB7XG4gICAgICAgICAgICBhc3NlcnQuZmFpbChgVmFsdWUgb3V0IG9mIGJvdW5kczogdmFsdWU9JHtudW19LCBtaW49JHttaW5WYWx9LCBtYXg9JHttYXhWYWx9YCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8vIERlZmF1bHQgZXhwb3J0IGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG5leHBvcnQgZGVmYXVsdCBCaW5hcnlTdHJlYW07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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
|