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