state-sync-log 0.9.0

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +277 -0
  4. package/dist/state-sync-log.esm.js +1339 -0
  5. package/dist/state-sync-log.esm.mjs +1339 -0
  6. package/dist/state-sync-log.umd.js +1343 -0
  7. package/dist/types/ClientId.d.ts +1 -0
  8. package/dist/types/SortedTxEntry.d.ts +44 -0
  9. package/dist/types/StateCalculator.d.ts +141 -0
  10. package/dist/types/TxRecord.d.ts +14 -0
  11. package/dist/types/checkpointUtils.d.ts +15 -0
  12. package/dist/types/checkpoints.d.ts +62 -0
  13. package/dist/types/clientState.d.ts +19 -0
  14. package/dist/types/createStateSyncLog.d.ts +97 -0
  15. package/dist/types/draft.d.ts +69 -0
  16. package/dist/types/error.d.ts +4 -0
  17. package/dist/types/index.d.ts +4 -0
  18. package/dist/types/json.d.ts +23 -0
  19. package/dist/types/operations.d.ts +64 -0
  20. package/dist/types/reconcile.d.ts +7 -0
  21. package/dist/types/txLog.d.ts +32 -0
  22. package/dist/types/txTimestamp.d.ts +27 -0
  23. package/dist/types/utils.d.ts +23 -0
  24. package/package.json +94 -0
  25. package/src/ClientId.ts +1 -0
  26. package/src/SortedTxEntry.ts +83 -0
  27. package/src/StateCalculator.ts +407 -0
  28. package/src/TxRecord.ts +15 -0
  29. package/src/checkpointUtils.ts +44 -0
  30. package/src/checkpoints.ts +208 -0
  31. package/src/clientState.ts +37 -0
  32. package/src/createStateSyncLog.ts +330 -0
  33. package/src/draft.ts +288 -0
  34. package/src/error.ts +12 -0
  35. package/src/index.ts +8 -0
  36. package/src/json.ts +25 -0
  37. package/src/operations.ts +157 -0
  38. package/src/reconcile.ts +124 -0
  39. package/src/txLog.ts +208 -0
  40. package/src/txTimestamp.ts +56 -0
  41. package/src/utils.ts +55 -0
