@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.
@@ -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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