cdk-nextjs 0.7.6 → 0.7.8

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 (65) hide show
  1. package/.jsii +3 -3
  2. package/.jsii.tabl.json +1 -1
  3. package/README.md +12 -3
  4. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +31 -13
  5. package/docs/adapter-runtime.md +1 -1
  6. package/docs/caching-guide.md +11 -1
  7. package/docs/harness-coverage.md +154 -73
  8. package/lib/adapter/adapter.mjs +12 -3
  9. package/lib/adapter/aws-cache-store.d.ts +221 -3
  10. package/lib/adapter/aws-cache-store.js +481 -35
  11. package/lib/adapter/aws-cache-store.test.js +706 -3
  12. package/lib/adapter/cache-handler.d.ts +5 -3
  13. package/lib/adapter/cache-handler.js +16 -10
  14. package/lib/adapter/cache-handler.mjs +517 -49
  15. package/lib/adapter/cache-handler.test.js +44 -1
  16. package/lib/adapter/cache-utils.d.ts +22 -0
  17. package/lib/adapter/cache-utils.js +44 -1
  18. package/lib/adapter/function-groups.js +17 -4
  19. package/lib/adapter/function-groups.test.js +33 -1
  20. package/lib/adapter/memory-cache-handler.d.ts +5 -1
  21. package/lib/adapter/memory-cache-handler.js +6 -2
  22. package/lib/adapter/s3-cache-handler.d.ts +12 -1
  23. package/lib/adapter/s3-cache-handler.js +30 -8
  24. package/lib/adapter/s3-cache-handler.test.js +84 -2
  25. package/lib/adapter/use-cache-common.d.ts +66 -1
  26. package/lib/adapter/use-cache-common.js +142 -19
  27. package/lib/adapter/use-cache-common.test.js +174 -1
  28. package/lib/adapter/use-cache-default-handler.js +36 -6
  29. package/lib/adapter/use-cache-default-handler.mjs +553 -47
  30. package/lib/adapter/use-cache-handlers.test.js +247 -7
  31. package/lib/adapter/use-cache-remote-handler.js +9 -7
  32. package/lib/adapter/use-cache-remote-handler.mjs +542 -45
  33. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +2 -1
  34. package/lib/lambdas/post-deploy/prune-revalidation-table.js +35 -13
  35. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +19 -1
  36. package/lib/nextjs-api.js +1 -1
  37. package/lib/nextjs-build/nextjs-build.js +1 -1
  38. package/lib/nextjs-cache.js +1 -1
  39. package/lib/nextjs-compute/nextjs-containers.js +1 -1
  40. package/lib/nextjs-compute/nextjs-functions.js +1 -1
  41. package/lib/nextjs-distribution.js +1 -1
  42. package/lib/nextjs-post-deploy.js +1 -1
  43. package/lib/nextjs-static-assets.js +1 -1
  44. package/lib/root-constructs/nextjs-base-construct.js +1 -1
  45. package/lib/root-constructs/nextjs-global-containers.js +1 -1
  46. package/lib/root-constructs/nextjs-global-functions.js +1 -1
  47. package/lib/root-constructs/nextjs-regional-containers.js +1 -1
  48. package/lib/root-constructs/nextjs-regional-functions.js +1 -1
  49. package/lib/runtime/core.js +20 -4
  50. package/lib/runtime/core.test.js +17 -1
  51. package/lib/runtime/image-utils.d.ts +8 -9
  52. package/lib/runtime/image-utils.js +16 -1
  53. package/lib/runtime/image-utils.test.js +13 -1
  54. package/lib/runtime/image.js +9 -3
  55. package/lib/runtime/lambda.mjs +66 -18
  56. package/lib/runtime/server.mjs +66 -18
  57. package/lib/runtime/tag-manifest.d.ts +40 -0
  58. package/lib/runtime/tag-manifest.js +59 -0
  59. package/lib/runtime/tag-manifest.test.d.ts +1 -0
  60. package/lib/runtime/tag-manifest.test.js +47 -0
  61. package/package.json +3 -3
  62. package/scripts/e2e-deploy.sh +7 -2
  63. package/scripts/e2e-harness/README.md +72 -35
  64. package/scripts/e2e-harness/screen.mjs +148 -7
  65. package/scripts/playwright-install-deps.sh +40 -0
@@ -57,23 +57,88 @@ export declare class EntryLru {
57
57
  private readonly maxBytes;
58
58
  private readonly entries;
59
59
  private bytes;
60
+ /**
61
+ * No later than the oldest entry's `timestamp`: the last scan's answer, less
62
+ * whatever was set since. Entries dropped since only make it early. See
63
+ * {@link oldestBound}.
64
+ */
65
+ private lowest;
60
66
  constructor(maxBytes: number);
61
67
  get(key: string): StoredEntry | undefined;
62
68
  set(key: string, entry: StoredEntry): void;
63
69
  delete(key: string): void;
70
+ /**
71
+ * The `timestamp` of the oldest entry held, `Infinity` with none, dropping
72
+ * on the way the entries past `revalidate` at `at` (`now()`): a handler
73
+ * that drops them when next read would otherwise hold them until then, and
74
+ * they would count here meanwhile. A scan, so asked once in a while: in
75
+ * between, {@link oldestBound} answers.
76
+ */
77
+ oldestTimestamp(at?: number): number;
78
+ /**
79
+ * No later than {@link oldestTimestamp}, without its scan: as of the last
80
+ * one, less the entries set since. `Infinity` with none held. Drops the
81
+ * entries past `revalidate` at `at` from the least recently used end, up to
82
+ * the first that isn't, so {@link holdsLive} doesn't walk past them on every
83
+ * request until the next scan.
84
+ */
85
+ oldestBound(at?: number): number;
86
+ /**
87
+ * Whether an entry not past `revalidate` at `at` is held. Usually the first
88
+ * entry answers; the expired ones it passes are dropped by the scan
89
+ * {@link oldestTimestamp} makes, not here, so asking changes nothing.
90
+ */
91
+ holdsLive(at: number): boolean;
64
92
  get size(): number;
65
93
  }
94
+ /** Whether `stored` is past `revalidate` at `at` (`now()`). */
95
+ export declare function isPastRevalidate(stored: StoredEntry, at: number): boolean;
66
96
  /** Default size of each handler's memory store: Next.js's default, 50 MB. */
67
97
  export declare const DEFAULT_MEMORY_BYTES: number;
98
+ /**
99
+ * How long one revalidation table request may take, per attempt. The SDK sets
100
+ * no limit, and a refresh left in flight across a Lambda freeze can sit on a
101
+ * connection that died meanwhile without a reset: every request that waits
102
+ * for the refresh (an instance `behind`, ISR) would wait with it. The SDK
103
+ * retries a timed-out attempt, so a dead connection costs up to its attempts
104
+ * times this.
105
+ */
106
+ export declare const TAG_TABLE_REQUEST_TIMEOUT_MS = 3000;
107
+ /**
108
+ * Wait for `work` if `wait`, or else let it run on: either way a rejection is
109
+ * logged with `failure` rather than thrown.
110
+ */
111
+ export declare function awaitIf(wait: boolean, work: Promise<void>, failure: string): Promise<void>;
112
+ export interface TagMethodsOptions {
113
+ /**
114
+ * Whether `refreshTags` always waits for the revalidation log query, rather
115
+ * than only when the instance is `behind`.
116
+ * @default false
117
+ */
118
+ readonly blocking?: boolean;
119
+ }
68
120
  /**
69
121
  * The `cacheHandlers` methods that only go through `tags`, the same for the
70
122
  * `default` and `remote` handlers.
71
123
  */
72
- export declare function tagMethods(tags: TrackedTagMarkers): Pick<CacheHandler, "refreshTags" | "getExpiration" | "updateTags">;
124
+ export declare function tagMethods(tags: TrackedTagMarkers, options?: TagMethodsOptions): Pick<CacheHandler, "refreshTags" | "updateTags">;
125
+ /**
126
+ * Run a cache handler method's work outside the request that called it
127
+ * ({@link TrackedTagMarkers.outsideRender}). Next.js awaits these methods
128
+ * inside a staged render, and 16.4 ends the render's static stage on any
129
+ * `Date.now()`, `new Date()`, `Math.random()` or `crypto` random call made in
130
+ * the request's context during it: ours, the AWS SDK's (request signing,
131
+ * invocation ids) and `debug`'s alike. A draft mode page, rendered whole at
132
+ * request time, lost its static stage that way to `refreshTags`, so the client
133
+ * cached nothing from its HTML. Creating the manifest is in here too: the
134
+ * first handler call of a process does it, inside a render.
135
+ */
136
+ export declare function outsideRender<T>(fn: () => T): T;
73
137
  /**
74
138
  * A handler built by `create` on first use rather than on import, so loading
75
139
  * the module - which jest, and Next.js's config validation, do without using
76
140
  * it - neither constructs AWS clients nor warns about missing configuration.
141
+ * Every method runs {@link outsideRender}.
77
142
  */
78
143
  export declare function lazyHandler(create: () => CacheHandler): CacheHandler;
79
144
  /**
@@ -3,14 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_MEMORY_BYTES = exports.EntryLru = exports.PendingSets = exports.now = void 0;
6
+ exports.TAG_TABLE_REQUEST_TIMEOUT_MS = exports.DEFAULT_MEMORY_BYTES = exports.EntryLru = exports.PendingSets = exports.now = void 0;
7
7
  exports.isBuildPhase = isBuildPhase;
8
8
  exports.numberFromEnv = numberFromEnv;
9
9
  exports.readStream = readStream;
10
10
  exports.storedEntryOf = storedEntryOf;
11
11
  exports.cacheEntryOf = cacheEntryOf;
12
12
  exports.isDynamicEntry = isDynamicEntry;
13
+ exports.isPastRevalidate = isPastRevalidate;
14
+ exports.awaitIf = awaitIf;
13
15
  exports.tagMethods = tagMethods;
16
+ exports.outsideRender = outsideRender;
14
17
  exports.lazyHandler = lazyHandler;
15
18
  exports.sharedTagManifest = sharedTagManifest;
16
19
  /*
@@ -24,6 +27,7 @@ exports.sharedTagManifest = sharedTagManifest;
24
27
  const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
25
28
  const debug_1 = __importDefault(require("debug"));
26
29
  const aws_cache_store_1 = require("./aws-cache-store");
30
+ const tag_manifest_1 = require("../runtime/tag-manifest");
27
31
  var aws_cache_store_2 = require("./aws-cache-store");
28
32
  Object.defineProperty(exports, "now", { enumerable: true, get: function () { return aws_cache_store_2.markerClock; } });
29
33
  /** Whether this process is `next build` rather than a deployed server. */