@@ -0,0 +1,1339 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ function getFinalizedEpochAndCheckpoint(yCheckpoint) {
5
+ let maxEpoch = -1;
6
+ let best = null;
7
+ let bestTxCount = -1;
8
+ let bestClientId = "";
9
+ for (const [key, cp] of yCheckpoint.entries()) {
10
+ const { epoch, clientId } = parseCheckpointKey(key);
11
+ if (epoch > maxEpoch) {
12
+ maxEpoch = epoch;
13
+ best = cp;
14
+ bestTxCount = cp.txCount;
15
+ bestClientId = clientId;
16
+ } else if (epoch === maxEpoch) {
17
+ if (cp.txCount > bestTxCount || cp.txCount === bestTxCount && clientId < bestClientId) {
18
+ best = cp;
19
+ bestTxCount = cp.txCount;
20
+ bestClientId = clientId;
21
+ }
22
+ }
23
+ }
24
+ return { finalizedEpoch: maxEpoch, checkpoint: best };
25
+ }
26
+ class StateSyncLogError extends Error {
27
+ constructor(msg) {
28
+ super(msg);
29
+ Object.setPrototypeOf(this, StateSyncLogError.prototype);
30
+ }
31
+ }
32
+ function failure(message) {
33
+ throw new StateSyncLogError(message);
34
+ }
35
+ function checkpointKeyDataToKey(data) {
36
+ return `${data.epoch};${data.txCount};${data.clientId}`;
37
+ }
38
+ function parseCheckpointKey(key) {
39
+ const i1 = key.indexOf(";");
40
+ const i2 = key.indexOf(";", i1 + 1);
41
+ if (i1 === -1 || i2 === -1) {
42
+ failure(`Malformed checkpoint key: ${key}`);
43
+ }
44
+ return {
45
+ epoch: Number.parseInt(key.substring(0, i1), 10),
46
+ txCount: Number.parseInt(key.substring(i1 + 1, i2), 10),
47
+ clientId: key.substring(i2 + 1)
48
+ };
49
+ }
50
+ function createCheckpoint(yTx, yCheckpoint, clientState, activeEpoch, currentState, myClientId) {
51
+ const { checkpoint: prevCP } = getFinalizedEpochAndCheckpoint(yCheckpoint);
52
+ const newWatermarks = prevCP ? { ...prevCP.watermarks } : {};
53
+ const sortedTxs = clientState.stateCalculator.getSortedTxs();
54
+ let endIndex = sortedTxs.length;
55
+ while (endIndex > 0 && sortedTxs[endIndex - 1].txTimestamp.epoch > activeEpoch) {
56
+ endIndex--;
57
+ }
58
+ const activeTxs = sortedTxs.slice(0, endIndex);
59
+ if (activeTxs.length === 0) {
60
+ return;
61
+ }
62
+ let minWallClock = Number.POSITIVE_INFINITY;
63
+ let txCount = 0;
64
+ for (const entry of activeTxs) {
65
+ const ts = entry.txTimestamp;
66
+ if (ts.wallClock < minWallClock) {
67
+ minWallClock = ts.wallClock;
68
+ }
69
+ const newWm = newWatermarks[ts.clientId] ? { ...newWatermarks[ts.clientId] } : { maxClock: -1, maxWallClock: 0 };
70
+ if (ts.clock > newWm.maxClock) {
71
+ newWm.maxClock = ts.clock;
72
+ newWm.maxWallClock = ts.wallClock;
73
+ }
74
+ newWatermarks[ts.clientId] = newWm;
75
+ txCount++;
76
+ }
77
+ for (const clientId in newWatermarks) {
78
+ if (minWallClock - newWatermarks[clientId].maxWallClock > clientState.retentionWindowMs) {
79
+ delete newWatermarks[clientId];
80
+ }
81
+ }
82
+ const cpKey = checkpointKeyDataToKey({
83
+ epoch: activeEpoch,
84
+ txCount,
85
+ clientId: myClientId
86
+ });
87
+ yCheckpoint.set(cpKey, {
88
+ state: currentState,
89
+ // Responsibility for cloning is moved to the caller if needed
90
+ watermarks: newWatermarks,
91
+ txCount,
92
+ minWallClock
93
+ });
94
+ const keysToDelete = [];
95
+ for (const entry of activeTxs) {
96
+ yTx.delete(entry.txTimestampKey);
97
+ keysToDelete.push(entry.txTimestampKey);
98
+ }
99
+ clientState.stateCalculator.removeTxs(keysToDelete);
100
+ }
101
+ function pruneCheckpoints(yCheckpoint, finalizedEpoch) {
102
+ let canonicalKey = null;
103
+ let bestTxCount = -1;
104
+ for (const [key] of yCheckpoint.entries()) {
105
+ const { epoch, txCount } = parseCheckpointKey(key);
106
+ if (epoch === finalizedEpoch && txCount > bestTxCount) {
107
+ canonicalKey = key;
108
+ bestTxCount = txCount;
109
+ }
110
+ }
111
+ for (const key of yCheckpoint.keys()) {
112
+ if (key !== canonicalKey) {
113
+ yCheckpoint.delete(key);
114
+ }
115
+ }
116
+ }
117
+ function getDefaultExportFromCjs(x) {
118
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
119
+ }
120
+ var fastDeepEqual;
121
+ var hasRequiredFastDeepEqual;
122
+ function requireFastDeepEqual() {
123
+ if (hasRequiredFastDeepEqual) return fastDeepEqual;
124
+ hasRequiredFastDeepEqual = 1;
125
+ fastDeepEqual = function equal2(a, b) {
126
+ if (a === b) return true;
127
+ if (a && b && typeof a == "object" && typeof b == "object") {
128
+ if (a.constructor !== b.constructor) return false;
129
+ var length, i, keys;
130
+ if (Array.isArray(a)) {
131
+ length = a.length;
132
+ if (length != b.length) return false;
133
+ for (i = length; i-- !== 0; )
134
+ if (!equal2(a[i], b[i])) return false;
135
+ return true;
136
+ }
137
+ if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
138
+ if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
139
+ if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
140
+ keys = Object.keys(a);
141
+ length = keys.length;
142
+ if (length !== Object.keys(b).length) return false;
143
+ for (i = length; i-- !== 0; )
144
+ if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
145
+ for (i = length; i-- !== 0; ) {
146
+ var key = keys[i];
147
+ if (!equal2(a[key], b[key])) return false;
148
+ }
149
+ return true;
150
+ }
151
+ return a !== a && b !== b;
152
+ };
153
+ return fastDeepEqual;
154
+ }
155
+ var fastDeepEqualExports = requireFastDeepEqual();
156
+ const equal = /* @__PURE__ */ getDefaultExportFromCjs(fastDeepEqualExports);
157
+ const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
158
+ let nanoid = (size = 21) => {
159
+ let id = "";
160
+ let bytes = crypto.getRandomValues(new Uint8Array(size |= 0));
161
+ while (size--) {
162
+ id += urlAlphabet[bytes[size] & 63];
163
+ }
164
+ return id;
165
+ };
166
+ var rfdc_1;
167
+ var hasRequiredRfdc;
168
+ function requireRfdc() {
169
+ if (hasRequiredRfdc) return rfdc_1;
170
+ hasRequiredRfdc = 1;
171
+ rfdc_1 = rfdc2;
172
+ function copyBuffer(cur) {
173
+ if (cur instanceof Buffer) {
174
+ return Buffer.from(cur);
175
+ }
176
+ return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length);
177
+ }
178
+ function rfdc2(opts) {
179
+ opts = opts || {};
180
+ if (opts.circles) return rfdcCircles(opts);
181
+ const constructorHandlers = /* @__PURE__ */ new Map();
182
+ constructorHandlers.set(Date, (o) => new Date(o));
183
+ constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)));
184
+ constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)));
185
+ if (opts.constructorHandlers) {
186
+ for (const handler2 of opts.constructorHandlers) {
187
+ constructorHandlers.set(handler2[0], handler2[1]);
188
+ }
189
+ }
190
+ let handler = null;
191
+ return opts.proto ? cloneProto : clone2;
192
+ function cloneArray(a, fn) {
193
+ const keys = Object.keys(a);
194
+ const a2 = new Array(keys.length);
195
+ for (let i = 0; i < keys.length; i++) {
196
+ const k = keys[i];
197
+ const cur = a[k];
198
+ if (typeof cur !== "object" || cur === null) {
199
+ a2[k] = cur;
200
+ } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
201
+ a2[k] = handler(cur, fn);
202
+ } else if (ArrayBuffer.isView(cur)) {
203
+ a2[k] = copyBuffer(cur);
204
+ } else {
205
+ a2[k] = fn(cur);
206
+ }
207
+ }
208
+ return a2;
209
+ }
210
+ function clone2(o) {
211
+ if (typeof o !== "object" || o === null) return o;
212
+ if (Array.isArray(o)) return cloneArray(o, clone2);
213
+ if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
214
+ return handler(o, clone2);
215
+ }
216
+ const o2 = {};
217
+ for (const k in o) {
218
+ if (Object.hasOwnProperty.call(o, k) === false) continue;
219
+ const cur = o[k];
220
+ if (typeof cur !== "object" || cur === null) {
221
+ o2[k] = cur;
222
+ } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
223
+ o2[k] = handler(cur, clone2);
224
+ } else if (ArrayBuffer.isView(cur)) {
225
+ o2[k] = copyBuffer(cur);
226
+ } else {
227
+ o2[k] = clone2(cur);
228
+ }
229
+ }
230
+ return o2;
231
+ }
232
+ function cloneProto(o) {
233
+ if (typeof o !== "object" || o === null) return o;
234
+ if (Array.isArray(o)) return cloneArray(o, cloneProto);
235
+ if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
236
+ return handler(o, cloneProto);
237
+ }
238
+ const o2 = {};
239
+ for (const k in o) {
240
+ const cur = o[k];
241
+ if (typeof cur !== "object" || cur === null) {
242
+ o2[k] = cur;
243
+ } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
244
+ o2[k] = handler(cur, cloneProto);
245
+ } else if (ArrayBuffer.isView(cur)) {
246
+ o2[k] = copyBuffer(cur);
247
+ } else {
248
+ o2[k] = cloneProto(cur);
249
+ }
250
+ }
251
+ return o2;
252
+ }
253
+ }
254
+ function rfdcCircles(opts) {
255
+ const refs = [];
256
+ const refsNew = [];
257
+ const constructorHandlers = /* @__PURE__ */ new Map();
258
+ constructorHandlers.set(Date, (o) => new Date(o));
259
+ constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)));
260
+ constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)));
261
+ if (opts.constructorHandlers) {
262
+ for (const handler2 of opts.constructorHandlers) {
263
+ constructorHandlers.set(handler2[0], handler2[1]);
264
+ }
265
+ }
266
+ let handler = null;
267
+ return opts.proto ? cloneProto : clone2;
268
+ function cloneArray(a, fn) {
269
+ const keys = Object.keys(a);
270
+ const a2 = new Array(keys.length);
271
+ for (let i = 0; i < keys.length; i++) {
272
+ const k = keys[i];
273
+ const cur = a[k];
274
+ if (typeof cur !== "object" || cur === null) {
275
+ a2[k] = cur;
276
+ } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
277
+ a2[k] = handler(cur, fn);
278
+ } else if (ArrayBuffer.isView(cur)) {
279
+ a2[k] = copyBuffer(cur);
280
+ } else {
281
+ const index = refs.indexOf(cur);
282
+ if (index !== -1) {
283
+ a2[k] = refsNew[index];
284
+ } else {
285
+ a2[k] = fn(cur);
286
+ }
287
+ }
288
+ }
289
+ return a2;
290
+ }
291
+ function clone2(o) {
292
+ if (typeof o !== "object" || o === null) return o;
293
+ if (Array.isArray(o)) return cloneArray(o, clone2);
294
+ if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
295
+ return handler(o, clone2);
296
+ }
297
+ const o2 = {};
298
+ refs.push(o);
299
+ refsNew.push(o2);
300
+ for (const k in o) {
301
+ if (Object.hasOwnProperty.call(o, k) === false) continue;
302
+ const cur = o[k];
303
+ if (typeof cur !== "object" || cur === null) {
304
+ o2[k] = cur;
305
+ } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
306
+ o2[k] = handler(cur, clone2);
307
+ } else if (ArrayBuffer.isView(cur)) {
308
+ o2[k] = copyBuffer(cur);
309
+ } else {
310
+ const i = refs.indexOf(cur);
311
+ if (i !== -1) {
312
+ o2[k] = refsNew[i];
313
+ } else {
314
+ o2[k] = clone2(cur);
315
+ }
316
+ }
317
+ }
318
+ refs.pop();
319
+ refsNew.pop();
320
+ return o2;
321
+ }
322
+ function cloneProto(o) {
323
+ if (typeof o !== "object" || o === null) return o;
324
+ if (Array.isArray(o)) return cloneArray(o, cloneProto);
325
+ if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
326
+ return handler(o, cloneProto);
327
+ }
328
+ const o2 = {};
329
+ refs.push(o);
330
+ refsNew.push(o2);
331
+ for (const k in o) {
332
+ const cur = o[k];
333
+ if (typeof cur !== "object" || cur === null) {
334
+ o2[k] = cur;
335
+ } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
336
+ o2[k] = handler(cur, cloneProto);
337
+ } else if (ArrayBuffer.isView(cur)) {
338
+ o2[k] = copyBuffer(cur);
339
+ } else {
340
+ const i = refs.indexOf(cur);
341
+ if (i !== -1) {
342
+ o2[k] = refsNew[i];
343
+ } else {
344
+ o2[k] = cloneProto(cur);
345
+ }
346
+ }
347
+ }
348
+ refs.pop();
349
+ refsNew.pop();
350
+ return o2;
351
+ }
352
+ }
353
+ return rfdc_1;
354
+ }
355
+ var rfdcExports = requireRfdc();
356
+ const rfdc = /* @__PURE__ */ getDefaultExportFromCjs(rfdcExports);
357
+ const clone = rfdc({ proto: true });
358
+ function deepEqual(a, b) {
359
+ return equal(a, b);
360
+ }
361
+ function generateID() {
362
+ return nanoid();
363
+ }
364
+ function isObject(value) {
365
+ return value !== null && typeof value === "object";
366
+ }
367
+ function deepClone(value) {
368
+ if (value === null || typeof value !== "object") {
369
+ return value;
370
+ }
371
+ return clone(value);
372
+ }
373
+ function lazy(fn) {
374
+ let computed = false;
375
+ let value;
376
+ return () => {
377
+ if (!computed) {
378
+ value = fn();
379
+ computed = true;
380
+ }
381
+ return value;
382
+ };
383
+ }
384
+ function createDraft(base) {
385
+ return {
386
+ root: base,
387
+ base,
388
+ ownedObjects: /* @__PURE__ */ new Set(),
389
+ isRootOwned: false
390
+ };
391
+ }
392
+ function shallowClone(obj) {
393
+ if (Array.isArray(obj)) {
394
+ return obj.slice();
395
+ }
396
+ const clone2 = {};
397
+ const keys = Object.keys(obj);
398
+ for (let i = 0; i < keys.length; i++) {
399
+ const key = keys[i];
400
+ clone2[key] = obj[key];
401
+ }
402
+ return clone2;
403
+ }
404
+ function ensureOwned(ctx, parent, key, child) {
405
+ if (ctx.ownedObjects.has(child)) {
406
+ return child;
407
+ }
408
+ const cloned = shallowClone(child);
409
+ parent[key] = cloned;
410
+ ctx.ownedObjects.add(cloned);
411
+ return cloned;
412
+ }
413
+ function ensureOwnedPath(ctx, path) {
414
+ if (!ctx.isRootOwned) {
415
+ ctx.root = shallowClone(ctx.root);
416
+ ctx.ownedObjects.add(ctx.root);
417
+ ctx.isRootOwned = true;
418
+ }
419
+ if (path.length === 0) {
420
+ return ctx.root;
421
+ }
422
+ let current = ctx.root;
423
+ for (let i = 0; i < path.length; i++) {
424
+ const segment = path[i];
425
+ const isArrayIndex = typeof segment === "number";
426
+ if (isArrayIndex) {
427
+ if (!Array.isArray(current)) {
428
+ failure(`Expected array at path segment ${segment}`);
429
+ }
430
+ if (segment < 0 || segment >= current.length) {
431
+ failure(`Index ${segment} out of bounds`);
432
+ }
433
+ } else {
434
+ if (!isObject(current) || Array.isArray(current)) {
435
+ failure(`Expected object at path segment "${segment}"`);
436
+ }
437
+ if (!(segment in current)) {
438
+ failure(`Property "${segment}" does not exist`);
439
+ }
440
+ }
441
+ const child = current[segment];
442
+ if (child === null || typeof child !== "object") {
443
+ failure(`Cannot traverse through primitive at path segment ${segment}`);
444
+ }
445
+ current = ensureOwned(ctx, current, segment, child);
446
+ }
447
+ return current;
448
+ }
449
+ function draftSet(ctx, path, key, value) {
450
+ const container = ensureOwnedPath(ctx, path);
451
+ if (Array.isArray(container)) {
452
+ failure("set requires object container");
453
+ }
454
+ container[key] = value;
455
+ }
456
+ function draftDelete(ctx, path, key) {
457
+ const container = ensureOwnedPath(ctx, path);
458
+ if (Array.isArray(container)) {
459
+ failure("delete requires object container");
460
+ }
461
+ delete container[key];
462
+ }
463
+ function draftSplice(ctx, path, index, deleteCount, inserts) {
464
+ const container = ensureOwnedPath(ctx, path);
465
+ if (!Array.isArray(container)) {
466
+ failure("splice requires array container");
467
+ }
468
+ const safeIndex = Math.min(index, container.length);
469
+ if (inserts.length === 0) {
470
+ container.splice(safeIndex, deleteCount);
471
+ } else if (inserts.length === 1) {
472
+ container.splice(safeIndex, deleteCount, inserts[0]);
473
+ } else {
474
+ container.splice(safeIndex, deleteCount, ...inserts);
475
+ }
476
+ }
477
+ function draftAddToSet(ctx, path, value) {
478
+ const container = ensureOwnedPath(ctx, path);
479
+ if (!Array.isArray(container)) {
480
+ failure("addToSet requires array container");
481
+ }
482
+ if (!container.some((item) => deepEqual(item, value))) {
483
+ container.push(value);
484
+ }
485
+ }
486
+ function draftDeleteFromSet(ctx, path, value) {
487
+ const container = ensureOwnedPath(ctx, path);
488
+ if (!Array.isArray(container)) {
489
+ failure("deleteFromSet requires array container");
490
+ }
491
+ for (let i = container.length - 1; i >= 0; i--) {
492
+ if (deepEqual(container[i], value)) {
493
+ container.splice(i, 1);
494
+ }
495
+ }
496
+ }
497
+ function applyOpToDraft(ctx, op) {
498
+ switch (op.kind) {
499
+ case "set":
500
+ draftSet(ctx, op.path, op.key, op.value);
501
+ break;
502
+ case "delete":
503
+ draftDelete(ctx, op.path, op.key);
504
+ break;
505
+ case "splice":
506
+ draftSplice(ctx, op.path, op.index, op.deleteCount, op.inserts);
507
+ break;
508
+ case "addToSet":
509
+ draftAddToSet(ctx, op.path, op.value);
510
+ break;
511
+ case "deleteFromSet":
512
+ draftDeleteFromSet(ctx, op.path, op.value);
513
+ break;
514
+ default:
515
+ throw failure(`Unknown operation kind: ${op.kind}`);
516
+ }
517
+ }
518
+ function applyTxImmutable(base, tx, validateFn) {
519
+ if (tx.ops.length === 0) return base;
520
+ const ctx = createDraft(base);
521
+ try {
522
+ for (const op of tx.ops) {
523
+ applyOpToDraft(ctx, op);
524
+ }
525
+ if (validateFn && !validateFn(ctx.root)) {
526
+ return base;
527
+ }
528
+ return ctx.root;
529
+ } catch {
530
+ return base;
531
+ }
532
+ }
533
+ function computeReconcileOps(currentState, targetState) {
534
+ const ops = [];
535
+ diffValue(currentState, targetState, [], ops);
536
+ return ops;
537
+ }
538
+ function diffValue(current, target, path, ops) {
539
+ if (current === target) return;
540
+ const currentType = typeof current;
541
+ const targetType = typeof target;
542
+ if (current === null || target === null || currentType !== "object" || targetType !== "object") {
543
+ emitReplace(path, target, ops);
544
+ return;
545
+ }
546
+ const currentIsArray = Array.isArray(current);
547
+ const targetIsArray = Array.isArray(target);
548
+ if (currentIsArray !== targetIsArray) {
549
+ emitReplace(path, target, ops);
550
+ return;
551
+ }
552
+ if (currentIsArray) {
553
+ diffArray(current, target, path, ops);
554
+ } else {
555
+ diffObject(current, target, path, ops);
556
+ }
557
+ }
558
+ function diffObject(current, target, path, ops) {
559
+ for (const key in current) {
560
+ if (Object.hasOwn(current, key) && !Object.hasOwn(target, key)) {
561
+ ops.push({ kind: "delete", path, key });
562
+ }
563
+ }
564
+ for (const key in target) {
565
+ if (Object.hasOwn(target, key)) {
566
+ const targetVal = target[key];
567
+ if (!Object.hasOwn(current, key)) {
568
+ ops.push({ kind: "set", path, key, value: targetVal });
569
+ } else if (current[key] !== targetVal) {
570
+ diffValue(current[key], targetVal, [...path, key], ops);
571
+ }
572
+ }
573
+ }
574
+ }
575
+ function diffArray(current, target, path, ops) {
576
+ const currentLen = current.length;
577
+ const targetLen = target.length;
578
+ const minLen = currentLen < targetLen ? currentLen : targetLen;
579
+ for (let i = 0; i < minLen; i++) {
580
+ if (current[i] !== target[i]) {
581
+ diffValue(current[i], target[i], [...path, i], ops);
582
+ }
583
+ }
584
+ if (targetLen > currentLen) {
585
+ ops.push({
586
+ kind: "splice",
587
+ path,
588
+ index: currentLen,
589
+ deleteCount: 0,
590
+ inserts: target.slice(currentLen)
591
+ });
592
+ } else if (currentLen > targetLen) {
593
+ ops.push({
594
+ kind: "splice",
595
+ path,
596
+ index: targetLen,
597
+ deleteCount: currentLen - targetLen,
598
+ inserts: []
599
+ });
600
+ }
601
+ }
602
+ function emitReplace(path, value, ops) {
603
+ if (path.length === 0) {
604
+ failure("StateSyncLog: Cannot replace root state directly via Ops.");
605
+ }
606
+ const parentPath = path.slice(0, -1);
607
+ const keyToCheck = path[path.length - 1];
608
+ if (typeof keyToCheck === "string") {
609
+ ops.push({ kind: "set", path: parentPath, key: keyToCheck, value });
610
+ } else {
611
+ ops.push({
612
+ kind: "splice",
613
+ path: parentPath,
614
+ index: keyToCheck,
615
+ deleteCount: 1,
616
+ inserts: [value]
617
+ });
618
+ }
619
+ }
620
+ function txTimestampToKey(ts) {
621
+ return `${ts.epoch};${ts.clock};${ts.clientId};${ts.wallClock}`;
622
+ }
623
+ function parseTxTimestampKey(key) {
624
+ const i1 = key.indexOf(";");
625
+ const i2 = key.indexOf(";", i1 + 1);
626
+ const i3 = key.indexOf(";", i2 + 1);
627
+ if (i1 === -1 || i2 === -1 || i3 === -1) {
628
+ failure(`Malformed timestamp key: ${key}`);
629
+ }
630
+ return {
631
+ epoch: Number.parseInt(key.substring(0, i1), 10),
632
+ clock: Number.parseInt(key.substring(i1 + 1, i2), 10),
633
+ clientId: key.substring(i2 + 1, i3),
634
+ wallClock: Number.parseInt(key.substring(i3 + 1), 10)
635
+ };
636
+ }
637
+ function compareTxTimestamps(a, b) {
638
+ if (a.epoch !== b.epoch) return a.epoch - b.epoch;
639
+ if (a.clock !== b.clock) return a.clock - b.clock;
640
+ if (a.clientId < b.clientId) return -1;
641
+ if (a.clientId > b.clientId) return 1;
642
+ return 0;
643
+ }
644
+ class SortedTxEntry {
645
+ constructor(txTimestampKey, _yTx) {
646
+ __publicField(this, "_txTimestamp");
647
+ __publicField(this, "_originalTxTimestampKey");
648
+ __publicField(this, "_originalTxTimestamp");
649
+ __publicField(this, "_txRecord");
650
+ this.txTimestampKey = txTimestampKey;
651
+ this._yTx = _yTx;
652
+ }
653
+ /**
654
+ * Gets the parsed timestamp, lazily parsing and caching on first access.
655
+ */
656
+ get txTimestamp() {
657
+ if (!this._txTimestamp) {
658
+ this._txTimestamp = parseTxTimestampKey(this.txTimestampKey);
659
+ }
660
+ return this._txTimestamp;
661
+ }
662
+ /**
663
+ * Gets the original tx timestamp key, lazily and caching on first access.
664
+ */
665
+ get originalTxTimestampKey() {
666
+ var _a;
667
+ if (this._originalTxTimestampKey === void 0) {
668
+ const tx = this.txRecord;
669
+ this._originalTxTimestampKey = (_a = tx.originalTxKey) != null ? _a : null;
670
+ }
671
+ return this._originalTxTimestampKey;
672
+ }
673
+ /**
674
+ * Gets the parsed original tx timestamp, lazily parsing and caching on first access.
675
+ */
676
+ get originalTxTimestamp() {
677
+ if (this._originalTxTimestamp === void 0) {
678
+ const key = this.originalTxTimestampKey;
679
+ this._originalTxTimestamp = key ? parseTxTimestampKey(key) : null;
680
+ }
681
+ return this._originalTxTimestamp;
682
+ }
683
+ /**
684
+ * Gets the logical (deduplicated) tx timestamp key.
685
+ * This is the original tx key if it exists, otherwise the physical key.
686
+ */
687
+ get dedupTxTimestampKey() {
688
+ var _a;
689
+ return (_a = this.originalTxTimestampKey) != null ? _a : this.txTimestampKey;
690
+ }
691
+ /**
692
+ * Gets the logical (deduplicated) parsed tx timestamp.
693
+ * This is the original tx timestamp if it exists, otherwise the physical timestamp.
694
+ */
695
+ get dedupTxTimestamp() {
696
+ var _a;
697
+ return (_a = this.originalTxTimestamp) != null ? _a : this.txTimestamp;
698
+ }
699
+ /**
700
+ * Gets the tx record, lazily fetching and caching on first access.
701
+ * Returns undefined if the tx doesn't exist.
702
+ */
703
+ get txRecord() {
704
+ if (!this._txRecord) {
705
+ this._txRecord = this._yTx.get(this.txTimestampKey);
706
+ if (!this._txRecord) {
707
+ throw failure(`SortedTxEntry: TxRecord not found for key ${this.txTimestampKey}`);
708
+ }
709
+ }
710
+ return this._txRecord;
711
+ }
712
+ }
713
+ function isTransactionInCheckpoint(ts, watermarks) {
714
+ const wm = watermarks[ts.clientId];
715
+ if (!wm) return false;
716
+ return ts.clock <= wm.maxClock;
717
+ }
718
+ class StateCalculator {
719
+ constructor(validateFn) {
720
+ /** Sorted tx cache (ALL active/future txs, kept sorted by timestamp) */
721
+ __publicField(this, "sortedTxs", []);
722
+ /** O(1) existence check and lookup */
723
+ __publicField(this, "sortedTxsMap", /* @__PURE__ */ new Map());
724
+ /**
725
+ * Index of the last transaction applied to cachedState.
726
+ * - null: state needs full recalculation from checkpoint
727
+ * - -1: no transactions have been applied yet (state === checkpoint state)
728
+ * - >= 0: transactions up to and including this index have been applied
729
+ */
730
+ __publicField(this, "lastAppliedIndex", null);
731
+ /** The cached calculated state */
732
+ __publicField(this, "cachedState", null);
733
+ /** The base checkpoint to calculate state from */
734
+ __publicField(this, "baseCheckpoint", null);
735
+ /**
736
+ * Applied dedup keys - tracks which LOGICAL txs have been applied.
737
+ * This is the originalTxKey (or physical key if no original) for each applied tx.
738
+ * Used to properly deduplicate re-emits.
739
+ */
740
+ __publicField(this, "appliedTxKeys", /* @__PURE__ */ new Set());
741
+ /** Max clock seen from any transaction (for Lamport clock updates) */
742
+ __publicField(this, "maxSeenClock", 0);
743
+ /** Validation function (optional) */
744
+ __publicField(this, "validateFn");
745
+ this.validateFn = validateFn;
746
+ }
747
+ /**
748
+ * Sets the base checkpoint. Invalidates cached state if checkpoint changed.
749
+ * @returns true if the checkpoint changed
750
+ */
751
+ setBaseCheckpoint(checkpoint) {
752
+ if (checkpoint === this.baseCheckpoint) {
753
+ return false;
754
+ }
755
+ this.baseCheckpoint = checkpoint;
756
+ this.invalidate();
757
+ return true;
758
+ }
759
+ /**
760
+ * Gets the current base checkpoint.
761
+ */
762
+ getBaseCheckpoint() {
763
+ return this.baseCheckpoint;
764
+ }
765
+ /**
766
+ * Clears all transactions and rebuilds from yTx map.
767
+ * This is used when the checkpoint changes and we need a fresh start.
768
+ */
769
+ rebuildFromYjs(yTx) {
770
+ this.sortedTxs = [];
771
+ this.sortedTxsMap.clear();
772
+ for (const key of yTx.keys()) {
773
+ const entry = new SortedTxEntry(key, yTx);
774
+ this.sortedTxs.push(entry);
775
+ this.sortedTxsMap.set(entry.txTimestampKey, entry);
776
+ if (entry.txTimestamp.clock > this.maxSeenClock) {
777
+ this.maxSeenClock = entry.txTimestamp.clock;
778
+ }
779
+ }
780
+ this.sortedTxs.sort((a, b) => compareTxTimestamps(a.txTimestamp, b.txTimestamp));
781
+ this.invalidate();
782
+ }
783
+ /**
784
+ * Inserts a transaction into the sorted cache.
785
+ * Invalidates cached state if the transaction was inserted before the calculated slice.
786
+ *
787
+ * @returns true if this caused invalidation (out-of-order insert)
788
+ */
789
+ insertTx(key, yTx) {
790
+ if (this.sortedTxsMap.has(key)) {
791
+ return false;
792
+ }
793
+ const entry = new SortedTxEntry(key, yTx);
794
+ const ts = entry.txTimestamp;
795
+ if (ts.clock > this.maxSeenClock) {
796
+ this.maxSeenClock = ts.clock;
797
+ }
798
+ const sortedTxs = this.sortedTxs;
799
+ let insertIndex = sortedTxs.length;
800
+ for (let i = sortedTxs.length - 1; i >= 0; i--) {
801
+ const existingTs = sortedTxs[i].txTimestamp;
802
+ if (compareTxTimestamps(ts, existingTs) >= 0) {
803
+ insertIndex = i + 1;
804
+ break;
805
+ }
806
+ if (i === 0) {
807
+ insertIndex = 0;
808
+ }
809
+ }
810
+ sortedTxs.splice(insertIndex, 0, entry);
811
+ this.sortedTxsMap.set(key, entry);
812
+ if (this.lastAppliedIndex !== null && insertIndex <= this.lastAppliedIndex) {
813
+ this.invalidate();
814
+ return true;
815
+ }
816
+ return false;
817
+ }
818
+ /**
819
+ * Removes multiple transactions from the sorted cache.
820
+ * @returns the number of keys that were actually removed
821
+ */
822
+ removeTxs(keys) {
823
+ if (keys.length === 0) return 0;
824
+ let removedCount = 0;
825
+ let minRemovedIndex = Number.POSITIVE_INFINITY;
826
+ const toDelete = /* @__PURE__ */ new Set();
827
+ for (const key of keys) {
828
+ const entry = this.sortedTxsMap.get(key);
829
+ if (entry) {
830
+ this.sortedTxsMap.delete(key);
831
+ toDelete.add(key);
832
+ const index = this.sortedTxs.indexOf(entry);
833
+ if (index !== -1 && index < minRemovedIndex) {
834
+ minRemovedIndex = index;
835
+ }
836
+ }
837
+ }
838
+ if (toDelete.size === 0) return 0;
839
+ const sortedTxs = this.sortedTxs;
840
+ let i = 0;
841
+ while (i < sortedTxs.length && toDelete.size > 0) {
842
+ if (toDelete.has(sortedTxs[i].txTimestampKey)) {
843
+ toDelete.delete(sortedTxs[i].txTimestampKey);
844
+ sortedTxs.splice(i, 1);
845
+ removedCount++;
846
+ } else {
847
+ i++;
848
+ }
849
+ }
850
+ if (this.lastAppliedIndex !== null && minRemovedIndex <= this.lastAppliedIndex) {
851
+ this.invalidate();
852
+ }
853
+ return removedCount;
854
+ }
855
+ /**
856
+ * Checks if a transaction key exists in the cache.
857
+ */
858
+ hasTx(key) {
859
+ return this.sortedTxsMap.has(key);
860
+ }
861
+ /**
862
+ * Gets a transaction entry by key.
863
+ */
864
+ getTx(key) {
865
+ return this.sortedTxsMap.get(key);
866
+ }
867
+ /**
868
+ * Gets all sorted transaction entries.
869
+ */
870
+ getSortedTxs() {
871
+ return this.sortedTxs;
872
+ }
873
+ /**
874
+ * Gets the number of transactions in the cache.
875
+ */
876
+ get txCount() {
877
+ return this.sortedTxs.length;
878
+ }
879
+ /**
880
+ * Returns true if the state needs full recalculation.
881
+ */
882
+ needsFullRecalculation() {
883
+ return this.lastAppliedIndex === null;
884
+ }
885
+ /**
886
+ * Invalidates the cached state, forcing a full recalculation on next calculateState().
887
+ * Note: cachedState is kept so computeReconcileOps can diff old vs new state.
888
+ */
889
+ invalidate() {
890
+ this.lastAppliedIndex = null;
891
+ }
892
+ /**
893
+ * Calculates and returns the current state, along with a lazy getter for ops that changed from the previous state.
894
+ *
895
+ * - If lastAppliedIndex is null: full recalculation from checkpoint
896
+ * - If lastAppliedIndex >= -1: incremental apply from lastAppliedIndex + 1
897
+ */
898
+ calculateState() {
899
+ var _a, _b, _c, _d;
900
+ const baseState = (_b = (_a = this.baseCheckpoint) == null ? void 0 : _a.state) != null ? _b : {};
901
+ const watermarks = (_d = (_c = this.baseCheckpoint) == null ? void 0 : _c.watermarks) != null ? _d : {};
902
+ const hasWatermarks = Object.keys(watermarks).length > 0;
903
+ if (this.lastAppliedIndex === null) {
904
+ return this.fullRecalculation(baseState, watermarks, hasWatermarks);
905
+ }
906
+ return this.incrementalApply(watermarks, hasWatermarks);
907
+ }
908
+ /**
909
+ * Full recalculation of state from the base checkpoint.
910
+ */
911
+ fullRecalculation(baseState, watermarks, hasWatermarks) {
912
+ var _a;
913
+ const oldState = (_a = this.cachedState) != null ? _a : {};
914
+ this.appliedTxKeys.clear();
915
+ this.lastAppliedIndex = -1;
916
+ this.cachedState = baseState;
917
+ const { state } = this.incrementalApply(watermarks, hasWatermarks, false);
918
+ const getAppliedOps = lazy(() => computeReconcileOps(oldState, state));
919
+ return { state, getAppliedOps };
920
+ }
921
+ /**
922
+ * Incremental apply of transactions from lastAppliedIndex + 1.
923
+ * @param returnOps If true, collects applied transactions (to lazy compute ops). If false, skips collection.
924
+ */
925
+ incrementalApply(watermarks, hasWatermarks, returnOps = true) {
926
+ let state = this.cachedState;
927
+ const appliedTxs = [];
928
+ const sortedTxs = this.sortedTxs;
929
+ const startIndex = this.lastAppliedIndex + 1;
930
+ for (let i = startIndex; i < sortedTxs.length; i++) {
931
+ const entry = sortedTxs[i];
932
+ const dedupKey = entry.dedupTxTimestampKey;
933
+ if (this.appliedTxKeys.has(dedupKey)) {
934
+ continue;
935
+ }
936
+ if (hasWatermarks) {
937
+ const dedupTs = entry.dedupTxTimestamp;
938
+ if (isTransactionInCheckpoint(dedupTs, watermarks)) {
939
+ this.appliedTxKeys.add(dedupKey);
940
+ continue;
941
+ }
942
+ }
943
+ const tx = entry.txRecord;
944
+ const newState = applyTxImmutable(state, tx, this.validateFn);
945
+ if (newState !== state) {
946
+ state = newState;
947
+ if (returnOps) {
948
+ appliedTxs.push(tx);
949
+ }
950
+ }
951
+ this.appliedTxKeys.add(dedupKey);
952
+ this.lastAppliedIndex = i;
953
+ }
954
+ if (sortedTxs.length > 0 && this.lastAppliedIndex < sortedTxs.length - 1) {
955
+ this.lastAppliedIndex = sortedTxs.length - 1;
956
+ }
957
+ this.cachedState = state;
958
+ const getAppliedOps = lazy(() => {
959
+ const ops = [];
960
+ for (const tx of appliedTxs) {
961
+ ops.push(...tx.ops);
962
+ }
963
+ return ops;
964
+ });
965
+ return { state, getAppliedOps };
966
+ }
967
+ /**
968
+ * Gets the max seen clock (for Lamport clock updates).
969
+ */
970
+ getMaxSeenClock() {
971
+ return this.maxSeenClock;
972
+ }
973
+ /**
974
+ * Gets the current cached state without recalculating.
975
+ * Returns null if state has never been calculated.
976
+ */
977
+ getCachedState() {
978
+ return this.cachedState;
979
+ }
980
+ /**
981
+ * Gets the last applied timestamp.
982
+ */
983
+ getLastAppliedTs() {
984
+ var _a, _b;
985
+ if (this.lastAppliedIndex === null || this.lastAppliedIndex < 0) {
986
+ return null;
987
+ }
988
+ return (_b = (_a = this.sortedTxs[this.lastAppliedIndex]) == null ? void 0 : _a.txTimestamp) != null ? _b : null;
989
+ }
990
+ /**
991
+ * Gets the last applied index (for debugging/tracking).
992
+ */
993
+ getLastAppliedIndex() {
994
+ return this.lastAppliedIndex;
995
+ }
996
+ }
997
+ function createClientState(validateFn, retentionWindowMs) {
998
+ return {
999
+ localClock: 0,
1000
+ cachedFinalizedEpoch: null,
1001
+ // Will be recalculated on first run
1002
+ stateCalculator: new StateCalculator(validateFn),
1003
+ retentionWindowMs
1004
+ };
1005
+ }
1006
+ function appendTx(ops, yTx, activeEpoch, myClientId, clientState, originalKey) {
1007
+ const calc = clientState.stateCalculator;
1008
+ const clock = Math.max(clientState.localClock, calc.getMaxSeenClock()) + 1;
1009
+ clientState.localClock = clock;
1010
+ const ts = {
1011
+ epoch: activeEpoch,
1012
+ clock,
1013
+ clientId: myClientId,
1014
+ wallClock: Date.now()
1015
+ };
1016
+ const key = txTimestampToKey(ts);
1017
+ const record = { ops, originalTxKey: originalKey };
1018
+ yTx.set(key, record);
1019
+ return key;
1020
+ }
1021
+ function syncLog(yTx, myClientId, clientState, finalizedEpoch, baseCP, newKeys) {
1022
+ var _a, _b;
1023
+ const calc = clientState.stateCalculator;
1024
+ const activeEpoch = finalizedEpoch + 1;
1025
+ const watermarks = (_a = baseCP == null ? void 0 : baseCP.watermarks) != null ? _a : {};
1026
+ const referenceTime = (_b = baseCP == null ? void 0 : baseCP.minWallClock) != null ? _b : 0;
1027
+ const shouldPrune = (ts, dedupTs) => {
1028
+ const isAncient = referenceTime - ts.wallClock > clientState.retentionWindowMs;
1029
+ if (isAncient) return true;
1030
+ return isTransactionInCheckpoint(dedupTs, watermarks);
1031
+ };
1032
+ const toDelete = [];
1033
+ const toReEmit = [];
1034
+ const processEntry = (entry) => {
1035
+ if (shouldPrune(entry.txTimestamp, entry.dedupTxTimestamp)) {
1036
+ toDelete.push(entry.txTimestampKey);
1037
+ return false;
1038
+ }
1039
+ if (entry.txTimestamp.epoch <= finalizedEpoch) {
1040
+ toReEmit.push({ originalKey: entry.dedupTxTimestampKey, tx: entry.txRecord });
1041
+ toDelete.push(entry.txTimestampKey);
1042
+ return false;
1043
+ }
1044
+ return true;
1045
+ };
1046
+ for (const entry of calc.getSortedTxs()) {
1047
+ if (processEntry(entry)) {
1048
+ break;
1049
+ }
1050
+ }
1051
+ const processKeyByTimestampKey = (txTimestampKey) => {
1052
+ if (yTx.has(txTimestampKey)) {
1053
+ processEntry(new SortedTxEntry(txTimestampKey, yTx));
1054
+ }
1055
+ };
1056
+ if (newKeys) {
1057
+ for (const key of newKeys) {
1058
+ processKeyByTimestampKey(key);
1059
+ }
1060
+ }
1061
+ for (const { originalKey, tx } of toReEmit) {
1062
+ const newKey = appendTx(tx.ops, yTx, activeEpoch, myClientId, clientState, originalKey);
1063
+ calc.insertTx(newKey, yTx);
1064
+ }
1065
+ for (const key of toDelete) {
1066
+ yTx.delete(key);
1067
+ }
1068
+ calc.removeTxs(toDelete);
1069
+ }
1070
+ function updateState(doc, yTx, yCheckpoint, myClientId, clientState, txChanges) {
1071
+ const calc = clientState.stateCalculator;
1072
+ const { finalizedEpoch, checkpoint: baseCP } = getFinalizedEpochAndCheckpoint(yCheckpoint);
1073
+ clientState.cachedFinalizedEpoch = finalizedEpoch;
1074
+ calc.setBaseCheckpoint(baseCP);
1075
+ const needsRebuildSortedCache = calc.getCachedState() === null || !txChanges;
1076
+ if (needsRebuildSortedCache) {
1077
+ calc.rebuildFromYjs(yTx);
1078
+ } else {
1079
+ calc.removeTxs(txChanges.deleted);
1080
+ }
1081
+ doc.transact(() => {
1082
+ syncLog(yTx, myClientId, clientState, finalizedEpoch, baseCP, txChanges == null ? void 0 : txChanges.added);
1083
+ pruneCheckpoints(yCheckpoint, finalizedEpoch);
1084
+ });
1085
+ if (needsRebuildSortedCache) {
1086
+ return calc.calculateState();
1087
+ }
1088
+ for (const key of txChanges.added) {
1089
+ if (yTx.has(key) && !calc.hasTx(key)) {
1090
+ calc.insertTx(key, yTx);
1091
+ }
1092
+ }
1093
+ return calc.calculateState();
1094
+ }
1095
+ const getSortedTxsSymbol = /* @__PURE__ */ Symbol("getSortedTxs");
1096
+ function createStateSyncLog(options) {
1097
+ const {
1098
+ yDoc,
1099
+ yTxMapName = "state-sync-log-tx",
1100
+ yCheckpointMapName = "state-sync-log-checkpoint",
1101
+ clientId = generateID(),
1102
+ yjsOrigin,
1103
+ validate,
1104
+ retentionWindowMs
1105
+ } = options;
1106
+ if (clientId.includes(";")) {
1107
+ failure(`clientId MUST NOT contain semicolons: ${clientId}`);
1108
+ }
1109
+ const yTx = yDoc.getMap(yTxMapName);
1110
+ const yCheckpoint = yDoc.getMap(yCheckpointMapName);
1111
+ const clientState = createClientState(
1112
+ validate,
1113
+ retentionWindowMs != null ? retentionWindowMs : Number.POSITIVE_INFINITY
1114
+ );
1115
+ const subscribers = /* @__PURE__ */ new Set();
1116
+ const notifySubscribers = (state, getAppliedOps) => {
1117
+ for (const sub of subscribers) {
1118
+ sub(state, getAppliedOps);
1119
+ }
1120
+ };
1121
+ const extractTxChanges = (event) => {
1122
+ const added = [];
1123
+ const deleted = [];
1124
+ for (const [key, change] of event.changes.keys) {
1125
+ if (change.action === "add") {
1126
+ added.push(key);
1127
+ } else if (change.action === "delete") {
1128
+ deleted.push(key);
1129
+ } else if (change.action === "update") {
1130
+ deleted.push(key);
1131
+ added.push(key);
1132
+ }
1133
+ }
1134
+ return { added, deleted };
1135
+ };
1136
+ const emptyTxChanges = { added: [], deleted: [] };
1137
+ const runUpdate = (txChanges) => {
1138
+ const { state, getAppliedOps } = updateState(
1139
+ yDoc,
1140
+ yTx,
1141
+ yCheckpoint,
1142
+ clientId,
1143
+ clientState,
1144
+ txChanges
1145
+ );
1146
+ notifySubscribers(state, getAppliedOps);
1147
+ };
1148
+ const txObserver = (event, _transaction) => {
1149
+ const txChanges = extractTxChanges(event);
1150
+ runUpdate(txChanges);
1151
+ };
1152
+ const checkpointObserver = (_event, _transaction) => {
1153
+ runUpdate(emptyTxChanges);
1154
+ };
1155
+ yCheckpoint.observe(checkpointObserver);
1156
+ yTx.observe(txObserver);
1157
+ runUpdate(void 0);
1158
+ let disposed = false;
1159
+ const assertNotDisposed = () => {
1160
+ if (disposed) {
1161
+ failure("StateSyncLog has been disposed and cannot be used");
1162
+ }
1163
+ };
1164
+ const getActiveEpochInternal = () => {
1165
+ if (clientState.cachedFinalizedEpoch === null) {
1166
+ failure("cachedFinalizedEpoch is null - this should not happen after initialization");
1167
+ }
1168
+ return clientState.cachedFinalizedEpoch + 1;
1169
+ };
1170
+ return {
1171
+ getState() {
1172
+ var _a;
1173
+ assertNotDisposed();
1174
+ return (_a = clientState.stateCalculator.getCachedState()) != null ? _a : {};
1175
+ },
1176
+ subscribe(callback) {
1177
+ assertNotDisposed();
1178
+ subscribers.add(callback);
1179
+ return () => {
1180
+ subscribers.delete(callback);
1181
+ };
1182
+ },
1183
+ emit(ops) {
1184
+ assertNotDisposed();
1185
+ yDoc.transact(() => {
1186
+ const activeEpoch = getActiveEpochInternal();
1187
+ appendTx(ops, yTx, activeEpoch, clientId, clientState);
1188
+ }, yjsOrigin);
1189
+ },
1190
+ reconcileState(targetState) {
1191
+ var _a;
1192
+ assertNotDisposed();
1193
+ const currentState = (_a = clientState.stateCalculator.getCachedState()) != null ? _a : {};
1194
+ const ops = computeReconcileOps(currentState, targetState);
1195
+ if (ops.length > 0) {
1196
+ this.emit(ops);
1197
+ }
1198
+ },
1199
+ compact() {
1200
+ assertNotDisposed();
1201
+ yDoc.transact(() => {
1202
+ var _a;
1203
+ const activeEpoch = getActiveEpochInternal();
1204
+ const currentState = (_a = clientState.stateCalculator.getCachedState()) != null ? _a : {};
1205
+ createCheckpoint(yTx, yCheckpoint, clientState, activeEpoch, currentState, clientId);
1206
+ }, yjsOrigin);
1207
+ },
1208
+ dispose() {
1209
+ if (disposed) return;
1210
+ disposed = true;
1211
+ yTx.unobserve(txObserver);
1212
+ yCheckpoint.unobserve(checkpointObserver);
1213
+ subscribers.clear();
1214
+ },
1215
+ getActiveEpoch() {
1216
+ assertNotDisposed();
1217
+ return getActiveEpochInternal();
1218
+ },
1219
+ getActiveEpochTxCount() {
1220
+ assertNotDisposed();
1221
+ const activeEpoch = getActiveEpochInternal();
1222
+ let count = 0;
1223
+ for (const entry of clientState.stateCalculator.getSortedTxs()) {
1224
+ const ts = entry.txTimestamp;
1225
+ if (ts.epoch === activeEpoch) {
1226
+ count++;
1227
+ } else if (ts.epoch > activeEpoch) {
1228
+ break;
1229
+ }
1230
+ }
1231
+ return count;
1232
+ },
1233
+ getActiveEpochStartTime() {
1234
+ assertNotDisposed();
1235
+ const activeEpoch = getActiveEpochInternal();
1236
+ for (const entry of clientState.stateCalculator.getSortedTxs()) {
1237
+ const ts = entry.txTimestamp;
1238
+ if (ts.epoch === activeEpoch) {
1239
+ return ts.wallClock;
1240
+ } else if (ts.epoch > activeEpoch) {
1241
+ break;
1242
+ }
1243
+ }
1244
+ return void 0;
1245
+ },
1246
+ isLogEmpty() {
1247
+ assertNotDisposed();
1248
+ return yTx.size === 0 && yCheckpoint.size === 0;
1249
+ },
1250
+ [getSortedTxsSymbol]() {
1251
+ assertNotDisposed();
1252
+ return clientState.stateCalculator.getSortedTxs();
1253
+ }
1254
+ };
1255
+ }
1256
+ function resolvePath(state, path) {
1257
+ let current = state;
1258
+ for (const segment of path) {
1259
+ if (typeof segment === "string") {
1260
+ if (!isObject(current) || Array.isArray(current)) {
1261
+ failure(`Expected object at path segment "${segment}"`);
1262
+ }
1263
+ if (!(segment in current)) {
1264
+ failure(`Property "${segment}" does not exist`);
1265
+ }
1266
+ current = current[segment];
1267
+ } else {
1268
+ if (!Array.isArray(current)) {
1269
+ failure(`Expected array at path segment ${segment}`);
1270
+ }
1271
+ if (segment < 0 || segment >= current.length) {
1272
+ failure(`Index ${segment} out of bounds`);
1273
+ }
1274
+ current = current[segment];
1275
+ }
1276
+ }
1277
+ return current;
1278
+ }
1279
+ function applyOp(state, op, cloneValues) {
1280
+ const container = resolvePath(state, op.path);
1281
+ switch (op.kind) {
1282
+ case "set":
1283
+ if (!isObject(container) || Array.isArray(container)) {
1284
+ failure("set requires object container");
1285
+ }
1286
+ container[op.key] = cloneValues ? deepClone(op.value) : op.value;
1287
+ break;
1288
+ case "delete":
1289
+ if (!isObject(container) || Array.isArray(container)) {
1290
+ failure("delete requires object container");
1291
+ }
1292
+ delete container[op.key];
1293
+ break;
1294
+ case "splice": {
1295
+ if (!Array.isArray(container)) {
1296
+ failure("splice requires array container");
1297
+ }
1298
+ const safeIndex = Math.min(op.index, container.length);
1299
+ container.splice(
1300
+ safeIndex,
1301
+ op.deleteCount,
1302
+ ...cloneValues ? op.inserts.map((v) => deepClone(v)) : op.inserts
1303
+ );
1304
+ break;
1305
+ }
1306
+ case "addToSet":
1307
+ if (!Array.isArray(container)) {
1308
+ failure("addToSet requires array container");
1309
+ }
1310
+ if (!container.some((item) => deepEqual(item, op.value))) {
1311
+ container.push(cloneValues ? deepClone(op.value) : op.value);
1312
+ }
1313
+ break;
1314
+ case "deleteFromSet":
1315
+ if (!Array.isArray(container)) {
1316
+ failure("deleteFromSet requires array container");
1317
+ }
1318
+ for (let i = container.length - 1; i >= 0; i--) {
1319
+ if (deepEqual(container[i], op.value)) {
1320
+ container.splice(i, 1);
1321
+ }
1322
+ }
1323
+ break;
1324
+ default:
1325
+ throw failure(`Unknown operation kind: ${op.kind}`);
1326
+ }
1327
+ }
1328
+ function applyOps(ops, target, options) {
1329
+ var _a;
1330
+ const cloneValues = (_a = options == null ? void 0 : options.cloneValues) != null ? _a : true;
1331
+ for (const op of ops) {
1332
+ applyOp(target, op, cloneValues);
1333
+ }
1334
+ }
1335
+ export {
1336
+ applyOps,
1337
+ createStateSyncLog
1338
+ };
1339
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGUtc3luYy1sb2cuZXNtLm1qcyIsInNvdXJjZXMiOlsiLi4vc3JjL2NoZWNrcG9pbnRVdGlscy50cyIsIi4uL3NyYy9lcnJvci50cyIsIi4uL3NyYy9jaGVja3BvaW50cy50cyIsIi4uLy4uLy4uL25vZGVfbW9kdWxlcy8ucG5wbS9mYXN0LWRlZXAtZXF1YWxAMy4xLjMvbm9kZV9tb2R1bGVzL2Zhc3QtZGVlcC1lcXVhbC9pbmRleC5qcyIsIi4uLy4uLy4uL25vZGVfbW9kdWxlcy8ucG5wbS9uYW5vaWRANS4xLjYvbm9kZV9tb2R1bGVzL25hbm9pZC91cmwtYWxwaGFiZXQvaW5kZXguanMiLCIuLi8uLi8uLi9ub2RlX21vZHVsZXMvLnBucG0vbmFub2lkQDUuMS42L25vZGVfbW9kdWxlcy9uYW5vaWQvaW5kZXguYnJvd3Nlci5qcyIsIi4uLy4uLy4uL25vZGVfbW9kdWxlcy8ucG5wbS9yZmRjQDEuNC4xL25vZGVfbW9kdWxlcy9yZmRjL2luZGV4LmpzIiwiLi4vc3JjL3V0aWxzLnRzIiwiLi4vc3JjL2RyYWZ0LnRzIiwiLi4vc3JjL3JlY29uY2lsZS50cyIsIi4uL3NyYy90eFRpbWVzdGFtcC50cyIsIi4uL3NyYy9Tb3J0ZWRUeEVudHJ5LnRzIiwiLi4vc3JjL1N0YXRlQ2FsY3VsYXRvci50cyIsIi4uL3NyYy9jbGllbnRTdGF0ZS50cyIsIi4uL3NyYy90eExvZy50cyIsIi4uL3NyYy9jcmVhdGVTdGF0ZVN5bmNMb2cudHMiLCIuLi9zcmMvb3BlcmF0aW9ucy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBZIGZyb20gXCJ5anNcIlxuaW1wb3J0IHsgdHlwZSBDaGVja3BvaW50UmVjb3JkLCBwYXJzZUNoZWNrcG9pbnRLZXkgfSBmcm9tIFwiLi9jaGVja3BvaW50c1wiXG5cbi8qKlxuICogRGV0ZXJtaW5lcyB0aGUgZmluYWxpemVkIGVwb2NoIGFuZCBpdHMgY2Fub25pY2FsIGNoZWNrcG9pbnQgaW4gYSBzaW5nbGUgcGFzcy5cbiAqXG4gKiBQb2xpY3kgQTogVGhlIGZpbmFsaXplZCBlcG9jaCBpcyB0aGUgbW9zdCByZWNlbnQgZXBvY2ggd2l0aCBhIGNoZWNrcG9pbnQuXG4gKiBDYW5vbmljYWwgY2hlY2twb2ludDogVGhlIGNoZWNrcG9pbnQgd2l0aCBoaWdoZXN0IHR4Q291bnQgZm9yIHRoYXQgZXBvY2hcbiAqICh0aWUtYnJlYWs6IGxvd2VzdCBjbGllbnRJZCBhbHBoYWJldGljYWxseSkuXG4gKlxuICogUmV0dXJucyB7IGZpbmFsaXplZEVwb2NoOiAtMSwgY2hlY2twb2ludDogbnVsbCB9IGlmIG5vIGNoZWNrcG9pbnRzIGV4aXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmluYWxpemVkRXBvY2hBbmRDaGVja3BvaW50KHlDaGVja3BvaW50OiBZLk1hcDxDaGVja3BvaW50UmVjb3JkPik6IHtcbiAgZmluYWxpemVkRXBvY2g6IG51bWJlclxuICBjaGVja3BvaW50OiBDaGVja3BvaW50UmVjb3JkIHwgbnVsbFxufSB7XG4gIGxldCBtYXhFcG9jaCA9IC0xXG4gIGxldCBiZXN0OiBDaGVja3BvaW50UmVjb3JkIHwgbnVsbCA9IG51bGxcbiAgbGV0IGJlc3RUeENvdW50ID0gLTFcbiAgbGV0IGJlc3RDbGllbnRJZCA9IFwiXCJcblxuICBmb3IgKGNvbnN0IFtrZXksIGNwXSBvZiB5Q2hlY2twb2ludC5lbnRyaWVzKCkpIHtcbiAgICBjb25zdCB7IGVwb2NoLCBjbGllbnRJZCB9ID0gcGFyc2VDaGVja3BvaW50S2V5KGtleSlcblxuICAgIGlmIChlcG9jaCA+IG1heEVwb2NoKSB7XG4gICAgICAvLyBOZXcgaGlnaGVzdCBlcG9jaCAtIHJlc2V0IGJlc3QgY2hlY2twb2ludCB0cmFja2luZ1xuICAgICAgbWF4RXBvY2ggPSBlcG9jaFxuICAgICAgYmVzdCA9IGNwXG4gICAgICBiZXN0VHhDb3VudCA9IGNwLnR4Q291bnRcbiAgICAgIGJlc3RDbGllbnRJZCA9IGNsaWVudElkXG4gICAgfSBlbHNlIGlmIChlcG9jaCA9PT0gbWF4RXBvY2gpIHtcbiAgICAgIC8vIFNhbWUgZXBvY2ggLSBjaGVjayBpZiB0aGlzIGlzIGEgYmV0dGVyIGNhbm9uaWNhbCBjaGVja3BvaW50XG4gICAgICAvLyBQcmltYXJ5OiBoaWdoZXIgdHhDb3VudCB3aW5zXG4gICAgICAvLyBTZWNvbmRhcnkgKHRpZS1icmVhayk6IGxvd2VyIGNsaWVudElkIChhbHBoYWJldGljYWxseSkgd2luc1xuICAgICAgaWYgKGNwLnR4Q291bnQgPiBiZXN0VHhDb3VudCB8fCAoY3AudHhDb3VudCA9PT0gYmVzdFR4Q291bnQgJiYgY2xpZW50SWQgPCBiZXN0Q2xpZW50SWQpKSB7XG4gICAgICAgIGJlc3QgPSBjcFxuICAgICAgICBiZXN0VHhDb3VudCA9IGNwLnR4Q291bnRcbiAgICAgICAgYmVzdENsaWVudElkID0gY2xpZW50SWRcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBmaW5hbGl6ZWRFcG9jaDogbWF4RXBvY2gsIGNoZWNrcG9pbnQ6IGJlc3QgfVxufVxuIiwiZXhwb3J0IGNsYXNzIFN0YXRlU3luY0xvZ0Vycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZykge1xuICAgIHN1cGVyKG1zZylcblxuICAgIC8vIFNldCB0aGUgcHJvdG90eXBlIGV4cGxpY2l0bHkgZm9yIGJldHRlciBpbnN0YW5jZW9mIHN1cHBvcnRcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgU3RhdGVTeW5jTG9nRXJyb3IucHJvdG90eXBlKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmYWlsdXJlKG1lc3NhZ2U6IHN0cmluZyk6IG5ldmVyIHtcbiAgdGhyb3cgbmV3IFN0YXRlU3luY0xvZ0Vycm9yKG1lc3NhZ2UpXG59XG4iLCJpbXBvcnQgKiBhcyBZIGZyb20gXCJ5anNcIlxuaW1wb3J0IHsgQ2xpZW50SWQgfSBmcm9tIFwiLi9DbGllbnRJZFwiXG5pbXBvcnQgeyBnZXRGaW5hbGl6ZWRFcG9jaEFuZENoZWNrcG9pbnQgfSBmcm9tIFwiLi9jaGVja3BvaW50VXRpbHNcIlxuaW1wb3J0IHsgQ2xpZW50U3RhdGUgfSBmcm9tIFwiLi9jbGllbnRTdGF0ZVwiXG5pbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4vZXJyb3JcIlxuaW1wb3J0IHsgSlNPTk9iamVjdCB9IGZyb20gXCIuL2pzb25cIlxuaW1wb3J0IHsgVHhSZWNvcmQgfSBmcm9tIFwiLi9UeFJlY29yZFwiXG5pbXBvcnQgeyBUeFRpbWVzdGFtcEtleSB9IGZyb20gXCIuL3R4VGltZXN0YW1wXCJcblxuLyoqXG4gKiBXYXRlcm1hcmtpbmcgZm9yIGRlZHVwbGljYXRpb24gYW5kIHBydW5pbmcuXG4gKiAtIG1heENsb2NrOiBBbGwgdHhzIGZyb20gdGhpcyBjbGllbnQgd2l0aCBjbG9jayA8PSBtYXhDbG9jayBhcmUgRklOQUxJWkVELlxuICogLSBtYXhXYWxsQ2xvY2s6IFRoZSBsYXN0IHRpbWUgd2Ugc2F3IHRoaXMgY2xpZW50IGFjdGl2ZSAoZm9yIHBydW5pbmcpLlxuICovXG50eXBlIENsaWVudFdhdGVybWFyayA9IFJlYWRvbmx5PHtcbiAgbWF4Q2xvY2s6IG51bWJlclxuICBtYXhXYWxsQ2xvY2s6IG51bWJlclxufT5cblxuLyoqXG4gKiBXYXRlcm1hcmtzIGZvciBhbGwgY2xpZW50cy5cbiAqL1xuZXhwb3J0IHR5cGUgQ2xpZW50V2F0ZXJtYXJrcyA9IFJlY29yZDxDbGllbnRJZCwgQ2xpZW50V2F0ZXJtYXJrPlxuXG4vKipcbiAqIEEgc25hcHNob3Qgb2YgdGhlIHN0YXRlIGF0IHRoZSBlbmQgb2YgYSBzcGVjaWZpYyBlcG9jaC5cbiAqL1xuZXhwb3J0IHR5cGUgQ2hlY2twb2ludFJlY29yZCA9IHtcbiAgc3RhdGU6IEpTT05PYmplY3QgLy8gVGhlIGRvY3VtZW50IHN0YXRlXG4gIHdhdGVybWFya3M6IENsaWVudFdhdGVybWFya3MgLy8gRGVkdXAvUHJ1bmluZyBpbmZvXG4gIHR4Q291bnQ6IG51bWJlciAvLyBUaWUtYnJlYWtlciBmb3IgY2Fub25pY2FsIHNlbGVjdGlvblxuICBtaW5XYWxsQ2xvY2s6IG51bWJlciAvLyBSZWZlcmVuY2UgdGltZSBmb3IgdGhpcyBlcG9jaCAoZGV0ZXJtaW5pc3RpYyBwcnVuaW5nKVxufVxuXG4vKipcbiAqIFVuaXF1ZSBJRCBmb3IgYSBjaGVja3BvaW50LlxuICogRm9ybWF0OiBgJHtlcG9jaH07JHt0eENvdW50fTske2NsaWVudElkfWBcbiAqL1xuZXhwb3J0IHR5cGUgQ2hlY2twb2ludEtleSA9IHN0cmluZ1xuXG4vKipcbiAqIERhdGEgZXh0cmFjdGVkIGZyb20gYSBjaGVja3BvaW50IGtleS5cbiAqL1xuZXhwb3J0IHR5cGUgQ2hlY2twb2ludEtleURhdGEgPSB7XG4gIGVwb2NoOiBudW1iZXJcbiAgdHhDb3VudDogbnVtYmVyXG4gIGNsaWVudElkOiBDbGllbnRJZFxufVxuXG4vKipcbiAqIENvbnZlcnRzIGNoZWNrcG9pbnQga2V5IGRhdGEgY29tcG9uZW50cyB0byBhIGtleSBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrcG9pbnRLZXlEYXRhVG9LZXkoZGF0YTogQ2hlY2twb2ludEtleURhdGEpOiBDaGVja3BvaW50S2V5IHtcbiAgcmV0dXJuIGAke2RhdGEuZXBvY2h9OyR7ZGF0YS50eENvdW50fTske2RhdGEuY2xpZW50SWR9YFxufVxuXG4vKipcbiAqIEhlbHBlciB0byBwYXJzZSBjaGVja3BvaW50IGtleXMuXG4gKiBDaGVja3BvaW50IGtleXMgaGF2ZSBmb3JtYXQ6IGAke2Vwb2NofTske3R4Q291bnR9OyR7Y2xpZW50SWR9YFxuICogVGhyb3dzIGlmIGtleSBpcyBtYWxmb3JtZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUNoZWNrcG9pbnRLZXkoa2V5OiBDaGVja3BvaW50S2V5KTogQ2hlY2twb2ludEtleURhdGEge1xuICBjb25zdCBpMSA9IGtleS5pbmRleE9mKFwiO1wiKVxuICBjb25zdCBpMiA9IGtleS5pbmRleE9mKFwiO1wiLCBpMSArIDEpXG5cbiAgaWYgKGkxID09PSAtMSB8fCBpMiA9PT0gLTEpIHtcbiAgICBmYWlsdXJlKGBNYWxmb3JtZWQgY2hlY2twb2ludCBrZXk6ICR7a2V5fWApXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGVwb2NoOiBOdW1iZXIucGFyc2VJbnQoa2V5LnN1YnN0cmluZygwLCBpMSksIDEwKSxcbiAgICB0eENvdW50OiBOdW1iZXIucGFyc2VJbnQoa2V5LnN1YnN0cmluZyhpMSArIDEsIGkyKSwgMTApLFxuICAgIGNsaWVudElkOiBrZXkuc3Vic3RyaW5nKGkyICsgMSksXG4gIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgcGVyaW9kaWNhbGx5IChlLmcuIGJ5IGEgc2VydmVyIG9yIGxlYWRlciBjbGllbnQpIHRvIGZpbmFsaXplIHRoZSBlcG9jaC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNoZWNrcG9pbnQoXG4gIHlUeDogWS5NYXA8VHhSZWNvcmQ+LFxuICB5Q2hlY2twb2ludDogWS5NYXA8Q2hlY2twb2ludFJlY29yZD4sXG4gIGNsaWVudFN0YXRlOiBDbGllbnRTdGF0ZSxcbiAgYWN0aXZlRXBvY2g6IG51bWJlcixcbiAgY3VycmVudFN0YXRlOiBKU09OT2JqZWN0LFxuICBteUNsaWVudElkOiBzdHJpbmdcbik6IHZvaWQge1xuICAvLyAxLiBTdGFydCB3aXRoIHByZXZpb3VzIHdhdGVybWFya3MgKGZyb20gZmluYWxpemVkIGVwb2NoID0gYWN0aXZlRXBvY2ggLSAxKVxuICBjb25zdCB7IGNoZWNrcG9pbnQ6IHByZXZDUCB9ID0gZ2V0RmluYWxpemVkRXBvY2hBbmRDaGVja3BvaW50KHlDaGVja3BvaW50KVxuICBjb25zdCBuZXdXYXRlcm1hcmtzID0gcHJldkNQID8geyAuLi5wcmV2Q1Aud2F0ZXJtYXJrcyB9IDoge31cblxuICAvLyBHZXQgYWN0aXZlIHR4cyB1c2luZyBjYWNoZWQgc29ydGVkIG9yZGVyIChmaWx0ZXIgYnkgZXBvY2gpXG4gIC8vIEZJTFRFUiBJUyBSRVFVSVJFRDpcbiAgLy8gQWx0aG91Z2ggd2UgYXJlIGZpbmFsaXppbmcgJ2FjdGl2ZUVwb2NoJywgb3RoZXIgcGVlcnMgbWF5IGhhdmUgYWxyZWFkeVxuICAvLyBhZHZhbmNlZCB0byB0aGUgbmV4dCBlcG9jaCBhbmQgc3RhcnRlZCBzeW5jaW5nIHRob3NlIHR4cy5cbiAgLy8gV2UgbXVzdCBlbnN1cmUgdGhpcyBjaGVja3BvaW50IE9OTFkgY29udGFpbnMgdHhzIGZyb20gJ2FjdGl2ZUVwb2NoJy5cbiAgLy8gVXNpbmcgc3RhdGVDYWxjdWxhdG9yLmdldFNvcnRlZFR4cyBhdm9pZHMgcmVkdW5kYW50IGtleSBwYXJzaW5nICh0aW1lc3RhbXBzIGFyZSBjYWNoZWQpLlxuICAvL1xuICAvLyBPUFRJTUlaQVRJT046IFNpbmNlIHNvcnRlZFR4cyBpcyBzb3J0ZWQgYnkgZXBvY2ggKHByaW1hcnkga2V5KSBhbmQgcGFzdCBlcG9jaHNcbiAgLy8gYXJlIHBydW5lZCwgd2Ugb25seSBuZWVkIHRvIGZpbmQgdGhlIHJpZ2h0IGJvdW5kYXJ5LiBGdXR1cmUgZXBvY2hzIGFyZSByYXJlLFxuICAvLyBzbyBhIHNpbXBsZSBsaW5lYXIgc2VhcmNoIGZyb20gdGhlIHJpZ2h0IGlzIGVmZmljaWVudCAodHlwaWNhbGx5IDAtMSBpdGVyYXRpb25zKS5cbiAgY29uc3Qgc29ydGVkVHhzID0gY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yLmdldFNvcnRlZFR4cygpXG5cbiAgLy8gRmluZCBlbmQgYm91bmRhcnkgYnkgc2VhcmNoaW5nIGZyb20gcmlnaHQgKHNraXAgYW55IGZ1dHVyZSBlcG9jaCBlbnRyaWVzKVxuICBsZXQgZW5kSW5kZXggPSBzb3J0ZWRUeHMubGVuZ3RoXG4gIHdoaWxlIChlbmRJbmRleCA+IDAgJiYgc29ydGVkVHhzW2VuZEluZGV4IC0gMV0udHhUaW1lc3RhbXAuZXBvY2ggPiBhY3RpdmVFcG9jaCkge1xuICAgIGVuZEluZGV4LS1cbiAgfVxuXG4gIC8vIFNsaWNlIGZyb20gc3RhcnQgdG8gZW5kSW5kZXggKHBhc3QgZXBvY2hzIGFyZSBwcnVuZWQsIHNvIHRoZXNlIGFyZSBhbGwgYWN0aXZlRXBvY2gpXG4gIGNvbnN0IGFjdGl2ZVR4cyA9IHNvcnRlZFR4cy5zbGljZSgwLCBlbmRJbmRleClcblxuICBpZiAoYWN0aXZlVHhzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiAvLyBEbyBub3RoaW5nIGlmIG5vIHR4cyAocHJldmVudHMgZW1wdHkgZXBvY2hzKVxuICB9XG5cbiAgLy8gMi4gVXBkYXRlIHdhdGVybWFya3MgYmFzZWQgb24gT0JTRVJWRUQgYWN0aXZlIHR4cyBhbmQgY2FsY3VsYXRlIG1pbldhbGxDbG9ja1xuICAvLyBOT1RFOiBXZSBjYW5ub3QgdXNlIGFjdGl2ZVR4c1swXS50eFRpbWVzdGFtcC53YWxsQ2xvY2sgZm9yIG1pbldhbGxDbG9jayBiZWNhdXNlXG4gIC8vIHR4cyBhcmUgc29ydGVkIGJ5IExhbXBvcnQgY2xvY2sgKGVwb2NoIOKGkiBjbG9jayDihpIgY2xpZW50SWQpLCBub3QgYnkgd2FsbENsb2NrLlxuICAvLyBBIGNsaWVudCBtYXkgaGF2ZSBhIGhpZ2ggTGFtcG9ydCBjbG9jayBidXQgZWFybHkgd2FsbENsb2NrIGR1ZSB0byBjbG9jayBkcmlmdFxuICAvLyBvciByZWNlaXZpbmcgbWFueSBtZXNzYWdlcyBiZWZvcmUgZW1pdHRpbmcuXG4gIGxldCBtaW5XYWxsQ2xvY2sgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFlcbiAgbGV0IHR4Q291bnQgPSAwXG4gIGZvciAoY29uc3QgZW50cnkgb2YgYWN0aXZlVHhzKSB7XG4gICAgY29uc3QgdHMgPSBlbnRyeS50eFRpbWVzdGFtcFxuXG4gICAgLy8gVHJhY2sgbWluIHdhbGxDbG9jayBmb3IgZGV0ZXJtaW5pc3RpYyBwcnVuaW5nIHJlZmVyZW5jZVxuICAgIGlmICh0cy53YWxsQ2xvY2sgPCBtaW5XYWxsQ2xvY2spIHtcbiAgICAgIG1pbldhbGxDbG9jayA9IHRzLndhbGxDbG9ja1xuICAgIH1cblxuICAgIGNvbnN0IG5ld1dtID0gbmV3V2F0ZXJtYXJrc1t0cy5jbGllbnRJZF1cbiAgICAgID8geyAuLi5uZXdXYXRlcm1hcmtzW3RzLmNsaWVudElkXSB9XG4gICAgICA6IHsgbWF4Q2xvY2s6IC0xLCBtYXhXYWxsQ2xvY2s6IDAgfVxuXG4gICAgaWYgKHRzLmNsb2NrID4gbmV3V20ubWF4Q2xvY2spIHtcbiAgICAgIG5ld1dtLm1heENsb2NrID0gdHMuY2xvY2tcbiAgICAgIG5ld1dtLm1heFdhbGxDbG9jayA9IHRzLndhbGxDbG9ja1xuICAgIH1cbiAgICBuZXdXYXRlcm1hcmtzW3RzLmNsaWVudElkXSA9IG5ld1dtXG4gICAgdHhDb3VudCsrXG4gIH1cblxuICAvLyAzLiBQcnVuZSBJbmFjdGl2ZSBXYXRlcm1hcmtzIChEZXRlcm1pbmlzdGljKVxuICAvLyBVc2VzIG1pbldhbGxDbG9jayBzbyBhbGwgY2xpZW50cyBhZ3JlZSBvbiBleGFjdGx5IHdobyB0byBwcnVuZS5cbiAgZm9yIChjb25zdCBjbGllbnRJZCBpbiBuZXdXYXRlcm1hcmtzKSB7XG4gICAgaWYgKG1pbldhbGxDbG9jayAtIG5ld1dhdGVybWFya3NbY2xpZW50SWRdLm1heFdhbGxDbG9jayA+IGNsaWVudFN0YXRlLnJldGVudGlvbldpbmRvd01zKSB7XG4gICAgICBkZWxldGUgbmV3V2F0ZXJtYXJrc1tjbGllbnRJZF1cbiAgICB9XG4gIH1cblxuICAvLyA0LiBTYXZlIENoZWNrcG9pbnRcbiAgY29uc3QgY3BLZXkgPSBjaGVja3BvaW50S2V5RGF0YVRvS2V5KHtcbiAgICBlcG9jaDogYWN0aXZlRXBvY2gsXG4gICAgdHhDb3VudCxcbiAgICBjbGllbnRJZDogbXlDbGllbnRJZCxcbiAgfSlcbiAgeUNoZWNrcG9pbnQuc2V0KGNwS2V5LCB7XG4gICAgc3RhdGU6IGN1cnJlbnRTdGF0ZSwgLy8gUmVzcG9uc2liaWxpdHkgZm9yIGNsb25pbmcgaXMgbW92ZWQgdG8gdGhlIGNhbGxlciBpZiBuZWVkZWRcbiAgICB3YXRlcm1hcmtzOiBuZXdXYXRlcm1hcmtzLFxuICAgIHR4Q291bnQsXG4gICAgbWluV2FsbENsb2NrLFxuICB9KVxuXG4gIC8vIDUuIEVhcmx5IHR4IHBydW5pbmcgKE9wdGltaXphdGlvbilcbiAgLy8gRGVsZXRlIGFsbCB0eHMgZnJvbSB0aGUgbm93LWZpbmFsaXplZCBlcG9jaFxuICAvLyBUaGlzIHJlZHVjZXMgbWVtb3J5IHByZXNzdXJlIGluc3RlYWQgb2Ygd2FpdGluZyBmb3IgY2xlYW51cExvZ1xuICBjb25zdCBrZXlzVG9EZWxldGU6IFR4VGltZXN0YW1wS2V5W10gPSBbXVxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGFjdGl2ZVR4cykge1xuICAgIHlUeC5kZWxldGUoZW50cnkudHhUaW1lc3RhbXBLZXkpXG4gICAga2V5c1RvRGVsZXRlLnB1c2goZW50cnkudHhUaW1lc3RhbXBLZXkpXG4gIH1cbiAgY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yLnJlbW92ZVR4cyhrZXlzVG9EZWxldGUpXG59XG5cbi8qKlxuICogR2FyYmFnZSBjb2xsZWN0cyBvbGQgY2hlY2twb2ludHMuXG4gKiBTaG91bGQgYmUgY2FsbGVkIHBlcmlvZGljYWxseSB0byBwcmV2ZW50IHVuYm91bmRlZCBncm93dGggb2YgeUNoZWNrcG9pbnQuXG4gKlxuICogS2VlcHMgb25seSB0aGUgY2Fub25pY2FsIGNoZWNrcG9pbnQgZm9yIHRoZSBmaW5hbGl6ZWQgZXBvY2guXG4gKiBFdmVyeXRoaW5nIGVsc2UgaXMgZGVsZXRlZCAob2xkIGVwb2NocyArIG5vbi1jYW5vbmljYWwpLlxuICpcbiAqIE5vdGU6IFRoZSBhY3RpdmUgZXBvY2ggbmV2ZXIgaGFzIGNoZWNrcG9pbnRzIC0gY3JlYXRpbmcgYSBjaGVja3BvaW50XG4gKiBmb3IgYW4gZXBvY2ggaW1tZWRpYXRlbHkgbWFrZXMgaXQgZmluYWxpemVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJ1bmVDaGVja3BvaW50cyhcbiAgeUNoZWNrcG9pbnQ6IFkuTWFwPENoZWNrcG9pbnRSZWNvcmQ+LFxuICBmaW5hbGl6ZWRFcG9jaDogbnVtYmVyXG4pOiB2b2lkIHtcbiAgLy8gRmluZCB0aGUgY2Fub25pY2FsIGNoZWNrcG9pbnQgYW5kIGl0cyBrZXkgaW4gb25lIHBhc3NcbiAgbGV0IGNhbm9uaWNhbEtleTogQ2hlY2twb2ludEtleSB8IG51bGwgPSBudWxsXG4gIGxldCBiZXN0VHhDb3VudCA9IC0xXG5cbiAgZm9yIChjb25zdCBba2V5XSBvZiB5Q2hlY2twb2ludC5lbnRyaWVzKCkpIHtcbiAgICBjb25zdCB7IGVwb2NoLCB0eENvdW50IH0gPSBwYXJzZUNoZWNrcG9pbnRLZXkoa2V5KVxuICAgIGlmIChlcG9jaCA9PT0gZmluYWxpemVkRXBvY2ggJiYgdHhDb3VudCA+IGJlc3RUeENvdW50KSB7XG4gICAgICBjYW5vbmljYWxLZXkgPSBrZXlcbiAgICAgIGJlc3RUeENvdW50ID0gdHhDb3VudFxuICAgIH1cbiAgfVxuXG4gIC8vIERlbGV0ZSBldmVyeXRoaW5nIGV4Y2VwdCB0aGUgY2Fub25pY2FsIGNoZWNrcG9pbnRcbiAgZm9yIChjb25zdCBrZXkgb2YgeUNoZWNrcG9pbnQua2V5cygpKSB7XG4gICAgaWYgKGtleSAhPT0gY2Fub25pY2FsS2V5KSB7XG4gICAgICB5Q2hlY2twb2ludC5kZWxldGUoa2V5KVxuICAgIH1cbiAgfVxufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBkbyBub3QgZWRpdCAuanMgZmlsZXMgZGlyZWN0bHkgLSBlZGl0IHNyYy9pbmRleC5qc3RcblxuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXF1YWwoYSwgYikge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIHRydWU7XG5cbiAgaWYgKGEgJiYgYiAmJiB0eXBlb2YgYSA9PSAnb2JqZWN0JyAmJiB0eXBlb2YgYiA9PSAnb2JqZWN0Jykge1xuICAgIGlmIChhLmNvbnN0cnVjdG9yICE9PSBiLmNvbnN0cnVjdG9yKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgbGVuZ3RoLCBpLCBrZXlzO1xuICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICBsZW5ndGggPSBhLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggIT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgIGZvciAoaSA9IGxlbmd0aDsgaS0tICE9PSAwOylcbiAgICAgICAgaWYgKCFlcXVhbChhW2ldLCBiW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG5cblxuICAgIGlmIChhLmNvbnN0cnVjdG9yID09PSBSZWdFeHApIHJldHVybiBhLnNvdXJjZSA9PT0gYi5zb3VyY2UgJiYgYS5mbGFncyA9PT0gYi5mbGFncztcbiAgICBpZiAoYS52YWx1ZU9mICE9PSBPYmplY3QucHJvdG90eXBlLnZhbHVlT2YpIHJldHVybiBhLnZhbHVlT2YoKSA9PT0gYi52YWx1ZU9mKCk7XG4gICAgaWYgKGEudG9TdHJpbmcgIT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcpIHJldHVybiBhLnRvU3RyaW5nKCkgPT09IGIudG9TdHJpbmcoKTtcblxuICAgIGtleXMgPSBPYmplY3Qua2V5cyhhKTtcbiAgICBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICBpZiAobGVuZ3RoICE9PSBPYmplY3Qua2V5cyhiKS5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgIGZvciAoaSA9IGxlbmd0aDsgaS0tICE9PSAwOylcbiAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIGtleXNbaV0pKSByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSAhPT0gMDspIHtcbiAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuXG4gICAgICBpZiAoIWVxdWFsKGFba2V5XSwgYltrZXldKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gdHJ1ZSBpZiBib3RoIE5hTiwgZmFsc2Ugb3RoZXJ3aXNlXG4gIHJldHVybiBhIT09YSAmJiBiIT09Yjtcbn07XG4iLCJleHBvcnQgY29uc3QgdXJsQWxwaGFiZXQgPVxuICAndXNlYW5kb20tMjZUMTk4MzQwUFg3NXB4SkFDS1ZFUllNSU5EQlVTSFdPTEZfR1FaYmZnaGprbHF2d3l6cmljdCdcbiIsIi8qIEB0cy1zZWxmLXR5cGVzPVwiLi9pbmRleC5kLnRzXCIgKi9cbmltcG9ydCB7IHVybEFscGhhYmV0IGFzIHNjb3BlZFVybEFscGhhYmV0IH0gZnJvbSAnLi91cmwtYWxwaGFiZXQvaW5kZXguanMnXG5leHBvcnQgeyB1cmxBbHBoYWJldCB9IGZyb20gJy4vdXJsLWFscGhhYmV0L2luZGV4LmpzJ1xuZXhwb3J0IGxldCByYW5kb20gPSBieXRlcyA9PiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKG5ldyBVaW50OEFycmF5KGJ5dGVzKSlcbmV4cG9ydCBsZXQgY3VzdG9tUmFuZG9tID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSwgZ2V0UmFuZG9tKSA9PiB7XG4gIGxldCBtYXNrID0gKDIgPDwgTWF0aC5sb2cyKGFscGhhYmV0Lmxlbmd0aCAtIDEpKSAtIDFcbiAgbGV0IHN0ZXAgPSAtfigoMS42ICogbWFzayAqIGRlZmF1bHRTaXplKSAvIGFscGhhYmV0Lmxlbmd0aClcbiAgcmV0dXJuIChzaXplID0gZGVmYXVsdFNpemUpID0+IHtcbiAgICBsZXQgaWQgPSAnJ1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBsZXQgYnl0ZXMgPSBnZXRSYW5kb20oc3RlcClcbiAgICAgIGxldCBqID0gc3RlcCB8IDBcbiAgICAgIHdoaWxlIChqLS0pIHtcbiAgICAgICAgaWQgKz0gYWxwaGFiZXRbYnl0ZXNbal0gJiBtYXNrXSB8fCAnJ1xuICAgICAgICBpZiAoaWQubGVuZ3RoID49IHNpemUpIHJldHVybiBpZFxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuZXhwb3J0IGxldCBjdXN0b21BbHBoYWJldCA9IChhbHBoYWJldCwgc2l6ZSA9IDIxKSA9PlxuICBjdXN0b21SYW5kb20oYWxwaGFiZXQsIHNpemUgfCAwLCByYW5kb20pXG5leHBvcnQgbGV0IG5hbm9pZCA9IChzaXplID0gMjEpID0+IHtcbiAgbGV0IGlkID0gJydcbiAgbGV0IGJ5dGVzID0gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheSgoc2l6ZSB8PSAwKSkpXG4gIHdoaWxlIChzaXplLS0pIHtcbiAgICBpZCArPSBzY29wZWRVcmxBbHBoYWJldFtieXRlc1tzaXplXSAmIDYzXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwiJ3VzZSBzdHJpY3QnXG5tb2R1bGUuZXhwb3J0cyA9IHJmZGNcblxuZnVuY3Rpb24gY29weUJ1ZmZlciAoY3VyKSB7XG4gIGlmIChjdXIgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oY3VyKVxuICB9XG5cbiAgcmV0dXJuIG5ldyBjdXIuY29uc3RydWN0b3IoY3VyLmJ1ZmZlci5zbGljZSgpLCBjdXIuYnl0ZU9mZnNldCwgY3VyLmxlbmd0aClcbn1cblxuZnVuY3Rpb24gcmZkYyAob3B0cykge1xuICBvcHRzID0gb3B0cyB8fCB7fVxuICBpZiAob3B0cy5jaXJjbGVzKSByZXR1cm4gcmZkY0NpcmNsZXMob3B0cylcblxuICBjb25zdCBjb25zdHJ1Y3RvckhhbmRsZXJzID0gbmV3IE1hcCgpXG4gIGNvbnN0cnVjdG9ySGFuZGxlcnMuc2V0KERhdGUsIChvKSA9PiBuZXcgRGF0ZShvKSlcbiAgY29uc3RydWN0b3JIYW5kbGVycy5zZXQoTWFwLCAobywgZm4pID0+IG5ldyBNYXAoY2xvbmVBcnJheShBcnJheS5mcm9tKG8pLCBmbikpKVxuICBjb25zdHJ1Y3RvckhhbmRsZXJzLnNldChTZXQsIChvLCBmbikgPT4gbmV3IFNldChjbG9uZUFycmF5KEFycmF5LmZyb20obyksIGZuKSkpXG4gIGlmIChvcHRzLmNvbnN0cnVjdG9ySGFuZGxlcnMpIHtcbiAgICBmb3IgKGNvbnN0IGhhbmRsZXIgb2Ygb3B0cy5jb25zdHJ1Y3RvckhhbmRsZXJzKSB7XG4gICAgICBjb25zdHJ1Y3RvckhhbmRsZXJzLnNldChoYW5kbGVyWzBdLCBoYW5kbGVyWzFdKVxuICAgIH1cbiAgfVxuXG4gIGxldCBoYW5kbGVyID0gbnVsbFxuXG4gIHJldHVybiBvcHRzLnByb3RvID8gY2xvbmVQcm90byA6IGNsb25lXG5cbiAgZnVuY3Rpb24gY2xvbmVBcnJheSAoYSwgZm4pIHtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoYSlcbiAgICBjb25zdCBhMiA9IG5ldyBBcnJheShrZXlzLmxlbmd0aClcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGsgPSBrZXlzW2ldXG4gICAgICBjb25zdCBjdXIgPSBhW2tdXG4gICAgICBpZiAodHlwZW9mIGN1ciAhPT0gJ29iamVjdCcgfHwgY3VyID09PSBudWxsKSB7XG4gICAgICAgIGEyW2tdID0gY3VyXG4gICAgICB9IGVsc2UgaWYgKGN1ci5jb25zdHJ1Y3RvciAhPT0gT2JqZWN0ICYmIChoYW5kbGVyID0gY29uc3RydWN0b3JIYW5kbGVycy5nZXQoY3VyLmNvbnN0cnVjdG9yKSkpIHtcbiAgICAgICAgYTJba10gPSBoYW5kbGVyKGN1ciwgZm4pXG4gICAgICB9IGVsc2UgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhjdXIpKSB7XG4gICAgICAgIGEyW2tdID0gY29weUJ1ZmZlcihjdXIpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhMltrXSA9IGZuKGN1cilcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGEyXG4gIH1cblxuICBmdW5jdGlvbiBjbG9uZSAobykge1xuICAgIGlmICh0eXBlb2YgbyAhPT0gJ29iamVjdCcgfHwgbyA9PT0gbnVsbCkgcmV0dXJuIG9cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvKSkgcmV0dXJuIGNsb25lQXJyYXkobywgY2xvbmUpXG4gICAgaWYgKG8uY29uc3RydWN0b3IgIT09IE9iamVjdCAmJiAoaGFuZGxlciA9IGNvbnN0cnVjdG9ySGFuZGxlcnMuZ2V0KG8uY29uc3RydWN0b3IpKSkge1xuICAgICAgcmV0dXJuIGhhbmRsZXIobywgY2xvbmUpXG4gICAgfVxuICAgIGNvbnN0IG8yID0ge31cbiAgICBmb3IgKGNvbnN0IGsgaW4gbykge1xuICAgICAgaWYgKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspID09PSBmYWxzZSkgY29udGludWVcbiAgICAgIGNvbnN0IGN1ciA9IG9ba11cbiAgICAgIGlmICh0eXBlb2YgY3VyICE9PSAnb2JqZWN0JyB8fCBjdXIgPT09IG51bGwpIHtcbiAgICAgICAgbzJba10gPSBjdXJcbiAgICAgIH0gZWxzZSBpZiAoY3VyLmNvbnN0cnVjdG9yICE9PSBPYmplY3QgJiYgKGhhbmRsZXIgPSBjb25zdHJ1Y3RvckhhbmRsZXJzLmdldChjdXIuY29uc3RydWN0b3IpKSkge1xuICAgICAgICBvMltrXSA9IGhhbmRsZXIoY3VyLCBjbG9uZSlcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KGN1cikpIHtcbiAgICAgICAgbzJba10gPSBjb3B5QnVmZmVyKGN1cilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG8yW2tdID0gY2xvbmUoY3VyKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbzJcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsb25lUHJvdG8gKG8pIHtcbiAgICBpZiAodHlwZW9mIG8gIT09ICdvYmplY3QnIHx8IG8gPT09IG51bGwpIHJldHVybiBvXG4gICAgaWYgKEFycmF5LmlzQXJyYXkobykpIHJldHVybiBjbG9uZUFycmF5KG8sIGNsb25lUHJvdG8pXG4gICAgaWYgKG8uY29uc3RydWN0b3IgIT09IE9iamVjdCAmJiAoaGFuZGxlciA9IGNvbnN0cnVjdG9ySGFuZGxlcnMuZ2V0KG8uY29uc3RydWN0b3IpKSkge1xuICAgICAgcmV0dXJuIGhhbmRsZXIobywgY2xvbmVQcm90bylcbiAgICB9XG4gICAgY29uc3QgbzIgPSB7fVxuICAgIGZvciAoY29uc3QgayBpbiBvKSB7XG4gICAgICBjb25zdCBjdXIgPSBvW2tdXG4gICAgICBpZiAodHlwZW9mIGN1ciAhPT0gJ29iamVjdCcgfHwgY3VyID09PSBudWxsKSB7XG4gICAgICAgIG8yW2tdID0gY3VyXG4gICAgICB9IGVsc2UgaWYgKGN1ci5jb25zdHJ1Y3RvciAhPT0gT2JqZWN0ICYmIChoYW5kbGVyID0gY29uc3RydWN0b3JIYW5kbGVycy5nZXQoY3VyLmNvbnN0cnVjdG9yKSkpIHtcbiAgICAgICAgbzJba10gPSBoYW5kbGVyKGN1ciwgY2xvbmVQcm90bylcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KGN1cikpIHtcbiAgICAgICAgbzJba10gPSBjb3B5QnVmZmVyKGN1cilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG8yW2tdID0gY2xvbmVQcm90byhjdXIpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvMlxuICB9XG59XG5cbmZ1bmN0aW9uIHJmZGNDaXJjbGVzIChvcHRzKSB7XG4gIGNvbnN0IHJlZnMgPSBbXVxuICBjb25zdCByZWZzTmV3ID0gW11cblxuICBjb25zdCBjb25zdHJ1Y3RvckhhbmRsZXJzID0gbmV3IE1hcCgpXG4gIGNvbnN0cnVjdG9ySGFuZGxlcnMuc2V0KERhdGUsIChvKSA9PiBuZXcgRGF0ZShvKSlcbiAgY29uc3RydWN0b3JIYW5kbGVycy5zZXQoTWFwLCAobywgZm4pID0+IG5ldyBNYXAoY2xvbmVBcnJheShBcnJheS5mcm9tKG8pLCBmbikpKVxuICBjb25zdHJ1Y3RvckhhbmRsZXJzLnNldChTZXQsIChvLCBmbikgPT4gbmV3IFNldChjbG9uZUFycmF5KEFycmF5LmZyb20obyksIGZuKSkpXG4gIGlmIChvcHRzLmNvbnN0cnVjdG9ySGFuZGxlcnMpIHtcbiAgICBmb3IgKGNvbnN0IGhhbmRsZXIgb2Ygb3B0cy5jb25zdHJ1Y3RvckhhbmRsZXJzKSB7XG4gICAgICBjb25zdHJ1Y3RvckhhbmRsZXJzLnNldChoYW5kbGVyWzBdLCBoYW5kbGVyWzFdKVxuICAgIH1cbiAgfVxuXG4gIGxldCBoYW5kbGVyID0gbnVsbFxuICByZXR1cm4gb3B0cy5wcm90byA/IGNsb25lUHJvdG8gOiBjbG9uZVxuXG4gIGZ1bmN0aW9uIGNsb25lQXJyYXkgKGEsIGZuKSB7XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGEpXG4gICAgY29uc3QgYTIgPSBuZXcgQXJyYXkoa2V5cy5sZW5ndGgpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBrID0ga2V5c1tpXVxuICAgICAgY29uc3QgY3VyID0gYVtrXVxuICAgICAgaWYgKHR5cGVvZiBjdXIgIT09ICdvYmplY3QnIHx8IGN1ciA9PT0gbnVsbCkge1xuICAgICAgICBhMltrXSA9IGN1clxuICAgICAgfSBlbHNlIGlmIChjdXIuY29uc3RydWN0b3IgIT09IE9iamVjdCAmJiAoaGFuZGxlciA9IGNvbnN0cnVjdG9ySGFuZGxlcnMuZ2V0KGN1ci5jb25zdHJ1Y3RvcikpKSB7XG4gICAgICAgIGEyW2tdID0gaGFuZGxlcihjdXIsIGZuKVxuICAgICAgfSBlbHNlIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoY3VyKSkge1xuICAgICAgICBhMltrXSA9IGNvcHlCdWZmZXIoY3VyKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSByZWZzLmluZGV4T2YoY3VyKVxuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgYTJba10gPSByZWZzTmV3W2luZGV4XVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGEyW2tdID0gZm4oY3VyKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhMlxuICB9XG5cbiAgZnVuY3Rpb24gY2xvbmUgKG8pIHtcbiAgICBpZiAodHlwZW9mIG8gIT09ICdvYmplY3QnIHx8IG8gPT09IG51bGwpIHJldHVybiBvXG4gICAgaWYgKEFycmF5LmlzQXJyYXkobykpIHJldHVybiBjbG9uZUFycmF5KG8sIGNsb25lKVxuICAgIGlmIChvLmNvbnN0cnVjdG9yICE9PSBPYmplY3QgJiYgKGhhbmRsZXIgPSBjb25zdHJ1Y3RvckhhbmRsZXJzLmdldChvLmNvbnN0cnVjdG9yKSkpIHtcbiAgICAgIHJldHVybiBoYW5kbGVyKG8sIGNsb25lKVxuICAgIH1cbiAgICBjb25zdCBvMiA9IHt9XG4gICAgcmVmcy5wdXNoKG8pXG4gICAgcmVmc05ldy5wdXNoKG8yKVxuICAgIGZvciAoY29uc3QgayBpbiBvKSB7XG4gICAgICBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwobywgaykgPT09IGZhbHNlKSBjb250aW51ZVxuICAgICAgY29uc3QgY3VyID0gb1trXVxuICAgICAgaWYgKHR5cGVvZiBjdXIgIT09ICdvYmplY3QnIHx8IGN1ciA9PT0gbnVsbCkge1xuICAgICAgICBvMltrXSA9IGN1clxuICAgICAgfSBlbHNlIGlmIChjdXIuY29uc3RydWN0b3IgIT09IE9iamVjdCAmJiAoaGFuZGxlciA9IGNvbnN0cnVjdG9ySGFuZGxlcnMuZ2V0KGN1ci5jb25zdHJ1Y3RvcikpKSB7XG4gICAgICAgIG8yW2tdID0gaGFuZGxlcihjdXIsIGNsb25lKVxuICAgICAgfSBlbHNlIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoY3VyKSkge1xuICAgICAgICBvMltrXSA9IGNvcHlCdWZmZXIoY3VyKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaSA9IHJlZnMuaW5kZXhPZihjdXIpXG4gICAgICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgICAgIG8yW2tdID0gcmVmc05ld1tpXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG8yW2tdID0gY2xvbmUoY3VyKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJlZnMucG9wKClcbiAgICByZWZzTmV3LnBvcCgpXG4gICAgcmV0dXJuIG8yXG4gIH1cblxuICBmdW5jdGlvbiBjbG9uZVByb3RvIChvKSB7XG4gICAgaWYgKHR5cGVvZiBvICE9PSAnb2JqZWN0JyB8fCBvID09PSBudWxsKSByZXR1cm4gb1xuICAgIGlmIChBcnJheS5pc0FycmF5KG8pKSByZXR1cm4gY2xvbmVBcnJheShvLCBjbG9uZVByb3RvKVxuICAgIGlmIChvLmNvbnN0cnVjdG9yICE9PSBPYmplY3QgJiYgKGhhbmRsZXIgPSBjb25zdHJ1Y3RvckhhbmRsZXJzLmdldChvLmNvbnN0cnVjdG9yKSkpIHtcbiAgICAgIHJldHVybiBoYW5kbGVyKG8sIGNsb25lUHJvdG8pXG4gICAgfVxuICAgIGNvbnN0IG8yID0ge31cbiAgICByZWZzLnB1c2gobylcbiAgICByZWZzTmV3LnB1c2gobzIpXG4gICAgZm9yIChjb25zdCBrIGluIG8pIHtcbiAgICAgIGNvbnN0IGN1ciA9IG9ba11cbiAgICAgIGlmICh0eXBlb2YgY3VyICE9PSAnb2JqZWN0JyB8fCBjdXIgPT09IG51bGwpIHtcbiAgICAgICAgbzJba10gPSBjdXJcbiAgICAgIH0gZWxzZSBpZiAoY3VyLmNvbnN0cnVjdG9yICE9PSBPYmplY3QgJiYgKGhhbmRsZXIgPSBjb25zdHJ1Y3RvckhhbmRsZXJzLmdldChjdXIuY29uc3RydWN0b3IpKSkge1xuICAgICAgICBvMltrXSA9IGhhbmRsZXIoY3VyLCBjbG9uZVByb3RvKVxuICAgICAgfSBlbHNlIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoY3VyKSkge1xuICAgICAgICBvMltrXSA9IGNvcHlCdWZmZXIoY3VyKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaSA9IHJlZnMuaW5kZXhPZihjdXIpXG4gICAgICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgICAgIG8yW2tdID0gcmVmc05ld1tpXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG8yW2tdID0gY2xvbmVQcm90byhjdXIpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmVmcy5wb3AoKVxuICAgIHJlZnNOZXcucG9wKClcbiAgICByZXR1cm4gbzJcbiAgfVxufVxuIiwiaW1wb3J0IGVxdWFsIGZyb20gXCJmYXN0LWRlZXAtZXF1YWxcIlxuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSBcIm5hbm9pZFwiXG5pbXBvcnQgcmZkYyBmcm9tIFwicmZkY1wiXG5pbXBvcnQgdHlwZSB7IEpTT05WYWx1ZSB9IGZyb20gXCIuL2pzb25cIlxuXG5jb25zdCBjbG9uZSA9IHJmZGMoeyBwcm90bzogdHJ1ZSB9KVxuXG4vKipcbiAqIERlZXAgZXF1YWxpdHkgY2hlY2sgZm9yIEpTT05WYWx1ZXMuXG4gKiBVc2VkIGZvciBhZGRUb1NldCAvIGRlbGV0ZUZyb21TZXQgb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBFcXVhbChhOiBKU09OVmFsdWUsIGI6IEpTT05WYWx1ZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gZXF1YWwoYSwgYilcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgbmFub2lkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVJRCgpOiBzdHJpbmcge1xuICByZXR1cm4gbmFub2lkKClcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhbiBvYmplY3QgKHR5cGVvZiA9PT0gXCJvYmplY3RcIiAmJiAhPT0gbnVsbCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIG9iamVjdCB7XG4gIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCJcbn1cblxuLyoqXG4gKiBEZWVwIGNsb25lcyBhIEpTT04tc2VyaWFsaXphYmxlIHZhbHVlLlxuICogT3B0aW1pemVkOiBwcmltaXRpdmVzIGFyZSByZXR1cm5lZCBhcy1pcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBDbG9uZTxUPih2YWx1ZTogVCk6IFQge1xuICAvLyBQcmltaXRpdmVzIGRvbid0IG5lZWQgY2xvbmluZ1xuICBpZiAodmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIHZhbHVlICE9PSBcIm9iamVjdFwiKSB7XG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cbiAgcmV0dXJuIGNsb25lKHZhbHVlKVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBsYXp5IG1lbW9pemVkIGdldHRlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhenk8VD4oZm46ICgpID0+IFQpOiAoKSA9PiBUIHtcbiAgbGV0IGNvbXB1dGVkID0gZmFsc2VcbiAgbGV0IHZhbHVlOiBUXG4gIHJldHVybiAoKSA9PiB7XG4gICAgaWYgKCFjb21wdXRlZCkge1xuICAgICAgdmFsdWUgPSBmbigpXG4gICAgICBjb21wdXRlZCA9IHRydWVcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cbn1cbiIsImltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi9lcnJvclwiXG5pbXBvcnQgdHlwZSB7IEpTT05PYmplY3QsIEpTT05SZWNvcmQsIEpTT05WYWx1ZSwgUGF0aCB9IGZyb20gXCIuL2pzb25cIlxuaW1wb3J0IHR5cGUgeyBPcCwgVmFsaWRhdGVGbiB9IGZyb20gXCIuL29wZXJhdGlvbnNcIlxuaW1wb3J0IHsgVHhSZWNvcmQgfSBmcm9tIFwiLi9UeFJlY29yZFwiXG5pbXBvcnQgeyBkZWVwRXF1YWwsIGlzT2JqZWN0IH0gZnJvbSBcIi4vdXRpbHNcIlxuXG4vKipcbiAqIEEgZHJhZnQgY29udGV4dCBmb3IgY29weS1vbi13cml0ZSBpbW11dGFibGUgdXBkYXRlcy5cbiAqXG4gKiBUaGlzIHByb3ZpZGVzIEltbWVyL011dGF0aXZlLWxpa2Ugc2VtYW50aWNzIHdpdGhvdXQgdGhlIHByb3h5IG92ZXJoZWFkOlxuICogLSBUaGUgb3JpZ2luYWwgYmFzZSBzdGF0ZSBpcyBuZXZlciBtdXRhdGVkXG4gKiAtIE9iamVjdHMgYXJlIGNsb25lZCBsYXppbHkgb24gZmlyc3QgbXV0YXRpb24gKGNvcHktb24td3JpdGUpXG4gKiAtIE9uY2UgYW4gb2JqZWN0IGlzIGNsb25lZCAoXCJvd25lZFwiKSwgaXQgY2FuIGJlIG11dGF0ZWQgZGlyZWN0bHlcbiAqIC0gSWYgbm8gY2hhbmdlcyBhcmUgbWFkZSwgdGhlIG9yaWdpbmFsIHJlZmVyZW5jZSBpcyBwcmVzZXJ2ZWQgKHN0cnVjdHVyYWwgc2hhcmluZylcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEcmFmdENvbnRleHQ8VCBleHRlbmRzIEpTT05PYmplY3Q+IHtcbiAgLyoqIFRoZSBjdXJyZW50IHJvb3QgKG1heSBiZSB0aGUgb3JpZ2luYWwgYmFzZSBvciBhIGNsb25lZCB2ZXJzaW9uKSAqL1xuICByb290OiBUXG4gIC8qKiBUaGUgb3JpZ2luYWwgYmFzZSBzdGF0ZSAobmV2ZXIgbXV0YXRlZCkgKi9cbiAgYmFzZTogVFxuICAvKiogU2V0IG9mIG9iamVjdHMgdGhhdCBoYXZlIGJlZW4gY2xvbmVkIGFuZCBhcmUgc2FmZSB0byBtdXRhdGUgKi9cbiAgb3duZWRPYmplY3RzOiBXZWFrU2V0PG9iamVjdD5cbiAgLyoqIE9wdGltaXphdGlvbjogZmFzdCBjaGVjayBpZiByb290IGlzIGFscmVhZHkgb3duZWQgKi9cbiAgaXNSb290T3duZWQ6IGJvb2xlYW5cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGRyYWZ0IGNvbnRleHQgZnJvbSBhIGJhc2Ugc3RhdGUuXG4gKiBUaGUgYmFzZSBzdGF0ZSB3aWxsIG5ldmVyIGJlIG11dGF0ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVEcmFmdDxUIGV4dGVuZHMgSlNPTk9iamVjdD4oYmFzZTogVCk6IERyYWZ0Q29udGV4dDxUPiB7XG4gIHJldHVybiB7XG4gICAgcm9vdDogYmFzZSxcbiAgICBiYXNlLFxuICAgIG93bmVkT2JqZWN0czogbmV3IFNldCgpLFxuICAgIGlzUm9vdE93bmVkOiBmYWxzZSxcbiAgfVxufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZHJhZnQgd2FzIG1vZGlmaWVkIChyb290ICE9PSBiYXNlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRHJhZnRNb2RpZmllZDxUIGV4dGVuZHMgSlNPTk9iamVjdD4oY3R4OiBEcmFmdENvbnRleHQ8VD4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGN0eC5yb290ICE9PSBjdHguYmFzZVxufVxuXG5mdW5jdGlvbiBzaGFsbG93Q2xvbmU8VCBleHRlbmRzIG9iamVjdD4ob2JqOiBUKTogVCB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gb2JqLnNsaWNlKCkgYXMgdW5rbm93biBhcyBUXG4gIH1cbiAgY29uc3QgY2xvbmUgPSB7fSBhcyBUXG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhvYmopXG4gIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IGtleXNbaV1cbiAgICA7KGNsb25lIGFzIGFueSlba2V5XSA9IChvYmogYXMgYW55KVtrZXldXG4gIH1cbiAgcmV0dXJuIGNsb25lXG59XG5cbi8qKlxuICogRW5zdXJlcyBhbiBvYmplY3QgaXMgb3duZWQgKGNsb25lZCBpZiBuZWNlc3NhcnkpIGFuZCByZXR1cm5zIHRoZSBvd25lZCB2ZXJzaW9uLlxuICogQWxzbyB1cGRhdGVzIHRoZSBwYXJlbnQgdG8gcG9pbnQgdG8gdGhlIGNsb25lZCBjaGlsZC5cbiAqL1xuZnVuY3Rpb24gZW5zdXJlT3duZWQ8VCBleHRlbmRzIEpTT05PYmplY3Q+KFxuICBjdHg6IERyYWZ0Q29udGV4dDxUPixcbiAgcGFyZW50OiBKU09OT2JqZWN0LFxuICBrZXk6IHN0cmluZyB8IG51bWJlcixcbiAgY2hpbGQ6IEpTT05SZWNvcmQgfCBKU09OVmFsdWVbXVxuKTogSlNPTlJlY29yZCB8IEpTT05WYWx1ZVtdIHtcbiAgaWYgKGN0eC5vd25lZE9iamVjdHMuaGFzKGNoaWxkKSkge1xuICAgIHJldHVybiBjaGlsZFxuICB9XG4gIGNvbnN0IGNsb25lZCA9IHNoYWxsb3dDbG9uZShjaGlsZClcbiAgOyhwYXJlbnQgYXMgYW55KVtrZXldID0gY2xvbmVkXG4gIGN0eC5vd25lZE9iamVjdHMuYWRkKGNsb25lZClcbiAgcmV0dXJuIGNsb25lZFxufVxuXG4vKipcbiAqIEVuc3VyZXMgYWxsIG9iamVjdHMgYWxvbmcgdGhlIHBhdGggYXJlIG93bmVkIChjbG9uZWQgaWYgbmVjZXNzYXJ5KS5cbiAqIFJldHVybnMgdGhlIGNvbnRhaW5lciBhdCB0aGUgZW5kIG9mIHRoZSBwYXRoLlxuICogVGhyb3dzIGlmIHRoZSBwYXRoIGlzIGludmFsaWQuXG4gKi9cbmZ1bmN0aW9uIGVuc3VyZU93bmVkUGF0aDxUIGV4dGVuZHMgSlNPTk9iamVjdD4oXG4gIGN0eDogRHJhZnRDb250ZXh0PFQ+LFxuICBwYXRoOiBQYXRoXG4pOiBKU09OUmVjb3JkIHwgSlNPTlZhbHVlW10ge1xuICAvLyBFbnN1cmUgcm9vdCBpcyBvd25lZCBmaXJzdFxuICBpZiAoIWN0eC5pc1Jvb3RPd25lZCkge1xuICAgIGN0eC5yb290ID0gc2hhbGxvd0Nsb25lKGN0eC5yb290IGFzIHVua25vd24gYXMgb2JqZWN0KSBhcyBUXG4gICAgY3R4Lm93bmVkT2JqZWN0cy5hZGQoY3R4LnJvb3QpXG4gICAgY3R4LmlzUm9vdE93bmVkID0gdHJ1ZVxuICB9XG5cbiAgaWYgKHBhdGgubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGN0eC5yb290XG4gIH1cblxuICBsZXQgY3VycmVudDogSlNPTlJlY29yZCB8IEpTT05WYWx1ZVtdID0gY3R4LnJvb3RcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBzZWdtZW50ID0gcGF0aFtpXVxuICAgIGNvbnN0IGlzQXJyYXlJbmRleCA9IHR5cGVvZiBzZWdtZW50ID09PSBcIm51bWJlclwiXG5cbiAgICAvLyBWYWxpZGF0ZSBjb250YWluZXIgdHlwZVxuICAgIGlmIChpc0FycmF5SW5kZXgpIHtcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShjdXJyZW50KSkge1xuICAgICAgICBmYWlsdXJlKGBFeHBlY3RlZCBhcnJheSBhdCBwYXRoIHNlZ21lbnQgJHtzZWdtZW50fWApXG4gICAgICB9XG4gICAgICBpZiAoc2VnbWVudCA8IDAgfHwgc2VnbWVudCA+PSBjdXJyZW50Lmxlbmd0aCkge1xuICAgICAgICBmYWlsdXJlKGBJbmRleCAke3NlZ21lbnR9IG91dCBvZiBib3VuZHNgKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KGN1cnJlbnQpIHx8IEFycmF5LmlzQXJyYXkoY3VycmVudCkpIHtcbiAgICAgICAgZmFpbHVyZShgRXhwZWN0ZWQgb2JqZWN0IGF0IHBhdGggc2VnbWVudCBcIiR7c2VnbWVudH1cImApXG4gICAgICB9XG4gICAgICBpZiAoIShzZWdtZW50IGluIGN1cnJlbnQpKSB7XG4gICAgICAgIGZhaWx1cmUoYFByb3BlcnR5IFwiJHtzZWdtZW50fVwiIGRvZXMgbm90IGV4aXN0YClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjaGlsZDogSlNPTlZhbHVlID0gKGN1cnJlbnQgYXMgYW55KVtzZWdtZW50XVxuXG4gICAgLy8gVmFsaWRhdGUgY2hpbGQgaXMgdHJhdmVyc2FibGVcbiAgICBpZiAoY2hpbGQgPT09IG51bGwgfHwgdHlwZW9mIGNoaWxkICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICBmYWlsdXJlKGBDYW5ub3QgdHJhdmVyc2UgdGhyb3VnaCBwcmltaXRpdmUgYXQgcGF0aCBzZWdtZW50ICR7c2VnbWVudH1gKVxuICAgIH1cblxuICAgIC8vIEVuc3VyZSBjaGlsZCBpcyBvd25lZCBhbmQgY29udGludWVcbiAgICBjdXJyZW50ID0gZW5zdXJlT3duZWQoY3R4LCBjdXJyZW50LCBzZWdtZW50LCBjaGlsZCBhcyBKU09OUmVjb3JkIHwgSlNPTlZhbHVlW10pXG4gIH1cblxuICByZXR1cm4gY3VycmVudFxufVxuXG4vKipcbiAqIEFwcGxpZXMgYSBzaW5nbGUgXCJzZXRcIiBvcGVyYXRpb24gdG8gdGhlIGRyYWZ0IHdpdGggY29weS1vbi13cml0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRyYWZ0U2V0PFQgZXh0ZW5kcyBKU09OT2JqZWN0PihcbiAgY3R4OiBEcmFmdENvbnRleHQ8VD4sXG4gIHBhdGg6IFBhdGgsXG4gIGtleTogc3RyaW5nLFxuICB2YWx1ZTogSlNPTlZhbHVlXG4pOiB2b2lkIHtcbiAgY29uc3QgY29udGFpbmVyID0gZW5zdXJlT3duZWRQYXRoKGN0eCwgcGF0aClcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29udGFpbmVyKSkge1xuICAgIGZhaWx1cmUoXCJzZXQgcmVxdWlyZXMgb2JqZWN0IGNvbnRhaW5lclwiKVxuICB9XG4gIDsoY29udGFpbmVyIGFzIEpTT05SZWNvcmQpW2tleV0gPSB2YWx1ZVxufVxuXG4vKipcbiAqIEFwcGxpZXMgYSBzaW5nbGUgXCJkZWxldGVcIiBvcGVyYXRpb24gdG8gdGhlIGRyYWZ0IHdpdGggY29weS1vbi13cml0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRyYWZ0RGVsZXRlPFQgZXh0ZW5kcyBKU09OT2JqZWN0PihcbiAgY3R4OiBEcmFmdENvbnRleHQ8VD4sXG4gIHBhdGg6IFBhdGgsXG4gIGtleTogc3RyaW5nXG4pOiB2b2lkIHtcbiAgY29uc3QgY29udGFpbmVyID0gZW5zdXJlT3duZWRQYXRoKGN0eCwgcGF0aClcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29udGFpbmVyKSkge1xuICAgIGZhaWx1cmUoXCJkZWxldGUgcmVxdWlyZXMgb2JqZWN0IGNvbnRhaW5lclwiKVxuICB9XG4gIGRlbGV0ZSAoY29udGFpbmVyIGFzIEpTT05SZWNvcmQpW2tleV1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGEgc2luZ2xlIFwic3BsaWNlXCIgb3BlcmF0aW9uIHRvIHRoZSBkcmFmdCB3aXRoIGNvcHktb24td3JpdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcmFmdFNwbGljZTxUIGV4dGVuZHMgSlNPTk9iamVjdD4oXG4gIGN0eDogRHJhZnRDb250ZXh0PFQ+LFxuICBwYXRoOiBQYXRoLFxuICBpbmRleDogbnVtYmVyLFxuICBkZWxldGVDb3VudDogbnVtYmVyLFxuICBpbnNlcnRzOiByZWFkb25seSBKU09OVmFsdWVbXVxuKTogdm9pZCB7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGVuc3VyZU93bmVkUGF0aChjdHgsIHBhdGgpXG4gIGlmICghQXJyYXkuaXNBcnJheShjb250YWluZXIpKSB7XG4gICAgZmFpbHVyZShcInNwbGljZSByZXF1aXJlcyBhcnJheSBjb250YWluZXJcIilcbiAgfVxuICBjb25zdCBzYWZlSW5kZXggPSBNYXRoLm1pbihpbmRleCwgY29udGFpbmVyLmxlbmd0aClcbiAgaWYgKGluc2VydHMubGVuZ3RoID09PSAwKSB7XG4gICAgY29udGFpbmVyLnNwbGljZShzYWZlSW5kZXgsIGRlbGV0ZUNvdW50KVxuICB9IGVsc2UgaWYgKGluc2VydHMubGVuZ3RoID09PSAxKSB7XG4gICAgY29udGFpbmVyLnNwbGljZShzYWZlSW5kZXgsIGRlbGV0ZUNvdW50LCBpbnNlcnRzWzBdKVxuICB9IGVsc2Uge1xuICAgIGNvbnRhaW5lci5zcGxpY2Uoc2FmZUluZGV4LCBkZWxldGVDb3VudCwgLi4uaW5zZXJ0cylcbiAgfVxufVxuXG4vKipcbiAqIEFwcGxpZXMgYSBzaW5nbGUgXCJhZGRUb1NldFwiIG9wZXJhdGlvbiB0byB0aGUgZHJhZnQgd2l0aCBjb3B5LW9uLXdyaXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJhZnRBZGRUb1NldDxUIGV4dGVuZHMgSlNPTk9iamVjdD4oXG4gIGN0eDogRHJhZnRDb250ZXh0PFQ+LFxuICBwYXRoOiBQYXRoLFxuICB2YWx1ZTogSlNPTlZhbHVlXG4pOiB2b2lkIHtcbiAgY29uc3QgY29udGFpbmVyID0gZW5zdXJlT3duZWRQYXRoKGN0eCwgcGF0aClcbiAgaWYgKCFBcnJheS5pc0FycmF5KGNvbnRhaW5lcikpIHtcbiAgICBmYWlsdXJlKFwiYWRkVG9TZXQgcmVxdWlyZXMgYXJyYXkgY29udGFpbmVyXCIpXG4gIH1cbiAgaWYgKCFjb250YWluZXIuc29tZSgoaXRlbSkgPT4gZGVlcEVxdWFsKGl0ZW0sIHZhbHVlKSkpIHtcbiAgICBjb250YWluZXIucHVzaCh2YWx1ZSlcbiAgfVxufVxuXG4vKipcbiAqIEFwcGxpZXMgYSBzaW5nbGUgXCJkZWxldGVGcm9tU2V0XCIgb3BlcmF0aW9uIHRvIHRoZSBkcmFmdCB3aXRoIGNvcHktb24td3JpdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcmFmdERlbGV0ZUZyb21TZXQ8VCBleHRlbmRzIEpTT05PYmplY3Q+KFxuICBjdHg6IERyYWZ0Q29udGV4dDxUPixcbiAgcGF0aDogUGF0aCxcbiAgdmFsdWU6IEpTT05WYWx1ZVxuKTogdm9pZCB7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGVuc3VyZU93bmVkUGF0aChjdHgsIHBhdGgpXG4gIGlmICghQXJyYXkuaXNBcnJheShjb250YWluZXIpKSB7XG4gICAgZmFpbHVyZShcImRlbGV0ZUZyb21TZXQgcmVxdWlyZXMgYXJyYXkgY29udGFpbmVyXCIpXG4gIH1cbiAgLy8gUmVtb3ZlIGFsbCBtYXRjaGluZyBpdGVtcyAoaXRlcmF0ZSBiYWNrd2FyZHMgdG8gYXZvaWQgaW5kZXggc2hpZnRpbmcpXG4gIGZvciAobGV0IGkgPSBjb250YWluZXIubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAoZGVlcEVxdWFsKGNvbnRhaW5lcltpXSwgdmFsdWUpKSB7XG4gICAgICBjb250YWluZXIuc3BsaWNlKGksIDEpXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQXBwbGllcyBhIHNpbmdsZSBvcGVyYXRpb24gdG8gdGhlIGRyYWZ0IHdpdGggY29weS1vbi13cml0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5T3BUb0RyYWZ0PFQgZXh0ZW5kcyBKU09OT2JqZWN0PihjdHg6IERyYWZ0Q29udGV4dDxUPiwgb3A6IE9wKTogdm9pZCB7XG4gIHN3aXRjaCAob3Aua2luZCkge1xuICAgIGNhc2UgXCJzZXRcIjpcbiAgICAgIGRyYWZ0U2V0KGN0eCwgb3AucGF0aCwgb3Aua2V5LCBvcC52YWx1ZSlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSBcImRlbGV0ZVwiOlxuICAgICAgZHJhZnREZWxldGUoY3R4LCBvcC5wYXRoLCBvcC5rZXkpXG4gICAgICBicmVha1xuICAgIGNhc2UgXCJzcGxpY2VcIjpcbiAgICAgIGRyYWZ0U3BsaWNlKGN0eCwgb3AucGF0aCwgb3AuaW5kZXgsIG9wLmRlbGV0ZUNvdW50LCBvcC5pbnNlcnRzKVxuICAgICAgYnJlYWtcbiAgICBjYXNlIFwiYWRkVG9TZXRcIjpcbiAgICAgIGRyYWZ0QWRkVG9TZXQoY3R4LCBvcC5wYXRoLCBvcC52YWx1ZSlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSBcImRlbGV0ZUZyb21TZXRcIjpcbiAgICAgIGRyYWZ0RGVsZXRlRnJvbVNldChjdHgsIG9wLnBhdGgsIG9wLnZhbHVlKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgZmFpbHVyZShgVW5rbm93biBvcGVyYXRpb24ga2luZDogJHsob3AgYXMgYW55KS5raW5kfWApXG4gIH1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGEgc2luZ2xlIHRyYW5zYWN0aW9uIHRvIGEgYmFzZSBzdGF0ZSBpbW11dGFibHkuXG4gKlxuICogS2V5IGJlbmVmaXRzIG92ZXIgTXV0YXRpdmUvSW1tZXI6XG4gKiAtIE5vIHByb3h5IG92ZXJoZWFkIC0gZGlyZWN0IG9iamVjdCBhY2Nlc3MgYW5kIGNvcHktb24td3JpdGUgY2xvbmluZ1xuICogLSBTdHJ1Y3R1cmFsIHNoYXJpbmcgLSB1bmNoYW5nZWQgc3VidHJlZXMga2VlcCB0aGVpciByZWZlcmVuY2VzXG4gKiAtIFplcm8tY29weSBvbiBmYWlsdXJlIC0gaWYgdmFsaWRhdGlvbiBmYWlscywgcmV0dXJucyBvcmlnaW5hbCBiYXNlIHVuY2hhbmdlZFxuICpcbiAqIEBwYXJhbSBiYXNlIC0gVGhlIGJhc2Ugc3RhdGUgKG5ldmVyIG11dGF0ZWQpXG4gKiBAcGFyYW0gdHggLSBUaGUgdHJhbnNhY3Rpb24gdG8gYXBwbHlcbiAqIEBwYXJhbSB2YWxpZGF0ZUZuIC0gT3B0aW9uYWwgdmFsaWRhdGlvbiBmdW5jdGlvblxuICogQHJldHVybnMgVGhlIGZpbmFsIHN0YXRlIChpZiB2YWxpZCkgb3IgdGhlIG9yaWdpbmFsIGJhc2UgKGlmIGludmFsaWQgb3IgZW1wdHkpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVR4SW1tdXRhYmxlPFQgZXh0ZW5kcyBKU09OT2JqZWN0PihcbiAgYmFzZTogVCxcbiAgdHg6IFBpY2s8VHhSZWNvcmQsIFwib3BzXCI+LFxuICB2YWxpZGF0ZUZuPzogVmFsaWRhdGVGbjxUPlxuKTogVCB7XG4gIGlmICh0eC5vcHMubGVuZ3RoID09PSAwKSByZXR1cm4gYmFzZVxuXG4gIGNvbnN0IGN0eCA9IGNyZWF0ZURyYWZ0KGJhc2UpXG5cbiAgdHJ5IHtcbiAgICBmb3IgKGNvbnN0IG9wIG9mIHR4Lm9wcykge1xuICAgICAgYXBwbHlPcFRvRHJhZnQoY3R4LCBvcClcbiAgICB9XG5cbiAgICBpZiAodmFsaWRhdGVGbiAmJiAhdmFsaWRhdGVGbihjdHgucm9vdCkpIHtcbiAgICAgIHJldHVybiBiYXNlXG4gICAgfVxuXG4gICAgcmV0dXJuIGN0eC5yb290XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBiYXNlXG4gIH1cbn1cbiIsImltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi9lcnJvclwiXG5pbXBvcnQgeyBKU09OUmVjb3JkLCBKU09OVmFsdWUsIFBhdGggfSBmcm9tIFwiLi9qc29uXCJcbmltcG9ydCB7IE9wIH0gZnJvbSBcIi4vb3BlcmF0aW9uc1wiXG5cbi8qKlxuICogUmVjb25jaWxlcyB0aGUgY3VycmVudCBzdGF0ZSB3aXRoIHRoZSB0YXJnZXQgc3RhdGUgYnkgY29tcHV0aW5nIGFuZCBlbWl0dGluZ1xuICogdGhlIG1pbmltYWwgc2V0IG9mIG9wZXJhdGlvbnMgbmVlZGVkIHRvIHRyYW5zZm9ybSBjdXJyZW50U3RhdGUgaW50byB0YXJnZXRTdGF0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVSZWNvbmNpbGVPcHMoY3VycmVudFN0YXRlOiBKU09OVmFsdWUsIHRhcmdldFN0YXRlOiBKU09OVmFsdWUpOiBPcFtdIHtcbiAgY29uc3Qgb3BzOiBPcFtdID0gW11cbiAgZGlmZlZhbHVlKGN1cnJlbnRTdGF0ZSwgdGFyZ2V0U3RhdGUsIFtdLCBvcHMpXG4gIHJldHVybiBvcHNcbn1cblxuZnVuY3Rpb24gZGlmZlZhbHVlKGN1cnJlbnQ6IEpTT05WYWx1ZSwgdGFyZ2V0OiBKU09OVmFsdWUsIHBhdGg6IFBhdGgsIG9wczogT3BbXSk6IHZvaWQge1xuICAvLyAxLiBSZWZlcmVuY2UgZXF1YWxpdHkgKHN0cnVjdHVyYWwgc2hhcmluZylcbiAgaWYgKGN1cnJlbnQgPT09IHRhcmdldCkgcmV0dXJuXG5cbiAgLy8gMi4gSGFuZGxlIHByaW1pdGl2ZXMgYW5kIG51bGwgcXVpY2tseVxuICBjb25zdCBjdXJyZW50VHlwZSA9IHR5cGVvZiBjdXJyZW50XG4gIGNvbnN0IHRhcmdldFR5cGUgPSB0eXBlb2YgdGFyZ2V0XG5cbiAgaWYgKGN1cnJlbnQgPT09IG51bGwgfHwgdGFyZ2V0ID09PSBudWxsIHx8IGN1cnJlbnRUeXBlICE9PSBcIm9iamVjdFwiIHx8IHRhcmdldFR5cGUgIT09IFwib2JqZWN0XCIpIHtcbiAgICAvLyBBdCBsZWFzdCBvbmUgaXMgcHJpbWl0aXZlL251bGwsIG9yIHR5cGVzIGRvbid0IG1hdGNoXG4gICAgZW1pdFJlcGxhY2UocGF0aCwgdGFyZ2V0LCBvcHMpXG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBCb3RoIGFyZSBvYmplY3RzIChvYmplY3Qgb3IgYXJyYXkpXG4gIGNvbnN0IGN1cnJlbnRJc0FycmF5ID0gQXJyYXkuaXNBcnJheShjdXJyZW50KVxuICBjb25zdCB0YXJnZXRJc0FycmF5ID0gQXJyYXkuaXNBcnJheSh0YXJnZXQpXG5cbiAgaWYgKGN1cnJlbnRJc0FycmF5ICE9PSB0YXJnZXRJc0FycmF5KSB7XG4gICAgLy8gVHlwZSBtaXNtYXRjaCAob25lIGFycmF5LCBvbmUgb2JqZWN0KVxuICAgIGVtaXRSZXBsYWNlKHBhdGgsIHRhcmdldCwgb3BzKVxuICAgIHJldHVyblxuICB9XG5cbiAgaWYgKGN1cnJlbnRJc0FycmF5KSB7XG4gICAgZGlmZkFycmF5KGN1cnJlbnQsIHRhcmdldCBhcyBKU09OVmFsdWVbXSwgcGF0aCwgb3BzKVxuICB9IGVsc2Uge1xuICAgIGRpZmZPYmplY3QoY3VycmVudCBhcyBKU09OUmVjb3JkLCB0YXJnZXQgYXMgSlNPTlJlY29yZCwgcGF0aCwgb3BzKVxuICB9XG59XG5cbmZ1bmN0aW9uIGRpZmZPYmplY3QoY3VycmVudDogSlNPTlJlY29yZCwgdGFyZ2V0OiBKU09OUmVjb3JkLCBwYXRoOiBQYXRoLCBvcHM6IE9wW10pOiB2b2lkIHtcbiAgLy8gMS4gRGVsZXRlIGtleXMgaW4gY3VycmVudCBidXQgbm90IGluIHRhcmdldFxuICBmb3IgKGNvbnN0IGtleSBpbiBjdXJyZW50KSB7XG4gICAgaWYgKE9iamVjdC5oYXNPd24oY3VycmVudCwga2V5KSAmJiAhT2JqZWN0Lmhhc093bih0YXJnZXQsIGtleSkpIHtcbiAgICAgIG9wcy5wdXNoKHsga2luZDogXCJkZWxldGVcIiwgcGF0aCwga2V5IH0pXG4gICAgfVxuICB9XG5cbiAgLy8gMi4gQWRkL1VwZGF0ZSBrZXlzIGluIHRhcmdldFxuICBmb3IgKGNvbnN0IGtleSBpbiB0YXJnZXQpIHtcbiAgICBpZiAoT2JqZWN0Lmhhc093bih0YXJnZXQsIGtleSkpIHtcbiAgICAgIGNvbnN0IHRhcmdldFZhbCA9IHRhcmdldFtrZXldXG4gICAgICBpZiAoIU9iamVjdC5oYXNPd24oY3VycmVudCwga2V5KSkge1xuICAgICAgICBvcHMucHVzaCh7IGtpbmQ6IFwic2V0XCIsIHBhdGgsIGtleSwgdmFsdWU6IHRhcmdldFZhbCB9KVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50W2tleV0gIT09IHRhcmdldFZhbCkge1xuICAgICAgICAvLyBPbmx5IHJlY3Vyc2UgaWYgdmFsdWVzIGRpZmZlciAocmVmZXJlbmNlIGNoZWNrIGZpcnN0KVxuICAgICAgICBkaWZmVmFsdWUoY3VycmVudFtrZXldLCB0YXJnZXRWYWwsIFsuLi5wYXRoLCBrZXldLCBvcHMpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGRpZmZBcnJheShjdXJyZW50OiBKU09OVmFsdWVbXSwgdGFyZ2V0OiBKU09OVmFsdWVbXSwgcGF0aDogUGF0aCwgb3BzOiBPcFtdKTogdm9pZCB7XG4gIGNvbnN0IGN1cnJlbnRMZW4gPSBjdXJyZW50Lmxlbmd0aFxuICBjb25zdCB0YXJnZXRMZW4gPSB0YXJnZXQubGVuZ3RoXG4gIGNvbnN0IG1pbkxlbiA9IGN1cnJlbnRMZW4gPCB0YXJnZXRMZW4gPyBjdXJyZW50TGVuIDogdGFyZ2V0TGVuXG5cbiAgLy8gRGlmZiBjb21tb24gZWxlbWVudHNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBtaW5MZW47IGkrKykge1xuICAgIGlmIChjdXJyZW50W2ldICE9PSB0YXJnZXRbaV0pIHtcbiAgICAgIGRpZmZWYWx1ZShjdXJyZW50W2ldLCB0YXJnZXRbaV0sIFsuLi5wYXRoLCBpXSwgb3BzKVxuICAgIH1cbiAgfVxuXG4gIC8vIEhhbmRsZSBsZW5ndGggZGlmZmVyZW5jZVxuICBpZiAodGFyZ2V0TGVuID4gY3VycmVudExlbikge1xuICAgIG9wcy5wdXNoKHtcbiAgICAgIGtpbmQ6IFwic3BsaWNlXCIsXG4gICAgICBwYXRoLFxuICAgICAgaW5kZXg6IGN1cnJlbnRMZW4sXG4gICAgICBkZWxldGVDb3VudDogMCxcbiAgICAgIGluc2VydHM6IHRhcmdldC5zbGljZShjdXJyZW50TGVuKSxcbiAgICB9KVxuICB9IGVsc2UgaWYgKGN1cnJlbnRMZW4gPiB0YXJnZXRMZW4pIHtcbiAgICBvcHMucHVzaCh7XG4gICAgICBraW5kOiBcInNwbGljZVwiLFxuICAgICAgcGF0aCxcbiAgICAgIGluZGV4OiB0YXJnZXRMZW4sXG4gICAgICBkZWxldGVDb3VudDogY3VycmVudExlbiAtIHRhcmdldExlbixcbiAgICAgIGluc2VydHM6IFtdLFxuICAgIH0pXG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdFJlcGxhY2UocGF0aDogUGF0aCwgdmFsdWU6IEpTT05WYWx1ZSwgb3BzOiBPcFtdKTogdm9pZCB7XG4gIGlmIChwYXRoLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIENhbm5vdCByZXBsYWNlIHJvb3QgZGlyZWN0bHkgdmlhIE9wcyAodW5sZXNzIHdlIGRlZmluZSBhICdyb290JyBvcCwgd2hpY2ggd2UgZG9uJ3QpXG4gICAgLy8gV2UgZXhwZWN0IHJvb3QgdG8gYmUgaGFuZGxlZCBieSBkaWZmT2JqZWN0IHVzdWFsbHkuXG4gICAgLy8gSWYgd2UgbGFuZCBoZXJlLCBpdCBtZWFucyByb290IHR5cGVzIG1pc21hdGNoZWQgKGUuZy4gT2JqIC0+IEFycmF5KS5cbiAgICBmYWlsdXJlKFwiU3RhdGVTeW5jTG9nOiBDYW5ub3QgcmVwbGFjZSByb290IHN0YXRlIGRpcmVjdGx5IHZpYSBPcHMuXCIpXG4gIH1cblxuICBjb25zdCBwYXJlbnRQYXRoID0gcGF0aC5zbGljZSgwLCAtMSlcbiAgY29uc3Qga2V5VG9DaGVjayA9IHBhdGhbcGF0aC5sZW5ndGggLSAxXVxuXG4gIGlmICh0eXBlb2Yga2V5VG9DaGVjayA9PT0gXCJzdHJpbmdcIikge1xuICAgIC8vIFBhcmVudCBpcyBPYmplY3RcbiAgICBvcHMucHVzaCh7IGtpbmQ6IFwic2V0XCIsIHBhdGg6IHBhcmVudFBhdGgsIGtleToga2V5VG9DaGVjaywgdmFsdWUgfSlcbiAgfSBlbHNlIHtcbiAgICAvLyBQYXJlbnQgaXMgQXJyYXlcbiAgICBvcHMucHVzaCh7XG4gICAgICBraW5kOiBcInNwbGljZVwiLFxuICAgICAgcGF0aDogcGFyZW50UGF0aCxcbiAgICAgIGluZGV4OiBrZXlUb0NoZWNrLFxuICAgICAgZGVsZXRlQ291bnQ6IDEsXG4gICAgICBpbnNlcnRzOiBbdmFsdWVdLFxuICAgIH0pXG4gIH1cbn1cbiIsImltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi9lcnJvclwiXG5cbi8qKlxuICogUGFyc2VkIHR4IHRpbWVzdGFtcCBjb21wb25lbnRzLlxuICovXG5leHBvcnQgdHlwZSBUeFRpbWVzdGFtcCA9IHtcbiAgZXBvY2g6IG51bWJlclxuICBjbG9jazogbnVtYmVyXG4gIGNsaWVudElkOiBzdHJpbmdcbiAgd2FsbENsb2NrOiBudW1iZXJcbn1cblxuLyoqXG4gKiBVbmlxdWUgdHggSUQgKENvbXBvc2l0ZSBLZXkpLlxuICovXG5leHBvcnQgdHlwZSBUeFRpbWVzdGFtcEtleSA9IHN0cmluZ1xuXG4vKipcbiAqIENvbnZlcnRzIGEgdGltZXN0YW1wIG9iamVjdCB0byBhIFRyYW5zYWN0aW9uVGltZXN0YW1wS2V5IHN0cmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR4VGltZXN0YW1wVG9LZXkodHM6IFR4VGltZXN0YW1wKTogVHhUaW1lc3RhbXBLZXkge1xuICByZXR1cm4gYCR7dHMuZXBvY2h9OyR7dHMuY2xvY2t9OyR7dHMuY2xpZW50SWR9OyR7dHMud2FsbENsb2NrfWBcbn1cblxuLyoqXG4gKiBIZWxwZXIgdG8gcGFyc2UgdHggdGltZXN0YW1wIGtleXMuXG4gKiBUaHJvd3MgaWYga2V5IGlzIG1hbGZvcm1lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVHhUaW1lc3RhbXBLZXkoa2V5OiBUeFRpbWVzdGFtcEtleSk6IFR4VGltZXN0YW1wIHtcbiAgY29uc3QgaTEgPSBrZXkuaW5kZXhPZihcIjtcIilcbiAgY29uc3QgaTIgPSBrZXkuaW5kZXhPZihcIjtcIiwgaTEgKyAxKVxuICBjb25zdCBpMyA9IGtleS5pbmRleE9mKFwiO1wiLCBpMiArIDEpXG5cbiAgaWYgKGkxID09PSAtMSB8fCBpMiA9PT0gLTEgfHwgaTMgPT09IC0xKSB7XG4gICAgZmFpbHVyZShgTWFsZm9ybWVkIHRpbWVzdGFtcCBrZXk6ICR7a2V5fWApXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGVwb2NoOiBOdW1iZXIucGFyc2VJbnQoa2V5LnN1YnN0cmluZygwLCBpMSksIDEwKSxcbiAgICBjbG9jazogTnVtYmVyLnBhcnNlSW50KGtleS5zdWJzdHJpbmcoaTEgKyAxLCBpMiksIDEwKSxcbiAgICBjbGllbnRJZDoga2V5LnN1YnN0cmluZyhpMiArIDEsIGkzKSxcbiAgICB3YWxsQ2xvY2s6IE51bWJlci5wYXJzZUludChrZXkuc3Vic3RyaW5nKGkzICsgMSksIDEwKSxcbiAgfVxufVxuXG4vKipcbiAqIENvbXBhcmVzIHR3byB0eCB0aW1lc3RhbXBzIGZvciBkZXRlcm1pbmlzdGljIG9yZGVyaW5nLlxuICogU29ydCBvcmRlcjogZXBvY2ggKGFzYykg4oaSIGNsb2NrIChhc2MpIOKGkiBjbGllbnRJZCAoYXNjKVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZVR4VGltZXN0YW1wcyhhOiBUeFRpbWVzdGFtcCwgYjogVHhUaW1lc3RhbXApOiBudW1iZXIge1xuICBpZiAoYS5lcG9jaCAhPT0gYi5lcG9jaCkgcmV0dXJuIGEuZXBvY2ggLSBiLmVwb2NoXG4gIGlmIChhLmNsb2NrICE9PSBiLmNsb2NrKSByZXR1cm4gYS5jbG9jayAtIGIuY2xvY2tcbiAgaWYgKGEuY2xpZW50SWQgPCBiLmNsaWVudElkKSByZXR1cm4gLTFcbiAgaWYgKGEuY2xpZW50SWQgPiBiLmNsaWVudElkKSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuIiwiaW1wb3J0IHR5cGUgKiBhcyBZIGZyb20gXCJ5anNcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuL2Vycm9yXCJcbmltcG9ydCB7IFR4UmVjb3JkIH0gZnJvbSBcIi4vVHhSZWNvcmRcIlxuaW1wb3J0IHsgcGFyc2VUeFRpbWVzdGFtcEtleSwgdHlwZSBUeFRpbWVzdGFtcCwgdHlwZSBUeFRpbWVzdGFtcEtleSB9IGZyb20gXCIuL3R4VGltZXN0YW1wXCJcblxuLyoqXG4gKiBBIGNhY2hlZCB0eCBlbnRyeSB3aXRoIGxhenkgcGFyc2luZyBhbmQgb3B0aW9uYWwgdHggY2FjaGluZy5cbiAqIFRoZSB0aW1lc3RhbXAgaXMgcGFyc2VkIG9uIGZpcnN0IGFjY2VzcyBhbmQgY2FjaGVkLlxuICogVGhlIHR4IHJlY29yZCBjYW4gYmUgZmV0Y2hlZCBsYXppbHkgYW5kIGNhY2hlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFNvcnRlZFR4RW50cnkge1xuICBwcml2YXRlIF90eFRpbWVzdGFtcD86IFR4VGltZXN0YW1wXG4gIHByaXZhdGUgX29yaWdpbmFsVHhUaW1lc3RhbXBLZXk/OiBUeFRpbWVzdGFtcEtleSB8IG51bGxcbiAgcHJpdmF0ZSBfb3JpZ2luYWxUeFRpbWVzdGFtcD86IFR4VGltZXN0YW1wIHwgbnVsbFxuICBwcml2YXRlIF90eFJlY29yZD86IFR4UmVjb3JkXG5cbiAgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgdHhUaW1lc3RhbXBLZXk6IFR4VGltZXN0YW1wS2V5LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3lUeDogWS5NYXA8VHhSZWNvcmQ+XG4gICkge31cblxuICAvKipcbiAgICogR2V0cyB0aGUgcGFyc2VkIHRpbWVzdGFtcCwgbGF6aWx5IHBhcnNpbmcgYW5kIGNhY2hpbmcgb24gZmlyc3QgYWNjZXNzLlxuICAgKi9cbiAgZ2V0IHR4VGltZXN0YW1wKCk6IFR4VGltZXN0YW1wIHtcbiAgICBpZiAoIXRoaXMuX3R4VGltZXN0YW1wKSB7XG4gICAgICB0aGlzLl90eFRpbWVzdGFtcCA9IHBhcnNlVHhUaW1lc3RhbXBLZXkodGhpcy50eFRpbWVzdGFtcEtleSlcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3R4VGltZXN0YW1wXG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgb3JpZ2luYWwgdHggdGltZXN0YW1wIGtleSwgbGF6aWx5IGFuZCBjYWNoaW5nIG9uIGZpcnN0IGFjY2Vzcy5cbiAgICovXG4gIGdldCBvcmlnaW5hbFR4VGltZXN0YW1wS2V5KCk6IFR4VGltZXN0YW1wS2V5IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuX29yaWdpbmFsVHhUaW1lc3RhbXBLZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgdHggPSB0aGlzLnR4UmVjb3JkXG4gICAgICB0aGlzLl9vcmlnaW5hbFR4VGltZXN0YW1wS2V5ID0gdHgub3JpZ2luYWxUeEtleSA/PyBudWxsXG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9vcmlnaW5hbFR4VGltZXN0YW1wS2V5XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgcGFyc2VkIG9yaWdpbmFsIHR4IHRpbWVzdGFtcCwgbGF6aWx5IHBhcnNpbmcgYW5kIGNhY2hpbmcgb24gZmlyc3QgYWNjZXNzLlxuICAgKi9cbiAgZ2V0IG9yaWdpbmFsVHhUaW1lc3RhbXAoKTogVHhUaW1lc3RhbXAgfCBudWxsIHtcbiAgICBpZiAodGhpcy5fb3JpZ2luYWxUeFRpbWVzdGFtcCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBrZXkgPSB0aGlzLm9yaWdpbmFsVHhUaW1lc3RhbXBLZXlcbiAgICAgIHRoaXMuX29yaWdpbmFsVHhUaW1lc3RhbXAgPSBrZXkgPyBwYXJzZVR4VGltZXN0YW1wS2V5KGtleSkgOiBudWxsXG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9vcmlnaW5hbFR4VGltZXN0YW1wXG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbG9naWNhbCAoZGVkdXBsaWNhdGVkKSB0eCB0aW1lc3RhbXAga2V5LlxuICAgKiBUaGlzIGlzIHRoZSBvcmlnaW5hbCB0eCBrZXkgaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgdGhlIHBoeXNpY2FsIGtleS5cbiAgICovXG4gIGdldCBkZWR1cFR4VGltZXN0YW1wS2V5KCk6IFR4VGltZXN0YW1wS2V5IHtcbiAgICByZXR1cm4gdGhpcy5vcmlnaW5hbFR4VGltZXN0YW1wS2V5ID8/IHRoaXMudHhUaW1lc3RhbXBLZXlcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsb2dpY2FsIChkZWR1cGxpY2F0ZWQpIHBhcnNlZCB0eCB0aW1lc3RhbXAuXG4gICAqIFRoaXMgaXMgdGhlIG9yaWdpbmFsIHR4IHRpbWVzdGFtcCBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSB0aGUgcGh5c2ljYWwgdGltZXN0YW1wLlxuICAgKi9cbiAgZ2V0IGRlZHVwVHhUaW1lc3RhbXAoKTogVHhUaW1lc3RhbXAge1xuICAgIHJldHVybiB0aGlzLm9yaWdpbmFsVHhUaW1lc3RhbXAgPz8gdGhpcy50eFRpbWVzdGFtcFxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHR4IHJlY29yZCwgbGF6aWx5IGZldGNoaW5nIGFuZCBjYWNoaW5nIG9uIGZpcnN0IGFjY2Vzcy5cbiAgICogUmV0dXJucyB1bmRlZmluZWQgaWYgdGhlIHR4IGRvZXNuJ3QgZXhpc3QuXG4gICAqL1xuICBnZXQgdHhSZWNvcmQoKTogVHhSZWNvcmQge1xuICAgIGlmICghdGhpcy5fdHhSZWNvcmQpIHtcbiAgICAgIHRoaXMuX3R4UmVjb3JkID0gdGhpcy5feVR4LmdldCh0aGlzLnR4VGltZXN0YW1wS2V5KVxuICAgICAgaWYgKCF0aGlzLl90eFJlY29yZCkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKGBTb3J0ZWRUeEVudHJ5OiBUeFJlY29yZCBub3QgZm91bmQgZm9yIGtleSAke3RoaXMudHhUaW1lc3RhbXBLZXl9YClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3R4UmVjb3JkXG4gIH1cbn1cbiIsImltcG9ydCB0eXBlICogYXMgWSBmcm9tIFwieWpzXCJcbmltcG9ydCB7IHR5cGUgQ2hlY2twb2ludFJlY29yZCwgdHlwZSBDbGllbnRXYXRlcm1hcmtzIH0gZnJvbSBcIi4vY2hlY2twb2ludHNcIlxuaW1wb3J0IHsgYXBwbHlUeEltbXV0YWJsZSB9IGZyb20gXCIuL2RyYWZ0XCJcbmltcG9ydCB7IEpTT05PYmplY3QgfSBmcm9tIFwiLi9qc29uXCJcbmltcG9ydCB7IE9wLCBWYWxpZGF0ZUZuIH0gZnJvbSBcIi4vb3BlcmF0aW9uc1wiXG5pbXBvcnQgeyBjb21wdXRlUmVjb25jaWxlT3BzIH0gZnJvbSBcIi4vcmVjb25jaWxlXCJcbmltcG9ydCB7IFNvcnRlZFR4RW50cnkgfSBmcm9tIFwiLi9Tb3J0ZWRUeEVudHJ5XCJcbmltcG9ydCB7IFR4UmVjb3JkIH0gZnJvbSBcIi4vVHhSZWNvcmRcIlxuaW1wb3J0IHsgY29tcGFyZVR4VGltZXN0YW1wcywgdHlwZSBUeFRpbWVzdGFtcCwgdHlwZSBUeFRpbWVzdGFtcEtleSB9IGZyb20gXCIuL3R4VGltZXN0YW1wXCJcbmltcG9ydCB7IGxhenkgfSBmcm9tIFwiLi91dGlsc1wiXG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdHJhbnNhY3Rpb24gaXMgY292ZXJlZCBieSB0aGUgY2hlY2twb2ludCB3YXRlcm1hcmtzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNUcmFuc2FjdGlvbkluQ2hlY2twb2ludCh0czogVHhUaW1lc3RhbXAsIHdhdGVybWFya3M6IENsaWVudFdhdGVybWFya3MpOiBib29sZWFuIHtcbiAgY29uc3Qgd20gPSB3YXRlcm1hcmtzW3RzLmNsaWVudElkXVxuICBpZiAoIXdtKSByZXR1cm4gZmFsc2VcbiAgcmV0dXJuIHRzLmNsb2NrIDw9IHdtLm1heENsb2NrXG59XG5cbi8qKlxuICogU3RhdGVDYWxjdWxhdG9yIGVuY2Fwc3VsYXRlcyB0aGUgc29ydGVkIHRyYW5zYWN0aW9uIGNhY2hlIGFuZCBzdGF0ZSBjYWxjdWxhdGlvbiBsb2dpYy5cbiAqXG4gKiBJdCBtYWludGFpbnM6XG4gKiAtIEEgc29ydGVkIGFycmF5IG9mIHRyYW5zYWN0aW9uIGVudHJpZXNcbiAqIC0gQSBtYXAgZm9yIE8oMSkgbG9va3VwXG4gKiAtIEEgdHJhY2tpbmcgaW5kZXggaW5kaWNhdGluZyB1cCB0byB3aGljaCB0eCB0aGUgc3RhdGUgaGFzIGJlZW4gY2FsY3VsYXRlZFxuICogLSBUaGUgY2FjaGVkIGNhbGN1bGF0ZWQgc3RhdGVcbiAqIC0gVGhlIGJhc2UgY2hlY2twb2ludFxuICpcbiAqIFRoZSB0cmFja2luZyBpbmRleCBpcyBpbnZhbGlkYXRlZCAoc2V0IHRvIG51bGwpIHdoZW46XG4gKiAtIEEgdHJhbnNhY3Rpb24gaXMgaW5zZXJ0ZWQgYmVmb3JlIHRoZSBhbHJlYWR5LWNhbGN1bGF0ZWQgc2xpY2VcbiAqIC0gQSB0cmFuc2FjdGlvbiBpcyBkZWxldGVkIGZyb20gdGhlIGFscmVhZHktY2FsY3VsYXRlZCBzbGljZVxuICogLSBUaGUgYmFzZSBjaGVja3BvaW50IGNoYW5nZXNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0YXRlQ2FsY3VsYXRvciB7XG4gIC8qKiBTb3J0ZWQgdHggY2FjaGUgKEFMTCBhY3RpdmUvZnV0dXJlIHR4cywga2VwdCBzb3J0ZWQgYnkgdGltZXN0YW1wKSAqL1xuICBwcml2YXRlIHNvcnRlZFR4czogU29ydGVkVHhFbnRyeVtdID0gW11cblxuICAvKiogTygxKSBleGlzdGVuY2UgY2hlY2sgYW5kIGxvb2t1cCAqL1xuICBwcml2YXRlIHNvcnRlZFR4c01hcDogTWFwPFR4VGltZXN0YW1wS2V5LCBTb3J0ZWRUeEVudHJ5PiA9IG5ldyBNYXAoKVxuXG4gIC8qKlxuICAgKiBJbmRleCBvZiB0aGUgbGFzdCB0cmFuc2FjdGlvbiBhcHBsaWVkIHRvIGNhY2hlZFN0YXRlLlxuICAgKiAtIG51bGw6IHN0YXRlIG5lZWRzIGZ1bGwgcmVjYWxjdWxhdGlvbiBmcm9tIGNoZWNrcG9pbnRcbiAgICogLSAtMTogbm8gdHJhbnNhY3Rpb25zIGhhdmUgYmVlbiBhcHBsaWVkIHlldCAoc3RhdGUgPT09IGNoZWNrcG9pbnQgc3RhdGUpXG4gICAqIC0gPj0gMDogdHJhbnNhY3Rpb25zIHVwIHRvIGFuZCBpbmNsdWRpbmcgdGhpcyBpbmRleCBoYXZlIGJlZW4gYXBwbGllZFxuICAgKi9cbiAgcHJpdmF0ZSBsYXN0QXBwbGllZEluZGV4OiBudW1iZXIgfCBudWxsID0gbnVsbFxuXG4gIC8qKiBUaGUgY2FjaGVkIGNhbGN1bGF0ZWQgc3RhdGUgKi9cbiAgcHJpdmF0ZSBjYWNoZWRTdGF0ZTogSlNPTk9iamVjdCB8IG51bGwgPSBudWxsXG5cbiAgLyoqIFRoZSBiYXNlIGNoZWNrcG9pbnQgdG8gY2FsY3VsYXRlIHN0YXRlIGZyb20gKi9cbiAgcHJpdmF0ZSBiYXNlQ2hlY2twb2ludDogQ2hlY2twb2ludFJlY29yZCB8IG51bGwgPSBudWxsXG5cbiAgLyoqXG4gICAqIEFwcGxpZWQgZGVkdXAga2V5cyAtIHRyYWNrcyB3aGljaCBMT0dJQ0FMIHR4cyBoYXZlIGJlZW4gYXBwbGllZC5cbiAgICogVGhpcyBpcyB0aGUgb3JpZ2luYWxUeEtleSAob3IgcGh5c2ljYWwga2V5IGlmIG5vIG9yaWdpbmFsKSBmb3IgZWFjaCBhcHBsaWVkIHR4LlxuICAgKiBVc2VkIHRvIHByb3Blcmx5IGRlZHVwbGljYXRlIHJlLWVtaXRzLlxuICAgKi9cbiAgcHJpdmF0ZSBhcHBsaWVkVHhLZXlzOiBTZXQ8VHhUaW1lc3RhbXBLZXk+ID0gbmV3IFNldCgpXG5cbiAgLyoqIE1heCBjbG9jayBzZWVuIGZyb20gYW55IHRyYW5zYWN0aW9uIChmb3IgTGFtcG9ydCBjbG9jayB1cGRhdGVzKSAqL1xuICBwcml2YXRlIG1heFNlZW5DbG9jayA9IDBcblxuICAvKiogVmFsaWRhdGlvbiBmdW5jdGlvbiAob3B0aW9uYWwpICovXG4gIHByaXZhdGUgdmFsaWRhdGVGbj86IFZhbGlkYXRlRm48SlNPTk9iamVjdD5cblxuICBjb25zdHJ1Y3Rvcih2YWxpZGF0ZUZuPzogVmFsaWRhdGVGbjxKU09OT2JqZWN0Pikge1xuICAgIHRoaXMudmFsaWRhdGVGbiA9IHZhbGlkYXRlRm5cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBiYXNlIGNoZWNrcG9pbnQuIEludmFsaWRhdGVzIGNhY2hlZCBzdGF0ZSBpZiBjaGVja3BvaW50IGNoYW5nZWQuXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGNoZWNrcG9pbnQgY2hhbmdlZFxuICAgKi9cbiAgc2V0QmFzZUNoZWNrcG9pbnQoY2hlY2twb2ludDogQ2hlY2twb2ludFJlY29yZCB8IG51bGwpOiBib29sZWFuIHtcbiAgICBpZiAoY2hlY2twb2ludCA9PT0gdGhpcy5iYXNlQ2hlY2twb2ludCkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuXG4gICAgdGhpcy5iYXNlQ2hlY2twb2ludCA9IGNoZWNrcG9pbnRcbiAgICB0aGlzLmludmFsaWRhdGUoKVxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgY3VycmVudCBiYXNlIGNoZWNrcG9pbnQuXG4gICAqL1xuICBnZXRCYXNlQ2hlY2twb2ludCgpOiBDaGVja3BvaW50UmVjb3JkIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZUNoZWNrcG9pbnRcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhcnMgYWxsIHRyYW5zYWN0aW9ucyBhbmQgcmVidWlsZHMgZnJvbSB5VHggbWFwLlxuICAgKiBUaGlzIGlzIHVzZWQgd2hlbiB0aGUgY2hlY2twb2ludCBjaGFuZ2VzIGFuZCB3ZSBuZWVkIGEgZnJlc2ggc3RhcnQuXG4gICAqL1xuICByZWJ1aWxkRnJvbVlqcyh5VHg6IFkuTWFwPFR4UmVjb3JkPik6IHZvaWQge1xuICAgIHRoaXMuc29ydGVkVHhzID0gW11cbiAgICB0aGlzLnNvcnRlZFR4c01hcC5jbGVhcigpXG5cbiAgICAvLyBDb2xsZWN0IGFsbCBlbnRyaWVzLCBidWlsZCB0aGUgbWFwIGFuZCBtYXggY2xvY2tcbiAgICBmb3IgKGNvbnN0IGtleSBvZiB5VHgua2V5cygpKSB7XG4gICAgICBjb25zdCBlbnRyeSA9IG5ldyBTb3J0ZWRUeEVudHJ5KGtleSwgeVR4KVxuICAgICAgdGhpcy5zb3J0ZWRUeHMucHVzaChlbnRyeSlcblxuICAgICAgdGhpcy5zb3J0ZWRUeHNNYXAuc2V0KGVudHJ5LnR4VGltZXN0YW1wS2V5LCBlbnRyeSlcbiAgICAgIGlmIChlbnRyeS50eFRpbWVzdGFtcC5jbG9jayA+IHRoaXMubWF4U2VlbkNsb2NrKSB7XG4gICAgICAgIHRoaXMubWF4U2VlbkNsb2NrID0gZW50cnkudHhUaW1lc3RhbXAuY2xvY2tcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTb3J0IG9uY2UgLSBPKG4gbG9nIG4pXG4gICAgdGhpcy5zb3J0ZWRUeHMuc29ydCgoYSwgYikgPT4gY29tcGFyZVR4VGltZXN0YW1wcyhhLnR4VGltZXN0YW1wLCBiLnR4VGltZXN0YW1wKSlcblxuICAgIC8vIEludmFsaWRhdGUgY2FjaGVkIHN0YXRlIHNpbmNlIHdlIHJlYnVpbHRcbiAgICB0aGlzLmludmFsaWRhdGUoKVxuICB9XG5cbiAgLyoqXG4gICAqIEluc2VydHMgYSB0cmFuc2FjdGlvbiBpbnRvIHRoZSBzb3J0ZWQgY2FjaGUuXG4gICAqIEludmFsaWRhdGVzIGNhY2hlZCBzdGF0ZSBpZiB0aGUgdHJhbnNhY3Rpb24gd2FzIGluc2VydGVkIGJlZm9yZSB0aGUgY2FsY3VsYXRlZCBzbGljZS5cbiAgICpcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGlzIGNhdXNlZCBpbnZhbGlkYXRpb24gKG91dC1vZi1vcmRlciBpbnNlcnQpXG4gICAqL1xuICBpbnNlcnRUeChrZXk6IFR4VGltZXN0YW1wS2V5LCB5VHg6IFkuTWFwPFR4UmVjb3JkPik6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNvcnRlZFR4c01hcC5oYXMoa2V5KSkge1xuICAgICAgcmV0dXJuIGZhbHNlIC8vIEFscmVhZHkgZXhpc3RzXG4gICAgfVxuXG4gICAgY29uc3QgZW50cnkgPSBuZXcgU29ydGVkVHhFbnRyeShrZXksIHlUeClcbiAgICBjb25zdCB0cyA9IGVudHJ5LnR4VGltZXN0YW1wXG5cbiAgICAvLyBVcGRhdGUgbWF4IHNlZW4gY2xvY2sgZm9yIExhbXBvcnQgY2xvY2sgbWVjaGFuaXNtXG4gICAgaWYgKHRzLmNsb2NrID4gdGhpcy5tYXhTZWVuQ2xvY2spIHtcbiAgICAgIHRoaXMubWF4U2VlbkNsb2NrID0gdHMuY2xvY2tcbiAgICB9XG5cbiAgICBjb25zdCBzb3J0ZWRUeHMgPSB0aGlzLnNvcnRlZFR4c1xuXG4gICAgLy8gRmluZCBpbnNlcnRpb24gcG9zaXRpb24gKHNlYXJjaCBmcm9tIGVuZCBzaW5jZSBuZXcgdHhzIHR5cGljYWxseSBoYXZlIGhpZ2hlciB0aW1lc3RhbXBzKVxuICAgIGxldCBpbnNlcnRJbmRleCA9IHNvcnRlZFR4cy5sZW5ndGggLy8gRGVmYXVsdDogYXBwZW5kIGF0IGVuZFxuICAgIGZvciAobGV0IGkgPSBzb3J0ZWRUeHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nVHMgPSBzb3J0ZWRUeHNbaV0udHhUaW1lc3RhbXBcbiAgICAgIGlmIChjb21wYXJlVHhUaW1lc3RhbXBzKHRzLCBleGlzdGluZ1RzKSA+PSAwKSB7XG4gICAgICAgIGluc2VydEluZGV4ID0gaSArIDFcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgIGluc2VydEluZGV4ID0gMCAvLyBJbnNlcnQgYXQgYmVnaW5uaW5nXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW5zZXJ0IGF0IHRoZSBmb3VuZCBwb3NpdGlvblxuICAgIHNvcnRlZFR4cy5zcGxpY2UoaW5zZXJ0SW5kZXgsIDAsIGVudHJ5KVxuICAgIHRoaXMuc29ydGVkVHhzTWFwLnNldChrZXksIGVudHJ5KVxuXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpbnZhbGlkYXRlcyBvdXIgY2FjaGVkIHN0YXRlXG4gICAgLy8gSWYgd2UgaW5zZXJ0ZWQgYmVmb3JlIG9yIGF0IHRoZSBsYXN0IGFwcGxpZWQgaW5kZXgsIHdlIG5lZWQgdG8gcmVjYWxjdWxhdGVcbiAgICBpZiAodGhpcy5sYXN0QXBwbGllZEluZGV4ICE9PSBudWxsICYmIGluc2VydEluZGV4IDw9IHRoaXMubGFzdEFwcGxpZWRJbmRleCkge1xuICAgICAgdGhpcy5pbnZhbGlkYXRlKClcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBtdWx0aXBsZSB0cmFuc2FjdGlvbnMgZnJvbSB0aGUgc29ydGVkIGNhY2hlLlxuICAgKiBAcmV0dXJucyB0aGUgbnVtYmVyIG9mIGtleXMgdGhhdCB3ZXJlIGFjdHVhbGx5IHJlbW92ZWRcbiAgICovXG4gIHJlbW92ZVR4cyhrZXlzOiByZWFkb25seSBUeFRpbWVzdGFtcEtleVtdKTogbnVtYmVyIHtcbiAgICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgICBsZXQgcmVtb3ZlZENvdW50ID0gMFxuICAgIGxldCBtaW5SZW1vdmVkSW5kZXggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFlcblxuICAgIC8vIEJ1aWxkIHNldCBvZiBrZXlzIHRvIGRlbGV0ZSBhbmQgdHJhY2sgdGhlaXIgaW5kaWNlc1xuICAgIGNvbnN0IHRvRGVsZXRlID0gbmV3IFNldDxUeFRpbWVzdGFtcEtleT4oKVxuICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5zb3J0ZWRUeHNNYXAuZ2V0KGtleSlcbiAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICB0aGlzLnNvcnRlZFR4c01hcC5kZWxldGUoa2V5KVxuICAgICAgICB0b0RlbGV0ZS5hZGQoa2V5KVxuXG4gICAgICAgIC8vIEZpbmQgaW5kZXggZm9yIGludmFsaWRhdGlvbiBjaGVja1xuICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuc29ydGVkVHhzLmluZGV4T2YoZW50cnkpXG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEgJiYgaW5kZXggPCBtaW5SZW1vdmVkSW5kZXgpIHtcbiAgICAgICAgICBtaW5SZW1vdmVkSW5kZXggPSBpbmRleFxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRvRGVsZXRlLnNpemUgPT09IDApIHJldHVybiAwXG5cbiAgICAvLyBTaW5nbGUgZm9yd2FyZCBwYXNzIHRocm91Z2ggc29ydGVkVHhzLCByZW1vdmluZyBtYXRjaGluZyBlbnRyaWVzXG4gICAgY29uc3Qgc29ydGVkVHhzID0gdGhpcy5zb3J0ZWRUeHNcbiAgICBsZXQgaSA9IDBcbiAgICB3aGlsZSAoaSA8IHNvcnRlZFR4cy5sZW5ndGggJiYgdG9EZWxldGUuc2l6ZSA+IDApIHtcbiAgICAgIGlmICh0b0RlbGV0ZS5oYXMoc29ydGVkVHhzW2ldLnR4VGltZXN0YW1wS2V5KSkge1xuICAgICAgICB0b0RlbGV0ZS5kZWxldGUoc29ydGVkVHhzW2ldLnR4VGltZXN0YW1wS2V5KVxuICAgICAgICBzb3J0ZWRUeHMuc3BsaWNlKGksIDEpXG4gICAgICAgIHJlbW92ZWRDb3VudCsrXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpKytcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0aGlzIGludmFsaWRhdGVzIG91ciBjYWNoZWQgc3RhdGVcbiAgICBpZiAodGhpcy5sYXN0QXBwbGllZEluZGV4ICE9PSBudWxsICYmIG1pblJlbW92ZWRJbmRleCA8PSB0aGlzLmxhc3RBcHBsaWVkSW5kZXgpIHtcbiAgICAgIHRoaXMuaW52YWxpZGF0ZSgpXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlbW92ZWRDb3VudFxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIHRyYW5zYWN0aW9uIGtleSBleGlzdHMgaW4gdGhlIGNhY2hlLlxuICAgKi9cbiAgaGFzVHgoa2V5OiBUeFRpbWVzdGFtcEtleSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNvcnRlZFR4c01hcC5oYXMoa2V5KVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYSB0cmFuc2FjdGlvbiBlbnRyeSBieSBrZXkuXG4gICAqL1xuICBnZXRUeChrZXk6IFR4VGltZXN0YW1wS2V5KTogU29ydGVkVHhFbnRyeSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuc29ydGVkVHhzTWFwLmdldChrZXkpXG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhbGwgc29ydGVkIHRyYW5zYWN0aW9uIGVudHJpZXMuXG4gICAqL1xuICBnZXRTb3J0ZWRUeHMoKTogcmVhZG9ubHkgU29ydGVkVHhFbnRyeVtdIHtcbiAgICByZXR1cm4gdGhpcy5zb3J0ZWRUeHNcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBudW1iZXIgb2YgdHJhbnNhY3Rpb25zIGluIHRoZSBjYWNoZS5cbiAgICovXG4gIGdldCB0eENvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuc29ydGVkVHhzLmxlbmd0aFxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3RhdGUgbmVlZHMgZnVsbCByZWNhbGN1bGF0aW9uLlxuICAgKi9cbiAgbmVlZHNGdWxsUmVjYWxjdWxhdGlvbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5sYXN0QXBwbGllZEluZGV4ID09PSBudWxsXG4gIH1cblxuICAvKipcbiAgICogSW52YWxpZGF0ZXMgdGhlIGNhY2hlZCBzdGF0ZSwgZm9yY2luZyBhIGZ1bGwgcmVjYWxjdWxhdGlvbiBvbiBuZXh0IGNhbGN1bGF0ZVN0YXRlKCkuXG4gICAqIE5vdGU6IGNhY2hlZFN0YXRlIGlzIGtlcHQgc28gY29tcHV0ZVJlY29uY2lsZU9wcyBjYW4gZGlmZiBvbGQgdnMgbmV3IHN0YXRlLlxuICAgKi9cbiAgaW52YWxpZGF0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxhc3RBcHBsaWVkSW5kZXggPSBudWxsXG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyB0aGUgY3VycmVudCBzdGF0ZSwgYWxvbmcgd2l0aCBhIGxhenkgZ2V0dGVyIGZvciBvcHMgdGhhdCBjaGFuZ2VkIGZyb20gdGhlIHByZXZpb3VzIHN0YXRlLlxuICAgKlxuICAgKiAtIElmIGxhc3RBcHBsaWVkSW5kZXggaXMgbnVsbDogZnVsbCByZWNhbGN1bGF0aW9uIGZyb20gY2hlY2twb2ludFxuICAgKiAtIElmIGxhc3RBcHBsaWVkSW5kZXggPj0gLTE6IGluY3JlbWVudGFsIGFwcGx5IGZyb20gbGFzdEFwcGxpZWRJbmRleCArIDFcbiAgICovXG4gIGNhbGN1bGF0ZVN0YXRlKCk6IHsgc3RhdGU6IEpTT05PYmplY3Q7IGdldEFwcGxpZWRPcHM6ICgpID0+IHJlYWRvbmx5IE9wW10gfSB7XG4gICAgY29uc3QgYmFzZVN0YXRlOiBKU09OT2JqZWN0ID0gdGhpcy5iYXNlQ2hlY2twb2ludD8uc3RhdGUgPz8ge31cbiAgICBjb25zdCB3YXRlcm1hcmtzID0gdGhpcy5iYXNlQ2hlY2twb2ludD8ud2F0ZXJtYXJrcyA/PyB7fVxuICAgIGNvbnN0IGhhc1dhdGVybWFya3MgPSBPYmplY3Qua2V5cyh3YXRlcm1hcmtzKS5sZW5ndGggPiAwXG5cbiAgICBpZiAodGhpcy5sYXN0QXBwbGllZEluZGV4ID09PSBudWxsKSB7XG4gICAgICAvLyBTTE9XIFBBVEg6IEZ1bGwgcmVjYWxjdWxhdGlvblxuICAgICAgcmV0dXJuIHRoaXMuZnVsbFJlY2FsY3VsYXRpb24oYmFzZVN0YXRlLCB3YXRlcm1hcmtzLCBoYXNXYXRlcm1hcmtzKVxuICAgIH1cblxuICAgIC8vIEZBU1QgUEFUSDogSW5jcmVtZW50YWwgYXBwbHlcbiAgICByZXR1cm4gdGhpcy5pbmNyZW1lbnRhbEFwcGx5KHdhdGVybWFya3MsIGhhc1dhdGVybWFya3MpXG4gIH1cblxuICAvKipcbiAgICogRnVsbCByZWNhbGN1bGF0aW9uIG9mIHN0YXRlIGZyb20gdGhlIGJhc2UgY2hlY2twb2ludC5cbiAgICovXG4gIHByaXZhdGUgZnVsbFJlY2FsY3VsYXRpb24oXG4gICAgYmFzZVN0YXRlOiBKU09OT2JqZWN0LFxuICAgIHdhdGVybWFya3M6IENsaWVudFdhdGVybWFya3MsXG4gICAgaGFzV2F0ZXJtYXJrczogYm9vbGVhblxuICApOiB7IHN0YXRlOiBKU09OT2JqZWN0OyBnZXRBcHBsaWVkT3BzOiAoKSA9PiByZWFkb25seSBPcFtdIH0ge1xuICAgIGNvbnN0IG9sZFN0YXRlID0gdGhpcy5jYWNoZWRTdGF0ZSA/PyB7fVxuXG4gICAgLy8gUmVzZXQgdHJhY2tpbmcgZm9yIGZ1bGwgcmVjb21wdXRlXG4gICAgdGhpcy5hcHBsaWVkVHhLZXlzLmNsZWFyKClcbiAgICB0aGlzLmxhc3RBcHBsaWVkSW5kZXggPSAtMVxuICAgIHRoaXMuY2FjaGVkU3RhdGUgPSBiYXNlU3RhdGVcblxuICAgIC8vIERlbGVnYXRlIHRvIGluY3JlbWVudGFsIGFwcGx5IHRvIHJlcGxheSBhbGwgdHJhbnNhY3Rpb25zXG4gICAgLy8gV2UgaWdub3JlIHRoZSByZXR1cm5lZCBvcHMgYmVjYXVzZSB0aGV5IHJlcHJlc2VudCB0aGUgb3BlcmF0aW9ucyBhcHBsaWVkIGZyb20gdGhlIGJhc2Ugc3RhdGUsXG4gICAgLy8gd2hlcmVhcyB3ZSB3YW50IHRoZSBkaWZmIGZyb20gdGhlICpwcmV2aW91cyBjYWNoZWQgc3RhdGUqLlxuICAgIC8vIFdlIHBhc3MgcmV0dXJuT3BzPWZhbHNlIHRvIGF2b2lkIGNvbGxlY3Rpbmcgb3BzIGR1cmluZyByZXBsYXkuXG4gICAgY29uc3QgeyBzdGF0ZSB9ID0gdGhpcy5pbmNyZW1lbnRhbEFwcGx5KHdhdGVybWFya3MsIGhhc1dhdGVybWFya3MsIGZhbHNlKVxuXG4gICAgLy8gTGF6eSBsb2FkIHRoZSByZWNvbmNpbGlhdGlvbiBvcHMgKGV4cGVuc2l2ZSBkaWZmKVxuICAgIGNvbnN0IGdldEFwcGxpZWRPcHMgPSBsYXp5KCgpID0+IGNvbXB1dGVSZWNvbmNpbGVPcHMob2xkU3RhdGUsIHN0YXRlKSlcblxuICAgIHJldHVybiB7IHN0YXRlLCBnZXRBcHBsaWVkT3BzIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRhbCBhcHBseSBvZiB0cmFuc2FjdGlvbnMgZnJvbSBsYXN0QXBwbGllZEluZGV4ICsgMS5cbiAgICogQHBhcmFtIHJldHVybk9wcyBJZiB0cnVlLCBjb2xsZWN0cyBhcHBsaWVkIHRyYW5zYWN0aW9ucyAodG8gbGF6eSBjb21wdXRlIG9wcykuIElmIGZhbHNlLCBza2lwcyBjb2xsZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBpbmNyZW1lbnRhbEFwcGx5KFxuICAgIHdhdGVybWFya3M6IENsaWVudFdhdGVybWFya3MsXG4gICAgaGFzV2F0ZXJtYXJrczogYm9vbGVhbixcbiAgICByZXR1cm5PcHMgPSB0cnVlXG4gICk6IHsgc3RhdGU6IEpTT05PYmplY3Q7IGdldEFwcGxpZWRPcHM6ICgpID0+IHJlYWRvbmx5IE9wW10gfSB7XG4gICAgbGV0IHN0YXRlID0gdGhpcy5jYWNoZWRTdGF0ZSBhcyBKU09OT2JqZWN0XG4gICAgY29uc3QgYXBwbGllZFR4czogVHhSZWNvcmRbXSA9IFtdXG4gICAgY29uc3Qgc29ydGVkVHhzID0gdGhpcy5zb3J0ZWRUeHNcbiAgICBjb25zdCBzdGFydEluZGV4ID0gdGhpcy5sYXN0QXBwbGllZEluZGV4ISArIDFcblxuICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgc29ydGVkVHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBlbnRyeSA9IHNvcnRlZFR4c1tpXVxuICAgICAgY29uc3QgZGVkdXBLZXkgPSBlbnRyeS5kZWR1cFR4VGltZXN0YW1wS2V5XG5cbiAgICAgIC8vIFNraXAgaWYgYWxyZWFkeSBhcHBsaWVkIChkZWR1cGxpY2F0aW9uKVxuICAgICAgaWYgKHRoaXMuYXBwbGllZFR4S2V5cy5oYXMoZGVkdXBLZXkpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIFNraXAgaWYgaW4gY2hlY2twb2ludFxuICAgICAgaWYgKGhhc1dhdGVybWFya3MpIHtcbiAgICAgICAgY29uc3QgZGVkdXBUcyA9IGVudHJ5LmRlZHVwVHhUaW1lc3RhbXBcbiAgICAgICAgaWYgKGlzVHJhbnNhY3Rpb25JbkNoZWNrcG9pbnQoZGVkdXBUcywgd2F0ZXJtYXJrcykpIHtcbiAgICAgICAgICB0aGlzLmFwcGxpZWRUeEtleXMuYWRkKGRlZHVwS2V5KVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgdHggPSBlbnRyeS50eFJlY29yZFxuXG4gICAgICAvLyBBcHBseSB0cmFuc2FjdGlvbiAxLWJ5LTEgdG8gYXZvaWQgZHJhZnQgY29udGV4dCBwb2xsdXRpb24gb24gdmFsaWRhdGlvbiBmYWlsdXJlXG4gICAgICBjb25zdCBuZXdTdGF0ZSA9IGFwcGx5VHhJbW11dGFibGUoc3RhdGUsIHR4LCB0aGlzLnZhbGlkYXRlRm4pXG5cbiAgICAgIGlmIChuZXdTdGF0ZSAhPT0gc3RhdGUpIHtcbiAgICAgICAgc3RhdGUgPSBuZXdTdGF0ZVxuICAgICAgICBpZiAocmV0dXJuT3BzKSB7XG4gICAgICAgICAgYXBwbGllZFR4cy5wdXNoKHR4KVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYXBwbGllZFR4S2V5cy5hZGQoZGVkdXBLZXkpXG4gICAgICB0aGlzLmxhc3RBcHBsaWVkSW5kZXggPSBpXG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIGxhc3RBcHBsaWVkSW5kZXggdG8gZW5kIGV2ZW4gaWYgYWxsIHR4cyB3ZXJlIHNraXBwZWRcbiAgICAvLyBUaGlzIGVuc3VyZXMgd2UgZG9uJ3QgcmUtcHJvY2VzcyBza2lwcGVkIHR4cyBvbiBuZXh0IGluY3JlbWVudGFsIGFwcGx5XG4gICAgaWYgKHNvcnRlZFR4cy5sZW5ndGggPiAwICYmIHRoaXMubGFzdEFwcGxpZWRJbmRleCEgPCBzb3J0ZWRUeHMubGVuZ3RoIC0gMSkge1xuICAgICAgdGhpcy5sYXN0QXBwbGllZEluZGV4ID0gc29ydGVkVHhzLmxlbmd0aCAtIDFcbiAgICB9XG5cbiAgICB0aGlzLmNhY2hlZFN0YXRlID0gc3RhdGVcblxuICAgIC8vIExhenkgZ2V0dGVyIGZvciBvcHMgKGZsYXR0ZW5zIGFwcGxpZWQgdHhzKVxuICAgIGNvbnN0IGdldEFwcGxpZWRPcHMgPSBsYXp5KCgpID0+IHtcbiAgICAgIGNvbnN0IG9wczogT3BbXSA9IFtdXG4gICAgICBmb3IgKGNvbnN0IHR4IG9mIGFwcGxpZWRUeHMpIHtcbiAgICAgICAgb3BzLnB1c2goLi4udHgub3BzKVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9wc1xuICAgIH0pXG5cbiAgICByZXR1cm4geyBzdGF0ZSwgZ2V0QXBwbGllZE9wcyB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbWF4IHNlZW4gY2xvY2sgKGZvciBMYW1wb3J0IGNsb2NrIHVwZGF0ZXMpLlxuICAgKi9cbiAgZ2V0TWF4U2VlbkNsb2NrKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMubWF4U2VlbkNsb2NrXG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgY3VycmVudCBjYWNoZWQgc3RhdGUgd2l0aG91dCByZWNhbGN1bGF0aW5nLlxuICAgKiBSZXR1cm5zIG51bGwgaWYgc3RhdGUgaGFzIG5ldmVyIGJlZW4gY2FsY3VsYXRlZC5cbiAgICovXG4gIGdldENhY2hlZFN0YXRlKCk6IEpTT05PYmplY3QgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWRTdGF0ZVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGxhc3QgYXBwbGllZCB0aW1lc3RhbXAuXG4gICAqL1xuICBnZXRMYXN0QXBwbGllZFRzKCk6IFR4VGltZXN0YW1wIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMubGFzdEFwcGxpZWRJbmRleCA9PT0gbnVsbCB8fCB0aGlzLmxhc3RBcHBsaWVkSW5kZXggPCAwKSB7XG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zb3J0ZWRUeHNbdGhpcy5sYXN0QXBwbGllZEluZGV4XT8udHhUaW1lc3RhbXAgPz8gbnVsbFxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGxhc3QgYXBwbGllZCBpbmRleCAoZm9yIGRlYnVnZ2luZy90cmFja2luZykuXG4gICAqL1xuICBnZXRMYXN0QXBwbGllZEluZGV4KCk6IG51bWJlciB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLmxhc3RBcHBsaWVkSW5kZXhcbiAgfVxufVxuIiwiaW1wb3J0IHsgSlNPTk9iamVjdCB9IGZyb20gXCIuL2pzb25cIlxuaW1wb3J0IHsgVmFsaWRhdGVGbiB9IGZyb20gXCIuL29wZXJhdGlvbnNcIlxuaW1wb3J0IHsgU3RhdGVDYWxjdWxhdG9yIH0gZnJvbSBcIi4vU3RhdGVDYWxjdWxhdG9yXCJcblxuLyoqXG4gKiBDbGllbnQtc2lkZSBzdGF0ZSBpbmNsdWRpbmcgY2xvY2tzIGFuZCBjYWxjdWxhdG9yIGZvciBzdGF0ZSBtYW5hZ2VtZW50XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpZW50U3RhdGUge1xuICAvLyBMYW1wb3J0IGNsb2NrcyAobW9ub3RvbmljLCBuZXZlciByZXNldClcbiAgbG9jYWxDbG9jazogbnVtYmVyXG5cbiAgLy8gQ2FjaGVkIGZpbmFsaXplZCBlcG9jaCAobnVsbCA9IG5vdCB5ZXQgaW5pdGlhbGl6ZWQsIHJlY2FsY3VsYXRlZCBvbmx5IHdoZW4gY2hlY2twb2ludCBtYXAgY2hhbmdlcylcbiAgY2FjaGVkRmluYWxpemVkRXBvY2g6IG51bWJlciB8IG51bGxcblxuICAvLyBTdGF0ZSBjYWxjdWxhdG9yIChtYW5hZ2VzIHNvcnRlZCB0eCBjYWNoZSwgc3RhdGUgY2FsY3VsYXRpb24sIGFuZCBpbnZhbGlkYXRpb24pXG4gIHN0YXRlQ2FsY3VsYXRvcjogU3RhdGVDYWxjdWxhdG9yXG5cbiAgLyoqXG4gICAqIFRpbWVzdGFtcCByZXRlbnRpb24gd2luZG93IGluIG1pbGxpc2Vjb25kcy5cbiAgICovXG4gIHJldGVudGlvbldpbmRvd01zOiBudW1iZXJcbn1cblxuLyoqXG4gKiBGYWN0b3J5IHRvIGNyZWF0ZSBhbiBpbml0aWFsIENsaWVudFN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDbGllbnRTdGF0ZShcbiAgdmFsaWRhdGVGbjogVmFsaWRhdGVGbjxKU09OT2JqZWN0PiB8IHVuZGVmaW5lZCxcbiAgcmV0ZW50aW9uV2luZG93TXM6IG51bWJlclxuKTogQ2xpZW50U3RhdGUge1xuICByZXR1cm4ge1xuICAgIGxvY2FsQ2xvY2s6IDAsXG4gICAgY2FjaGVkRmluYWxpemVkRXBvY2g6IG51bGwsIC8vIFdpbGwgYmUgcmVjYWxjdWxhdGVkIG9uIGZpcnN0IHJ1blxuICAgIHN0YXRlQ2FsY3VsYXRvcjogbmV3IFN0YXRlQ2FsY3VsYXRvcih2YWxpZGF0ZUZuKSxcbiAgICByZXRlbnRpb25XaW5kb3dNcyxcbiAgfVxufVxuIiwiaW1wb3J0ICogYXMgWSBmcm9tIFwieWpzXCJcbmltcG9ydCB7IHR5cGUgQ2hlY2twb2ludFJlY29yZCwgcHJ1bmVDaGVja3BvaW50cyB9IGZyb20gXCIuL2NoZWNrcG9pbnRzXCJcbmltcG9ydCB7IGdldEZpbmFsaXplZEVwb2NoQW5kQ2hlY2twb2ludCB9IGZyb20gXCIuL2NoZWNrcG9pbnRVdGlsc1wiXG5pbXBvcnQgeyBDbGllbnRTdGF0ZSB9IGZyb20gXCIuL2NsaWVudFN0YXRlXCJcbmltcG9ydCB7IEpTT05PYmplY3QgfSBmcm9tIFwiLi9qc29uXCJcbmltcG9ydCB7IE9wIH0gZnJvbSBcIi4vb3BlcmF0aW9uc1wiXG5pbXBvcnQgeyBTb3J0ZWRUeEVudHJ5IH0gZnJvbSBcIi4vU29ydGVkVHhFbnRyeVwiXG5pbXBvcnQgeyBpc1RyYW5zYWN0aW9uSW5DaGVja3BvaW50IH0gZnJvbSBcIi4vU3RhdGVDYWxjdWxhdG9yXCJcbmltcG9ydCB7IFR4UmVjb3JkIH0gZnJvbSBcIi4vVHhSZWNvcmRcIlxuaW1wb3J0IHsgdHlwZSBUeFRpbWVzdGFtcCwgdHlwZSBUeFRpbWVzdGFtcEtleSwgdHhUaW1lc3RhbXBUb0tleSB9IGZyb20gXCIuL3R4VGltZXN0YW1wXCJcblxuLyoqXG4gKiBDaGFuZ2VzIHRvIHRyYW5zYWN0aW9uIGtleXMgZnJvbSBhIFkuWU1hcEV2ZW50LlxuICogLSBhZGRlZDoga2V5cyB0aGF0IHdlcmUgYWRkZWRcbiAqIC0gZGVsZXRlZDoga2V5cyB0aGF0IHdlcmUgZGVsZXRlZFxuICovXG5leHBvcnQgdHlwZSBUeEtleUNoYW5nZXMgPSB7XG4gIGFkZGVkOiByZWFkb25seSBUeFRpbWVzdGFtcEtleVtdXG4gIGRlbGV0ZWQ6IHJlYWRvbmx5IFR4VGltZXN0YW1wS2V5W11cbn1cblxuLyoqXG4gKiBBcHBlbmRzIGEgbmV3IHRyYW5zYWN0aW9uIHRvIHRoZSBsb2cuXG4gKlxuICogQHBhcmFtIG9yaWdpbmFsS2V5IC0gT3B0aW9uYWwgcmVmZXJlbmNlIHRvIHRoZSBvcmlnaW5hbCB0cmFuc2FjdGlvbiBrZXkgZm9yIHJlLWVtaXRzLlxuICogICAgICAgICAgICAgICAgICAgICAgVXNlZCBieSBzeW5jTG9nIHRvIHByZXNlcnZlIHRyYW5zYWN0aW9ucyBtaXNzZWQgYnkgY2hlY2twb2ludHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRUeChcbiAgb3BzOiByZWFkb25seSBPcFtdLFxuICB5VHg6IFkuTWFwPFR4UmVjb3JkPixcbiAgYWN0aXZlRXBvY2g6IG51bWJlcixcbiAgbXlDbGllbnRJZDogc3RyaW5nLFxuICBjbGllbnRTdGF0ZTogQ2xpZW50U3RhdGUsXG4gIG9yaWdpbmFsS2V5PzogVHhUaW1lc3RhbXBLZXlcbik6IFR4VGltZXN0YW1wS2V5IHtcbiAgY29uc3QgY2FsYyA9IGNsaWVudFN0YXRlLnN0YXRlQ2FsY3VsYXRvclxuXG4gIC8vIDEuIEFkdmFuY2UgbG9naWNhbCBjbG9jayAoTGFtcG9ydCkgYmFzZWQgb24gYWxsIHNlZW4gdHJhZmZpY1xuICBjb25zdCBjbG9jayA9IE1hdGgubWF4KGNsaWVudFN0YXRlLmxvY2FsQ2xvY2ssIGNhbGMuZ2V0TWF4U2VlbkNsb2NrKCkpICsgMVxuICBjbGllbnRTdGF0ZS5sb2NhbENsb2NrID0gY2xvY2tcblxuICAvLyAyLiBHZW5lcmF0ZSBLZXkgd2l0aCBXYWxsQ2xvY2sgZm9yIGZ1dHVyZSBwcnVuaW5nIHNhZmV0eVxuICBjb25zdCB0czogVHhUaW1lc3RhbXAgPSB7XG4gICAgZXBvY2g6IGFjdGl2ZUVwb2NoLFxuICAgIGNsb2NrLFxuICAgIGNsaWVudElkOiBteUNsaWVudElkLFxuICAgIHdhbGxDbG9jazogRGF0ZS5ub3coKSxcbiAgfVxuICBjb25zdCBrZXkgPSB0eFRpbWVzdGFtcFRvS2V5KHRzKVxuXG4gIC8vIDMuIFdyaXRlIHRvIFlqcyAoQXRvbWljKVxuICBjb25zdCByZWNvcmQ6IFR4UmVjb3JkID0geyBvcHMsIG9yaWdpbmFsVHhLZXk6IG9yaWdpbmFsS2V5IH1cbiAgeVR4LnNldChrZXksIHJlY29yZClcblxuICByZXR1cm4ga2V5XG59XG5cbi8qKlxuICogU3luY2hyb25pemVzIHRoZSB0cmFuc2FjdGlvbiBsb2cgd2l0aCB0aGUgY3VycmVudCBjaGVja3BvaW50LlxuICogUmUtZW1pdHMgbWlzc2VkIHRyYW5zYWN0aW9ucyBhbmQgcHJ1bmVzIG9sZCBvbmVzLlxuICpcbiAqIFNob3VsZCBiZSBjYWxsZWQgQkVGT1JFIHVwZGF0ZVN0YXRlIHRvIGVuc3VyZSBsb2cgaXMgY2xlYW4gYW5kIGNvbXBsZXRlLlxuICpcbiAqIEByZXR1cm5zIHRydWUgaWYgYW55IHRyYW5zYWN0aW9ucyB3ZXJlIHJlLWVtaXR0ZWQgb3IgZGVsZXRlZCwgd2hpY2ggbWF5IGludmFsaWRhdGUgbGFzdEFwcGxpZWRJbmRleFxuICovXG5mdW5jdGlvbiBzeW5jTG9nKFxuICB5VHg6IFkuTWFwPFR4UmVjb3JkPixcbiAgbXlDbGllbnRJZDogc3RyaW5nLFxuICBjbGllbnRTdGF0ZTogQ2xpZW50U3RhdGUsXG4gIGZpbmFsaXplZEVwb2NoOiBudW1iZXIsXG4gIGJhc2VDUDogQ2hlY2twb2ludFJlY29yZCB8IG51bGwsXG4gIG5ld0tleXM/OiByZWFkb25seSBUeFRpbWVzdGFtcEtleVtdIC8vIGtleXMgYWRkZWQgaW4gdGhpcyB1cGRhdGVcbik6IHZvaWQge1xuICBjb25zdCBjYWxjID0gY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yXG4gIGNvbnN0IGFjdGl2ZUVwb2NoID0gZmluYWxpemVkRXBvY2ggKyAxXG4gIGNvbnN0IHdhdGVybWFya3MgPSBiYXNlQ1A/LndhdGVybWFya3MgPz8ge31cblxuICAvLyBEZXRlcm1pbmlzdGljIFJlZmVyZW5jZSBUaW1lOiBVc2Ugc3RvcmVkIG1pbldhbGxDbG9jayBpZiBhdmFpbGFibGUsIG90aGVyd2lzZSAwIChub3RoaW5nIGFuY2llbnQpLlxuICBjb25zdCByZWZlcmVuY2VUaW1lID0gYmFzZUNQPy5taW5XYWxsQ2xvY2sgPz8gMFxuXG4gIC8vIEhlbHBlciB0byBjaGVjayBpZiBhIHRyYW5zYWN0aW9uIHNob3VsZCBiZSBwcnVuZWRcbiAgY29uc3Qgc2hvdWxkUHJ1bmUgPSAodHM6IFR4VGltZXN0YW1wLCBkZWR1cFRzOiBUeFRpbWVzdGFtcCk6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IGlzQW5jaWVudCA9IHJlZmVyZW5jZVRpbWUgLSB0cy53YWxsQ2xvY2sgPiBjbGllbnRTdGF0ZS5yZXRlbnRpb25XaW5kb3dNc1xuICAgIGlmIChpc0FuY2llbnQpIHJldHVybiB0cnVlXG4gICAgcmV0dXJuIGlzVHJhbnNhY3Rpb25JbkNoZWNrcG9pbnQoZGVkdXBUcywgd2F0ZXJtYXJrcylcbiAgfVxuXG4gIGNvbnN0IHRvRGVsZXRlOiBUeFRpbWVzdGFtcEtleVtdID0gW11cbiAgY29uc3QgdG9SZUVtaXQ6IEFycmF5PHsgb3JpZ2luYWxLZXk6IFR4VGltZXN0YW1wS2V5OyB0eDogVHhSZWNvcmQgfT4gPSBbXVxuXG4gIC8vIDEuIEhlbHBlciB0byBkZWNpZGUgd2hhdCB0byBkbyB3aXRoIGVhY2ggdHJhbnNhY3Rpb25cbiAgY29uc3QgcHJvY2Vzc0VudHJ5ID0gKGVudHJ5OiBTb3J0ZWRUeEVudHJ5KTogYm9vbGVhbiA9PiB7XG4gICAgaWYgKHNob3VsZFBydW5lKGVudHJ5LnR4VGltZXN0YW1wLCBlbnRyeS5kZWR1cFR4VGltZXN0YW1wKSkge1xuICAgICAgdG9EZWxldGUucHVzaChlbnRyeS50eFRpbWVzdGFtcEtleSlcbiAgICAgIHJldHVybiBmYWxzZSAvLyBkZWxldGVkXG4gICAgfVxuXG4gICAgaWYgKGVudHJ5LnR4VGltZXN0YW1wLmVwb2NoIDw9IGZpbmFsaXplZEVwb2NoKSB7XG4gICAgICAvLyBOb3QgaW4gY2hlY2twb2ludCBhbmQgc3RpbGwgZnJlc2ggLSByZS1lbWl0IGl0IHRvIHRoZSBhY3RpdmUgZXBvY2hcbiAgICAgIHRvUmVFbWl0LnB1c2goeyBvcmlnaW5hbEtleTogZW50cnkuZGVkdXBUeFRpbWVzdGFtcEtleSwgdHg6IGVudHJ5LnR4UmVjb3JkIH0pXG4gICAgICB0b0RlbGV0ZS5wdXNoKGVudHJ5LnR4VGltZXN0YW1wS2V5KVxuICAgICAgcmV0dXJuIGZhbHNlIC8vIHJlLWVtaXR0ZWRcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZSAvLyBhY3RpdmUvZnJlc2hcbiAgfVxuXG4gIC8vIDIuIFNjYW4gbG9jYWwgY2FjaGUgKHNvcnRlZFR4cykgdG8gaWRlbnRpZnkgbWlzc2luZy9hbmNpZW50IHRyYW5zYWN0aW9uc1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGNhbGMuZ2V0U29ydGVkVHhzKCkpIHtcbiAgICBpZiAocHJvY2Vzc0VudHJ5KGVudHJ5KSkge1xuICAgICAgLy8gT3B0aW1pemF0aW9uOiBQaHlzaWNhbCBrZXlzIGFyZSBzb3J0ZWQuIElmIHdlIGhpdCB0aGUgYWN0aXZlL2ZyZXNoIHRlcnJpdG9yeSwgd2UgY2FuIHN0b3AuXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHByb2Nlc3NLZXlCeVRpbWVzdGFtcEtleSA9ICh0eFRpbWVzdGFtcEtleTogVHhUaW1lc3RhbXBLZXkpOiB2b2lkID0+IHtcbiAgICAvLyBPbmx5IHByb2Nlc3MgaWYgaXQgYWN0dWFsbHkgZXhpc3RzIGluIFlqcyBNYXBcbiAgICBpZiAoeVR4Lmhhcyh0eFRpbWVzdGFtcEtleSkpIHtcbiAgICAgIHByb2Nlc3NFbnRyeShuZXcgU29ydGVkVHhFbnRyeSh0eFRpbWVzdGFtcEtleSwgeVR4KSlcbiAgICB9XG4gIH1cblxuICAvLyAzLiBTY2FuIE5FVyBrZXlzIGZyb20gWWpzIHRvIGhhbmRsZSBpbmNvbWluZyB0cmFuc2FjdGlvbnMgKHN5bmMpXG4gIC8vIEFueSBjbGllbnQgY2FuIHJlLWVtaXQgLSBkZWR1cGxpY2F0aW9uIHZpYSBvcmlnaW5hbFR4S2V5IGhhbmRsZXMgZHVwbGljYXRlcy5cbiAgaWYgKG5ld0tleXMpIHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBuZXdLZXlzKSB7XG4gICAgICBwcm9jZXNzS2V5QnlUaW1lc3RhbXBLZXkoa2V5KVxuICAgIH1cbiAgfVxuXG4gIC8vIDQuIFJlLWVtaXQgbWlzc2VkIHRyYW5zYWN0aW9ucyBCRUZPUkUgcHJ1bmluZ1xuICBmb3IgKGNvbnN0IHsgb3JpZ2luYWxLZXksIHR4IH0gb2YgdG9SZUVtaXQpIHtcbiAgICBjb25zdCBuZXdLZXkgPSBhcHBlbmRUeCh0eC5vcHMsIHlUeCwgYWN0aXZlRXBvY2gsIG15Q2xpZW50SWQsIGNsaWVudFN0YXRlLCBvcmlnaW5hbEtleSlcbiAgICBjYWxjLmluc2VydFR4KG5ld0tleSwgeVR4KVxuICB9XG5cbiAgLy8gNS4gUHJ1bmUgb2xkL2ZpbmFsaXplZC9yZWR1bmRhbnQgdHJhbnNhY3Rpb25zIGZyb20gWWpzIE1hcFxuICBmb3IgKGNvbnN0IGtleSBvZiB0b0RlbGV0ZSkge1xuICAgIHlUeC5kZWxldGUoa2V5KVxuICB9XG4gIGNhbGMucmVtb3ZlVHhzKHRvRGVsZXRlKVxufVxuXG4vKipcbiAqIFRoZSBwcmltYXJ5IHVwZGF0ZSBmdW5jdGlvbiB0aGF0IG1haW50YWlucyBjdXJyZW50IHN0YXRlLlxuICpcbiAqIEBwYXJhbSB0eENoYW5nZXMgLSBDaGFuZ2VzIGZyb20gWS5ZTWFwRXZlbnQuIElmIHVuZGVmaW5lZCAoZmlyc3QgcnVuKSwgcGVyZm9ybXMgYSBmdWxsIHNjYW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVTdGF0ZShcbiAgZG9jOiBZLkRvYyxcbiAgeVR4OiBZLk1hcDxUeFJlY29yZD4sXG4gIHlDaGVja3BvaW50OiBZLk1hcDxDaGVja3BvaW50UmVjb3JkPixcbiAgbXlDbGllbnRJZDogc3RyaW5nLFxuICBjbGllbnRTdGF0ZTogQ2xpZW50U3RhdGUsXG4gIHR4Q2hhbmdlczogVHhLZXlDaGFuZ2VzIHwgdW5kZWZpbmVkXG4pOiB7IHN0YXRlOiBKU09OT2JqZWN0OyBnZXRBcHBsaWVkT3BzOiAoKSA9PiByZWFkb25seSBPcFtdIH0ge1xuICBjb25zdCBjYWxjID0gY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yXG5cbiAgLy8gQWx3YXlzIGNhbGN1bGF0ZSBmcmVzaCBmaW5hbGl6ZWQgZXBvY2ggYW5kIGNoZWNrcG9pbnQgdG8gaGFuZGxlIHN5bmMgcmFjZSBjb25kaXRpb25zXG4gIGNvbnN0IHsgZmluYWxpemVkRXBvY2gsIGNoZWNrcG9pbnQ6IGJhc2VDUCB9ID0gZ2V0RmluYWxpemVkRXBvY2hBbmRDaGVja3BvaW50KHlDaGVja3BvaW50KVxuXG4gIC8vIFVwZGF0ZSByZWFkLWNhY2hlXG4gIGNsaWVudFN0YXRlLmNhY2hlZEZpbmFsaXplZEVwb2NoID0gZmluYWxpemVkRXBvY2hcblxuICAvLyBTZXQgYmFzZSBjaGVja3BvaW50ICh0aGlzIGhhbmRsZXMgaW52YWxpZGF0aW9uIGlmIGNoZWNrcG9pbnQgY2hhbmdlZClcbiAgY2FsYy5zZXRCYXNlQ2hlY2twb2ludChiYXNlQ1ApXG5cbiAgLy8gVHJhY2sgaWYgd2UgbmVlZCB0byByZWJ1aWxkIHNvcnRlZCBjYWNoZSAoZmlyc3QgcnVuIG9yIG1pc3NpbmcgZGVsdGEpXG4gIC8vIE9wdGltaXphdGlvbjogV2UgZG9uJ3QgbmVlZCB0byByZWJ1aWxkIGp1c3QgYmVjYXVzZSBjaGVja3BvaW50IGNoYW5nZWQsXG4gIC8vIGFzIGxvbmcgYXMgd2UgaGF2ZSB0eENoYW5nZXMgdG8ga2VlcCBjYWNoZSBpbiBzeW5jLlxuICBjb25zdCBuZWVkc1JlYnVpbGRTb3J0ZWRDYWNoZSA9IGNhbGMuZ2V0Q2FjaGVkU3RhdGUoKSA9PT0gbnVsbCB8fCAhdHhDaGFuZ2VzXG5cbiAgLy8gUmVidWlsZCBzb3J0ZWQgY2FjaGUgYmVmb3JlIHN5bmNMb2cgaWYgbmVlZGVkXG4gIGlmIChuZWVkc1JlYnVpbGRTb3J0ZWRDYWNoZSkge1xuICAgIGNhbGMucmVidWlsZEZyb21ZanMoeVR4KVxuICB9IGVsc2Uge1xuICAgIC8vIElmIG5vdCByZWJ1aWxkaW5nLCBpbW1lZGlhdGVseSBwcm9jZXNzIGRlbGV0aW9ucyB0byBhdm9pZCBcImdob3N0XCIgdHJhbnNhY3Rpb25zXG4gICAgLy8gaW4gc3luY0xvZyAoZS5nLiBhdHRlbXB0aW5nIHRvIGFjY2VzcyBhIHRyYW5zYWN0aW9uIHRoYXQgd2FzIGp1c3QgZGVsZXRlZCkuXG4gICAgY2FsYy5yZW1vdmVUeHModHhDaGFuZ2VzLmRlbGV0ZWQpXG4gIH1cblxuICAvLyBTeW5jIGFuZCBwcnVuZSB3aXRoaW4gdHJhbnNhY3Rpb25cbiAgZG9jLnRyYW5zYWN0KCgpID0+IHtcbiAgICBzeW5jTG9nKHlUeCwgbXlDbGllbnRJZCwgY2xpZW50U3RhdGUsIGZpbmFsaXplZEVwb2NoLCBiYXNlQ1AsIHR4Q2hhbmdlcz8uYWRkZWQpXG5cbiAgICAvLyBTYWZlIHRvIHVzZSBsb2NhbCBmaW5hbGl6ZWRFcG9jaCBoZXJlXG4gICAgcHJ1bmVDaGVja3BvaW50cyh5Q2hlY2twb2ludCwgZmluYWxpemVkRXBvY2gpXG4gIH0pXG5cbiAgaWYgKG5lZWRzUmVidWlsZFNvcnRlZENhY2hlKSB7XG4gICAgLy8gRnVsbCByZWNvbXB1dGUgKGNhbGN1bGF0b3IgaGFuZGxlcyB0aGlzKVxuICAgIHJldHVybiBjYWxjLmNhbGN1bGF0ZVN0YXRlKClcbiAgfVxuXG4gIC8vIEluY3JlbWVudGFsIHVwZGF0ZSB1c2luZyBvbmx5IGNoYW5nZWQga2V5cyAoY2FsY3VsYXRvciBoYW5kbGVzIHRoaXMpXG4gIC8vIHR4Q2hhbmdlcyBpcyBndWFyYW50ZWVkIHRvIGV4aXN0IGhlcmUgc2luY2UgIXR4Q2hhbmdlcyBpbXBsaWVzIG5lZWRzUmVidWlsZFNvcnRlZENhY2hlXG5cbiAgLy8gVXBkYXRlIHNvcnRlZCBjYWNoZSB3aXRoIG5ldyBrZXlzIGZyb20gdHhDaGFuZ2VzXG4gIC8vIFRoaXMgbXVzdCBoYXBwZW4gYWZ0ZXIgc3luY0xvZyB3aGljaCBtYXkgaGF2ZSBkZWxldGVkIHNvbWUgb2YgdGhlc2Uga2V5c1xuICBmb3IgKGNvbnN0IGtleSBvZiB0eENoYW5nZXMuYWRkZWQpIHtcbiAgICAvLyBDUklUSUNBTDogQ2hlY2sgeVR4LmhhcyhrZXkpISBzeW5jTG9nIG1pZ2h0IGhhdmUganVzdCBwcnVuZWQgaXQuXG4gICAgaWYgKHlUeC5oYXMoa2V5KSAmJiAhY2FsYy5oYXNUeChrZXkpKSB7XG4gICAgICBjYWxjLmluc2VydFR4KGtleSwgeVR4KVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjYWxjLmNhbGN1bGF0ZVN0YXRlKClcbn1cbiIsImltcG9ydCAqIGFzIFkgZnJvbSBcInlqc1wiXG5pbXBvcnQgeyBDaGVja3BvaW50UmVjb3JkLCBjcmVhdGVDaGVja3BvaW50IH0gZnJvbSBcIi4vY2hlY2twb2ludHNcIlxuaW1wb3J0IHsgY3JlYXRlQ2xpZW50U3RhdGUgfSBmcm9tIFwiLi9jbGllbnRTdGF0ZVwiXG5pbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4vZXJyb3JcIlxuaW1wb3J0IHsgSlNPTk9iamVjdCB9IGZyb20gXCIuL2pzb25cIlxuXG5pbXBvcnQgeyBPcCwgVmFsaWRhdGVGbiB9IGZyb20gXCIuL29wZXJhdGlvbnNcIlxuXG5pbXBvcnQgeyBjb21wdXRlUmVjb25jaWxlT3BzIH0gZnJvbSBcIi4vcmVjb25jaWxlXCJcbmltcG9ydCB7IFNvcnRlZFR4RW50cnkgfSBmcm9tIFwiLi9Tb3J0ZWRUeEVudHJ5XCJcbmltcG9ydCB7IFR4UmVjb3JkIH0gZnJvbSBcIi4vVHhSZWNvcmRcIlxuaW1wb3J0IHsgYXBwZW5kVHgsIFR4S2V5Q2hhbmdlcywgdXBkYXRlU3RhdGUgfSBmcm9tIFwiLi90eExvZ1wiXG5pbXBvcnQgeyBUeFRpbWVzdGFtcEtleSB9IGZyb20gXCIuL3R4VGltZXN0YW1wXCJcbmltcG9ydCB7IGdlbmVyYXRlSUQgfSBmcm9tIFwiLi91dGlsc1wiXG5cbmV4cG9ydCBjb25zdCBnZXRTb3J0ZWRUeHNTeW1ib2wgPSBTeW1ib2woXCJnZXRTb3J0ZWRUeHNcIilcblxuZXhwb3J0IGludGVyZmFjZSBTdGF0ZVN5bmNMb2dPcHRpb25zPFN0YXRlIGV4dGVuZHMgSlNPTk9iamVjdD4ge1xuICAvKipcbiAgICogVGhlIFkuanMgRG9jdW1lbnQgdG8gYmluZCB0by5cbiAgICovXG4gIHlEb2M6IFkuRG9jXG5cbiAgLyoqXG4gICAqIE5hbWUgZm9yIHRoZSB0eHMgWS5NYXAuXG4gICAqIERlZmF1bHQ6IFwic3RhdGUtc3luYy1sb2ctdHhcIlxuICAgKi9cbiAgeVR4TWFwTmFtZT86IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBOYW1lIGZvciB0aGUgY2hlY2twb2ludCBZLk1hcC5cbiAgICogRGVmYXVsdDogXCJzdGF0ZS1zeW5jLWxvZy1jaGVja3BvaW50XCJcbiAgICovXG4gIHlDaGVja3BvaW50TWFwTmFtZT86IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhpcyBjbGllbnQuXG4gICAqIElmIG9taXR0ZWQsIGEgcmFuZG9tIFVVSUQgKG5hbm9pZCkgd2lsbCBiZSBnZW5lcmF0ZWQuXG4gICAqIE5PVEU6IElmIHlvdSBuZWVkIHRvIHJlc3VtZSBhIHNlc3Npb24gKGtlZXAgbG9jYWwgY2xvY2svd2F0ZXJtYXJrKSwgeW91IE1VU1QgcHJvdmlkZSBhIHN0YWJsZSBJRC5cbiAgICogTVVTVCBOT1QgY29udGFpbiBzZW1pY29sb25zLlxuICAgKi9cbiAgY2xpZW50SWQ/OiBzdHJpbmdcblxuICAvKipcbiAgICogT3JpZ2luIHRhZyBmb3IgWS5qcyB0eHMgY3JlYXRlZCBieSB0aGlzIGxpYnJhcnkuXG4gICAqL1xuICB5anNPcmlnaW4/OiB1bmtub3duXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIHZhbGlkYXRpb24gZnVuY3Rpb24uXG4gICAqIFJ1bnMgYWZ0ZXIgZWFjaCB0eCdzIG9wcyBhcmUgYXBwbGllZC5cbiAgICogSWYgaXQgcmV0dXJucyBmYWxzZSwgdGhlIHR4IGlzIHJlamVjdGVkIChzdGF0ZSByZXZlcnRzKS5cbiAgICogTVVTVCBiZSBkZXRlcm1pbmlzdGljIGFuZCBjb25zaXN0ZW50IGFjcm9zcyBhbGwgY2xpZW50cy5cbiAgICovXG4gIHZhbGlkYXRlPzogKHN0YXRlOiBTdGF0ZSkgPT4gYm9vbGVhblxuXG4gIC8qKlxuICAgKiBUaW1lc3RhbXAgcmV0ZW50aW9uIHdpbmRvdyBpbiBtaWxsaXNlY29uZHMuXG4gICAqIFR4cyBvbGRlciB0aGFuIHRoaXMgd2luZG93IGFyZSBjb25zaWRlcmVkIFwiQW5jaWVudFwiIGFuZCBwcnVuZWQuXG4gICAqXG4gICAqIERlZmF1bHQ6IEluZmluaXR5IChObyBwcnVuaW5nKS5cbiAgICogUmVjb21tZW5kZWQ6IDE0IGRheXMgKDEyMDk2MDAwMDAgbXMpLlxuICAgKi9cbiAgcmV0ZW50aW9uV2luZG93TXM6IG51bWJlciB8IHVuZGVmaW5lZFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlU3luY0xvZ0NvbnRyb2xsZXI8U3RhdGUgZXh0ZW5kcyBKU09OT2JqZWN0PiB7XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHN0YXRlLlxuICAgKi9cbiAgZ2V0U3RhdGUoKTogU3RhdGVcblxuICAvKipcbiAgICogU3Vic2NyaWJlcyB0byBzdGF0ZSBjaGFuZ2VzLlxuICAgKi9cbiAgc3Vic2NyaWJlKGNhbGxiYWNrOiAobmV3U3RhdGU6IFN0YXRlLCBnZXRBcHBsaWVkT3BzOiAoKSA9PiByZWFkb25seSBPcFtdKSA9PiB2b2lkKTogKCkgPT4gdm9pZFxuXG4gIC8qKlxuICAgKiBFbWl0cyBhIG5ldyB0eCAobGlzdCBvZiBvcGVyYXRpb25zKSB0byB0aGUgbG9nLlxuICAgKi9cbiAgZW1pdChvcHM6IE9wW10pOiB2b2lkXG5cbiAgLyoqXG4gICAqIFJlY29uY2lsZXMgdGhlIGN1cnJlbnQgc3RhdGUgd2l0aCB0aGUgdGFyZ2V0IHN0YXRlLlxuICAgKi9cbiAgcmVjb25jaWxlU3RhdGUodGFyZ2V0U3RhdGU6IFN0YXRlKTogdm9pZFxuXG4gIC8qKlxuICAgKiBNYW51YWxseSB0cmlnZ2VycyBlcG9jaCBjb21wYWN0aW9uIChDaGVja3BvaW50aW5nKS5cbiAgICovXG4gIGNvbXBhY3QoKTogdm9pZFxuXG4gIC8qKlxuICAgKiBDbGVhbnMgdXAgb2JzZXJ2ZXJzIGFuZCByZWxlYXNlcyBtZW1vcnkuXG4gICAqL1xuICBkaXNwb3NlKCk6IHZvaWRcblxuICAvLyAtLS0gT2JzZXJ2YWJpbGl0eSAmIFN0YXRzIC0tLVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IGFjdGl2ZSBlcG9jaCBudW1iZXIuXG4gICAqL1xuICBnZXRBY3RpdmVFcG9jaCgpOiBudW1iZXJcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIHR4cyBjdXJyZW50bHkgaW4gdGhlIGFjdGl2ZSBlcG9jaC5cbiAgICovXG4gIGdldEFjdGl2ZUVwb2NoVHhDb3VudCgpOiBudW1iZXJcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgd2FsbENsb2NrIHRpbWVzdGFtcCBvZiB0aGUgZmlyc3QgdHggaW4gdGhlIGFjdGl2ZSBlcG9jaC5cbiAgICovXG4gIGdldEFjdGl2ZUVwb2NoU3RhcnRUaW1lKCk6IG51bWJlciB8IHVuZGVmaW5lZFxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGxvZyBpcyBjb21wbGV0ZWx5IGVtcHR5LlxuICAgKi9cbiAgaXNMb2dFbXB0eSgpOiBib29sZWFuXG5cbiAgLyoqXG4gICAqIEludGVybmFsL1Rlc3Rpbmc6IFJldHVybnMgYWxsIHR4cyBjdXJyZW50bHkgaW4gdGhlIGxvZywgc29ydGVkLlxuICAgKi9cbiAgW2dldFNvcnRlZFR4c1N5bWJvbF0oKTogcmVhZG9ubHkgU29ydGVkVHhFbnRyeVtdXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIFN0YXRlU3luY0xvZyBjb250cm9sbGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3RhdGVTeW5jTG9nPFN0YXRlIGV4dGVuZHMgSlNPTk9iamVjdD4oXG4gIG9wdGlvbnM6IFN0YXRlU3luY0xvZ09wdGlvbnM8U3RhdGU+XG4pOiBTdGF0ZVN5bmNMb2dDb250cm9sbGVyPFN0YXRlPiB7XG4gIGNvbnN0IHtcbiAgICB5RG9jLFxuICAgIHlUeE1hcE5hbWUgPSBcInN0YXRlLXN5bmMtbG9nLXR4XCIsXG4gICAgeUNoZWNrcG9pbnRNYXBOYW1lID0gXCJzdGF0ZS1zeW5jLWxvZy1jaGVja3BvaW50XCIsXG4gICAgY2xpZW50SWQgPSBnZW5lcmF0ZUlEKCksXG4gICAgeWpzT3JpZ2luLFxuICAgIHZhbGlkYXRlLFxuICAgIHJldGVudGlvbldpbmRvd01zLFxuICB9ID0gb3B0aW9uc1xuXG4gIGlmIChjbGllbnRJZC5pbmNsdWRlcyhcIjtcIikpIHtcbiAgICBmYWlsdXJlKGBjbGllbnRJZCBNVVNUIE5PVCBjb250YWluIHNlbWljb2xvbnM6ICR7Y2xpZW50SWR9YClcbiAgfVxuXG4gIGNvbnN0IHlUeCA9IHlEb2MuZ2V0TWFwPFR4UmVjb3JkPih5VHhNYXBOYW1lKVxuICBjb25zdCB5Q2hlY2twb2ludCA9IHlEb2MuZ2V0TWFwPENoZWNrcG9pbnRSZWNvcmQ+KHlDaGVja3BvaW50TWFwTmFtZSlcblxuICAvLyBDYXN0IHZhbGlkYXRlIHRvIGJhc2ljIHR5cGUgdG8gbWF0Y2ggaW50ZXJuYWwgQ2xpZW50U3RhdGVcbiAgY29uc3QgY2xpZW50U3RhdGUgPSBjcmVhdGVDbGllbnRTdGF0ZShcbiAgICB2YWxpZGF0ZSBhcyB1bmtub3duIGFzIFZhbGlkYXRlRm48SlNPTk9iamVjdD4sXG4gICAgcmV0ZW50aW9uV2luZG93TXMgPz8gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZXG4gIClcblxuICAvLyBMaXN0ZW5lcnNcbiAgY29uc3Qgc3Vic2NyaWJlcnMgPSBuZXcgU2V0PChzdGF0ZTogU3RhdGUsIGdldEFwcGxpZWRPcHM6ICgpID0+IHJlYWRvbmx5IE9wW10pID0+IHZvaWQ+KClcblxuICBjb25zdCBub3RpZnlTdWJzY3JpYmVycyA9IChzdGF0ZTogU3RhdGUsIGdldEFwcGxpZWRPcHM6ICgpID0+IHJlYWRvbmx5IE9wW10pID0+IHtcbiAgICBmb3IgKGNvbnN0IHN1YiBvZiBzdWJzY3JpYmVycykge1xuICAgICAgc3ViKHN0YXRlLCBnZXRBcHBsaWVkT3BzKVxuICAgIH1cbiAgfVxuXG4gIC8vIEhlbHBlciB0byBleHRyYWN0IGtleSBjaGFuZ2VzIGZyb20gWU1hcEV2ZW50XG4gIGNvbnN0IGV4dHJhY3RUeENoYW5nZXMgPSAoZXZlbnQ6IFkuWU1hcEV2ZW50PFR4UmVjb3JkPik6IFR4S2V5Q2hhbmdlcyA9PiB7XG4gICAgY29uc3QgYWRkZWQ6IFR4VGltZXN0YW1wS2V5W10gPSBbXVxuICAgIGNvbnN0IGRlbGV0ZWQ6IFR4VGltZXN0YW1wS2V5W10gPSBbXVxuXG4gICAgZm9yIChjb25zdCBba2V5LCBjaGFuZ2VdIG9mIGV2ZW50LmNoYW5nZXMua2V5cykge1xuICAgICAgaWYgKGNoYW5nZS5hY3Rpb24gPT09IFwiYWRkXCIpIHtcbiAgICAgICAgYWRkZWQucHVzaChrZXkpXG4gICAgICB9IGVsc2UgaWYgKGNoYW5nZS5hY3Rpb24gPT09IFwiZGVsZXRlXCIpIHtcbiAgICAgICAgZGVsZXRlZC5wdXNoKGtleSlcbiAgICAgIH0gZWxzZSBpZiAoY2hhbmdlLmFjdGlvbiA9PT0gXCJ1cGRhdGVcIikge1xuICAgICAgICBkZWxldGVkLnB1c2goa2V5KVxuICAgICAgICBhZGRlZC5wdXNoKGtleSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBhZGRlZCwgZGVsZXRlZCB9XG4gIH1cblxuICAvLyBFbXB0eSB0eENoYW5nZXMgb2JqZWN0IGZvciBjaGVja3BvaW50IG9ic2VydmVyIChubyB0eCBrZXlzIGNoYW5nZWQpXG4gIGNvbnN0IGVtcHR5VHhDaGFuZ2VzOiBUeEtleUNoYW5nZXMgPSB7IGFkZGVkOiBbXSwgZGVsZXRlZDogW10gfVxuXG4gIC8vIFVwZGF0ZSBMb2dpYyB3aXRoIGluY3JlbWVudGFsIGNoYW5nZXNcbiAgY29uc3QgcnVuVXBkYXRlID0gKHR4Q2hhbmdlczogVHhLZXlDaGFuZ2VzIHwgdW5kZWZpbmVkKSA9PiB7XG4gICAgY29uc3QgeyBzdGF0ZSwgZ2V0QXBwbGllZE9wcyB9ID0gdXBkYXRlU3RhdGUoXG4gICAgICB5RG9jLFxuICAgICAgeVR4LFxuICAgICAgeUNoZWNrcG9pbnQsXG4gICAgICBjbGllbnRJZCxcbiAgICAgIGNsaWVudFN0YXRlLFxuICAgICAgdHhDaGFuZ2VzXG4gICAgKVxuICAgIG5vdGlmeVN1YnNjcmliZXJzKHN0YXRlIGFzIFN0YXRlLCBnZXRBcHBsaWVkT3BzKVxuICB9XG5cbiAgLy8gVHggb2JzZXJ2ZXJcbiAgY29uc3QgdHhPYnNlcnZlciA9IChldmVudDogWS5ZTWFwRXZlbnQ8VHhSZWNvcmQ+LCBfdHJhbnNhY3Rpb246IFkuVHJhbnNhY3Rpb24pID0+IHtcbiAgICBjb25zdCB0eENoYW5nZXMgPSBleHRyYWN0VHhDaGFuZ2VzKGV2ZW50KVxuICAgIHJ1blVwZGF0ZSh0eENoYW5nZXMpXG4gIH1cblxuICAvLyBDaGVja3BvaW50IG9ic2VydmVyXG4gIGNvbnN0IGNoZWNrcG9pbnRPYnNlcnZlciA9IChcbiAgICBfZXZlbnQ6IFkuWU1hcEV2ZW50PENoZWNrcG9pbnRSZWNvcmQ+LFxuICAgIF90cmFuc2FjdGlvbjogWS5UcmFuc2FjdGlvblxuICApID0+IHtcbiAgICBydW5VcGRhdGUoZW1wdHlUeENoYW5nZXMpXG4gIH1cblxuICB5Q2hlY2twb2ludC5vYnNlcnZlKGNoZWNrcG9pbnRPYnNlcnZlcilcbiAgeVR4Lm9ic2VydmUodHhPYnNlcnZlcilcblxuICAvLyBJbml0aWFsIHJ1biAoZnVsbCByZWNvbXB1dGUsIHRyZWF0IGFzIGNoZWNrcG9pbnQgY2hhbmdlIHRvIGluaXRpYWxpemUgZXBvY2ggY2FjaGUpXG4gIHJ1blVwZGF0ZSh1bmRlZmluZWQpXG5cbiAgLy8gVHJhY2sgZGlzcG9zYWwgc3RhdGVcbiAgbGV0IGRpc3Bvc2VkID0gZmFsc2VcblxuICBjb25zdCBhc3NlcnROb3REaXNwb3NlZCA9ICgpID0+IHtcbiAgICBpZiAoZGlzcG9zZWQpIHtcbiAgICAgIGZhaWx1cmUoXCJTdGF0ZVN5bmNMb2cgaGFzIGJlZW4gZGlzcG9zZWQgYW5kIGNhbm5vdCBiZSB1c2VkXCIpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgZ2V0QWN0aXZlRXBvY2hJbnRlcm5hbCA9ICgpID0+IHtcbiAgICBpZiAoY2xpZW50U3RhdGUuY2FjaGVkRmluYWxpemVkRXBvY2ggPT09IG51bGwpIHtcbiAgICAgIGZhaWx1cmUoXCJjYWNoZWRGaW5hbGl6ZWRFcG9jaCBpcyBudWxsIC0gdGhpcyBzaG91bGQgbm90IGhhcHBlbiBhZnRlciBpbml0aWFsaXphdGlvblwiKVxuICAgIH1cbiAgICByZXR1cm4gY2xpZW50U3RhdGUuY2FjaGVkRmluYWxpemVkRXBvY2ggKyAxXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdldFN0YXRlKCk6IFN0YXRlIHtcbiAgICAgIGFzc2VydE5vdERpc3Bvc2VkKClcbiAgICAgIHJldHVybiAoY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yLmdldENhY2hlZFN0YXRlKCkgPz8ge30pIGFzIFN0YXRlXG4gICAgfSxcblxuICAgIHN1YnNjcmliZShjYWxsYmFjazogKG5ld1N0YXRlOiBTdGF0ZSwgZ2V0QXBwbGllZE9wczogKCkgPT4gcmVhZG9ubHkgT3BbXSkgPT4gdm9pZCk6ICgpID0+IHZvaWQge1xuICAgICAgYXNzZXJ0Tm90RGlzcG9zZWQoKVxuICAgICAgc3Vic2NyaWJlcnMuYWRkKGNhbGxiYWNrKVxuICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgc3Vic2NyaWJlcnMuZGVsZXRlKGNhbGxiYWNrKVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBlbWl0KG9wczogT3BbXSk6IHZvaWQge1xuICAgICAgYXNzZXJ0Tm90RGlzcG9zZWQoKVxuICAgICAgeURvYy50cmFuc2FjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZUVwb2NoID0gZ2V0QWN0aXZlRXBvY2hJbnRlcm5hbCgpXG4gICAgICAgIGFwcGVuZFR4KG9wcywgeVR4LCBhY3RpdmVFcG9jaCwgY2xpZW50SWQsIGNsaWVudFN0YXRlKVxuICAgICAgfSwgeWpzT3JpZ2luKVxuICAgIH0sXG5cbiAgICByZWNvbmNpbGVTdGF0ZSh0YXJnZXRTdGF0ZTogU3RhdGUpOiB2b2lkIHtcbiAgICAgIGFzc2VydE5vdERpc3Bvc2VkKClcbiAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IChjbGllbnRTdGF0ZS5zdGF0ZUNhbGN1bGF0b3IuZ2V0Q2FjaGVkU3RhdGUoKSA/PyB7fSkgYXMgU3RhdGVcbiAgICAgIGNvbnN0IG9wcyA9IGNvbXB1dGVSZWNvbmNpbGVPcHMoY3VycmVudFN0YXRlLCB0YXJnZXRTdGF0ZSlcbiAgICAgIGlmIChvcHMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLmVtaXQob3BzKVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBjb21wYWN0KCk6IHZvaWQge1xuICAgICAgYXNzZXJ0Tm90RGlzcG9zZWQoKVxuICAgICAgeURvYy50cmFuc2FjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZUVwb2NoID0gZ2V0QWN0aXZlRXBvY2hJbnRlcm5hbCgpXG4gICAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IGNsaWVudFN0YXRlLnN0YXRlQ2FsY3VsYXRvci5nZXRDYWNoZWRTdGF0ZSgpID8/IHt9XG4gICAgICAgIGNyZWF0ZUNoZWNrcG9pbnQoeVR4LCB5Q2hlY2twb2ludCwgY2xpZW50U3RhdGUsIGFjdGl2ZUVwb2NoLCBjdXJyZW50U3RhdGUsIGNsaWVudElkKVxuICAgICAgfSwgeWpzT3JpZ2luKVxuICAgIH0sXG5cbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgaWYgKGRpc3Bvc2VkKSByZXR1cm4gLy8gQWxyZWFkeSBkaXNwb3NlZCwgbm8tb3BcbiAgICAgIGRpc3Bvc2VkID0gdHJ1ZVxuICAgICAgeVR4LnVub2JzZXJ2ZSh0eE9ic2VydmVyKVxuICAgICAgeUNoZWNrcG9pbnQudW5vYnNlcnZlKGNoZWNrcG9pbnRPYnNlcnZlcilcbiAgICAgIHN1YnNjcmliZXJzLmNsZWFyKClcbiAgICB9LFxuXG4gICAgZ2V0QWN0aXZlRXBvY2goKTogbnVtYmVyIHtcbiAgICAgIGFzc2VydE5vdERpc3Bvc2VkKClcbiAgICAgIHJldHVybiBnZXRBY3RpdmVFcG9jaEludGVybmFsKClcbiAgICB9LFxuXG4gICAgZ2V0QWN0aXZlRXBvY2hUeENvdW50KCk6IG51bWJlciB7XG4gICAgICBhc3NlcnROb3REaXNwb3NlZCgpXG4gICAgICBjb25zdCBhY3RpdmVFcG9jaCA9IGdldEFjdGl2ZUVwb2NoSW50ZXJuYWwoKVxuICAgICAgbGV0IGNvdW50ID0gMFxuICAgICAgLy8gT25seSBjdXJyZW50IG9yIGZ1dHVyZSBlcG9jaHMgZXhpc3QgaW4gc29ydGVkVHhzIChwYXN0IGVwb2NocyBhcmUgcHJ1bmVkIGR1cmluZyB1cGRhdGVTdGF0ZSkuXG4gICAgICAvLyBGdXR1cmUgZXBvY2hzIGFwcGVhciBpZiB3ZSByZWNlaXZlIHR4cyBiZWZvcmUgdGhlIGNvcnJlc3BvbmRpbmcgY2hlY2twb2ludC5cbiAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yLmdldFNvcnRlZFR4cygpKSB7XG4gICAgICAgIGNvbnN0IHRzID0gZW50cnkudHhUaW1lc3RhbXBcbiAgICAgICAgaWYgKHRzLmVwb2NoID09PSBhY3RpdmVFcG9jaCkge1xuICAgICAgICAgIGNvdW50KytcbiAgICAgICAgfSBlbHNlIGlmICh0cy5lcG9jaCA+IGFjdGl2ZUVwb2NoKSB7XG4gICAgICAgICAgYnJlYWsgLy8gT3B0aW1pemF0aW9uOiBzb3J0ZWQgb3JkZXIgbWVhbnMgd2UgY2FuIHN0b3AgZWFybHlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNvdW50XG4gICAgfSxcblxuICAgIGdldEFjdGl2ZUVwb2NoU3RhcnRUaW1lKCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgICBhc3NlcnROb3REaXNwb3NlZCgpXG4gICAgICBjb25zdCBhY3RpdmVFcG9jaCA9IGdldEFjdGl2ZUVwb2NoSW50ZXJuYWwoKVxuICAgICAgLy8gT25seSBjdXJyZW50IG9yIGZ1dHVyZSBlcG9jaHMgZXhpc3QgaW4gc29ydGVkVHhzIChwYXN0IGVwb2NocyBhcmUgcHJ1bmVkIGR1cmluZyB1cGRhdGVTdGF0ZSkuXG4gICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGNsaWVudFN0YXRlLnN0YXRlQ2FsY3VsYXRvci5nZXRTb3J0ZWRUeHMoKSkge1xuICAgICAgICBjb25zdCB0cyA9IGVudHJ5LnR4VGltZXN0YW1wXG4gICAgICAgIGlmICh0cy5lcG9jaCA9PT0gYWN0aXZlRXBvY2gpIHtcbiAgICAgICAgICByZXR1cm4gdHMud2FsbENsb2NrXG4gICAgICAgIH0gZWxzZSBpZiAodHMuZXBvY2ggPiBhY3RpdmVFcG9jaCkge1xuICAgICAgICAgIGJyZWFrIC8vIE9wdGltaXphdGlvbjogc29ydGVkIG9yZGVyIG1lYW5zIHdlIGNhbiBzdG9wIGVhcmx5XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9LFxuXG4gICAgaXNMb2dFbXB0eSgpOiBib29sZWFuIHtcbiAgICAgIGFzc2VydE5vdERpc3Bvc2VkKClcbiAgICAgIHJldHVybiB5VHguc2l6ZSA9PT0gMCAmJiB5Q2hlY2twb2ludC5zaXplID09PSAwXG4gICAgfSxcblxuICAgIFtnZXRTb3J0ZWRUeHNTeW1ib2xdKCk6IHJlYWRvbmx5IFNvcnRlZFR4RW50cnlbXSB7XG4gICAgICBhc3NlcnROb3REaXNwb3NlZCgpXG4gICAgICByZXR1cm4gY2xpZW50U3RhdGUuc3RhdGVDYWxjdWxhdG9yLmdldFNvcnRlZFR4cygpXG4gICAgfSxcbiAgfVxufVxuIiwiaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuL2Vycm9yXCJcclxuaW1wb3J0IHsgSlNPTk9iamVjdCwgSlNPTlZhbHVlLCBQYXRoIH0gZnJvbSBcIi4vanNvblwiXHJcbmltcG9ydCB7IGRlZXBDbG9uZSwgZGVlcEVxdWFsLCBpc09iamVjdCB9IGZyb20gXCIuL3V0aWxzXCJcclxuXHJcbi8qKlxyXG4gKiBTdXBwb3J0ZWQgb3BlcmF0aW9ucy5cclxuICogQXBwbGllZCBzZXF1ZW50aWFsbHkgd2l0aGluIGEgdHguXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBPcCA9XHJcbiAgfCB7IGtpbmQ6IFwic2V0XCI7IHBhdGg6IFBhdGg7IGtleTogc3RyaW5nOyB2YWx1ZTogSlNPTlZhbHVlIH1cclxuICB8IHsga2luZDogXCJkZWxldGVcIjsgcGF0aDogUGF0aDsga2V5OiBzdHJpbmcgfVxyXG4gIHwgeyBraW5kOiBcInNwbGljZVwiOyBwYXRoOiBQYXRoOyBpbmRleDogbnVtYmVyOyBkZWxldGVDb3VudDogbnVtYmVyOyBpbnNlcnRzOiBKU09OVmFsdWVbXSB9XHJcbiAgfCB7IGtpbmQ6IFwiYWRkVG9TZXRcIjsgcGF0aDogUGF0aDsgdmFsdWU6IEpTT05WYWx1ZSB9XHJcbiAgfCB7IGtpbmQ6IFwiZGVsZXRlRnJvbVNldFwiOyBwYXRoOiBQYXRoOyB2YWx1ZTogSlNPTlZhbHVlIH1cclxuXHJcbi8qKlxyXG4gKiBWYWxpZGF0aW9uIGZ1bmN0aW9uIHR5cGUuXHJcbiAqXHJcbiAqIFJ1bGVzOlxyXG4gKiAtIFZhbGlkYXRpb24gTVVTVCBkZXBlbmQgb25seSBvbiBjYW5kaWRhdGVTdGF0ZSAoYW5kIGRldGVybWluaXN0aWMgY29kZSkuXHJcbiAqIC0gVmFsaWRhdGlvbiBydW5zIG9uY2UgcGVyIHR4LCBhZnRlciBhbGwgb3BzIGFwcGx5LlxyXG4gKiAtIElmIHZhbGlkYXRpb24gZmFpbHMsIHRoZSB4IGlzIHJlamVjdGVkIChzdGF0ZSByZXZlcnRzIHRvIHByZXZpb3VzKS5cclxuICogLSBJZiBubyB2YWxpZGF0b3IgaXMgcHJvdmlkZWQsIHZhbGlkYXRpb24gZGVmYXVsdHMgdG8gdHJ1ZS5cclxuICpcclxuICogSU1QT1JUQU5UOiBWYWxpZGF0aW9uIG91dGNvbWUgaXMgKipkZXJpdmVkIGxvY2FsIHN0YXRlKiogYW5kIE1VU1QgTk9UIGJlIHJlcGxpY2F0ZWQuXHJcbiAqIEFsbCBjbGllbnRzIE1VU1QgdXNlIHRoZSBzYW1lIHZhbGlkYXRpb24gbG9naWMgdG8gZW5zdXJlIGNvbnNpc3RlbmN5LlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgVmFsaWRhdGVGbjxTdGF0ZSBleHRlbmRzIEpTT05PYmplY3Q+ID0gKGNhbmRpZGF0ZVN0YXRlOiBTdGF0ZSkgPT4gYm9vbGVhblxyXG5cclxuLyoqXHJcbiAqIFJlc29sdmVzIGEgcGF0aCB3aXRoaW4gdGhlIHN0YXRlLlxyXG4gKiBUaHJvd3MgaWYgYW55IHNlZ21lbnQgaXMgbWlzc2luZyBvciBoYXMgd3JvbmcgdHlwZS5cclxuICovXHJcbmZ1bmN0aW9uIHJlc29sdmVQYXRoKHN0YXRlOiBKU09OT2JqZWN0LCBwYXRoOiBQYXRoKTogSlNPTlZhbHVlIHtcclxuICBsZXQgY3VycmVudDogSlNPTlZhbHVlID0gc3RhdGVcclxuICBmb3IgKGNvbnN0IHNlZ21lbnQgb2YgcGF0aCkge1xyXG4gICAgaWYgKHR5cGVvZiBzZWdtZW50ID09PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgIGlmICghaXNPYmplY3QoY3VycmVudCkgfHwgQXJyYXkuaXNBcnJheShjdXJyZW50KSkge1xyXG4gICAgICAgIGZhaWx1cmUoYEV4cGVjdGVkIG9iamVjdCBhdCBwYXRoIHNlZ21lbnQgXCIke3NlZ21lbnR9XCJgKVxyXG4gICAgICB9XHJcbiAgICAgIGlmICghKHNlZ21lbnQgaW4gY3VycmVudCkpIHtcclxuICAgICAgICBmYWlsdXJlKGBQcm9wZXJ0eSBcIiR7c2VnbWVudH1cIiBkb2VzIG5vdCBleGlzdGApXHJcbiAgICAgIH1cclxuICAgICAgY3VycmVudCA9IGN1cnJlbnRbc2VnbWVudF1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShjdXJyZW50KSkge1xyXG4gICAgICAgIGZhaWx1cmUoYEV4cGVjdGVkIGFycmF5IGF0IHBhdGggc2VnbWVudCAke3NlZ21lbnR9YClcclxuICAgICAgfVxyXG4gICAgICBpZiAoc2VnbWVudCA8IDAgfHwgc2VnbWVudCA+PSBjdXJyZW50Lmxlbmd0aCkge1xyXG4gICAgICAgIGZhaWx1cmUoYEluZGV4ICR7c2VnbWVudH0gb3V0IG9mIGJvdW5kc2ApXHJcbiAgICAgIH1cclxuICAgICAgY3VycmVudCA9IGN1cnJlbnRbc2VnbWVudF1cclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIGN1cnJlbnRcclxufVxyXG5cclxuLyoqXHJcbiAqIEFwcGxpZXMgYSBzaW5nbGUgb3BlcmF0aW9uLlxyXG4gKiAoUmVmZXJlbmNlIGltcGxlbWVudGF0aW9uIGZvciBzdGFuZGFyZCBKU09OLXBhdGNoIGJlaGF2aW9yKVxyXG4gKi9cclxuZnVuY3Rpb24gYXBwbHlPcChzdGF0ZTogSlNPTk9iamVjdCwgb3A6IE9wLCBjbG9uZVZhbHVlczogYm9vbGVhbik6IHZvaWQge1xyXG4gIC8vIFNwZWNpYWwgY2FzZTogaWYgcGF0aCBpcyBlbXB0eSwgd2UgY2FuJ3QgcmVzb2x2ZSBcImNvbnRhaW5lclwiLlxyXG4gIC8vIFRoZSBjYWxsZXIgbXVzdCBoYW5kbGUgcm9vdC1sZXZlbCByZXBsYWNlbWVudCBpZiBuZWNlc3NhcnksIGJ1dFxyXG4gIC8vIHN0YW5kYXJkIE9wcyB1c3VhbGx5IGFjdCBPTiBhIGNvbnRhaW5lci5cclxuICAvLyBFeGNlcHRpb246IGlmIHdlIGFjdCBvbiByb290LCBoYW5kbGUgZXhwbGljaXRseSBvciBhc3N1bWUgcGF0aCBsZW5ndGggPiAwLlxyXG4gIC8vIEZvciB0aGlzIHNwZWMsIE9wcyBtb2RpZnkgKmZpZWxkcyogb3IgKmluZGljZXMqLlxyXG4gIC8vIElmIHBhdGggaXMgZW1wdHksIGl0IG1lYW5zIHdlIGFyZSBhY3RpbmcgT04gdGhlIHJvb3Qgb2JqZWN0IGl0c2VsZj9cclxuICAvLyBUaGUgc3BlYydzIFwic2V0XCIgZXhhbXBsZTogY29udGFpbmVyW29wLmtleV0gPSBvcC52YWx1ZS5cclxuICAvLyBUaGlzIGltcGxpZXMgd2UgcmVzb2x2ZSBwYXRoIHRvIGdldCB0aGUgUEFSRU5UIGNvbnRhaW5lci5cclxuXHJcbiAgY29uc3QgY29udGFpbmVyID0gcmVzb2x2ZVBhdGgoc3RhdGUsIG9wLnBhdGgpXHJcblxyXG4gIHN3aXRjaCAob3Aua2luZCkge1xyXG4gICAgY2FzZSBcInNldFwiOlxyXG4gICAgICBpZiAoIWlzT2JqZWN0KGNvbnRhaW5lcikgfHwgQXJyYXkuaXNBcnJheShjb250YWluZXIpKSB7XHJcbiAgICAgICAgZmFpbHVyZShcInNldCByZXF1aXJlcyBvYmplY3QgY29udGFpbmVyXCIpXHJcbiAgICAgIH1cclxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcclxuICAgICAgOyhjb250YWluZXIgYXMgYW55KVtvcC5rZXldID0gY2xvbmVWYWx1ZXMgPyBkZWVwQ2xvbmUob3AudmFsdWUpIDogb3AudmFsdWVcclxuICAgICAgYnJlYWtcclxuXHJcbiAgICBjYXNlIFwiZGVsZXRlXCI6XHJcbiAgICAgIGlmICghaXNPYmplY3QoY29udGFpbmVyKSB8fCBBcnJheS5pc0FycmF5KGNvbnRhaW5lcikpIHtcclxuICAgICAgICBmYWlsdXJlKFwiZGVsZXRlIHJlcXVpcmVzIG9iamVjdCBjb250YWluZXJcIilcclxuICAgICAgfVxyXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxyXG4gICAgICBkZWxldGUgKGNvbnRhaW5lciBhcyBhbnkpW29wLmtleV1cclxuICAgICAgYnJlYWtcclxuXHJcbiAgICBjYXNlIFwic3BsaWNlXCI6IHtcclxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbnRhaW5lcikpIHtcclxuICAgICAgICBmYWlsdXJlKFwic3BsaWNlIHJlcXVpcmVzIGFycmF5IGNvbnRhaW5lclwiKVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IHNhZmVJbmRleCA9IE1hdGgubWluKG9wLmluZGV4LCBjb250YWluZXIubGVuZ3RoKVxyXG4gICAgICBjb250YWluZXIuc3BsaWNlKFxyXG4gICAgICAgIHNhZmVJbmRleCxcclxuICAgICAgICBvcC5kZWxldGVDb3VudCxcclxuICAgICAgICAuLi4oY2xvbmVWYWx1ZXMgPyBvcC5pbnNlcnRzLm1hcCgodikgPT4gZGVlcENsb25lKHYpKSA6IG9wLmluc2VydHMpXHJcbiAgICAgIClcclxuICAgICAgYnJlYWtcclxuICAgIH1cclxuXHJcbiAgICBjYXNlIFwiYWRkVG9TZXRcIjpcclxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbnRhaW5lcikpIHtcclxuICAgICAgICBmYWlsdXJlKFwiYWRkVG9TZXQgcmVxdWlyZXMgYXJyYXkgY29udGFpbmVyXCIpXHJcbiAgICAgIH1cclxuICAgICAgaWYgKCFjb250YWluZXIuc29tZSgoaXRlbSkgPT4gZGVlcEVxdWFsKGl0ZW0sIG9wLnZhbHVlKSkpIHtcclxuICAgICAgICBjb250YWluZXIucHVzaChjbG9uZVZhbHVlcyA/IGRlZXBDbG9uZShvcC52YWx1ZSkgOiBvcC52YWx1ZSlcclxuICAgICAgfVxyXG4gICAgICBicmVha1xyXG5cclxuICAgIGNhc2UgXCJkZWxldGVGcm9tU2V0XCI6XHJcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb250YWluZXIpKSB7XHJcbiAgICAgICAgZmFpbHVyZShcImRlbGV0ZUZyb21TZXQgcmVxdWlyZXMgYXJyYXkgY29udGFpbmVyXCIpXHJcbiAgICAgIH1cclxuICAgICAgLy8gUmVtb3ZlIGFsbCBtYXRjaGluZyBpdGVtcyB1c2luZyBzcGxpY2UgKGZyb20gZW5kIHRvIGF2b2lkIGluZGV4IHNoaWZ0aW5nKVxyXG4gICAgICBmb3IgKGxldCBpID0gY29udGFpbmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgaWYgKGRlZXBFcXVhbChjb250YWluZXJbaV0sIG9wLnZhbHVlKSkge1xyXG4gICAgICAgICAgY29udGFpbmVyLnNwbGljZShpLCAxKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBicmVha1xyXG5cclxuICAgIGRlZmF1bHQ6XHJcbiAgICAgIHRocm93IGZhaWx1cmUoYFVua25vd24gb3BlcmF0aW9uIGtpbmQ6ICR7KG9wIGFzIGFueSkua2luZH1gKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE9wdGlvbnMgZm9yIGFwcGx5T3BzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBBcHBseU9wc09wdGlvbnMge1xyXG4gIC8qKlxyXG4gICAqIFdoZXRoZXIgdG8gZGVlcCBjbG9uZSB2YWx1ZXMgYmVmb3JlIGluc2VydGluZyB0aGVtIGludG8gdGhlIHRhcmdldC5cclxuICAgKiAtIGB0cnVlYCAoZGVmYXVsdCk6IFZhbHVlcyBhcmUgY2xvbmVkIHRvIHByZXZlbnQgYWxpYXNpbmcgYmV0d2VlbiB0aGUgb3BzIGFuZCB0YXJnZXQuXHJcbiAgICogLSBgZmFsc2VgOiBWYWx1ZXMgYXJlIHVzZWQgZGlyZWN0bHkgZm9yIGJldHRlciBwZXJmb3JtYW5jZS4gT25seSB1c2UgdGhpcyBpZiB5b3VcclxuICAgKiAgIGd1YXJhbnRlZSB0aGUgb3AgdmFsdWVzIHdvbid0IGJlIG11dGF0ZWQgYWZ0ZXIgYXBwbGljYXRpb24uXHJcbiAgICovXHJcbiAgY2xvbmVWYWx1ZXM/OiBib29sZWFuXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBcHBsaWVzIGEgbGlzdCBvZiBvcGVyYXRpb25zIHRvIGEgbXV0YWJsZSB0YXJnZXQgb2JqZWN0LlxyXG4gKiBVc2UgdGhpcyB0byBzeW5jaHJvbml6ZSBhbiBleHRlcm5hbCBtdXRhYmxlIHN0YXRlIChlLmcuLCBNb2JYIHN0b3JlKVxyXG4gKiB3aXRoIHRoZSBvcGVyYXRpb25zIHJlY2VpdmVkIHZpYSBzdWJzY3JpYmUoKS5cclxuICpcclxuICogQHBhcmFtIG9wcyAtIFRoZSBsaXN0IG9mIG9wZXJhdGlvbnMgdG8gYXBwbHkuXHJcbiAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgbXV0YWJsZSBvYmplY3QgdG8gbW9kaWZ5LlxyXG4gKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbmFsIHNldHRpbmdzIGZvciBjb250cm9sbGluZyBjbG9uaW5nIGJlaGF2aW9yLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5T3BzKG9wczogcmVhZG9ubHkgT3BbXSwgdGFyZ2V0OiBKU09OT2JqZWN0LCBvcHRpb25zPzogQXBwbHlPcHNPcHRpb25zKTogdm9pZCB7XHJcbiAgY29uc3QgY2xvbmVWYWx1ZXMgPSBvcHRpb25zPy5jbG9uZVZhbHVlcyA/PyB0cnVlXHJcbiAgZm9yIChjb25zdCBvcCBvZiBvcHMpIHtcclxuICAgIGFwcGx5T3AodGFyZ2V0LCBvcCwgY2xvbmVWYWx1ZXMpXHJcbiAgfVxyXG59XHJcbiJdLCJuYW1lcyI6WyJlcXVhbCIsInNjb3BlZFVybEFscGhhYmV0IiwicmZkYyIsImhhbmRsZXIiLCJjbG9uZSJdLCJtYXBwaW5ncyI6Ijs7O0FBWU8sU0FBUywrQkFBK0IsYUFHN0M7QUFDQSxNQUFJLFdBQVc7QUFDZixNQUFJLE9BQWdDO0FBQ3BDLE1BQUksY0FBYztBQUNsQixNQUFJLGVBQWU7QUFFbkIsYUFBVyxDQUFDLEtBQUssRUFBRSxLQUFLLFlBQVksV0FBVztBQUM3QyxVQUFNLEVBQUUsT0FBTyxhQUFhLG1CQUFtQixHQUFHO0FBRWxELFFBQUksUUFBUSxVQUFVO0FBRXBCLGlCQUFXO0FBQ1gsYUFBTztBQUNQLG9CQUFjLEdBQUc7QUFDakIscUJBQWU7QUFBQSxJQUNqQixXQUFXLFVBQVUsVUFBVTtBQUk3QixVQUFJLEdBQUcsVUFBVSxlQUFnQixHQUFHLFlBQVksZUFBZSxXQUFXLGNBQWU7QUFDdkYsZUFBTztBQUNQLHNCQUFjLEdBQUc7QUFDakIsdUJBQWU7QUFBQSxNQUNqQjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBRUEsU0FBTyxFQUFFLGdCQUFnQixVQUFVLFlBQVksS0FBQTtBQUNqRDtBQzNDTyxNQUFNLDBCQUEwQixNQUFNO0FBQUEsRUFDM0MsWUFBWSxLQUFhO0FBQ3ZCLFVBQU0sR0FBRztBQUdULFdBQU8sZUFBZSxNQUFNLGtCQUFrQixTQUFTO0FBQUEsRUFDekQ7QUFDRjtBQUVPLFNBQVMsUUFBUSxTQUF3QjtBQUM5QyxRQUFNLElBQUksa0JBQWtCLE9BQU87QUFDckM7QUN5Q0EsU0FBUyx1QkFBdUIsTUFBd0M7QUFDdEUsU0FBTyxHQUFHLEtBQUssS0FBSyxJQUFJLEtBQUssT0FBTyxJQUFJLEtBQUssUUFB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