@dbx-tools/shared-core 0.9.5 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,513 @@
1
+ /**
2
+ * Browser-safe string toolkit: tokenization, identifier / slug
3
+ * generation (with hash-suffix collision resistance), HTML escaping,
4
+ * header-value trimming, and a nested description-tree renderer for
5
+ * long-form LLM prompt / tool-description text. Depends only on the
6
+ * local {@link fnvHashWithOptions} for deterministic hash suffixes.
7
+ *
8
+ * @module
9
+ */
10
+ import { fnvHashWithOptions } from "./hash.js";
11
+ // A leading `v`/`V` immediately followed by digits (a version marker like
12
+ // `v2`) is kept as ONE token instead of splitting into `v` + `2`; it leads the
13
+ // alternation so it wins over the generic letter / digit runs. Everything else
14
+ // is the usual camelCase word / number / all-caps-acronym split.
15
+ const TOKENIZE_CAMEL_CASE_REGEXP = /[vV][0-9]+|[A-Z]?[a-z]+|[0-9]+|[A-Z]+(?![a-z])/g;
16
+ const TOKENIZE_NON_ALPHANUMERIC_REGEXP = /[a-zA-Z0-9]+/g;
17
+ const TOKENIZE_OVERRIDES = [
18
+ (token, options) => {
19
+ if (!options.capitalize)
20
+ return token;
21
+ const lower = token.toLowerCase();
22
+ if (lower === "ai")
23
+ return "AI";
24
+ if (lower === "fs")
25
+ return "FS";
26
+ return token;
27
+ },
28
+ // Version marker `v2` -> `V2` when capitalizing (the leading `v` uppercases,
29
+ // the digits stay), so it reads as one unit rather than "V 2".
30
+ (token, options) => {
31
+ if (options.capitalize && /^v[0-9]+$/.test(token)) {
32
+ return `V${token.slice(1)}`;
33
+ }
34
+ return token;
35
+ },
36
+ ];
37
+ const URI_REGEXP = /^([a-zA-Z][a-zA-Z0-9+.-]*)?:\/\/([^\s/?#][^\s]*)?$/;
38
+ const EMAIL_REGEXP = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+)@([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+)$/;
39
+ const TOKENIZE_DEFAULTS = {
40
+ distinct: false,
41
+ lowerCase: false,
42
+ capitalize: false,
43
+ omitUriScheme: false,
44
+ omitEmailDomain: false,
45
+ camelCase: true,
46
+ };
47
+ const IDENTIFIER_DEFAULTS = {
48
+ ...TOKENIZE_DEFAULTS,
49
+ lowerCase: true,
50
+ maxLength: Infinity,
51
+ truncateStrategy: "hash",
52
+ truncateHashLength: 6,
53
+ delimiter: "-",
54
+ };
55
+ export function* tokenizeWithOptions(options, ...values) {
56
+ const opts = { ...TOKENIZE_DEFAULTS, ...options };
57
+ const seen = opts.distinct ? new Set() : undefined;
58
+ const regexp = opts.camelCase ? TOKENIZE_CAMEL_CASE_REGEXP : TOKENIZE_NON_ALPHANUMERIC_REGEXP;
59
+ for (const value of values) {
60
+ if (value == null)
61
+ continue;
62
+ let stringValue = typeof value === "string" ? value : String(value);
63
+ if (!stringValue)
64
+ continue;
65
+ if (opts.omitUriScheme) {
66
+ const match = stringValue.match(URI_REGEXP);
67
+ if (match)
68
+ stringValue = match[2] ?? "";
69
+ }
70
+ if (opts.omitEmailDomain) {
71
+ const match = stringValue.match(EMAIL_REGEXP);
72
+ if (match)
73
+ stringValue = match[1] ?? "";
74
+ }
75
+ if (!stringValue)
76
+ continue;
77
+ for (const tokenMatch of stringValue.matchAll(regexp)) {
78
+ let token = tokenMatch[0];
79
+ if (opts.lowerCase)
80
+ token = token.toLowerCase();
81
+ if (opts.capitalize)
82
+ token = capitalize(token);
83
+ if (!token)
84
+ continue;
85
+ for (const override of TOKENIZE_OVERRIDES) {
86
+ token = override(token, opts);
87
+ if (!token)
88
+ break;
89
+ }
90
+ if (!token || seen?.has(token))
91
+ continue;
92
+ seen?.add(token);
93
+ yield token;
94
+ }
95
+ }
96
+ }
97
+ export function* tokenize(...values) {
98
+ yield* tokenizeWithOptions({}, ...values);
99
+ }
100
+ /**
101
+ * Join tokenized values with `delimiter`. When the next token would push the
102
+ * result over `maxLength`: `trim` stops adding; `empty` returns `""`; `hash`
103
+ * appends a digest of accepted tokens plus the overflow token if the result
104
+ * still fits, otherwise `""`.
105
+ */
106
+ export function toIdentifierWithOptions(options, ...values) {
107
+ const opts = {
108
+ ...IDENTIFIER_DEFAULTS,
109
+ ...options,
110
+ lowerCase: true,
111
+ };
112
+ const tokens = [];
113
+ let currentLength = 0;
114
+ for (const token of tokenizeWithOptions(opts, ...values)) {
115
+ const sepLength = tokens.length > 0 ? opts.delimiter.length : 0;
116
+ const nextLength = currentLength + sepLength + token.length;
117
+ if (nextLength > opts.maxLength) {
118
+ if (opts.truncateStrategy === "empty")
119
+ return "";
120
+ if (opts.truncateStrategy === "trim")
121
+ break;
122
+ const hash = digestTokens(opts.truncateHashLength, tokens, token);
123
+ if (currentLength + sepLength + hash.length <= opts.maxLength) {
124
+ return tokens.length > 0 ? tokens.join(opts.delimiter) + opts.delimiter + hash : hash;
125
+ }
126
+ return "";
127
+ }
128
+ tokens.push(token);
129
+ currentLength = nextLength;
130
+ }
131
+ return tokens.join(opts.delimiter);
132
+ }
133
+ export function toIdentifier(...values) {
134
+ return toIdentifierWithOptions({}, ...values);
135
+ }
136
+ /**
137
+ * Slugified identifier: same rules as {@link toIdentifierWithOptions} with the
138
+ * delimiter forced to `-`. Accepts {@link KeyOptions} so callers cannot
139
+ * override the delimiter.
140
+ */
141
+ export function toSlugWithOptions(options, ...values) {
142
+ return toIdentifierWithOptions({ ...options, delimiter: "-" }, ...values);
143
+ }
144
+ export function toSlug(...values) {
145
+ return toSlugWithOptions({}, ...values);
146
+ }
147
+ /**
148
+ * Trim `value` and return `null` for non-strings, `undefined`, or
149
+ * strings that are empty after trimming. Lets call sites collapse the
150
+ * common
151
+ *
152
+ * ```ts
153
+ * typeof v === "string" && v.trim() ? v.trim() : null
154
+ * ```
155
+ *
156
+ * dance into a single helper. Useful for HTTP header / query / form
157
+ * extractors where downstream code wants `string | null` to drive a
158
+ * cheap `??` / `if (x)` cascade.
159
+ */
160
+ export function trimToNull(value) {
161
+ if (typeof value !== "string")
162
+ return null;
163
+ const trimmed = value.trim();
164
+ return trimmed ? trimmed : null;
165
+ }
166
+ // Config lists arrive either already split (an array) or as one env-var string
167
+ // with entries separated by commas and/or whitespace.
168
+ const LIST_SEPARATOR_REGEXP = /[\s,]+/;
169
+ /**
170
+ * Normalize a config list that may arrive as an array or as a single
171
+ * comma/whitespace-separated string: split, apply `transform`, drop empties,
172
+ * and de-duplicate (first occurrence wins).
173
+ *
174
+ * This is the shape every allow-list / fallback-order setting in this repo
175
+ * takes, because the same value can come from typed config (`string[]`) or from
176
+ * an environment variable (`"a, b c"`). Pass `transform` to normalize entries
177
+ * as they are read; it defaults to trimming.
178
+ *
179
+ * @example
180
+ * parseList("docs.example.com, *.databricks.com");
181
+ * parseList(process.env.MODEL_FALLBACKS);
182
+ * parseList(raw, normalizeUrlPattern);
183
+ */
184
+ export function parseList(raw, transform = (entry) => entry.trim()) {
185
+ const entries = typeof raw === "string" ? raw.split(LIST_SEPARATOR_REGEXP) : Array.isArray(raw) ? raw : [];
186
+ const out = [];
187
+ const seen = new Set();
188
+ for (const entry of entries) {
189
+ const normalized = transform(entry);
190
+ if (!normalized || seen.has(normalized))
191
+ continue;
192
+ seen.add(normalized);
193
+ out.push(normalized);
194
+ }
195
+ return out;
196
+ }
197
+ /**
198
+ * {@link trimToNull} with an empty-string miss instead of `null`, for callers
199
+ * that build a string unconditionally and treat "absent" as "".
200
+ *
201
+ * Reading loosely-typed JSON is the motivating case: a field that should be a
202
+ * string may be missing or the wrong type, and the caller wants `""` rather
203
+ * than a null check at every access.
204
+ *
205
+ * @example
206
+ * const title = trimToEmpty(record.title); // always a string
207
+ */
208
+ export function trimToEmpty(value) {
209
+ return trimToNull(value) ?? "";
210
+ }
211
+ /**
212
+ * Trim the first usable string out of `value`. Returns `null` when
213
+ * `value` is `undefined`, `null`, an empty string, or an array whose
214
+ * first string member is empty. Mirrors how Express / Node header
215
+ * accessors expose single vs. repeated headers - the first
216
+ * non-empty entry wins, everything else is ignored.
217
+ */
218
+ export function firstNonEmpty(value) {
219
+ if (Array.isArray(value)) {
220
+ for (const item of value) {
221
+ const trimmed = trimToNull(item);
222
+ if (trimmed)
223
+ return trimmed;
224
+ }
225
+ return null;
226
+ }
227
+ return trimToNull(value);
228
+ }
229
+ /**
230
+ * Escape the five characters significant in HTML text and
231
+ * double-quoted attribute values (`&`, `<`, `>`, `"`, `'`) so an
232
+ * untrusted string can be interpolated into markup without breaking
233
+ * out of its context. `&` is replaced first so ampersands introduced
234
+ * by the later replacements aren't double-escaped.
235
+ */
236
+ export function escapeHtml(value) {
237
+ return value
238
+ .replace(/&/g, "&amp;")
239
+ .replace(/</g, "&lt;")
240
+ .replace(/>/g, "&gt;")
241
+ .replace(/"/g, "&quot;")
242
+ .replace(/'/g, "&#39;");
243
+ }
244
+ /**
245
+ * Slugify `value` (using the standard {@link toIdentifierWithOptions}
246
+ * tokenizer + delimiter rules) and **always** suffix a short
247
+ * deterministic hash. Use when you need a stable, slugified id that
248
+ * is guaranteed to be unique across descriptions sharing the same
249
+ * leading tokens (tool ids, cache keys, etc.).
250
+ *
251
+ * Behaviour differs from `toIdentifierWithOptions({ maxLength,
252
+ * truncateStrategy: "hash" })`: that helper only appends a hash when
253
+ * the slug *overflows* `maxLength`. This helper appends a hash
254
+ * unconditionally so the result is collision-resistant even for
255
+ * short inputs. The hash is computed over the raw `value` so two
256
+ * descriptions producing the same slug still get different ids.
257
+ *
258
+ * @param value - Source string (typically a tool/agent description).
259
+ * @param options.delimiter - Token separator (default `"_"`).
260
+ * @param options.slugMaxLength - Cap on the slug portion (the part
261
+ * before the hash). Default 32.
262
+ * @param options.hashLength - Length of the suffix produced by
263
+ * {@link fnvHashWithOptions} (Crockford-style base-32 alphabet, max 7
264
+ * chars). Default 6.
265
+ * @param options.fallbackPrefix - Prefix used when the slug is empty
266
+ * (e.g. punctuation-only input). Default `"id"`.
267
+ */
268
+ export function toUniqueSlug(value, options = {}) {
269
+ const delimiter = options.delimiter ?? "_";
270
+ const slugMaxLength = options.slugMaxLength ?? 32;
271
+ const hashLength = options.hashLength ?? 6;
272
+ const fallbackPrefix = options.fallbackPrefix ?? "id";
273
+ const slug = toIdentifierWithOptions({ delimiter, maxLength: slugMaxLength, truncateStrategy: "trim" }, value);
274
+ const suffix = fnvHashWithOptions({ length: hashLength }, value);
275
+ return slug ? `${slug}${delimiter}${suffix}` : `${fallbackPrefix}${delimiter}${suffix}`;
276
+ }
277
+ function digestTokens(length, parts, extra) {
278
+ let combined = "";
279
+ for (const part of parts)
280
+ combined += part + "\0";
281
+ if (extra !== undefined)
282
+ combined += extra + "\0";
283
+ return fnvHashWithOptions({ length }, combined);
284
+ }
285
+ const LIST_KEYS = ["bullets", "numbered"];
286
+ /**
287
+ * Format a nested description tree as a Markdown-ish string suitable
288
+ * for an LLM system prompt, Zod `.describe()` block, Mastra tool
289
+ * description, or any other long-form text destination.
290
+ *
291
+ * Every string section is dedented (common leading whitespace stripped),
292
+ * right-trimmed line by line, and freed of leading / trailing blank
293
+ * lines, so callers can write multi-line template literals indented
294
+ * naturally in source without leaking that indentation into the
295
+ * consumer-facing output. Plain-string inputs flow through unchanged
296
+ * apart from the same normalization pass, so a single multi-line
297
+ * template literal works directly:
298
+ *
299
+ * ```ts
300
+ * toDescription(`
301
+ * Ask the Genie space "${alias}" a question.
302
+ * Pass the answer through as-is.
303
+ * `);
304
+ * // Ask the Genie space "default" a question.
305
+ * // Pass the answer through as-is.
306
+ *
307
+ * toDescription([
308
+ * `
309
+ * Ask the Genie space a question.
310
+ * Phrase it from the user's perspective.
311
+ * `,
312
+ * { bullets: [
313
+ * ["Pass the answer through as-is", { numbered: ["item", "item"] }],
314
+ * ]},
315
+ * { Instructions: "Reply with the SQL only." },
316
+ * ]);
317
+ * // Ask the Genie space a question.
318
+ * // Phrase it from the user's perspective.
319
+ * // - Pass the answer through as-is
320
+ * // 1. item
321
+ * // 2. item
322
+ * //
323
+ * // Instructions:
324
+ * //
325
+ * // Reply with the SQL only.
326
+ * ```
327
+ *
328
+ * See {@link Description} for the node grammar.
329
+ */
330
+ export function toDescription(node) {
331
+ return renderBlock(node, "")
332
+ .replace(/[ \t]+$/gm, "")
333
+ .replace(/\n+$/, "");
334
+ }
335
+ function renderBlock(node, pad) {
336
+ if (node == null)
337
+ return "";
338
+ if (typeof node === "string")
339
+ return prependPad(dedentSection(node), pad);
340
+ if (Array.isArray(node))
341
+ return renderSequence(node, pad);
342
+ const kind = listKind(node);
343
+ if (kind) {
344
+ return renderList(node[kind], pad, kind);
345
+ }
346
+ return renderMap(node, pad);
347
+ }
348
+ /**
349
+ * Normalize a string section: right-strip every line, drop the
350
+ * common leading-whitespace prefix shared by all non-blank lines,
351
+ * and trim leading / trailing blank lines. Matches Python's
352
+ * `textwrap.dedent` semantics so embedded indented template
353
+ * literals round-trip cleanly.
354
+ */
355
+ function dedentSection(text) {
356
+ if (!text)
357
+ return "";
358
+ const lines = text.split("\n").map((line) => line.replace(/[ \t]+$/, ""));
359
+ let min = Infinity;
360
+ for (const line of lines) {
361
+ if (!line)
362
+ continue;
363
+ const match = /^[ \t]*/.exec(line);
364
+ const width = match ? match[0].length : 0;
365
+ if (width < min)
366
+ min = width;
367
+ }
368
+ const stripped = min === Infinity || min === 0 ? lines : lines.map((line) => (line ? line.slice(min) : ""));
369
+ let start = 0;
370
+ let end = stripped.length;
371
+ while (start < end && !stripped[start])
372
+ start += 1;
373
+ while (end > start && !stripped[end - 1])
374
+ end -= 1;
375
+ return stripped.slice(start, end).join("\n");
376
+ }
377
+ /**
378
+ * An object is treated as a typed list only when it has exactly one
379
+ * own key, that key is `bullets` or `numbered`, and the value is an
380
+ * array. Everything else is a headers map - so callers wanting a
381
+ * single header literally named `bullets` or `numbered` can use a
382
+ * multi-key map or rename.
383
+ */
384
+ function listKind(node) {
385
+ const keys = Object.keys(node);
386
+ if (keys.length !== 1)
387
+ return null;
388
+ const key = keys[0];
389
+ if (LIST_KEYS.includes(key) && Array.isArray(node[key])) {
390
+ return key;
391
+ }
392
+ return null;
393
+ }
394
+ function prependPad(text, pad) {
395
+ if (!text)
396
+ return "";
397
+ if (!pad)
398
+ return text;
399
+ return text
400
+ .split("\n")
401
+ .map((line) => (line ? pad + line : ""))
402
+ .join("\n");
403
+ }
404
+ function renderSequence(items, pad) {
405
+ const rendered = [];
406
+ for (const item of items) {
407
+ const text = renderBlock(item, pad);
408
+ if (!text)
409
+ continue;
410
+ rendered.push({ text, node: item });
411
+ }
412
+ if (rendered.length === 0)
413
+ return "";
414
+ let out = rendered[0].text;
415
+ for (let i = 1; i < rendered.length; i += 1) {
416
+ const sep = needsBlankLineBetween(rendered[i - 1].node, rendered[i].node) ? "\n\n" : "\n";
417
+ out += sep + rendered[i].text;
418
+ }
419
+ return out;
420
+ }
421
+ /**
422
+ * Maps always create their own section boundary (a `Header:` line plus
423
+ * a blank line before the body), so anything touching a map gets a
424
+ * blank-line break. Plain text adjacent to a typed list flushes
425
+ * together in either direction: text-before-list reads as a lead-in,
426
+ * text-after-list as a trailing summary. Two text paragraphs and two
427
+ * adjacent lists both get a blank-line break for legibility.
428
+ */
429
+ function needsBlankLineBetween(prev, curr) {
430
+ if (isMap(prev) || isMap(curr))
431
+ return true;
432
+ const prevIsText = typeof prev === "string";
433
+ const currIsText = typeof curr === "string";
434
+ if (prevIsText !== currIsText)
435
+ return false;
436
+ return true;
437
+ }
438
+ /**
439
+ * A node is a headers map when it is a non-array, non-list object.
440
+ * `bullets` / `numbered` single-key objects are the only structured
441
+ * objects that aren't maps.
442
+ */
443
+ function isMap(node) {
444
+ if (node == null)
445
+ return false;
446
+ if (typeof node === "string")
447
+ return false;
448
+ if (Array.isArray(node))
449
+ return false;
450
+ return listKind(node) === null;
451
+ }
452
+ function renderList(items, pad, kind) {
453
+ if (items.length === 0)
454
+ return "";
455
+ if (items.length === 1 && typeof items[0] === "string") {
456
+ return prependPad(items[0], pad);
457
+ }
458
+ const lines = [];
459
+ for (let i = 0; i < items.length; i += 1) {
460
+ const item = items[i];
461
+ const marker = kind === "bullets" ? "- " : `${i + 1}. `;
462
+ const body = renderBlock(item, "");
463
+ const bodyLines = body.split("\n");
464
+ lines.push(`${pad}${marker}${bodyLines[0] ?? ""}`);
465
+ const continuation = pad + " ".repeat(marker.length);
466
+ for (const line of bodyLines.slice(1)) {
467
+ lines.push(line ? `${continuation}${line}` : "");
468
+ }
469
+ }
470
+ return lines.join("\n");
471
+ }
472
+ function renderMap(node, pad) {
473
+ const parts = [];
474
+ for (const [header, value] of Object.entries(node)) {
475
+ const body = renderBlock(value, pad);
476
+ if (!body && !header.trim())
477
+ continue;
478
+ const headerLine = header.trim() ? `${pad}${header}:` : "";
479
+ parts.push(body ? `${headerLine}\n\n${body}` : headerLine);
480
+ }
481
+ return parts.join("\n\n");
482
+ }
483
+ /**
484
+ * Format a count with its noun, pluralizing (naive `+s`) unless the count is 1:
485
+ * `pluralize(1, "barrel")` -> `"1 barrel"`, `pluralize(3, "barrel")` ->
486
+ * `"3 barrels"`. Collapses the `${n} noun${n === 1 ? "" : "s"}` idiom.
487
+ */
488
+ export function pluralize(count, noun) {
489
+ return `${count} ${noun}${count === 1 ? "" : "s"}`;
490
+ }
491
+ /**
492
+ * Title-case a snake / kebab / camel identifier into a human-readable label:
493
+ * tokenize (lowercased, capitalized), then join with spaces. Falls back to
494
+ * the raw `value` when it yields no tokens (e.g. punctuation-only input).
495
+ * `bge_large_en` -> `"Bge Large En"`, `promptId` -> `"Prompt Id"`.
496
+ *
497
+ * The single source of truth for the "humanize a column / field name" idiom -
498
+ * reused by the chat data-grid headers and the export renderer. Extra
499
+ * {@link TokenizeOptions} (e.g. `camelCase: false`) merge over the defaults.
500
+ */
501
+ export function toLabel(value, options) {
502
+ const tokens = [...tokenizeWithOptions({ lowerCase: true, capitalize: true, ...options }, value)];
503
+ return tokens.length > 0 ? tokens.join(" ") : value;
504
+ }
505
+ /**
506
+ * Upper-case the first character of `value`, leaving the rest untouched.
507
+ * `"working"` -> `"Working"`. Collapses the
508
+ * `s.charAt(0).toUpperCase() + s.slice(1)` idiom.
509
+ */
510
+ export function capitalize(value) {
511
+ return value ? value.charAt(0).toUpperCase() + value.slice(1) : value;
512
+ }
513
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaW5nLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmluZy11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUNILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQTZDL0MsMEVBQTBFO0FBQzFFLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0UsaUVBQWlFO0FBQ2pFLE1BQU0sMEJBQTBCLEdBQUcsaURBQWlELENBQUM7QUFDckYsTUFBTSxnQ0FBZ0MsR0FBRyxlQUFlLENBQUM7QUFDekQsTUFBTSxrQkFBa0IsR0FBNEQ7SUFDbEYsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDakIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDdEMsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2xDLElBQUksS0FBSyxLQUFLLElBQUk7WUFBRSxPQUFPLElBQUksQ0FBQztRQUNoQyxJQUFJLEtBQUssS0FBSyxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDaEMsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsNkVBQTZFO0lBQzdFLCtEQUErRDtJQUMvRCxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUNqQixJQUFJLE9BQU8sQ0FBQyxVQUFVLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2xELE9BQU8sSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGLENBQUM7QUFDRixNQUFNLFVBQVUsR0FBRyxvREFBb0QsQ0FBQztBQUN4RSxNQUFNLFlBQVksR0FBRywwRUFBMEUsQ0FBQztBQUVoRyxNQUFNLGlCQUFpQixHQUE0QjtJQUNqRCxRQUFRLEVBQUUsS0FBSztJQUNmLFNBQVMsRUFBRSxLQUFLO0lBQ2hCLFVBQVUsRUFBRSxLQUFLO0lBQ2pCLGFBQWEsRUFBRSxLQUFLO0lBQ3BCLGVBQWUsRUFBRSxLQUFLO0lBQ3RCLFNBQVMsRUFBRSxJQUFJO0NBQ2hCLENBQUM7QUFFRixNQUFNLG1CQUFtQixHQUE4QjtJQUNyRCxHQUFHLGlCQUFpQjtJQUNwQixTQUFTLEVBQUUsSUFBSTtJQUNmLFNBQVMsRUFBRSxRQUFRO0lBQ25CLGdCQUFnQixFQUFFLE1BQU07SUFDeEIsa0JBQWtCLEVBQUUsQ0FBQztJQUNyQixTQUFTLEVBQUUsR0FBRztDQUNmLENBQUM7QUFFRixNQUFNLFNBQVMsQ0FBQyxDQUFDLG1CQUFtQixDQUNsQyxPQUF3QixFQUN4QixHQUFHLE1BQWlCO0lBRXBCLE1BQU0sSUFBSSxHQUE0QixFQUFFLEdBQUcsaUJBQWlCLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQztJQUMzRSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsRUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDM0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsMEJBQTBCLENBQUMsQ0FBQyxDQUFDLGdDQUFnQyxDQUFDO0lBRTlGLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7UUFDM0IsSUFBSSxLQUFLLElBQUksSUFBSTtZQUFFLFNBQVM7UUFDNUIsSUFBSSxXQUFXLEdBQUcsT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsV0FBVztZQUFFLFNBQVM7UUFDM0IsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUM1QyxJQUFJLEtBQUs7Z0JBQUUsV0FBVyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDMUMsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDOUMsSUFBSSxLQUFLO2dCQUFFLFdBQVcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzFDLENBQUM7UUFDRCxJQUFJLENBQUMsV0FBVztZQUFFLFNBQVM7UUFDM0IsS0FBSyxNQUFNLFVBQVUsSUFBSSxXQUFXLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDdEQsSUFBSSxLQUFLLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBRSxDQUFDO1lBQzNCLElBQUksSUFBSSxDQUFDLFNBQVM7Z0JBQUUsS0FBSyxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNoRCxJQUFJLElBQUksQ0FBQyxVQUFVO2dCQUFFLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLEtBQUs7Z0JBQUUsU0FBUztZQUNyQixLQUFLLE1BQU0sUUFBUSxJQUFJLGtCQUFrQixFQUFFLENBQUM7Z0JBQzFDLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUM5QixJQUFJLENBQUMsS0FBSztvQkFBRSxNQUFNO1lBQ3BCLENBQUM7WUFDRCxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDO2dCQUFFLFNBQVM7WUFDekMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNqQixNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsTUFBaUI7SUFDNUMsS0FBSyxDQUFDLENBQUMsbUJBQW1CLENBQUMsRUFBRSxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDNUMsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLE9BQTBCLEVBQUUsR0FBRyxNQUFpQjtJQUN0RixNQUFNLElBQUksR0FBOEI7UUFDdEMsR0FBRyxtQkFBbUI7UUFDdEIsR0FBRyxPQUFPO1FBQ1YsU0FBUyxFQUFFLElBQUk7S0FDaEIsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixJQUFJLGFBQWEsR0FBRyxDQUFDLENBQUM7SUFFdEIsS0FBSyxNQUFNLEtBQUssSUFBSSxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ3pELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sVUFBVSxHQUFHLGFBQWEsR0FBRyxTQUFTLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUU1RCxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDaEMsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEtBQUssT0FBTztnQkFBRSxPQUFPLEVBQUUsQ0FBQztZQUNqRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsS0FBSyxNQUFNO2dCQUFFLE1BQU07WUFFNUMsTUFBTSxJQUFJLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDbEUsSUFBSSxhQUFhLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUM5RCxPQUFPLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3hGLENBQUM7WUFDRCxPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7UUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25CLGFBQWEsR0FBRyxVQUFVLENBQUM7SUFDN0IsQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDckMsQ0FBQztBQUVELE1BQU0sVUFBVSxZQUFZLENBQUMsR0FBRyxNQUFpQjtJQUMvQyxPQUFPLHVCQUF1QixDQUFDLEVBQUUsRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLE9BQW1CLEVBQUUsR0FBRyxNQUFpQjtJQUN6RSxPQUFPLHVCQUF1QixDQUFDLEVBQUUsR0FBRyxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDNUUsQ0FBQztBQUVELE1BQU0sVUFBVSxNQUFNLENBQUMsR0FBRyxNQUFpQjtJQUN6QyxPQUFPLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFDO0FBQzFDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLEtBQWM7SUFDdkMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDM0MsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzdCLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNsQyxDQUFDO0FBRUQsK0VBQStFO0FBQy9FLHNEQUFzRDtBQUN0RCxNQUFNLHFCQUFxQixHQUFHLFFBQVEsQ0FBQztBQUV2Qzs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQ3ZCLEdBQWtELEVBQ2xELFlBQXVDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFO0lBRTlELE1BQU0sT0FBTyxHQUNYLE9BQU8sR0FBRyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM3RixNQUFNLEdBQUcsR0FBYSxFQUFFLENBQUM7SUFDekIsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUMvQixLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzVCLE1BQU0sVUFBVSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1lBQUUsU0FBUztRQUNsRCxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JCLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkIsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLEtBQWM7SUFDeEMsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ2pDLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLEtBQWM7SUFDMUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDekIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakMsSUFBSSxPQUFPO2dCQUFFLE9BQU8sT0FBTyxDQUFDO1FBQzlCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxLQUFhO0lBQ3RDLE9BQU8sS0FBSztTQUNULE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDO1NBQ3RCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO1NBQ3JCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO1NBQ3JCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDO1NBQ3ZCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVCRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQzFCLEtBQWEsRUFDYixVQUtJLEVBQUU7SUFFTixNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLEdBQUcsQ0FBQztJQUMzQyxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztJQUNsRCxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQztJQUMzQyxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQztJQUN0RCxNQUFNLElBQUksR0FBRyx1QkFBdUIsQ0FDbEMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsRUFDakUsS0FBSyxDQUNOLENBQUM7SUFDRixNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNqRSxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLEdBQUcsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLGNBQWMsR0FBRyxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUM7QUFDMUYsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLE1BQWMsRUFBRSxLQUF3QixFQUFFLEtBQWM7SUFDNUUsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSztRQUFFLFFBQVEsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ2xELElBQUksS0FBSyxLQUFLLFNBQVM7UUFBRSxRQUFRLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQztJQUNsRCxPQUFPLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDbEQsQ0FBQztBQW9CRCxNQUFNLFNBQVMsR0FBRyxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQVUsQ0FBQztBQUduRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJDRztBQUNILE1BQU0sVUFBVSxhQUFhLENBQUMsSUFBaUI7SUFDN0MsT0FBTyxXQUFXLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztTQUN6QixPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztTQUN4QixPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3pCLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxJQUFpQixFQUFFLEdBQVc7SUFDakQsSUFBSSxJQUFJLElBQUksSUFBSTtRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzVCLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUTtRQUFFLE9BQU8sVUFBVSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMxRSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQUUsT0FBTyxjQUFjLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzFELE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUErQixDQUFDLENBQUM7SUFDdkQsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNULE9BQU8sVUFBVSxDQUFFLElBQWlELENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQyxJQUFtQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzdELENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLGFBQWEsQ0FBQyxJQUFZO0lBQ2pDLElBQUksQ0FBQyxJQUFJO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDckIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDMUUsSUFBSSxHQUFHLEdBQUcsUUFBUSxDQUFDO0lBQ25CLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUk7WUFBRSxTQUFTO1FBQ3BCLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkMsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUMsSUFBSSxLQUFLLEdBQUcsR0FBRztZQUFFLEdBQUcsR0FBRyxLQUFLLENBQUM7SUFDL0IsQ0FBQztJQUNELE1BQU0sUUFBUSxHQUNaLEdBQUcsS0FBSyxRQUFRLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3RixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxJQUFJLEdBQUcsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO0lBQzFCLE9BQU8sS0FBSyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7UUFBRSxLQUFLLElBQUksQ0FBQyxDQUFDO0lBQ25ELE9BQU8sR0FBRyxHQUFHLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNuRCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMvQyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxRQUFRLENBQUMsSUFBNkI7SUFDN0MsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ25DLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUUsQ0FBQztJQUNyQixJQUFLLFNBQStCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMvRSxPQUFPLEdBQWUsQ0FBQztJQUN6QixDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsSUFBWSxFQUFFLEdBQVc7SUFDM0MsSUFBSSxDQUFDLElBQUk7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNyQixJQUFJLENBQUMsR0FBRztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3RCLE9BQU8sSUFBSTtTQUNSLEtBQUssQ0FBQyxJQUFJLENBQUM7U0FDWCxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUN2QyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDaEIsQ0FBQztBQUVELFNBQVMsY0FBYyxDQUFDLEtBQTZCLEVBQUUsR0FBVztJQUNoRSxNQUFNLFFBQVEsR0FBMEMsRUFBRSxDQUFDO0lBQzNELEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsSUFBSTtZQUFFLFNBQVM7UUFDcEIsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNyQyxJQUFJLEdBQUcsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFFLENBQUMsSUFBSSxDQUFDO0lBQzVCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUM1QyxNQUFNLEdBQUcsR0FBRyxxQkFBcUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBRSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQzVGLEdBQUcsSUFBSSxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBRSxDQUFDLElBQUksQ0FBQztJQUNqQyxDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQVMscUJBQXFCLENBQUMsSUFBaUIsRUFBRSxJQUFpQjtJQUNqRSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDNUMsTUFBTSxVQUFVLEdBQUcsT0FBTyxJQUFJLEtBQUssUUFBUSxDQUFDO0lBQzVDLE1BQU0sVUFBVSxHQUFHLE9BQU8sSUFBSSxLQUFLLFFBQVEsQ0FBQztJQUM1QyxJQUFJLFVBQVUsS0FBSyxVQUFVO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDNUMsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsS0FBSyxDQUFDLElBQWlCO0lBQzlCLElBQUksSUFBSSxJQUFJLElBQUk7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMvQixJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVE7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMzQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDdEMsT0FBTyxRQUFRLENBQUMsSUFBK0IsQ0FBQyxLQUFLLElBQUksQ0FBQztBQUM1RCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBNkIsRUFBRSxHQUFXLEVBQUUsSUFBYztJQUM1RSxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ2xDLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdkQsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBYSxFQUFFLENBQUM7SUFDM0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUUsQ0FBQztRQUN2QixNQUFNLE1BQU0sR0FBRyxJQUFJLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ3hELE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDbkMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNuRCxNQUFNLFlBQVksR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckQsS0FBSyxNQUFNLElBQUksSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDdEMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsWUFBWSxHQUFHLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNuRCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMxQixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsSUFBaUMsRUFBRSxHQUFXO0lBQy9ELE1BQU0sS0FBSyxHQUFhLEVBQUUsQ0FBQztJQUMzQixLQUFLLE1BQU0sQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ25ELE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7WUFBRSxTQUFTO1FBQ3RDLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMzRCxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLE9BQU8sSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEtBQWEsRUFBRSxJQUFZO0lBQ25ELE9BQU8sR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDckQsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sVUFBVSxPQUFPLENBQUMsS0FBYSxFQUFFLE9BQXlCO0lBQzlELE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDbEcsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0FBQ3RELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxLQUFhO0lBQ3RDLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUN4RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCcm93c2VyLXNhZmUgc3RyaW5nIHRvb2xraXQ6IHRva2VuaXphdGlvbiwgaWRlbnRpZmllciAvIHNsdWdcbiAqIGdlbmVyYXRpb24gKHdpdGggaGFzaC1zdWZmaXggY29sbGlzaW9uIHJlc2lzdGFuY2UpLCBIVE1MIGVzY2FwaW5nLFxuICogaGVhZGVyLXZhbHVlIHRyaW1taW5nLCBhbmQgYSBuZXN0ZWQgZGVzY3JpcHRpb24tdHJlZSByZW5kZXJlciBmb3JcbiAqIGxvbmctZm9ybSBMTE0gcHJvbXB0IC8gdG9vbC1kZXNjcmlwdGlvbiB0ZXh0LiBEZXBlbmRzIG9ubHkgb24gdGhlXG4gKiBsb2NhbCB7QGxpbmsgZm52SGFzaFdpdGhPcHRpb25zfSBmb3IgZGV0ZXJtaW5pc3RpYyBoYXNoIHN1ZmZpeGVzLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgZm52SGFzaFdpdGhPcHRpb25zIH0gZnJvbSBcIi4vaGFzaC50c1wiO1xuXG4vKipcbiAqIE9wdGlvbnMgY29udHJvbGxpbmcge0BsaW5rIHRva2VuaXplV2l0aE9wdGlvbnN9LiBBbGwgZGVmYXVsdCBvZmYgZXhjZXB0XG4gKiBgY2FtZWxDYXNlYC5cbiAqXG4gKiAtIGBkaXN0aW5jdGAgLSBkcm9wIGR1cGxpY2F0ZSB0b2tlbnMgKGZpcnN0IG9jY3VycmVuY2Ugd2lucykuXG4gKiAtIGBsb3dlckNhc2VgIC0gbG93ZXJjYXNlIGV2ZXJ5IHRva2VuLlxuICogLSBgY2FwaXRhbGl6ZWAgLSB1cHBlci1jYXNlIGVhY2ggdG9rZW4ncyBmaXJzdCBsZXR0ZXIgKHRoZW5cbiAqICAge0BsaW5rIFRPS0VOSVpFX09WRVJSSURFU30gZml4IHVwIGBhaWAgLT4gYEFJYCwgYGZzYCAtPiBgRlNgLCBhbmRcbiAqICAgYHYyYCAtPiBgVjJgKS5cbiAqIC0gYG9taXRVcmlTY2hlbWVgIC0gc3RyaXAgYSBsZWFkaW5nIGBzY2hlbWU6Ly9gIGJlZm9yZSB0b2tlbml6aW5nLlxuICogLSBgb21pdEVtYWlsRG9tYWluYCAtIGtlZXAgb25seSB0aGUgbG9jYWwgcGFydCBvZiBhbiBlbWFpbC5cbiAqIC0gYGNhbWVsQ2FzZWAgLSBzcGxpdCBvbiBjYW1lbENhc2UgYm91bmRhcmllcyAvIGRpZ2l0IHJ1bnMgLyBhY3Jvbnltc1xuICogICAoZGVmYXVsdCBgdHJ1ZWApOyB3aGVuIGBmYWxzZWAsIHNwbGl0IG9ubHkgb24gbm9uLWFscGhhbnVtZXJpY3MuXG4gKi9cbmV4cG9ydCB0eXBlIFRva2VuaXplT3B0aW9ucyA9IHtcbiAgZGlzdGluY3Q/OiBib29sZWFuO1xuICBsb3dlckNhc2U/OiBib29sZWFuO1xuICBjYXBpdGFsaXplPzogYm9vbGVhbjtcbiAgb21pdFVyaVNjaGVtZT86IGJvb2xlYW47XG4gIG9taXRFbWFpbERvbWFpbj86IGJvb2xlYW47XG4gIGNhbWVsQ2FzZT86IGJvb2xlYW47XG59O1xuXG4vKipcbiAqIFRva2VuaXphdGlvbiBhbmQgb3ZlcmZsb3cgY29udHJvbHMgZm9yIGxvd2VyY2FzZSBrZXlzIGFuZCBzbHVncy4gVGhlIGRlZmF1bHRcbiAqIGxlbmd0aCBpcyB1bmxpbWl0ZWQ7IG92ZXJmbG93IHVzZXMgYSBzaXgtY2hhcmFjdGVyIGhhc2ggdW5sZXNzIG92ZXJyaWRkZW4uXG4gKi9cbmV4cG9ydCB0eXBlIEtleU9wdGlvbnMgPSBPbWl0PFRva2VuaXplT3B0aW9ucywgXCJsb3dlckNhc2VcIiB8IFwiY2FwaXRhbGl6ZVwiPiAmIHtcbiAgbWF4TGVuZ3RoPzogbnVtYmVyO1xuICB0cnVuY2F0ZVN0cmF0ZWd5PzogXCJoYXNoXCIgfCBcInRyaW1cIiB8IFwiZW1wdHlcIjtcbiAgdHJ1bmNhdGVIYXNoTGVuZ3RoPzogbnVtYmVyO1xufTtcblxuLyoqIHtAbGluayBLZXlPcHRpb25zfSBwbHVzIHRoZSB0b2tlbiBkZWxpbWl0ZXIgdXNlZCBieSBpZGVudGlmaWVyIGdlbmVyYXRpb24uICovXG5leHBvcnQgdHlwZSBJZGVudGlmaWVyT3B0aW9ucyA9IEtleU9wdGlvbnMgJiB7XG4gIGRlbGltaXRlcj86IHN0cmluZztcbn07XG5cbnR5cGUgUmVzb2x2ZWRUb2tlbml6ZU9wdGlvbnMgPSBSZXF1aXJlZDxUb2tlbml6ZU9wdGlvbnM+O1xudHlwZSBSZXNvbHZlZElkZW50aWZpZXJPcHRpb25zID0gUmVxdWlyZWQ8XG4gIElkZW50aWZpZXJPcHRpb25zICYgUGljazxUb2tlbml6ZU9wdGlvbnMsIFwibG93ZXJDYXNlXCIgfCBcImNhcGl0YWxpemVcIj5cbj47XG5cbi8vIEEgbGVhZGluZyBgdmAvYFZgIGltbWVkaWF0ZWx5IGZvbGxvd2VkIGJ5IGRpZ2l0cyAoYSB2ZXJzaW9uIG1hcmtlciBsaWtlXG4vLyBgdjJgKSBpcyBrZXB0IGFzIE9ORSB0b2tlbiBpbnN0ZWFkIG9mIHNwbGl0dGluZyBpbnRvIGB2YCArIGAyYDsgaXQgbGVhZHMgdGhlXG4vLyBhbHRlcm5hdGlvbiBzbyBpdCB3aW5zIG92ZXIgdGhlIGdlbmVyaWMgbGV0dGVyIC8gZGlnaXQgcnVucy4gRXZlcnl0aGluZyBlbHNlXG4vLyBpcyB0aGUgdXN1YWwgY2FtZWxDYXNlIHdvcmQgLyBudW1iZXIgLyBhbGwtY2Fwcy1hY3JvbnltIHNwbGl0LlxuY29uc3QgVE9LRU5JWkVfQ0FNRUxfQ0FTRV9SRUdFWFAgPSAvW3ZWXVswLTldK3xbQS1aXT9bYS16XSt8WzAtOV0rfFtBLVpdKyg/IVthLXpdKS9nO1xuY29uc3QgVE9LRU5JWkVfTk9OX0FMUEhBTlVNRVJJQ19SRUdFWFAgPSAvW2EtekEtWjAtOV0rL2c7XG5jb25zdCBUT0tFTklaRV9PVkVSUklERVM6ICgodG9rZW46IHN0cmluZywgb3B0aW9uczogVG9rZW5pemVPcHRpb25zKSA9PiBzdHJpbmcpW10gPSBbXG4gICh0b2tlbiwgb3B0aW9ucykgPT4ge1xuICAgIGlmICghb3B0aW9ucy5jYXBpdGFsaXplKSByZXR1cm4gdG9rZW47XG4gICAgY29uc3QgbG93ZXIgPSB0b2tlbi50b0xvd2VyQ2FzZSgpO1xuICAgIGlmIChsb3dlciA9PT0gXCJhaVwiKSByZXR1cm4gXCJBSVwiO1xuICAgIGlmIChsb3dlciA9PT0gXCJmc1wiKSByZXR1cm4gXCJGU1wiO1xuICAgIHJldHVybiB0b2tlbjtcbiAgfSxcbiAgLy8gVmVyc2lvbiBtYXJrZXIgYHYyYCAtPiBgVjJgIHdoZW4gY2FwaXRhbGl6aW5nICh0aGUgbGVhZGluZyBgdmAgdXBwZXJjYXNlcyxcbiAgLy8gdGhlIGRpZ2l0cyBzdGF5KSwgc28gaXQgcmVhZHMgYXMgb25lIHVuaXQgcmF0aGVyIHRoYW4gXCJWIDJcIi5cbiAgKHRva2VuLCBvcHRpb25zKSA9PiB7XG4gICAgaWYgKG9wdGlvbnMuY2FwaXRhbGl6ZSAmJiAvXnZbMC05XSskLy50ZXN0KHRva2VuKSkge1xuICAgICAgcmV0dXJuIGBWJHt0b2tlbi5zbGljZSgxKX1gO1xuICAgIH1cbiAgICByZXR1cm4gdG9rZW47XG4gIH0sXG5dO1xuY29uc3QgVVJJX1JFR0VYUCA9IC9eKFthLXpBLVpdW2EtekEtWjAtOSsuLV0qKT86XFwvXFwvKFteXFxzLz8jXVteXFxzXSopPyQvO1xuY29uc3QgRU1BSUxfUkVHRVhQID0gL14oW2EtekEtWjAtOS4hIyQlJicqKy89P15fYHt8fX4tXSspQChbYS16QS1aMC05LV0rKD86XFwuW2EtekEtWjAtOS1dKykrKSQvO1xuXG5jb25zdCBUT0tFTklaRV9ERUZBVUxUUzogUmVzb2x2ZWRUb2tlbml6ZU9wdGlvbnMgPSB7XG4gIGRpc3RpbmN0OiBmYWxzZSxcbiAgbG93ZXJDYXNlOiBmYWxzZSxcbiAgY2FwaXRhbGl6ZTogZmFsc2UsXG4gIG9taXRVcmlTY2hlbWU6IGZhbHNlLFxuICBvbWl0RW1haWxEb21haW46IGZhbHNlLFxuICBjYW1lbENhc2U6IHRydWUsXG59O1xuXG5jb25zdCBJREVOVElGSUVSX0RFRkFVTFRTOiBSZXNvbHZlZElkZW50aWZpZXJPcHRpb25zID0ge1xuICAuLi5UT0tFTklaRV9ERUZBVUxUUyxcbiAgbG93ZXJDYXNlOiB0cnVlLFxuICBtYXhMZW5ndGg6IEluZmluaXR5LFxuICB0cnVuY2F0ZVN0cmF0ZWd5OiBcImhhc2hcIixcbiAgdHJ1bmNhdGVIYXNoTGVuZ3RoOiA2LFxuICBkZWxpbWl0ZXI6IFwiLVwiLFxufTtcblxuZXhwb3J0IGZ1bmN0aW9uKiB0b2tlbml6ZVdpdGhPcHRpb25zKFxuICBvcHRpb25zOiBUb2tlbml6ZU9wdGlvbnMsXG4gIC4uLnZhbHVlczogdW5rbm93bltdXG4pOiBHZW5lcmF0b3I8c3RyaW5nPiB7XG4gIGNvbnN0IG9wdHM6IFJlc29sdmVkVG9rZW5pemVPcHRpb25zID0geyAuLi5UT0tFTklaRV9ERUZBVUxUUywgLi4ub3B0aW9ucyB9O1xuICBjb25zdCBzZWVuID0gb3B0cy5kaXN0aW5jdCA/IG5ldyBTZXQ8c3RyaW5nPigpIDogdW5kZWZpbmVkO1xuICBjb25zdCByZWdleHAgPSBvcHRzLmNhbWVsQ2FzZSA/IFRPS0VOSVpFX0NBTUVMX0NBU0VfUkVHRVhQIDogVE9LRU5JWkVfTk9OX0FMUEhBTlVNRVJJQ19SRUdFWFA7XG5cbiAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgY29udGludWU7XG4gICAgbGV0IHN0cmluZ1ZhbHVlID0gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiID8gdmFsdWUgOiBTdHJpbmcodmFsdWUpO1xuICAgIGlmICghc3RyaW5nVmFsdWUpIGNvbnRpbnVlO1xuICAgIGlmIChvcHRzLm9taXRVcmlTY2hlbWUpIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gc3RyaW5nVmFsdWUubWF0Y2goVVJJX1JFR0VYUCk7XG4gICAgICBpZiAobWF0Y2gpIHN0cmluZ1ZhbHVlID0gbWF0Y2hbMl0gPz8gXCJcIjtcbiAgICB9XG4gICAgaWYgKG9wdHMub21pdEVtYWlsRG9tYWluKSB7XG4gICAgICBjb25zdCBtYXRjaCA9IHN0cmluZ1ZhbHVlLm1hdGNoKEVNQUlMX1JFR0VYUCk7XG4gICAgICBpZiAobWF0Y2gpIHN0cmluZ1ZhbHVlID0gbWF0Y2hbMV0gPz8gXCJcIjtcbiAgICB9XG4gICAgaWYgKCFzdHJpbmdWYWx1ZSkgY29udGludWU7XG4gICAgZm9yIChjb25zdCB0b2tlbk1hdGNoIG9mIHN0cmluZ1ZhbHVlLm1hdGNoQWxsKHJlZ2V4cCkpIHtcbiAgICAgIGxldCB0b2tlbiA9IHRva2VuTWF0Y2hbMF0hO1xuICAgICAgaWYgKG9wdHMubG93ZXJDYXNlKSB0b2tlbiA9IHRva2VuLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAob3B0cy5jYXBpdGFsaXplKSB0b2tlbiA9IGNhcGl0YWxpemUodG9rZW4pO1xuICAgICAgaWYgKCF0b2tlbikgY29udGludWU7XG4gICAgICBmb3IgKGNvbnN0IG92ZXJyaWRlIG9mIFRPS0VOSVpFX09WRVJSSURFUykge1xuICAgICAgICB0b2tlbiA9IG92ZXJyaWRlKHRva2VuLCBvcHRzKTtcbiAgICAgICAgaWYgKCF0b2tlbikgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoIXRva2VuIHx8IHNlZW4/Lmhhcyh0b2tlbikpIGNvbnRpbnVlO1xuICAgICAgc2Vlbj8uYWRkKHRva2VuKTtcbiAgICAgIHlpZWxkIHRva2VuO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24qIHRva2VuaXplKC4uLnZhbHVlczogdW5rbm93bltdKTogR2VuZXJhdG9yPHN0cmluZz4ge1xuICB5aWVsZCogdG9rZW5pemVXaXRoT3B0aW9ucyh7fSwgLi4udmFsdWVzKTtcbn1cblxuLyoqXG4gKiBKb2luIHRva2VuaXplZCB2YWx1ZXMgd2l0aCBgZGVsaW1pdGVyYC4gV2hlbiB0aGUgbmV4dCB0b2tlbiB3b3VsZCBwdXNoIHRoZVxuICogcmVzdWx0IG92ZXIgYG1heExlbmd0aGA6IGB0cmltYCBzdG9wcyBhZGRpbmc7IGBlbXB0eWAgcmV0dXJucyBgXCJcImA7IGBoYXNoYFxuICogYXBwZW5kcyBhIGRpZ2VzdCBvZiBhY2NlcHRlZCB0b2tlbnMgcGx1cyB0aGUgb3ZlcmZsb3cgdG9rZW4gaWYgdGhlIHJlc3VsdFxuICogc3RpbGwgZml0cywgb3RoZXJ3aXNlIGBcIlwiYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvSWRlbnRpZmllcldpdGhPcHRpb25zKG9wdGlvbnM6IElkZW50aWZpZXJPcHRpb25zLCAuLi52YWx1ZXM6IHVua25vd25bXSk6IHN0cmluZyB7XG4gIGNvbnN0IG9wdHM6IFJlc29sdmVkSWRlbnRpZmllck9wdGlvbnMgPSB7XG4gICAgLi4uSURFTlRJRklFUl9ERUZBVUxUUyxcbiAgICAuLi5vcHRpb25zLFxuICAgIGxvd2VyQ2FzZTogdHJ1ZSxcbiAgfTtcbiAgY29uc3QgdG9rZW5zOiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgY3VycmVudExlbmd0aCA9IDA7XG5cbiAgZm9yIChjb25zdCB0b2tlbiBvZiB0b2tlbml6ZVdpdGhPcHRpb25zKG9wdHMsIC4uLnZhbHVlcykpIHtcbiAgICBjb25zdCBzZXBMZW5ndGggPSB0b2tlbnMubGVuZ3RoID4gMCA/IG9wdHMuZGVsaW1pdGVyLmxlbmd0aCA6IDA7XG4gICAgY29uc3QgbmV4dExlbmd0aCA9IGN1cnJlbnRMZW5ndGggKyBzZXBMZW5ndGggKyB0b2tlbi5sZW5ndGg7XG5cbiAgICBpZiAobmV4dExlbmd0aCA+IG9wdHMubWF4TGVuZ3RoKSB7XG4gICAgICBpZiAob3B0cy50cnVuY2F0ZVN0cmF0ZWd5ID09PSBcImVtcHR5XCIpIHJldHVybiBcIlwiO1xuICAgICAgaWYgKG9wdHMudHJ1bmNhdGVTdHJhdGVneSA9PT0gXCJ0cmltXCIpIGJyZWFrO1xuXG4gICAgICBjb25zdCBoYXNoID0gZGlnZXN0VG9rZW5zKG9wdHMudHJ1bmNhdGVIYXNoTGVuZ3RoLCB0b2tlbnMsIHRva2VuKTtcbiAgICAgIGlmIChjdXJyZW50TGVuZ3RoICsgc2VwTGVuZ3RoICsgaGFzaC5sZW5ndGggPD0gb3B0cy5tYXhMZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHRva2Vucy5sZW5ndGggPiAwID8gdG9rZW5zLmpvaW4ob3B0cy5kZWxpbWl0ZXIpICsgb3B0cy5kZWxpbWl0ZXIgKyBoYXNoIDogaGFzaDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHRva2Vucy5wdXNoKHRva2VuKTtcbiAgICBjdXJyZW50TGVuZ3RoID0gbmV4dExlbmd0aDtcbiAgfVxuXG4gIHJldHVybiB0b2tlbnMuam9pbihvcHRzLmRlbGltaXRlcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0lkZW50aWZpZXIoLi4udmFsdWVzOiB1bmtub3duW10pOiBzdHJpbmcge1xuICByZXR1cm4gdG9JZGVudGlmaWVyV2l0aE9wdGlvbnMoe30sIC4uLnZhbHVlcyk7XG59XG5cbi8qKlxuICogU2x1Z2lmaWVkIGlkZW50aWZpZXI6IHNhbWUgcnVsZXMgYXMge0BsaW5rIHRvSWRlbnRpZmllcldpdGhPcHRpb25zfSB3aXRoIHRoZVxuICogZGVsaW1pdGVyIGZvcmNlZCB0byBgLWAuIEFjY2VwdHMge0BsaW5rIEtleU9wdGlvbnN9IHNvIGNhbGxlcnMgY2Fubm90XG4gKiBvdmVycmlkZSB0aGUgZGVsaW1pdGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TbHVnV2l0aE9wdGlvbnMob3B0aW9uczogS2V5T3B0aW9ucywgLi4udmFsdWVzOiB1bmtub3duW10pOiBzdHJpbmcge1xuICByZXR1cm4gdG9JZGVudGlmaWVyV2l0aE9wdGlvbnMoeyAuLi5vcHRpb25zLCBkZWxpbWl0ZXI6IFwiLVwiIH0sIC4uLnZhbHVlcyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b1NsdWcoLi4udmFsdWVzOiB1bmtub3duW10pOiBzdHJpbmcge1xuICByZXR1cm4gdG9TbHVnV2l0aE9wdGlvbnMoe30sIC4uLnZhbHVlcyk7XG59XG5cbi8qKlxuICogVHJpbSBgdmFsdWVgIGFuZCByZXR1cm4gYG51bGxgIGZvciBub24tc3RyaW5ncywgYHVuZGVmaW5lZGAsIG9yXG4gKiBzdHJpbmdzIHRoYXQgYXJlIGVtcHR5IGFmdGVyIHRyaW1taW5nLiBMZXRzIGNhbGwgc2l0ZXMgY29sbGFwc2UgdGhlXG4gKiBjb21tb25cbiAqXG4gKiBgYGB0c1xuICogdHlwZW9mIHYgPT09IFwic3RyaW5nXCIgJiYgdi50cmltKCkgPyB2LnRyaW0oKSA6IG51bGxcbiAqIGBgYFxuICpcbiAqIGRhbmNlIGludG8gYSBzaW5nbGUgaGVscGVyLiBVc2VmdWwgZm9yIEhUVFAgaGVhZGVyIC8gcXVlcnkgLyBmb3JtXG4gKiBleHRyYWN0b3JzIHdoZXJlIGRvd25zdHJlYW0gY29kZSB3YW50cyBgc3RyaW5nIHwgbnVsbGAgdG8gZHJpdmUgYVxuICogY2hlYXAgYD8/YCAvIGBpZiAoeClgIGNhc2NhZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmltVG9OdWxsKHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIpIHJldHVybiBudWxsO1xuICBjb25zdCB0cmltbWVkID0gdmFsdWUudHJpbSgpO1xuICByZXR1cm4gdHJpbW1lZCA/IHRyaW1tZWQgOiBudWxsO1xufVxuXG4vLyBDb25maWcgbGlzdHMgYXJyaXZlIGVpdGhlciBhbHJlYWR5IHNwbGl0IChhbiBhcnJheSkgb3IgYXMgb25lIGVudi12YXIgc3RyaW5nXG4vLyB3aXRoIGVudHJpZXMgc2VwYXJhdGVkIGJ5IGNvbW1hcyBhbmQvb3Igd2hpdGVzcGFjZS5cbmNvbnN0IExJU1RfU0VQQVJBVE9SX1JFR0VYUCA9IC9bXFxzLF0rLztcblxuLyoqXG4gKiBOb3JtYWxpemUgYSBjb25maWcgbGlzdCB0aGF0IG1heSBhcnJpdmUgYXMgYW4gYXJyYXkgb3IgYXMgYSBzaW5nbGVcbiAqIGNvbW1hL3doaXRlc3BhY2Utc2VwYXJhdGVkIHN0cmluZzogc3BsaXQsIGFwcGx5IGB0cmFuc2Zvcm1gLCBkcm9wIGVtcHRpZXMsXG4gKiBhbmQgZGUtZHVwbGljYXRlIChmaXJzdCBvY2N1cnJlbmNlIHdpbnMpLlxuICpcbiAqIFRoaXMgaXMgdGhlIHNoYXBlIGV2ZXJ5IGFsbG93LWxpc3QgLyBmYWxsYmFjay1vcmRlciBzZXR0aW5nIGluIHRoaXMgcmVwb1xuICogdGFrZXMsIGJlY2F1c2UgdGhlIHNhbWUgdmFsdWUgY2FuIGNvbWUgZnJvbSB0eXBlZCBjb25maWcgKGBzdHJpbmdbXWApIG9yIGZyb21cbiAqIGFuIGVudmlyb25tZW50IHZhcmlhYmxlIChgXCJhLCBiIGNcImApLiBQYXNzIGB0cmFuc2Zvcm1gIHRvIG5vcm1hbGl6ZSBlbnRyaWVzXG4gKiBhcyB0aGV5IGFyZSByZWFkOyBpdCBkZWZhdWx0cyB0byB0cmltbWluZy5cbiAqXG4gKiBAZXhhbXBsZVxuICogcGFyc2VMaXN0KFwiZG9jcy5leGFtcGxlLmNvbSwgKi5kYXRhYnJpY2tzLmNvbVwiKTtcbiAqIHBhcnNlTGlzdChwcm9jZXNzLmVudi5NT0RFTF9GQUxMQkFDS1MpO1xuICogcGFyc2VMaXN0KHJhdywgbm9ybWFsaXplVXJsUGF0dGVybik7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUxpc3QoXG4gIHJhdzogc3RyaW5nIHwgcmVhZG9ubHkgc3RyaW5nW10gfCB1bmRlZmluZWQgfCBudWxsLFxuICB0cmFuc2Zvcm06IChlbnRyeTogc3RyaW5nKSA9PiBzdHJpbmcgPSAoZW50cnkpID0+IGVudHJ5LnRyaW0oKSxcbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgZW50cmllcyA9XG4gICAgdHlwZW9mIHJhdyA9PT0gXCJzdHJpbmdcIiA/IHJhdy5zcGxpdChMSVNUX1NFUEFSQVRPUl9SRUdFWFApIDogQXJyYXkuaXNBcnJheShyYXcpID8gcmF3IDogW107XG4gIGNvbnN0IG91dDogc3RyaW5nW10gPSBbXTtcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBub3JtYWxpemVkID0gdHJhbnNmb3JtKGVudHJ5KTtcbiAgICBpZiAoIW5vcm1hbGl6ZWQgfHwgc2Vlbi5oYXMobm9ybWFsaXplZCkpIGNvbnRpbnVlO1xuICAgIHNlZW4uYWRkKG5vcm1hbGl6ZWQpO1xuICAgIG91dC5wdXNoKG5vcm1hbGl6ZWQpO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICoge0BsaW5rIHRyaW1Ub051bGx9IHdpdGggYW4gZW1wdHktc3RyaW5nIG1pc3MgaW5zdGVhZCBvZiBgbnVsbGAsIGZvciBjYWxsZXJzXG4gKiB0aGF0IGJ1aWxkIGEgc3RyaW5nIHVuY29uZGl0aW9uYWxseSBhbmQgdHJlYXQgXCJhYnNlbnRcIiBhcyBcIlwiLlxuICpcbiAqIFJlYWRpbmcgbG9vc2VseS10eXBlZCBKU09OIGlzIHRoZSBtb3RpdmF0aW5nIGNhc2U6IGEgZmllbGQgdGhhdCBzaG91bGQgYmUgYVxuICogc3RyaW5nIG1heSBiZSBtaXNzaW5nIG9yIHRoZSB3cm9uZyB0eXBlLCBhbmQgdGhlIGNhbGxlciB3YW50cyBgXCJcImAgcmF0aGVyXG4gKiB0aGFuIGEgbnVsbCBjaGVjayBhdCBldmVyeSBhY2Nlc3MuXG4gKlxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHRpdGxlID0gdHJpbVRvRW1wdHkocmVjb3JkLnRpdGxlKTsgLy8gYWx3YXlzIGEgc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmltVG9FbXB0eSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG4gIHJldHVybiB0cmltVG9OdWxsKHZhbHVlKSA/PyBcIlwiO1xufVxuXG4vKipcbiAqIFRyaW0gdGhlIGZpcnN0IHVzYWJsZSBzdHJpbmcgb3V0IG9mIGB2YWx1ZWAuIFJldHVybnMgYG51bGxgIHdoZW5cbiAqIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAsIGBudWxsYCwgYW4gZW1wdHkgc3RyaW5nLCBvciBhbiBhcnJheSB3aG9zZVxuICogZmlyc3Qgc3RyaW5nIG1lbWJlciBpcyBlbXB0eS4gTWlycm9ycyBob3cgRXhwcmVzcyAvIE5vZGUgaGVhZGVyXG4gKiBhY2Nlc3NvcnMgZXhwb3NlIHNpbmdsZSB2cy4gcmVwZWF0ZWQgaGVhZGVycyAtIHRoZSBmaXJzdFxuICogbm9uLWVtcHR5IGVudHJ5IHdpbnMsIGV2ZXJ5dGhpbmcgZWxzZSBpcyBpZ25vcmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlyc3ROb25FbXB0eSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB8IG51bGwge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdmFsdWUpIHtcbiAgICAgIGNvbnN0IHRyaW1tZWQgPSB0cmltVG9OdWxsKGl0ZW0pO1xuICAgICAgaWYgKHRyaW1tZWQpIHJldHVybiB0cmltbWVkO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gdHJpbVRvTnVsbCh2YWx1ZSk7XG59XG5cbi8qKlxuICogRXNjYXBlIHRoZSBmaXZlIGNoYXJhY3RlcnMgc2lnbmlmaWNhbnQgaW4gSFRNTCB0ZXh0IGFuZFxuICogZG91YmxlLXF1b3RlZCBhdHRyaWJ1dGUgdmFsdWVzIChgJmAsIGA8YCwgYD5gLCBgXCJgLCBgJ2ApIHNvIGFuXG4gKiB1bnRydXN0ZWQgc3RyaW5nIGNhbiBiZSBpbnRlcnBvbGF0ZWQgaW50byBtYXJrdXAgd2l0aG91dCBicmVha2luZ1xuICogb3V0IG9mIGl0cyBjb250ZXh0LiBgJmAgaXMgcmVwbGFjZWQgZmlyc3Qgc28gYW1wZXJzYW5kcyBpbnRyb2R1Y2VkXG4gKiBieSB0aGUgbGF0ZXIgcmVwbGFjZW1lbnRzIGFyZW4ndCBkb3VibGUtZXNjYXBlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZUh0bWwodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB2YWx1ZVxuICAgIC5yZXBsYWNlKC8mL2csIFwiJmFtcDtcIilcbiAgICAucmVwbGFjZSgvPC9nLCBcIiZsdDtcIilcbiAgICAucmVwbGFjZSgvPi9nLCBcIiZndDtcIilcbiAgICAucmVwbGFjZSgvXCIvZywgXCImcXVvdDtcIilcbiAgICAucmVwbGFjZSgvJy9nLCBcIiYjMzk7XCIpO1xufVxuXG4vKipcbiAqIFNsdWdpZnkgYHZhbHVlYCAodXNpbmcgdGhlIHN0YW5kYXJkIHtAbGluayB0b0lkZW50aWZpZXJXaXRoT3B0aW9uc31cbiAqIHRva2VuaXplciArIGRlbGltaXRlciBydWxlcykgYW5kICoqYWx3YXlzKiogc3VmZml4IGEgc2hvcnRcbiAqIGRldGVybWluaXN0aWMgaGFzaC4gVXNlIHdoZW4geW91IG5lZWQgYSBzdGFibGUsIHNsdWdpZmllZCBpZCB0aGF0XG4gKiBpcyBndWFyYW50ZWVkIHRvIGJlIHVuaXF1ZSBhY3Jvc3MgZGVzY3JpcHRpb25zIHNoYXJpbmcgdGhlIHNhbWVcbiAqIGxlYWRpbmcgdG9rZW5zICh0b29sIGlkcywgY2FjaGUga2V5cywgZXRjLikuXG4gKlxuICogQmVoYXZpb3VyIGRpZmZlcnMgZnJvbSBgdG9JZGVudGlmaWVyV2l0aE9wdGlvbnMoeyBtYXhMZW5ndGgsXG4gKiB0cnVuY2F0ZVN0cmF0ZWd5OiBcImhhc2hcIiB9KWA6IHRoYXQgaGVscGVyIG9ubHkgYXBwZW5kcyBhIGhhc2ggd2hlblxuICogdGhlIHNsdWcgKm92ZXJmbG93cyogYG1heExlbmd0aGAuIFRoaXMgaGVscGVyIGFwcGVuZHMgYSBoYXNoXG4gKiB1bmNvbmRpdGlvbmFsbHkgc28gdGhlIHJlc3VsdCBpcyBjb2xsaXNpb24tcmVzaXN0YW50IGV2ZW4gZm9yXG4gKiBzaG9ydCBpbnB1dHMuIFRoZSBoYXNoIGlzIGNvbXB1dGVkIG92ZXIgdGhlIHJhdyBgdmFsdWVgIHNvIHR3b1xuICogZGVzY3JpcHRpb25zIHByb2R1Y2luZyB0aGUgc2FtZSBzbHVnIHN0aWxsIGdldCBkaWZmZXJlbnQgaWRzLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIFNvdXJjZSBzdHJpbmcgKHR5cGljYWxseSBhIHRvb2wvYWdlbnQgZGVzY3JpcHRpb24pLlxuICogQHBhcmFtIG9wdGlvbnMuZGVsaW1pdGVyIC0gVG9rZW4gc2VwYXJhdG9yIChkZWZhdWx0IGBcIl9cImApLlxuICogQHBhcmFtIG9wdGlvbnMuc2x1Z01heExlbmd0aCAtIENhcCBvbiB0aGUgc2x1ZyBwb3J0aW9uICh0aGUgcGFydFxuICogICBiZWZvcmUgdGhlIGhhc2gpLiBEZWZhdWx0IDMyLlxuICogQHBhcmFtIG9wdGlvbnMuaGFzaExlbmd0aCAtIExlbmd0aCBvZiB0aGUgc3VmZml4IHByb2R1Y2VkIGJ5XG4gKiAgIHtAbGluayBmbnZIYXNoV2l0aE9wdGlvbnN9IChDcm9ja2ZvcmQtc3R5bGUgYmFzZS0zMiBhbHBoYWJldCwgbWF4IDdcbiAqICAgY2hhcnMpLiBEZWZhdWx0IDYuXG4gKiBAcGFyYW0gb3B0aW9ucy5mYWxsYmFja1ByZWZpeCAtIFByZWZpeCB1c2VkIHdoZW4gdGhlIHNsdWcgaXMgZW1wdHlcbiAqICAgKGUuZy4gcHVuY3R1YXRpb24tb25seSBpbnB1dCkuIERlZmF1bHQgYFwiaWRcImAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1VuaXF1ZVNsdWcoXG4gIHZhbHVlOiBzdHJpbmcsXG4gIG9wdGlvbnM6IHtcbiAgICBkZWxpbWl0ZXI/OiBzdHJpbmc7XG4gICAgc2x1Z01heExlbmd0aD86IG51bWJlcjtcbiAgICBoYXNoTGVuZ3RoPzogbnVtYmVyO1xuICAgIGZhbGxiYWNrUHJlZml4Pzogc3RyaW5nO1xuICB9ID0ge30sXG4pOiBzdHJpbmcge1xuICBjb25zdCBkZWxpbWl0ZXIgPSBvcHRpb25zLmRlbGltaXRlciA/PyBcIl9cIjtcbiAgY29uc3Qgc2x1Z01heExlbmd0aCA9IG9wdGlvbnMuc2x1Z01heExlbmd0aCA/PyAzMjtcbiAgY29uc3QgaGFzaExlbmd0aCA9IG9wdGlvbnMuaGFzaExlbmd0aCA/PyA2O1xuICBjb25zdCBmYWxsYmFja1ByZWZpeCA9IG9wdGlvbnMuZmFsbGJhY2tQcmVmaXggPz8gXCJpZFwiO1xuICBjb25zdCBzbHVnID0gdG9JZGVudGlmaWVyV2l0aE9wdGlvbnMoXG4gICAgeyBkZWxpbWl0ZXIsIG1heExlbmd0aDogc2x1Z01heExlbmd0aCwgdHJ1bmNhdGVTdHJhdGVneTogXCJ0cmltXCIgfSxcbiAgICB2YWx1ZSxcbiAgKTtcbiAgY29uc3Qgc3VmZml4ID0gZm52SGFzaFdpdGhPcHRpb25zKHsgbGVuZ3RoOiBoYXNoTGVuZ3RoIH0sIHZhbHVlKTtcbiAgcmV0dXJuIHNsdWcgPyBgJHtzbHVnfSR7ZGVsaW1pdGVyfSR7c3VmZml4fWAgOiBgJHtmYWxsYmFja1ByZWZpeH0ke2RlbGltaXRlcn0ke3N1ZmZpeH1gO1xufVxuXG5mdW5jdGlvbiBkaWdlc3RUb2tlbnMobGVuZ3RoOiBudW1iZXIsIHBhcnRzOiByZWFkb25seSBzdHJpbmdbXSwgZXh0cmE/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgY29tYmluZWQgPSBcIlwiO1xuICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpIGNvbWJpbmVkICs9IHBhcnQgKyBcIlxcMFwiO1xuICBpZiAoZXh0cmEgIT09IHVuZGVmaW5lZCkgY29tYmluZWQgKz0gZXh0cmEgKyBcIlxcMFwiO1xuICByZXR1cm4gZm52SGFzaFdpdGhPcHRpb25zKHsgbGVuZ3RoIH0sIGNvbWJpbmVkKTtcbn1cblxuLyoqXG4gKiBBIG5vZGUgaW4gdGhlIGRlc2NyaXB0aW9uIHRyZWUgY29uc3VtZWQgYnkge0BsaW5rIHRvRGVzY3JpcHRpb259LlxuICpcbiAqIC0gYHN0cmluZ2AgLSBhIHRleHQgcGFyYWdyYXBoLlxuICogLSBgRGVzY3JpcHRpb25bXWAgLSBhIHNlcXVlbmNlIG9mIHN0YWNrZWQgYmxvY2tzIGF0IHRoZSBzYW1lIGxldmVsXG4gKiAgIChubyBsaXN0IG1hcmtlcnMpLiBQbGFpbiB0ZXh0IGFkamFjZW50IHRvIGEgbGlzdCAoZWl0aGVyIGRpcmVjdGlvbilcbiAqICAgZmx1c2hlcyB0b2dldGhlciBzbyB0aGUgcHJvc2UgcmVhZHMgYXMgYSBsZWFkLWluIG9yIHRyYWlsaW5nXG4gKiAgIHN1bW1hcnkuIFR3byB0ZXh0IHBhcmFncmFwaHMsIHR3byBhZGphY2VudCBsaXN0cywgYW5kIGFueXRoaW5nXG4gKiAgIHRvdWNoaW5nIGEgbWFwIGdldCBhIGJsYW5rLWxpbmUgYnJlYWsuXG4gKiAtIGB7IGJ1bGxldHM6IFsuLi5dIH1gIC8gYHsgbnVtYmVyZWQ6IFsuLi5dIH1gIC0gZXhwbGljaXQgbGlzdC4gQVxuICogICBsaXN0IG9mIG9uZSBiYXJlIHN0cmluZyBkcm9wcyBpdHMgbWFya2VyIChgLWAgLyBgMS5gKTsgYSBsaXN0IG9mXG4gKiAgIG9uZSBpdGVtIHdpdGggbmVzdGVkIGNoaWxkcmVuIGtlZXBzIGl0cyBtYXJrZXIgYXMgdGhlIHZpc3VhbCBhbmNob3JcbiAqICAgZm9yIHRoZSBpbmRlbnRlZCBjaGlsZHJlbi5cbiAqIC0gYW55IG90aGVyIG9iamVjdCAtIGhlYWRlcnMgbWFwOiBlYWNoIGtleSBiZWNvbWVzIGEgYEhlYWRlcjpgIGxpbmVcbiAqICAgZm9sbG93ZWQgYnkgYSBibGFuayBsaW5lIGFuZCB0aGUgcmVuZGVyZWQgdmFsdWUuXG4gKi9cbmV4cG9ydCB0eXBlIERlc2NyaXB0aW9uID0gc3RyaW5nIHwgcmVhZG9ubHkgRGVzY3JpcHRpb25bXSB8IHsgcmVhZG9ubHkgW2tleTogc3RyaW5nXTogRGVzY3JpcHRpb24gfTtcblxuY29uc3QgTElTVF9LRVlTID0gW1wiYnVsbGV0c1wiLCBcIm51bWJlcmVkXCJdIGFzIGNvbnN0O1xudHlwZSBMaXN0S2luZCA9ICh0eXBlb2YgTElTVF9LRVlTKVtudW1iZXJdO1xuXG4vKipcbiAqIEZvcm1hdCBhIG5lc3RlZCBkZXNjcmlwdGlvbiB0cmVlIGFzIGEgTWFya2Rvd24taXNoIHN0cmluZyBzdWl0YWJsZVxuICogZm9yIGFuIExMTSBzeXN0ZW0gcHJvbXB0LCBab2QgYC5kZXNjcmliZSgpYCBibG9jaywgTWFzdHJhIHRvb2xcbiAqIGRlc2NyaXB0aW9uLCBvciBhbnkgb3RoZXIgbG9uZy1mb3JtIHRleHQgZGVzdGluYXRpb24uXG4gKlxuICogRXZlcnkgc3RyaW5nIHNlY3Rpb24gaXMgZGVkZW50ZWQgKGNvbW1vbiBsZWFkaW5nIHdoaXRlc3BhY2Ugc3RyaXBwZWQpLFxuICogcmlnaHQtdHJpbW1lZCBsaW5lIGJ5IGxpbmUsIGFuZCBmcmVlZCBvZiBsZWFkaW5nIC8gdHJhaWxpbmcgYmxhbmtcbiAqIGxpbmVzLCBzbyBjYWxsZXJzIGNhbiB3cml0ZSBtdWx0aS1saW5lIHRlbXBsYXRlIGxpdGVyYWxzIGluZGVudGVkXG4gKiBuYXR1cmFsbHkgaW4gc291cmNlIHdpdGhvdXQgbGVha2luZyB0aGF0IGluZGVudGF0aW9uIGludG8gdGhlXG4gKiBjb25zdW1lci1mYWNpbmcgb3V0cHV0LiBQbGFpbi1zdHJpbmcgaW5wdXRzIGZsb3cgdGhyb3VnaCB1bmNoYW5nZWRcbiAqIGFwYXJ0IGZyb20gdGhlIHNhbWUgbm9ybWFsaXphdGlvbiBwYXNzLCBzbyBhIHNpbmdsZSBtdWx0aS1saW5lXG4gKiB0ZW1wbGF0ZSBsaXRlcmFsIHdvcmtzIGRpcmVjdGx5OlxuICpcbiAqIGBgYHRzXG4gKiB0b0Rlc2NyaXB0aW9uKGBcbiAqICAgQXNrIHRoZSBHZW5pZSBzcGFjZSBcIiR7YWxpYXN9XCIgYSBxdWVzdGlvbi5cbiAqICAgUGFzcyB0aGUgYW5zd2VyIHRocm91Z2ggYXMtaXMuXG4gKiBgKTtcbiAqIC8vIEFzayB0aGUgR2VuaWUgc3BhY2UgXCJkZWZhdWx0XCIgYSBxdWVzdGlvbi5cbiAqIC8vIFBhc3MgdGhlIGFuc3dlciB0aHJvdWdoIGFzLWlzLlxuICpcbiAqIHRvRGVzY3JpcHRpb24oW1xuICogICBgXG4gKiAgICAgQXNrIHRoZSBHZW5pZSBzcGFjZSBhIHF1ZXN0aW9uLlxuICogICAgIFBocmFzZSBpdCBmcm9tIHRoZSB1c2VyJ3MgcGVyc3BlY3RpdmUuXG4gKiAgIGAsXG4gKiAgIHsgYnVsbGV0czogW1xuICogICAgIFtcIlBhc3MgdGhlIGFuc3dlciB0aHJvdWdoIGFzLWlzXCIsIHsgbnVtYmVyZWQ6IFtcIml0ZW1cIiwgXCJpdGVtXCJdIH1dLFxuICogICBdfSxcbiAqICAgeyBJbnN0cnVjdGlvbnM6IFwiUmVwbHkgd2l0aCB0aGUgU1FMIG9ubHkuXCIgfSxcbiAqIF0pO1xuICogLy8gQXNrIHRoZSBHZW5pZSBzcGFjZSBhIHF1ZXN0aW9uLlxuICogLy8gUGhyYXNlIGl0IGZyb20gdGhlIHVzZXIncyBwZXJzcGVjdGl2ZS5cbiAqIC8vIC0gUGFzcyB0aGUgYW5zd2VyIHRocm91Z2ggYXMtaXNcbiAqIC8vICAgMS4gaXRlbVxuICogLy8gICAyLiBpdGVtXG4gKiAvL1xuICogLy8gSW5zdHJ1Y3Rpb25zOlxuICogLy9cbiAqIC8vIFJlcGx5IHdpdGggdGhlIFNRTCBvbmx5LlxuICogYGBgXG4gKlxuICogU2VlIHtAbGluayBEZXNjcmlwdGlvbn0gZm9yIHRoZSBub2RlIGdyYW1tYXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0Rlc2NyaXB0aW9uKG5vZGU6IERlc2NyaXB0aW9uKTogc3RyaW5nIHtcbiAgcmV0dXJuIHJlbmRlckJsb2NrKG5vZGUsIFwiXCIpXG4gICAgLnJlcGxhY2UoL1sgXFx0XSskL2dtLCBcIlwiKVxuICAgIC5yZXBsYWNlKC9cXG4rJC8sIFwiXCIpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJCbG9jayhub2RlOiBEZXNjcmlwdGlvbiwgcGFkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAobm9kZSA9PSBudWxsKSByZXR1cm4gXCJcIjtcbiAgaWYgKHR5cGVvZiBub2RlID09PSBcInN0cmluZ1wiKSByZXR1cm4gcHJlcGVuZFBhZChkZWRlbnRTZWN0aW9uKG5vZGUpLCBwYWQpO1xuICBpZiAoQXJyYXkuaXNBcnJheShub2RlKSkgcmV0dXJuIHJlbmRlclNlcXVlbmNlKG5vZGUsIHBhZCk7XG4gIGNvbnN0IGtpbmQgPSBsaXN0S2luZChub2RlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgaWYgKGtpbmQpIHtcbiAgICByZXR1cm4gcmVuZGVyTGlzdCgobm9kZSBhcyBSZWNvcmQ8TGlzdEtpbmQsIHJlYWRvbmx5IERlc2NyaXB0aW9uW10+KVtraW5kXSwgcGFkLCBraW5kKTtcbiAgfVxuICByZXR1cm4gcmVuZGVyTWFwKG5vZGUgYXMgUmVjb3JkPHN0cmluZywgRGVzY3JpcHRpb24+LCBwYWQpO1xufVxuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHN0cmluZyBzZWN0aW9uOiByaWdodC1zdHJpcCBldmVyeSBsaW5lLCBkcm9wIHRoZVxuICogY29tbW9uIGxlYWRpbmctd2hpdGVzcGFjZSBwcmVmaXggc2hhcmVkIGJ5IGFsbCBub24tYmxhbmsgbGluZXMsXG4gKiBhbmQgdHJpbSBsZWFkaW5nIC8gdHJhaWxpbmcgYmxhbmsgbGluZXMuIE1hdGNoZXMgUHl0aG9uJ3NcbiAqIGB0ZXh0d3JhcC5kZWRlbnRgIHNlbWFudGljcyBzbyBlbWJlZGRlZCBpbmRlbnRlZCB0ZW1wbGF0ZVxuICogbGl0ZXJhbHMgcm91bmQtdHJpcCBjbGVhbmx5LlxuICovXG5mdW5jdGlvbiBkZWRlbnRTZWN0aW9uKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghdGV4dCkgcmV0dXJuIFwiXCI7XG4gIGNvbnN0IGxpbmVzID0gdGV4dC5zcGxpdChcIlxcblwiKS5tYXAoKGxpbmUpID0+IGxpbmUucmVwbGFjZSgvWyBcXHRdKyQvLCBcIlwiKSk7XG4gIGxldCBtaW4gPSBJbmZpbml0eTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgaWYgKCFsaW5lKSBjb250aW51ZTtcbiAgICBjb25zdCBtYXRjaCA9IC9eWyBcXHRdKi8uZXhlYyhsaW5lKTtcbiAgICBjb25zdCB3aWR0aCA9IG1hdGNoID8gbWF0Y2hbMF0ubGVuZ3RoIDogMDtcbiAgICBpZiAod2lkdGggPCBtaW4pIG1pbiA9IHdpZHRoO1xuICB9XG4gIGNvbnN0IHN0cmlwcGVkID1cbiAgICBtaW4gPT09IEluZmluaXR5IHx8IG1pbiA9PT0gMCA/IGxpbmVzIDogbGluZXMubWFwKChsaW5lKSA9PiAobGluZSA/IGxpbmUuc2xpY2UobWluKSA6IFwiXCIpKTtcbiAgbGV0IHN0YXJ0ID0gMDtcbiAgbGV0IGVuZCA9IHN0cmlwcGVkLmxlbmd0aDtcbiAgd2hpbGUgKHN0YXJ0IDwgZW5kICYmICFzdHJpcHBlZFtzdGFydF0pIHN0YXJ0ICs9IDE7XG4gIHdoaWxlIChlbmQgPiBzdGFydCAmJiAhc3RyaXBwZWRbZW5kIC0gMV0pIGVuZCAtPSAxO1xuICByZXR1cm4gc3RyaXBwZWQuc2xpY2Uoc3RhcnQsIGVuZCkuam9pbihcIlxcblwiKTtcbn1cblxuLyoqXG4gKiBBbiBvYmplY3QgaXMgdHJlYXRlZCBhcyBhIHR5cGVkIGxpc3Qgb25seSB3aGVuIGl0IGhhcyBleGFjdGx5IG9uZVxuICogb3duIGtleSwgdGhhdCBrZXkgaXMgYGJ1bGxldHNgIG9yIGBudW1iZXJlZGAsIGFuZCB0aGUgdmFsdWUgaXMgYW5cbiAqIGFycmF5LiBFdmVyeXRoaW5nIGVsc2UgaXMgYSBoZWFkZXJzIG1hcCAtIHNvIGNhbGxlcnMgd2FudGluZyBhXG4gKiBzaW5nbGUgaGVhZGVyIGxpdGVyYWxseSBuYW1lZCBgYnVsbGV0c2Agb3IgYG51bWJlcmVkYCBjYW4gdXNlIGFcbiAqIG11bHRpLWtleSBtYXAgb3IgcmVuYW1lLlxuICovXG5mdW5jdGlvbiBsaXN0S2luZChub2RlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IExpc3RLaW5kIHwgbnVsbCB7XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhub2RlKTtcbiAgaWYgKGtleXMubGVuZ3RoICE9PSAxKSByZXR1cm4gbnVsbDtcbiAgY29uc3Qga2V5ID0ga2V5c1swXSE7XG4gIGlmICgoTElTVF9LRVlTIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyhrZXkpICYmIEFycmF5LmlzQXJyYXkobm9kZVtrZXldKSkge1xuICAgIHJldHVybiBrZXkgYXMgTGlzdEtpbmQ7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIHByZXBlbmRQYWQodGV4dDogc3RyaW5nLCBwYWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghdGV4dCkgcmV0dXJuIFwiXCI7XG4gIGlmICghcGFkKSByZXR1cm4gdGV4dDtcbiAgcmV0dXJuIHRleHRcbiAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAubWFwKChsaW5lKSA9PiAobGluZSA/IHBhZCArIGxpbmUgOiBcIlwiKSlcbiAgICAuam9pbihcIlxcblwiKTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyU2VxdWVuY2UoaXRlbXM6IHJlYWRvbmx5IERlc2NyaXB0aW9uW10sIHBhZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcmVuZGVyZWQ6IHsgdGV4dDogc3RyaW5nOyBub2RlOiBEZXNjcmlwdGlvbiB9W10gPSBbXTtcbiAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XG4gICAgY29uc3QgdGV4dCA9IHJlbmRlckJsb2NrKGl0ZW0sIHBhZCk7XG4gICAgaWYgKCF0ZXh0KSBjb250aW51ZTtcbiAgICByZW5kZXJlZC5wdXNoKHsgdGV4dCwgbm9kZTogaXRlbSB9KTtcbiAgfVxuICBpZiAocmVuZGVyZWQubGVuZ3RoID09PSAwKSByZXR1cm4gXCJcIjtcbiAgbGV0IG91dCA9IHJlbmRlcmVkWzBdIS50ZXh0O1xuICBmb3IgKGxldCBpID0gMTsgaSA8IHJlbmRlcmVkLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgY29uc3Qgc2VwID0gbmVlZHNCbGFua0xpbmVCZXR3ZWVuKHJlbmRlcmVkW2kgLSAxXSEubm9kZSwgcmVuZGVyZWRbaV0hLm5vZGUpID8gXCJcXG5cXG5cIiA6IFwiXFxuXCI7XG4gICAgb3V0ICs9IHNlcCArIHJlbmRlcmVkW2ldIS50ZXh0O1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogTWFwcyBhbHdheXMgY3JlYXRlIHRoZWlyIG93biBzZWN0aW9uIGJvdW5kYXJ5IChhIGBIZWFkZXI6YCBsaW5lIHBsdXNcbiAqIGEgYmxhbmsgbGluZSBiZWZvcmUgdGhlIGJvZHkpLCBzbyBhbnl0aGluZyB0b3VjaGluZyBhIG1hcCBnZXRzIGFcbiAqIGJsYW5rLWxpbmUgYnJlYWsuIFBsYWluIHRleHQgYWRqYWNlbnQgdG8gYSB0eXBlZCBsaXN0IGZsdXNoZXNcbiAqIHRvZ2V0aGVyIGluIGVpdGhlciBkaXJlY3Rpb246IHRleHQtYmVmb3JlLWxpc3QgcmVhZHMgYXMgYSBsZWFkLWluLFxuICogdGV4dC1hZnRlci1saXN0IGFzIGEgdHJhaWxpbmcgc3VtbWFyeS4gVHdvIHRleHQgcGFyYWdyYXBocyBhbmQgdHdvXG4gKiBhZGphY2VudCBsaXN0cyBib3RoIGdldCBhIGJsYW5rLWxpbmUgYnJlYWsgZm9yIGxlZ2liaWxpdHkuXG4gKi9cbmZ1bmN0aW9uIG5lZWRzQmxhbmtMaW5lQmV0d2VlbihwcmV2OiBEZXNjcmlwdGlvbiwgY3VycjogRGVzY3JpcHRpb24pOiBib29sZWFuIHtcbiAgaWYgKGlzTWFwKHByZXYpIHx8IGlzTWFwKGN1cnIpKSByZXR1cm4gdHJ1ZTtcbiAgY29uc3QgcHJldklzVGV4dCA9IHR5cGVvZiBwcmV2ID09PSBcInN0cmluZ1wiO1xuICBjb25zdCBjdXJySXNUZXh0ID0gdHlwZW9mIGN1cnIgPT09IFwic3RyaW5nXCI7XG4gIGlmIChwcmV2SXNUZXh0ICE9PSBjdXJySXNUZXh0KSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEEgbm9kZSBpcyBhIGhlYWRlcnMgbWFwIHdoZW4gaXQgaXMgYSBub24tYXJyYXksIG5vbi1saXN0IG9iamVjdC5cbiAqIGBidWxsZXRzYCAvIGBudW1iZXJlZGAgc2luZ2xlLWtleSBvYmplY3RzIGFyZSB0aGUgb25seSBzdHJ1Y3R1cmVkXG4gKiBvYmplY3RzIHRoYXQgYXJlbid0IG1hcHMuXG4gKi9cbmZ1bmN0aW9uIGlzTWFwKG5vZGU6IERlc2NyaXB0aW9uKTogYm9vbGVhbiB7XG4gIGlmIChub2RlID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgaWYgKHR5cGVvZiBub2RlID09PSBcInN0cmluZ1wiKSByZXR1cm4gZmFsc2U7XG4gIGlmIChBcnJheS5pc0FycmF5KG5vZGUpKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBsaXN0S2luZChub2RlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gcmVuZGVyTGlzdChpdGVtczogcmVhZG9ubHkgRGVzY3JpcHRpb25bXSwgcGFkOiBzdHJpbmcsIGtpbmQ6IExpc3RLaW5kKTogc3RyaW5nIHtcbiAgaWYgKGl0ZW1zLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFwiXCI7XG4gIGlmIChpdGVtcy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGl0ZW1zWzBdID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIHByZXBlbmRQYWQoaXRlbXNbMF0sIHBhZCk7XG4gIH1cbiAgY29uc3QgbGluZXM6IHN0cmluZ1tdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICBjb25zdCBpdGVtID0gaXRlbXNbaV0hO1xuICAgIGNvbnN0IG1hcmtlciA9IGtpbmQgPT09IFwiYnVsbGV0c1wiID8gXCItIFwiIDogYCR7aSArIDF9LiBgO1xuICAgIGNvbnN0IGJvZHkgPSByZW5kZXJCbG9jayhpdGVtLCBcIlwiKTtcbiAgICBjb25zdCBib2R5TGluZXMgPSBib2R5LnNwbGl0KFwiXFxuXCIpO1xuICAgIGxpbmVzLnB1c2goYCR7cGFkfSR7bWFya2VyfSR7Ym9keUxpbmVzWzBdID8/IFwiXCJ9YCk7XG4gICAgY29uc3QgY29udGludWF0aW9uID0gcGFkICsgXCIgXCIucmVwZWF0KG1hcmtlci5sZW5ndGgpO1xuICAgIGZvciAoY29uc3QgbGluZSBvZiBib2R5TGluZXMuc2xpY2UoMSkpIHtcbiAgICAgIGxpbmVzLnB1c2gobGluZSA/IGAke2NvbnRpbnVhdGlvbn0ke2xpbmV9YCA6IFwiXCIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbGluZXMuam9pbihcIlxcblwiKTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyTWFwKG5vZGU6IFJlY29yZDxzdHJpbmcsIERlc2NyaXB0aW9uPiwgcGFkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBbaGVhZGVyLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMobm9kZSkpIHtcbiAgICBjb25zdCBib2R5ID0gcmVuZGVyQmxvY2sodmFsdWUsIHBhZCk7XG4gICAgaWYgKCFib2R5ICYmICFoZWFkZXIudHJpbSgpKSBjb250aW51ZTtcbiAgICBjb25zdCBoZWFkZXJMaW5lID0gaGVhZGVyLnRyaW0oKSA/IGAke3BhZH0ke2hlYWRlcn06YCA6IFwiXCI7XG4gICAgcGFydHMucHVzaChib2R5ID8gYCR7aGVhZGVyTGluZX1cXG5cXG4ke2JvZHl9YCA6IGhlYWRlckxpbmUpO1xuICB9XG4gIHJldHVybiBwYXJ0cy5qb2luKFwiXFxuXFxuXCIpO1xufVxuXG4vKipcbiAqIEZvcm1hdCBhIGNvdW50IHdpdGggaXRzIG5vdW4sIHBsdXJhbGl6aW5nIChuYWl2ZSBgK3NgKSB1bmxlc3MgdGhlIGNvdW50IGlzIDE6XG4gKiBgcGx1cmFsaXplKDEsIFwiYmFycmVsXCIpYCAtPiBgXCIxIGJhcnJlbFwiYCwgYHBsdXJhbGl6ZSgzLCBcImJhcnJlbFwiKWAgLT5cbiAqIGBcIjMgYmFycmVsc1wiYC4gQ29sbGFwc2VzIHRoZSBgJHtufSBub3VuJHtuID09PSAxID8gXCJcIiA6IFwic1wifWAgaWRpb20uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwbHVyYWxpemUoY291bnQ6IG51bWJlciwgbm91bjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2NvdW50fSAke25vdW59JHtjb3VudCA9PT0gMSA/IFwiXCIgOiBcInNcIn1gO1xufVxuXG4vKipcbiAqIFRpdGxlLWNhc2UgYSBzbmFrZSAvIGtlYmFiIC8gY2FtZWwgaWRlbnRpZmllciBpbnRvIGEgaHVtYW4tcmVhZGFibGUgbGFiZWw6XG4gKiB0b2tlbml6ZSAobG93ZXJjYXNlZCwgY2FwaXRhbGl6ZWQpLCB0aGVuIGpvaW4gd2l0aCBzcGFjZXMuIEZhbGxzIGJhY2sgdG9cbiAqIHRoZSByYXcgYHZhbHVlYCB3aGVuIGl0IHlpZWxkcyBubyB0b2tlbnMgKGUuZy4gcHVuY3R1YXRpb24tb25seSBpbnB1dCkuXG4gKiBgYmdlX2xhcmdlX2VuYCAtPiBgXCJCZ2UgTGFyZ2UgRW5cImAsIGBwcm9tcHRJZGAgLT4gYFwiUHJvbXB0IElkXCJgLlxuICpcbiAqIFRoZSBzaW5nbGUgc291cmNlIG9mIHRydXRoIGZvciB0aGUgXCJodW1hbml6ZSBhIGNvbHVtbiAvIGZpZWxkIG5hbWVcIiBpZGlvbSAtXG4gKiByZXVzZWQgYnkgdGhlIGNoYXQgZGF0YS1ncmlkIGhlYWRlcnMgYW5kIHRoZSBleHBvcnQgcmVuZGVyZXIuIEV4dHJhXG4gKiB7QGxpbmsgVG9rZW5pemVPcHRpb25zfSAoZS5nLiBgY2FtZWxDYXNlOiBmYWxzZWApIG1lcmdlIG92ZXIgdGhlIGRlZmF1bHRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9MYWJlbCh2YWx1ZTogc3RyaW5nLCBvcHRpb25zPzogVG9rZW5pemVPcHRpb25zKTogc3RyaW5nIHtcbiAgY29uc3QgdG9rZW5zID0gWy4uLnRva2VuaXplV2l0aE9wdGlvbnMoeyBsb3dlckNhc2U6IHRydWUsIGNhcGl0YWxpemU6IHRydWUsIC4uLm9wdGlvbnMgfSwgdmFsdWUpXTtcbiAgcmV0dXJuIHRva2Vucy5sZW5ndGggPiAwID8gdG9rZW5zLmpvaW4oXCIgXCIpIDogdmFsdWU7XG59XG5cbi8qKlxuICogVXBwZXItY2FzZSB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGB2YWx1ZWAsIGxlYXZpbmcgdGhlIHJlc3QgdW50b3VjaGVkLlxuICogYFwid29ya2luZ1wiYCAtPiBgXCJXb3JraW5nXCJgLiBDb2xsYXBzZXMgdGhlXG4gKiBgcy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHMuc2xpY2UoMSlgIGlkaW9tLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FwaXRhbGl6ZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHZhbHVlID8gdmFsdWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyB2YWx1ZS5zbGljZSgxKSA6IHZhbHVlO1xufVxuIl19
@@ -1 +1 @@
1
- {"root":["../src/async.ts","../src/brand.ts","../src/error.ts","../src/execution.ts","../src/function.ts","../src/hash.ts","../src/http.ts","../src/json.ts","../src/log.ts","../src/net.ts","../src/object.ts","../src/pattern.ts","../src/predicate.ts","../src/string.ts","../src/token.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/async-utils.ts","../src/brand-utils.ts","../src/error-utils.ts","../src/execution.ts","../src/function-utils.ts","../src/hash.ts","../src/http.ts","../src/json.ts","../src/log.ts","../src/net.ts","../src/object.ts","../src/pattern.ts","../src/predicate.ts","../src/string-utils.ts","../src/token.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "projen": "projen"
20
20
  },
21
21
  "devDependencies": {
22
- "@dbx-tools/test-polyglot": "^0.9.5",
22
+ "@dbx-tools/test-polyglot": "^0.9.6",
23
23
  "@types/bun": "1.3.14",
24
24
  "@types/node": "^24.6.0",
25
25
  "typescript": "^5.9.3"
@@ -41,7 +41,7 @@
41
41
  "./package.json": "./package.json"
42
42
  }
43
43
  },
44
- "version": "0.9.5",
44
+ "version": "0.9.6",
45
45
  "types": "./lib/index.d.ts",
46
46
  "type": "module",
47
47
  "exports": {