@@ -133,6 +137,12 @@ class EntryLru {
133
137
  maxBytes;
134
138
  entries = new Map();
135
139
  bytes = 0;
140
+ /**
141
+ * No later than the oldest entry's `timestamp`: the last scan's answer, less
142
+ * whatever was set since. Entries dropped since only make it early. See
143
+ * {@link oldestBound}.
144
+ */
145
+ lowest = Infinity;
136
146
  constructor(maxBytes) {
137
147
  this.maxBytes = maxBytes;
138
148
  }
@@ -153,6 +163,7 @@ class EntryLru {
153
163
  }
154
164
  this.entries.set(key, entry);
155
165
  this.bytes += size;
166
+ this.lowest = Math.min(this.lowest, entry.timestamp);
156
167
  for (const [oldestKey, oldest] of this.entries) {
157
168
  if (this.bytes <= this.maxBytes) {
158
169
  break;
@@ -166,7 +177,59 @@ class EntryLru {
166
177
  if (existing) {
167
178
  this.entries.delete(key);
168
179
  this.bytes -= sizeOf(key, existing);
180
+ if (this.entries.size === 0) {
181
+ this.lowest = Infinity;
182
+ }
183
+ }
184
+ }
185
+ /**
186
+ * The `timestamp` of the oldest entry held, `Infinity` with none, dropping
187
+ * on the way the entries past `revalidate` at `at` (`now()`): a handler
188
+ * that drops them when next read would otherwise hold them until then, and
189
+ * they would count here meanwhile. A scan, so asked once in a while: in
190
+ * between, {@link oldestBound} answers.
191
+ */
192
+ oldestTimestamp(at = -Infinity) {
193
+ let oldest = Infinity;
194
+ for (const [key, entry] of this.entries) {
195
+ if (isPastRevalidate(entry, at)) {
196
+ this.delete(key);
197
+ }
198
+ else {
199
+ oldest = Math.min(oldest, entry.timestamp);
200
+ }
201
+ }
202
+ this.lowest = oldest;
203
+ return oldest;
204
+ }
205
+ /**
206
+ * No later than {@link oldestTimestamp}, without its scan: as of the last
207
+ * one, less the entries set since. `Infinity` with none held. Drops the
208
+ * entries past `revalidate` at `at` from the least recently used end, up to
209
+ * the first that isn't, so {@link holdsLive} doesn't walk past them on every
210
+ * request until the next scan.
211
+ */
212
+ oldestBound(at = -Infinity) {
213
+ for (const [key, entry] of this.entries) {
214
+ if (!isPastRevalidate(entry, at)) {
215
+ break;
216
+ }
217
+ this.delete(key);
218
+ }
219
+ return this.entries.size === 0 ? Infinity : this.lowest;
220
+ }
221
+ /**
222
+ * Whether an entry not past `revalidate` at `at` is held. Usually the first
223
+ * entry answers; the expired ones it passes are dropped by the scan
224
+ * {@link oldestTimestamp} makes, not here, so asking changes nothing.
225
+ */
226
+ holdsLive(at) {
227
+ for (const entry of this.entries.values()) {
228
+ if (!isPastRevalidate(entry, at)) {
229
+ return true;
230
+ }
169
231
  }
232
+ return false;
170
233
  }
171
234
  get size() {
172
235
  return this.entries.size;
@@ -176,41 +239,89 @@ exports.EntryLru = EntryLru;
176
239
  function sizeOf(key, entry) {
177
240
  return entry.value.byteLength + key.length;
178
241
  }
242
+ /** Whether `stored` is past `revalidate` at `at` (`now()`). */
243
+ function isPastRevalidate(stored, at) {
244
+ return at > stored.timestamp + stored.revalidate * 1000;
245
+ }
179
246
  /** Default size of each handler's memory store: Next.js's default, 50 MB. */
180
247
  exports.DEFAULT_MEMORY_BYTES = 50 * 1024 * 1024;
248
+ /**
249
+ * How long one revalidation table request may take, per attempt. The SDK sets
250
+ * no limit, and a refresh left in flight across a Lambda freeze can sit on a
251
+ * connection that died meanwhile without a reset: every request that waits
252
+ * for the refresh (an instance `behind`, ISR) would wait with it. The SDK
253
+ * retries a timed-out attempt, so a dead connection costs up to its attempts
254
+ * times this.
255
+ */
256
+ exports.TAG_TABLE_REQUEST_TIMEOUT_MS = 3000;
257
+ /**
258
+ * Wait for `work` if `wait`, or else let it run on: either way a rejection is
259
+ * logged with `failure` rather than thrown.
260
+ */
261
+ async function awaitIf(wait, work, failure) {
262
+ const logged = work.catch((error) => {
263
+ console.error(failure, error);
264
+ });
265
+ if (wait) {
266
+ await logged;
267
+ }
268
+ }
181
269
  /**
182
270
  * The `cacheHandlers` methods that only go through `tags`, the same for the
183
271
  * `default` and `remote` handlers.
184
272
  */
185
- function tagMethods(tags) {
273
+ function tagMethods(tags, options = {}) {
186
274
  return {
187
- refreshTags: () => tags.refresh(),
188
- async getExpiration(implicitTags) {
189
- await tags.ensure(implicitTags);
190
- return tags.expiration(implicitTags);
191
- },
275
+ // Started, not awaited, while the instance keeps up, unless `blocking`.
276
+ // Next.js awaits `refreshTags` inside the first `'use cache'` lookup of a
277
+ // request (`use-cache-wrapper`), and a staged render ends its static stage
278
+ // on a timer: a log `Query` there pushed the entry out of the static
279
+ // stage, so a cached navigation stored the page segment without it. What
280
+ // the query finds applies from the next request. Awaited once the instance
281
+ // is `behind`, which the runtime settles before a page render starts
282
+ // (`catchUp`): the first request after an idle or frozen spell would
283
+ // otherwise serve whatever was revalidated elsewhere meanwhile. A page's
284
+ // render just after `catchUp` gets a grace more (`behindInRender`), so a
285
+ // request that came in just short of the line doesn't cross it inside
286
+ // the render. Not even then while the instance holds no entry the query
287
+ // could expire (`holdsEntries`), with a `refreshIntervalMs` of `0` too.
288
+ refreshTags: () => awaitIf(options.blocking === true || (tags.behindInRender && tags.holdsEntries), tags.refresh(), "Error refreshing cache tags:"),
192
289
  async updateTags(revalidatedTags, durations) {
193
290
  await tags.update(revalidatedTags, durations);
194
291
  },
195
292
  };
196
293
  }
294
+ /**
295
+ * Run a cache handler method's work outside the request that called it
296
+ * ({@link TrackedTagMarkers.outsideRender}). Next.js awaits these methods
297
+ * inside a staged render, and 16.4 ends the render's static stage on any
298
+ * `Date.now()`, `new Date()`, `Math.random()` or `crypto` random call made in
299
+ * the request's context during it: ours, the AWS SDK's (request signing,
300
+ * invocation ids) and `debug`'s alike. A draft mode page, rendered whole at
301
+ * request time, lost its static stage that way to `refreshTags`, so the client
302
+ * cached nothing from its HTML. Creating the manifest is in here too: the
303
+ * first handler call of a process does it, inside a render.
304
+ */
305
+ function outsideRender(fn) {
306
+ return (0, tag_manifest_1.outsideRequest)(sharedTagManifest).outsideRender(fn);
307
+ }
197
308
  /**
198
309
  * A handler built by `create` on first use rather than on import, so loading
199
310
  * the module - which jest, and Next.js's config validation, do without using
200
311
  * it - neither constructs AWS clients nor warns about missing configuration.
312
+ * Every method runs {@link outsideRender}.
201
313
  */
202
314
  function lazyHandler(create) {
203
315
  let handler;
204
316
  const instance = () => (handler ??= create());
205
317
  return {
206
- get: (cacheKey, softTags) => instance().get(cacheKey, softTags),
207
- set: (cacheKey, pendingEntry) => instance().set(cacheKey, pendingEntry),
208
- refreshTags: () => instance().refreshTags(),
209
- getExpiration: (tags) => instance().getExpiration(tags),
210
- updateTags: (tags, durations) => instance().updateTags(tags, durations),
318
+ get: (cacheKey, softTags) => outsideRender(() => instance().get(cacheKey, softTags)),
319
+ set: (cacheKey, pendingEntry) => outsideRender(() => instance().set(cacheKey, pendingEntry)),
320
+ refreshTags: () => outsideRender(() => instance().refreshTags()),
321
+ getExpiration: (tags) => outsideRender(() => instance().getExpiration(tags)),
322
+ updateTags: (tags, durations) => outsideRender(() => instance().updateTags(tags, durations)),
211
323
  };
212
324
  }
213
- const TAG_MANIFEST_SYMBOL = Symbol.for("cdk-nextjs.use-cache.tag-manifest");
214
325
  /**
215
326
  * The process's one {@link TrackedTagMarkers}, from the environment.
216
327
  *
@@ -224,27 +335,39 @@ const TAG_MANIFEST_SYMBOL = Symbol.for("cdk-nextjs.use-cache.tag-manifest");
224
335
  */
225
336
  function sharedTagManifest() {
226
337
  const global = globalThis;
227
- if (!global[TAG_MANIFEST_SYMBOL]) {
338
+ if (!global[tag_manifest_1.TAG_MANIFEST_SYMBOL]) {
228
339
  const config = (0, aws_cache_store_1.resolveAwsCacheConfig)();
229
340
  const refreshIntervalMs = numberFromEnv("CDK_NEXTJS_TAG_REFRESH_MS", aws_cache_store_1.DEFAULT_TAG_REFRESH_MS);
230
341
  if (config.tableName && !isBuildPhase()) {
231
- const client = new client_dynamodb_1.DynamoDBClient({ region: config.region });
232
- global[TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
342
+ const client = new client_dynamodb_1.DynamoDBClient({
343
+ region: config.region,
344
+ // Without `throwOnRequestTimeout` the timeout only logs a warning. It
345
+ // ends once the response headers arrive: `socketTimeout`, an
346
+ // inactivity timer kept until the request closes, covers the body.
347
+ requestHandler: {
348
+ requestTimeout: exports.TAG_TABLE_REQUEST_TIMEOUT_MS,
349
+ throwOnRequestTimeout: true,
350
+ socketTimeout: exports.TAG_TABLE_REQUEST_TIMEOUT_MS,
351
+ },
352
+ });
353
+ global[tag_manifest_1.TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
233
354
  markers: new aws_cache_store_1.TagMarkerTable(client, config.tableName, config.buildId),
234
355
  log: new aws_cache_store_1.RevalidationLog(client, config.tableName, config.buildId),
235
356
  refreshIntervalMs,
236
357
  debug: (0, debug_1.default)("cdk-nextjs:cache-handler:tags"),
358
+ // Set in every Lambda runtime; a container is never frozen.
359
+ canFreeze: process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined,
237
360
  });
238
361
  }
239
362
  else {
240
363
  if (!isBuildPhase()) {
241
364
  console.warn("CDK_NEXTJS_REVALIDATION_TABLE_NAME environment variable not set, cache tags are local to each instance");
242
365
  }
243
- global[TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
366
+ global[tag_manifest_1.TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
244
367
  refreshIntervalMs,
245
368
  });
246
369
  }
247
370
  }
248
- return global[TAG_MANIFEST_SYMBOL];
371
+ return global[tag_manifest_1.TAG_MANIFEST_SYMBOL];
249
372
  }
250
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlLWNhY2hlLWNvbW1vbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL3VzZS1jYWNoZS1jb21tb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBeUJBLG9DQUVDO0FBR0Qsc0NBSUM7QUFrQkQsZ0NBcUJDO0FBR0Qsc0NBS0M7QUFHRCxvQ0FnQkM7QUFPRCx3Q0FFQztBQWtHRCxnQ0FhQztBQU9ELGtDQVVDO0FBZUQsOENBNEJDO0FBeFJEOzs7Ozs7RUFNRTtBQUNGLHNEQUFzRDtBQUN0RCw4REFBMEQ7QUFDMUQsa0RBQTZCO0FBSzdCLHVEQU0yQjtBQUUzQixxREFBdUQ7QUFBOUMsc0dBQUEsV0FBVyxPQUFPO0FBRTNCLDBFQUEwRTtBQUMxRSxTQUFnQixZQUFZO0lBQzFCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEtBQUssd0JBQXdCLENBQUM7QUFDN0QsQ0FBQztBQUVELDhEQUE4RDtBQUM5RCxTQUFnQixhQUFhLENBQUMsSUFBWSxFQUFFLFFBQWdCO0lBQzFELE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUIsTUFBTSxLQUFLLEdBQUcsR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsRSxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7QUFDakUsQ0FBQztBQVVEOzs7Ozs7O0dBT0c7QUFDSSxLQUFLLFVBQVUsVUFBVSxDQUM5QixNQUFrQztJQUVsQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbEMsTUFBTSxNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUNoQyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFDYixTQUFTLENBQUM7UUFDUixNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzVDLElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxNQUFNO1FBQ1IsQ0FBQztRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkIsSUFBSSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUM7SUFDM0IsQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNmLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7UUFDM0IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELDJFQUEyRTtBQUNwRSxLQUFLLFVBQVUsYUFBYSxDQUNqQyxZQUFpQztJQUVqQyxNQUFNLEtBQUssR0FBRyxNQUFNLFlBQVksQ0FBQztJQUNqQyxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO0FBQzVELENBQUM7QUFFRCx5RUFBeUU7QUFDekUsU0FBZ0IsWUFBWSxDQUMxQixNQUFtQixFQUNuQixhQUFxQixNQUFNLENBQUMsVUFBVTtJQUV0QyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDO0lBQzNCLE9BQU87UUFDTCxHQUFHLE1BQU07UUFDVCxVQUFVO1FBQ1YsS0FBSyxFQUFFLElBQUksY0FBYyxDQUFhO1lBQ3BDLEtBQUssQ0FBQyxVQUFVO2dCQUNkLHFFQUFxRTtnQkFDckUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDbEMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JCLENBQUM7U0FDRixDQUFDO0tBQ0gsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLEtBQWlDO0lBQzlELE9BQU8sS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBYSxXQUFXO0lBQ0wsT0FBTyxHQUFHLElBQUksR0FBRyxFQUF5QixDQUFDO0lBRTVELHFEQUFxRDtJQUNyRCxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQVc7UUFDcEIsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDakUsTUFBTSxDQUFDLENBQUM7UUFDVixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxHQUFXO1FBQ2YsSUFBSSxPQUFPLEdBQWUsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMvQixPQUFPLEdBQUcsRUFBRTtZQUNWLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssT0FBTyxFQUFFLENBQUM7Z0JBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzNCLENBQUM7WUFDRCxPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQXpCRCxrQ0F5QkM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQWEsUUFBUTtJQUlVO0lBSFosT0FBTyxHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO0lBQ2xELEtBQUssR0FBRyxDQUFDLENBQUM7SUFFbEIsWUFBNkIsUUFBZ0I7UUFBaEIsYUFBUSxHQUFSLFFBQVEsQ0FBUTtJQUFHLENBQUM7SUFFakQsR0FBRyxDQUFDLEdBQVc7UUFDYixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwQyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsNkNBQTZDO1lBQzdDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUMvQixDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsR0FBRyxDQUFDLEdBQVcsRUFBRSxLQUFrQjtRQUNqQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDaEMsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3pCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDO1FBQ25CLEtBQUssTUFBTSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDL0MsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDaEMsTUFBTTtZQUNSLENBQUM7WUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLENBQUMsR0FBVztRQUNoQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekIsSUFBSSxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztJQUMzQixDQUFDO0NBQ0Y7QUE1Q0QsNEJBNENDO0FBRUQsU0FBUyxNQUFNLENBQUMsR0FBVyxFQUFFLEtBQWtCO0lBQzdDLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztBQUM3QyxDQUFDO0FBRUQsNkVBQTZFO0FBQ2hFLFFBQUEsb0JBQW9CLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFckQ7OztHQUdHO0FBQ0gsU0FBZ0IsVUFBVSxDQUN4QixJQUF1QjtJQUV2QixPQUFPO1FBQ0wsV0FBVyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7UUFDakMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxZQUFZO1lBQzlCLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNoQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdkMsQ0FBQztRQUNELEtBQUssQ0FBQyxVQUFVLENBQUMsZUFBZSxFQUFFLFNBQVM7WUFDekMsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNoRCxDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLE1BQTBCO0lBQ3BELElBQUksT0FBaUMsQ0FBQztJQUN0QyxNQUFNLFFBQVEsR0FBRyxHQUFHLEVBQUUsQ0FBQyxDQUFDLE9BQU8sS0FBSyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLE9BQU87UUFDTCxHQUFHLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQztRQUMvRCxHQUFHLEVBQUUsQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQztRQUN2RSxXQUFXLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsV0FBVyxFQUFFO1FBQzNDLGFBQWEsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQztRQUN2RCxVQUFVLEVBQUUsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQztLQUN4RSxDQUFDO0FBQ0osQ0FBQztBQUVELE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO0FBRTVFOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQixpQkFBaUI7SUFDL0IsTUFBTSxNQUFNLEdBQUcsVUFBMkQsQ0FBQztJQUMzRSxJQUFJLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztRQUNqQyxNQUFNLE1BQU0sR0FBRyxJQUFBLHVDQUFxQixHQUFFLENBQUM7UUFDdkMsTUFBTSxpQkFBaUIsR0FBRyxhQUFhLENBQ3JDLDJCQUEyQixFQUMzQix3Q0FBc0IsQ0FDdkIsQ0FBQztRQUNGLElBQUksTUFBTSxDQUFDLFNBQVMsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7WUFDeEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxnQ0FBYyxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzdELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLElBQUksbUNBQWlCLENBQUM7Z0JBQ2xELE9BQU8sRUFBRSxJQUFJLGdDQUFjLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQztnQkFDckUsR0FBRyxFQUFFLElBQUksaUNBQWUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxpQkFBaUI7Z0JBQ2pCLEtBQUssRUFBRSxJQUFBLGVBQVEsRUFBQywrQkFBK0IsQ0FBQzthQUNqRCxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO2dCQUNwQixPQUFPLENBQUMsSUFBSSxDQUNWLHdHQUF3RyxDQUN6RyxDQUFDO1lBQ0osQ0FBQztZQUNELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLElBQUksbUNBQWlCLENBQUM7Z0JBQ2xELGlCQUFpQjthQUNsQixDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIFdoYXQgdGhlIHR3byBgY2FjaGVIYW5kbGVyc2AgKGAndXNlIGNhY2hlJ2AgYW5kIGAndXNlIGNhY2hlOiByZW1vdGUnYCkgc2hhcmU6XG4gIHRoZSBpbi1tZW1vcnkgZW50cnkgc3RvcmUsIHRoZSBwZW5kaW5nLWBzZXRgIGJvb2trZWVwaW5nIE5leHQuanMgcmVxdWlyZXMgb2ZcbiAgZXZlcnkgaGFuZGxlciwgYW5kIHRoZSBwcm9jZXNzJ3Mgb25lIHRhZyBtYW5pZmVzdCAoYFRyYWNrZWRUYWdNYXJrZXJzYCksXG4gIHdoaWNoIG1ha2VzIGByZXZhbGlkYXRlVGFnYCByZWFjaCBldmVyeSBpbnN0YW5jZSB0aHJvdWdoIHRoZSByZXZhbGlkYXRpb25cbiAgdGFibGUncyBtYXJrZXIgcm93cy5cbiovXG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCB7IER5bmFtb0RCQ2xpZW50IH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1keW5hbW9kYlwiO1xuaW1wb3J0IGdldERlYnVnIGZyb20gXCJkZWJ1Z1wiO1xuaW1wb3J0IHR5cGUge1xuICBDYWNoZUVudHJ5LFxuICBDYWNoZUhhbmRsZXIsXG59IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL2xpYi9jYWNoZS1oYW5kbGVycy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9UQUdfUkVGUkVTSF9NUyxcbiAgcmVzb2x2ZUF3c0NhY2hlQ29uZmlnLFxuICBSZXZhbGlkYXRpb25Mb2csXG4gIFRhZ01hcmtlclRhYmxlLFxuICBUcmFja2VkVGFnTWFya2Vycyxcbn0gZnJvbSBcIi4vYXdzLWNhY2hlLXN0b3JlXCI7XG5cbmV4cG9ydCB7IG1hcmtlckNsb2NrIGFzIG5vdyB9IGZyb20gXCIuL2F3cy1jYWNoZS1zdG9yZVwiO1xuXG4vKiogV2hldGhlciB0aGlzIHByb2Nlc3MgaXMgYG5leHQgYnVpbGRgIHJhdGhlciB0aGFuIGEgZGVwbG95ZWQgc2VydmVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQnVpbGRQaGFzZSgpOiBib29sZWFuIHtcbiAgcmV0dXJuIHByb2Nlc3MuZW52Lk5FWFRfUEhBU0UgPT09IFwicGhhc2UtcHJvZHVjdGlvbi1idWlsZFwiO1xufVxuXG4vKiogQSBwb3NpdGl2ZSBpbnRlZ2VyIGVudmlyb25tZW50IHZhcmlhYmxlLCBvciBgZmFsbGJhY2tgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG51bWJlckZyb21FbnYobmFtZTogc3RyaW5nLCBmYWxsYmFjazogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnZbbmFtZV07XG4gIGNvbnN0IHZhbHVlID0gcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSBcIlwiID8gTmFOIDogTnVtYmVyKHJhdyk7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpICYmIHZhbHVlID49IDAgPyB2YWx1ZSA6IGZhbGxiYWNrO1xufVxuXG4vKipcbiAqIEEgYENhY2hlRW50cnlgIHdpdGggaXRzIHZhbHVlIHJlYWQgdG8gdGhlIGVuZDogdGhlIGJ5dGVzIGFyZSB3aGF0IGlzIGtlcHQsXG4gKiBhbmQgZXZlcnkgYGdldGAgaGFuZHMgb3V0IGEgZnJlc2ggc3RyZWFtIG92ZXIgdGhlbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdG9yZWRFbnRyeSBleHRlbmRzIE9taXQ8Q2FjaGVFbnRyeSwgXCJ2YWx1ZVwiPiB7XG4gIHZhbHVlOiBVaW50OEFycmF5O1xufVxuXG4vKipcbiAqIFJlYWQgYHN0cmVhbWAgdG8gdGhlIGVuZCwgb3IgdGhyb3cgaWYgaXQgZXJyb3JzLlxuICpcbiAqIGBDYWNoZUVudHJ5LnZhbHVlYCBcImNhbiBlcnJvciBhbmQgb25seSBoYXZlIHBhcnRpYWwgZGF0YVwiIChOZXh0LmpzJ3NcbiAqIGBjYWNoZS1oYW5kbGVycy90eXBlcy5kLnRzYCkuIFRocm93aW5nIGlzIGhvdyBhIHBhcnRpYWwgZW50cnkgaXMga2VwdCBvdXQ6XG4gKiBib3RoIGhhbmRsZXJzIHN0b3JlIG5vdGhpbmcgd2hlbiB0aGlzIHJlamVjdHMsIHdoaWNoIGlzIHdoYXQgTmV4dC5qcydzIG93blxuICogZGVmYXVsdCBoYW5kbGVyIGRvZXMgdG9vLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFN0cmVhbShcbiAgc3RyZWFtOiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pixcbik6IFByb21pc2U8VWludDhBcnJheT4ge1xuICBjb25zdCByZWFkZXIgPSBzdHJlYW0uZ2V0UmVhZGVyKCk7XG4gIGNvbnN0IGNodW5rczogVWludDhBcnJheVtdID0gW107XG4gIGxldCBzaXplID0gMDtcbiAgZm9yICg7Oykge1xuICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjaHVua3MucHVzaCh2YWx1ZSk7XG4gICAgc2l6ZSArPSB2YWx1ZS5ieXRlTGVuZ3RoO1xuICB9XG4gIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gIGxldCBvZmZzZXQgPSAwO1xuICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykge1xuICAgIGJ5dGVzLnNldChjaHVuaywgb2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gY2h1bmsuYnl0ZUxlbmd0aDtcbiAgfVxuICByZXR1cm4gYnl0ZXM7XG59XG5cbi8qKiBgcGVuZGluZ0VudHJ5YCByZXNvbHZlZCBhbmQgcmVhZCB0byB0aGUgZW5kLiBTZWUge0BsaW5rIHJlYWRTdHJlYW19LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0b3JlZEVudHJ5T2YoXG4gIHBlbmRpbmdFbnRyeTogUHJvbWlzZTxDYWNoZUVudHJ5Pixcbik6IFByb21pc2U8U3RvcmVkRW50cnk+IHtcbiAgY29uc3QgZW50cnkgPSBhd2FpdCBwZW5kaW5nRW50cnk7XG4gIHJldHVybiB7IC4uLmVudHJ5LCB2YWx1ZTogYXdhaXQgcmVhZFN0cmVhbShlbnRyeS52YWx1ZSkgfTtcbn1cblxuLyoqIGBzdG9yZWRgIGFzIHRoZSBgQ2FjaGVFbnRyeWAgYSBgZ2V0YCByZXR1cm5zLCB3aXRoIGl0cyBvd24gc3RyZWFtLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhY2hlRW50cnlPZihcbiAgc3RvcmVkOiBTdG9yZWRFbnRyeSxcbiAgcmV2YWxpZGF0ZTogbnVtYmVyID0gc3RvcmVkLnJldmFsaWRhdGUsXG4pOiBDYWNoZUVudHJ5IHtcbiAgY29uc3QgYnl0ZXMgPSBzdG9yZWQudmFsdWU7XG4gIHJldHVybiB7XG4gICAgLi4uc3RvcmVkLFxuICAgIHJldmFsaWRhdGUsXG4gICAgdmFsdWU6IG5ldyBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pih7XG4gICAgICBzdGFydChjb250cm9sbGVyKSB7XG4gICAgICAgIC8vIEEgY29weTogd2hvZXZlciByZWFkcyB0aGUgc3RyZWFtIG1heSB0cmFuc2ZlciBvciBtdXRhdGUgdGhlIGNodW5rLlxuICAgICAgICBjb250cm9sbGVyLmVucXVldWUoYnl0ZXMuc2xpY2UoKSk7XG4gICAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICAgIH0sXG4gICAgfSksXG4gIH07XG59XG5cbi8qKlxuICogV2hldGhlciBOZXh0LmpzIHdvdWxkIHJlZ2VuZXJhdGUgYGVudHJ5YCBvbiBldmVyeSByZWFkIGFueXdheSwgc28gc3RvcmluZyBpdFxuICogaXMgYSB3cml0ZSBub3RoaW5nIHJlYWRzIGJhY2suIE5leHQuanMncyBkZWZhdWx0IGhhbmRsZXIgc2tpcHMgdGhlc2UgdGhlIHNhbWVcbiAqIHdheSwgb3V0c2lkZSB0aGUgZGV2IHNlcnZlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRHluYW1pY0VudHJ5KGVudHJ5OiBQaWNrPENhY2hlRW50cnksIFwiZXhwaXJlXCI+KTogYm9vbGVhbiB7XG4gIHJldHVybiBlbnRyeS5leHBpcmUgPT09IDA7XG59XG5cbi8qKlxuICogVGhlIGluLWZsaWdodCBgc2V0YHMsIGJ5IGNhY2hlIGtleS4gYENhY2hlSGFuZGxlci5zZXRgIHJlY2VpdmVzIGFuIGVudHJ5IHRoYXRcbiAqIG1heSBzdGlsbCBiZSBzdHJlYW1pbmcsIGFuZCBcImlmIGEgYGdldGAgZm9yIHRoZSBzYW1lIGNhY2hlIGtleSBpcyBjYWxsZWRcbiAqIGJlZm9yZSB0aGUgcGVuZGluZyBlbnRyeSBpcyBjb21wbGV0ZSwgdGhlIGNhY2hlIGhhbmRsZXIgbXVzdCB3YWl0IGZvciB0aGVcbiAqIGBzZXRgIG9wZXJhdGlvbiB0byBmaW5pc2hcIiAoYGNhY2hlLWhhbmRsZXJzL3R5cGVzLmQudHNgKS5cbiAqL1xuZXhwb3J0IGNsYXNzIFBlbmRpbmdTZXRzIHtcbiAgcHJpdmF0ZSByZWFkb25seSBwZW5kaW5nID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG5cbiAgLyoqIFJlc29sdmVzIG9uY2Ugbm8gYHNldGAgZm9yIGBrZXlgIGlzIGluIGZsaWdodC4gKi9cbiAgYXN5bmMgd2FpdChrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAobGV0IHAgPSB0aGlzLnBlbmRpbmcuZ2V0KGtleSk7IHA7IHAgPSB0aGlzLnBlbmRpbmcuZ2V0KGtleSkpIHtcbiAgICAgIGF3YWl0IHA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgYHNldGAgZm9yIGBrZXlgIGFuZCByZXR1cm4gdGhlIGZ1bmN0aW9uIHRoYXQgZW5kcyBpdC4gU2FmZSB0b1xuICAgKiBjYWxsIG1vcmUgdGhhbiBvbmNlOiBvbmx5IHRoZSByZWdpc3RyYXRpb24gaXQgbWFkZSBpcyByZW1vdmVkLlxuICAgKi9cbiAgYmVnaW4oa2V5OiBzdHJpbmcpOiAoKSA9PiB2b2lkIHtcbiAgICBsZXQgcmVzb2x2ZTogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocikgPT4gKHJlc29sdmUgPSByKSk7XG4gICAgdGhpcy5wZW5kaW5nLnNldChrZXksIHByb21pc2UpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5wZW5kaW5nLmdldChrZXkpID09PSBwcm9taXNlKSB7XG4gICAgICAgIHRoaXMucGVuZGluZy5kZWxldGUoa2V5KTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogU3RvcmVkIGVudHJpZXMgYnkgY2FjaGUga2V5LCBsZWFzdCByZWNlbnRseSB1c2VkIGV2aWN0ZWQgZmlyc3Qgb25jZSB0aGVpclxuICogYnl0ZXMgcGFzcyBgbWF4Qnl0ZXNgLiBTaXplZCBieSBieXRlcyByYXRoZXIgdGhhbiBlbnRyaWVzLCBsaWtlIE5leHQuanMnc1xuICogZGVmYXVsdCBoYW5kbGVyIChgY2FjaGVNYXhNZW1vcnlTaXplYCwgNTAgTUIpLCBzaW5jZSBhIGAndXNlIGNhY2hlJ2AgZW50cnkgaXNcbiAqIGFuIFJTQyBwYXlsb2FkIG9mIGFueSBzaXplLlxuICovXG5leHBvcnQgY2xhc3MgRW50cnlMcnUge1xuICBwcml2YXRlIHJlYWRvbmx5IGVudHJpZXMgPSBuZXcgTWFwPHN0cmluZywgU3RvcmVkRW50cnk+KCk7XG4gIHByaXZhdGUgYnl0ZXMgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgbWF4Qnl0ZXM6IG51bWJlcikge31cblxuICBnZXQoa2V5OiBzdHJpbmcpOiBTdG9yZWRFbnRyeSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gICAgaWYgKGVudHJ5KSB7XG4gICAgICAvLyBSZS1pbnNlcnRlZCB0byBtYXJrIGl0IG1vc3QgcmVjZW50bHkgdXNlZC5cbiAgICAgIHRoaXMuZW50cmllcy5kZWxldGUoa2V5KTtcbiAgICAgIHRoaXMuZW50cmllcy5zZXQoa2V5LCBlbnRyeSk7XG4gICAgfVxuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIHNldChrZXk6IHN0cmluZywgZW50cnk6IFN0b3JlZEVudHJ5KTogdm9pZCB7XG4gICAgdGhpcy5kZWxldGUoa2V5KTtcbiAgICBjb25zdCBzaXplID0gc2l6ZU9mKGtleSwgZW50cnkpO1xuICAgIGlmIChzaXplID4gdGhpcy5tYXhCeXRlcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmVudHJpZXMuc2V0KGtleSwgZW50cnkpO1xuICAgIHRoaXMuYnl0ZXMgKz0gc2l6ZTtcbiAgICBmb3IgKGNvbnN0IFtvbGRlc3RLZXksIG9sZGVzdF0gb2YgdGhpcy5lbnRyaWVzKSB7XG4gICAgICBpZiAodGhpcy5ieXRlcyA8PSB0aGlzLm1heEJ5dGVzKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShvbGRlc3RLZXkpO1xuICAgICAgdGhpcy5ieXRlcyAtPSBzaXplT2Yob2xkZXN0S2V5LCBvbGRlc3QpO1xuICAgIH1cbiAgfVxuXG4gIGRlbGV0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5lbnRyaWVzLmdldChrZXkpO1xuICAgIGlmIChleGlzdGluZykge1xuICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy5ieXRlcyAtPSBzaXplT2Yoa2V5LCBleGlzdGluZyk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IHNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5lbnRyaWVzLnNpemU7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2l6ZU9mKGtleTogc3RyaW5nLCBlbnRyeTogU3RvcmVkRW50cnkpOiBudW1iZXIge1xuICByZXR1cm4gZW50cnkudmFsdWUuYnl0ZUxlbmd0aCArIGtleS5sZW5ndGg7XG59XG5cbi8qKiBEZWZhdWx0IHNpemUgb2YgZWFjaCBoYW5kbGVyJ3MgbWVtb3J5IHN0b3JlOiBOZXh0LmpzJ3MgZGVmYXVsdCwgNTAgTUIuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NRU1PUllfQllURVMgPSA1MCAqIDEwMjQgKiAxMDI0O1xuXG4vKipcbiAqIFRoZSBgY2FjaGVIYW5kbGVyc2AgbWV0aG9kcyB0aGF0IG9ubHkgZ28gdGhyb3VnaCBgdGFnc2AsIHRoZSBzYW1lIGZvciB0aGVcbiAqIGBkZWZhdWx0YCBhbmQgYHJlbW90ZWAgaGFuZGxlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0YWdNZXRob2RzKFxuICB0YWdzOiBUcmFja2VkVGFnTWFya2Vycyxcbik6IFBpY2s8Q2FjaGVIYW5kbGVyLCBcInJlZnJlc2hUYWdzXCIgfCBcImdldEV4cGlyYXRpb25cIiB8IFwidXBkYXRlVGFnc1wiPiB7XG4gIHJldHVybiB7XG4gICAgcmVmcmVzaFRhZ3M6ICgpID0+IHRhZ3MucmVmcmVzaCgpLFxuICAgIGFzeW5jIGdldEV4cGlyYXRpb24oaW1wbGljaXRUYWdzKSB7XG4gICAgICBhd2FpdCB0YWdzLmVuc3VyZShpbXBsaWNpdFRhZ3MpO1xuICAgICAgcmV0dXJuIHRhZ3MuZXhwaXJhdGlvbihpbXBsaWNpdFRhZ3MpO1xuICAgIH0sXG4gICAgYXN5bmMgdXBkYXRlVGFncyhyZXZhbGlkYXRlZFRhZ3MsIGR1cmF0aW9ucykge1xuICAgICAgYXdhaXQgdGFncy51cGRhdGUocmV2YWxpZGF0ZWRUYWdzLCBkdXJhdGlvbnMpO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogQSBoYW5kbGVyIGJ1aWx0IGJ5IGBjcmVhdGVgIG9uIGZpcnN0IHVzZSByYXRoZXIgdGhhbiBvbiBpbXBvcnQsIHNvIGxvYWRpbmdcbiAqIHRoZSBtb2R1bGUgLSB3aGljaCBqZXN0LCBhbmQgTmV4dC5qcydzIGNvbmZpZyB2YWxpZGF0aW9uLCBkbyB3aXRob3V0IHVzaW5nXG4gKiBpdCAtIG5laXRoZXIgY29uc3RydWN0cyBBV1MgY2xpZW50cyBub3Igd2FybnMgYWJvdXQgbWlzc2luZyBjb25maWd1cmF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGF6eUhhbmRsZXIoY3JlYXRlOiAoKSA9PiBDYWNoZUhhbmRsZXIpOiBDYWNoZUhhbmRsZXIge1xuICBsZXQgaGFuZGxlcjogQ2FjaGVIYW5kbGVyIHwgdW5kZWZpbmVkO1xuICBjb25zdCBpbnN0YW5jZSA9ICgpID0+IChoYW5kbGVyID8/PSBjcmVhdGUoKSk7XG4gIHJldHVybiB7XG4gICAgZ2V0OiAoY2FjaGVLZXksIHNvZnRUYWdzKSA9PiBpbnN0YW5jZSgpLmdldChjYWNoZUtleSwgc29mdFRhZ3MpLFxuICAgIHNldDogKGNhY2hlS2V5LCBwZW5kaW5nRW50cnkpID0+IGluc3RhbmNlKCkuc2V0KGNhY2hlS2V5LCBwZW5kaW5nRW50cnkpLFxuICAgIHJlZnJlc2hUYWdzOiAoKSA9PiBpbnN0YW5jZSgpLnJlZnJlc2hUYWdzKCksXG4gICAgZ2V0RXhwaXJhdGlvbjogKHRhZ3MpID0+IGluc3RhbmNlKCkuZ2V0RXhwaXJhdGlvbih0YWdzKSxcbiAgICB1cGRhdGVUYWdzOiAodGFncywgZHVyYXRpb25zKSA9PiBpbnN0YW5jZSgpLnVwZGF0ZVRhZ3ModGFncywgZHVyYXRpb25zKSxcbiAgfTtcbn1cblxuY29uc3QgVEFHX01BTklGRVNUX1NZTUJPTCA9IFN5bWJvbC5mb3IoXCJjZGstbmV4dGpzLnVzZS1jYWNoZS50YWctbWFuaWZlc3RcIik7XG5cbi8qKlxuICogVGhlIHByb2Nlc3MncyBvbmUge0BsaW5rIFRyYWNrZWRUYWdNYXJrZXJzfSwgZnJvbSB0aGUgZW52aXJvbm1lbnQuXG4gKlxuICogS2VwdCBvbiBgZ2xvYmFsVGhpc2AgYmVjYXVzZSB0aGUgaW5jcmVtZW50YWwgY2FjaGUgaGFuZGxlciBhbmQgdGhlIGBkZWZhdWx0YFxuICogYW5kIGByZW1vdGVgIGhhbmRsZXJzIGFyZSBzZXBhcmF0ZSBidW5kbGVzIC0gc2VwYXJhdGUgbW9kdWxlIGluc3RhbmNlcyAtIGFuZFxuICogc2hvdWxkIHNoYXJlIG9uZSBtYW5pZmVzdDogb25lIHJlZnJlc2ggcmVhZCBmb3IgYWxsIG9mIHRoZW0sIGFuZCBvbmUgbWFya2VyXG4gKiB3cml0ZSBwZXIgYHJldmFsaWRhdGVUYWdgLlxuICpcbiAqIEF0IGJ1aWxkIHRpbWUgdGhlcmUgaXMgbm8gdGFibGUgdG8gcmVhZCAoYW5kIG5vIGNyZWRlbnRpYWxzIHRvIHJlYWQgaXRcbiAqIHdpdGgpLCBzbyB0YWdzIHN0YXkgbG9jYWwgdG8gdGhlIHByb2Nlc3MgdGhlcmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFyZWRUYWdNYW5pZmVzdCgpOiBUcmFja2VkVGFnTWFya2VycyB7XG4gIGNvbnN0IGdsb2JhbCA9IGdsb2JhbFRoaXMgYXMgeyBbVEFHX01BTklGRVNUX1NZTUJPTF0/OiBUcmFja2VkVGFnTWFya2VycyB9O1xuICBpZiAoIWdsb2JhbFtUQUdfTUFOSUZFU1RfU1lNQk9MXSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlc29sdmVBd3NDYWNoZUNvbmZpZygpO1xuICAgIGNvbnN0IHJlZnJlc2hJbnRlcnZhbE1zID0gbnVtYmVyRnJvbUVudihcbiAgICAgIFwiQ0RLX05FWFRKU19UQUdfUkVGUkVTSF9NU1wiLFxuICAgICAgREVGQVVMVF9UQUdfUkVGUkVTSF9NUyxcbiAgICApO1xuICAgIGlmIChjb25maWcudGFibGVOYW1lICYmICFpc0J1aWxkUGhhc2UoKSkge1xuICAgICAgY29uc3QgY2xpZW50ID0gbmV3IER5bmFtb0RCQ2xpZW50KHsgcmVnaW9uOiBjb25maWcucmVnaW9uIH0pO1xuICAgICAgZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdID0gbmV3IFRyYWNrZWRUYWdNYXJrZXJzKHtcbiAgICAgICAgbWFya2VyczogbmV3IFRhZ01hcmtlclRhYmxlKGNsaWVudCwgY29uZmlnLnRhYmxlTmFtZSwgY29uZmlnLmJ1aWxkSWQpLFxuICAgICAgICBsb2c6IG5ldyBSZXZhbGlkYXRpb25Mb2coY2xpZW50LCBjb25maWcudGFibGVOYW1lLCBjb25maWcuYnVpbGRJZCksXG4gICAgICAgIHJlZnJlc2hJbnRlcnZhbE1zLFxuICAgICAgICBkZWJ1ZzogZ2V0RGVidWcoXCJjZGstbmV4dGpzOmNhY2hlLWhhbmRsZXI6dGFnc1wiKSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWlzQnVpbGRQaGFzZSgpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBcIkNES19ORVhUSlNfUkVWQUxJREFUSU9OX1RBQkxFX05BTUUgZW52aXJvbm1lbnQgdmFyaWFibGUgbm90IHNldCwgY2FjaGUgdGFncyBhcmUgbG9jYWwgdG8gZWFjaCBpbnN0YW5jZVwiLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdID0gbmV3IFRyYWNrZWRUYWdNYXJrZXJzKHtcbiAgICAgICAgcmVmcmVzaEludGVydmFsTXMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGdsb2JhbFtUQUdfTUFOSUZFU1RfU1lNQk9MXTtcbn1cbiJdfQ==
373
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlLWNhY2hlLWNvbW1vbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL3VzZS1jYWNoZS1jb21tb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBMEJBLG9DQUVDO0FBR0Qsc0NBSUM7QUFrQkQsZ0NBcUJDO0FBR0Qsc0NBS0M7QUFHRCxvQ0FnQkM7QUFPRCx3Q0FFQztBQXlKRCw0Q0FFQztBQW1CRCwwQkFXQztBQWVELGdDQTRCQztBQWFELHNDQUVDO0FBUUQsa0NBY0M7QUFhRCw4Q0F3Q0M7QUE1YUQ7Ozs7OztFQU1FO0FBQ0Ysc0RBQXNEO0FBQ3RELDhEQUEwRDtBQUMxRCxrREFBNkI7QUFLN0IsdURBTTJCO0FBQzNCLDBEQUE4RTtBQUU5RSxxREFBdUQ7QUFBOUMsc0dBQUEsV0FBVyxPQUFPO0FBRTNCLDBFQUEwRTtBQUMxRSxTQUFnQixZQUFZO0lBQzFCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEtBQUssd0JBQXdCLENBQUM7QUFDN0QsQ0FBQztBQUVELDhEQUE4RDtBQUM5RCxTQUFnQixhQUFhLENBQUMsSUFBWSxFQUFFLFFBQWdCO0lBQzFELE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUIsTUFBTSxLQUFLLEdBQUcsR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsRSxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7QUFDakUsQ0FBQztBQVVEOzs7Ozs7O0dBT0c7QUFDSSxLQUFLLFVBQVUsVUFBVSxDQUM5QixNQUFrQztJQUVsQyxNQUFNLE1BQU0sR0FBRyxNQUFN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Q0FBQztnQkFDbEUsaUJBQWlCO2dCQUNqQixLQUFLLEVBQUUsSUFBQSxlQUFRLEVBQUMsK0JBQStCLENBQUM7Z0JBQ2hELDREQUE0RDtnQkFDNUQsU0FBUyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLEtBQUssU0FBUzthQUM5RCxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO2dCQUNwQixPQUFPLENBQUMsSUFBSSxDQUNWLHdHQUF3RyxDQUN6RyxDQUFDO1lBQ0osQ0FBQztZQUNELE1BQU0sQ0FBQyxrQ0FBbUIsQ0FBQyxHQUFHLElBQUksbUNBQWlCLENBQUM7Z0JBQ2xELGlCQUFpQjthQUNsQixDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLGtDQUFtQixDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIFdoYXQgdGhlIHR3byBgY2FjaGVIYW5kbGVyc2AgKGAndXNlIGNhY2hlJ2AgYW5kIGAndXNlIGNhY2hlOiByZW1vdGUnYCkgc2hhcmU6XG4gIHRoZSBpbi1tZW1vcnkgZW50cnkgc3RvcmUsIHRoZSBwZW5kaW5nLWBzZXRgIGJvb2trZWVwaW5nIE5leHQuanMgcmVxdWlyZXMgb2ZcbiAgZXZlcnkgaGFuZGxlciwgYW5kIHRoZSBwcm9jZXNzJ3Mgb25lIHRhZyBtYW5pZmVzdCAoYFRyYWNrZWRUYWdNYXJrZXJzYCksXG4gIHdoaWNoIG1ha2VzIGByZXZhbGlkYXRlVGFnYCByZWFjaCBldmVyeSBpbnN0YW5jZSB0aHJvdWdoIHRoZSByZXZhbGlkYXRpb25cbiAgdGFibGUncyBtYXJrZXIgcm93cy5cbiovXG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCB7IER5bmFtb0RCQ2xpZW50IH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1keW5hbW9kYlwiO1xuaW1wb3J0IGdldERlYnVnIGZyb20gXCJkZWJ1Z1wiO1xuaW1wb3J0IHR5cGUge1xuICBDYWNoZUVudHJ5LFxuICBDYWNoZUhhbmRsZXIsXG59IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL2xpYi9jYWNoZS1oYW5kbGVycy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9UQUdfUkVGUkVTSF9NUyxcbiAgcmVzb2x2ZUF3c0NhY2hlQ29uZmlnLFxuICBSZXZhbGlkYXRpb25Mb2csXG4gIFRhZ01hcmtlclRhYmxlLFxuICBUcmFja2VkVGFnTWFya2Vycyxcbn0gZnJvbSBcIi4vYXdzLWNhY2hlLXN0b3JlXCI7XG5pbXBvcnQgeyBvdXRzaWRlUmVxdWVzdCwgVEFHX01BTklGRVNUX1NZTUJPTCB9IGZyb20gXCIuLi9ydW50aW1lL3RhZy1tYW5pZmVzdFwiO1xuXG5leHBvcnQgeyBtYXJrZXJDbG9jayBhcyBub3cgfSBmcm9tIFwiLi9hd3MtY2FjaGUtc3RvcmVcIjtcblxuLyoqIFdoZXRoZXIgdGhpcyBwcm9jZXNzIGlzIGBuZXh0IGJ1aWxkYCByYXRoZXIgdGhhbiBhIGRlcGxveWVkIHNlcnZlci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0J1aWxkUGhhc2UoKTogYm9vbGVhbiB7XG4gIHJldHVybiBwcm9jZXNzLmVudi5ORVhUX1BIQVNFID09PSBcInBoYXNlLXByb2R1Y3Rpb24tYnVpbGRcIjtcbn1cblxuLyoqIEEgcG9zaXRpdmUgaW50ZWdlciBlbnZpcm9ubWVudCB2YXJpYWJsZSwgb3IgYGZhbGxiYWNrYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJGcm9tRW52KG5hbWU6IHN0cmluZywgZmFsbGJhY2s6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52W25hbWVdO1xuICBjb25zdCB2YWx1ZSA9IHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gXCJcIiA/IE5hTiA6IE51bWJlcihyYXcpO1xuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKHZhbHVlKSAmJiB2YWx1ZSA+PSAwID8gdmFsdWUgOiBmYWxsYmFjaztcbn1cblxuLyoqXG4gKiBBIGBDYWNoZUVudHJ5YCB3aXRoIGl0cyB2YWx1ZSByZWFkIHRvIHRoZSBlbmQ6IHRoZSBieXRlcyBhcmUgd2hhdCBpcyBrZXB0LFxuICogYW5kIGV2ZXJ5IGBnZXRgIGhhbmRzIG91dCBhIGZyZXNoIHN0cmVhbSBvdmVyIHRoZW0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmVkRW50cnkgZXh0ZW5kcyBPbWl0PENhY2hlRW50cnksIFwidmFsdWVcIj4ge1xuICB2YWx1ZTogVWludDhBcnJheTtcbn1cblxuLyoqXG4gKiBSZWFkIGBzdHJlYW1gIHRvIHRoZSBlbmQsIG9yIHRocm93IGlmIGl0IGVycm9ycy5cbiAqXG4gKiBgQ2FjaGVFbnRyeS52YWx1ZWAgXCJjYW4gZXJyb3IgYW5kIG9ubHkgaGF2ZSBwYXJ0aWFsIGRhdGFcIiAoTmV4dC5qcydzXG4gKiBgY2FjaGUtaGFuZGxlcnMvdHlwZXMuZC50c2ApLiBUaHJvd2luZyBpcyBob3cgYSBwYXJ0aWFsIGVudHJ5IGlzIGtlcHQgb3V0OlxuICogYm90aCBoYW5kbGVycyBzdG9yZSBub3RoaW5nIHdoZW4gdGhpcyByZWplY3RzLCB3aGljaCBpcyB3aGF0IE5leHQuanMncyBvd25cbiAqIGRlZmF1bHQgaGFuZGxlciBkb2VzIHRvby5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRTdHJlYW0oXG4gIHN0cmVhbTogUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4sXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgcmVhZGVyID0gc3RyZWFtLmdldFJlYWRlcigpO1xuICBjb25zdCBjaHVua3M6IFVpbnQ4QXJyYXlbXSA9IFtdO1xuICBsZXQgc2l6ZSA9IDA7XG4gIGZvciAoOzspIHtcbiAgICBjb25zdCB7IGRvbmUsIHZhbHVlIH0gPSBhd2FpdCByZWFkZXIucmVhZCgpO1xuICAgIGlmIChkb25lKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2h1bmtzLnB1c2godmFsdWUpO1xuICAgIHNpemUgKz0gdmFsdWUuYnl0ZUxlbmd0aDtcbiAgfVxuICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KHNpemUpO1xuICBsZXQgb2Zmc2V0ID0gMDtcbiAgZm9yIChjb25zdCBjaHVuayBvZiBjaHVua3MpIHtcbiAgICBieXRlcy5zZXQoY2h1bmssIG9mZnNldCk7XG4gICAgb2Zmc2V0ICs9IGNodW5rLmJ5dGVMZW5ndGg7XG4gIH1cbiAgcmV0dXJuIGJ5dGVzO1xufVxuXG4vKiogYHBlbmRpbmdFbnRyeWAgcmVzb2x2ZWQgYW5kIHJlYWQgdG8gdGhlIGVuZC4gU2VlIHtAbGluayByZWFkU3RyZWFtfS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdG9yZWRFbnRyeU9mKFxuICBwZW5kaW5nRW50cnk6IFByb21pc2U8Q2FjaGVFbnRyeT4sXG4pOiBQcm9taXNlPFN0b3JlZEVudHJ5PiB7XG4gIGNvbnN0IGVudHJ5ID0gYXdhaXQgcGVuZGluZ0VudHJ5O1xuICByZXR1cm4geyAuLi5lbnRyeSwgdmFsdWU6IGF3YWl0IHJlYWRTdHJlYW0oZW50cnkudmFsdWUpIH07XG59XG5cbi8qKiBgc3RvcmVkYCBhcyB0aGUgYENhY2hlRW50cnlgIGEgYGdldGAgcmV0dXJucywgd2l0aCBpdHMgb3duIHN0cmVhbS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWNoZUVudHJ5T2YoXG4gIHN0b3JlZDogU3RvcmVkRW50cnksXG4gIHJldmFsaWRhdGU6IG51bWJlciA9IHN0b3JlZC5yZXZhbGlkYXRlLFxuKTogQ2FjaGVFbnRyeSB7XG4gIGNvbnN0IGJ5dGVzID0gc3RvcmVkLnZhbHVlO1xuICByZXR1cm4ge1xuICAgIC4uLnN0b3JlZCxcbiAgICByZXZhbGlkYXRlLFxuICAgIHZhbHVlOiBuZXcgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4oe1xuICAgICAgc3RhcnQoY29udHJvbGxlcikge1xuICAgICAgICAvLyBBIGNvcHk6IHdob2V2ZXIgcmVhZHMgdGhlIHN0cmVhbSBtYXkgdHJhbnNmZXIgb3IgbXV0YXRlIHRoZSBjaHVuay5cbiAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGJ5dGVzLnNsaWNlKCkpO1xuICAgICAgICBjb250cm9sbGVyLmNsb3NlKCk7XG4gICAgICB9LFxuICAgIH0pLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgTmV4dC5qcyB3b3VsZCByZWdlbmVyYXRlIGBlbnRyeWAgb24gZXZlcnkgcmVhZCBhbnl3YXksIHNvIHN0b3JpbmcgaXRcbiAqIGlzIGEgd3JpdGUgbm90aGluZyByZWFkcyBiYWNrLiBOZXh0LmpzJ3MgZGVmYXVsdCBoYW5kbGVyIHNraXBzIHRoZXNlIHRoZSBzYW1lXG4gKiB3YXksIG91dHNpZGUgdGhlIGRldiBzZXJ2ZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0R5bmFtaWNFbnRyeShlbnRyeTogUGljazxDYWNoZUVudHJ5LCBcImV4cGlyZVwiPik6IGJvb2xlYW4ge1xuICByZXR1cm4gZW50cnkuZXhwaXJlID09PSAwO1xufVxuXG4vKipcbiAqIFRoZSBpbi1mbGlnaHQgYHNldGBzLCBieSBjYWNoZSBrZXkuIGBDYWNoZUhhbmRsZXIuc2V0YCByZWNlaXZlcyBhbiBlbnRyeSB0aGF0XG4gKiBtYXkgc3RpbGwgYmUgc3RyZWFtaW5nLCBhbmQgXCJpZiBhIGBnZXRgIGZvciB0aGUgc2FtZSBjYWNoZSBrZXkgaXMgY2FsbGVkXG4gKiBiZWZvcmUgdGhlIHBlbmRpbmcgZW50cnkgaXMgY29tcGxldGUsIHRoZSBjYWNoZSBoYW5kbGVyIG11c3Qgd2FpdCBmb3IgdGhlXG4gKiBgc2V0YCBvcGVyYXRpb24gdG8gZmluaXNoXCIgKGBjYWNoZS1oYW5kbGVycy90eXBlcy5kLnRzYCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBQZW5kaW5nU2V0cyB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVuZGluZyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PigpO1xuXG4gIC8qKiBSZXNvbHZlcyBvbmNlIG5vIGBzZXRgIGZvciBga2V5YCBpcyBpbiBmbGlnaHQuICovXG4gIGFzeW5jIHdhaXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGxldCBwID0gdGhpcy5wZW5kaW5nLmdldChrZXkpOyBwOyBwID0gdGhpcy5wZW5kaW5nLmdldChrZXkpKSB7XG4gICAgICBhd2FpdCBwO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIGBzZXRgIGZvciBga2V5YCBhbmQgcmV0dXJuIHRoZSBmdW5jdGlvbiB0aGF0IGVuZHMgaXQuIFNhZmUgdG9cbiAgICogY2FsbCBtb3JlIHRoYW4gb25jZTogb25seSB0aGUgcmVnaXN0cmF0aW9uIGl0IG1hZGUgaXMgcmVtb3ZlZC5cbiAgICovXG4gIGJlZ2luKGtleTogc3RyaW5nKTogKCkgPT4gdm9pZCB7XG4gICAgbGV0IHJlc29sdmU6ICgpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2U8dm9pZD4oKHIpID0+IChyZXNvbHZlID0gcikpO1xuICAgIHRoaXMucGVuZGluZy5zZXQoa2V5LCBwcm9taXNlKTtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucGVuZGluZy5nZXQoa2V5KSA9PT0gcHJvbWlzZSkge1xuICAgICAgICB0aGlzLnBlbmRpbmcuZGVsZXRlKGtleSk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKCk7XG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIFN0b3JlZCBlbnRyaWVzIGJ5IGNhY2hlIGtleSwgbGVhc3QgcmVjZW50bHkgdXNlZCBldmljdGVkIGZpcnN0IG9uY2UgdGhlaXJcbiAqIGJ5dGVzIHBhc3MgYG1heEJ5dGVzYC4gU2l6ZWQgYnkgYnl0ZXMgcmF0aGVyIHRoYW4gZW50cmllcywgbGlrZSBOZXh0LmpzJ3NcbiAqIGRlZmF1bHQgaGFuZGxlciAoYGNhY2hlTWF4TWVtb3J5U2l6ZWAsIDUwIE1CKSwgc2luY2UgYSBgJ3VzZSBjYWNoZSdgIGVudHJ5IGlzXG4gKiBhbiBSU0MgcGF5bG9hZCBvZiBhbnkgc2l6ZS5cbiAqL1xuZXhwb3J0IGNsYXNzIEVudHJ5THJ1IHtcbiAgcHJpdmF0ZSByZWFkb25seSBlbnRyaWVzID0gbmV3IE1hcDxzdHJpbmcsIFN0b3JlZEVudHJ5PigpO1xuICBwcml2YXRlIGJ5dGVzID0gMDtcbiAgLyoqXG4gICAqIE5vIGxhdGVyIHRoYW4gdGhlIG9sZGVzdCBlbnRyeSdzIGB0aW1lc3RhbXBgOiB0aGUgbGFzdCBzY2FuJ3MgYW5zd2VyLCBsZXNzXG4gICAqIHdoYXRldmVyIHdhcyBzZXQgc2luY2UuIEVudHJpZXMgZHJvcHBlZCBzaW5jZSBvbmx5IG1ha2UgaXQgZWFybHkuIFNlZVxuICAgKiB7QGxpbmsgb2xkZXN0Qm91bmR9LlxuICAgKi9cbiAgcHJpdmF0ZSBsb3dlc3QgPSBJbmZpbml0eTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IG1heEJ5dGVzOiBudW1iZXIpIHt9XG5cbiAgZ2V0KGtleTogc3RyaW5nKTogU3RvcmVkRW50cnkgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5lbnRyaWVzLmdldChrZXkpO1xuICAgIGlmIChlbnRyeSkge1xuICAgICAgLy8gUmUtaW5zZXJ0ZWQgdG8gbWFyayBpdCBtb3N0IHJlY2VudGx5IHVzZWQuXG4gICAgICB0aGlzLmVudHJpZXMuZGVsZXRlKGtleSk7XG4gICAgICB0aGlzLmVudHJpZXMuc2V0KGtleSwgZW50cnkpO1xuICAgIH1cbiAgICByZXR1cm4gZW50cnk7XG4gIH1cblxuICBzZXQoa2V5OiBzdHJpbmcsIGVudHJ5OiBTdG9yZWRFbnRyeSk6IHZvaWQge1xuICAgIHRoaXMuZGVsZXRlKGtleSk7XG4gICAgY29uc3Qgc2l6ZSA9IHNpemVPZihrZXksIGVudHJ5KTtcbiAgICBpZiAoc2l6ZSA+IHRoaXMubWF4Qnl0ZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5lbnRyaWVzLnNldChrZXksIGVudHJ5KTtcbiAgICB0aGlzLmJ5dGVzICs9IHNpemU7XG4gICAgdGhpcy5sb3dlc3QgPSBNYXRoLm1pbih0aGlzLmxvd2VzdCwgZW50cnkudGltZXN0YW1wKTtcbiAgICBmb3IgKGNvbnN0IFtvbGRlc3RLZXksIG9sZGVzdF0gb2YgdGhpcy5lbnRyaWVzKSB7XG4gICAgICBpZiAodGhpcy5ieXRlcyA8PSB0aGlzLm1heEJ5dGVzKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShvbGRlc3RLZXkpO1xuICAgICAgdGhpcy5ieXRlcyAtPSBzaXplT2Yob2xkZXN0S2V5LCBvbGRlc3QpO1xuICAgIH1cbiAgfVxuXG4gIGRlbGV0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5lbnRyaWVzLmdldChrZXkpO1xuICAgIGlmIChleGlzdGluZykge1xuICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy5ieXRlcyAtPSBzaXplT2Yoa2V5LCBleGlzdGluZyk7XG4gICAgICBpZiAodGhpcy5lbnRyaWVzLnNpemUgPT09IDApIHtcbiAgICAgICAgdGhpcy5sb3dlc3QgPSBJbmZpbml0eTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIGB0aW1lc3RhbXBgIG9mIHRoZSBvbGRlc3QgZW50cnkgaGVsZCwgYEluZmluaXR5YCB3aXRoIG5vbmUsIGRyb3BwaW5nXG4gICAqIG9uIHRoZSB3YXkgdGhlIGVudHJpZXMgcGFzdCBgcmV2YWxpZGF0ZWAgYXQgYGF0YCAoYG5vdygpYCk6IGEgaGFuZGxlclxuICAgKiB0aGF0IGRyb3BzIHRoZW0gd2hlbiBuZXh0IHJlYWQgd291bGQgb3RoZXJ3aXNlIGhvbGQgdGhlbSB1bnRpbCB0aGVuLCBhbmRcbiAgICogdGhleSB3b3VsZCBjb3VudCBoZXJlIG1lYW53aGlsZS4gQSBzY2FuLCBzbyBhc2tlZCBvbmNlIGluIGEgd2hpbGU6IGluXG4gICAqIGJldHdlZW4sIHtAbGluayBvbGRlc3RCb3VuZH0gYW5zd2Vycy5cbiAgICovXG4gIG9sZGVzdFRpbWVzdGFtcChhdCA9IC1JbmZpbml0eSk6IG51bWJlciB7XG4gICAgbGV0IG9sZGVzdCA9IEluZmluaXR5O1xuICAgIGZvciAoY29uc3QgW2tleSwgZW50cnldIG9mIHRoaXMuZW50cmllcykge1xuICAgICAgaWYgKGlzUGFzdFJldmFsaWRhdGUoZW50cnksIGF0KSkge1xuICAgICAgICB0aGlzLmRlbGV0ZShrZXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2xkZXN0ID0gTWF0aC5taW4ob2xkZXN0LCBlbnRyeS50aW1lc3RhbXApO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmxvd2VzdCA9IG9sZGVzdDtcbiAgICByZXR1cm4gb2xkZXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIE5vIGxhdGVyIHRoYW4ge0BsaW5rIG9sZGVzdFRpbWVzdGFtcH0sIHdpdGhvdXQgaXRzIHNjYW46IGFzIG9mIHRoZSBsYXN0XG4gICAqIG9uZSwgbGVzcyB0aGUgZW50cmllcyBzZXQgc2luY2UuIGBJbmZpbml0eWAgd2l0aCBub25lIGhlbGQuIERyb3BzIHRoZVxuICAgKiBlbnRyaWVzIHBhc3QgYHJldmFsaWRhdGVgIGF0IGBhdGAgZnJvbSB0aGUgbGVhc3QgcmVjZW50bHkgdXNlZCBlbmQsIHVwIHRvXG4gICAqIHRoZSBmaXJzdCB0aGF0IGlzbid0LCBzbyB7QGxpbmsgaG9sZHNMaXZlfSBkb2Vzbid0IHdhbGsgcGFzdCB0aGVtIG9uIGV2ZXJ5XG4gICAqIHJlcXVlc3QgdW50aWwgdGhlIG5leHQgc2Nhbi5cbiAgICovXG4gIG9sZGVzdEJvdW5kKGF0ID0gLUluZmluaXR5KTogbnVtYmVyIHtcbiAgICBmb3IgKGNvbnN0IFtrZXksIGVudHJ5XSBvZiB0aGlzLmVudHJpZXMpIHtcbiAgICAgIGlmICghaXNQYXN0UmV2YWxpZGF0ZShlbnRyeSwgYXQpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgdGhpcy5kZWxldGUoa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZW50cmllcy5zaXplID09PSAwID8gSW5maW5pdHkgOiB0aGlzLmxvd2VzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGFuIGVudHJ5IG5vdCBwYXN0IGByZXZhbGlkYXRlYCBhdCBgYXRgIGlzIGhlbGQuIFVzdWFsbHkgdGhlIGZpcnN0XG4gICAqIGVudHJ5IGFuc3dlcnM7IHRoZSBleHBpcmVkIG9uZXMgaXQgcGFzc2VzIGFyZSBkcm9wcGVkIGJ5IHRoZSBzY2FuXG4gICAqIHtAbGluayBvbGRlc3RUaW1lc3RhbXB9IG1ha2VzLCBub3QgaGVyZSwgc28gYXNraW5nIGNoYW5nZXMgbm90aGluZy5cbiAgICovXG4gIGhvbGRzTGl2ZShhdDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiB0aGlzLmVudHJpZXMudmFsdWVzKCkpIHtcbiAgICAgIGlmICghaXNQYXN0UmV2YWxpZGF0ZShlbnRyeSwgYXQpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBnZXQgc2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXMuc2l6ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzaXplT2Yoa2V5OiBzdHJpbmcsIGVudHJ5OiBTdG9yZWRFbnRyeSk6IG51bWJlciB7XG4gIHJldHVybiBlbnRyeS52YWx1ZS5ieXRlTGVuZ3RoICsga2V5Lmxlbmd0aDtcbn1cblxuLyoqIFdoZXRoZXIgYHN0b3JlZGAgaXMgcGFzdCBgcmV2YWxpZGF0ZWAgYXQgYGF0YCAoYG5vdygpYCkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQYXN0UmV2YWxpZGF0ZShzdG9yZWQ6IFN0b3JlZEVudHJ5LCBhdDogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiBhdCA+IHN0b3JlZC50aW1lc3RhbXAgKyBzdG9yZWQucmV2YWxpZGF0ZSAqIDEwMDA7XG59XG5cbi8qKiBEZWZhdWx0IHNpemUgb2YgZWFjaCBoYW5kbGVyJ3MgbWVtb3J5IHN0b3JlOiBOZXh0LmpzJ3MgZGVmYXVsdCwgNTAgTUIuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NRU1PUllfQllURVMgPSA1MCAqIDEwMjQgKiAxMDI0O1xuXG4vKipcbiAqIEhvdyBsb25nIG9uZSByZXZhbGlkYXRpb24gdGFibGUgcmVxdWVzdCBtYXkgdGFrZSwgcGVyIGF0dGVtcHQuIFRoZSBTREsgc2V0c1xuICogbm8gbGltaXQsIGFuZCBhIHJlZnJlc2ggbGVmdCBpbiBmbGlnaHQgYWNyb3NzIGEgTGFtYmRhIGZyZWV6ZSBjYW4gc2l0IG9uIGFcbiAqIGNvbm5lY3Rpb24gdGhhdCBkaWVkIG1lYW53aGlsZSB3aXRob3V0IGEgcmVzZXQ6IGV2ZXJ5IHJlcXVlc3QgdGhhdCB3YWl0c1xuICogZm9yIHRoZSByZWZyZXNoIChhbiBpbnN0YW5jZSBgYmVoaW5kYCwgSVNSKSB3b3VsZCB3YWl0IHdpdGggaXQuIFRoZSBTREtcbiAqIHJldHJpZXMgYSB0aW1lZC1vdXQgYXR0ZW1wdCwgc28gYSBkZWFkIGNvbm5lY3Rpb24gY29zdHMgdXAgdG8gaXRzIGF0dGVtcHRzXG4gKiB0aW1lcyB0aGlzLlxuICovXG5leHBvcnQgY29uc3QgVEFHX1RBQkxFX1JFUVVFU1RfVElNRU9VVF9NUyA9IDMwMDA7XG5cbi8qKlxuICogV2FpdCBmb3IgYHdvcmtgIGlmIGB3YWl0YCwgb3IgZWxzZSBsZXQgaXQgcnVuIG9uOiBlaXRoZXIgd2F5IGEgcmVqZWN0aW9uIGlzXG4gKiBsb2dnZWQgd2l0aCBgZmFpbHVyZWAgcmF0aGVyIHRoYW4gdGhyb3duLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXdhaXRJZihcbiAgd2FpdDogYm9vbGVhbixcbiAgd29yazogUHJvbWlzZTx2b2lkPixcbiAgZmFpbHVyZTogc3RyaW5nLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGxvZ2dlZCA9IHdvcmsuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgY29uc29sZS5lcnJvcihmYWlsdXJlLCBlcnJvcik7XG4gIH0pO1xuICBpZiAod2FpdCkge1xuICAgIGF3YWl0IGxvZ2dlZDtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRhZ01ldGhvZHNPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgYHJlZnJlc2hUYWdzYCBhbHdheXMgd2FpdHMgZm9yIHRoZSByZXZhbGlkYXRpb24gbG9nIHF1ZXJ5LCByYXRoZXJcbiAgICogdGhhbiBvbmx5IHdoZW4gdGhlIGluc3RhbmNlIGlzIGBiZWhpbmRgLlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgYmxvY2tpbmc/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFRoZSBgY2FjaGVIYW5kbGVyc2AgbWV0aG9kcyB0aGF0IG9ubHkgZ28gdGhyb3VnaCBgdGFnc2AsIHRoZSBzYW1lIGZvciB0aGVcbiAqIGBkZWZhdWx0YCBhbmQgYHJlbW90ZWAgaGFuZGxlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0YWdNZXRob2RzKFxuICB0YWdzOiBUcmFja2VkVGFnTWFya2VycyxcbiAgb3B0aW9uczogVGFnTWV0aG9kc09wdGlvbnMgPSB7fSxcbik6IFBpY2s8Q2FjaGVIYW5kbGVyLCBcInJlZnJlc2hUYWdzXCIgfCBcInVwZGF0ZVRhZ3NcIj4ge1xuICByZXR1cm4ge1xuICAgIC8vIFN0YXJ0ZWQsIG5vdCBhd2FpdGVkLCB3aGlsZSB0aGUgaW5zdGFuY2Uga2VlcHMgdXAsIHVubGVzcyBgYmxvY2tpbmdgLlxuICAgIC8vIE5leHQuanMgYXdhaXRzIGByZWZyZXNoVGFnc2AgaW5zaWRlIHRoZSBmaXJzdCBgJ3VzZSBjYWNoZSdgIGxvb2t1cCBvZiBhXG4gICAgLy8gcmVxdWVzdCAoYHVzZS1jYWNoZS13cmFwcGVyYCksIGFuZCBhIHN0YWdlZCByZW5kZXIgZW5kcyBpdHMgc3RhdGljIHN0YWdlXG4gICAgLy8gb24gYSB0aW1lcjogYSBsb2cgYFF1ZXJ5YCB0aGVyZSBwdXNoZWQgdGhlIGVudHJ5IG91dCBvZiB0aGUgc3RhdGljXG4gICAgLy8gc3RhZ2UsIHNvIGEgY2FjaGVkIG5hdmlnYXRpb24gc3RvcmVkIHRoZSBwYWdlIHNlZ21lbnQgd2l0aG91dCBpdC4gV2hhdFxuICAgIC8vIHRoZSBxdWVyeSBmaW5kcyBhcHBsaWVzIGZyb20gdGhlIG5leHQgcmVxdWVzdC4gQXdhaXRlZCBvbmNlIHRoZSBpbnN0YW5jZVxuICAgIC8vIGlzIGBiZWhpbmRgLCB3aGljaCB0aGUgcnVudGltZSBzZXR0bGVzIGJlZm9yZSBhIHBhZ2UgcmVuZGVyIHN0YXJ0c1xuICAgIC8vIChgY2F0Y2hVcGApOiB0aGUgZmlyc3QgcmVxdWVzdCBhZnRlciBhbiBpZGxlIG9yIGZyb3plbiBzcGVsbCB3b3VsZFxuICAgIC8vIG90aGVyd2lzZSBzZXJ2ZSB3aGF0ZXZlciB3YXMgcmV2YWxpZGF0ZWQgZWxzZXdoZXJlIG1lYW53aGlsZS4gQSBwYWdlJ3NcbiAgICAvLyByZW5kZXIganVzdCBhZnRlciBgY2F0Y2hVcGAgZ2V0cyBhIGdyYWNlIG1vcmUgKGBiZWhpbmRJblJlbmRlcmApLCBzbyBhXG4gICAgLy8gcmVxdWVzdCB0aGF0IGNhbWUgaW4ganVzdCBzaG9ydCBvZiB0aGUgbGluZSBkb2Vzbid0IGNyb3NzIGl0IGluc2lkZVxuICAgIC8vIHRoZSByZW5kZXIuIE5vdCBldmVuIHRoZW4gd2hpbGUgdGhlIGluc3RhbmNlIGhvbGRzIG5vIGVudHJ5IHRoZSBxdWVyeVxuICAgIC8vIGNvdWxkIGV4cGlyZSAoYGhvbGRzRW50cmllc2ApLCB3aXRoIGEgYHJlZnJlc2hJbnRlcnZhbE1zYCBvZiBgMGAgdG9vLlxuICAgIHJlZnJlc2hUYWdzOiAoKSA9PlxuICAgICAgYXdhaXRJZihcbiAgICAgICAgb3B0aW9ucy5ibG9ja2luZyA9PT0gdHJ1ZSB8fCAodGFncy5iZWhpbmRJblJlbmRlciAmJiB0YWdzLmhvbGRzRW50cmllcyksXG4gICAgICAgIHRhZ3MucmVmcmVzaCgpLFxuICAgICAgICBcIkVycm9yIHJlZnJlc2hpbmcgY2FjaGUgdGFnczpcIixcbiAgICAgICksXG4gICAgYXN5bmMgdXBkYXRlVGFncyhyZXZhbGlkYXRlZFRhZ3MsIGR1cmF0aW9ucykge1xuICAgICAgYXdhaXQgdGFncy51cGRhdGUocmV2YWxpZGF0ZWRUYWdzLCBkdXJhdGlvbnMpO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogUnVuIGEgY2FjaGUgaGFuZGxlciBtZXRob2QncyB3b3JrIG91dHNpZGUgdGhlIHJlcXVlc3QgdGhhdCBjYWxsZWQgaXRcbiAqICh7QGxpbmsgVHJhY2tlZFRhZ01hcmtlcnMub3V0c2lkZVJlbmRlcn0pLiBOZXh0LmpzIGF3YWl0cyB0aGVzZSBtZXRob2RzXG4gKiBpbnNpZGUgYSBzdGFnZWQgcmVuZGVyLCBhbmQgMTYuNCBlbmRzIHRoZSByZW5kZXIncyBzdGF0aWMgc3RhZ2Ugb24gYW55XG4gKiBgRGF0ZS5ub3coKWAsIGBuZXcgRGF0ZSgpYCwgYE1hdGgucmFuZG9tKClgIG9yIGBjcnlwdG9gIHJhbmRvbSBjYWxsIG1hZGUgaW5cbiAqIHRoZSByZXF1ZXN0J3MgY29udGV4dCBkdXJpbmcgaXQ6IG91cnMsIHRoZSBBV1MgU0RLJ3MgKHJlcXVlc3Qgc2lnbmluZyxcbiAqIGludm9jYXRpb24gaWRzKSBhbmQgYGRlYnVnYCdzIGFsaWtlLiBBIGRyYWZ0IG1vZGUgcGFnZSwgcmVuZGVyZWQgd2hvbGUgYXRcbiAqIHJlcXVlc3QgdGltZSwgbG9zdCBpdHMgc3RhdGljIHN0YWdlIHRoYXQgd2F5IHRvIGByZWZyZXNoVGFnc2AsIHNvIHRoZSBjbGllbnRcbiAqIGNhY2hlZCBub3RoaW5nIGZyb20gaXRzIEhUTUwuIENyZWF0aW5nIHRoZSBtYW5pZmVzdCBpcyBpbiBoZXJlIHRvbzogdGhlXG4gKiBmaXJzdCBoYW5kbGVyIGNhbGwgb2YgYSBwcm9jZXNzIGRvZXMgaXQsIGluc2lkZSBhIHJlbmRlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG91dHNpZGVSZW5kZXI8VD4oZm46ICgpID0+IFQpOiBUIHtcbiAgcmV0dXJuIG91dHNpZGVSZXF1ZXN0KHNoYXJlZFRhZ01hbmlmZXN0KS5vdXRzaWRlUmVuZGVyKGZuKTtcbn1cblxuLyoqXG4gKiBBIGhhbmRsZXIgYnVpbHQgYnkgYGNyZWF0ZWAgb24gZmlyc3QgdXNlIHJhdGhlciB0aGFuIG9uIGltcG9ydCwgc28gbG9hZGluZ1xuICogdGhlIG1vZHVsZSAtIHdoaWNoIGplc3QsIGFuZCBOZXh0LmpzJ3MgY29uZmlnIHZhbGlkYXRpb24sIGRvIHdpdGhvdXQgdXNpbmdcbiAqIGl0IC0gbmVpdGhlciBjb25zdHJ1Y3RzIEFXUyBjbGllbnRzIG5vciB3YXJucyBhYm91dCBtaXNzaW5nIGNvbmZpZ3VyYXRpb24uXG4gKiBFdmVyeSBtZXRob2QgcnVucyB7QGxpbmsgb3V0c2lkZVJlbmRlcn0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXp5SGFuZGxlcihjcmVhdGU6ICgpID0+IENhY2hlSGFuZGxlcik6IENhY2hlSGFuZGxlciB7XG4gIGxldCBoYW5kbGVyOiBDYWNoZUhhbmRsZXIgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IGluc3RhbmNlID0gKCkgPT4gKGhhbmRsZXIgPz89IGNyZWF0ZSgpKTtcbiAgcmV0dXJuIHtcbiAgICBnZXQ6IChjYWNoZUtleSwgc29mdFRhZ3MpID0+XG4gICAgICBvdXRzaWRlUmVuZGVyKCgpID0+IGluc3RhbmNlKCkuZ2V0KGNhY2hlS2V5LCBzb2Z0VGFncykpLFxuICAgIHNldDogKGNhY2hlS2V5LCBwZW5kaW5nRW50cnkpID0+XG4gICAgICBvdXRzaWRlUmVuZGVyKCgpID0+IGluc3RhbmNlKCkuc2V0KGNhY2hlS2V5LCBwZW5kaW5nRW50cnkpKSxcbiAgICByZWZyZXNoVGFnczogKCkgPT4gb3V0c2lkZVJlbmRlcigoKSA9PiBpbnN0YW5jZSgpLnJlZnJlc2hUYWdzKCkpLFxuICAgIGdldEV4cGlyYXRpb246ICh0YWdzKSA9PlxuICAgICAgb3V0c2lkZVJlbmRlcigoKSA9PiBpbnN0YW5jZSgpLmdldEV4cGlyYXRpb24odGFncykpLFxuICAgIHVwZGF0ZVRhZ3M6ICh0YWdzLCBkdXJhdGlvbnMpID0+XG4gICAgICBvdXRzaWRlUmVuZGVyKCgpID0+IGluc3RhbmNlKCkudXBkYXRlVGFncyh0YWdzLCBkdXJhdGlvbnMpKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBUaGUgcHJvY2VzcydzIG9uZSB7QGxpbmsgVHJhY2tlZFRhZ01hcmtlcnN9LCBmcm9tIHRoZSBlbnZpcm9ubWVudC5cbiAqXG4gKiBLZXB0IG9uIGBnbG9iYWxUaGlzYCBiZWNhdXNlIHRoZSBpbmNyZW1lbnRhbCBjYWNoZSBoYW5kbGVyIGFuZCB0aGUgYGRlZmF1bHRgXG4gKiBhbmQgYHJlbW90ZWAgaGFuZGxlcnMgYXJlIHNlcGFyYXRlIGJ1bmRsZXMgLSBzZXBhcmF0ZSBtb2R1bGUgaW5zdGFuY2VzIC0gYW5kXG4gKiBzaG91bGQgc2hhcmUgb25lIG1hbmlmZXN0OiBvbmUgcmVmcmVzaCByZWFkIGZvciBhbGwgb2YgdGhlbSwgYW5kIG9uZSBtYXJrZXJcbiAqIHdyaXRlIHBlciBgcmV2YWxpZGF0ZVRhZ2AuXG4gKlxuICogQXQgYnVpbGQgdGltZSB0aGVyZSBpcyBubyB0YWJsZSB0byByZWFkIChhbmQgbm8gY3JlZGVudGlhbHMgdG8gcmVhZCBpdFxuICogd2l0aCksIHNvIHRhZ3Mgc3RheSBsb2NhbCB0byB0aGUgcHJvY2VzcyB0aGVyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNoYXJlZFRhZ01hbmlmZXN0KCk6IFRyYWNrZWRUYWdNYXJrZXJzIHtcbiAgY29uc3QgZ2xvYmFsID0gZ2xvYmFsVGhpcyBhcyB7IFtUQUdfTUFOSUZFU1RfU1lNQk9MXT86IFRyYWNrZWRUYWdNYXJrZXJzIH07XG4gIGlmICghZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVzb2x2ZUF3c0NhY2hlQ29uZmlnKCk7XG4gICAgY29uc3QgcmVmcmVzaEludGVydmFsTXMgPSBudW1iZXJGcm9tRW52KFxuICAgICAgXCJDREtfTkVYVEpTX1RBR19SRUZSRVNIX01TXCIsXG4gICAgICBERUZBVUxUX1RBR19SRUZSRVNIX01TLFxuICAgICk7XG4gICAgaWYgKGNvbmZpZy50YWJsZU5hbWUgJiYgIWlzQnVpbGRQaGFzZSgpKSB7XG4gICAgICBjb25zdCBjbGllbnQgPSBuZXcgRHluYW1vREJDbGllbnQoe1xuICAgICAgICByZWdpb246IGNvbmZpZy5yZWdpb24sXG4gICAgICAgIC8vIFdpdGhvdXQgYHRocm93T25SZXF1ZXN0VGltZW91dGAgdGhlIHRpbWVvdXQgb25seSBsb2dzIGEgd2FybmluZy4gSXRcbiAgICAgICAgLy8gZW5kcyBvbmNlIHRoZSByZXNwb25zZSBoZWFkZXJzIGFycml2ZTogYHNvY2tldFRpbWVvdXRgLCBhblxuICAgICAgICAvLyBpbmFjdGl2aXR5IHRpbWVyIGtlcHQgdW50aWwgdGhlIHJlcXVlc3QgY2xvc2VzLCBjb3ZlcnMgdGhlIGJvZHkuXG4gICAgICAgIHJlcXVlc3RIYW5kbGVyOiB7XG4gICAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IFRBR19UQUJMRV9SRVFVRVNUX1RJTUVPVVRfTVMsXG4gICAgICAgICAgdGhyb3dPblJlcXVlc3RUaW1lb3V0OiB0cnVlLFxuICAgICAgICAgIHNvY2tldFRpbWVvdXQ6IFRBR19UQUJMRV9SRVFVRVNUX1RJTUVPVVRfTVMsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGdsb2JhbFtUQUdfTUFOSUZFU1RfU1lNQk9MXSA9IG5ldyBUcmFja2VkVGFnTWFya2Vycyh7XG4gICAgICAgIG1hcmtlcnM6IG5ldyBUYWdNYXJrZXJUYWJsZShjbGllbnQsIGNvbmZpZy50YWJsZU5hbWUsIGNvbmZpZy5idWlsZElkKSxcbiAgICAgICAgbG9nOiBuZXcgUmV2YWxpZGF0aW9uTG9nKGNsaWVudCwgY29uZmlnLnRhYmxlTmFtZSwgY29uZmlnLmJ1aWxkSWQpLFxuICAgICAgICByZWZyZXNoSW50ZXJ2YWxNcyxcbiAgICAgICAgZGVidWc6IGdldERlYnVnKFwiY2RrLW5leHRqczpjYWNoZS1oYW5kbGVyOnRhZ3NcIiksXG4gICAgICAgIC8vIFNldCBpbiBldmVyeSBMYW1iZGEgcnVudGltZTsgYSBjb250YWluZXIgaXMgbmV2ZXIgZnJvemVuLlxuICAgICAgICBjYW5GcmVlemU6IHByb2Nlc3MuZW52LkFXU19MQU1CREFfRlVOQ1RJT05fTkFNRSAhPT0gdW5kZWZpbmVkLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghaXNCdWlsZFBoYXNlKCkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIFwiQ0RLX05FWFRKU19SRVZBTElEQVRJT05fVEFCTEVfTkFNRSBlbnZpcm9ubWVudCB2YXJpYWJsZSBub3Qgc2V0LCBjYWNoZSB0YWdzIGFyZSBsb2NhbCB0byBlYWNoIGluc3RhbmNlXCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBnbG9iYWxbVEFHX01BTklGRVNUX1NZTUJPTF0gPSBuZXcgVHJhY2tlZFRhZ01hcmtlcnMoe1xuICAgICAgICByZWZyZXNoSW50ZXJ2YWxNcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdO1xufVxuIl19