@jsprismarine/binaryutils 0.15.0-unstable-20261024002035
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +373 -0
- package/README.md +186 -0
- package/dist/BinaryStream.cjs.cjs +839 -0
- package/dist/BinaryStream.d.ts +488 -0
- package/dist/BinaryStream.d.ts.map +1 -0
- package/dist/BinaryStream.es.js +831 -0
- package/dist/_virtual/_rolldown/runtime.cjs.cjs +24 -0
- package/dist/index.cjs.cjs +8 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +2 -0
- package/package.json +69 -0
|
@@ -0,0 +1,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+PSAwLCAnSW5kZXggbXVzdCBiZSBub24tbmVnYXRpdmUnKTtcbiAgICAgICAgdGhpcy53cml0ZUluZGV4ID0gaW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dW5zIHRoZSByZWFkIGluZGV4LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHVibGljIGdldFJlYWRJbmRleCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkSW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgd3JpdGUgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0V3JpdGVJbmRleCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy53cml0ZUluZGV4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERvIHJlYWQgYXNzZXJ0aW9ucywgY2hlY2sgaWYgdGhlIHJlYWQgYnVmZmVyIGlzIG51bGwuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJ5dGVMZW5ndGhcbiAgICAgKi9cbiAgICBwcml2YXRlIGRvUmVhZEFzc2VydGlvbnMoYnl0ZUxlbmd0aDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGJ1ZiA9IHRoaXMucmVhZEJ1ZmZlcjtcbiAgICAgICAgaWYgKGJ1ZiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgYXNzZXJ0LmZhaWwoJ0Nhbm5vdCByZWFkIHdpdGhvdXQgYnVmZmVyIGRhdGEhJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhpcyB1c2VkIHRvIGNvbXBhcmUgdGhlICp0b3RhbCogYnVmZmVyIGxlbmd0aCBhZ2FpbnN0IHRoZSByZXF1ZXN0ZWQgbGVuZ3RoIGFuZFxuICAgICAgICAvLyBpZ25vcmUgcmVhZEluZGV4IGVudGlyZWx5LCBzbyBpdCBjYXVnaHQgYWxtb3N0IG5vdGhpbmc6IHJlYWQoNCkgYXQgb2Zmc2V0IDk5OCBvZiBhXG4gICAgICAgIC8vIDEwMDAtYnl0ZSBidWZmZXIgcmV0dXJuZWQgMiBieXRlcyB3aXRoIG5vIGVycm9yLCByZWFkQm9vbGVhbiBwYXN0IHRoZSBlbmQgcmV0dXJuZWRcbiAgICAgICAgLy8gdHJ1ZSwgYW5kIHRoZSBmaXhlZC13aWR0aCByZWFkZXJzIGJsZXcgdXAgd2l0aCBhbiBFUlJfT1VUX09GX1JBTkdFIHJhaXNlZCBmcm9tXG4gICAgICAgIC8vIGluc2lkZSBCdWZmZXIgcmF0aGVyIHRoYW4gYW4gQXNzZXJ0aW9uRXJyb3IgcmFpc2VkIGhlcmUuXG4gICAgICAgIGlmICh0aGlzLnJlYWRJbmRleCArIGJ5dGVMZW5ndGggPiBidWYuYnl0ZUxlbmd0aCkge1xuICAgICAgICAgICAgYXNzZXJ0LmZhaWwoXG4gICAgICAgICAgICAgICAgYENhbm5vdCByZWFkICR7Ynl0ZUxlbmd0aH0gYnl0ZShzKSBhdCBvZmZzZXQgJHt0aGlzLnJlYWRJbmRleH06IGAgK1xuICAgICAgICAgICAgICAgICAgICBgb25seSAke01hdGgubWF4KDAsIGJ1Zi5ieXRlTGVuZ3RoIC0gdGhpcy5yZWFkSW5kZXgpfSBsZWZ0IGluIGJ1ZmZlcmBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEbyByZWFkIGFzc2VydGlvbnMsIGNoZWNrIGlmIHRoZSByZWFkIGJ1ZmZlciBpcyBudWxsLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfGJpZ2ludH0gbnVtXG4gICAgICogQHBhcmFtIHtudW1iZXJ8YmlnaW50fSBtaW5WYWxcbiAgICAgKiBAcGFyYW0ge251bWJlcnxiaWdpbnR9IG1heFZhbFxuICAgICAqL1xuICAgIHByaXZhdGUgZG9Xcml0ZUFzc2VydGlvbnMobnVtOiBudW1iZXIsIG1pblZhbDogbnVtYmVyLCBtYXhWYWw6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBBcmd1bWVudCBleHByZXNzaW9ucyBhcmUgZXZhbHVhdGVkICpiZWZvcmUqIHRoZSBjYWxsLCBzbyB0aGUgdGVtcGxhdGUgbGl0ZXJhbCB1c2VkXG4gICAgICAgIC8vIHRvIGJlIGJ1aWx0IG9uIGV2ZXJ5IHN1Y2Nlc3NmdWwgd3JpdGUgLSBzaXh0ZWVuIHdyaXRlIG1ldGhvZHMgcm91dGUgdGhyb3VnaCBoZXJlLlxuICAgICAgICAvLyBGb3Igd3JpdGVGbG9hdC93cml0ZURvdWJsZSB0aGUgYm91bmRzIGFyZSBkb3VibGVzLCBzbyBlYWNoIGNhbGwgcmFuIHRocmVlXG4gICAgICAgIC8vIGRvdWJsZS10by1zdHJpbmcgY29udmVyc2lvbnMgYW5kIHRocmV3IHRoZSByZXN1bHQgYXdheS4gQnVpbGRpbmcgdGhlIG1lc3NhZ2Ugb25seVxuICAgICAgICAvLyBvbiBmYWlsdXJlIGlzIHdvcnRoIH4yLjN4IG9uIGEgbWl4ZWQgcGFja2V0LWVuY29kaW5nIHdvcmtsb2FkLlxuICAgICAgICAvL1xuICAgICAgICAvLyBgIShhICYmIGIpYCByYXRoZXIgdGhhbiBgYSA8IG1pbiB8fCBhID4gbWF4YDogdGhlIGxhdHRlciBzaWxlbnRseSBhY2NlcHRzIE5hTixcbiAgICAgICAgLy8gd2hpY2ggdGhpcyBtZXRob2QgaGFzIGFsd2F5cyByZWplY3RlZC5cbiAgICAgICAgaWYgKCEobnVtID49IG1pblZhbCAmJiBudW0gPD0gbWF4VmFsKSkge1xuICAgICAgICAgICAgYXNzZXJ0LmZhaWwoYFZhbHVlIG91dCBvZiBib3VuZHM6IHZhbHVlPSR7bnVtfSwgbWluPSR7bWluVmFsfSwgbWF4PSR7bWF4VmFsfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBEZWZhdWx0IGV4cG9ydCBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuZXhwb3J0IGRlZmF1bHQgQmluYXJ5U3RyZWFtO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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
|