Version 2.9.0-3.0.dev
Merge commit '65a944f78fa7f45946d3fcd306bc7840ade80615' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7bd6b44..1aa6464 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,25 @@
-## 2.8.0
+## 2.9.0
+
+### Language
+
+### Core libraries
+
+#### `dart:html`
+
+* **Breaking Change**: `CssClassSet.add()` previously returned `null` if the
+ `CssClassSet` corresponded to multiple elements. In order to align with the
+ null-safe changes in the `Set` interface, it will now return `false`
+ instead. The same applies for `CssClassSet.toggle`.
+
+#### `dart:io`
+
+* Class `OSError` now implements `Exception`. This change means `OSError` will
+ now be caught in catch clauses catching `Exception`s.
+
+### Dart VM
+
+
+## 2.8.0 - 2020-04-29
Much of the changes in this release are in preparation for non-nullable types,
which will arrive in a future version. In anticipation of that, we have made a
@@ -109,18 +130,10 @@
of `Node`, even though it was not returning anything. This has been
corrected to `void`.
-* **Breaking Change**: `CssClassSet.add()` previously returned `null` if the
- `CssClassSet` corresponded to multiple elements. In order to align with the
- null-safe changes in the `Set` interface, it will now return `false`
- instead. The same applies for `CssClassSet.toggle`.
-
[#39627]: https://github.com/dart-lang/sdk/issues/39627
#### `dart:io`
-* Class `OSError` now implements `Exception`. This change means `OSError` will
- now be caught in catch clauses catching `Exception`s.
-
* Class `HttpParser` will no longer throw an exception when a HTTP response
status code is within [0, 999]. Customized status codes in this range are
now valid.
@@ -2885,7 +2898,7 @@
* `dart:web_audio`
- * new method on `AudioContext` – `createIirFilter` returns a new class
+ * new method on `AudioContext` - `createIirFilter` returns a new class
`IirFilterNode`.
* `dart:web_gl`
@@ -4037,8 +4050,8 @@
### Tool changes
* Dartium and content shell
- * The Chrome-based tools that ship as part of the Dart SDK – Dartium and
- content shell – are now based on Chrome version 45 (instead of Chrome 39).
+ * The Chrome-based tools that ship as part of the Dart SDK - Dartium and
+ content shell - are now based on Chrome version 45 (instead of Chrome 39).
* Dart browser libraries (`dart:html`, `dart:svg`, etc) *have not* been
updated.
* These are still based on Chrome 39.
@@ -4582,7 +4595,7 @@
dart2dart (aka `dart2js --output-type=dart`) utility as part
of dart2js
-## 1.10.0 – 2015-04-29
+## 1.10.0 - 2015-04-29
### Core library changes
@@ -4621,7 +4634,7 @@
* On Mac and Linux, signals sent to `pub run` and forwarded to the child
command.
-## 1.9.3 – 2015-04-14
+## 1.9.3 - 2015-04-14
This is a bug fix release which merges a number of commits from `bleeding_edge`.
@@ -4646,7 +4659,7 @@
Pub can fail to load transformers necessary for local development -
[r44876](https://code.google.com/p/dart/source/detail?r=44876)
-## 1.9.1 – 2015-03-25
+## 1.9.1 - 2015-03-25
### Language changes
@@ -4760,7 +4773,7 @@
* Isolates spawned via `Isolate.spawn` now allow most objects, including
top-level and static functions, to be sent between them.
-## 1.8.5 – 2015-01-21
+## 1.8.5 - 2015-01-21
* Code generation for SIMD on ARM and ARM64 is fixed.
@@ -4770,7 +4783,7 @@
[issue 21795]: https://code.google.com/p/dart/issues/detail?id=21795
-## 1.8.3 – 2014-12-10
+## 1.8.3 - 2014-12-10
* Breakpoints can be set in the Editor using file suffixes ([issue 21280][]).
@@ -4787,7 +4800,7 @@
[issue 21280]: https://code.google.com/p/dart/issues/detail?id=21280
[issue 21698]: https://code.google.com/p/dart/issues/detail?id=21698
-## 1.8.0 – 2014-11-28
+## 1.8.0 - 2014-11-28
* `dart:collection`: `SplayTree` added the `toSet` function.
@@ -4828,7 +4841,7 @@
[alpn]: https://tools.ietf.org/html/rfc7301
-## 1.7.0 – 2014-10-15
+## 1.7.0 - 2014-10-15
### Tool changes
diff --git a/DEPS b/DEPS
index 3b96c94..232f736 100644
--- a/DEPS
+++ b/DEPS
@@ -86,7 +86,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164
"dart_style_tag": "1.3.2", # Please see the note above before updating.
- "dartdoc_tag" : "v0.30.4",
+ "dartdoc_tag" : "v0.31.0",
"ffi_tag": "ea88d71b043ee14b268c3aedff14e9eb32e20959",
"fixnum_tag": "0.10.9",
"glob_tag": "1.1.7",
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index b073f3b..fbacec0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -517,6 +517,13 @@
/// state.
bool isUnassigned(Variable variable);
+ /// Call this method before visiting a labeled statement.
+ /// Call [labeledStatement_end] after visiting the statement.
+ void labeledStatement_begin(Node node);
+
+ /// Call this method after visiting a labeled statement.
+ void labeledStatement_end();
+
/// Call this method after visiting the RHS of a logical binary operation
/// ("||" or "&&").
/// [wholeExpression] should be the whole logical binary expression.
@@ -938,6 +945,18 @@
}
@override
+ void labeledStatement_begin(Node node) {
+ return _wrap('labeledStatement_begin($node)',
+ () => _wrapped.labeledStatement_begin(node));
+ }
+
+ @override
+ void labeledStatement_end() {
+ return _wrap(
+ 'labeledStatement_end()', () => _wrapped.labeledStatement_end());
+ }
+
+ @override
void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
{@required bool isAnd}) {
_wrap(
@@ -1404,8 +1423,9 @@
VariableModel<Type> infoForVar = variableInfo[variable];
if (infoForVar == null) return this;
+ Type declaredType = typeOperations.variableType(variable);
VariableModel<Type> newInfoForVar =
- infoForVar.write(writtenType, typeOperations);
+ infoForVar.write(declaredType, writtenType, typeOperations);
if (identical(newInfoForVar, infoForVar)) return this;
return _updateVariableInfo(variable, newInfoForVar);
@@ -1737,8 +1757,8 @@
/// Returns a new [VariableModel] reflecting the fact that the variable was
/// just written to.
- VariableModel<Type> write(
- Type writtenType, TypeOperations<Object, Type> typeOperations) {
+ VariableModel<Type> write(Type declaredType, Type writtenType,
+ TypeOperations<Object, Type> typeOperations) {
List<Type> newPromotedTypes;
if (promotedTypes == null) {
newPromotedTypes = null;
@@ -1760,7 +1780,7 @@
}
}
newPromotedTypes = _tryPromoteToTypeOfInterest(
- typeOperations, newPromotedTypes, writtenType);
+ typeOperations, declaredType, newPromotedTypes, writtenType);
if (identical(promotedTypes, newPromotedTypes) && assigned) return this;
List<Type> newTested;
if (newPromotedTypes == null && promotedTypes != null) {
@@ -1787,8 +1807,14 @@
/// is required, a new promotion chain will be created and returned.
List<Type> _tryPromoteToTypeOfInterest(
TypeOperations<Object, Type> typeOperations,
+ Type declaredType,
List<Type> promotedTypes,
Type writtenType) {
+ if (writeCaptured) {
+ assert(promotedTypes == null);
+ return promotedTypes;
+ }
+
// Figure out if we have any promotion candidates (types that are a
// supertype of writtenType and a proper subtype of the currently-promoted
// type). If at any point we find an exact match, we take it immediately.
@@ -1830,6 +1856,16 @@
}
}
+ // The declared type is always a type of interest, but we never promote
+ // to the declared type. So, try NonNull of it.
+ Type declaredTypeNonNull = typeOperations.promoteToNonNull(declaredType);
+ if (!typeOperations.isSameType(declaredTypeNonNull, declaredType)) {
+ handleTypeOfInterest(declaredTypeNonNull);
+ if (result != null) {
+ return result;
+ }
+ }
+
for (int i = 0; i < tested.length; i++) {
Type type = tested[i];
@@ -1838,7 +1874,7 @@
return result;
}
- var typeNonNull = typeOperations.promoteToNonNull(type);
+ Type typeNonNull = typeOperations.promoteToNonNull(type);
if (!typeOperations.isSameType(typeNonNull, type)) {
handleTypeOfInterest(typeNonNull);
if (result != null) {
@@ -2443,6 +2479,21 @@
}
@override
+ void labeledStatement_begin(Node node) {
+ _BranchTargetContext<Variable, Type> context =
+ new _BranchTargetContext<Variable, Type>();
+ _stack.add(context);
+ _statementToContext[node] = context;
+ }
+
+ @override
+ void labeledStatement_end() {
+ _BranchTargetContext<Variable, Type> context =
+ _stack.removeLast() as _BranchTargetContext<Variable, Type>;
+ _current = _join(_current, context._breakModel);
+ }
+
+ @override
void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
{@required bool isAnd}) {
_BranchContext<Variable, Type> context =
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 99e57f3..ae5b0e2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -3435,9 +3435,6 @@
Location of the SDK sources for use when compiling additional platform
libraries.
- --supermixin
- Ignored for now.
-
--single-root-scheme=String
--single-root-base=<dir>
Specify a custom URI scheme and a location on disk where such URIs are
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
index b56e507..75be976 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
@@ -630,7 +630,7 @@
if (atEndOfFile()) {
appendEofToken();
} else {
- unexpected($EOF);
+ unexpectedEof();
}
}
@@ -1778,6 +1778,11 @@
}
}
+ void unexpectedEof() {
+ ErrorToken errorToken = buildUnexpectedCharacterToken($EOF, tokenStart);
+ prependErrorToken(errorToken);
+ }
+
void unterminatedString(int quoteChar, int quoteStart, int start,
{bool asciiOnly, bool isMultiLine, bool isRaw}) {
String suffix = new String.fromCharCodes(
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/labeled_statement.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/labeled_statement.dart
new file mode 100644
index 0000000..3417f11
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/labeled_statement.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+block_break(bool c) {
+ late int v;
+ label:
+ {
+ if (c) {
+ break label;
+ }
+ v = 0;
+ return;
+ }
+ /*unassigned*/ v;
+}
+
+if_break(bool c) {
+ late int v;
+ label:
+ if (c) {
+ if (c) {
+ break label;
+ }
+ v = 0;
+ return;
+ }
+ /*unassigned*/ v;
+}
+
+try_break(bool c) {
+ late int v;
+ label:
+ try {
+ if (c) {
+ break label;
+ }
+ v = 0;
+ return;
+ } finally {}
+ /*unassigned*/ v;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index fc831aa..8676e22 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -856,6 +856,41 @@
});
});
+ test('labeledBlock without break', () {
+ var h = _Harness();
+ var x = h.addVar('x', 'int?');
+ var block = _Statement();
+ h.run((flow) {
+ h.declare(x, initialized: true);
+
+ h.ifIsNotType(x, 'int', () {
+ h.labeledBlock(block, () {
+ flow.handleExit();
+ });
+ });
+ expect(flow.promotedType(x).type, 'int');
+ });
+ });
+
+ test('labeledBlock with break joins', () {
+ var h = _Harness();
+ var x = h.addVar('x', 'int?');
+ var block = _Statement();
+ h.run((flow) {
+ h.declare(x, initialized: true);
+
+ h.ifIsNotType(x, 'int', () {
+ h.labeledBlock(block, () {
+ h.if_(h.expr, () {
+ flow.handleBreak(block);
+ });
+ flow.handleExit();
+ });
+ });
+ expect(flow.promotedType(x), isNull);
+ });
+ });
+
test('logicalBinaryOp_rightBegin(isAnd: true) promotes in RHS', () {
var h = _Harness();
var x = h.addVar('x', 'int?');
@@ -1931,6 +1966,42 @@
});
group('Promotes to NonNull of a type of interest', () {
+ test('when declared type', () {
+ var h = _Harness();
+ var x = _Var('x', _Type('int?'));
+
+ var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+ expect(s1.variableInfo, {
+ x: _matchVariableModel(chain: null),
+ });
+
+ var s2 = s1.write(x, _Type('int'), h);
+ expect(s2.variableInfo, {
+ x: _matchVariableModel(chain: ['int']),
+ });
+ });
+
+ test('when declared type, if write-captured', () {
+ var h = _Harness();
+ var x = h.addVar('x', 'int?');
+
+ var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+ expect(s1.variableInfo, {
+ x: _matchVariableModel(chain: null),
+ });
+
+ var s2 = s1.removePromotedAll([], [x]);
+ expect(s2.variableInfo, {
+ x: _matchVariableModel(chain: null, writeCaptured: true),
+ });
+
+ // 'x' is write-captured, so not promoted
+ var s3 = s2.write(x, _Type('int'), h);
+ expect(s3.variableInfo, {
+ x: _matchVariableModel(chain: null, writeCaptured: true),
+ });
+ });
+
test('when promoted', () {
var h = _Harness();
var s1 = FlowModel<_Var, _Type>(true)
@@ -2018,19 +2089,27 @@
// class A {}
// class B extends A {}
// class C extends B {}
+ h.addSubtype(_Type('Object'), _Type('A'), false);
+ h.addSubtype(_Type('Object'), _Type('A?'), false);
+ h.addSubtype(_Type('Object'), _Type('B?'), false);
+ h.addSubtype(_Type('A'), _Type('Object'), true);
h.addSubtype(_Type('A'), _Type('Object?'), true);
h.addSubtype(_Type('A'), _Type('A?'), true);
h.addSubtype(_Type('A'), _Type('B?'), false);
+ h.addSubtype(_Type('A?'), _Type('Object'), false);
h.addSubtype(_Type('A?'), _Type('Object?'), true);
h.addSubtype(_Type('A?'), _Type('A'), false);
h.addSubtype(_Type('A?'), _Type('B?'), false);
+ h.addSubtype(_Type('B'), _Type('Object'), true);
h.addSubtype(_Type('B'), _Type('A'), true);
h.addSubtype(_Type('B'), _Type('A?'), true);
h.addSubtype(_Type('B'), _Type('B?'), true);
+ h.addSubtype(_Type('B?'), _Type('Object'), false);
h.addSubtype(_Type('B?'), _Type('Object?'), true);
h.addSubtype(_Type('B?'), _Type('A'), false);
h.addSubtype(_Type('B?'), _Type('A?'), true);
h.addSubtype(_Type('B?'), _Type('B'), false);
+ h.addSubtype(_Type('C'), _Type('Object'), true);
h.addSubtype(_Type('C'), _Type('A'), true);
h.addSubtype(_Type('C'), _Type('A?'), true);
h.addSubtype(_Type('C'), _Type('B'), true);
@@ -2856,7 +2935,7 @@
test('assigned', () {
var h = _Harness();
var intQModel = model([intQType]);
- var writtenModel = intQModel.write(_Type('Object?'), h);
+ var writtenModel = intQModel.write(intQType, _Type('Object?'), h);
var p1 = {x: writtenModel, y: writtenModel, z: intQModel, w: intQModel};
var p2 = {x: writtenModel, y: intQModel, z: writtenModel, w: intQModel};
var joined = FlowModel.joinVariableInfo(h, p1, p2);
@@ -3017,6 +3096,7 @@
'int? <: int': false,
'int? <: num': false,
'int? <: num?': true,
+ 'int? <: Object': false,
'int? <: Object?': true,
'num <: int': false,
'num <: Iterable': false,
@@ -3028,9 +3108,11 @@
'num? <: int?': false,
'num? <: num': false,
'num? <: num*': true,
+ 'num? <: Object': false,
'num? <: Object?': true,
'num* <: num': true,
'num* <: num?': true,
+ 'num* <: Object': true,
'num* <: Object?': true,
'Iterable <: int': false,
'Iterable <: num': false,
@@ -3040,9 +3122,12 @@
'List <: Iterable': true,
'List <: Object': true,
'Object <: int': false,
+ 'Object <: int?': false,
'Object <: List': false,
'Object <: num': false,
+ 'Object <: num?': false,
'Object <: Object?': true,
+ 'Object? <: Object': false,
'Object? <: int': false,
'Object? <: int?': false,
'String <: int': false,
@@ -3150,6 +3235,11 @@
_flow.ifStatement_end(true);
}
+ /// Equivalent for `if (variable is! type) { ifTrue; }`
+ void ifIsNotType(_Var variable, String type, void ifTrue()) {
+ if_(isNotType(variableRead(variable), type), ifTrue);
+ }
+
/// Creates a [LazyExpression] representing an `is!` check, checking whether
/// [subExpression] has the given [type].
LazyExpression isNotType(LazyExpression subExpression, String type) {
@@ -3182,6 +3272,13 @@
};
}
+ /// Invokes flow analysis of a labeled block.
+ void labeledBlock(_Statement node, void body()) {
+ _flow.labeledStatement_begin(node);
+ body();
+ _flow.labeledStatement_end();
+ }
+
/// Creates a [LazyExpression] representing an equality check between two
/// other expressions.
LazyExpression notEqual(LazyExpression lhs, LazyExpression rhs) {
@@ -3230,7 +3327,7 @@
/// Causes [variable] to be promoted to [type].
void promote(_Var variable, String type) {
- if_(isNotType(variableRead(variable), type), _flow.handleExit);
+ ifIsNotType(variable, type, _flow.handleExit);
}
@override
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/labeled_statement.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/labeled_statement.dart
new file mode 100644
index 0000000..a8faf57
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/labeled_statement.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+block_break(int? x, bool c) {
+ label:
+ {
+ if (x == null) {
+ if (c) {
+ break label;
+ }
+ return;
+ }
+ }
+ x;
+}
+
+if_break(int? x, bool c) {
+ label:
+ if (true) {
+ if (x == null) {
+ if (c) {
+ break label;
+ }
+ return;
+ }
+ }
+ x;
+}
+
+try_break(int? x, bool c) {
+ label:
+ try {
+ if (x == null) {
+ if (c) {
+ break label;
+ }
+ return;
+ }
+ } finally {}
+ x;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/labeled_statement.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/labeled_statement.dart
new file mode 100644
index 0000000..c5eccbe
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/labeled_statement.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+block_break(bool b) {
+ label:
+ {
+ if (b) {
+ break label;
+ }
+ return;
+ }
+ 1;
+}
+
+if_break(bool b) {
+ label:
+ if (true) {
+ if (b) {
+ break label;
+ }
+ return;
+ }
+ 1;
+}
+
+try_break(bool b) {
+ label:
+ try {
+ if (b) {
+ break label;
+ }
+ return;
+ } finally {
+ 1;
+ }
+ 2;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart
index b691511..1a1a094 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart
@@ -41,9 +41,14 @@
x;
}
-notATypeOfInterest_nullability(Object? x) {
+typeOfInterest_declaredNullable_exact(int? x) {
x = 1;
- x;
+ /*int*/ x;
+}
+
+typeOfInterest_declaredNullable_subtype(Object? x) {
+ x = 1;
+ /*Object*/ x;
}
typeOfInterest_notEqualNull(Object? x) {
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart
index c416f58..6446c09 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart
@@ -12,12 +12,9 @@
/*member: B.i=:int**/
}
-/// TODO: Solve CFE / analyzer difference.
-/// I suspect that this is a bug in analyzer.
-/// We check `i` against separate signatures from `NULLABLE` and `NONNULLABLE`.
/*class: C:A,C,NONNULLABLE,NULLABLE,Object*/
class C extends A {
/*member: C.i:int?*/
/*member: C.i=:int?*/
- int? /*analyzer.error: CompileTimeErrorCode.INVALID_OVERRIDE*/ i;
+ int? i;
}
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 0655cf8..2e32b66 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -10,10 +10,12 @@
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
import 'package:analyzer/dart/element/element.dart' show LibraryElement;
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/micro/resolve_file.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:meta/meta.dart';
/// The cache that can be reuse for across multiple completion request.
///
@@ -29,12 +31,47 @@
final FileResolver _fileResolver;
DartCompletionRequestImpl _dartCompletionRequest;
+ final List<String> _computedImportedLibraries = [];
CiderCompletionComputer(this._logger, this._cache, this._fileResolver);
+ @deprecated
Future<List<CompletionSuggestion>> compute(String path, int offset) async {
+ var file = _fileResolver.resourceProvider.getFile(path);
+ var content = file.readAsStringSync();
+
+ var lineInfo = LineInfo.fromContent(content);
+ var location = lineInfo.getLocation(offset);
+
+ var result = await compute2(
+ path: path,
+ line: location.lineNumber - 1,
+ character: location.columnNumber - 1,
+ );
+
+ return result.suggestions;
+ }
+
+ /// Return completion suggestions for the file and position.
+ ///
+ /// The [path] must be the absolute and normalized path of the file.
+ ///
+ /// The content of the file has already been updated.
+ ///
+ /// The [line] and [character] are zero based.
+ Future<CiderCompletionResult> compute2({
+ @required String path,
+ @required int line,
+ @required int character,
+ }) async {
+ var file = _fileResolver.resourceProvider.getFile(path);
+ var content = file.readAsStringSync();
+
var resolvedUnit = _fileResolver.resolve(path);
+ var lineInfo = LineInfo.fromContent(content);
+ var offset = lineInfo.getOffsetOfLine(line) + character;
+
var completionRequest = CompletionRequestImpl(
resolvedUnit,
offset,
@@ -71,7 +108,10 @@
);
});
- return suggestions;
+ return CiderCompletionResult._(
+ suggestions,
+ _computedImportedLibraries,
+ );
}
/// Return suggestions from libraries imported into the [target].
@@ -99,6 +139,7 @@
var cacheEntry = _cache._importedLibraries[path];
if (cacheEntry == null || cacheEntry.signature != signature) {
+ _computedImportedLibraries.add(path);
var suggestions = _librarySuggestions(element);
cacheEntry = _CiderImportedLibrarySuggestions(
signature,
@@ -124,7 +165,16 @@
class CiderCompletionResult {
final List<CompletionSuggestion> suggestions;
- CiderCompletionResult(this.suggestions);
+ /// Paths of imported libraries for which suggestions were (re)computed
+ /// during processing of this request. Does not include libraries that were
+ /// processed during previous requests, and reused from the cache now.
+ @visibleForTesting
+ final List<String> computedImportedLibraries;
+
+ CiderCompletionResult._(
+ this.suggestions,
+ this.computedImportedLibraries,
+ );
}
class _CiderImportedLibrarySuggestions {
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
index 335e0c9..629cb25 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
@@ -61,8 +61,8 @@
</div><!-- /panels -->
<footer>
<a target="_blank"
- href="https://github.com/dart-lang/sdk/blob/master/pkg/nnbd_migration/README.md">Null
- safety migration help</a>
+ href="https://goo.gle/dart-null-safety-migration-tool">Null safety
+ migration help</a>
<span class="wide"> </span>
<div>Based on {{ sdkVersion }}</div>
</footer>
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
index 821e26a..fa4b09e 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
@@ -270,7 +270,7 @@
''';
String _index_html;
-// index_html md5 is 'b80e110b4fee8e204eeefbfcffeeff7c'
+// index_html md5 is '2cf3e3cd2e7c2331a600c030c2976c58'
String _index_html_base64 = '''
PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
@@ -313,11 +313,10 @@
Y2Vob2xkZXIiPlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC48L3A+CiAgICAgICAgICAg
IDwvZGl2PjwhLS0gL3BhbmVsLWNvbnRlbnQgLS0+CiAgICAgICAgPC9kaXY+PCEtLSAvZWRpdC1wYW5l
bCAtLT4KICAgIDwvZGl2PjwhLS0gL2luZm8tcGFuZWwgLS0+CjwvZGl2PjwhLS0gL3BhbmVscyAtLT4K
-PGZvb3Rlcj4KICAgIDxhIHRhcmdldD0iX2JsYW5rIgogICAgICAgaHJlZj0iaHR0cHM6Ly9naXRodWIu
-Y29tL2RhcnQtbGFuZy9zZGsvYmxvYi9tYXN0ZXIvcGtnL25uYmRfbWlncmF0aW9uL1JFQURNRS5tZCI+
-TnVsbAogICAgICAgIHNhZmV0eSBtaWdyYXRpb24gaGVscDwvYT4KICAgIDxzcGFuIGNsYXNzPSJ3aWRl
-Ij4gPC9zcGFuPgogICAgPGRpdj5CYXNlZCBvbiB7eyBzZGtWZXJzaW9uIH19PC9kaXY+CjwvZm9vdGVy
-Pgo8L2JvZHk+CjwvaHRtbD4K
+PGZvb3Rlcj4KICAgIDxhIHRhcmdldD0iX2JsYW5rIgogICAgICBocmVmPSJodHRwczovL2dvby5nbGUv
+ZGFydC1udWxsLXNhZmV0eS1taWdyYXRpb24tdG9vbCI+TnVsbCBzYWZldHkKICAgICAgICBtaWdyYXRp
+b24gaGVscDwvYT4KICAgIDxzcGFuIGNsYXNzPSJ3aWRlIj4gPC9zcGFuPgogICAgPGRpdj5CYXNlZCBv
+biB7eyBzZGtWZXJzaW9uIH19PC9kaXY+CjwvZm9vdGVyPgo8L2JvZHk+CjwvaHRtbD4K
''';
String _migration_css;
@@ -531,12 +530,12 @@
czpzZXRPclVwZGF0ZUxlYWZUYWdzfX0oKQpmdW5jdGlvbiBpbml0aWFsaXplRGVmZXJyZWRIdW5rKGEp
e3g9di50eXBlcy5sZW5ndGgKYShodW5rSGVscGVycyx2LHcsJCl9ZnVuY3Rpb24gZ2V0R2xvYmFsRnJv
bU5hbWUoYSl7Zm9yKHZhciB0PTA7dDx3Lmxlbmd0aDt0Kyspe2lmKHdbdF09PUMpY29udGludWUKaWYo
-d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17Rks6ZnVuY3Rpb24gRksoKXt9LApvbzpm
+d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17ZW86ZnVuY3Rpb24gZW8oKXt9LApvbzpm
dW5jdGlvbihhKXt2YXIgdCxzPWFeNDgKaWYoczw9OSlyZXR1cm4gcwp0PWF8MzIKaWYoOTc8PXQmJnQ8
PTEwMilyZXR1cm4gdC04NwpyZXR1cm4tMX0sCnFDOmZ1bmN0aW9uKGEsYixjLGQpe1AuazEoYiwic3Rh
cnQiKQppZihjIT1udWxsKXtQLmsxKGMsImVuZCIpCmlmKGI+YylILlZqKFAuVEUoYiwwLGMsInN0YXJ0
IixudWxsKSl9cmV0dXJuIG5ldyBILm5IKGEsYixjLGQuQygibkg8MD4iKSl9LApLMTpmdW5jdGlvbihh
-LGIsYyxkKXtpZih1Lmd3LmIoYSkpcmV0dXJuIG5ldyBILnh5KGEsYixjLkMoIkA8MD4iKS5LKGQpLkMo
+LGIsYyxkKXtpZih1Lmd3LmMoYSkpcmV0dXJuIG5ldyBILnh5KGEsYixjLkMoIkA8MD4iKS5LKGQpLkMo
Inh5PDEsMj4iKSkKcmV0dXJuIG5ldyBILmkxKGEsYixjLkMoIkA8MD4iKS5LKGQpLkMoImkxPDEsMj4i
KSl9LApXcDpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5saigiTm8gZWxlbWVudCIpfSwKZFU6ZnVuY3Rp
b24oKXtyZXR1cm4gbmV3IFAubGooIlRvbyBtYW55IGVsZW1lbnRzIil9LAphcjpmdW5jdGlvbigpe3Jl
@@ -546,723 +545,682 @@
YTcoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCmkx
OmZ1bmN0aW9uIGkxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKeHk6ZnVuY3Rp
b24geHkoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApNSDpmdW5jdGlvbiBNSChh
-LGIsYyl7dmFyIF89dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9YgpfLiR0aT1jfSwKbEo6ZnVuY3Rpb24g
-bEooYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApVNTpmdW5jdGlvbiBVNShhLGIs
-Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCnZHOmZ1bmN0aW9uIHZHKGEsYixjKXt0aGlz
+LGIsYyl7dmFyIF89dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9YgpfLiR0aT1jfSwKQTg6ZnVuY3Rpb24g
+QTgoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApVNTpmdW5jdGlvbiBVNShhLGIs
+Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sClNPOmZ1bmN0aW9uIFNPKGEsYixjKXt0aGlz
LmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKU1U6ZnVuY3Rpb24gU1UoKXt9LApSZTpmdW5jdGlvbiBS
-ZSgpe30sCncyOmZ1bmN0aW9uIHcyKCl7fSwKd3Y6ZnVuY3Rpb24gd3YoYSl7dGhpcy5hPWF9LApkYzpm
+ZSgpe30sClhDOmZ1bmN0aW9uIFhDKCl7fSwKd3Y6ZnVuY3Rpb24gd3YoYSl7dGhpcy5hPWF9LApkYzpm
dW5jdGlvbigpe3Rocm93IEguYihQLkw0KCJDYW5ub3QgbW9kaWZ5IHVubW9kaWZpYWJsZSBNYXAiKSl9
LApOUTpmdW5jdGlvbihhKXt2YXIgdCxzPUguSmcoYSkKaWYodHlwZW9mIHM9PSJzdHJpbmciKXJldHVy
biBzCnQ9Im1pbmlmaWVkOiIrYQpyZXR1cm4gdH0sClh0OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYiE9
-bnVsbCl7dD1iLngKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gdS5hVS5iKGEpfSwKZDpmdW5jdGlv
+bnVsbCl7dD1iLngKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gdS5hVS5jKGEpfSwKZDpmdW5jdGlv
bihhKXt2YXIgdAppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJudW1i
ZXIiKXtpZihhIT09MClyZXR1cm4iIithfWVsc2UgaWYoITA9PT1hKXJldHVybiJ0cnVlIgplbHNlIGlm
-KCExPT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIKdD1KLkFjKGEp
-CmlmKHR5cGVvZiB0IT0ic3RyaW5nIil0aHJvdyBILmIoSC50TChhKSkKcmV0dXJuIHR9LAplUTpmdW5j
-dGlvbihhKXt2YXIgdD1hLiRpZGVudGl0eUhhc2gKaWYodD09bnVsbCl7dD1NYXRoLnJhbmRvbSgpKjB4
-M2ZmZmZmZmZ8MAphLiRpZGVudGl0eUhhc2g9dH1yZXR1cm4gdH0sCkhwOmZ1bmN0aW9uKGEsYil7dmFy
-IHQscyxyLHEscCxvLG49bnVsbAppZih0eXBlb2YgYSE9InN0cmluZyIpSC5WaihILnRMKGEpKQp0PS9e
-XHMqWystXT8oKDB4W2EtZjAtOV0rKXwoXGQrKXwoW2EtejAtOV0rKSlccyokL2kuZXhlYyhhKQppZih0
-PT1udWxsKXJldHVybiBuCmlmKDM+PXQubGVuZ3RoKXJldHVybiBILmsodCwzKQpzPUguYyh0WzNdKQpp
+KCExPT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIKdD1KLmooYSkK
+aWYodHlwZW9mIHQhPSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpyZXR1cm4gdH0sCmVROmZ1bmN0
+aW9uKGEpe3ZhciB0PWEuJGlkZW50aXR5SGFzaAppZih0PT1udWxsKXt0PU1hdGgucmFuZG9tKCkqMHgz
+ZmZmZmZmZnwwCmEuJGlkZW50aXR5SGFzaD10fXJldHVybiB0fSwKSHA6ZnVuY3Rpb24oYSxiKXt2YXIg
+dCxzLHIscSxwLG8sbj1udWxsCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILlZqKEgudEwoYSkpCnQ9L15c
+cypbKy1dPygoMHhbYS1mMC05XSspfChcZCspfChbYS16MC05XSspKVxzKiQvaS5leGVjKGEpCmlmKHQ9
+PW51bGwpcmV0dXJuIG4KaWYoMz49dC5sZW5ndGgpcmV0dXJuIEguT0godCwzKQpzPUgueSh0WzNdKQpp
ZihiPT1udWxsKXtpZihzIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZih0WzJdIT1udWxsKXJl
dHVybiBwYXJzZUludChhLDE2KQpyZXR1cm4gbn1pZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUoYiwy
LDM2LCJyYWRpeCIsbikpCmlmKGI9PT0xMCYmcyE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYo
YjwxMHx8cz09bnVsbCl7cj1iPD0xMD80NytiOjg2K2IKcT10WzFdCmZvcihwPXEubGVuZ3RoLG89MDtv
PHA7KytvKWlmKChDLnhCLldkKHEsbyl8MzIpPnIpcmV0dXJuIG59cmV0dXJuIHBhcnNlSW50KGEsYil9
-LApsaDpmdW5jdGlvbihhKXt2YXIgdD1ILkg1KGEpCnJldHVybiB0fSwKSDU6ZnVuY3Rpb24oYSl7dmFy
-IHQscyxyCmlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBILkooSC5xKGEpLG51bGwpCmlmKEouaWEo
-YSk9PT1DLk9rfHx1LmFrLmIoYSkpe3Q9Qy53YihhKQppZihILkJlKHQpKXJldHVybiB0CnM9YS5jb25z
-dHJ1Y3RvcgppZih0eXBlb2Ygcz09ImZ1bmN0aW9uIil7cj1zLm5hbWUKaWYodHlwZW9mIHI9PSJzdHJp
-bmciJiZILkJlKHIpKXJldHVybiByfX1yZXR1cm4gSC5KKEgucShhKSxudWxsKX0sCkJlOmZ1bmN0aW9u
-KGEpe3ZhciB0PWEhPT0iT2JqZWN0IiYmYSE9PSIiCnJldHVybiB0fSwKTTA6ZnVuY3Rpb24oKXtpZigh
-IXNlbGYubG9jYXRpb24pcmV0dXJuIHNlbGYubG9jYXRpb24uaHJlZgpyZXR1cm4gbnVsbH0sClZLOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YS5sZW5ndGgKaWYocDw9NTAwKXJldHVybiBTdHJpbmcuZnJv
-bUNoYXJDb2RlLmFwcGx5KG51bGwsYSkKZm9yKHQ9IiIscz0wO3M8cDtzPXIpe3I9cys1MDAKcT1yPHA/
-cjpwCnQrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhLnNsaWNlKHMscSkpfXJldHVybiB0
-fSwKQ3E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9SC5WTShbXSx1LnQpCmZvcih0PWEubGVuZ3RoLHM9
-MDtzPGEubGVuZ3RoO2EubGVuZ3RoPT09dHx8KDAsSC5saykoYSksKytzKXtyPWFbc10KaWYoIUgub2so
-cikpdGhyb3cgSC5iKEgudEwocikpCmlmKHI8PTY1NTM1KUMuTm0uQShxLHIpCmVsc2UgaWYocjw9MTEx
-NDExMSl7Qy5ObS5BKHEsNTUyOTYrKEMuam4ud0coci02NTUzNiwxMCkmMTAyMykpCkMuTm0uQShxLDU2
-MzIwKyhyJjEwMjMpKX1lbHNlIHRocm93IEguYihILnRMKHIpKX1yZXR1cm4gSC5WSyhxKX0sCmVUOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTA7czx0Oysrcyl7cj1hW3NdCmlmKCFI
-Lm9rKHIpKXRocm93IEguYihILnRMKHIpKQppZihyPDApdGhyb3cgSC5iKEgudEwocikpCmlmKHI+NjU1
-MzUpcmV0dXJuIEguQ3EoYSl9cmV0dXJuIEguVksoYSl9LApmdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQs
-cyxyLHEKaWYoYzw9NTAwJiZiPT09MCYmYz09PWEubGVuZ3RoKXJldHVybiBTdHJpbmcuZnJvbUNoYXJD
-b2RlLmFwcGx5KG51bGwsYSkKZm9yKHQ9YixzPSIiO3Q8Yzt0PXIpe3I9dCs1MDAKcT1yPGM/cjpjCnMr
-PVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhLnN1YmFycmF5KHQscSkpfXJldHVybiBzfSwK
-THc6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoMDw9YSl7aWYoYTw9NjU1MzUpcmV0dXJuIFN0cmluZy5mcm9t
-Q2hhckNvZGUoYSkKaWYoYTw9MTExNDExMSl7dD1hLTY1NTM2CnJldHVybiBTdHJpbmcuZnJvbUNoYXJD
-b2RlKCg1NTI5NnxDLmpuLndHKHQsMTApKT4+PjAsNTYzMjB8dCYxMDIzKX19dGhyb3cgSC5iKFAuVEUo
-YSwwLDExMTQxMTEsbnVsbCxudWxsKSl9LApvMjpmdW5jdGlvbihhKXtpZihhLmRhdGU9PT12b2lkIDAp
-YS5kYXRlPW5ldyBEYXRlKGEuYSkKcmV0dXJuIGEuZGF0ZX0sCnRKOmZ1bmN0aW9uKGEpe3JldHVybiBh
-LmI/SC5vMihhKS5nZXRVVENGdWxsWWVhcigpKzA6SC5vMihhKS5nZXRGdWxsWWVhcigpKzB9LApOUzpm
-dW5jdGlvbihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRDTW9udGgoKSsxOkgubzIoYSkuZ2V0TW9u
-dGgoKSsxfSwKakE6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYj9ILm8yKGEpLmdldFVUQ0RhdGUoKSswOkgu
-bzIoYSkuZ2V0RGF0ZSgpKzB9LApLTDpmdW5jdGlvbihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRD
-SG91cnMoKSswOkgubzIoYSkuZ2V0SG91cnMoKSswfSwKY2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYj9I
-Lm8yKGEpLmdldFVUQ01pbnV0ZXMoKSswOkgubzIoYSkuZ2V0TWludXRlcygpKzB9LApKZDpmdW5jdGlv
-bihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRDU2Vjb25kcygpKzA6SC5vMihhKS5nZXRTZWNvbmRz
-KCkrMH0sClZhOmZ1bmN0aW9uKGEpe3JldHVybiBhLmI/SC5vMihhKS5nZXRVVENNaWxsaXNlY29uZHMo
-KSswOkgubzIoYSkuZ2V0TWlsbGlzZWNvbmRzKCkrMH0sCnpvOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
-LHI9e30Kci5hPTAKdD1bXQpzPVtdCnIuYT1iLmxlbmd0aApDLk5tLkZWKHQsYikKci5iPSIiCmlmKGMh
-PW51bGwmJmMuYSE9PTApYy5VKDAsbmV3IEguQ2oocixzLHQpKQoiIityLmEKcmV0dXJuIEouSnkoYSxu
-ZXcgSC5MSShDLlRlLDAsdCxzLDApKX0sCkVrOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihi
-IGluc3RhbmNlb2YgQXJyYXkpdD1jPT1udWxsfHxjLmE9PT0wCmVsc2UgdD0hMQppZih0KXtzPWIKcj1z
-Lmxlbmd0aAppZihyPT09MCl7aWYoISFhLiQwKXJldHVybiBhLiQwKCl9ZWxzZSBpZihyPT09MSl7aWYo
-ISFhLiQxKXJldHVybiBhLiQxKHNbMF0pfWVsc2UgaWYocj09PTIpe2lmKCEhYS4kMilyZXR1cm4gYS4k
-MihzWzBdLHNbMV0pfWVsc2UgaWYocj09PTMpe2lmKCEhYS4kMylyZXR1cm4gYS4kMyhzWzBdLHNbMV0s
-c1syXSl9ZWxzZSBpZihyPT09NCl7aWYoISFhLiQ0KXJldHVybiBhLiQ0KHNbMF0sc1sxXSxzWzJdLHNb
-M10pfWVsc2UgaWYocj09PTUpaWYoISFhLiQ1KXJldHVybiBhLiQ1KHNbMF0sc1sxXSxzWzJdLHNbM10s
-c1s0XSkKcT1hWyIiKyIkIityXQppZihxIT1udWxsKXJldHVybiBxLmFwcGx5KGEscyl9cmV0dXJuIEgu
-RXcoYSxiLGMpfSwKRXc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPWIgaW5z
-dGFuY2VvZiBBcnJheT9iOlAuQ0goYiwhMCx1LnopLGo9ay5sZW5ndGgsaT1hLiRSCmlmKGo8aSlyZXR1
-cm4gSC56byhhLGssYykKdD1hLiRECnM9dD09bnVsbApyPSFzP3QoKTpudWxsCnE9Si5pYShhKQpwPXEu
-JEMKaWYodHlwZW9mIHA9PSJzdHJpbmciKXA9cVtwXQppZihzKXtpZihjIT1udWxsJiZjLmEhPT0wKXJl
-dHVybiBILnpvKGEsayxjKQppZihqPT09aSlyZXR1cm4gcC5hcHBseShhLGspCnJldHVybiBILnpvKGEs
-ayxjKX1pZihyIGluc3RhbmNlb2YgQXJyYXkpe2lmKGMhPW51bGwmJmMuYSE9PTApcmV0dXJuIEguem8o
-YSxrLGMpCmlmKGo+aStyLmxlbmd0aClyZXR1cm4gSC56byhhLGssbnVsbCkKQy5ObS5GVihrLHIuc2xp
-Y2Uoai1pKSkKcmV0dXJuIHAuYXBwbHkoYSxrKX1lbHNle2lmKGo+aSlyZXR1cm4gSC56byhhLGssYykK
-bz1PYmplY3Qua2V5cyhyKQppZihjPT1udWxsKWZvcihzPW8ubGVuZ3RoLG49MDtuPG8ubGVuZ3RoO28u
-bGVuZ3RoPT09c3x8KDAsSC5saykobyksKytuKUMuTm0uQShrLHJbSC5jKG9bbl0pXSkKZWxzZXtmb3Io
-cz1vLmxlbmd0aCxtPTAsbj0wO248by5sZW5ndGg7by5sZW5ndGg9PT1zfHwoMCxILmxrKShvKSwrK24p
-e2w9SC5jKG9bbl0pCmlmKGMueDQoMCxsKSl7KyttCkMuTm0uQShrLGMucSgwLGwpKX1lbHNlIEMuTm0u
-QShrLHJbbF0pfWlmKG0hPT1jLmEpcmV0dXJuIEguem8oYSxrLGMpfXJldHVybiBwLmFwcGx5KGEsayl9
-fSwKcFk6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKEgudEwoYSkpfSwKazpmdW5jdGlvbihhLGIpe2lmKGE9
-PW51bGwpSi5IKGEpCnRocm93IEguYihILkhZKGEsYikpfSwKSFk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
-LHI9ImluZGV4IgppZighSC5vayhiKSlyZXR1cm4gbmV3IFAuQVQoITAsYixyLG51bGwpCnQ9SC5XWShK
-LkgoYSkpCmlmKCEoYjwwKSl7aWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gSC5wWSh0KQpzPWI+
-PXR9ZWxzZSBzPSEwCmlmKHMpcmV0dXJuIFAudChiLGEscixudWxsLHQpCnJldHVybiBQLk83KGIscil9
-LAphdTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9IkludmFsaWQgdmFsdWUiCmlmKGE+YylyZXR1cm4gbmV3
-IFAuYkooMCxjLCEwLGEsInN0YXJ0Iix0KQppZihiIT1udWxsKXtpZighSC5vayhiKSlyZXR1cm4gbmV3
-IFAuQVQoITAsYiwiZW5kIixudWxsKQppZihiPGF8fGI+YylyZXR1cm4gbmV3IFAuYkooYSxjLCEwLGIs
-ImVuZCIsdCl9cmV0dXJuIG5ldyBQLkFUKCEwLGIsImVuZCIsbnVsbCl9LAp0TDpmdW5jdGlvbihhKXty
-ZXR1cm4gbmV3IFAuQVQoITAsYSxudWxsLG51bGwpfSwKYjpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1u
-dWxsKWE9bmV3IFAuTEsoKQp0PW5ldyBFcnJvcigpCnQuZGFydEV4Y2VwdGlvbj1hCmlmKCJkZWZpbmVQ
-cm9wZXJ0eSIgaW4gT2JqZWN0KXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCwibWVzc2FnZSIse2dldDpI
-Lkp1fSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1ILkp1CnJldHVybiB0fSwKSnU6ZnVuY3Rpb24o
-KXtyZXR1cm4gSi5BYyh0aGlzLmRhcnRFeGNlcHRpb24pfSwKVmo6ZnVuY3Rpb24oYSl7dGhyb3cgSC5i
-KGEpfSwKbGs6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAuYTQoYSkpfSwKY006ZnVuY3Rpb24oYSl7dmFy
-IHQscyxyLHEscCxvCmE9SC5lQShhLnJlcGxhY2UoU3RyaW5nKHt9KSwnJHJlY2VpdmVyJCcpKQp0PWEu
-bWF0Y2goL1xcXCRbYS16QS1aXStcXFwkL2cpCmlmKHQ9PW51bGwpdD1ILlZNKFtdLHUucykKcz10Lmlu
-ZGV4T2YoIlxcJGFyZ3VtZW50c1xcJCIpCnI9dC5pbmRleE9mKCJcXCRhcmd1bWVudHNFeHByXFwkIikK
-cT10LmluZGV4T2YoIlxcJGV4cHJcXCQiKQpwPXQuaW5kZXhPZigiXFwkbWV0aG9kXFwkIikKbz10Lmlu
-ZGV4T2YoIlxcJHJlY2VpdmVyXFwkIikKcmV0dXJuIG5ldyBILmY5KGEucmVwbGFjZShuZXcgUmVnRXhw
-KCdcXFxcXFwkYXJndW1lbnRzXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxhY2UobmV3
-IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c0V4cHJcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJyku
-cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkZXhwclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKikn
-KS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRtZXRob2RcXFxcXFwkJywnZycpLCcoKD86eHxbXnhd
-KSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkcmVjZWl2ZXJcXFxcXFwkJywnZycpLCcoKD86
-eHxbXnhdKSopJykscyxyLHEscCxvKX0sClM3OmZ1bmN0aW9uKGEpe3JldHVybiBmdW5jdGlvbigkZXhw
-ciQpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7JGV4cHIkLiRtZXRob2QkKCRh
-cmd1bWVudHNFeHByJCl9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKTWo6ZnVuY3Rpb24o
-YSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dHJ5eyRleHByJC4kbWV0aG9kJH1jYXRjaCh0KXtyZXR1
-cm4gdC5tZXNzYWdlfX0oYSl9LApJajpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5XMChhLGI9PW51
-bGw/bnVsbDpiLm1ldGhvZCl9LApUMzpmdW5jdGlvbihhLGIpe3ZhciB0PWI9PW51bGwscz10P251bGw6
-Yi5tZXRob2QKcmV0dXJuIG5ldyBILmF6KGEscyx0P251bGw6Yi5yZWNlaXZlcil9LApSdTpmdW5jdGlv
-bihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVsbCxlPW5ldyBILkFtKGEpCmlm
-KGE9PW51bGwpcmV0dXJuIGYKaWYoYSBpbnN0YW5jZW9mIEguYnEpcmV0dXJuIGUuJDEoYS5hKQppZih0
-eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlmKCJkYXJ0RXhjZXB0aW9uIiBpbiBhKXJldHVybiBl
-LiQxKGEuZGFydEV4Y2VwdGlvbikKZWxzZSBpZighKCJtZXNzYWdlIiBpbiBhKSlyZXR1cm4gYQp0PWEu
-bWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9PSJudW1iZXIiKXtzPWEubnVt
-YmVyCnI9cyY2NTUzNQppZigoQy5qbi53RyhzLDE2KSY4MTkxKT09PTEwKXN3aXRjaChyKXtjYXNlIDQz
-ODpyZXR1cm4gZS4kMShILlQzKEguZCh0KSsiIChFcnJvciAiK3IrIikiLGYpKQpjYXNlIDQ0NTpjYXNl
-IDUwMDc6cmV0dXJuIGUuJDEoSC5JaihILmQodCkrIiAoRXJyb3IgIityKyIpIixmKSl9fWlmKGEgaW5z
-dGFuY2VvZiBUeXBlRXJyb3Ipe3E9JC5TbigpCnA9JC5scSgpCm89JC5OOSgpCm49JC5pSSgpCm09JC5V
-TigpCmw9JC5aaCgpCms9JC5yTigpCiQuYzMoKQpqPSQuSEsoKQppPSQucjEoKQpoPXEucVModCkKaWYo
-aCE9bnVsbClyZXR1cm4gZS4kMShILlQzKEguYyh0KSxoKSkKZWxzZXtoPXAucVModCkKaWYoaCE9bnVs
-bCl7aC5tZXRob2Q9ImNhbGwiCnJldHVybiBlLiQxKEguVDMoSC5jKHQpLGgpKX1lbHNle2g9by5xUyh0
-KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1tLnFTKHQpCmlmKGg9PW51bGwpe2g9
-bC5xUyh0KQppZihoPT1udWxsKXtoPWsucVModCkKaWYoaD09bnVsbCl7aD1uLnFTKHQpCmlmKGg9PW51
-bGwpe2g9ai5xUyh0KQppZihoPT1udWxsKXtoPWkucVModCkKZz1oIT1udWxsfWVsc2UgZz0hMH1lbHNl
-IGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMAppZihn
-KXJldHVybiBlLiQxKEguSWooSC5jKHQpLGgpKX19cmV0dXJuIGUuJDEobmV3IEgudlYodHlwZW9mIHQ9
-PSJzdHJpbmciP3Q6IiIpKX1pZihhIGluc3RhbmNlb2YgUmFuZ2VFcnJvcil7aWYodHlwZW9mIHQ9PSJz
-dHJpbmciJiZ0LmluZGV4T2YoImNhbGwgc3RhY2siKSE9PS0xKXJldHVybiBuZXcgUC5LWSgpCnQ9ZnVu
-Y3Rpb24oYil7dHJ5e3JldHVybiBTdHJpbmcoYil9Y2F0Y2goZCl7fXJldHVybiBudWxsfShhKQpyZXR1
-cm4gZS4kMShuZXcgUC5BVCghMSxmLGYsdHlwZW9mIHQ9PSJzdHJpbmciP3QucmVwbGFjZSgvXlJhbmdl
-RXJyb3I6XHMqLywiIik6dCkpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9yPT0iZnVuY3Rpb24iJiZhIGlu
-c3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2YgdD09InN0cmluZyImJnQ9PT0idG9vIG11Y2gg
-cmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRzOmZ1bmN0aW9uKGEpe3ZhciB0
-CmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVsbClyZXR1cm4gbmV3IEguWE8o
-YSkKdD1hLiRjYWNoZWRUcmFjZQppZih0IT1udWxsKXJldHVybiB0CnJldHVybiBhLiRjYWNoZWRUcmFj
-ZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9YS5sZW5ndGgKZm9yKHQ9
-MDt0PHE7dD1yKXtzPXQrMQpyPXMrMQpiLnQoMCxhW3RdLGFbc10pfXJldHVybiBifSwKZnQ6ZnVuY3Rp
-b24oYSxiLGMsZCxlLGYpe3UuWi5hKGEpCnN3aXRjaChILldZKGIpKXtjYXNlIDA6cmV0dXJuIGEuJDAo
-KQpjYXNlIDE6cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQyKGMsZCkKY2FzZSAzOnJldHVy
-biBhLiQzKGMsZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9dGhyb3cgSC5iKG5ldyBQLkNE
-KCJVbnN1cHBvcnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFwcGVkIGNsb3N1cmUiKSl9LAp0
-UjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKdD1hLiRpZGVudGl0eQpp
-ZighIXQpcmV0dXJuIHQKdD1mdW5jdGlvbihjLGQsZSl7cmV0dXJuIGZ1bmN0aW9uKGYsZyxoLGkpe3Jl
-dHVybiBlKGMsZCxmLGcsaCxpKX19KGEsYixILmZ0KQphLiRpZGVudGl0eT10CnJldHVybiB0fSwKaUE6
-ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG4sbSxsPW51bGwsaz1iWzBdLGo9
-ay4kY2FsbE5hbWUsaT1lP09iamVjdC5jcmVhdGUobmV3IEguengoKS5jb25zdHJ1Y3Rvci5wcm90b3R5
-cGUpOk9iamVjdC5jcmVhdGUobmV3IEguankobCxsLGwsbCkuY29uc3RydWN0b3IucHJvdG90eXBlKQpp
-LiRpbml0aWFsaXplPWkuY29uc3RydWN0b3IKaWYoZSl0PWZ1bmN0aW9uIHN0YXRpY190ZWFyX29mZigp
-e3RoaXMuJGluaXRpYWxpemUoKX0KZWxzZXtzPSQueWoKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1
-cm4gcy5oKCkKJC55aj1zKzEKcz1uZXcgRnVuY3Rpb24oImEsYixjLGQiK3MsInRoaXMuJGluaXRpYWxp
-emUoYSxiLGMsZCIrcysiKSIpCnQ9c31pLmNvbnN0cnVjdG9yPXQKdC5wcm90b3R5cGU9aQppZighZSl7
-cj1ILmJ4KGEsayxmKQpyLiRyZWZsZWN0aW9uSW5mbz1kfWVsc2V7aS4kc3RhdGljX25hbWU9ZwpyPWt9
-cT1ILmltKGQsZSxmKQppLiRTPXEKaVtqXT1yCmZvcihwPXIsbz0xO288Yi5sZW5ndGg7KytvKXtuPWJb
-b10KbT1uLiRjYWxsTmFtZQppZihtIT1udWxsKXtuPWU/bjpILmJ4KGEsbixmKQppW21dPW59aWYobz09
-PWMpe24uJHJlZmxlY3Rpb25JbmZvPWQKcD1ufX1pLiRDPXAKaS4kUj1rLiRSCmkuJEQ9ay4kRApyZXR1
-cm4gdH0sCmltOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJu
-IGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGQoZSl9fShILkJwLGEpCmlmKHR5
-cGVvZiBhPT0ic3RyaW5nIil7aWYoYil0aHJvdyBILmIoIkNhbm5vdCBjb21wdXRlIHNpZ25hdHVyZSBm
-b3Igc3RhdGljIHRlYXJvZmYuIikKdD1jP0guUFc6SC5UbgpyZXR1cm4gZnVuY3Rpb24oZCxlKXtyZXR1
-cm4gZnVuY3Rpb24oKXtyZXR1cm4gZSh0aGlzLGQpfX0oYSx0KX10aHJvdyBILmIoIkVycm9yIGluIGZ1
-bmN0aW9uVHlwZSBvZiB0ZWFyb2ZmIil9LAp2cTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILkRWCnN3
-aXRjaChiPy0xOmEpe2Nhc2UgMDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oKXty
-ZXR1cm4gZih0aGlzKVtlXSgpfX0oYyx0KQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJu
-IGZ1bmN0aW9uKGcpe3JldHVybiBmKHRoaXMpW2VdKGcpfX0oYyx0KQpjYXNlIDI6cmV0dXJuIGZ1bmN0
-aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCl7cmV0dXJuIGYodGhpcylbZV0oZyxoKX19KGMsdCkK
-Y2FzZSAzOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSl7cmV0dXJuIGYo
-dGhpcylbZV0oZyxoLGkpfX0oYyx0KQpjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1
-bmN0aW9uKGcsaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGopfX0oYyx0KQpjYXNlIDU6cmV0
-dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGosayl7cmV0dXJuIGYodGhpcylb
-ZV0oZyxoLGksaixrKX19KGMsdCkKZGVmYXVsdDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVu
-Y3Rpb24oKXtyZXR1cm4gZS5hcHBseShmKHRoaXMpLGFyZ3VtZW50cyl9fShkLHQpfX0sCmJ4OmZ1bmN0
-aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbgppZihjKXJldHVybiBILkhmKGEsYikKdD1iLiRzdHVi
-TmFtZQpzPWIubGVuZ3RoCnI9YVt0XQpxPWI9PW51bGw/cj09bnVsbDpiPT09cgpwPSFxfHxzPj0yNwpp
-ZihwKXJldHVybiBILnZxKHMsIXEsdCxiKQppZihzPT09MCl7cT0kLnlqCmlmKHR5cGVvZiBxIT09Im51
-bWJlciIpcmV0dXJuIHEuaCgpCiQueWo9cSsxCm89InNlbGYiK3EKcT0icmV0dXJuIGZ1bmN0aW9uKCl7
-dmFyICIrbysiID0gdGhpcy4iCnA9JC5tSgpyZXR1cm4gbmV3IEZ1bmN0aW9uKHErSC5kKHA9PW51bGw/
-JC5tSj1ILkUyKCJzZWxmIik6cCkrIjtyZXR1cm4gIitvKyIuIitILmQodCkrIigpO30iKSgpfW49ImFi
-Y2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Ii5zcGxpdCgiIikuc3BsaWNlKDAscykuam9pbigiLCIpCnE9
-JC55agppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLmgoKQokLnlqPXErMQpuKz1xCnE9InJl
-dHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIgpwPSQubUoKcmV0dXJuIG5ldyBGdW5jdGlv
-bihxK0guZChwPT1udWxsPyQubUo9SC5FMigic2VsZiIpOnApKyIuIitILmQodCkrIigiK24rIik7fSIp
-KCl9LApaNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILkRWLHM9SC55Uwpzd2l0Y2goYj8tMTphKXtj
-YXNlIDA6dGhyb3cgSC5iKEguRWYoIkludGVyY2VwdGVkIGZ1bmN0aW9uIHdpdGggbm8gYXJndW1lbnRz
-LiIpKQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4g
-Zih0aGlzKVtlXShnKHRoaXMpKX19KGMsdCxzKQpjYXNlIDI6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXty
-ZXR1cm4gZnVuY3Rpb24oaCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoKX19KGMsdCxzKQpjYXNl
-IDM6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpKXtyZXR1cm4gZih0aGlz
-KVtlXShnKHRoaXMpLGgsaSl9fShjLHQscykKY2FzZSA0OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0
-dXJuIGZ1bmN0aW9uKGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqKX19KGMsdCxz
-KQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGosayl7cmV0
-dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrKX19KGMsdCxzKQpjYXNlIDY6cmV0dXJuIGZ1bmN0
-aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGosayxsKXtyZXR1cm4gZih0aGlzKVtlXShnKHRo
-aXMpLGgsaSxqLGssbCl9fShjLHQscykKZGVmYXVsdDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcsaCl7cmV0
-dXJuIGZ1bmN0aW9uKCl7aD1bZyh0aGlzKV0KQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoaCxhcmd1
-bWVudHMpCnJldHVybiBlLmFwcGx5KGYodGhpcyksaCl9fShkLHQscyl9fSwKSGY6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzLHIscSxwLG8sbixtPSQubUoKaWYobT09bnVsbCltPSQubUo9SC5FMigic2VsZiIpCnQ9
-JC5QNAppZih0PT1udWxsKXQ9JC5QND1ILkUyKCJyZWNlaXZlciIpCnM9Yi4kc3R1Yk5hbWUKcj1iLmxl
-bmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51bGw6Yj09PXEKbz0hcHx8cj49MjgKaWYobylyZXR1cm4g
-SC5aNChyLCFwLHMsYikKaWYocj09PTEpe209InJldHVybiBmdW5jdGlvbigpe3JldHVybiB0aGlzLiIr
-SC5kKG0pKyIuIitILmQocykrIih0aGlzLiIrSC5kKHQpKyIpOyIKdD0kLnlqCmlmKHR5cGVvZiB0IT09
-Im51bWJlciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcgRnVuY3Rpb24obSt0KyJ9Iiko
-KX1uPSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHItMSkuam9p
-bigiLCIpCm09InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIitILmQobSkrIi4iK0gu
-ZChzKSsiKHRoaXMuIitILmQodCkrIiwgIituKyIpOyIKdD0kLnlqCmlmKHR5cGVvZiB0IT09Im51bWJl
-ciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcgRnVuY3Rpb24obSt0KyJ9IikoKX0sCnVj
-OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3JldHVybiBILmlBKGEsYixjLGQsISFlLCEhZixnKX0sClRu
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2UsSC5xKGEuYSksYil9LApQVzpm
-dW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgucShhLmMpLGIpfSwKRFY6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApFMjpmdW5jdGlv
-bihhKXt2YXIgdCxzLHIscT1uZXcgSC5qeSgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIp
-LHA9Si5FcChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9yKHQ9cC5sZW5ndGgscz0wO3M8
-dDsrK3Mpe3I9cFtzXQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpmdW5jdGlvbihhKXtpZihhPT1u
-dWxsKUguZk8oImJvb2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBudWxsIikKcmV0dXJuIGF9LApm
-TzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6ZnVuY3Rpb24oYSl7dGhyb3cg
-SC5iKG5ldyBQLnQ3KGEpKX0sCkVmOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5FcShhKX0sCllnOmZ1
-bmN0aW9uKGEpe3JldHVybiB2LmdldElzb2xhdGVUYWcoYSl9LApWTTpmdW5jdGlvbihhLGIpe2Fbdi5h
-cnJheVJ0aV09YgpyZXR1cm4gYX0sCm9YOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwK
-cmV0dXJuIGEuJHRpfSwKSU06ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBILlk5KGFbIiRhIitILmQoYyld
-LEgub1goYikpfSwKWTk6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiCmE9YS5hcHBseShu
-dWxsLGIpCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYQpp
-Zih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gYS5hcHBseShudWxsLGIpCnJldHVybiBifSwKRlo6
-ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBhLmFwcGx5KGIsSC5ZOShKLmlhKGIpWyIkYSIrSC5kKGMpXSxI
-Lm9YKGIpKSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFs
-dWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0sCkc6
-ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1ILmMoJC55LiQxKGEpKSxvPSQualtwXQppZihvIT1udWxs
-KXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVu
-dW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9
-dD0kLnZbcF0KaWYodCE9bnVsbClyZXR1cm4gdApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbcF0KaWYocz09
-bnVsbCl7cD1ILmMoJC51LiQyKGEscCkpCmlmKHAhPW51bGwpe289JC5qW3BdCmlmKG8hPW51bGwpe09i
-amVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVy
-YWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX10PSQu
-dltwXQppZih0IT1udWxsKXJldHVybiB0CnM9di5pbnRlcmNlcHRvcnNCeVRhZ1twXX19aWYocz09bnVs
-bClyZXR1cm4gbnVsbAp0PXMucHJvdG90eXBlCnI9cFswXQppZihyPT09IiEiKXtvPUgubCh0KQokLmpb
-cF09bwpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpv
-LGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBv
-Lml9aWYocj09PSJ+Iil7JC52W3BdPXQKcmV0dXJuIHR9aWYocj09PSItIil7cT1ILmwodCkKT2JqZWN0
-LmRlZmluZVByb3BlcnR5KE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSx2LmRpc3BhdGNoUHJvcGVydHlO
-YW1lLHt2YWx1ZTpxLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1
-ZX0pCnJldHVybiBxLml9aWYocj09PSIrIilyZXR1cm4gSC5MYyhhLHQpCmlmKHI9PT0iKiIpdGhyb3cg
-SC5iKFAubihwKSkKaWYodi5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5sKHQpCk9iamVjdC5kZWZpbmVQ
-cm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSksdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFs
-dWU6cSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1
-cm4gcS5pfWVsc2UgcmV0dXJuIEguTGMoYSx0KX0sCkxjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9T2JqZWN0
-LmdldFByb3RvdHlwZU9mKGEpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LHYuZGlzcGF0Y2hQcm9wZXJ0
-eU5hbWUse3ZhbHVlOkouUXUoYix0LG51bGwsbnVsbCksZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0
-cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIGJ9LApsOmZ1bmN0aW9uKGEpe3JldHVybiBKLlF1
-KGEsITEsbnVsbCwhIWEuJGlYail9LApWRjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9Yi5wcm90b3R5cGUK
-aWYodi5sZWFmVGFnc1thXT09PXRydWUpcmV0dXJuIEgubCh0KQplbHNlIHJldHVybiBKLlF1KHQsYyxu
-dWxsLG51bGwpfSwKTTpmdW5jdGlvbigpe2lmKCEwPT09JC5LKXJldHVybgokLks9ITAKSC5EKCl9LApE
-OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbQokLmo9T2JqZWN0LmNyZWF0ZShudWxsKQokLnY9
-T2JqZWN0LmNyZWF0ZShudWxsKQpILmEoKQp0PXYuaW50ZXJjZXB0b3JzQnlUYWcKcz1PYmplY3QuZ2V0
-T3duUHJvcGVydHlOYW1lcyh0KQppZih0eXBlb2Ygd2luZG93IT0idW5kZWZpbmVkIil7d2luZG93CnI9
-ZnVuY3Rpb24oKXt9CmZvcihxPTA7cTxzLmxlbmd0aDsrK3Epe3A9c1txXQpvPSQueDcuJDEocCkKaWYo
-byE9bnVsbCl7bj1ILlZGKHAsdFtwXSxvKQppZihuIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHko
-byx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpuLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6
-dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnIucHJvdG90eXBlPW99fX19Zm9yKHE9MDtxPHMubGVuZ3Ro
-OysrcSl7cD1zW3FdCmlmKC9eW0EtWmEtel9dLy50ZXN0KHApKXttPXRbcF0KdFsiISIrcF09bQp0WyJ+
-IitwXT1tCnRbIi0iK3BdPW0KdFsiKyIrcF09bQp0WyIqIitwXT1tfX19LAphOmZ1bmN0aW9uKCl7dmFy
-IHQscyxyLHEscCxvLG49Qy5PNCgpCm49SC5GKEMuWXEsSC5GKEMuS1UsSC5GKEMuZlEsSC5GKEMuZlEs
-SC5GKEMuaTcsSC5GKEMueGksSC5GKEMuZGsoQy53YiksbikpKSkpKSkKaWYodHlwZW9mIGRhcnROYXRp
-dmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIhPSJ1bmRlZmluZWQiKXt0PWRhcnROYXRpdmVEaXNwYXRj
-aEhvb2tzVHJhbnNmb3JtZXIKaWYodHlwZW9mIHQ9PSJmdW5jdGlvbiIpdD1bdF0KaWYodC5jb25zdHJ1
-Y3Rvcj09QXJyYXkpZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCmlmKHR5cGVvZiByPT0iZnVu
-Y3Rpb24iKW49cihuKXx8bn19cT1uLmdldFRhZwpwPW4uZ2V0VW5rbm93blRhZwpvPW4ucHJvdG90eXBl
-Rm9yVGFnCiQueT1uZXcgSC5yKHEpCiQudT1uZXcgSC5kQyhwKQokLng3PW5ldyBILndOKG8pfSwKRjpm
-dW5jdGlvbihhLGIpe3JldHVybiBhKGIpfHxifSwKdjQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0
-PWI/Im0iOiIiLHM9Yz8iIjoiaSIscj1kPyJ1IjoiIixxPWU/InMiOiIiLHA9Zj8iZyI6IiIsbz1mdW5j
-dGlvbihnLGgpe3RyeXtyZXR1cm4gbmV3IFJlZ0V4cChnLGgpfWNhdGNoKG4pe3JldHVybiBufX0oYSx0
-K3MrcitxK3ApCmlmKG8gaW5zdGFuY2VvZiBSZWdFeHApcmV0dXJuIG8KdGhyb3cgSC5iKFAucnIoIkls
-bGVnYWwgUmVnRXhwIHBhdHRlcm4gKCIrU3RyaW5nKG8pKyIpIixhLG51bGwpKX0sCm0yOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdAppZih0eXBlb2YgYj09InN0cmluZyIpcmV0dXJuIGEuaW5kZXhPZihiLGMpPj0w
-CmVsc2UgaWYoYiBpbnN0YW5jZW9mIEguVlIpe3Q9Qy54Qi55bihhLGMpCnJldHVybiBiLmIudGVzdCh0
-KX1lbHNle3Q9Si5GTChiLEMueEIueW4oYSxjKSkKcmV0dXJuIXQuZ2wwKHQpfX0sCkE0OmZ1bmN0aW9u
-KGEpe2lmKGEuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEucmVwbGFjZSgvXCQvZywiJCQkJCIpCnJl
-dHVybiBhfSwKZUE6ZnVuY3Rpb24oYSl7aWYoL1tbXF17fSgpKis/LlxcXiR8XS8udGVzdChhKSlyZXR1
-cm4gYS5yZXBsYWNlKC9bW1xde30oKSorPy5cXF4kfF0vZywiXFwkJiIpCnJldHVybiBhfSwKeXM6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciB0PUgubk0oYSxiLGMpCnJldHVybiB0fSwKbk06ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0LHMscixxCmlmKGI9PT0iIil7aWYoYT09PSIiKXJldHVybiBjCnQ9YS5sZW5ndGgKZm9yKHM9
-YyxyPTA7cjx0OysrcilzPXMrYVtyXStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfXE9YS5p
-bmRleE9mKGIsMCkKaWYocTwwKXJldHVybiBhCmlmKGEubGVuZ3RoPDUwMHx8Yy5pbmRleE9mKCIkIiww
-KT49MClyZXR1cm4gYS5zcGxpdChiKS5qb2luKGMpCnJldHVybiBhLnJlcGxhY2UobmV3IFJlZ0V4cChI
-LmVBKGIpLCdnJyksSC5BNChjKSl9LApQRDpmdW5jdGlvbiBQRChhLGIpe3RoaXMuYT1hCnRoaXMuJHRp
-PWJ9LApXVTpmdW5jdGlvbiBXVSgpe30sCkxQOmZ1bmN0aW9uIExQKGEsYixjLGQpe3ZhciBfPXRoaXMK
-Xy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sClhSOmZ1bmN0aW9uIFhSKGEsYil7dGhpcy5hPWEKdGhp
-cy4kdGk9Yn0sCkxJOmZ1bmN0aW9uIExJKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9YQpfLmM9Ygpf
-LmQ9YwpfLmU9ZApfLmY9ZX0sCkNqOmZ1bmN0aW9uIENqKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0
-aGlzLmM9Y30sCmY5OmZ1bmN0aW9uIGY5KGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1i
-Cl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Yn0sCmF6OmZ1bmN0aW9uIGF6KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnZW
-OmZ1bmN0aW9uIHZWKGEpe3RoaXMuYT1hfSwKYnE6ZnVuY3Rpb24gYnEoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Yn0sCkFtOmZ1bmN0aW9uIEFtKGEpe3RoaXMuYT1hfSwKWE86ZnVuY3Rpb24gWE8oYSl7dGhpcy5h
-PWEKdGhpcy5iPW51bGx9LApUcDpmdW5jdGlvbiBUcCgpe30sCmxjOmZ1bmN0aW9uIGxjKCl7fSwKeng6
-ZnVuY3Rpb24gengoKXt9LApqeTpmdW5jdGlvbiBqeShhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8u
-Yj1iCl8uYz1jCl8uZD1kfSwKRXE6ZnVuY3Rpb24gRXEoYSl7dGhpcy5hPWF9LAprWTpmdW5jdGlvbiBr
-WShhKXt0aGlzLmE9YX0sCk41OmZ1bmN0aW9uIE41KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1f
-LmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LAp2aDpmdW5jdGlvbiB2aChhLGIpe3ZhciBfPXRo
-aXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVuY3Rpb24gaTUoYSxiKXt0aGlzLmE9YQp0
-aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5k
-PV8uYz1udWxsCl8uJHRpPWN9LApyOmZ1bmN0aW9uIHIoYSl7dGhpcy5hPWF9LApkQzpmdW5jdGlvbiBk
-QyhhKXt0aGlzLmE9YX0sCndOOmZ1bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlI6ZnVuY3Rpb24gVlIo
-YSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbH0sCkVLOmZ1bmN0aW9uIEVLKGEp
-e3RoaXMuYj1hfSwKS1c6ZnVuY3Rpb24gS1coYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1j
-fSwKUGI6ZnVuY3Rpb24gUGIoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPW51
-bGx9LAp0UTpmdW5jdGlvbiB0UShhLGIpe3RoaXMuYT1hCnRoaXMuYz1ifSwKTkY6ZnVuY3Rpb24gTkYo
-YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKU2Q6ZnVuY3Rpb24gU2QoYSxiLGMpe3Zh
-ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPW51bGx9LApYRjpmdW5jdGlvbihhKXtyZXR1cm4g
-YX0sCkRROmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSW50OEFycmF5KGEpfSwKb2Q6ZnVuY3Rpb24oYSxi
-LGMpe2lmKGE+Pj4wIT09YXx8YT49Yyl0aHJvdyBILmIoSC5IWShiLGEpKX0sCnJNOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdAppZighKGE+Pj4wIT09YSkpdD1iPj4+MCE9PWJ8fGE+Ynx8Yj5jCmVsc2UgdD0hMApp
-Zih0KXRocm93IEguYihILmF1KGEsYixjKSkKcmV0dXJuIGJ9LApXWjpmdW5jdGlvbiBXWigpe30sCnBG
-OmZ1bmN0aW9uIHBGKCl7fSwKYjA6ZnVuY3Rpb24gYjAoKXt9LApEZzpmdW5jdGlvbiBEZygpe30sClBn
-OmZ1bmN0aW9uIFBnKCl7fSwKeGo6ZnVuY3Rpb24geGooKXt9LApkRTpmdW5jdGlvbiBkRSgpe30sClpB
-OmZ1bmN0aW9uIFpBKCl7fSwKd2Y6ZnVuY3Rpb24gd2YoKXt9LApQcTpmdW5jdGlvbiBQcSgpe30sCmVF
-OmZ1bmN0aW9uIGVFKCl7fSwKVjY6ZnVuY3Rpb24gVjYoKXt9LApSRzpmdW5jdGlvbiBSRygpe30sClZQ
-OmZ1bmN0aW9uIFZQKCl7fSwKV0I6ZnVuY3Rpb24gV0IoKXt9LApaRzpmdW5jdGlvbiBaRygpe30sCmN6
-OmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5jCnJldHVybiB0PT1udWxsP2IuYz1ILkJjKGEsYi56LCEwKTp0
-fSwKeFo6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLmMKcmV0dXJuIHQ9PW51bGw/Yi5jPUguUTIoYSwiYjgi
-LFtiLnpdKTp0fSwKUTE6ZnVuY3Rpb24oYSl7dmFyIHQ9YS55CmlmKHQ9PT02fHx0PT09N3x8dD09PTgp
-cmV0dXJuIEguUTEoYS56KQpyZXR1cm4gdD09PTExfHx0PT09MTJ9LAptRDpmdW5jdGlvbihhKXtyZXR1
-cm4gYS5jeX0sCkRQOmZ1bmN0aW9uKGEpe3JldHVybiBILkUodi50eXBlVW5pdmVyc2UsYSwhMSl9LApQ
-TDpmdW5jdGlvbihhLGIsYyxhMCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZD1i
-LnkKc3dpdGNoKGQpe2Nhc2UgNTpjYXNlIDE6Y2FzZSAyOmNhc2UgMzpjYXNlIDQ6cmV0dXJuIGIKY2Fz
-ZSA2OnQ9Yi56CnM9SC5QTChhLHQsYyxhMCkKaWYocz09PXQpcmV0dXJuIGIKcmV0dXJuIEguU08oYSxz
-LCEwKQpjYXNlIDc6dD1iLnoKcz1ILlBMKGEsdCxjLGEwKQppZihzPT09dClyZXR1cm4gYgpyZXR1cm4g
-SC5CYyhhLHMsITApCmNhc2UgODp0PWIuegpzPUguUEwoYSx0LGMsYTApCmlmKHM9PT10KXJldHVybiBi
-CnJldHVybiBILkxOKGEscywhMCkKY2FzZSA5OnI9Yi5RCnE9SC5iWihhLHIsYyxhMCkKaWYocT09PXIp
-cmV0dXJuIGIKcmV0dXJuIEguUTIoYSxiLnoscSkKY2FzZSAxMDpwPWIuegpvPUguUEwoYSxwLGMsYTAp
-Cm49Yi5RCm09SC5iWihhLG4sYyxhMCkKaWYobz09PXAmJm09PT1uKXJldHVybiBiCnJldHVybiBILmFw
-KGEsbyxtKQpjYXNlIDExOmw9Yi56Cms9SC5QTChhLGwsYyxhMCkKaj1iLlEKaT1ILnFUKGEsaixjLGEw
-KQppZihrPT09bCYmaT09PWopcmV0dXJuIGIKcmV0dXJuIEguTmYoYSxrLGkpCmNhc2UgMTI6aD1iLlEK
-YTArPWgubGVuZ3RoCmc9SC5iWihhLGgsYyxhMCkKcD1iLnoKbz1ILlBMKGEscCxjLGEwKQppZihnPT09
-aCYmbz09PXApcmV0dXJuIGIKcmV0dXJuIEguRFMoYSxvLGcsITApCmNhc2UgMTM6Zj1iLnoKaWYoZjxh
-MClyZXR1cm4gYgplPWNbZi1hMF0KaWYoZT09bnVsbClyZXR1cm4gYgpyZXR1cm4gZQpkZWZhdWx0OnRo
-cm93IEguYihQLmhWKCJBdHRlbXB0ZWQgdG8gc3Vic3RpdHV0ZSB1bmV4cGVjdGVkIFJUSSBraW5kICIr
-ZCkpfX0sCmJaOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHA9Yi5sZW5ndGgsbz1bXQpmb3Io
-dD0hMSxzPTA7czxwOysrcyl7cj1iW3NdCnE9SC5QTChhLHIsYyxkKQppZihxIT09cil0PSEwCm8ucHVz
-aChxKX1yZXR1cm4gdD9vOmJ9LAp2TzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG89Yi5s
-ZW5ndGgsbj1bXQpmb3IodD0hMSxzPTA7czxvO3MrPTIpe3I9YltzXQpxPWJbcysxXQpwPUguUEwoYSxx
-LGMsZCkKaWYocCE9PXEpdD0hMApuLnB1c2gocikKbi5wdXNoKHApfXJldHVybiB0P246Yn0sCnFUOmZ1
-bmN0aW9uKGEsYixjLGQpe3ZhciB0LHM9Yi5hLHI9SC5iWihhLHMsYyxkKSxxPWIuYixwPUguYlooYSxx
-LGMsZCksbz1iLmMsbj1ILnZPKGEsbyxjLGQpCmlmKHI9PT1zJiZwPT09cSYmbj09PW8pcmV0dXJuIGIK
-dD1uZXcgSC5FVCgpCnQuYT1yCnQuYj1wCnQuYz1uCnJldHVybiB0fSwKSlM6ZnVuY3Rpb24oYSl7dmFy
-IHQ9YS4kUwppZih0IT1udWxsKXtpZih0eXBlb2YgdD09Im51bWJlciIpcmV0dXJuIEguQnAodCkKcmV0
-dXJuIGEuJFMoKX1yZXR1cm4gbnVsbH0sClVlOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoSC5RMShiKSlp
-ZihhIGluc3RhbmNlb2YgSC5UcCl7dD1ILkpTKGEpCmlmKHQhPW51bGwpcmV0dXJuIHR9cmV0dXJuIEgu
-cShhKX0sCnE6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYSBpbnN0YW5jZW9mIFAuTWgpe3Q9YS4kdGkKcmV0
-dXJuIHQhPW51bGw/dDpILlZVKGEpfWlmKEFycmF5LmlzQXJyYXkoYSkpcmV0dXJuIEgudDYoYSkKcmV0
-dXJuIEguVlUoSi5pYShhKSl9LAp0NjpmdW5jdGlvbihhKXt2YXIgdD1hW3YuYXJyYXlSdGldLHM9dS52
-CmlmKHQ9PW51bGwpcmV0dXJuIHMKaWYodC5jb25zdHJ1Y3RvciE9PXMuY29uc3RydWN0b3IpcmV0dXJu
-IHMKcmV0dXJuIHR9LApMaDpmdW5jdGlvbihhKXt2YXIgdD1hLiR0aQpyZXR1cm4gdCE9bnVsbD90Okgu
-VlUoYSl9LApWVTpmdW5jdGlvbihhKXt2YXIgdD1hLmNvbnN0cnVjdG9yLHM9dC4kY2NhY2hlCmlmKHMh
-PW51bGwpcmV0dXJuIHMKcmV0dXJuIEgucjkoYSx0KX0sCnI5OmZ1bmN0aW9uKGEsYil7dmFyIHQ9YSBp
-bnN0YW5jZW9mIEguVHA/YS5fX3Byb3RvX18uX19wcm90b19fLmNvbnN0cnVjdG9yOmIscz1ILmFpKHYu
-dHlwZVVuaXZlcnNlLHQubmFtZSkKYi4kY2NhY2hlPXMKcmV0dXJuIHN9LApCcDpmdW5jdGlvbihhKXt2
-YXIgdCxzPWEscj12LnR5cGVzLHE9cltzXQppZih0eXBlb2YgcT09InN0cmluZyIpe3Q9SC5FKHYudHlw
-ZVVuaXZlcnNlLHEsITEpCnJbc109dApyZXR1cm4gdH1yZXR1cm4gcX0sCkpKOmZ1bmN0aW9uKGEpe3Zh
-ciB0PXRoaXMscz1ILllPLHI9dS5LCmlmKHQ9PT1yKXtzPUgua2UKdC5hPUguVGl9ZWxzZSBpZihILkE4
-KHQpfHx0PT09cil7cz1ILkl3CnQuYT1ILmhufWVsc2UgaWYodD09PXUuUylzPUgub2sKZWxzZSBpZih0
-PT09dS5nUilzPUguS0gKZWxzZSBpZih0PT09dS5kaSlzPUguS0gKZWxzZSBpZih0PT09dS5OKXM9SC5N
-TQplbHNlIGlmKHQ9PT11Lnkpcz1ILnJRCmVsc2UgaWYodC55PT09OSl7cj10LnoKaWYodC5RLmV2ZXJ5
-KEguY2MpKXt0LnI9IiRpIityCnM9SC50NH19dC5iPXMKcmV0dXJuIHQuYihhKX0sCllPOmZ1bmN0aW9u
-KGEpe3ZhciB0PXRoaXMKcmV0dXJuIEguV2Uodi50eXBlVW5pdmVyc2UsSC5VZShhLHQpLG51bGwsdCxu
-dWxsKX0sCnQ0OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz10LnIKaWYoYSBpbnN0YW5jZW9mIFAuTWgp
-cmV0dXJuISFhW3NdCnJldHVybiEhSi5pYShhKVtzXX0sCk96OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMK
-aWYoYT09bnVsbClyZXR1cm4gYQplbHNlIGlmKHQuYihhKSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYyhI
-LnAoYSxILlVlKGEsdCksSC5KKHQsbnVsbCkpKSl9LApEaDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1u
-dWxsCmlmKEguV2Uodi50eXBlVW5pdmVyc2UsYSx0LGIsdCkpcmV0dXJuIGEKdGhyb3cgSC5iKEguWmMo
-IlRoZSB0eXBlIGFyZ3VtZW50ICciK0guZChILkooYSx0KSkrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0
-aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitILmQoSC5KKGIsdCkpKyInIG9mIHR5cGUgdmFyaWFibGUg
-JyIrYysiJyBpbiAnIitILmQoZCkrIicuIikpfSwKcDpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9UC5oKGEp
-LHM9SC5KKGI9PW51bGw/SC5xKGEpOmIsbnVsbCkKcmV0dXJuIHQrIjogdHlwZSAnIitILmQocykrIicg
-aXMgbm90IGEgc3VidHlwZSBvZiB0eXBlICciK0guZChjKSsiJyJ9LApaYzpmdW5jdGlvbihhKXtyZXR1
-cm4gbmV3IEgueCgiVHlwZUVycm9yOiAiK2EpfSwKQjpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC54
-KCJUeXBlRXJyb3I6ICIrSC5wKGEsbnVsbCxiKSl9LAprZTpmdW5jdGlvbihhKXtyZXR1cm4hMH0sClRp
-OmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKSXc6ZnVuY3Rpb24oYSl7cmV0dXJuITB9LApobjpmdW5jdGlv
-bihhKXtyZXR1cm4gYX0sCnJROmZ1bmN0aW9uKGEpe3JldHVybiEwPT09YXx8ITE9PT1hfSwKRTk6ZnVu
-Y3Rpb24oYSl7aWYoITA9PT1hfHwhMT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJv
-dyBILmIoSC5CKGEsImJvb2wiKSl9LApkajpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIp
-cmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5CKGEsImRvdWJsZSIpKX0sCm9r
-OmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hfSwK
-V1k6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1
-cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILkIoYSwiaW50IikpfSwKS0g6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVyIn0sCnVVOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBh
-PT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILkIoYSwibnVt
-IikpfSwKTU06ZnVuY3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ic3RyaW5nIn0sCmM6ZnVuY3Rpb24o
-YSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cg
-SC5iKEguQihhLCJTdHJpbmciKSl9LAp3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PSIiLHM9
-IiIscj0wO3I8YS5sZW5ndGg7KytyLHM9IiwgIil0Kz1DLnhCLmgocyxILkooYVtyXSxiKSkKcmV0dXJu
-IHR9LApmOmZ1bmN0aW9uKGExLGEyLGEzKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYs
-ZSxkLGMsYixhLGEwPSIsICIKaWYoYTMhPW51bGwpe3Q9YTMubGVuZ3RoCmlmKGEyPT1udWxsKXthMj1I
-LlZNKFtdLHUucykKcz1udWxsfWVsc2Ugcz1hMi5sZW5ndGgKcj1hMi5sZW5ndGgKZm9yKHE9dDtxPjA7
-LS1xKUMuTm0uQShhMiwiVCIrKHIrcSkpCmZvcihwPXUuSyxvPSI8IixuPSIiLHE9MDtxPHQ7KytxLG49
-YTApe28rPW4KbT1hMi5sZW5ndGgKbD1tLTEtcQppZihsPDApcmV0dXJuIEguayhhMixsKQpvPUMueEIu
-aChvLGEyW2xdKQprPWEzW3FdCmlmKCEoSC5BOChrKXx8az09PXApKW09IShrPT09cCkKZWxzZSBtPSEx
-CmlmKG0pbys9Qy54Qi5oKCIgZXh0ZW5kcyAiLEguSihrLGEyKSl9bys9Ij4ifWVsc2V7bz0iIgpzPW51
-bGx9cD1hMS56Cmo9YTEuUQppPWouYQpoPWkubGVuZ3RoCmc9ai5iCmY9Zy5sZW5ndGgKZT1qLmMKZD1l
-Lmxlbmd0aApjPUguSihwLGEyKQpmb3IoYj0iIixhPSIiLHE9MDtxPGg7KytxLGE9YTApYis9Qy54Qi5o
-KGEsSC5KKGlbcV0sYTIpKQppZihmPjApe2IrPWErIlsiCmZvcihhPSIiLHE9MDtxPGY7KytxLGE9YTAp
-Yis9Qy54Qi5oKGEsSC5KKGdbcV0sYTIpKQpiKz0iXSJ9aWYoZD4wKXtiKz1hKyJ7Igpmb3IoYT0iIixx
-PTA7cTxkO3ErPTIsYT1hMCliKz1DLnhCLmgoYSxILkooZVtxKzFdLGEyKSkrIiAiK2VbcV0KYis9In0i
-fWlmKHMhPW51bGwpYTIubGVuZ3RoPXMKcmV0dXJuIG8rIigiK2IrIikgPT4gIitILmQoYyl9LApKOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbT1hLnkKaWYobT09PTUpcmV0dXJuImVyYXNlZCIK
-aWYobT09PTIpcmV0dXJuImR5bmFtaWMiCmlmKG09PT0zKXJldHVybiJ2b2lkIgppZihtPT09MSlyZXR1
-cm4iTmV2ZXIiCmlmKG09PT00KXJldHVybiJhbnkiCmlmKG09PT02KXt0PUguSihhLnosYikKcmV0dXJu
-IHR9aWYobT09PTcpe3M9YS56CnQ9SC5KKHMsYikKcj1zLnkKcmV0dXJuIEoubShyPT09MTF8fHI9PT0x
-Mj9DLnhCLmgoIigiLHQpKyIpIjp0LCI/Iil9aWYobT09PTgpcmV0dXJuIkZ1dHVyZU9yPCIrSC5kKEgu
-SihhLnosYikpKyI+IgppZihtPT09OSl7cT1ILkMoYS56KQpwPWEuUQpyZXR1cm4gcC5sZW5ndGghPT0w
-P3ErKCI8IitILncocCxiKSsiPiIpOnF9aWYobT09PTExKXJldHVybiBILmYoYSxiLG51bGwpCmlmKG09
-PT0xMilyZXR1cm4gSC5mKGEueixiLGEuUSkKaWYobT09PTEzKXtvPWEuegpuPWIubGVuZ3RoCm89bi0x
-LW8KaWYobzwwfHxvPj1uKXJldHVybiBILmsoYixvKQpyZXR1cm4gYltvXX1yZXR1cm4iPyJ9LApDOmZ1
-bmN0aW9uKGEpe3ZhciB0LHM9SC5KZyhhKQppZihzIT1udWxsKXJldHVybiBzCnQ9Im1pbmlmaWVkOiIr
-YQpyZXR1cm4gdH0sClFvOmZ1bmN0aW9uKGEsYil7dmFyIHQ9YS50UltiXQpmb3IoO3R5cGVvZiB0PT0i
-c3RyaW5nIjspdD1hLnRSW3RdCnJldHVybiB0fSwKYWk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
-LG89YS5lVCxuPW9bYl0KaWYobj09bnVsbClyZXR1cm4gSC5FKGEsYiwhMSkKZWxzZSBpZih0eXBlb2Yg
-bj09Im51bWJlciIpe3Q9bgpzPUgubVooYSw1LCIjIikKcj1bXQpmb3IocT0wO3E8dDsrK3Epci5wdXNo
-KHMpCnA9SC5RMihhLGIscikKb1tiXT1wCnJldHVybiBwfWVsc2UgcmV0dXJuIG59LAp4YjpmdW5jdGlv
-bihhLGIpe3JldHVybiBILkl4KGEudFIsYil9LApGRjpmdW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEu
-ZVQsYil9LApFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWEuZUMscj1zLmdldChiKQppZihyIT1udWxs
-KXJldHVybiByCnQ9SC56KGEsbnVsbCxiLGMpCnMuc2V0KGIsdCkKcmV0dXJuIHR9LApjRTpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQscyxyPWIuY2gKaWYocj09bnVsbClyPWIuY2g9bmV3IE1hcCgpCnQ9ci5nZXQo
-YykKaWYodCE9bnVsbClyZXR1cm4gdApzPUgueihhLGIsYywhMCkKci5zZXQoYyxzKQpyZXR1cm4gc30s
-CnY1OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1iLmN4CmlmKHE9PW51bGwpcT1iLmN4PW5ldyBN
-YXAoKQp0PWMuY3kKcz1xLmdldCh0KQppZihzIT1udWxsKXJldHVybiBzCnI9SC5hcChhLGIsYy55PT09
-MTA/Yy5ROltjXSkKcS5zZXQodCxyKQpyZXR1cm4gcn0sCno6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9
-SC5pKEgubyhhLGIsYyxkKSkKaWYodCE9bnVsbClyZXR1cm4gdAp0aHJvdyBILmIoUC5uKCdfVW5pdmVy
-c2UuX3BhcnNlUmVjaXBlKCInK0guZChjKSsnIiknKSl9LApCRDpmdW5jdGlvbihhLGIpe2IuYT1ILk96
-CmIuYj1ILkpKCnJldHVybiBifSwKbVo6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscj1hLmVDLmdldChj
-KQppZihyIT1udWxsKXJldHVybiByCnQ9bmV3IEguSmMobnVsbCxudWxsKQp0Lnk9Ygp0LmN5PWMKcz1I
-LkJEKGEsdCkKYS5lQy5zZXQoYyxzKQpyZXR1cm4gc30sClNPOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
-PWIuY3krIioiLHI9YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguWjcoYSxiLHMsYykK
-YS5lQy5zZXQocyx0KQpyZXR1cm4gdH0sClo3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKaWYoZCl7
-dD1iLnkKaWYoSC5BOChiKXx8Yj09PXUuS3x8Yj09PXUuUHx8dD09PTd8fHQ9PT02KXJldHVybiBifXM9
-bmV3IEguSmMobnVsbCxudWxsKQpzLnk9NgpzLno9YgpzLmN5PWMKcmV0dXJuIEguQkQoYSxzKX0sCkJj
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIj8iLHI9YS5lQy5nZXQocykKaWYociE9bnVsbCly
-ZXR1cm4gcgp0PUgubGwoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpyZXR1cm4gdH0sCmxsOmZ1bmN0aW9u
-KGEsYixjLGQpe3ZhciB0LHMscixxLHAKaWYoZCl7dD1iLnkKaWYoIUguQTgoYikpaWYoIShiPT09dS5Q
-KSlpZih0IT09NylzPXQ9PT04JiZILmxSKGIueikKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAK
-aWYocylyZXR1cm4gYgplbHNlIGlmKHQ9PT0xKXJldHVybiB1LlAKZWxzZSBpZih0PT09Nil7cj1iLnoK
-cT1yLnkKaWYocT09PTEpcmV0dXJuIHUuUAplbHNlIGlmKHE9PT04JiZILmxSKHIueikpcmV0dXJuIHIK
-ZWxzZSByZXR1cm4gSC5jeihhLGIpfX1wPW5ldyBILkpjKG51bGwsbnVsbCkKcC55PTcKcC56PWIKcC5j
-eT1jCnJldHVybiBILkJEKGEscCl9LApMTjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1iLmN5KyIvIixy
-PWEuZUMuZ2V0KHMpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1ILmVWKGEsYixzLGMpCmEuZUMuc2V0KHMs
-dCkKcmV0dXJuIHR9LAplVjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzCmlmKGQpe3Q9Yi55CmlmKEgu
-QTgoYil8fGI9PT11Lkt8fGI9PT11LkspcmV0dXJuIGIKZWxzZSBpZih0PT09MSlyZXR1cm4gSC5RMihh
-LCJiOCIsW2JdKQplbHNlIGlmKGI9PT11LlApcmV0dXJuIHUuYVF9cz1uZXcgSC5KYyhudWxsLG51bGwp
-CnMueT04CnMuej1iCnMuY3k9YwpyZXR1cm4gSC5CRChhLHMpfSwKSGM6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzLHI9IiIrYisiXiIscT1hLmVDLmdldChyKQppZihxIT1udWxsKXJldHVybiBxCnQ9bmV3IEguSmMo
-bnVsbCxudWxsKQp0Lnk9MTMKdC56PWIKdC5jeT1yCnM9SC5CRChhLHQpCmEuZUMuc2V0KHIscykKcmV0
-dXJuIHN9LApVeDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9
-MDtyPHE7KytyLHM9IiwiKXQrPXMrYVtyXS5jeQpyZXR1cm4gdH0sClM0OmZ1bmN0aW9uKGEpe3ZhciB0
-LHMscixxLHAsbz1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9MDtyPG87cis9MixzPSIsIil7cT1hW3Jd
-CnA9YVtyKzFdLmN5CnQrPXMrcSsiOiIrcH1yZXR1cm4gdH0sClEyOmZ1bmN0aW9uKGEsYixjKXt2YXIg
-dCxzLHIscT1iCmlmKGMubGVuZ3RoIT09MClxKz0iPCIrSC5VeChjKSsiPiIKdD1hLmVDLmdldChxKQpp
-Zih0IT1udWxsKXJldHVybiB0CnM9bmV3IEguSmMobnVsbCxudWxsKQpzLnk9OQpzLno9YgpzLlE9Ywpp
-ZihjLmxlbmd0aD4wKXMuYz1jWzBdCnMuY3k9cQpyPUguQkQoYSxzKQphLmVDLnNldChxLHIpCnJldHVy
-biByfSwKYXA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbwppZihiLnk9PT0xMCl7dD1iLnoK
-cz1iLlEuY29uY2F0KGMpfWVsc2V7cz1jCnQ9Yn1yPXQuY3krIjsiKygiPCIrSC5VeChzKSsiPiIpCnE9
-YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpwPW5ldyBILkpjKG51bGwsbnVsbCkKcC55PTEw
-CnAuej10CnAuUT1zCnAuY3k9cgpvPUguQkQoYSxwKQphLmVDLnNldChyLG8pCnJldHVybiBvfSwKTmY6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHA9Yi5jeSxvPWMuYSxuPW8ubGVuZ3RoLG09Yy5iLGw9
-bS5sZW5ndGgsaz1jLmMsaj1rLmxlbmd0aCxpPSIoIitILlV4KG8pCmlmKGw+MClpKz0obj4wPyIsIjoi
-IikrIlsiK0guVXgobSkrIl0iCmlmKGo+MClpKz0obj4wPyIsIjoiIikrInsiK0guUzQoaykrIn0iCnQ9
-cCsoaSsiKSIpCnM9YS5lQy5nZXQodCkKaWYocyE9bnVsbClyZXR1cm4gcwpyPW5ldyBILkpjKG51bGws
-bnVsbCkKci55PTExCnIuej1iCnIuUT1jCnIuY3k9dApxPUguQkQoYSxyKQphLmVDLnNldCh0LHEpCnJl
-dHVybiBxfSwKRFM6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz1iLmN5KyI8IitILlV4KGMpKyI+Iixy
-PWEuZUMuZ2V0KHMpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1ILmh3KGEsYixjLHMsZCkKYS5lQy5zZXQo
-cyx0KQpyZXR1cm4gdH0sCmh3OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscCxvLG4sbQpp
-ZihlKXt0PWMubGVuZ3RoCnM9bmV3IEFycmF5KHQpCmZvcihyPTAscT0wO3E8dDsrK3Epe3A9Y1txXQpp
-ZihwLnk9PT0xKXtzW3FdPXA7KytyfX1pZihyPjApe289SC5QTChhLGIscywwKQpuPUguYlooYSxjLHMs
-MCkKcmV0dXJuIEguRFMoYSxvLG4sYyE9PW4pfX1tPW5ldyBILkpjKG51bGwsbnVsbCkKbS55PTEyCm0u
-ej1iCm0uUT1jCm0uY3k9ZApyZXR1cm4gSC5CRChhLG0pfSwKbzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1
-cm57dTphLGU6YixyOmMsczpbXSxwOjAsbjpkfX0sCmk6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxv
-LG4sbSxsLGssaixpLGg9YS5yLGc9YS5zCmZvcih0PWgubGVuZ3RoLHM9MDtzPHQ7KXtyPWguY2hhckNv
-ZGVBdChzKQppZihyPj00OCYmcjw9NTcpcz1ILkFsKHMrMSxyLGgsZykKZWxzZSBpZigoKChyfDMyKT4+
-PjApLTk3JjY1NTM1KTwyNnx8cj09PTk1fHxyPT09MzYpcz1ILlI4KGEscyxoLGcsITEpCmVsc2UgaWYo
-cj09PTQ2KXM9SC5SOChhLHMsaCxnLCEwKQplbHNleysrcwpzd2l0Y2gocil7Y2FzZSA0NDpicmVhawpj
-YXNlIDU4OmJyZWFrCmNhc2UgNTk6Zy5wdXNoKEguS1EoYS51LGEuZSxnLnBvcCgpKSkKYnJlYWsKY2Fz
-ZSA5NDpnLnB1c2goSC5IYyhhLnUsZy5wb3AoKSkpCmJyZWFrCmNhc2UgMzU6Zy5wdXNoKEgubVooYS51
-LDUsIiMiKSkKYnJlYWsKY2FzZSA2NDpnLnB1c2goSC5tWihhLnUsMiwiQCIpKQpicmVhawpjYXNlIDEy
-NjpnLnB1c2goSC5tWihhLnUsMywifiIpKQpicmVhawpjYXNlIDYwOmcucHVzaChhLnApCmEucD1nLmxl
-bmd0aApicmVhawpjYXNlIDYyOnE9YS51CnA9Zy5zcGxpY2UoYS5wKQpILnJUKGEudSxhLmUscCkKYS5w
-PWcucG9wKCkKbz1nLnBvcCgpCmlmKHR5cGVvZiBvPT0ic3RyaW5nIilnLnB1c2goSC5RMihxLG8scCkp
-CmVsc2V7bj1ILktRKHEsYS5lLG8pCnN3aXRjaChuLnkpe2Nhc2UgMTE6Zy5wdXNoKEguRFMocSxuLHAs
-YS5uKSkKYnJlYWsKZGVmYXVsdDpnLnB1c2goSC5hcChxLG4scCkpCmJyZWFrfX1icmVhawpjYXNlIDM4
-OkguSTMoYSxnKQpicmVhawpjYXNlIDQyOm09YS51CmcucHVzaChILlNPKG0sSC5LUShtLGEuZSxnLnBv
-cCgpKSxhLm4pKQpicmVhawpjYXNlIDYzOm09YS51CmcucHVzaChILkJjKG0sSC5LUShtLGEuZSxnLnBv
-cCgpKSxhLm4pKQpicmVhawpjYXNlIDQ3Om09YS51CmcucHVzaChILkxOKG0sSC5LUShtLGEuZSxnLnBv
-cCgpKSxhLm4pKQpicmVhawpjYXNlIDQwOmcucHVzaChhLnApCmEucD1nLmxlbmd0aApicmVhawpjYXNl
-IDQxOnE9YS51Cmw9bmV3IEguRVQoKQprPXEuc0VBCmo9cS5zRUEKbz1nLnBvcCgpCmlmKHR5cGVvZiBv
-PT0ibnVtYmVyIilzd2l0Y2gobyl7Y2FzZS0xOms9Zy5wb3AoKQpicmVhawpjYXNlLTI6aj1nLnBvcCgp
-CmJyZWFrCmRlZmF1bHQ6Zy5wdXNoKG8pCmJyZWFrfWVsc2UgZy5wdXNoKG8pCnA9Zy5zcGxpY2UoYS5w
-KQpILnJUKGEudSxhLmUscCkKYS5wPWcucG9wKCkKbC5hPXAKbC5iPWsKbC5jPWoKZy5wdXNoKEguTmYo
-cSxILktRKHEsYS5lLGcucG9wKCkpLGwpKQpicmVhawpjYXNlIDkxOmcucHVzaChhLnApCmEucD1nLmxl
-bmd0aApicmVhawpjYXNlIDkzOnA9Zy5zcGxpY2UoYS5wKQpILnJUKGEudSxhLmUscCkKYS5wPWcucG9w
-KCkKZy5wdXNoKHApCmcucHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6Zy5wdXNoKGEucCkKYS5wPWcubGVu
-Z3RoCmJyZWFrCmNhc2UgMTI1OnA9Zy5zcGxpY2UoYS5wKQpILldTKGEudSxhLmUscCkKYS5wPWcucG9w
-KCkKZy5wdXNoKHApCmcucHVzaCgtMikKYnJlYWsKZGVmYXVsdDp0aHJvdyJCYWQgY2hhcmFjdGVyICIr
-cn19fWk9Zy5wb3AoKQpyZXR1cm4gSC5LUShhLnUsYS5lLGkpfSwKQWw6ZnVuY3Rpb24oYSxiLGMsZCl7
-dmFyIHQscyxyPWItNDgKZm9yKHQ9Yy5sZW5ndGg7YTx0OysrYSl7cz1jLmNoYXJDb2RlQXQoYSkKaWYo
-IShzPj00OCYmczw9NTcpKWJyZWFrCnI9cioxMCsocy00OCl9ZC5wdXNoKHIpCnJldHVybiBhfSwKUjg6
-ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG8sbj1iKzEKZm9yKHQ9Yy5sZW5ndGg7bjx0
-Oysrbil7cz1jLmNoYXJDb2RlQXQobikKaWYocz09PTQ2KXtpZihlKWJyZWFrCmU9ITB9ZWxzZXtpZigh
-KCgoKHN8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxzPT09OTV8fHM9PT0zNikpcj1zPj00OCYmczw9NTcK
-ZWxzZSByPSEwCmlmKCFyKWJyZWFrfX1xPWMuc3Vic3RyaW5nKGIsbikKaWYoZSl7dD1hLnUKcD1hLmUK
-aWYocC55PT09MTApcD1wLnoKbz1ILlFvKHQscC56KVtxXQppZihvPT1udWxsKUguVmooJ05vICInK3Er
-JyIgaW4gIicrSC5tRChwKSsnIicpCmQucHVzaChILmNFKHQscCxvKSl9ZWxzZSBkLnB1c2gocSkKcmV0
-dXJuIG59LApJMzpmdW5jdGlvbihhLGIpe3ZhciB0PWIucG9wKCkKaWYoMD09PXQpe2IucHVzaChILm1a
-KGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXQpe2IucHVzaChILm1aKGEudSw0LCIxJiIpKQpyZXR1
-cm59dGhyb3cgSC5iKFAuaFYoIlVuZXhwZWN0ZWQgZXh0ZW5kZWQgb3BlcmF0aW9uICIrSC5kKHQpKSl9
-LApLUTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGM9PSJzdHJpbmciKXJldHVybiBILlEyKGEsYyxh
-LnNFQSkKZWxzZSBpZih0eXBlb2YgYz09Im51bWJlciIpcmV0dXJuIEguVFYoYSxiLGMpCmVsc2UgcmV0
-dXJuIGN9LApyVDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1jLmxlbmd0aApmb3IodD0wO3Q8czsrK3Qp
-Y1t0XT1ILktRKGEsYixjW3RdKX0sCldTOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWMubGVuZ3RoCmZv
-cih0PTE7dDxzO3QrPTIpY1t0XT1ILktRKGEsYixjW3RdKX0sClRWOmZ1bmN0aW9uKGEsYixjKXt2YXIg
-dCxzLHI9Yi55CmlmKHI9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIuegp0PWIuUQpzPXQubGVuZ3RoCmlm
-KGM8PXMpcmV0dXJuIHRbYy0xXQpjLT1zCmI9Yi56CnI9Yi55fWVsc2UgaWYoYz09PTApcmV0dXJuIGIK
+LApNOmZ1bmN0aW9uKGEpe3ZhciB0PUguSDUoYSkKcmV0dXJuIHR9LApINTpmdW5jdGlvbihhKXt2YXIg
+dCxzLHIKaWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gSC5kbShILnpLKGEpLG51bGwpCmlmKEouaWEo
+YSk9PT1DLk9rfHx1LmFrLmMoYSkpe3Q9Qy5PNChhKQppZihILmYodCkpcmV0dXJuIHQKcz1hLmNvbnN0
+cnVjdG9yCmlmKHR5cGVvZiBzPT0iZnVuY3Rpb24iKXtyPXMubmFtZQppZih0eXBlb2Ygcj09InN0cmlu
+ZyImJkguZihyKSlyZXR1cm4gcn19cmV0dXJuIEguZG0oSC56SyhhKSxudWxsKX0sCmY6ZnVuY3Rpb24o
+YSl7dmFyIHQ9YSE9PSJPYmplY3QiJiZhIT09IiIKcmV0dXJuIHR9LApNMDpmdW5jdGlvbigpe2lmKCEh
+c2VsZi5sb2NhdGlvbilyZXR1cm4gc2VsZi5sb2NhdGlvbi5ocmVmCnJldHVybiBudWxsfSwKVks6ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyLHEscD1hLmxlbmd0aAppZihwPD01MDApcmV0dXJuIFN0cmluZy5mcm9t
+Q2hhckNvZGUuYXBwbHkobnVsbCxhKQpmb3IodD0iIixzPTA7czxwO3M9cil7cj1zKzUwMApxPXI8cD9y
+OnAKdCs9U3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGEuc2xpY2UocyxxKSl9cmV0dXJuIHR9
+LApDcTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1ILlZNKFtdLHUudCkKZm9yKHQ9YS5sZW5ndGgscz0w
+O3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpe3I9YVtzXQppZighSC5vayhy
+KSl0aHJvdyBILmIoSC50TChyKSkKaWYocjw9NjU1MzUpQy5ObS5BKHEscikKZWxzZSBpZihyPD0xMTE0
+MTExKXtDLk5tLkEocSw1NTI5NisoQy5qbi53RyhyLTY1NTM2LDEwKSYxMDIzKSkKQy5ObS5BKHEsNTYz
+MjArKHImMTAyMykpfWVsc2UgdGhyb3cgSC5iKEgudEwocikpfXJldHVybiBILlZLKHEpfSwKZVQ6ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyCmZvcih0PWEubGVuZ3RoLHM9MDtzPHQ7KytzKXtyPWFbc10KaWYoIUgu
+b2socikpdGhyb3cgSC5iKEgudEwocikpCmlmKHI8MCl0aHJvdyBILmIoSC50TChyKSkKaWYocj42NTUz
+NSlyZXR1cm4gSC5DcShhKX1yZXR1cm4gSC5WSyhhKX0sCmZ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+LHIscQppZihjPD01MDAmJmI9PT0wJiZjPT09YS5sZW5ndGgpcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNv
+ZGUuYXBwbHkobnVsbCxhKQpmb3IodD1iLHM9IiI7dDxjO3Q9cil7cj10KzUwMApxPXI8Yz9yOmMKcys9
+U3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGEuc3ViYXJyYXkodCxxKSl9cmV0dXJuIHN9LApM
+dzpmdW5jdGlvbihhKXt2YXIgdAppZigwPD1hKXtpZihhPD02NTUzNSlyZXR1cm4gU3RyaW5nLmZyb21D
+aGFyQ29kZShhKQppZihhPD0xMTE0MTExKXt0PWEtNjU1MzYKcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNv
+ZGUoKDU1Mjk2fEMuam4ud0codCwxMCkpPj4+MCw1NjMyMHx0JjEwMjMpfX10aHJvdyBILmIoUC5URShh
+LDAsMTExNDExMSxudWxsLG51bGwpKX0sCm8yOmZ1bmN0aW9uKGEpe2lmKGEuZGF0ZT09PXZvaWQgMClh
+LmRhdGU9bmV3IERhdGUoYS5hKQpyZXR1cm4gYS5kYXRlfSwKdEo6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
+Yj9ILm8yKGEpLmdldFVUQ0Z1bGxZZWFyKCkrMDpILm8yKGEpLmdldEZ1bGxZZWFyKCkrMH0sCk5TOmZ1
+bmN0aW9uKGEpe3JldHVybiBhLmI/SC5vMihhKS5nZXRVVENNb250aCgpKzE6SC5vMihhKS5nZXRNb250
+aCgpKzF9LApqQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRDRGF0ZSgpKzA6SC5v
+MihhKS5nZXREYXRlKCkrMH0sCktMOmZ1bmN0aW9uKGEpe3JldHVybiBhLmI/SC5vMihhKS5nZXRVVENI
+b3VycygpKzA6SC5vMihhKS5nZXRIb3VycygpKzB9LApjaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5iP0gu
+bzIoYSkuZ2V0VVRDTWludXRlcygpKzA6SC5vMihhKS5nZXRNaW51dGVzKCkrMH0sCkpkOmZ1bmN0aW9u
+KGEpe3JldHVybiBhLmI/SC5vMihhKS5nZXRVVENTZWNvbmRzKCkrMDpILm8yKGEpLmdldFNlY29uZHMo
+KSswfSwKbzE6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYj9ILm8yKGEpLmdldFVUQ01pbGxpc2Vjb25kcygp
+KzA6SC5vMihhKS5nZXRNaWxsaXNlY29uZHMoKSswfSwKem86ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
+cj17fQpyLmE9MAp0PVtdCnM9W10Kci5hPWIubGVuZ3RoCkMuTm0uRlYodCxiKQpyLmI9IiIKaWYoYyE9
+bnVsbCYmYy5hIT09MCljLlUoMCxuZXcgSC5DaihyLHMsdCkpCiIiK3IuYQpyZXR1cm4gSi5KeShhLG5l
+dyBILkxJKEMuVGUsMCx0LHMsMCkpfSwKRWs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlmKGIg
+aW5zdGFuY2VvZiBBcnJheSl0PWM9PW51bGx8fGMuYT09PTAKZWxzZSB0PSExCmlmKHQpe3M9YgpyPXMu
+bGVuZ3RoCmlmKHI9PT0wKXtpZighIWEuJDApcmV0dXJuIGEuJDAoKX1lbHNlIGlmKHI9PT0xKXtpZigh
+IWEuJDEpcmV0dXJuIGEuJDEoc1swXSl9ZWxzZSBpZihyPT09Mil7aWYoISFhLiQyKXJldHVybiBhLiQy
+KHNbMF0sc1sxXSl9ZWxzZSBpZihyPT09Myl7aWYoISFhLiQzKXJldHVybiBhLiQzKHNbMF0sc1sxXSxz
+WzJdKX1lbHNlIGlmKHI9PT00KXtpZighIWEuJDQpcmV0dXJuIGEuJDQoc1swXSxzWzFdLHNbMl0sc1sz
+XSl9ZWxzZSBpZihyPT09NSlpZighIWEuJDUpcmV0dXJuIGEuJDUoc1swXSxzWzFdLHNbMl0sc1szXSxz
+WzRdKQpxPWFbIiIrIiQiK3JdCmlmKHEhPW51bGwpcmV0dXJuIHEuYXBwbHkoYSxzKX1yZXR1cm4gSC5F
+dyhhLGIsYyl9LApFdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGs9YiBpbnN0
+YW5jZW9mIEFycmF5P2I6UC5DSChiLCEwLHUueiksaj1rLmxlbmd0aCxpPWEuJFIKaWYoajxpKXJldHVy
+biBILnpvKGEsayxjKQp0PWEuJEQKcz10PT1udWxsCnI9IXM/dCgpOm51bGwKcT1KLmlhKGEpCnA9cS4k
+QwppZih0eXBlb2YgcD09InN0cmluZyIpcD1xW3BdCmlmKHMpe2lmKGMhPW51bGwmJmMuYSE9PTApcmV0
+dXJuIEguem8oYSxrLGMpCmlmKGo9PT1pKXJldHVybiBwLmFwcGx5KGEsaykKcmV0dXJuIEguem8oYSxr
+LGMpfWlmKHIgaW5zdGFuY2VvZiBBcnJheSl7aWYoYyE9bnVsbCYmYy5hIT09MClyZXR1cm4gSC56byhh
+LGssYykKaWYoaj5pK3IubGVuZ3RoKXJldHVybiBILnpvKGEsayxudWxsKQpDLk5tLkZWKGssci5zbGlj
+ZShqLWkpKQpyZXR1cm4gcC5hcHBseShhLGspfWVsc2V7aWYoaj5pKXJldHVybiBILnpvKGEsayxjKQpv
+PU9iamVjdC5rZXlzKHIpCmlmKGM9PW51bGwpZm9yKHM9by5sZW5ndGgsbj0wO248by5sZW5ndGg7by5s
+ZW5ndGg9PT1zfHwoMCxILmxrKShvKSwrK24pQy5ObS5BKGsscltILnkob1tuXSldKQplbHNle2Zvcihz
+PW8ubGVuZ3RoLG09MCxuPTA7bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8fCgwLEgubGspKG8pLCsrbil7
+bD1ILnkob1tuXSkKaWYoYy54NCgwLGwpKXsrK20KQy5ObS5BKGssYy5xKDAsbCkpfWVsc2UgQy5ObS5B
+KGsscltsXSl9aWYobSE9PWMuYSlyZXR1cm4gSC56byhhLGssYyl9cmV0dXJuIHAuYXBwbHkoYSxrKX19
+LApwWTpmdW5jdGlvbihhKXt0aHJvdyBILmIoSC50TChhKSl9LApPSDpmdW5jdGlvbihhLGIpe2lmKGE9
+PW51bGwpSi5IbShhKQp0aHJvdyBILmIoSC5IWShhLGIpKX0sCkhZOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cyxyPSJpbmRleCIKaWYoIUgub2soYikpcmV0dXJuIG5ldyBQLnUoITAsYixyLG51bGwpCnQ9SC5TYyhK
+LkhtKGEpKQppZighKGI8MCkpe2lmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIEgucFkodCkKcz1i
+Pj10fWVsc2Ugcz0hMAppZihzKXJldHVybiBQLkNmKGIsYSxyLG51bGwsdCkKcmV0dXJuIFAueChiLHIp
+fSwKYXU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PSJJbnZhbGlkIHZhbHVlIgppZihhPmMpcmV0dXJuIG5l
+dyBQLmJKKDAsYywhMCxhLCJzdGFydCIsdCkKaWYoYiE9bnVsbCl7aWYoIUgub2soYikpcmV0dXJuIG5l
+dyBQLnUoITAsYiwiZW5kIixudWxsKQppZihiPGF8fGI+YylyZXR1cm4gbmV3IFAuYkooYSxjLCEwLGIs
+ImVuZCIsdCl9cmV0dXJuIG5ldyBQLnUoITAsYiwiZW5kIixudWxsKX0sCnRMOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBuZXcgUC51KCEwLGEsbnVsbCxudWxsKX0sCmI6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYT09bnVs
+bClhPW5ldyBQLm4oKQp0PW5ldyBFcnJvcigpCnQuZGFydEV4Y2VwdGlvbj1hCmlmKCJkZWZpbmVQcm9w
+ZXJ0eSIgaW4gT2JqZWN0KXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCwibWVzc2FnZSIse2dldDpILmh9
+KQp0Lm5hbWU9IiJ9ZWxzZSB0LnRvU3RyaW5nPUguaApyZXR1cm4gdH0sCmg6ZnVuY3Rpb24oKXtyZXR1
+cm4gSi5qKHRoaXMuZGFydEV4Y2VwdGlvbil9LApWajpmdW5jdGlvbihhKXt0aHJvdyBILmIoYSl9LAps
+azpmdW5jdGlvbihhKXt0aHJvdyBILmIoUC5hNChhKSl9LApjTTpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
+cSxwLG8KYT1ILmVBKGEucmVwbGFjZShTdHJpbmcoe30pLCckcmVjZWl2ZXIkJykpCnQ9YS5tYXRjaCgv
+XFxcJFthLXpBLVpdK1xcXCQvZykKaWYodD09bnVsbCl0PUguVk0oW10sdS5zKQpzPXQuaW5kZXhPZigi
+XFwkYXJndW1lbnRzXFwkIikKcj10LmluZGV4T2YoIlxcJGFyZ3VtZW50c0V4cHJcXCQiKQpxPXQuaW5k
+ZXhPZigiXFwkZXhwclxcJCIpCnA9dC5pbmRleE9mKCJcXCRtZXRob2RcXCQiKQpvPXQuaW5kZXhPZigi
+XFwkcmVjZWl2ZXJcXCQiKQpyZXR1cm4gbmV3IEguZjkoYS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxc
+XCRhcmd1bWVudHNcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhw
+KCdcXFxcXFwkYXJndW1lbnRzRXhwclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5yZXBsYWNl
+KG5ldyBSZWdFeHAoJ1xcXFxcXCRleHByXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxh
+Y2UobmV3IFJlZ0V4cCgnXFxcXFxcJG1ldGhvZFxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5y
+ZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRyZWNlaXZlclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0p
+KiknKSxzLHIscSxwLG8pfSwKUzc6ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dmFy
+ICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXskZXhwciQuJG1ldGhvZCQoJGFyZ3VtZW50
+c0V4cHIkKX1jYXRjaCh0KXtyZXR1cm4gdC5tZXNzYWdlfX0oYSl9LApNajpmdW5jdGlvbihhKXtyZXR1
+cm4gZnVuY3Rpb24oJGV4cHIkKXt0cnl7JGV4cHIkLiRtZXRob2QkfWNhdGNoKHQpe3JldHVybiB0Lm1l
+c3NhZ2V9fShhKX0sCklqOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILlcwKGEsYj09bnVsbD9udWxs
+OmIubWV0aG9kKX0sClQzOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yj09bnVsbCxzPXQ/bnVsbDpiLm1ldGhv
+ZApyZXR1cm4gbmV3IEguYXooYSxzLHQ/bnVsbDpiLnJlY2VpdmVyKX0sClJ1OmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZj1udWxsLGU9bmV3IEguQW0oYSkKaWYoYT09bnVs
+bClyZXR1cm4gZgppZihhIGluc3RhbmNlb2YgSC5icSlyZXR1cm4gZS4kMShhLmEpCmlmKHR5cGVvZiBh
+IT09Im9iamVjdCIpcmV0dXJuIGEKaWYoImRhcnRFeGNlcHRpb24iIGluIGEpcmV0dXJuIGUuJDEoYS5k
+YXJ0RXhjZXB0aW9uKQplbHNlIGlmKCEoIm1lc3NhZ2UiIGluIGEpKXJldHVybiBhCnQ9YS5tZXNzYWdl
+CmlmKCJudW1iZXIiIGluIGEmJnR5cGVvZiBhLm51bWJlcj09Im51bWJlciIpe3M9YS5udW1iZXIKcj1z
+JjY1NTM1CmlmKChDLmpuLndHKHMsMTYpJjgxOTEpPT09MTApc3dpdGNoKHIpe2Nhc2UgNDM4OnJldHVy
+biBlLiQxKEguVDMoSC5kKHQpKyIgKEVycm9yICIrcisiKSIsZikpCmNhc2UgNDQ1OmNhc2UgNTAwNzpy
+ZXR1cm4gZS4kMShILklqKEguZCh0KSsiIChFcnJvciAiK3IrIikiLGYpKX19aWYoYSBpbnN0YW5jZW9m
+IFR5cGVFcnJvcil7cT0kLlNuKCkKcD0kLmxxKCkKbz0kLk45KCkKbj0kLmlJKCkKbT0kLktmKCkKbD0k
+LlpoKCkKaz0kLnJOKCkKJC5jMygpCmo9JC5ISygpCmk9JC5yMSgpCmg9cS5xUyh0KQppZihoIT1udWxs
+KXJldHVybiBlLiQxKEguVDMoSC55KHQpLGgpKQplbHNle2g9cC5xUyh0KQppZihoIT1udWxsKXtoLm1l
+dGhvZD0iY2FsbCIKcmV0dXJuIGUuJDEoSC5UMyhILnkodCksaCkpfWVsc2V7aD1vLnFTKHQpCmlmKGg9
+PW51bGwpe2g9bi5xUyh0KQppZihoPT1udWxsKXtoPW0ucVModCkKaWYoaD09bnVsbCl7aD1sLnFTKHQp
+CmlmKGg9PW51bGwpe2g9ay5xUyh0KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1q
+LnFTKHQpCmlmKGg9PW51bGwpe2g9aS5xUyh0KQpnPWghPW51bGx9ZWxzZSBnPSEwfWVsc2UgZz0hMH1l
+bHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwCmlmKGcpcmV0dXJu
+IGUuJDEoSC5JaihILnkodCksaCkpfX1yZXR1cm4gZS4kMShuZXcgSC52Vih0eXBlb2YgdD09InN0cmlu
+ZyI/dDoiIikpfWlmKGEgaW5zdGFuY2VvZiBSYW5nZUVycm9yKXtpZih0eXBlb2YgdD09InN0cmluZyIm
+JnQuaW5kZXhPZigiY2FsbCBzdGFjayIpIT09LTEpcmV0dXJuIG5ldyBQLktZKCkKdD1mdW5jdGlvbihi
+KXt0cnl7cmV0dXJuIFN0cmluZyhiKX1jYXRjaChkKXt9cmV0dXJuIG51bGx9KGEpCnJldHVybiBlLiQx
+KG5ldyBQLnUoITEsZixmLHR5cGVvZiB0PT0ic3RyaW5nIj90LnJlcGxhY2UoL15SYW5nZUVycm9yOlxz
+Ki8sIiIpOnQpKX1pZih0eXBlb2YgSW50ZXJuYWxFcnJvcj09ImZ1bmN0aW9uIiYmYSBpbnN0YW5jZW9m
+IEludGVybmFsRXJyb3IpaWYodHlwZW9mIHQ9PSJzdHJpbmciJiZ0PT09InRvbyBtdWNoIHJlY3Vyc2lv
+biIpcmV0dXJuIG5ldyBQLktZKCkKcmV0dXJuIGF9LAp0czpmdW5jdGlvbihhKXt2YXIgdAppZihhIGlu
+c3RhbmNlb2YgSC5icSlyZXR1cm4gYS5iCmlmKGE9PW51bGwpcmV0dXJuIG5ldyBILlhPKGEpCnQ9YS4k
+Y2FjaGVkVHJhY2UKaWYodCE9bnVsbClyZXR1cm4gdApyZXR1cm4gYS4kY2FjaGVkVHJhY2U9bmV3IEgu
+WE8oYSl9LApCNzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxPWEubGVuZ3RoCmZvcih0PTA7dDxxO3Q9
+cil7cz10KzEKcj1zKzEKYi5ZKDAsYVt0XSxhW3NdKX1yZXR1cm4gYn0sCmZ0OmZ1bmN0aW9uKGEsYixj
+LGQsZSxmKXt1LlouYihhKQpzd2l0Y2goSC5TYyhiKSl7Y2FzZSAwOnJldHVybiBhLiQwKCkKY2FzZSAx
+OnJldHVybiBhLiQxKGMpCmNhc2UgMjpyZXR1cm4gYS4kMihjLGQpCmNhc2UgMzpyZXR1cm4gYS4kMyhj
+LGQsZSkKY2FzZSA0OnJldHVybiBhLiQ0KGMsZCxlLGYpfXRocm93IEguYihuZXcgUC5DRCgiVW5zdXBw
+b3J0ZWQgbnVtYmVyIG9mIGFyZ3VtZW50cyBmb3Igd3JhcHBlZCBjbG9zdXJlIikpfSwKdFI6ZnVuY3Rp
+b24oYSxiKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBudWxsCnQ9YS4kaWRlbnRpdHkKaWYoISF0KXJl
+dHVybiB0CnQ9ZnVuY3Rpb24oYyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gZShj
+LGQsZixnLGgsaSl9fShhLGIsSC5mdCkKYS4kaWRlbnRpdHk9dApyZXR1cm4gdH0sCmlBOmZ1bmN0aW9u
+KGEsYixjLGQsZSxmLGcpe3ZhciB0LHMscixxLHAsbyxuLG0sbD1udWxsLGs9YlswXSxqPWsuJGNhbGxO
+YW1lLGk9ZT9PYmplY3QuY3JlYXRlKG5ldyBILnp4KCkuY29uc3RydWN0b3IucHJvdG90eXBlKTpPYmpl
+Y3QuY3JlYXRlKG5ldyBILnJUKGwsbCxsLGwpLmNvbnN0cnVjdG9yLnByb3RvdHlwZSkKaS4kaW5pdGlh
+bGl6ZT1pLmNvbnN0cnVjdG9yCmlmKGUpdD1mdW5jdGlvbiBzdGF0aWNfdGVhcl9vZmYoKXt0aGlzLiRp
+bml0aWFsaXplKCl9CmVsc2V7cz0kLnlqCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuVCgp
+CiQueWo9cysxCnM9bmV3IEZ1bmN0aW9uKCJhLGIsYyxkIitzLCJ0aGlzLiRpbml0aWFsaXplKGEsYixj
+LGQiK3MrIikiKQp0PXN9aS5jb25zdHJ1Y3Rvcj10CnQucHJvdG90eXBlPWkKaWYoIWUpe3I9SC5ieChh
+LGssZikKci4kcmVmbGVjdGlvbkluZm89ZH1lbHNle2kuJHN0YXRpY19uYW1lPWcKcj1rfXE9SC5pbShk
+LGUsZikKaS4kUz1xCmlbal09cgpmb3IocD1yLG89MTtvPGIubGVuZ3RoOysrbyl7bj1iW29dCm09bi4k
+Y2FsbE5hbWUKaWYobSE9bnVsbCl7bj1lP246SC5ieChhLG4sZikKaVttXT1ufWlmKG89PT1jKXtuLiRy
+ZWZsZWN0aW9uSW5mbz1kCnA9bn19aS4kQz1wCmkuJFI9ay4kUgppLiREPWsuJEQKcmV0dXJuIHR9LApp
+bTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBmdW5jdGlv
+bihkLGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBkKGUpfX0oSC5CcCxhKQppZih0eXBlb2YgYT09
+InN0cmluZyIpe2lmKGIpdGhyb3cgSC5iKCJDYW5ub3QgY29tcHV0ZSBzaWduYXR1cmUgZm9yIHN0YXRp
+YyB0ZWFyb2ZmLiIpCnQ9Yz9ILlBXOkguVG4KcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0
+aW9uKCl7cmV0dXJuIGUodGhpcyxkKX19KGEsdCl9dGhyb3cgSC5iKCJFcnJvciBpbiBmdW5jdGlvblR5
+cGUgb2YgdGVhcm9mZiIpfSwKdnE6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9SC5EVgpzd2l0Y2goYj8t
+MTphKXtjYXNlIDA6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYo
+dGhpcylbZV0oKX19KGMsdCkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlv
+bihnKXtyZXR1cm4gZih0aGlzKVtlXShnKX19KGMsdCkKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYp
+e3JldHVybiBmdW5jdGlvbihnLGgpe3JldHVybiBmKHRoaXMpW2VdKGcsaCl9fShjLHQpCmNhc2UgMzpy
+ZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGkpe3JldHVybiBmKHRoaXMpW2Vd
+KGcsaCxpKX19KGMsdCkKY2FzZSA0OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihn
+LGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSxqKX19KGMsdCkKY2FzZSA1OnJldHVybiBmdW5j
+dGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2VdKGcsaCxp
+LGosayl9fShjLHQpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7
+cmV0dXJuIGUuYXBwbHkoZih0aGlzKSxhcmd1bWVudHMpfX0oZCx0KX19LApieDpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQscyxyLHEscCxvLG4KaWYoYylyZXR1cm4gSC5IZihhLGIpCnQ9Yi4kc3R1Yk5hbWUKcz1i
+Lmxlbmd0aApyPWFbdF0KcT1iPT1udWxsP3I9PW51bGw6Yj09PXIKcD0hcXx8cz49MjcKaWYocClyZXR1
+cm4gSC52cShzLCFxLHQsYikKaWYocz09PTApe3E9JC55agppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJl
+dHVybiBxLlQoKQokLnlqPXErMQpvPSJzZWxmIitxCnE9InJldHVybiBmdW5jdGlvbigpe3ZhciAiK28r
+IiA9IHRoaXMuIgpwPSQubUoKcmV0dXJuIG5ldyBGdW5jdGlvbihxK0guZChwPT1udWxsPyQubUo9SC5F
+Migic2VsZiIpOnApKyI7cmV0dXJuICIrbysiLiIrSC5kKHQpKyIoKTt9IikoKX1uPSJhYmNkZWZnaGlq
+a2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHMpLmpvaW4oIiwiKQpxPSQueWoKaWYo
+dHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gcS5UKCkKJC55aj1xKzEKbis9cQpxPSJyZXR1cm4gZnVu
+Y3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIKcD0kLm1KCnJldHVybiBuZXcgRnVuY3Rpb24ocStILmQo
+cD09bnVsbD8kLm1KPUguRTIoInNlbGYiKTpwKSsiLiIrSC5kKHQpKyIoIituKyIpO30iKSgpfSwKWjQ6
+ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9SC5EVixzPUgueVMKc3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnRo
+cm93IEguYihILkVmKCJJbnRlcmNlcHRlZCBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50cy4iKSkKY2Fz
+ZSAxOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylb
+ZV0oZyh0aGlzKSl9fShjLHQscykKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1
+bmN0aW9uKGgpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCl9fShjLHQscykKY2FzZSAzOnJldHVy
+biBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyh0
+aGlzKSxoLGkpfX0oYyx0LHMpCmNhc2UgNDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5j
+dGlvbihoLGksail7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksail9fShjLHQscykKY2FzZSA1
+OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGspe3JldHVybiBmKHRo
+aXMpW2VdKGcodGhpcyksaCxpLGosayl9fShjLHQscykKY2FzZSA2OnJldHVybiBmdW5jdGlvbihlLGYs
+Zyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGssbCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGks
+aixrLGwpfX0oYyx0LHMpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZixnLGgpe3JldHVybiBmdW5j
+dGlvbigpe2g9W2codGhpcyldCkFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGgsYXJndW1lbnRzKQpy
+ZXR1cm4gZS5hcHBseShmKHRoaXMpLGgpfX0oZCx0LHMpfX0sCkhmOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cyxyLHEscCxvLG4sbT0kLm1KCmlmKG09PW51bGwpbT0kLm1KPUguRTIoInNlbGYiKQp0PSQuUDQKaWYo
+dD09bnVsbCl0PSQuUDQ9SC5FMigicmVjZWl2ZXIiKQpzPWIuJHN0dWJOYW1lCnI9Yi5sZW5ndGgKcT1h
+W3NdCnA9Yj09bnVsbD9xPT1udWxsOmI9PT1xCm89IXB8fHI+PTI4CmlmKG8pcmV0dXJuIEguWjQociwh
+cCxzLGIpCmlmKHI9PT0xKXttPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0guZChtKSsi
+LiIrSC5kKHMpKyIodGhpcy4iK0guZCh0KSsiKTsiCnQ9JC55agppZih0eXBlb2YgdCE9PSJudW1iZXIi
+KXJldHVybiB0LlQoKQokLnlqPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9bj0iYWJj
+ZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxyLTEpLmpvaW4oIiwiKQpt
+PSJyZXR1cm4gZnVuY3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIrSC5kKG0pKyIuIitILmQocykrIih0
+aGlzLiIrSC5kKHQpKyIsICIrbisiKTsiCnQ9JC55agppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVy
+biB0LlQoKQokLnlqPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9LAp1YzpmdW5jdGlv
+bihhLGIsYyxkLGUsZixnKXtyZXR1cm4gSC5pQShhLGIsYyxkLCEhZSwhIWYsZyl9LApUbjpmdW5jdGlv
+bihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgueksoYS5hKSxiKX0sClBXOmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2UsSC56SyhhLmMpLGIpfSwKRFY6ZnVuY3Rpb24o
+YSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApFMjpmdW5jdGlvbihhKXt2
+YXIgdCxzLHIscT1uZXcgSC5yVCgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIpLHA9Si5F
+cChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9yKHQ9cC5sZW5ndGgscz0wO3M8dDsrK3Mp
+e3I9cFtzXQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpmdW5jdGlvbihhKXtpZihhPT1udWxsKUgu
+Zk8oImJvb2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBudWxsIikKcmV0dXJuIGF9LApmTzpmdW5j
+dGlvbihhKXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5l
+dyBQLmMoYSkpfSwKRWY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILkVxKGEpfSwKWWc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHYuZ2V0SXNvbGF0ZVRhZyhhKX0sClZNOmZ1bmN0aW9uKGEsYil7YS4kdGk9YgpyZXR1
+cm4gYX0sCm9YOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIGEuJHRpfSwK
+SU06ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBILlk5KGFbIiRhIitILmQoYyldLEgub1goYikpfSwKWTk6
+ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiCmE9YS5hcHBseShudWxsLGIpCmlmKGE9PW51
+bGwpcmV0dXJuIG51bGwKaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09ImZ1
+bmN0aW9uIilyZXR1cm4gYS5hcHBseShudWxsLGIpCnJldHVybiBifSwKRlo6ZnVuY3Rpb24oYSxiLGMp
+e3JldHVybiBhLmFwcGx5KGIsSC5ZOShKLmlhKGIpWyIkYSIrSC5kKGMpXSxILm9YKGIpKSl9LAppdzpm
+dW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFsdWU6YyxlbnVtZXJhYmxl
+OmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0sCnczOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscixxLHA9SC55KCQuTkYuJDEoYSkpLG89JC5ud1twXQppZihvIT1udWxsKXtPYmplY3QuZGVm
+aW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFs
+c2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9dD0kLnZ2W3BdCmlm
+KHQhPW51bGwpcmV0dXJuIHQKcz12LmludGVyY2VwdG9yc0J5VGFnW3BdCmlmKHM9PW51bGwpe3A9SC55
+KCQuVFguJDIoYSxwKSkKaWYocCE9bnVsbCl7bz0kLm53W3BdCmlmKG8hPW51bGwpe09iamVjdC5kZWZp
+bmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxz
+ZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX10PSQudnZbcF0KaWYo
+dCE9bnVsbClyZXR1cm4gdApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbcF19fWlmKHM9PW51bGwpcmV0dXJu
+IG51bGwKdD1zLnByb3RvdHlwZQpyPXBbMF0KaWYocj09PSIhIil7bz1ILlZhKHQpCiQubndbcF09bwpP
+YmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVudW1l
+cmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9aWYo
+cj09PSJ+Iil7JC52dltwXT10CnJldHVybiB0fWlmKHI9PT0iLSIpe3E9SC5WYSh0KQpPYmplY3QuZGVm
+aW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUs
+e3ZhbHVlOnEsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkK
+cmV0dXJuIHEuaX1pZihyPT09IisiKXJldHVybiBILkxjKGEsdCkKaWYocj09PSIqIil0aHJvdyBILmIo
+UC5TWShwKSkKaWYodi5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5WYSh0KQpPYmplY3QuZGVmaW5lUHJv
+cGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVl
+OnEsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJu
+IHEuaX1lbHNlIHJldHVybiBILkxjKGEsdCl9LApMYzpmdW5jdGlvbihhLGIpe3ZhciB0PU9iamVjdC5n
+ZXRQcm90b3R5cGVPZihhKQpPYmplY3QuZGVmaW5lUHJvcGVydHkodCx2LmRpc3BhdGNoUHJvcGVydHlO
+YW1lLHt2YWx1ZTpKLlF1KGIsdCxudWxsLG51bGwpLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1
+ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBifSwKVmE6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUXUo
+YSwhMSxudWxsLCEhYS4kaVhqKX0sClZGOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLnByb3RvdHlwZQpp
+Zih2LmxlYWZUYWdzW2FdPT09dHJ1ZSlyZXR1cm4gSC5WYSh0KQplbHNlIHJldHVybiBKLlF1KHQsYyxu
+dWxsLG51bGwpfSwKWEQ6ZnVuY3Rpb24oKXtpZighMD09PSQuQnYpcmV0dXJuCiQuQnY9ITAKSC5aMSgp
+fSwKWjE6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtCiQubnc9T2JqZWN0LmNyZWF0ZShudWxs
+KQokLnZ2PU9iamVjdC5jcmVhdGUobnVsbCkKSC5rTygpCnQ9di5pbnRlcmNlcHRvcnNCeVRhZwpzPU9i
+amVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpCmlmKHR5cGVvZiB3aW5kb3chPSJ1bmRlZmluZWQiKXt3
+aW5kb3cKcj1mdW5jdGlvbigpe30KZm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCm89JC54Ny4k
+MShwKQppZihvIT1udWxsKXtuPUguVkYocCx0W3BdLG8pCmlmKG4hPW51bGwpe09iamVjdC5kZWZpbmVQ
+cm9wZXJ0eShvLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm4sZW51bWVyYWJsZTpmYWxzZSx3
+cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKci5wcm90b3R5cGU9b319fX1mb3IocT0wO3E8
+cy5sZW5ndGg7KytxKXtwPXNbcV0KaWYoL15bQS1aYS16X10vLnRlc3QocCkpe209dFtwXQp0WyIhIitw
+XT1tCnRbIn4iK3BdPW0KdFsiLSIrcF09bQp0WyIrIitwXT1tCnRbIioiK3BdPW19fX0sCmtPOmZ1bmN0
+aW9uKCl7dmFyIHQscyxyLHEscCxvLG49Qy5ZcSgpCm49SC51ZChDLktVLEgudWQoQy5mUSxILnVkKEMu
+aTcsSC51ZChDLmk3LEgudWQoQy54aSxILnVkKEMuZGssSC51ZChDLndiKEMuTzQpLG4pKSkpKSkpCmlm
+KHR5cGVvZiBkYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyIT0idW5kZWZpbmVkIil7dD1k
+YXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyCmlmKHR5cGVvZiB0PT0iZnVuY3Rpb24iKXQ9
+W3RdCmlmKHQuY29uc3RydWN0b3I9PUFycmF5KWZvcihzPTA7czx0Lmxlbmd0aDsrK3Mpe3I9dFtzXQpp
+Zih0eXBlb2Ygcj09ImZ1bmN0aW9uIiluPXIobil8fG59fXE9bi5nZXRUYWcKcD1uLmdldFVua25vd25U
+YWcKbz1uLnByb3RvdHlwZUZvclRhZwokLk5GPW5ldyBILmRDKHEpCiQuVFg9bmV3IEgud04ocCkKJC54
+Nz1uZXcgSC5WWChvKX0sCnVkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEoYil8fGJ9LAp2NDpmdW5jdGlv
+bihhLGIsYyxkLGUsZil7dmFyIHQ9Yj8ibSI6IiIscz1jPyIiOiJpIixyPWQ/InUiOiIiLHE9ZT8icyI6
+IiIscD1mPyJnIjoiIixvPWZ1bmN0aW9uKGcsaCl7dHJ5e3JldHVybiBuZXcgUmVnRXhwKGcsaCl9Y2F0
+Y2gobil7cmV0dXJuIG59fShhLHQrcytyK3ErcCkKaWYobyBpbnN0YW5jZW9mIFJlZ0V4cClyZXR1cm4g
+bwp0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBSZWdFeHAgcGF0dGVybiAoIitTdHJpbmcobykrIikiLGEs
+bnVsbCkpfSwKbTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKHR5cGVvZiBiPT0ic3RyaW5nIilyZXR1
+cm4gYS5pbmRleE9mKGIsYyk+PTAKZWxzZSBpZihiIGluc3RhbmNlb2YgSC5WUil7dD1DLnhCLnluKGEs
+YykKcmV0dXJuIGIuYi50ZXN0KHQpfWVsc2V7dD1KLkZMKGIsQy54Qi55bihhLGMpKQpyZXR1cm4hdC5n
+bDAodCl9fSwKQTQ6ZnVuY3Rpb24oYSl7aWYoYS5pbmRleE9mKCIkIiwwKT49MClyZXR1cm4gYS5yZXBs
+YWNlKC9cJC9nLCIkJCQkIikKcmV0dXJuIGF9LAplQTpmdW5jdGlvbihhKXtpZigvW1tcXXt9KCkqKz8u
+XFxeJHxdLy50ZXN0KGEpKXJldHVybiBhLnJlcGxhY2UoL1tbXF17fSgpKis/LlxcXiR8XS9nLCJcXCQm
+IikKcmV0dXJuIGF9LAp5czpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5uTShhLGIsYykKcmV0dXJuIHR9
+LApuTTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEKaWYoYj09PSIiKXtpZihhPT09IiIpcmV0dXJu
+IGMKdD1hLmxlbmd0aApmb3Iocz1jLHI9MDtyPHQ7KytyKXM9cythW3JdK2MKcmV0dXJuIHMuY2hhckNv
+ZGVBdCgwKT09MD9zOnN9cT1hLmluZGV4T2YoYiwwKQppZihxPDApcmV0dXJuIGEKaWYoYS5sZW5ndGg8
+NTAwfHxjLmluZGV4T2YoIiQiLDApPj0wKXJldHVybiBhLnNwbGl0KGIpLmpvaW4oYykKcmV0dXJuIGEu
+cmVwbGFjZShuZXcgUmVnRXhwKEguZUEoYiksJ2cnKSxILkE0KGMpKX0sClBEOmZ1bmN0aW9uIFBEKGEs
+Yil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCldVOmZ1bmN0aW9uIFdVKCl7fSwKTFA6ZnVuY3Rpb24gTFAo
+YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKWFI6ZnVuY3Rpb24g
+WFIoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKTEk6ZnVuY3Rpb24gTEkoYSxiLGMsZCxlKXt2YXIg
+Xz10aGlzCl8uYT1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uZj1lfSwKQ2o6ZnVuY3Rpb24gQ2ooYSxiLGMp
+e3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKZjk6ZnVuY3Rpb24gZjkoYSxiLGMsZCxlLGYpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWZ9LApXMDpmdW5jdGlvbiBX
+MChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKYXo6ZnVuY3Rpb24gYXooYSxiLGMpe3RoaXMuYT1hCnRo
+aXMuYj1iCnRoaXMuYz1jfSwKdlY6ZnVuY3Rpb24gdlYoYSl7dGhpcy5hPWF9LApicTpmdW5jdGlvbiBi
+cShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQW06ZnVuY3Rpb24gQW0oYSl7dGhpcy5hPWF9LApYTzpm
+dW5jdGlvbiBYTyhhKXt0aGlzLmE9YQp0aGlzLmI9bnVsbH0sClRwOmZ1bmN0aW9uIFRwKCl7fSwKbGM6
+ZnVuY3Rpb24gbGMoKXt9LAp6eDpmdW5jdGlvbiB6eCgpe30sCnJUOmZ1bmN0aW9uIHJUKGEsYixjLGQp
+e3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApFcTpmdW5jdGlvbiBFcShhKXt0aGlz
+LmE9YX0sCmtZOmZ1bmN0aW9uIGtZKGEpe3RoaXMuYT1hfSwKTjU6ZnVuY3Rpb24gTjUoYSl7dmFyIF89
+dGhpcwpfLmE9MApfLmY9Xy5lPV8uZD1fLmM9Xy5iPW51bGwKXy5yPTAKXy4kdGk9YX0sCnZoOmZ1bmN0
+aW9uIHZoKGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LAppNTpmdW5jdGlv
+biBpNShhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApONjpmdW5jdGlvbiBONihhLGIsYyl7dmFyIF89
+dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGwKXy4kdGk9Y30sCmRDOmZ1bmN0aW9uIGRDKGEpe3Ro
+aXMuYT1hfSwKd046ZnVuY3Rpb24gd04oYSl7dGhpcy5hPWF9LApWWDpmdW5jdGlvbiBWWChhKXt0aGlz
+LmE9YX0sClZSOmZ1bmN0aW9uIFZSKGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51
+bGx9LApFSzpmdW5jdGlvbiBFSyhhKXt0aGlzLmI9YX0sCktXOmZ1bmN0aW9uIEtXKGEsYixjKXt0aGlz
+LmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClBiOmZ1bmN0aW9uIFBiKGEsYixjKXt2YXIgXz10aGlzCl8u
+YT1hCl8uYj1iCl8uYz1jCl8uZD1udWxsfSwKdFE6ZnVuY3Rpb24gdFEoYSxiKXt0aGlzLmE9YQp0aGlz
+LmM9Yn0sCnVuOmZ1bmN0aW9uIHVuKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClNk
+OmZ1bmN0aW9uIFNkKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1udWxsfSwK
+WEY6ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LApEUTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEludDhBcnJh
+eShhKX0sCm9kOmZ1bmN0aW9uKGEsYixjKXtpZihhPj4+MCE9PWF8fGE+PWMpdGhyb3cgSC5iKEguSFko
+YixhKSl9LApyTTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYoIShhPj4+MCE9PWEpKXQ9Yj4+PjAhPT1i
+fHxhPmJ8fGI+YwplbHNlIHQ9ITAKaWYodCl0aHJvdyBILmIoSC5hdShhLGIsYykpCnJldHVybiBifSwK
+V1o6ZnVuY3Rpb24gV1ooKXt9LApFVDpmdW5jdGlvbiBFVCgpe30sCmRmOmZ1bmN0aW9uIGRmKCl7fSwK
+YjA6ZnVuY3Rpb24gYjAoKXt9LApEZzpmdW5jdGlvbiBEZygpe30sClBnOmZ1bmN0aW9uIFBnKCl7fSwK
+eGo6ZnVuY3Rpb24geGooKXt9LApkRTpmdW5jdGlvbiBkRSgpe30sClpBOmZ1bmN0aW9uIFpBKCl7fSwK
+d2Y6ZnVuY3Rpb24gd2YoKXt9LApQcTpmdW5jdGlvbiBQcSgpe30sCmVFOmZ1bmN0aW9uIGVFKCl7fSwK
+VjY6ZnVuY3Rpb24gVjYoKXt9LApSRzpmdW5jdGlvbiBSRygpe30sClZQOmZ1bmN0aW9uIFZQKCl7fSwK
+V0I6ZnVuY3Rpb24gV0IoKXt9LApaRzpmdW5jdGlvbiBaRygpe30sCnhaOmZ1bmN0aW9uKGEsYil7dmFy
+IHQ9Yi5kCnJldHVybiB0PT1udWxsP2IuZD1ILkooYSwiYjgiLFtiLlFdKTp0fSwKUTE6ZnVuY3Rpb24o
+YSl7dmFyIHQ9YS56CmlmKHQ9PT02fHx0PT09N3x8dD09PTgpcmV0dXJuIEguUTEoYS5RKQpyZXR1cm4g
+dD09PTExfHx0PT09MTJ9LAptRDpmdW5jdGlvbihhKXtyZXR1cm4gYS5kYn0sCllROmZ1bmN0aW9uKGEp
+e3JldHVybiBILkUodi50eXBlVW5pdmVyc2UsYSl9LApKUzpmdW5jdGlvbihhKXt2YXIgdD1hLiRTCmlm
+KHQhPW51bGwpe2lmKHR5cGVvZiB0PT0ibnVtYmVyIilyZXR1cm4gSC5CcCh0KQpyZXR1cm4gYS4kUygp
+fXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihILlExKGIpKWlmKGEgaW5zdGFu
+Y2VvZiBILlRwKXt0PUguSlMoYSkKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gSC56SyhhKX0sCnpL
+OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGEgaW5zdGFuY2VvZiBQLmspe3Q9YS4kdGkKcmV0dXJuIHQhPW51
+bGw/dDpILlZVKGEpfWlmKEFycmF5LmlzQXJyYXkoYSkpcmV0dXJuIEgudDYoYSkKcmV0dXJuIEguVlUo
+Si5pYShhKSl9LAp0NjpmdW5jdGlvbihhKXt2YXIgdD1hLiR0aSxzPXUudQppZih0PT1udWxsKXJldHVy
+biBzCmlmKHQuY29uc3RydWN0b3IhPT1zLmNvbnN0cnVjdG9yKXJldHVybiBzCnJldHVybiB0fSwKTGg6
+ZnVuY3Rpb24oYSl7dmFyIHQ9YS4kdGkKcmV0dXJuIHQhPW51bGw/dDpILlZVKGEpfSwKVlU6ZnVuY3Rp
+b24oYSl7dmFyIHQ9YS5jb25zdHJ1Y3RvcixzPXQuJGNjYWNoZQppZihzIT1udWxsKXJldHVybiBzCnJl
+dHVybiBILnI5KGEsdCl9LApyOTpmdW5jdGlvbihhLGIpe3ZhciB0PWEgaW5zdGFuY2VvZiBILlRwP2Eu
+X19wcm90b19fLl9fcHJvdG9fXy5jb25zdHJ1Y3RvcjpiLHM9SC5haSh2LnR5cGVVbml2ZXJzZSx0Lm5h
+bWUpCmIuJGNjYWNoZT1zCnJldHVybiBzfSwKQnA6ZnVuY3Rpb24oYSl7dmFyIHQscz1hLHI9di50eXBl
+cyxxPXJbc10KaWYodHlwZW9mIHE9PSJzdHJpbmciKXt0PUguRSh2LnR5cGVVbml2ZXJzZSxxKQpyW3Nd
+PXQKcmV0dXJuIHR9cmV0dXJuIHF9LApKSjpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1zLnoscT1I
+LllPCmlmKEguY2Mocykpe3E9SC5JdwpzLmI9cy5hPUguaG59ZWxzZSBpZihyPT09OSl7dD1zLmRiCmlm
+KCJLTiI9PT10KXE9SC5vawplbHNlIGlmKCJDUCI9PT10KXE9SC5LSAplbHNlIGlmKCJGSyI9PT10KXE9
+SC5LSAplbHNlIGlmKCJxVSI9PT10KXE9SC5NTQplbHNlIGlmKCJhMiI9PT10KXE9SC5sCmVsc2V7cj1z
+LlEKaWYocy5jaC5ldmVyeShILmNjKSl7cy54PSIkaSIrcgpxPUgudDR9fX1zLmM9cQpyZXR1cm4gcy5j
+KGEpfSwKWU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwpyZXR1cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxI
+LlVlKGEsdCksbnVsbCx0LG51bGwpfSwKdDQ6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy54CmlmKGEgaW5z
+dGFuY2VvZiBQLmspcmV0dXJuISFhW3RdCnJldHVybiEhSi5pYShhKVt0XX0sCk96OmZ1bmN0aW9uKGEp
+e3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIGEKdD10aGlzCmlmKHQuYyhhKSlyZXR1cm4gYQp0aHJvdyBI
+LmIoSC5RNShILldLKGEsSC5VZShhLHQpLEguZG0odCxudWxsKSkpKX0sCkF2OmZ1bmN0aW9uKGEpe3Zh
+ciB0CmlmKGE9PW51bGwpcmV0dXJuIGEKdD10aGlzCmlmKHQuYyhhKSlyZXR1cm4gYQp0aHJvdyBILmIo
+SC5aYyhILldLKGEsSC5VZShhLHQpLEguZG0odCxudWxsKSkpKX0sCkRoOmZ1bmN0aW9uKGEsYixjLGQp
+e3ZhciB0PW51bGwKaWYoSC5XZSh2LnR5cGVVbml2ZXJzZSxhLHQsYix0KSlyZXR1cm4gYQp0aHJvdyBI
+LmIoSC5aYygiVGhlIHR5cGUgYXJndW1lbnQgJyIrSC5kKEguZG0oYSx0KSkrIicgaXMgbm90IGEgc3Vi
+dHlwZSBvZiB0aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitILmQoSC5kbShiLHQpKSsiJyBvZiB0eXBl
+IHZhcmlhYmxlICciK2MrIicgaW4gJyIrSC5kKGQpKyInLiIpKX0sCldLOmZ1bmN0aW9uKGEsYixjKXt2
+YXIgdD1QLnAoYSkscz1ILmRtKGI9PW51bGw/SC56SyhhKTpiLG51bGwpCnJldHVybiB0KyI6IHR5cGUg
+JyIrSC5kKHMpKyInIGlzIG5vdCBhIHN1YnR5cGUgb2YgdHlwZSAnIitILmQoYykrIicifSwKUTU6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIG5ldyBILmh6KCJDYXN0RXJyb3I6ICIrYSl9LApQdjpmdW5jdGlvbihhLGIp
+e3JldHVybiBuZXcgSC5oeigiQ2FzdEVycm9yOiAiK0guV0soYSxudWxsLGIpKX0sClpjOmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgSC5pTSgiVHlwZUVycm9yOiAiK2EpfSwKcTpmdW5jdGlvbihhLGIpe3JldHVy
+biBuZXcgSC5pTSgiVHlwZUVycm9yOiAiK0guV0soYSxudWxsLGIpKX0sCkl3OmZ1bmN0aW9uKGEpe3Jl
+dHVybiEwfSwKaG46ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LApsOmZ1bmN0aW9uKGEpe3JldHVybiEwPT09
+YXx8ITE9PT1hfSwKRTk6ZnVuY3Rpb24oYSl7aWYoITA9PT1hfHwhMT09PWEpcmV0dXJuIGEKaWYoYT09
+bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJib29sIikpfSwKeGQ6ZnVuY3Rpb24oYSl7aWYo
+ITA9PT1hfHwhMT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEs
+ImJvb2wiKSl9LApkajpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYo
+YT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJkb3VibGUiKSl9LApJZzpmdW5jdGlvbihh
+KXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBI
+LmIoSC5xKGEsImRvdWJsZSIpKX0sCm9rOmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09Im51bWJl
+ciImJk1hdGguZmxvb3IoYSk9PT1hfSwKU0g6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIi
+JiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihI
+LlB2KGEsImludCIpKX0sClNjOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5m
+bG9vcihhKT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImlu
+dCIpKX0sCktIOmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09Im51bWJlciJ9LAp1VTpmdW5jdGlv
+bihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJv
+dyBILmIoSC5QdihhLCJudW0iKSl9LApETjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIp
+cmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIm51bSIpKX0sCk1NOmZ1
+bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09InN0cmluZyJ9LApyYzpmdW5jdGlvbihhKXtpZih0eXBl
+b2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5Qdihh
+LCJTdHJpbmciKSl9LAp5OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gYQpp
+ZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiU3RyaW5nIikpfSwKaW86ZnVuY3Rpb24o
+YSxiKXt2YXIgdCxzLHIKZm9yKHQ9IiIscz0iIixyPTA7cjxhLmxlbmd0aDsrK3Iscz0iLCAiKXQrPUMu
+eEIuVChzLEguZG0oYVtyXSxiKSkKcmV0dXJuIHR9LApiSTpmdW5jdGlvbihhMCxhMSxhMil7dmFyIHQs
+cyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYT0iLCAiCmlmKGEyIT1udWxsKXt0PWEy
+Lmxlbmd0aAppZihhMT09bnVsbCl7YTE9SC5WTShbXSx1LnMpCnM9bnVsbH1lbHNlIHM9YTEubGVuZ3Ro
+CnI9YTEubGVuZ3RoCmZvcihxPXQ7cT4wOy0tcSlDLk5tLkEoYTEsIlQiKyhyK3EpKQpmb3IocD0iPCIs
+bz0iIixxPTA7cTx0OysrcSxvPWEpe3ArPW8Kbj1hMS5sZW5ndGgKbT1uLTEtcQppZihtPDApcmV0dXJu
+IEguT0goYTEsbSkKcD1DLnhCLlQocCxhMVttXSkKbD1hMltxXQppZighSC5jYyhsKSlwKz1DLnhCLlQo
+IiBleHRlbmRzICIsSC5kbShsLGExKSl9cCs9Ij4ifWVsc2V7cD0iIgpzPW51bGx9bj1hMC5RCms9YTAu
+Y2gKaj1rLmEKaT1qLmxlbmd0aApoPWsuYgpnPWgubGVuZ3RoCmY9ay5jCmU9Zi5sZW5ndGgKZD1ILmRt
+KG4sYTEpCmZvcihjPSIiLGI9IiIscT0wO3E8aTsrK3EsYj1hKWMrPUMueEIuVChiLEguZG0oaltxXSxh
+MSkpCmlmKGc+MCl7Yys9YisiWyIKZm9yKGI9IiIscT0wO3E8ZzsrK3EsYj1hKWMrPUMueEIuVChiLEgu
+ZG0oaFtxXSxhMSkpCmMrPSJdIn1pZihlPjApe2MrPWIrInsiCmZvcihiPSIiLHE9MDtxPGU7cSs9Mixi
+PWEpYys9Qy54Qi5UKGIsSC5kbShmW3ErMV0sYTEpKSsiICIrZltxXQpjKz0ifSJ9aWYocyE9bnVsbClh
+MS5sZW5ndGg9cwpyZXR1cm4gcCsiKCIrYysiKSA9PiAiK0guZChkKX0sCmRtOmZ1bmN0aW9uKGEsYil7
+dmFyIHQscyxyLHEscD1hLnoKaWYocD09PTUpcmV0dXJuImVyYXNlZCIKaWYocD09PTIpcmV0dXJuImR5
+bmFtaWMiCmlmKHA9PT0zKXJldHVybiJ2b2lkIgppZihwPT09MSlyZXR1cm4iTmV2ZXIiCmlmKHA9PT00
+KXJldHVybiJhbnkiCmlmKHA9PT02KXJldHVybiBILmQoSC5kbShhLlEsYikpKyIqIgppZihwPT09Nyly
+ZXR1cm4gSC5kKEguZG0oYS5RLGIpKSsiPyIKaWYocD09PTgpcmV0dXJuIkZ1dHVyZU9yPCIrSC5kKEgu
+ZG0oYS5RLGIpKSsiPiIKaWYocD09PTkpe3Q9SC5vMyhhLlEpCnM9YS5jaApyZXR1cm4gcy5sZW5ndGgh
+PT0wP3QrKCI8IitILmlvKHMsYikrIj4iKTp0fWlmKHA9PT0xMSlyZXR1cm4gSC5iSShhLGIsbnVsbCkK
+aWYocD09PTEyKXJldHVybiBILmJJKGEuUSxiLGEuY2gpCmlmKHA9PT0xMyl7cj1hLlEKcT1iLmxlbmd0
+aApyPXEtMS1yCmlmKHI8MHx8cj49cSlyZXR1cm4gSC5PSChiLHIpCnJldHVybiBiW3JdfXJldHVybiI/
+In0sCm8zOmZ1bmN0aW9uKGEpe3ZhciB0LHM9SC5KZyhhKQppZihzIT1udWxsKXJldHVybiBzCnQ9Im1p
+bmlmaWVkOiIrYQpyZXR1cm4gdH0sClFvOmZ1bmN0aW9uKGEsYil7dmFyIHQ9YS50UltiXQpmb3IoO3R5
+cGVvZiB0PT0ic3RyaW5nIjspdD1hLnRSW3RdCnJldHVybiB0fSwKYWk6ZnVuY3Rpb24oYSxiKXt2YXIg
+dCxzLHIscSxwLG89YS5lVCxuPW9bYl0KaWYobj09bnVsbClyZXR1cm4gSC5FKGEsYikKZWxzZSBpZih0
+eXBlb2Ygbj09Im51bWJlciIpe3Q9bgpzPUgubShhLDUsIiMiKQpyPVtdCmZvcihxPTA7cTx0OysrcSly
+LnB1c2gocykKcD1ILkooYSxiLHIpCm9bYl09cApyZXR1cm4gcH1lbHNlIHJldHVybiBufSwKeGI6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gSC5JeChhLnRSLGIpfSwKRkY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5J
+eChhLmVULGIpfSwKRTpmdW5jdGlvbihhLGIpe3ZhciB0LHM9YS5lQyxyPXMuZ2V0KGIpCmlmKHIhPW51
+bGwpcmV0dXJuIHIKdD1ILnooYSxudWxsLGIpCnMuc2V0KGIsdCkKcmV0dXJuIHR9LApjRTpmdW5jdGlv
+bihhLGIsYyl7dmFyIHQscyxyPWIuY3gKaWYocj09bnVsbClyPWIuY3g9bmV3IE1hcCgpCnQ9ci5nZXQo
+YykKaWYodCE9bnVsbClyZXR1cm4gdApzPUgueihhLGIsYykKci5zZXQoYyxzKQpyZXR1cm4gc30sCnY1
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1iLmN5CmlmKHE9PW51bGwpcT1iLmN5PW5ldyBNYXAo
+KQp0PWMuZGIKcz1xLmdldCh0KQppZihzIT1udWxsKXJldHVybiBzCnI9SC5hKGEsYixjLno9PT0xMD9j
+LmNoOltjXSkKcS5zZXQodCxyKQpyZXR1cm4gcn0sCno6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguaShI
+Lm8oYSxiLGMpKQpyZXR1cm4gdH0sCldHOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5kYgphLmVDLnNldCh0
+LGIpCmIuYT1ILk96CmIuYj1ILkF2CmIuYz1ILkpKCnJldHVybiBifSwKbTpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQscz1hLmVDLmdldChjKQppZihzIT1udWxsKXJldHVybiBzCnQ9bmV3IEguSmMobnVsbCxudWxs
+LG51bGwpCnQuej1iCnQuZGI9YwpyZXR1cm4gSC5XRyhhLHQpfSwKdjpmdW5jdGlvbihhLGIsYyxkKXt2
+YXIgdCxzPWEuZUMuZ2V0KGQpCmlmKHMhPW51bGwpcmV0dXJuIHMKdD1uZXcgSC5KYyhudWxsLG51bGws
+bnVsbCkKdC56PWIKdC5RPWMKdC5kYj1kCnJldHVybiBILldHKGEsdCl9LApIOmZ1bmN0aW9uKGEsYil7
+dmFyIHQscz0iIitiKyJeIixyPWEuZUMuZ2V0KHMpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1uZXcgSC5K
+YyhudWxsLG51bGwsbnVsbCkKdC56PTEzCnQuUT1iCnQuZGI9cwpyZXR1cm4gSC5XRyhhLHQpfSwKVXg6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9YS5sZW5ndGgKZm9yKHQ9IiIscz0iIixyPTA7cjxxOysrcixz
+PSIsIil0Kz1zK2Fbcl0uZGIKcmV0dXJuIHR9LApTNDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG89
+YS5sZW5ndGgKZm9yKHQ9IiIscz0iIixyPTA7cjxvO3IrPTIscz0iLCIpe3E9YVtyXQpwPWFbcisxXS5k
+Ygp0Kz1zK3ErIjoiK3B9cmV0dXJuIHR9LApKOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9YgppZihj
+Lmxlbmd0aCE9PTApcis9IjwiK0guVXgoYykrIj4iCnQ9YS5lQy5nZXQocikKaWYodCE9bnVsbClyZXR1
+cm4gdApzPW5ldyBILkpjKG51bGwsbnVsbCxudWxsKQpzLno9OQpzLlE9YgpzLmNoPWMKaWYoYy5sZW5n
+dGg+MClzLmQ9Y1swXQpzLmRiPXIKcmV0dXJuIEguV0coYSxzKX0sCmE6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0LHMscixxLHAKaWYoYi56PT09MTApe3Q9Yi5RCnM9Yi5jaC5jb25jYXQoYyl9ZWxzZXtzPWMKdD1i
+fXI9dC5kYisiOyIrKCI8IitILlV4KHMpKyI+IikKcT1hLmVDLmdldChyKQppZihxIT1udWxsKXJldHVy
+biBxCnA9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnAuej0xMApwLlE9dApwLmNoPXMKcC5kYj1yCnJl
+dHVybiBILldHKGEscCl9LApDOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1iLmRiLHA9Yy5hLG89
+cC5sZW5ndGgsbj1jLmIsbT1uLmxlbmd0aCxsPWMuYyxrPWwubGVuZ3RoLGo9IigiK0guVXgocCkKaWYo
+bT4wKWorPShvPjA/IiwiOiIiKSsiWyIrSC5VeChuKSsiXSIKaWYoaz4wKWorPShvPjA/IiwiOiIiKSsi
+eyIrSC5TNChsKSsifSIKdD1xKyhqKyIpIikKcz1hLmVDLmdldCh0KQppZihzIT1udWxsKXJldHVybiBz
+CnI9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnIuej0xMQpyLlE9YgpyLmNoPWMKci5kYj10CnJldHVy
+biBILldHKGEscil9LApEOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuZGIrIjwiK0guVXgoYykrIj4i
+LHI9YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PW5ldyBILkpjKG51bGwsbnVsbCxudWxs
+KQp0Lno9MTIKdC5RPWIKdC5jaD1jCnQuZGI9cwpyZXR1cm4gSC5XRyhhLHQpfSwKbzpmdW5jdGlvbihh
+LGIsYyl7cmV0dXJue3U6YSxlOmIscjpjLHM6W10scDowfX0sCmk6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
+LHEscCxvLG4sbSxsLGssaixpLGgsZz1hLnIsZj1hLnMKZm9yKHQ9Zy5sZW5ndGgscz0wO3M8dDspe3I9
+Zy5jaGFyQ29kZUF0KHMpCmlmKHI+PTQ4JiZyPD01NylzPUguQShzKzEscixnLGYpCmVsc2UgaWYoKCgo
+cnwzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHI9PT05NXx8cj09PTM2KXM9SC50KGEscyxnLGYsITEpCmVs
+c2UgaWYocj09PTQ2KXM9SC50KGEscyxnLGYsITApCmVsc2V7KytzCnN3aXRjaChyKXtjYXNlIDQ0OmJy
+ZWFrCmNhc2UgNTg6YnJlYWsKY2FzZSA1OTpmLnB1c2goSC5LKGEudSxhLmUsZi5wb3AoKSkpCmJyZWFr
+CmNhc2UgOTQ6Zi5wdXNoKEguSChhLnUsZi5wb3AoKSkpCmJyZWFrCmNhc2UgMzU6Zi5wdXNoKEgubShh
+LnUsNSwiIyIpKQpicmVhawpjYXNlIDY0OmYucHVzaChILm0oYS51LDIsIkAiKSkKYnJlYWsKY2FzZSAx
+MjY6Zi5wdXNoKEgubShhLnUsMywifiIpKQpicmVhawpjYXNlIDYwOmYucHVzaChhLnApCmEucD1mLmxl
+bmd0aApicmVhawpjYXNlIDYyOnE9YS51CnA9Zi5zcGxpY2UoYS5wKQpILnIoYS51LGEuZSxwKQphLnA9
+Zi5wb3AoKQpvPWYucG9wKCkKaWYodHlwZW9mIG89PSJzdHJpbmciKWYucHVzaChILkoocSxvLHApKQpl
+bHNle249SC5LKHEsYS5lLG8pCnN3aXRjaChuLnope2Nhc2UgMTE6Zi5wdXNoKEguRChxLG4scCkpCmJy
+ZWFrCmRlZmF1bHQ6Zi5wdXNoKEguYShxLG4scCkpCmJyZWFrfX1icmVhawpjYXNlIDM4OkguSShhLGYp
+CmJyZWFrCmNhc2UgNDI6bT1hLnUKbD1ILksobSxhLmUsZi5wb3AoKSkKZi5wdXNoKEgudihtLDYsbCxs
+LmRiKyIqIikpCmJyZWFrCmNhc2UgNjM6bT1hLnUKbD1ILksobSxhLmUsZi5wb3AoKSkKZi5wdXNoKEgu
+dihtLDcsbCxsLmRiKyI/IikpCmJyZWFrCmNhc2UgNDc6bT1hLnUKbD1ILksobSxhLmUsZi5wb3AoKSkK
+Zi5wdXNoKEgudihtLDgsbCxsLmRiKyIvIikpCmJyZWFrCmNhc2UgNDA6Zi5wdXNoKGEucCkKYS5wPWYu
+bGVuZ3RoCmJyZWFrCmNhc2UgNDE6cT1hLnUKaz1uZXcgSC5HKCkKaj1xLnNFQQppPXEuc0VBCm89Zi5w
+b3AoKQppZih0eXBlb2Ygbz09Im51bWJlciIpc3dpdGNoKG8pe2Nhc2UtMTpqPWYucG9wKCkKYnJlYWsK
+Y2FzZS0yOmk9Zi5wb3AoKQpicmVhawpkZWZhdWx0OmYucHVzaChvKQpicmVha31lbHNlIGYucHVzaChv
+KQpwPWYuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUscCkKYS5wPWYucG9wKCkKay5hPXAKay5iPWoKay5j
+PWkKZi5wdXNoKEguQyhxLEguSyhxLGEuZSxmLnBvcCgpKSxrKSkKYnJlYWsKY2FzZSA5MTpmLnB1c2go
+YS5wKQphLnA9Zi5sZW5ndGgKYnJlYWsKY2FzZSA5MzpwPWYuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUs
+cCkKYS5wPWYucG9wKCkKZi5wdXNoKHApCmYucHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6Zi5wdXNoKGEu
+cCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgMTI1OnA9Zi5zcGxpY2UoYS5wKQpILkIoYS51LGEuZSxw
+KQphLnA9Zi5wb3AoKQpmLnB1c2gocCkKZi5wdXNoKC0yKQpicmVhawpkZWZhdWx0OnRocm93IkJhZCBj
+aGFyYWN0ZXIgIityfX19aD1mLnBvcCgpCnJldHVybiBILksoYS51LGEuZSxoKX0sCkE6ZnVuY3Rpb24o
+YSxiLGMsZCl7dmFyIHQscyxyPWItNDgKZm9yKHQ9Yy5sZW5ndGg7YTx0OysrYSl7cz1jLmNoYXJDb2Rl
+QXQoYSkKaWYoIShzPj00OCYmczw9NTcpKWJyZWFrCnI9cioxMCsocy00OCl9ZC5wdXNoKHIpCnJldHVy
+biBhfSwKdDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuPWIrMQpmb3IodD1jLmxl
+bmd0aDtuPHQ7KytuKXtzPWMuY2hhckNvZGVBdChuKQppZihzPT09NDYpe2lmKGUpYnJlYWsKZT0hMH1l
+bHNle2lmKCEoKCgoc3wzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHM9PT05NXx8cz09PTM2KSlyPXM+PTQ4
+JiZzPD01NwplbHNlIHI9ITAKaWYoIXIpYnJlYWt9fXE9Yy5zdWJzdHJpbmcoYixuKQppZihlKXt0PWEu
+dQpwPWEuZQppZihwLno9PT0xMClwPXAuUQpvPUguUW8odCxwLlEpW3FdCmlmKG89PW51bGwpSC5Waign
+Tm8gIicrcSsnIiBpbiAiJytILm1EKHApKyciJykKZC5wdXNoKEguY0UodCxwLG8pKX1lbHNlIGQucHVz
+aChxKQpyZXR1cm4gbn0sCkk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLnBvcCgpCmlmKDA9PT10KXtiLnB1
+c2goSC5tKGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXQpe2IucHVzaChILm0oYS51LDQsIjEmIikp
+CnJldHVybn10aHJvdyBILmIoUC5oVigiVW5leHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILmQo
+dCkpKX0sCks6ZnVuY3Rpb24oYSxiLGMpe2lmKHR5cGVvZiBjPT0ic3RyaW5nIilyZXR1cm4gSC5KKGEs
+YyxhLnNFQSkKZWxzZSBpZih0eXBlb2YgYz09Im51bWJlciIpcmV0dXJuIEguVFYoYSxiLGMpCmVsc2Ug
+cmV0dXJuIGN9LApyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWMubGVuZ3RoCmZvcih0PTA7dDxzOysr
+dCljW3RdPUguSyhhLGIsY1t0XSl9LApCOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWMubGVuZ3RoCmZv
+cih0PTE7dDxzO3QrPTIpY1t0XT1ILksoYSxiLGNbdF0pfSwKVFY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMscj1iLnoKaWYocj09PTEwKXtpZihjPT09MClyZXR1cm4gYi5RCnQ9Yi5jaApzPXQubGVuZ3RoCmlm
+KGM8PXMpcmV0dXJuIHRbYy0xXQpjLT1zCmI9Yi5RCnI9Yi56fWVsc2UgaWYoYz09PTApcmV0dXJuIGIK
aWYociE9PTkpdGhyb3cgSC5iKFAuaFYoIkluZGV4ZWQgYmFzZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0
-eXBlIikpCnQ9Yi5RCmlmKGM8PXQubGVuZ3RoKXJldHVybiB0W2MtMV0KdGhyb3cgSC5iKFAuaFYoIkJh
-ZCBpbmRleCAiK2MrIiBmb3IgIitiLlooMCkpKX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQs
-cyxyLHEscCxvLG4sbSxsLGsKaWYoYj09PWQpcmV0dXJuITAKaWYoSC5BOChkKXx8ZD09PXUuSylyZXR1
-cm4hMAp0PWIueQppZih0PT09NClyZXR1cm4hMAppZihILkE4KGIpKXJldHVybiExCmlmKGI9PT11LlAp
-cmV0dXJuITAKcz10PT09MTMKaWYocylpZihILldlKGEsY1tiLnpdLGMsZCxlKSlyZXR1cm4hMApyPWQu
-eQppZih0PT09NilyZXR1cm4gSC5XZShhLGIueixjLGQsZSkKaWYocj09PTYpe3E9ZC56CnJldHVybiBI
-LldlKGEsYixjLHEsZSl9aWYodD09PTgpe2lmKCFILldlKGEsYi56LGMsZCxlKSlyZXR1cm4hMQpyZXR1
-cm4gSC5XZShhLEgueFooYSxiKSxjLGQsZSl9aWYodD09PTcpe3E9SC5XZShhLGIueixjLGQsZSkKcmV0
-dXJuIHF9aWYocj09PTgpe2lmKEguV2UoYSxiLGMsZC56LGUpKXJldHVybiEwCnJldHVybiBILldlKGEs
-YixjLEgueFooYSxkKSxlKX1pZihyPT09Nyl7cT1ILldlKGEsYixjLGQueixlKQpyZXR1cm4gcX1pZihz
-KXJldHVybiExCnE9dCE9PTExCmlmKCghcXx8dD09PTEyKSYmZD09PXUuWilyZXR1cm4hMAppZihyPT09
-MTIpe2lmKGI9PT11LmcpcmV0dXJuITAKaWYodCE9PTEyKXJldHVybiExCnA9Yi5RCm89ZC5RCm49cC5s
-ZW5ndGgKaWYobiE9PW8ubGVuZ3RoKXJldHVybiExCmM9Yz09bnVsbD9wOnAuY29uY2F0KGMpCmU9ZT09
-bnVsbD9vOm8uY29uY2F0KGUpCmZvcihxPXUuYXYsbT0wO208bjsrK20pe2w9cFttXQprPW9bbV0KcS5h
-KGwpCnEuYShrKQppZighSC5XZShhLGwsYyxrLGUpfHwhSC5XZShhLGssZSxsLGMpKXJldHVybiExfXJl
-dHVybiBILmJPKGEsYi56LGMsZC56LGUpfWlmKHI9PT0xMSl7aWYoYj09PXUuZylyZXR1cm4hMAppZihx
-KXJldHVybiExCnJldHVybiBILmJPKGEsYixjLGQsZSl9aWYodD09PTkpe2lmKHIhPT05KXJldHVybiEx
-CnJldHVybiBILnBHKGEsYixjLGQsZSl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMCxhMSxhMixhMyxh
-NCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYQppZighSC5XZShhMCxh
-MS56LGEyLGEzLnosYTQpKXJldHVybiExCnQ9YTEuUQpzPWEzLlEKcj10LmEKcT1zLmEKcD1yLmxlbmd0
-aApvPXEubGVuZ3RoCmlmKHA+bylyZXR1cm4hMQpuPW8tcAptPXQuYgpsPXMuYgprPW0ubGVuZ3RoCmo9
-bC5sZW5ndGgKaWYocCtrPG8railyZXR1cm4hMQpmb3IoaT0wO2k8cDsrK2kpe2g9cltpXQppZighSC5X
-ZShhMCxxW2ldLGE0LGgsYTIpKXJldHVybiExfWZvcihpPTA7aTxuOysraSl7aD1tW2ldCmlmKCFILldl
-KGEwLHFbcCtpXSxhNCxoLGEyKSlyZXR1cm4hMX1mb3IoaT0wO2k8ajsrK2kpe2g9bVtuK2ldCmlmKCFI
-LldlKGEwLGxbaV0sYTQsaCxhMikpcmV0dXJuITF9Zz10LmMKZj1zLmMKZT1nLmxlbmd0aApkPWYubGVu
-Z3RoCmZvcihpPTAsYz0wO2M8ZDtjKz0yKXtiPWZbY10KZG97aWYoaT49ZSlyZXR1cm4hMQphPWdbaV0K
-aSs9Mn13aGlsZShhPGIpCmlmKGI8YSlyZXR1cm4hMQpoPWdbaS0xXQppZighSC5XZShhMCxmW2MrMV0s
-YTQsaCxhMikpcmV0dXJuITF9cmV0dXJuITB9LApwRzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMs
-cixxLHAsbyxuLG0sbD1iLnosaz1kLnoKaWYobD09PWspe3Q9Yi5RCnM9ZC5RCnI9dC5sZW5ndGgKZm9y
-KHE9MDtxPHI7KytxKXtwPXRbcV0Kbz1zW3FdCmlmKCFILldlKGEscCxjLG8sZSkpcmV0dXJuITF9cmV0
-dXJuITB9aWYoZD09PXUuSylyZXR1cm4hMApuPUguUW8oYSxsKQppZihuPT1udWxsKXJldHVybiExCm09
-bltrXQppZihtPT1udWxsKXJldHVybiExCnI9bS5sZW5ndGgKcz1kLlEKZm9yKHE9MDtxPHI7KytxKWlm
-KCFILldlKGEsSC5jRShhLGIsbVtxXSksYyxzW3FdLGUpKXJldHVybiExCnJldHVybiEwfSwKbFI6ZnVu
-Y3Rpb24oYSl7dmFyIHQscz1hLnkKaWYoIShhPT09dS5QKSlpZighSC5BOChhKSlpZihzIT09NylpZigh
-KHM9PT02JiZILmxSKGEueikpKXQ9cz09PTgmJkgubFIoYS56KQplbHNlIHQ9ITAKZWxzZSB0PSEwCmVs
-c2UgdD0hMAplbHNlIHQ9ITAKcmV0dXJuIHR9LApjYzpmdW5jdGlvbihhKXtyZXR1cm4gSC5BOChhKXx8
-YT09PXUuS30sCkE4OmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS55LHI9cwppZihyIT09MilpZihyIT09Mylp
-ZihyIT09NClpZihyIT09NSl7dD11LksKaWYoIShhPT09dCkpcz1zPT09NyYmYS56PT09dAplbHNlIHM9
-ITB9ZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCnJldHVybiBzfSwKSXg6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdCxzLHI9T2JqZWN0LmtleXMoYikscT1yLmxlbmd0aApmb3IodD0wO3Q8cTsr
-K3Qpe3M9clt0XQphW3NdPWJbc119fSwKSmM6ZnVuY3Rpb24gSmMoYSxiKXt2YXIgXz10aGlzCl8uYT1h
-Cl8uYj1iCl8ueD1fLnI9Xy5jPW51bGwKXy55PTAKXy5jeT1fLmN4PV8uY2g9Xy5RPV8uej1udWxsfSwK
-RVQ6ZnVuY3Rpb24gRVQoKXt0aGlzLmM9dGhpcy5iPXRoaXMuYT1udWxsfSwKa1M6ZnVuY3Rpb24ga1Mo
-KXt9LAp4OmZ1bmN0aW9uIHgoYSl7dGhpcy5hPWF9LApSOTpmdW5jdGlvbihhKXtyZXR1cm4gdS5kLmIo
-YSl8fHUuQi5iKGEpfHx1LmR6LmIoYSl8fHUuSS5iKGEpfHx1LkEuYihhKXx8dS5nNC5iKGEpfHx1Lmcy
-LmIoYSl9LApKZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5tYW5nbGVkR2xvYmFsTmFtZXNbYV19fSxKPXsK
-UXU6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJue2k6YSxwOmIsZTpjLHg6ZH19LAprczpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIscSxwPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0KaWYocD09bnVsbClpZigkLks9
-PW51bGwpe0guTSgpCnA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXX1pZihwIT1udWxsKXt0PXAucApp
-ZighMT09PXQpcmV0dXJuIHAuaQppZighMD09PXQpcmV0dXJuIGEKcz1PYmplY3QuZ2V0UHJvdG90eXBl
-T2YoYSkKaWYodD09PXMpcmV0dXJuIHAuaQppZihwLmU9PT1zKXRocm93IEguYihQLm4oIlJldHVybiBp
-bnRlcmNlcHRvciBmb3IgIitILmQodChhLHApKSkpfXI9YS5jb25zdHJ1Y3RvcgpxPXI9PW51bGw/bnVs
-bDpyWyQuQSgpXQppZihxIT1udWxsKXJldHVybiBxCnE9SC5HKGEpCmlmKHEhPW51bGwpcmV0dXJuIHEK
-aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEMuREcKdD1PYmplY3QuZ2V0UHJvdG90eXBlT2Yo
-YSkKaWYodD09bnVsbClyZXR1cm4gQy5aUQppZih0PT09T2JqZWN0LnByb3RvdHlwZSlyZXR1cm4gQy5a
-UQppZih0eXBlb2Ygcj09ImZ1bmN0aW9uIil7T2JqZWN0LmRlZmluZVByb3BlcnR5KHIsJC5BKCkse3Zh
-bHVlOkMudkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkK
-cmV0dXJuIEMudkJ9cmV0dXJuIEMudkJ9LApRaTpmdW5jdGlvbihhLGIpe2lmKGE8MHx8YT40Mjk0OTY3
-Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0OTY3Mjk1LCJsZW5ndGgiLG51bGwpKQpyZXR1cm4gSi5w
-eShuZXcgQXJyYXkoYSksYil9LApweTpmdW5jdGlvbihhLGIpe3JldHVybiBKLkVwKEguVk0oYSxiLkMo
-ImpkPDA+IikpKX0sCkVwOmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CnJldHVybiBhfSwK
-dW46ZnVuY3Rpb24oYSl7YS5maXhlZCRsZW5ndGg9QXJyYXkKYS5pbW11dGFibGUkbGlzdD1BcnJheQpy
-ZXR1cm4gYX0sCkdhOmZ1bmN0aW9uKGEpe2lmKGE8MjU2KXN3aXRjaChhKXtjYXNlIDk6Y2FzZSAxMDpj
-YXNlIDExOmNhc2UgMTI6Y2FzZSAxMzpjYXNlIDMyOmNhc2UgMTMzOmNhc2UgMTYwOnJldHVybiEwCmRl
-ZmF1bHQ6cmV0dXJuITF9c3dpdGNoKGEpe2Nhc2UgNTc2MDpjYXNlIDgxOTI6Y2FzZSA4MTkzOmNhc2Ug
-ODE5NDpjYXNlIDgxOTU6Y2FzZSA4MTk2OmNhc2UgODE5NzpjYXNlIDgxOTg6Y2FzZSA4MTk5OmNhc2Ug
-ODIwMDpjYXNlIDgyMDE6Y2FzZSA4MjAyOmNhc2UgODIzMjpjYXNlIDgyMzM6Y2FzZSA4MjM5OmNhc2Ug
-ODI4NzpjYXNlIDEyMjg4OmNhc2UgNjUyNzk6cmV0dXJuITAKZGVmYXVsdDpyZXR1cm4hMX19LAptbTpm
-dW5jdGlvbihhLGIpe3ZhciB0LHMKZm9yKHQ9YS5sZW5ndGg7Yjx0Oyl7cz1DLnhCLldkKGEsYikKaWYo
-cyE9PTMyJiZzIT09MTMmJiFKLkdhKHMpKWJyZWFrOysrYn1yZXR1cm4gYn0sCmMxOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscwpmb3IoO2I+MDtiPXQpe3Q9Yi0xCnM9Qy54Qi5PMihhLHQpCmlmKHMhPT0zMiYmcyE9
-PTEzJiYhSi5HYShzKSlicmVha31yZXR1cm4gYn0sClJFOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0
-dXJuIGEKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4g
-Si5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJu
-IEoua3MoYSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUku
-cHJvdG90eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09
-bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUK
-aWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5w
-cm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3Mo
-YSl9LApVNjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90
-eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQu
-cHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0
-dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJl
-dHVybiBKLmtzKGEpfSwKaWE6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZihNYXRo
-LmZsb29yKGEpPT1hKXJldHVybiBKLnVyLnByb3RvdHlwZQpyZXR1cm4gSi5WQS5wcm90b3R5cGV9aWYo
-dHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBK
-LllFLnByb3RvdHlwZQppZih0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVybiBKLnlFLnByb3RvdHlwZQpp
-ZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJv
-YmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJu
-IGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlv
-bihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwp
-cmV0dXJuIGEKaWYoIShhIGluc3RhbmNlb2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVy
-biBhfSwKenE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1B
-cnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2Yg
-YT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9m
-IFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApBYzpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShh
-KS5aKGEpfSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuZHUoYSxiLGMsZCl9LApG
+eXBlIikpCnQ9Yi5jaAppZihjPD10Lmxlbmd0aClyZXR1cm4gdFtjLTFdCnRocm93IEguYihQLmhWKCJC
+YWQgaW5kZXggIitjKyIgZm9yICIrYi53KDApKSl9LApXZTpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0
+LHMscixxLHAsbyxuLG0sbCxrCmlmKGI9PT1kKXJldHVybiEwCmlmKEguY2MoZCkpcmV0dXJuITAKdD1i
+LnoKaWYodD09PTQpcmV0dXJuITAKaWYoSC5jYyhiKSlyZXR1cm4hMQppZihiPT09dS5QKXJldHVybiEw
+CnM9dD09PTEzCmlmKHMpaWYoSC5XZShhLGNbYi5RXSxjLGQsZSkpcmV0dXJuITAKcj1kLnoKaWYodD09
+PTYpcmV0dXJuIEguV2UoYSxiLlEsYyxkLGUpCmlmKHI9PT02KXtxPWQuUQpyZXR1cm4gSC5XZShhLGIs
+YyxxLGUpfWlmKHQ9PT04KXtpZighSC5XZShhLGIuUSxjLGQsZSkpcmV0dXJuITEKcmV0dXJuIEguV2Uo
+YSxILnhaKGEsYiksYyxkLGUpfWlmKHQ9PT03KXtxPUguV2UoYSxiLlEsYyxkLGUpCnJldHVybiBxfWlm
+KHI9PT04KXtpZihILldlKGEsYixjLGQuUSxlKSlyZXR1cm4hMApyZXR1cm4gSC5XZShhLGIsYyxILnha
+KGEsZCksZSl9aWYocj09PTcpe3E9SC5XZShhLGIsYyxkLlEsZSkKcmV0dXJuIHF9aWYocylyZXR1cm4h
+MQpxPXQhPT0xMQppZigoIXF8fHQ9PT0xMikmJmQ9PT11LlopcmV0dXJuITAKaWYocj09PTEyKXtpZihi
+PT09dS5nKXJldHVybiEwCmlmKHQhPT0xMilyZXR1cm4hMQpwPWIuY2gKbz1kLmNoCm49cC5sZW5ndGgK
+aWYobiE9PW8ubGVuZ3RoKXJldHVybiExCmZvcihxPXUuYXYsbT0wO208bjsrK20pe2w9cFttXQprPW9b
+bV0KcS5iKGwpCnEuYihrKQppZighSC5XZShhLGwsYyxrLGUpfHwhSC5XZShhLGssZSxsLGMpKXJldHVy
+biExfWM9Yz09bnVsbD9wOnAuY29uY2F0KGMpCmU9ZT09bnVsbD9vOm8uY29uY2F0KGUpCnJldHVybiBI
+LmJPKGEsYi5RLGMsZC5RLGUpfWlmKHI9PT0xMSl7aWYoYj09PXUuZylyZXR1cm4hMAppZihxKXJldHVy
+biExCnJldHVybiBILmJPKGEsYixjLGQsZSl9aWYodD09PTkpe2lmKHIhPT05KXJldHVybiExCnJldHVy
+biBILnBHKGEsYixjLGQsZSl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMCxhMSxhMixhMyxhNCl7dmFy
+IHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYQppZighSC5XZShhMCxhMS5RLGEy
+LGEzLlEsYTQpKXJldHVybiExCnQ9YTEuY2gKcz1hMy5jaApyPXQuYQpxPXMuYQpwPXIubGVuZ3RoCm89
+cS5sZW5ndGgKaWYocD5vKXJldHVybiExCm49by1wCm09dC5iCmw9cy5iCms9bS5sZW5ndGgKaj1sLmxl
+bmd0aAppZihwK2s8bytqKXJldHVybiExCmZvcihpPTA7aTxwOysraSl7aD1yW2ldCmlmKCFILldlKGEw
+LHFbaV0sYTQsaCxhMikpcmV0dXJuITF9Zm9yKGk9MDtpPG47KytpKXtoPW1baV0KaWYoIUguV2UoYTAs
+cVtwK2ldLGE0LGgsYTIpKXJldHVybiExfWZvcihpPTA7aTxqOysraSl7aD1tW24raV0KaWYoIUguV2Uo
+YTAsbFtpXSxhNCxoLGEyKSlyZXR1cm4hMX1nPXQuYwpmPXMuYwplPWcubGVuZ3RoCmQ9Zi5sZW5ndGgK
+Zm9yKGk9MCxjPTA7YzxkO2MrPTIpe2I9ZltjXQpkb3tpZihpPj1lKXJldHVybiExCmE9Z1tpXQppKz0y
+fXdoaWxlKGE8YikKaWYoYjxhKXJldHVybiExCmg9Z1tpLTFdCmlmKCFILldlKGEwLGZbYysxXSxhNCxo
+LGEyKSlyZXR1cm4hMX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEs
+cCxvLG4sbSxsPWIuUSxrPWQuUQppZihsPT09ayl7dD1iLmNoCnM9ZC5jaApyPXQubGVuZ3RoCmZvcihx
+PTA7cTxyOysrcSl7cD10W3FdCm89c1txXQppZighSC5XZShhLHAsYyxvLGUpKXJldHVybiExfXJldHVy
+biEwfW49SC5RbyhhLGwpCmlmKG49PW51bGwpcmV0dXJuITEKbT1uW2tdCmlmKG09PW51bGwpcmV0dXJu
+ITEKcj1tLmxlbmd0aApzPWQuY2gKZm9yKHE9MDtxPHI7KytxKWlmKCFILldlKGEsSC5jRShhLGIsbVtx
+XSksYyxzW3FdLGUpKXJldHVybiExCnJldHVybiEwfSwKY2M6ZnVuY3Rpb24oYSl7dmFyIHQscwppZihh
+PT09dS5LKXJldHVybiEwCnQ9YS56CmlmKHQhPT0yKWlmKHQhPT0zKWlmKHQhPT00KWlmKHQhPT01KXM9
+dD09PTgmJkguY2MoYS5RKQplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAKcmV0
+dXJuIHN9LApJeDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1PYmplY3Qua2V5cyhiKSxxPXIubGVuZ3Ro
+CmZvcih0PTA7dDxxOysrdCl7cz1yW3RdCmFbc109YltzXX19LApKYzpmdW5jdGlvbiBKYyhhLGIsYyl7
+dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLnk9Xy54PV8uZD1udWxsCl8uej0wCl8uZGI9Xy5j
+eT1fLmN4PV8uY2g9Xy5RPW51bGx9LApHOmZ1bmN0aW9uIEcoKXt0aGlzLmM9dGhpcy5iPXRoaXMuYT1u
+dWxsfSwKdTk6ZnVuY3Rpb24gdTkoKXt9LApoejpmdW5jdGlvbiBoeihhKXt0aGlzLmE9YX0sCmlNOmZ1
+bmN0aW9uIGlNKGEpe3RoaXMuYT1hfSwKUjk6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuZC5jKGEpfHx1LkIu
+YyhhKXx8dS5kei5jKGEpfHx1LkkuYyhhKXx8dS5BLmMoYSl8fHUuZzQuYyhhKXx8dS5nMi5jKGEpfSwK
+Smc6ZnVuY3Rpb24oYSl7cmV0dXJuIHYubWFuZ2xlZEdsb2JhbE5hbWVzW2FdfX0sSj17ClF1OmZ1bmN0
+aW9uKGEsYixjLGQpe3JldHVybntpOmEscDpiLGU6Yyx4OmR9fSwKa3M6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyLHEscD1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdCmlmKHA9PW51bGwpaWYoJC5Cdj09bnVsbCl7
+SC5YRCgpCnA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXX1pZihwIT1udWxsKXt0PXAucAppZighMT09
+PXQpcmV0dXJuIHAuaQppZighMD09PXQpcmV0dXJuIGEKcz1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkK
+aWYodD09PXMpcmV0dXJuIHAuaQppZihwLmU9PT1zKXRocm93IEguYihQLlNZKCJSZXR1cm4gaW50ZXJj
+ZXB0b3IgZm9yICIrSC5kKHQoYSxwKSkpKX1yPWEuY29uc3RydWN0b3IKcT1yPT1udWxsP251bGw6clsk
+LlVOKCldCmlmKHEhPW51bGwpcmV0dXJuIHEKcT1ILnczKGEpCmlmKHEhPW51bGwpcmV0dXJuIHEKaWYo
+dHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEMuREcKdD1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkK
+aWYodD09bnVsbClyZXR1cm4gQy5aUQppZih0PT09T2JqZWN0LnByb3RvdHlwZSlyZXR1cm4gQy5aUQpp
+Zih0eXBlb2Ygcj09ImZ1bmN0aW9uIil7T2JqZWN0LmRlZmluZVByb3BlcnR5KHIsJC5VTigpLHt2YWx1
+ZTpDLnZCLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJl
+dHVybiBDLnZCfXJldHVybiBDLnZCfSwKUWk6ZnVuY3Rpb24oYSxiKXtpZihhPDB8fGE+NDI5NDk2NzI5
+NSl0aHJvdyBILmIoUC5URShhLDAsNDI5NDk2NzI5NSwibGVuZ3RoIixudWxsKSkKcmV0dXJuIEoucHko
+bmV3IEFycmF5KGEpLGIpfSwKcHk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5FcChILlZNKGEsYi5DKCJq
+ZDwwPiIpKSl9LApFcDpmdW5jdGlvbihhKXthLmZpeGVkJGxlbmd0aD1BcnJheQpyZXR1cm4gYX0sCnpD
+OmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CmEuaW1tdXRhYmxlJGxpc3Q9QXJyYXkKcmV0
+dXJuIGF9LApHYTpmdW5jdGlvbihhKXtpZihhPDI1Nilzd2l0Y2goYSl7Y2FzZSA5OmNhc2UgMTA6Y2Fz
+ZSAxMTpjYXNlIDEyOmNhc2UgMTM6Y2FzZSAzMjpjYXNlIDEzMzpjYXNlIDE2MDpyZXR1cm4hMApkZWZh
+dWx0OnJldHVybiExfXN3aXRjaChhKXtjYXNlIDU3NjA6Y2FzZSA4MTkyOmNhc2UgODE5MzpjYXNlIDgx
+OTQ6Y2FzZSA4MTk1OmNhc2UgODE5NjpjYXNlIDgxOTc6Y2FzZSA4MTk4OmNhc2UgODE5OTpjYXNlIDgy
+MDA6Y2FzZSA4MjAxOmNhc2UgODIwMjpjYXNlIDgyMzI6Y2FzZSA4MjMzOmNhc2UgODIzOTpjYXNlIDgy
+ODc6Y2FzZSAxMjI4ODpjYXNlIDY1Mjc5OnJldHVybiEwCmRlZmF1bHQ6cmV0dXJuITF9fSwKbW06ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzCmZvcih0PWEubGVuZ3RoO2I8dDspe3M9Qy54Qi5XZChhLGIpCmlmKHMh
+PT0zMiYmcyE9PTEzJiYhSi5HYShzKSlicmVhazsrK2J9cmV0dXJuIGJ9LApjMTpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMKZm9yKDtiPjA7Yj10KXt0PWItMQpzPUMueEIuTzIoYSx0KQppZihzIT09MzImJnMhPT0x
+MyYmIUouR2EocykpYnJlYWt9cmV0dXJuIGJ9LApSRTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVy
+biBhCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEou
+YzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIGEKcmV0dXJuIEou
+a3MoYSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUkucHJv
+dG90eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVs
+bClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYo
+dHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90
+b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0s
+ClU2OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUK
+aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90
+b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4g
+Si5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gYQpyZXR1cm4g
+Si5rcyhhKX0sCmlhOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoTWF0aC5mbG9v
+cihhKT09YSlyZXR1cm4gSi51ci5wcm90b3R5cGUKcmV0dXJuIEouVkEucHJvdG90eXBlfWlmKHR5cGVv
+ZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gSi5ZRS5w
+cm90b3R5cGUKaWYodHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gSi55RS5wcm90b3R5cGUKaWYoYS5j
+b25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0
+Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlm
+KGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlvbihhKXtp
+Zih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJu
+IGEKaWYoIShhIGluc3RhbmNlb2YgUC5rKSlyZXR1cm4gSi5rZC5wcm90b3R5cGUKcmV0dXJuIGF9LAp6
+cTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJl
+dHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVu
+Y3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5rKXJl
+dHVybiBhCnJldHVybiBKLmtzKGEpfSwKQjI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnpxKGEpLlko
+YSxiLGMpfSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuZHUoYSxiLGMsZCl9LApG
TDpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLmRkKGEsYil9LApHQTpmdW5jdGlvbihhLGIpe3Jl
dHVybiBKLnpxKGEpLlcoYSxiKX0sCkdyOmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLmdtVyhhKX0s
-Ckg6ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYoYSkuZ2soYSl9LApJOmZ1bmN0aW9uKGEpe3JldHVybiBK
-LmlhKGEpLmdpKGEpfSwKSVQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouenEoYSkuZ3coYSl9LApKeTpmdW5j
-dGlvbihhLGIpe3JldHVybiBKLmlhKGEpLmU3KGEsYil9LApLVjpmdW5jdGlvbihhLGIpe3JldHVybiBK
-LnJZKGEpLnluKGEsYil9LApMdDpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS53ZyhhKX0sCk0xOmZ1
-bmN0aW9uKGEsYixjKXtyZXR1cm4gSi56cShhKS5FMihhLGIsYyl9LApRTTpmdW5jdGlvbihhKXtyZXR1
-cm4gSi5SRShhKS5nUHUoYSl9LApRejpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLldkKGEsYil9
-LApSTTpmdW5jdGlvbihhLGIpe2lmKGE9PW51bGwpcmV0dXJuIGI9PW51bGwKaWYodHlwZW9mIGEhPSJv
-YmplY3QiKXJldHVybiBiIT1udWxsJiZhPT09YgpyZXR1cm4gSi5pYShhKS5ETihhLGIpfSwKVDA6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIEouclkoYSkuYlMoYSl9LAphNjpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZ
-KGEpLk8yKGEsYil9LApiVDpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5ENChhKX0sCmNIOmZ1bmN0
-aW9uKGEpe3JldHVybiBKLnJZKGEpLmhjKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSku
-Z0REKGEpfSwKZFo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuT24oYSxiLGMsZCl9LApk
-ZzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5yWShhKS5pNyhhLGIsYyxkKX0sCmRoOmZ1bmN0aW9u
-KGEpe3JldHVybiBKLlJFKGEpLnRuKGEpfSwKaEU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi56cShhKS5V
-KGEsYil9LAppZzpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nUWcoYSl9LApsNTpmdW5jdGlvbihh
-LGIpe3JldHVybiBKLlJFKGEpLnNoZihhLGIpfSwKbGQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZ
-KGEpLk5qKGEsYixjKX0sCm06ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYT09Im51bWJlciImJnR5cGVv
-ZiBiPT0ibnVtYmVyIilyZXR1cm4gYStiCnJldHVybiBKLlRKKGEpLmgoYSxiKX0sCnA0OmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIEouclkoYSkuVGMoYSxiKX0sCnEwOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5y
-WShhKS5RaShhLGIsYyl9LApxRjpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nVmwoYSl9LAp0SDpm
-dW5jdGlvbihhLGIsYyl7cmV0dXJuIEouUkUoYSkucGsoYSxiLGMpfSwKdTk6ZnVuY3Rpb24oYSxiLGMp
-e3JldHVybiBKLnpxKGEpLnQoYSxiLGMpfSwKeDk6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYj09PSJu
-dW1iZXIiKWlmKGEuY29uc3RydWN0b3I9PUFycmF5fHx0eXBlb2YgYT09InN0cmluZyJ8fEguWHQoYSxh
-W3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdKSlpZihiPj4+MD09PWImJmI8YS5sZW5ndGgpcmV0dXJuIGFb
-Yl0KcmV0dXJuIEouVTYoYSkucShhLGIpfSwKemw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5VNihhKS50
-ZyhhLGIpfSwKdkI6ZnVuY3Rpb24gdkIoKXt9LAp5RTpmdW5jdGlvbiB5RSgpe30sCllFOmZ1bmN0aW9u
-IFlFKCl7fSwKTUY6ZnVuY3Rpb24gTUYoKXt9LAppQzpmdW5jdGlvbiBpQygpe30sCmtkOmZ1bmN0aW9u
-IGtkKCl7fSwKYzU6ZnVuY3Rpb24gYzUoKXt9LApqZDpmdW5jdGlvbiBqZChhKXt0aGlzLiR0aT1hfSwK
-UG86ZnVuY3Rpb24gUG8oYSl7dGhpcy4kdGk9YX0sCm0xOmZ1bmN0aW9uIG0xKGEsYixjKXt2YXIgXz10
-aGlzCl8uYT1hCl8uYj1iCl8uYz0wCl8uZD1udWxsCl8uJHRpPWN9LApxSTpmdW5jdGlvbiBxSSgpe30s
-CnVyOmZ1bmN0aW9uIHVyKCl7fSwKVkE6ZnVuY3Rpb24gVkEoKXt9LApEcjpmdW5jdGlvbiBEcigpe319
-LFA9ewpPajpmdW5jdGlvbigpe3ZhciB0LHMscj17fQppZihzZWxmLnNjaGVkdWxlSW1tZWRpYXRlIT1u
-dWxsKXJldHVybiBQLkVYKCkKaWYoc2VsZi5NdXRhdGlvbk9ic2VydmVyIT1udWxsJiZzZWxmLmRvY3Vt
-ZW50IT1udWxsKXt0PXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2IikKcz1zZWxmLmRvY3Vt
-ZW50LmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpyLmE9bnVsbApuZXcgc2VsZi5NdXRhdGlvbk9ic2VydmVy
-KEgudFIobmV3IFAudGgociksMSkpLm9ic2VydmUodCx7Y2hpbGRMaXN0OnRydWV9KQpyZXR1cm4gbmV3
-IFAuaGEocix0LHMpfWVsc2UgaWYoc2VsZi5zZXRJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAueXQoKQpy
-ZXR1cm4gUC5xVygpfSwKWlY6ZnVuY3Rpb24oYSl7c2VsZi5zY2hlZHVsZUltbWVkaWF0ZShILnRSKG5l
-dyBQLlZzKHUuTS5hKGEpKSwwKSl9LApxRzpmdW5jdGlvbihhKXtzZWxmLnNldEltbWVkaWF0ZShILnRS
-KG5ldyBQLkZ0KHUuTS5hKGEpKSwwKSl9LApCejpmdW5jdGlvbihhKXt1Lk0uYShhKQpQLlFOKDAsYSl9
-LApRTjpmdW5jdGlvbihhLGIpe3ZhciB0PW5ldyBQLlczKCkKdC5DWShhLGIpCnJldHVybiB0fSwKRlg6
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmloKG5ldyBQLnZzKCQuWDMsYS5DKCJ2czwwPiIpKSxhLkMo
-ImloPDA+IikpfSwKREk6ZnVuY3Rpb24oYSxiKXthLiQyKDAsbnVsbCkKYi5iPSEwCnJldHVybiBiLmF9
-LApqUTpmdW5jdGlvbihhLGIpe1AuSmUoYSxiKX0sCnlDOmZ1bmN0aW9uKGEsYil7Yi5hTSgwLGEpfSwK
-ZjM6ZnVuY3Rpb24oYSxiKXtiLncwKEguUnUoYSksSC50cyhhKSl9LApKZTpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMscj1uZXcgUC5XTShiKSxxPW5ldyBQLlNYKGIpCmlmKGEgaW5zdGFuY2VvZiBQLnZzKWEuUWQo
-cixxLHUueikKZWxzZXt0PXUuegppZih1LmMuYihhKSlhLlNxKHIscSx0KQplbHNle3M9bmV3IFAudnMo
-JC5YMyx1Ll8pCnMuYT00CnMuYz1hCnMuUWQocixxLHQpfX19LApsejpmdW5jdGlvbihhKXt2YXIgdD1m
-dW5jdGlvbihiLGMpe3JldHVybiBmdW5jdGlvbihkLGUpe3doaWxlKHRydWUpdHJ5e2IoZCxlKQpicmVh
-a31jYXRjaChzKXtlPXMKZD1jfX19KGEsMSkKcmV0dXJuICQuWDMuTGoobmV3IFAuR3ModCksdS5QLHUu
-Uyx1LnopfSwKR1E6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkZ5KGEsMSl9LApUaDpmdW5jdGlvbigp
-e3JldHVybiBDLndRfSwKWW06ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkZ5KGEsMyl9LApsMDpmdW5j
-dGlvbihhLGIpe3JldHVybiBuZXcgUC5xNChhLGIuQygicTQ8MD4iKSl9LAprMzpmdW5jdGlvbihhLGIp
-e3ZhciB0LHMscgpiLmE9MQp0cnl7YS5TcShuZXcgUC5wVihiKSxuZXcgUC5VNyhiKSx1LlApfWNhdGNo
-KHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5yYihuZXcgUC52cihiLHQscykpfX0sCkE5OmZ1bmN0aW9u
-KGEsYil7dmFyIHQscyxyCmZvcih0PXUuXztzPWEuYSxzPT09MjspYT10LmEoYS5jKQppZihzPj00KXty
-PWIuYWgoKQpiLmE9YS5hCmIuYz1hLmMKUC5IWihiLHIpfWVsc2V7cj11LnguYShiLmMpCmIuYT0yCmIu
-Yz1hCmEualEocil9fSwKSFo6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGks
-aCxnLGYsZT1udWxsLGQ9e30sYz1kLmE9YQpmb3IodD11Lm4scz11Lngscj11LmM7ITA7KXtxPXt9CnA9
-Yy5hPT09OAppZihiPT1udWxsKXtpZihwKXtvPXQuYShjLmMpClAuTDIoZSxlLGMuYixvLmEsby5iKX1y
-ZXR1cm59Zm9yKDtuPWIuYSxuIT1udWxsO2I9bil7Yi5hPW51bGwKUC5IWihkLmEsYil9Yz1kLmEKbT1j
-LmMKcS5hPXAKcS5iPW0KbD0hcAppZihsKXtrPWIuYwprPShrJjEpIT09MHx8KGsmMTUpPT09OH1lbHNl
-IGs9ITAKaWYoayl7az1iLmIKaj1rLmIKaWYocCl7aT1jLmI9PT1qCmk9IShpfHxpKX1lbHNlIGk9ITEK
-aWYoaSl7dC5hKG0pClAuTDIoZSxlLGMuYixtLmEsbS5iKQpyZXR1cm59aD0kLlgzCmlmKGghPT1qKSQu
-WDM9agplbHNlIGg9ZQpjPWIuYwppZigoYyYxNSk9PT04KW5ldyBQLlJUKGQscSxiLHApLiQwKCkKZWxz
-ZSBpZihsKXtpZigoYyYxKSE9PTApbmV3IFAucnEocSxiLG0pLiQwKCl9ZWxzZSBpZigoYyYyKSE9PTAp
-bmV3IFAuUlcoZCxxLGIpLiQwKCkKaWYoaCE9bnVsbCkkLlgzPWgKYz1xLmIKaWYoci5iKGMpKXtpZihj
-LmE+PTQpe2c9cy5hKGsuYykKay5jPW51bGwKYj1rLk44KGcpCmsuYT1jLmEKay5jPWMuYwpkLmE9Ywpj
-b250aW51ZX1lbHNlIFAuQTkoYyxrKQpyZXR1cm59fWY9Yi5iCmc9cy5hKGYuYykKZi5jPW51bGwKYj1m
-Lk44KGcpCmM9cS5hCmw9cS5iCmlmKCFjKXtmLiR0aS5jLmEobCkKZi5hPTQKZi5jPWx9ZWxzZXt0LmEo
-bCkKZi5hPTgKZi5jPWx9ZC5hPWYKYz1mfX0sClZIOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYodS5hZy5i
-KGEpKXJldHVybiBiLkxqKGEsdS56LHUuSyx1LmwpCnQ9dS5iSQppZih0LmIoYSkpcmV0dXJuIHQuYShh
-KQp0aHJvdyBILmIoUC5MMyhhLCJvbkVycm9yIiwiRXJyb3IgaGFuZGxlciBtdXN0IGFjY2VwdCBvbmUg
-T2JqZWN0IG9yIG9uZSBPYmplY3QgYW5kIGEgU3RhY2tUcmFjZSBhcyBhcmd1bWVudHMsIGFuZCByZXR1
-cm4gYSBhIHZhbGlkIHJlc3VsdCIpKX0sCnB1OmZ1bmN0aW9uKCl7dmFyIHQscwpmb3IoO3Q9JC5TNix0
-IT1udWxsOyl7JC5tZz1udWxsCnM9dC5iCiQuUzY9cwppZihzPT1udWxsKSQuazg9bnVsbAp0LmEuJDAo
-KX19LAplTjpmdW5jdGlvbigpeyQuVUQ9ITAKdHJ5e1AucHUoKX1maW5hbGx5eyQubWc9bnVsbAokLlVE
-PSExCmlmKCQuUzYhPW51bGwpJC51dCgpLiQxKFAuVjkoKSl9fSwKZVc6ZnVuY3Rpb24oYSl7dmFyIHQ9
-bmV3IFAuT00oYSkKaWYoJC5TNj09bnVsbCl7JC5TNj0kLms4PXQKaWYoISQuVUQpJC51dCgpLiQxKFAu
-VjkoKSl9ZWxzZSAkLms4PSQuazguYj10fSwKclI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPSQuUzYKaWYo
-cj09bnVsbCl7UC5lVyhhKQokLm1nPSQuazgKcmV0dXJufXQ9bmV3IFAuT00oYSkKcz0kLm1nCmlmKHM9
-PW51bGwpe3QuYj1yCiQuUzY9JC5tZz10fWVsc2V7dC5iPXMuYgokLm1nPXMuYj10CmlmKHQuYj09bnVs
-bCkkLms4PXR9fSwKcmI6ZnVuY3Rpb24oYSl7dmFyIHQ9bnVsbCxzPSQuWDMKaWYoQy5OVT09PXMpe1Au
-VGsodCx0LEMuTlUsYSkKcmV0dXJufVAuVGsodCx0LHMsdS5NLmEocy5HWShhKSkpfSwKUXc6ZnVuY3Rp
-b24oYSxiKXtpZihhPT1udWxsKUguVmooUC5oRygic3RyZWFtIikpCnJldHVybiBuZXcgUC54SShiLkMo
-InhJPDA+IikpfSwKVGw6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iPT1udWxsP1AudjAoYSk6YgpQLlVJKGEs
-ImVycm9yIix1LkspCnJldHVybiBuZXcgUC5PSChhLHQpfSwKdjA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYo
-dS5tLmIoYSkpe3Q9YS5nSUkoKQppZih0IT1udWxsKXJldHVybiB0fXJldHVybiBDLnBkfSwKTDI6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD17fQp0LmE9ZAp0LmI9ZQppZihkPT1udWxsKXt0LmE9bmV3IFAu
-QVQoITEsbnVsbCwiZXJyb3IiLCJNdXN0IG5vdCBiZSBudWxsIikKdC5iPVAuWmIoKX1QLnJSKG5ldyBQ
-LnBLKHQpKX0sClQ4OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVy
+CkhtOmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2KGEpLmdoKGEpfSwKSVQ6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouenEoYSkuZ2t6KGEpfSwKSnk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5pYShhKS5lNyhhLGIpfSwK
+S1Y6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS55bihhLGIpfSwKTHQ6ZnVuY3Rpb24oYSl7cmV0
+dXJuIEouUkUoYSkud2coYSl9LApNMTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouenEoYSkuRTIoYSxi
+LGMpfSwKUU06ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuZ1B1KGEpfSwKUXo6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gSi5yWShhKS5XZChhLGIpfSwKUk06ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVy
+biBiPT1udWxsCmlmKHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYiE9bnVsbCYmYT09PWIKcmV0dXJu
+IEouaWEoYSkuRE4oYSxiKX0sClQwOmZ1bmN0aW9uKGEpe3JldHVybiBKLnJZKGEpLmJTKGEpfSwKYTY6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5PMihhLGIpfSwKYlQ6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouUkUoYSkuRDQoYSl9LApiYjpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmdHlw
+ZW9mIGI9PSJudW1iZXIiKXJldHVybiBhK2IKcmV0dXJuIEouVEooYSkuVChhLGIpfSwKY0g6ZnVuY3Rp
+b24oYSl7cmV0dXJuIEouclkoYSkuaGMoYSl9LApkUjpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5n
+REQoYSl9LApkWjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5SRShhKS5PbihhLGIsYyxkKX0sCmRn
+OmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLnJZKGEpLmk3KGEsYixjLGQpfSwKZGg6ZnVuY3Rpb24o
+YSl7cmV0dXJuIEouUkUoYSkudG4oYSl9LApoRTpmdW5jdGlvbihhLGIpe3JldHVybiBKLnpxKGEpLlUo
+YSxiKX0sCmhmOmZ1bmN0aW9uKGEpe3JldHVybiBKLmlhKGEpLmdpKGEpfSwKaHc6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gSi5yWShhKS5UYyhhLGIpfSwKaWc6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuZ1Fn
+KGEpfSwKajpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS53KGEpfSwKbDU6ZnVuY3Rpb24oYSxiKXty
+ZXR1cm4gSi5SRShhKS5zaGYoYSxiKX0sCmxkOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5yWShhKS5O
+aihhLGIsYyl9LApxMDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouclkoYSkuUWkoYSxiLGMpfSwKcUY6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuZ1ZsKGEpfSwKdEg6ZnVuY3Rpb24oYSxiLGMpe3JldHVy
+biBKLlJFKGEpLnBrKGEsYixjKX0sCncyOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGI9PT0ibnVtYmVy
+IilpZihhLmNvbnN0cnVjdG9yPT1BcnJheXx8dHlwZW9mIGE9PSJzdHJpbmcifHxILlh0KGEsYVt2LmRp
+c3BhdGNoUHJvcGVydHlOYW1lXSkpaWYoYj4+PjA9PT1iJiZiPGEubGVuZ3RoKXJldHVybiBhW2JdCnJl
+dHVybiBKLlU2KGEpLnEoYSxiKX0sCnpsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouVTYoYSkudGcoYSxi
+KX0sCnZCOmZ1bmN0aW9uIHZCKCl7fSwKeUU6ZnVuY3Rpb24geUUoKXt9LApZRTpmdW5jdGlvbiBZRSgp
+e30sCk1GOmZ1bmN0aW9uIE1GKCl7fSwKaUM6ZnVuY3Rpb24gaUMoKXt9LAprZDpmdW5jdGlvbiBrZCgp
+e30sCmM1OmZ1bmN0aW9uIGM1KCl7fSwKamQ6ZnVuY3Rpb24gamQoYSl7dGhpcy4kdGk9YX0sClBvOmZ1
+bmN0aW9uIFBvKGEpe3RoaXMuJHRpPWF9LAptMTpmdW5jdGlvbiBtMShhLGIsYyl7dmFyIF89dGhpcwpf
+LmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApfLiR0aT1jfSwKcUk6ZnVuY3Rpb24gcUkoKXt9LAp1cjpm
+dW5jdGlvbiB1cigpe30sClZBOmZ1bmN0aW9uIFZBKCl7fSwKRHI6ZnVuY3Rpb24gRHIoKXt9fSxQPXsK
+T2o6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9e30KaWYoc2VsZi5zY2hlZHVsZUltbWVkaWF0ZSE9bnVsbCly
+ZXR1cm4gUC5FWCgpCmlmKHNlbGYuTXV0YXRpb25PYnNlcnZlciE9bnVsbCYmc2VsZi5kb2N1bWVudCE9
+bnVsbCl7dD1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpCnM9c2VsZi5kb2N1bWVudC5j
+cmVhdGVFbGVtZW50KCJzcGFuIikKci5hPW51bGwKbmV3IHNlbGYuTXV0YXRpb25PYnNlcnZlcihILnRS
+KG5ldyBQLnRoKHIpLDEpKS5vYnNlcnZlKHQse2NoaWxkTGlzdDp0cnVlfSkKcmV0dXJuIG5ldyBQLmhh
+KHIsdCxzKX1lbHNlIGlmKHNlbGYuc2V0SW1tZWRpYXRlIT1udWxsKXJldHVybiBQLnl0KCkKcmV0dXJu
+IFAucVcoKX0sClpWOmZ1bmN0aW9uKGEpe3NlbGYuc2NoZWR1bGVJbW1lZGlhdGUoSC50UihuZXcgUC5W
+cyh1Lk0uYihhKSksMCkpfSwKcUc6ZnVuY3Rpb24oYSl7c2VsZi5zZXRJbW1lZGlhdGUoSC50UihuZXcg
+UC5GdCh1Lk0uYihhKSksMCkpfSwKQno6ZnVuY3Rpb24oYSl7dS5NLmIoYSkKUC5RTigwLGEpfSwKUU46
+ZnVuY3Rpb24oYSxiKXt2YXIgdD1uZXcgUC5XMygpCnQuQ1koYSxiKQpyZXR1cm4gdH0sCkZYOmZ1bmN0
+aW9uKGEpe3JldHVybiBuZXcgUC5paChuZXcgUC52cygkLlgzLGEuQygidnM8MD4iKSksYS5DKCJpaDww
+PiIpKX0sCkRJOmZ1bmN0aW9uKGEsYil7YS4kMigwLG51bGwpCmIuYj0hMApyZXR1cm4gYi5hfSwKalE6
+ZnVuY3Rpb24oYSxiKXtQLkplKGEsYil9LAp5QzpmdW5jdGlvbihhLGIpe2IuYU0oMCxhKX0sCmYzOmZ1
+bmN0aW9uKGEsYil7Yi53MChILlJ1KGEpLEgudHMoYSkpfSwKSmU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+LHI9bmV3IFAuV00oYikscT1uZXcgUC5TWChiKQppZihhIGluc3RhbmNlb2YgUC52cylhLlFkKHIscSx1
+LnopCmVsc2V7dD11LnoKaWYodS5jLmMoYSkpYS5TcShyLHEsdCkKZWxzZXtzPW5ldyBQLnZzKCQuWDMs
+dS5fKQpzLmE9NApzLmM9YQpzLlFkKHIsbnVsbCx0KX19fSwKbHo6ZnVuY3Rpb24oYSl7dmFyIHQ9ZnVu
+Y3Rpb24oYixjKXtyZXR1cm4gZnVuY3Rpb24oZCxlKXt3aGlsZSh0cnVlKXRyeXtiKGQsZSkKYnJlYWt9
+Y2F0Y2gocyl7ZT1zCmQ9Y319fShhLDEpCnJldHVybiAkLlgzLkxqKG5ldyBQLkdzKHQpLHUuUCx1LmVn
+LHUueil9LApHUTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuRnkoYSwxKX0sClRoOmZ1bmN0aW9uKCl7
+cmV0dXJuIEMud1F9LApZbTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuRnkoYSwzKX0sCmwwOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIG5ldyBQLnE0KGEsYi5DKCJxNDwwPiIpKX0sCmszOmZ1bmN0aW9uKGEsYil7
+dmFyIHQscyxyCmIuYT0xCnRyeXthLlNxKG5ldyBQLnBWKGIpLG5ldyBQLlU3KGIpLHUuUCl9Y2F0Y2go
+cil7dD1ILlJ1KHIpCnM9SC50cyhyKQpQLnJiKG5ldyBQLnZyKGIsdCxzKSl9fSwKQTk6ZnVuY3Rpb24o
+YSxiKXt2YXIgdCxzLHIKZm9yKHQ9dS5fO3M9YS5hLHM9PT0yOylhPXQuYihhLmMpCmlmKHM+PTQpe3I9
+Yi5haCgpCmIuYT1hLmEKYi5jPWEuYwpQLkhaKGIscil9ZWxzZXtyPXUueC5iKGIuYykKYi5hPTIKYi5j
+PWEKYS5qUShyKX19LApIWjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxo
+LGcsZixlPW51bGwsZD17fSxjPWQuYT1hCmZvcih0PXUubixzPXUueCxyPXUuYzshMDspe3E9e30KcD1j
+LmE9PT04CmlmKGI9PW51bGwpe2lmKHApe289dC5iKGMuYykKUC5MMihlLGUsYy5iLG8uYSxvLmIpfXJl
+dHVybn1mb3IoO249Yi5hLG4hPW51bGw7Yj1uKXtiLmE9bnVsbApQLkhaKGQuYSxiKX1jPWQuYQptPWMu
+YwpxLmE9cApxLmI9bQpsPSFwCmlmKGwpe2s9Yi5jCms9KGsmMSkhPT0wfHwoayYxNSk9PT04fWVsc2Ug
+az0hMAppZihrKXtrPWIuYgpqPWsuYgppZihwKXtpPWMuYj09PWoKaT0hKGl8fGkpfWVsc2UgaT0hMQpp
+ZihpKXt0LmIobSkKUC5MMihlLGUsYy5iLG0uYSxtLmIpCnJldHVybn1oPSQuWDMKaWYoaCE9PWopJC5Y
+Mz1qCmVsc2UgaD1lCmM9Yi5jCmlmKChjJjE1KT09PTgpbmV3IFAuUlQoZCxxLGIscCkuJDAoKQplbHNl
+IGlmKGwpe2lmKChjJjEpIT09MCluZXcgUC5ycShxLGIsbSkuJDAoKX1lbHNlIGlmKChjJjIpIT09MClu
+ZXcgUC5SVyhkLHEsYikuJDAoKQppZihoIT1udWxsKSQuWDM9aApjPXEuYgppZihyLmMoYykpe2lmKGMu
+YT49NCl7Zz1zLmIoay5jKQprLmM9bnVsbApiPWsuTjgoZykKay5hPWMuYQprLmM9Yy5jCmQuYT1jCmNv
+bnRpbnVlfWVsc2UgUC5BOShjLGspCnJldHVybn19Zj1iLmIKZz1zLmIoZi5jKQpmLmM9bnVsbApiPWYu
+TjgoZykKYz1xLmEKbD1xLmIKaWYoIWMpe2YuJHRpLmQuYihsKQpmLmE9NApmLmM9bH1lbHNle3QuYihs
+KQpmLmE9OApmLmM9bH1kLmE9ZgpjPWZ9fSwKVkg6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZih1LmFnLmMo
+YSkpcmV0dXJuIGIuTGooYSx1LnosdS5LLHUubCkKdD11LnkKaWYodC5jKGEpKXJldHVybiB0LmIoYSkK
+dGhyb3cgSC5iKFAuTDMoYSwib25FcnJvciIsIkVycm9yIGhhbmRsZXIgbXVzdCBhY2NlcHQgb25lIE9i
+amVjdCBvciBvbmUgT2JqZWN0IGFuZCBhIFN0YWNrVHJhY2UgYXMgYXJndW1lbnRzLCBhbmQgcmV0dXJu
+IGEgYSB2YWxpZCByZXN1bHQiKSl9LApwdTpmdW5jdGlvbigpe3ZhciB0LHMKZm9yKDt0PSQuUzYsdCE9
+bnVsbDspeyQubWc9bnVsbApzPXQuYgokLlM2PXMKaWYocz09bnVsbCkkLms4PW51bGwKdC5hLiQwKCl9
+fSwKZU46ZnVuY3Rpb24oKXskLlVEPSEwCnRyeXtQLnB1KCl9ZmluYWxseXskLm1nPW51bGwKJC5VRD0h
+MQppZigkLlM2IT1udWxsKSQudXQoKS4kMShQLlVJKCkpfX0sCmVXOmZ1bmN0aW9uKGEpe3ZhciB0PW5l
+dyBQLk9NKGEpCmlmKCQuUzY9PW51bGwpeyQuUzY9JC5rOD10CmlmKCEkLlVEKSQudXQoKS4kMShQLlVJ
+KCkpfWVsc2UgJC5rOD0kLms4LmI9dH0sCnJSOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0kLlM2CmlmKHI9
+PW51bGwpe1AuZVcoYSkKJC5tZz0kLms4CnJldHVybn10PW5ldyBQLk9NKGEpCnM9JC5tZwppZihzPT1u
+dWxsKXt0LmI9cgokLlM2PSQubWc9dH1lbHNle3QuYj1zLmIKJC5tZz1zLmI9dAppZih0LmI9PW51bGwp
+JC5rOD10fX0sCnJiOmZ1bmN0aW9uKGEpe3ZhciB0PW51bGwscz0kLlgzCmlmKEMuTlU9PT1zKXtQLlRr
+KHQsdCxDLk5VLGEpCnJldHVybn1QLlRrKHQsdCxzLHUuTS5iKHMuR1koYSkpKX0sClF3OmZ1bmN0aW9u
+KGEsYil7aWYoYT09bnVsbClILlZqKFAuRWUoInN0cmVhbSIpKQpyZXR1cm4gbmV3IFAueEkoYi5DKCJ4
+STwwPiIpKX0sCkwyOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQ9e30KdC5hPWQKUC5yUihuZXcgUC5w
+Syh0LGUpKX0sClQ4OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVy
biBkLiQwKCkKJC5YMz1jCnQ9cwp0cnl7cz1kLiQwKCkKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwK
eXY6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQx
KGUpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMShlKQpyZXR1cm4gc31maW5hbGx5eyQuWDM9dH19LApReDpm
dW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQy
KGUsZikKJC5YMz1jCnQ9cwp0cnl7cz1kLiQyKGUsZikKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwK
-VGs6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKdS5NLmEoZCkKdD1DLk5VIT09YwppZih0KWQ9ISghdHx8
+VGs6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKdS5NLmIoZCkKdD1DLk5VIT09YwppZih0KWQ9ISghdHx8
ITEpP2MuR1koZCk6Yy5SVChkLHUuSCkKUC5lVyhkKX0sCnRoOmZ1bmN0aW9uIHRoKGEpe3RoaXMuYT1h
fSwKaGE6ZnVuY3Rpb24gaGEoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnM6ZnVu
Y3Rpb24gVnMoYSl7dGhpcy5hPWF9LApGdDpmdW5jdGlvbiBGdChhKXt0aGlzLmE9YX0sClczOmZ1bmN0
@@ -1287,3609 +1245,3595 @@
dGlvbiBPTShhKXt0aGlzLmE9YQp0aGlzLmI9bnVsbH0sCnFoOmZ1bmN0aW9uIHFoKCl7fSwKQjU6ZnVu
Y3Rpb24gQjUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sClBJOmZ1bmN0aW9uIFBJKGEsYil7dGhpcy5h
PWEKdGhpcy5iPWJ9LApNTzpmdW5jdGlvbiBNTygpe30sCmtUOmZ1bmN0aW9uIGtUKCl7fSwKeEk6ZnVu
-Y3Rpb24geEkoYSl7dGhpcy4kdGk9YX0sCk9IOmZ1bmN0aW9uIE9IKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LAptMDpmdW5jdGlvbiBtMCgpe30sCnBLOmZ1bmN0aW9uIHBLKGEpe3RoaXMuYT1hfSwKSmk6ZnVu
-Y3Rpb24gSmkoKXt9LApoajpmdW5jdGlvbiBoaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
-PWN9LApWcDpmdW5jdGlvbiBWcChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKT1I6ZnVuY3Rpb24gT1Io
-YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKRUY6ZnVuY3Rpb24oYSxiLGMpe3JldHVy
-biBiLkMoIkA8MD4iKS5LKGMpLkMoIkZvPDEsMj4iKS5hKEguQjcoYSxuZXcgSC5ONShiLkMoIkA8MD4i
-KS5LKGMpLkMoIk41PDEsMj4iKSkpKX0sCkZsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILk41KGEu
-QygiQDwwPiIpLksoYikuQygiTjU8MSwyPiIpKX0sCkxzOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5i
-NihhLkMoImI2PDA+IikpfSwKVDI6ZnVuY3Rpb24oKXt2YXIgdD1PYmplY3QuY3JlYXRlKG51bGwpCnRb
-Ijxub24taWRlbnRpZmllci1rZXk+Il09dApkZWxldGUgdFsiPG5vbi1pZGVudGlmaWVyLWtleT4iXQpy
-ZXR1cm4gdH0sCnJqOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1uZXcgUC5sbShhLGIsYy5DKCJsbTwwPiIp
-KQp0LmM9YS5lCnJldHVybiB0fSwKRVA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5oQihhKSl7
-aWYoYj09PSIoIiYmYz09PSIpIilyZXR1cm4iKC4uLikiCnJldHVybiBiKyIuLi4iK2N9dD1ILlZNKFtd
-LHUucykKQy5ObS5BKCQueGcsYSkKdHJ5e1AuVnIoYSx0KX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3Ro
-KXJldHVybiBILmsoJC54ZywtMSkKJC54Zy5wb3AoKX1zPVAudmcoYix1LlIuYSh0KSwiLCAiKStjCnJl
-dHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKV0U6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYo
-UC5oQihhKSlyZXR1cm4gYisiLi4uIitjCnQ9bmV3IFAuUm4oYikKQy5ObS5BKCQueGcsYSkKdHJ5e3M9
-dApzLmE9UC52ZyhzLmEsYSwiLCAiKX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILmso
-JC54ZywtMSkKJC54Zy5wb3AoKX10LmErPWMKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9z
-OnN9LApoQjpmdW5jdGlvbihhKXt2YXIgdCxzCmZvcih0PSQueGcubGVuZ3RoLHM9MDtzPHQ7KytzKWlm
-KGE9PT0kLnhnW3NdKXJldHVybiEwCnJldHVybiExfSwKVnI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIs
-cSxwLG8sbixtPWEuZ3coYSksbD0wLGs9MAp3aGlsZSghMCl7aWYoIShsPDgwfHxrPDMpKWJyZWFrCmlm
-KCFtLm0oKSlyZXR1cm4KdD1ILmQobS5nUihtKSkKQy5ObS5BKGIsdCkKbCs9dC5sZW5ndGgrMjsrK2t9
-aWYoIW0ubSgpKXtpZihrPD01KXJldHVybgppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnM9
-Yi5wb3AoKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnI9Yi5wb3AoKX1lbHNle3E9bS5n
-UihtKTsrK2sKaWYoIW0ubSgpKXtpZihrPD00KXtDLk5tLkEoYixILmQocSkpCnJldHVybn1zPUguZChx
-KQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnI9Yi5wb3AoKQpsKz1zLmxlbmd0aCsyfWVs
-c2V7cD1tLmdSKG0pOysrawpmb3IoO20ubSgpO3E9cCxwPW8pe289bS5nUihtKTsrK2sKaWYoaz4xMDAp
-e3doaWxlKCEwKXtpZighKGw+NzUmJms+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguayhi
-LC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyOy0ta31DLk5tLkEoYiwiLi4uIikKcmV0dXJufX1yPUguZChx
-KQpzPUguZChwKQpsKz1zLmxlbmd0aCtyLmxlbmd0aCs0fX1pZihrPmIubGVuZ3RoKzIpe2wrPTUKbj0i
-Li4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYoIShsPjgwJiZiLmxlbmd0aD4zKSlicmVhawppZigw
-Pj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCmwtPWIucG9wKCkubGVuZ3RoKzIKaWYobj09bnVsbCl7
-bCs9NQpuPSIuLi4ifX1pZihuIT1udWxsKUMuTm0uQShiLG4pCkMuTm0uQShiLHIpCkMuTm0uQShiLHMp
-fSwKdE06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5McyhiKQpmb3IodD1hLmxlbmd0aCxzPTA7czxh
-Lmxlbmd0aDthLmxlbmd0aD09PXR8fCgwLEgubGspKGEpLCsrcylyLkEoMCxiLmEoYVtzXSkpCnJldHVy
-biByfSwKbk86ZnVuY3Rpb24oYSl7dmFyIHQscz17fQppZihQLmhCKGEpKXJldHVybiJ7Li4ufSIKdD1u
-ZXcgUC5SbigiIikKdHJ5e0MuTm0uQSgkLnhnLGEpCnQuYSs9InsiCnMuYT0hMApKLmhFKGEsbmV3IFAu
-cmEocyx0KSkKdC5hKz0ifSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5rKCQueGcs
-LTEpCiQueGcucG9wKCl9cz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApiNjpmdW5j
-dGlvbiBiNihhKXt2YXIgXz10aGlzCl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVsbApfLnI9MApf
-LiR0aT1hfSwKYm46ZnVuY3Rpb24gYm4oYSl7dGhpcy5hPWEKdGhpcy5jPXRoaXMuYj1udWxsfSwKbG06
-ZnVuY3Rpb24gbG0oYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRp
-PWN9LAptVzpmdW5jdGlvbiBtVygpe30sCkxVOmZ1bmN0aW9uIExVKCl7fSwKbEQ6ZnVuY3Rpb24gbEQo
-KXt9LAppbDpmdW5jdGlvbiBpbCgpe30sCnJhOmZ1bmN0aW9uIHJhKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApZazpmdW5jdGlvbiBZaygpe30sCnlROmZ1bmN0aW9uIHlRKGEpe3RoaXMuYT1hfSwKS1A6ZnVu
-Y3Rpb24gS1AoKXt9LApQbjpmdW5jdGlvbiBQbigpe30sCkdqOmZ1bmN0aW9uIEdqKGEsYil7dGhpcy5h
-PWEKdGhpcy4kdGk9Yn0sCk1hOmZ1bmN0aW9uIE1hKCl7fSwKUks6ZnVuY3Rpb24gUksoKXt9LApYdjpm
-dW5jdGlvbiBYdigpe30sCm5ZOmZ1bmN0aW9uIG5ZKCl7fSwKTGo6ZnVuY3Rpb24gTGooKXt9LApSVTpm
-dW5jdGlvbiBSVSgpe30sCkJTOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKaWYodHlwZW9mIGEhPSJz
-dHJpbmciKXRocm93IEguYihILnRMKGEpKQp0PW51bGwKdHJ5e3Q9SlNPTi5wYXJzZShhKX1jYXRjaChy
-KXtzPUguUnUocikKcT1QLnJyKFN0cmluZyhzKSxudWxsLG51bGwpCnRocm93IEguYihxKX1xPVAuUWUo
-dCkKcmV0dXJuIHF9LApRZTpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBudWxsCmlm
-KHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYQppZihPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkhPT1B
-cnJheS5wcm90b3R5cGUpcmV0dXJuIG5ldyBQLnV3KGEsT2JqZWN0LmNyZWF0ZShudWxsKSkKZm9yKHQ9
-MDt0PGEubGVuZ3RoOysrdClhW3RdPVAuUWUoYVt0XSkKcmV0dXJuIGF9LApreTpmdW5jdGlvbihhLGIs
-YyxkKXtpZihiIGluc3RhbmNlb2YgVWludDhBcnJheSlyZXR1cm4gUC5SUCghMSxiLGMsZCkKcmV0dXJu
-IG51bGx9LApSUDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHI9JC5yZigpCmlmKHI9PW51bGwpcmV0
-dXJuIG51bGwKdD0wPT09YwppZih0JiYhMClyZXR1cm4gUC5PUShyLGIpCnM9Yi5sZW5ndGgKZD1QLmpC
-KGMsZCxzKQppZih0JiZkPT09cylyZXR1cm4gUC5PUShyLGIpCnJldHVybiBQLk9RKHIsYi5zdWJhcnJh
-eShjLGQpKX0sCk9ROmZ1bmN0aW9uKGEsYil7aWYoUC5BaihiKSlyZXR1cm4gbnVsbApyZXR1cm4gUC5K
-aChhLGIpfSwKSmg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnRyeXt0PWEuZGVjb2RlKGIpCnJldHVybiB0
-fWNhdGNoKHMpe0guUnUocyl9cmV0dXJuIG51bGx9LApBajpmdW5jdGlvbihhKXt2YXIgdCxzPWEubGVu
-Z3RoLTIKZm9yKHQ9MDt0PHM7Kyt0KWlmKGFbdF09PT0yMzcpaWYoKGFbdCsxXSYyMjQpPT09MTYwKXJl
-dHVybiEwCnJldHVybiExfSwKV0k6ZnVuY3Rpb24oKXt2YXIgdCxzCnRyeXt0PW5ldyBUZXh0RGVjb2Rl
-cigidXRmLTgiLHtmYXRhbDp0cnVlfSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKX1yZXR1cm4gbnVs
-bH0sCmNQOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIKZm9yKHQ9Si5VNihhKSxzPWI7czxjOysrcyl7
-cj10LnEoYSxzKQppZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLnpNKCkKaWYoKHImMTI3KSE9
-PXIpcmV0dXJuIHMtYn1yZXR1cm4gYy1ifSwKeE06ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2lmKEMuam4u
-elkoZiw0KSE9PTApdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIHBhZGRlZCBs
-ZW5ndGggbXVzdCBiZSBtdWx0aXBsZSBvZiBmb3VyLCBpcyAiK2YsYSxjKSkKaWYoZCtlIT09Zil0aHJv
-dyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywgJz0nIG5vdCBhdCB0aGUgZW5kIixhLGIp
-KQppZihlPjIpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIG1vcmUgdGhhbiB0
-d28gJz0nIGNoYXJhY3RlcnMiLGEsYikpfSwKdXc6ZnVuY3Rpb24gdXcoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Ygp0aGlzLmM9bnVsbH0sCmk4OmZ1bmN0aW9uIGk4KGEpe3RoaXMuYT1hfSwKQ1Y6ZnVuY3Rpb24g
-Q1YoKXt9LAp2QTpmdW5jdGlvbiB2QSgpe30sClVrOmZ1bmN0aW9uIFVrKCl7fSwKd0k6ZnVuY3Rpb24g
-d0koKXt9LApaaTpmdW5jdGlvbiBaaSgpe30sCmJ5OmZ1bmN0aW9uIGJ5KCl7fSwKTXg6ZnVuY3Rpb24g
-TXgoYSl7dGhpcy5hPWF9LAp1NTpmdW5jdGlvbiB1NSgpe30sCkUzOmZ1bmN0aW9uIEUzKCl7fSwKUnc6
-ZnVuY3Rpb24gUncoYSl7dGhpcy5iPTAKdGhpcy5jPWF9LApHWTpmdW5jdGlvbiBHWShhKXt0aGlzLmE9
-YX0sCmJ6OmZ1bmN0aW9uIGJ6KGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9ITAKXy5mPV8u
-ZT1fLmQ9MH0sClFBOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkhwKGEsYykKaWYodCE9bnVsbClyZXR1
-cm4gdAppZihiIT1udWxsKXJldHVybiBiLiQxKGEpCnRocm93IEguYihQLnJyKGEsbnVsbCxudWxsKSl9
-LApvczpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNlb2YgSC5UcClyZXR1cm4gYS5aKDApCnJldHVybiJJ
-bnN0YW5jZSBvZiAnIitILmQoSC5saChhKSkrIicifSwKTzg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9
-Si5RaShhLGMpCmlmKGEhPT0wJiYhMClmb3IodD0wO3Q8cy5sZW5ndGg7Kyt0KUMuTm0udChzLHQsYikK
-cmV0dXJuIHN9LApDSDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1ILlZNKFtdLGMuQygiamQ8MD4iKSkK
-Zm9yKHQ9Si5JVChhKTt0Lm0oKTspQy5ObS5BKHMsYy5hKHQuZ1IodCkpKQppZihiKXJldHVybiBzCnJl
-dHVybiBjLkMoInpNPDA+IikuYShKLkVwKHMpKX0sCkFGOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGIuQygi
-ek08MD4iKS5hKEoudW4oUC5DSChhLCExLGIpKSl9LApITTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYo
-QXJyYXkuaXNBcnJheShhKSl7dS50LmEoYSkKdD1hLmxlbmd0aApjPVAuakIoYixjLHQpCnJldHVybiBI
-LmVUKGI+MHx8Yzx0P0MuTm0uRDYoYSxiLGMpOmEpfWlmKHUuYm0uYihhKSlyZXR1cm4gSC5mdyhhLGIs
-UC5qQihiLGMsYS5sZW5ndGgpKQpyZXR1cm4gUC5idyhhLGIsYyl9LApPbzpmdW5jdGlvbihhKXtyZXR1
-cm4gSC5MdyhhKX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwPW51bGwKaWYoYjwwKXRo
-cm93IEguYihQLlRFKGIsMCxKLkgoYSkscCxwKSkKdD1jPT1udWxsCmlmKCF0JiZjPGIpdGhyb3cgSC5i
-KFAuVEUoYyxiLEouSChhKSxwLHApKQpzPUouSVQoYSkKZm9yKHI9MDtyPGI7KytyKWlmKCFzLm0oKSl0
-aHJvdyBILmIoUC5URShiLDAscixwLHApKQpxPVtdCmlmKHQpZm9yKDtzLm0oKTspcS5wdXNoKHMuZ1Io
-cykpCmVsc2UgZm9yKHI9YjtyPGM7KytyKXtpZighcy5tKCkpdGhyb3cgSC5iKFAuVEUoYyxiLHIscCxw
-KSkKcS5wdXNoKHMuZ1IocykpfXJldHVybiBILmVUKHEpfSwKbnU6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
-dyBILlZSKGEsSC52NChhLCExLCEwLCExLCExLCExKSl9LAp2ZzpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9
-Si5JVChiKQppZighdC5tKCkpcmV0dXJuIGEKaWYoYy5sZW5ndGg9PT0wKXtkbyBhKz1ILmQodC5nUih0
-KSkKd2hpbGUodC5tKCkpfWVsc2V7YSs9SC5kKHQuZ1IodCkpCmZvcig7dC5tKCk7KWE9YStjK0guZCh0
-LmdSKHQpKX1yZXR1cm4gYX0sCmxyOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBuZXcgUC5tcChhLGIs
-YyxkKX0sCnVvOmZ1bmN0aW9uKCl7dmFyIHQ9SC5NMCgpCmlmKHQhPW51bGwpcmV0dXJuIFAuaEsodCkK
-dGhyb3cgSC5iKFAuTDQoIidVcmkuYmFzZScgaXMgbm90IHN1cHBvcnRlZCIpKX0sCmVQOmZ1bmN0aW9u
-KGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuPSIwMTIzNDU2Nzg5QUJDREVGIgppZihjPT09Qy54TSl7
-dD0kLno0KCkuYgppZih0eXBlb2YgYiE9InN0cmluZyIpSC5WaihILnRMKGIpKQp0PXQudGVzdChiKX1l
-bHNlIHQ9ITEKaWYodClyZXR1cm4gYgpILkxoKGMpLkMoIlVrLlMiKS5hKGIpCnM9Yy5nWkUoKS5XSihi
-KQpmb3IodD1zLmxlbmd0aCxyPTAscT0iIjtyPHQ7KytyKXtwPXNbcl0KaWYocDwxMjgpe289cD4+PjQK
-aWYobz49OClyZXR1cm4gSC5rKGEsbykKbz0oYVtvXSYxPDwocCYxNSkpIT09MH1lbHNlIG89ITEKaWYo
-bylxKz1ILkx3KHApCmVsc2UgcT1kJiZwPT09MzI/cSsiKyI6cSsiJSIrbltwPj4+NCYxNV0rbltwJjE1
-XX1yZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sClpiOmZ1bmN0aW9uKCl7dmFyIHQscwppZihI
-Lm9UKCQucDYoKSkpcmV0dXJuIEgudHMobmV3IEVycm9yKCkpCnRyeXt0aHJvdyBILmIoIiIpfWNhdGNo
-KHMpe0guUnUocykKdD1ILnRzKHMpCnJldHVybiB0fX0sCkdxOmZ1bmN0aW9uKGEpe3ZhciB0PU1hdGgu
-YWJzKGEpLHM9YTwwPyItIjoiIgppZih0Pj0xMDAwKXJldHVybiIiK2EKaWYodD49MTAwKXJldHVybiBz
-KyIwIit0CmlmKHQ+PTEwKXJldHVybiBzKyIwMCIrdApyZXR1cm4gcysiMDAwIit0fSwKVng6ZnVuY3Rp
-b24oYSl7aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0dXJuIjAiK2EKcmV0dXJuIjAwIith
-fSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpyZXR1cm4iMCIrYX0sCmg6ZnVuY3Rp
-b24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIifHxILnJRKGEpfHxudWxsPT1hKXJldHVybiBKLkFjKGEp
-CmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSlNPTi5zdHJpbmdpZnkoYSkKcmV0dXJuIFAub3Mo
-YSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQzYoYSl9LAp4WTpmdW5jdGlvbihhKXtyZXR1
-cm4gbmV3IFAuQVQoITEsbnVsbCxudWxsLGEpfSwKTDM6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcg
-UC5BVCghMCxhLGIsYyl9LApoRzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQVQoITEsbnVsbCxhLCJN
-dXN0IG5vdCBiZSBudWxsIil9LApVSTpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbCl0aHJvdyBILmIo
-UC5oRyhiKSkKcmV0dXJuIGF9LApPNzpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5iSihudWxsLG51
-bGwsITAsYSxiLCJWYWx1ZSBub3QgaW4gcmFuZ2UiKX0sClRFOmZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0
-dXJuIG5ldyBQLmJKKGIsYywhMCxhLGQsIkludmFsaWQgdmFsdWUiKX0sCndBOmZ1bmN0aW9uKGEsYixj
-LGQpe2lmKGE8Ynx8YT5jKXRocm93IEguYihQLlRFKGEsYixjLGQsbnVsbCkpCnJldHVybiBhfSwKakI6
-ZnVuY3Rpb24oYSxiLGMpe2lmKDA+YXx8YT5jKXRocm93IEguYihQLlRFKGEsMCxjLCJzdGFydCIsbnVs
-bCkpCmlmKGIhPW51bGwpe2lmKGE+Ynx8Yj5jKXRocm93IEguYihQLlRFKGIsYSxjLCJlbmQiLG51bGwp
-KQpyZXR1cm4gYn1yZXR1cm4gY30sCmsxOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGEhPT0ibnVtYmVy
-IilyZXR1cm4gYS5KKCkKaWYoYTwwKXRocm93IEguYihQLlRFKGEsMCxudWxsLGIsbnVsbCkpCnJldHVy
-biBhfSwKdDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PUguV1koZT09bnVsbD9KLkgoYik6ZSkKcmV0
-dXJuIG5ldyBQLmVZKHQsITAsYSxjLCJJbmRleCBvdXQgb2YgcmFuZ2UiKX0sCkw0OmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgUC51YihhKX0sCm46ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmRzKGEpfSwKUFY6
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmxqKGEpfSwKYTQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQ
-LlVWKGEpfSwKcnI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcgUC5hRShhLGIsYyl9LApkSDpmdW5j
-dGlvbihhLGIsYyxkKXt2YXIgdCxzPUguVk0oW10sZC5DKCJqZDwwPiIpKQpDLk5tLnNrKHMsYSkKZm9y
-KHQ9MDt0PGE7Kyt0KUMuTm0udChzLHQsYi4kMSh0KSkKcmV0dXJuIHN9LApoSzpmdW5jdGlvbihhKXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9YS5sZW5ndGgKaWYoZD49NSl7
-dD0oKEouUXooYSw0KV41OCkqM3xDLnhCLldkKGEsMCleMTAwfEMueEIuV2QoYSwxKV45N3xDLnhCLldk
-KGEsMileMTE2fEMueEIuV2QoYSwzKV45Nyk+Pj4wCmlmKHQ9PT0wKXJldHVybiBQLktEKGQ8ZD9DLnhC
-Lk5qKGEsMCxkKTphLDUsZSkuZ2xSKCkKZWxzZSBpZih0PT09MzIpcmV0dXJuIFAuS0QoQy54Qi5Oaihh
-LDUsZCksMCxlKS5nbFIoKX1zPW5ldyBBcnJheSg4KQpzLmZpeGVkJGxlbmd0aD1BcnJheQpyPUguVk0o
-cyx1LnQpCkMuTm0udChyLDAsMCkKQy5ObS50KHIsMSwtMSkKQy5ObS50KHIsMiwtMSkKQy5ObS50KHIs
-NywtMSkKQy5ObS50KHIsMywwKQpDLk5tLnQociw0LDApCkMuTm0udChyLDUsZCkKQy5ObS50KHIsNixk
-KQppZihQLlVCKGEsMCxkLDAscik+PTE0KUMuTm0udChyLDcsZCkKcT1yWzFdCmlmKHR5cGVvZiBxIT09
-Im51bWJlciIpcmV0dXJuIHEudEIoKQppZihxPj0wKWlmKFAuVUIoYSwwLHEsMjAscik9PT0yMClyWzdd
-PXEKcz1yWzJdCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuaCgpCnA9cysxCm89clszXQpu
-PXJbNF0KbT1yWzVdCmw9cls2XQppZih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkooKQppZih0
-eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBILnBZKG0pCmlmKGw8bSltPWwKaWYodHlwZW9mIG4hPT0i
-bnVtYmVyIilyZXR1cm4gbi5KKCkKaWYobjxwKW49bQplbHNlIGlmKG48PXEpbj1xKzEKaWYodHlwZW9m
-IG8hPT0ibnVtYmVyIilyZXR1cm4gby5KKCkKaWYobzxwKW89bgpzPXJbN10KaWYodHlwZW9mIHMhPT0i
-bnVtYmVyIilyZXR1cm4gcy5KKCkKaz1zPDAKaWYoaylpZihwPnErMyl7aj1lCms9ITF9ZWxzZXtzPW8+
-MAppZihzJiZvKzE9PT1uKXtqPWUKaz0hMX1lbHNle2lmKCEobTxkJiZtPT09bisyJiZKLnEwKGEsIi4u
-IixuKSkpaT1tPm4rMiYmSi5xMChhLCIvLi4iLG0tMykKZWxzZSBpPSEwCmlmKGkpe2o9ZQprPSExfWVs
-c2V7aWYocT09PTQpaWYoSi5xMChhLCJmaWxlIiwwKSl7aWYocDw9MCl7aWYoIUMueEIuUWkoYSwiLyIs
-bikpe2g9ImZpbGU6Ly8vIgp0PTN9ZWxzZXtoPSJmaWxlOi8vIgp0PTJ9YT1oK0MueEIuTmooYSxuLGQp
-CnEtPTAKcz10LTAKbSs9cwpsKz1zCmQ9YS5sZW5ndGgKcD03Cm89NwpuPTd9ZWxzZSBpZihuPT09bSl7
-Zz1tKzE7KytsCmE9Qy54Qi5pNyhhLG4sbSwiLyIpOysrZAptPWd9aj0iZmlsZSJ9ZWxzZSBpZihDLnhC
-LlFpKGEsImh0dHAiLDApKXtpZihzJiZvKzM9PT1uJiZDLnhCLlFpKGEsIjgwIixvKzEpKXtmPW4tMwpt
-LT0zCmwtPTMKYT1DLnhCLmk3KGEsbyxuLCIiKQpkLT0zCm49Zn1qPSJodHRwIn1lbHNlIGo9ZQplbHNl
-IGlmKHE9PT01JiZKLnEwKGEsImh0dHBzIiwwKSl7aWYocyYmbys0PT09biYmSi5xMChhLCI0NDMiLG8r
-MSkpe2Y9bi00Cm0tPTQKbC09NAphPUouZGcoYSxvLG4sIiIpCmQtPTMKbj1mfWo9Imh0dHBzIn1lbHNl
-IGo9ZQprPSEwfX19ZWxzZSBqPWUKaWYoayl7cz1hLmxlbmd0aAppZihkPHMpe2E9Si5sZChhLDAsZCkK
-cS09MApwLT0wCm8tPTAKbi09MAptLT0wCmwtPTB9cmV0dXJuIG5ldyBQLlVmKGEscSxwLG8sbixtLGws
-ail9cmV0dXJuIFAuanYoYSwwLGQscSxwLG8sbixtLGwsail9LApNdDpmdW5jdGlvbihhKXtILmMoYSkK
-cmV0dXJuIFAua3UoYSwwLGEubGVuZ3RoLEMueE0sITEpfSwKV1g6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5O
-CnJldHVybiBDLk5tLk4wKEguVk0oYS5zcGxpdCgiJiIpLHUucyksUC5GbCh0LHQpLG5ldyBQLm4xKEMu
-eE0pLHUuZil9LApIaDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbT1udWxsLGw9IklQ
-djQgYWRkcmVzcyBzaG91bGQgY29udGFpbiBleGFjdGx5IDQgcGFydHMiLGs9ImVhY2ggcGFydCBtdXN0
-IGJlIGluIHRoZSByYW5nZSAwLi4yNTUiLGo9bmV3IFAuY1MoYSksaT1uZXcgVWludDhBcnJheSg0KQpm
-b3IodD1pLmxlbmd0aCxzPWIscj1zLHE9MDtzPGM7KytzKXtwPUMueEIuTzIoYSxzKQppZihwIT09NDYp
-e2lmKChwXjQ4KT45KWouJDIoImludmFsaWQgY2hhcmFjdGVyIixzKX1lbHNle2lmKHE9PT0zKWouJDIo
-bCxzKQpvPVAuUUEoQy54Qi5OaihhLHIscyksbSxtKQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVy
-biBvLm9zKCkKaWYobz4yNTUpai4kMihrLHIpCm49cSsxCmlmKHE+PXQpcmV0dXJuIEguayhpLHEpCmlb
+Y3Rpb24geEkoYSl7dGhpcy4kdGk9YX0sCkN3OmZ1bmN0aW9uIEN3KGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LAptMDpmdW5jdGlvbiBtMCgpe30sCnBLOmZ1bmN0aW9uIHBLKGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LApKaTpmdW5jdGlvbiBKaSgpe30sCmhqOmZ1bmN0aW9uIGhqKGEsYixjKXt0aGlzLmE9YQp0aGlz
+LmI9Ygp0aGlzLmM9Y30sClZwOmZ1bmN0aW9uIFZwKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApPUjpm
+dW5jdGlvbiBPUihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApFRjpmdW5jdGlvbihh
+LGIsYyl7cmV0dXJuIGIuQygiQDwwPiIpLksoYykuQygiRm88MSwyPiIpLmIoSC5CNyhhLG5ldyBILk41
+KGIuQygiQDwwPiIpLksoYykuQygiTjU8MSwyPiIpKSkpfSwKRmw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+bmV3IEguTjUoYS5DKCJAPDA+IikuSyhiKS5DKCJONTwxLDI+IikpfSwKTHM6ZnVuY3Rpb24oYSl7cmV0
+dXJuIG5ldyBQLmI2KGEuQygiYjY8MD4iKSl9LApUMjpmdW5jdGlvbigpe3ZhciB0PU9iamVjdC5jcmVh
+dGUobnVsbCkKdFsiPG5vbi1pZGVudGlmaWVyLWtleT4iXT10CmRlbGV0ZSB0WyI8bm9uLWlkZW50aWZp
+ZXIta2V5PiJdCnJldHVybiB0fSwKcmo6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PW5ldyBQLmxtKGEsYixj
+LkMoImxtPDA+IikpCnQuYz1hLmUKcmV0dXJuIHR9LApFUDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwpp
+ZihQLmhCKGEpKXtpZihiPT09IigiJiZjPT09IikiKXJldHVybiIoLi4uKSIKcmV0dXJuIGIrIi4uLiIr
+Y310PUguVk0oW10sdS5zKQpDLk5tLkEoJC54ZyxhKQp0cnl7UC5WcihhLHQpfWZpbmFsbHl7aWYoMD49
+JC54Zy5sZW5ndGgpcmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX1zPVAudmcoYix1LlIuYih0
+KSwiLCAiKStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKV0U6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0LHMKaWYoUC5oQihhKSlyZXR1cm4gYisiLi4uIitjCnQ9bmV3IFAuUm4oYikKQy5ObS5BKCQu
+eGcsYSkKdHJ5e3M9dApzLmE9UC52ZyhzLmEsYSwiLCAiKX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3Ro
+KXJldHVybiBILk9IKCQueGcsLTEpCiQueGcucG9wKCl9dC5hKz1jCnM9dC5hCnJldHVybiBzLmNoYXJD
+b2RlQXQoMCk9PTA/czpzfSwKaEI6ZnVuY3Rpb24oYSl7dmFyIHQscwpmb3IodD0kLnhnLmxlbmd0aCxz
+PTA7czx0OysrcylpZihhPT09JC54Z1tzXSlyZXR1cm4hMApyZXR1cm4hMX0sClZyOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscyxyLHEscCxvLG4sbT1hLmdreihhKSxsPTAsaz0wCndoaWxlKCEwKXtpZighKGw8ODB8
+fGs8MykpYnJlYWsKaWYoIW0ubSgpKXJldHVybgp0PUguZChtLmdSKG0pKQpDLk5tLkEoYix0KQpsKz10
+Lmxlbmd0aCsyOysra31pZighbS5tKCkpe2lmKGs8PTUpcmV0dXJuCmlmKDA+PWIubGVuZ3RoKXJldHVy
+biBILk9IKGIsLTEpCnM9Yi5wb3AoKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpyPWIu
+cG9wKCl9ZWxzZXtxPW0uZ1IobSk7KytrCmlmKCFtLm0oKSl7aWYoazw9NCl7Qy5ObS5BKGIsSC5kKHEp
+KQpyZXR1cm59cz1ILmQocSkKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKcj1iLnBvcCgp
+CmwrPXMubGVuZ3RoKzJ9ZWxzZXtwPW0uZ1IobSk7KytrCmZvcig7bS5tKCk7cT1wLHA9byl7bz1tLmdS
+KG0pOysrawppZihrPjEwMCl7d2hpbGUoITApe2lmKCEobD43NSYmaz4zKSlicmVhawppZigwPj1iLmxl
+bmd0aClyZXR1cm4gSC5PSChiLC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyOy0ta31DLk5tLkEoYiwiLi4u
+IikKcmV0dXJufX1yPUguZChxKQpzPUguZChwKQpsKz1zLmxlbmd0aCtyLmxlbmd0aCs0fX1pZihrPmIu
+bGVuZ3RoKzIpe2wrPTUKbj0iLi4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYoIShsPjgwJiZiLmxl
+bmd0aD4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpsLT1iLnBvcCgpLmxl
+bmd0aCsyCmlmKG49PW51bGwpe2wrPTUKbj0iLi4uIn19aWYobiE9bnVsbClDLk5tLkEoYixuKQpDLk5t
+LkEoYixyKQpDLk5tLkEoYixzKX0sCnRNOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPVAuTHMoYikKZm9y
+KHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpci5B
+KDAsYi5iKGFbc10pKQpyZXR1cm4gcn0sCm5POmZ1bmN0aW9uKGEpe3ZhciB0LHM9e30KaWYoUC5oQihh
+KSlyZXR1cm4iey4uLn0iCnQ9bmV3IFAuUm4oIiIpCnRyeXtDLk5tLkEoJC54ZyxhKQp0LmErPSJ7Igpz
+LmE9ITAKSi5oRShhLG5ldyBQLnJhKHMsdCkpCnQuYSs9In0ifWZpbmFsbHl7aWYoMD49JC54Zy5sZW5n
+dGgpcmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX1zPXQuYQpyZXR1cm4gcy5jaGFyQ29kZUF0
+KDApPT0wP3M6c30sCmI2OmZ1bmN0aW9uIGI2KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1fLmQ9
+Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApibjpmdW5jdGlvbiBibihhKXt0aGlzLmE9YQp0aGlz
+LmM9dGhpcy5iPW51bGx9LApsbTpmdW5jdGlvbiBsbShhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9
+YgpfLmQ9Xy5jPW51bGwKXy4kdGk9Y30sCm1XOmZ1bmN0aW9uIG1XKCl7fSwKTFU6ZnVuY3Rpb24gTFUo
+KXt9LApsRDpmdW5jdGlvbiBsRCgpe30sCmlsOmZ1bmN0aW9uIGlsKCl7fSwKcmE6ZnVuY3Rpb24gcmEo
+YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCllrOmZ1bmN0aW9uIFlrKCl7fSwKeVE6ZnVuY3Rpb24geVEo
+YSl7dGhpcy5hPWF9LApLUDpmdW5jdGlvbiBLUCgpe30sClBuOmZ1bmN0aW9uIFBuKCl7fSwKR2o6ZnVu
+Y3Rpb24gR2ooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKbGY6ZnVuY3Rpb24gbGYoKXt9LApSSzpm
+dW5jdGlvbiBSSygpe30sClh2OmZ1bmN0aW9uIFh2KCl7fSwKblk6ZnVuY3Rpb24gblkoKXt9LApXWTpm
+dW5jdGlvbiBXWSgpe30sClJVOmZ1bmN0aW9uIFJVKCl7fSwKQlM6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+LHIscQppZih0eXBlb2YgYSE9InN0cmluZyIpdGhyb3cgSC5iKEgudEwoYSkpCnQ9bnVsbAp0cnl7dD1K
+U09OLnBhcnNlKGEpfWNhdGNoKHIpe3M9SC5SdShyKQpxPVAucnIoU3RyaW5nKHMpLG51bGwsbnVsbCkK
+dGhyb3cgSC5iKHEpfXE9UC5RZSh0KQpyZXR1cm4gcX0sClFlOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9
+PW51bGwpcmV0dXJuIG51bGwKaWYodHlwZW9mIGEhPSJvYmplY3QiKXJldHVybiBhCmlmKE9iamVjdC5n
+ZXRQcm90b3R5cGVPZihhKSE9PUFycmF5LnByb3RvdHlwZSlyZXR1cm4gbmV3IFAudXcoYSxPYmplY3Qu
+Y3JlYXRlKG51bGwpKQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KWFbdF09UC5RZShhW3RdKQpyZXR1cm4g
+YX0sCmt5OmZ1bmN0aW9uKGEsYixjLGQpe2lmKGIgaW5zdGFuY2VvZiBVaW50OEFycmF5KXJldHVybiBQ
+LlJQKCExLGIsYyxkKQpyZXR1cm4gbnVsbH0sClJQOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscj0k
+LnJmKCkKaWYocj09bnVsbClyZXR1cm4gbnVsbAp0PTA9PT1jCmlmKHQmJiEwKXJldHVybiBQLk9RKHIs
+YikKcz1iLmxlbmd0aApkPVAuakIoYyxkLHMpCmlmKHQmJmQ9PT1zKXJldHVybiBQLk9RKHIsYikKcmV0
+dXJuIFAuT1EocixiLnN1YmFycmF5KGMsZCkpfSwKT1E6ZnVuY3Rpb24oYSxiKXtpZihQLkJlKGIpKXJl
+dHVybiBudWxsCnJldHVybiBQLkpoKGEsYil9LApKaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMKdHJ5e3Q9
+YS5kZWNvZGUoYikKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKX1yZXR1cm4gbnVsbH0sCkJlOmZ1bmN0
+aW9uKGEpe3ZhciB0LHM9YS5sZW5ndGgtMgpmb3IodD0wO3Q8czsrK3QpaWYoYVt0XT09PTIzNylpZigo
+YVt0KzFdJjIyNCk9PT0xNjApcmV0dXJuITAKcmV0dXJuITF9LApXSTpmdW5jdGlvbigpe3ZhciB0LHMK
+dHJ5e3Q9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2ZhdGFsOnRydWV9KQpyZXR1cm4gdH1jYXRjaChz
+KXtILlJ1KHMpfXJldHVybiBudWxsfSwKY1A6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpmb3IodD1K
+LlU2KGEpLHM9YjtzPGM7KytzKXtyPXQucShhLHMpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJu
+IHIuek0oKQppZigociYxMjcpIT09cilyZXR1cm4gcy1ifXJldHVybiBjLWJ9LAp4TTpmdW5jdGlvbihh
+LGIsYyxkLGUsZil7aWYoQy5qbi56WShmLDQpIT09MCl0aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNl
+NjQgcGFkZGluZywgcGFkZGVkIGxlbmd0aCBtdXN0IGJlIG11bHRpcGxlIG9mIGZvdXIsIGlzICIrZixh
+LGMpKQppZihkK2UhPT1mKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBwYWRkaW5nLCAnPScg
+bm90IGF0IHRoZSBlbmQiLGEsYikpCmlmKGU+Mil0aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQg
+cGFkZGluZywgbW9yZSB0aGFuIHR3byAnPScgY2hhcmFjdGVycyIsYSxiKSl9LAp1dzpmdW5jdGlvbiB1
+dyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1udWxsfSwKaTg6ZnVuY3Rpb24gaTgoYSl7dGhp
+cy5hPWF9LApDVjpmdW5jdGlvbiBDVigpe30sCnZBOmZ1bmN0aW9uIHZBKCl7fSwKVWs6ZnVuY3Rpb24g
+VWsoKXt9LAp3STpmdW5jdGlvbiB3SSgpe30sClppOmZ1bmN0aW9uIFppKCl7fSwKYnk6ZnVuY3Rpb24g
+YnkoKXt9LApNeDpmdW5jdGlvbiBNeChhKXt0aGlzLmE9YX0sCnU1OmZ1bmN0aW9uIHU1KCl7fSwKRTM6
+ZnVuY3Rpb24gRTMoKXt9LApSdzpmdW5jdGlvbiBSdyhhKXt0aGlzLmI9MAp0aGlzLmM9YX0sCkdZOmZ1
+bmN0aW9uIEdZKGEpe3RoaXMuYT1hfSwKYno6ZnVuY3Rpb24gYnooYSxiKXt2YXIgXz10aGlzCl8uYT1h
+Cl8uYj1iCl8uYz0hMApfLmY9Xy5lPV8uZD0wfSwKUUE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguSHAo
+YSxjKQppZih0IT1udWxsKXJldHVybiB0CmlmKGIhPW51bGwpcmV0dXJuIGIuJDEoYSkKdGhyb3cgSC5i
+KFAucnIoYSxudWxsLG51bGwpKX0sCkY6ZnVuY3Rpb24oYSl7aWYoYSBpbnN0YW5jZW9mIEguVHApcmV0
+dXJuIGEudygwKQpyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEguTShhKSkrIicifSwKTzg6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciB0LHM9Si5RaShhLGMpCmlmKGEhPT0wJiYhMClmb3IodD0wO3Q8cy5sZW5ndGg7
+Kyt0KUMuTm0uWShzLHQsYikKcmV0dXJuIHN9LApDSDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1ILlZN
+KFtdLGMuQygiamQ8MD4iKSkKZm9yKHQ9Si5JVChhKTt0Lm0oKTspQy5ObS5BKHMsYy5iKHQuZ1IodCkp
+KQppZihiKXJldHVybiBzCnJldHVybiBjLkMoInpNPDA+IikuYihKLkVwKHMpKX0sCkFGOmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIGIuQygiek08MD4iKS5iKEouekMoUC5DSChhLCExLGIpKSl9LApITTpmdW5jdGlv
+bihhLGIsYyl7dmFyIHQKaWYoQXJyYXkuaXNBcnJheShhKSl7dS50LmIoYSkKdD1hLmxlbmd0aApjPVAu
+akIoYixjLHQpCnJldHVybiBILmVUKGI+MHx8Yzx0P0MuTm0uRDYoYSxiLGMpOmEpfWlmKHUuYm0uYyhh
+KSlyZXR1cm4gSC5mdyhhLGIsUC5qQihiLGMsYS5sZW5ndGgpKQpyZXR1cm4gUC5idyhhLGIsYyl9LApP
+bzpmdW5jdGlvbihhKXtyZXR1cm4gSC5MdyhhKX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIs
+cSxwPW51bGwKaWYoYjwwKXRocm93IEguYihQLlRFKGIsMCxKLkhtKGEpLHAscCkpCnQ9Yz09bnVsbApp
+ZighdCYmYzxiKXRocm93IEguYihQLlRFKGMsYixKLkhtKGEpLHAscCkpCnM9Si5JVChhKQpmb3Iocj0w
+O3I8YjsrK3IpaWYoIXMubSgpKXRocm93IEguYihQLlRFKGIsMCxyLHAscCkpCnE9W10KaWYodClmb3Io
+O3MubSgpOylxLnB1c2gocy5nUihzKSkKZWxzZSBmb3Iocj1iO3I8YzsrK3Ipe2lmKCFzLm0oKSl0aHJv
+dyBILmIoUC5URShjLGIscixwLHApKQpxLnB1c2gocy5nUihzKSl9cmV0dXJuIEguZVQocSl9LApudTpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEsITAsITEsITEsITEpKX0sCnZnOmZ1
+bmN0aW9uKGEsYixjKXt2YXIgdD1KLklUKGIpCmlmKCF0Lm0oKSlyZXR1cm4gYQppZihjLmxlbmd0aD09
+PTApe2RvIGErPUguZCh0LmdSKHQpKQp3aGlsZSh0Lm0oKSl9ZWxzZXthKz1ILmQodC5nUih0KSkKZm9y
+KDt0Lm0oKTspYT1hK2MrSC5kKHQuZ1IodCkpfXJldHVybiBhfSwKbHI6ZnVuY3Rpb24oYSxiLGMsZCl7
+cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIgdD1ILk0wKCkKaWYodCE9
+bnVsbClyZXR1cm4gUC5oSyh0KQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNlJyBpcyBub3Qgc3VwcG9y
+dGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG49IjAxMjM0NTY3ODlB
+QkNERUYiCmlmKGM9PT1DLnhNKXt0PSQuejQoKS5iCmlmKHR5cGVvZiBiIT0ic3RyaW5nIilILlZqKEgu
+dEwoYikpCnQ9dC50ZXN0KGIpfWVsc2UgdD0hMQppZih0KXJldHVybiBiCkguTGgoYykuQygiVWsuUyIp
+LmIoYikKcz1jLmdaRSgpLldKKGIpCmZvcih0PXMubGVuZ3RoLHI9MCxxPSIiO3I8dDsrK3Ipe3A9c1ty
+XQppZihwPDEyOCl7bz1wPj4+NAppZihvPj04KXJldHVybiBILk9IKGEsbykKbz0oYVtvXSYxPDwocCYx
+NSkpIT09MH1lbHNlIG89ITEKaWYobylxKz1ILkx3KHApCmVsc2UgcT1kJiZwPT09MzI/cSsiKyI6cSsi
+JSIrbltwPj4+NCYxNV0rbltwJjE1XX1yZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCkdxOmZ1
+bmN0aW9uKGEpe3ZhciB0PU1hdGguYWJzKGEpLHM9YTwwPyItIjoiIgppZih0Pj0xMDAwKXJldHVybiIi
+K2EKaWYodD49MTAwKXJldHVybiBzKyIwIit0CmlmKHQ+PTEwKXJldHVybiBzKyIwMCIrdApyZXR1cm4g
+cysiMDAwIit0fSwKVng6ZnVuY3Rpb24oYSl7aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0
+dXJuIjAiK2EKcmV0dXJuIjAwIithfSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpy
+ZXR1cm4iMCIrYX0sCnA6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIifHxILmwoYSl8fG51
+bGw9PWEpcmV0dXJuIEouaihhKQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEpTT04uc3RyaW5n
+aWZ5KGEpCnJldHVybiBQLkYoYSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQzYoYSl9LAp4
+WTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAudSghMSxudWxsLG51bGwsYSl9LApMMzpmdW5jdGlvbihh
+LGIsYyl7cmV0dXJuIG5ldyBQLnUoITAsYSxiLGMpfSwKRWU6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQ
+LnUoITEsbnVsbCxhLCJNdXN0IG5vdCBiZSBudWxsIil9LAp4OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5l
+dyBQLmJKKG51bGwsbnVsbCwhMCxhLGIsIlZhbHVlIG5vdCBpbiByYW5nZSIpfSwKVEU6ZnVuY3Rpb24o
+YSxiLGMsZCxlKXtyZXR1cm4gbmV3IFAuYkooYixjLCEwLGEsZCwiSW52YWxpZCB2YWx1ZSIpfSwKd0E6
+ZnVuY3Rpb24oYSxiLGMsZCl7aWYoYTxifHxhPmMpdGhyb3cgSC5iKFAuVEUoYSxiLGMsZCxudWxsKSl9
+LApqQjpmdW5jdGlvbihhLGIsYyl7aWYoMD5hfHxhPmMpdGhyb3cgSC5iKFAuVEUoYSwwLGMsInN0YXJ0
+IixudWxsKSkKaWYoYiE9bnVsbCl7aWYoYT5ifHxiPmMpdGhyb3cgSC5iKFAuVEUoYixhLGMsImVuZCIs
+bnVsbCkpCnJldHVybiBifXJldHVybiBjfSwKazE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYSE9PSJu
+dW1iZXIiKXJldHVybiBhLkooKQppZihhPDApdGhyb3cgSC5iKFAuVEUoYSwwLG51bGwsYixudWxsKSl9
+LApDZjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PUguU2MoZT09bnVsbD9KLkhtKGIpOmUpCnJldHVy
+biBuZXcgUC5lWSh0LCEwLGEsYywiSW5kZXggb3V0IG9mIHJhbmdlIil9LApMNDpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAudWIoYSl9LApTWTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuZHMoYSl9LApQVjpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IFAubGooYSl9LAphNDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAu
+VVYoYSl9LApycjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLmFFKGEsYixjKX0sCmRIOmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciB0LHM9SC5WTShbXSxkLkMoImpkPDA+IikpCkMuTm0uc2gocyxhKQpmb3Io
+dD0wO3Q8YTsrK3QpQy5ObS5ZKHMsdCxiLiQxKHQpKQpyZXR1cm4gc30sCmhLOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlPW51bGwsZD1hLmxlbmd0aAppZihkPj01KXt0
+PSgoSi5ReihhLDQpXjU4KSozfEMueEIuV2QoYSwwKV4xMDB8Qy54Qi5XZChhLDEpXjk3fEMueEIuV2Qo
+YSwyKV4xMTZ8Qy54Qi5XZChhLDMpXjk3KT4+PjAKaWYodD09PTApcmV0dXJuIFAuS0QoZDxkP0MueEIu
+TmooYSwwLGQpOmEsNSxlKS5nbFIoKQplbHNlIGlmKHQ9PT0zMilyZXR1cm4gUC5LRChDLnhCLk5qKGEs
+NSxkKSwwLGUpLmdsUigpfXM9bmV3IEFycmF5KDgpCnMuZml4ZWQkbGVuZ3RoPUFycmF5CnI9SC5WTShz
+LHUudCkKQy5ObS5ZKHIsMCwwKQpDLk5tLlkociwxLC0xKQpDLk5tLlkociwyLC0xKQpDLk5tLlkociw3
+LC0xKQpDLk5tLlkociwzLDApCkMuTm0uWShyLDQsMCkKQy5ObS5ZKHIsNSxkKQpDLk5tLlkociw2LGQp
+CmlmKFAuVUIoYSwwLGQsMCxyKT49MTQpQy5ObS5ZKHIsNyxkKQpxPXJbMV0KaWYodHlwZW9mIHEhPT0i
+bnVtYmVyIilyZXR1cm4gcS50QigpCmlmKHE+PTApaWYoUC5VQihhLDAscSwyMCxyKT09PTIwKXJbN109
+cQpzPXJbMl0KaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5UKCkKcD1zKzEKbz1yWzNdCm49
+cls0XQptPXJbNV0KbD1yWzZdCmlmKHR5cGVvZiBsIT09Im51bWJlciIpcmV0dXJuIGwuSigpCmlmKHR5
+cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkKaWYobDxtKW09bAppZih0eXBlb2YgbiE9PSJu
+dW1iZXIiKXJldHVybiBuLkooKQppZihuPHApbj1tCmVsc2UgaWYobjw9cSluPXErMQppZih0eXBlb2Yg
+byE9PSJudW1iZXIiKXJldHVybiBvLkooKQppZihvPHApbz1uCnM9cls3XQppZih0eXBlb2YgcyE9PSJu
+dW1iZXIiKXJldHVybiBzLkooKQprPXM8MAppZihrKWlmKHA+cSszKXtqPWUKaz0hMX1lbHNle3M9bz4w
+CmlmKHMmJm8rMT09PW4pe2o9ZQprPSExfWVsc2V7aWYoIShtPGQmJm09PT1uKzImJkoucTAoYSwiLi4i
+LG4pKSlpPW0+bisyJiZKLnEwKGEsIi8uLiIsbS0zKQplbHNlIGk9ITAKaWYoaSl7aj1lCms9ITF9ZWxz
+ZXtpZihxPT09NClpZihKLnEwKGEsImZpbGUiLDApKXtpZihwPD0wKXtpZighQy54Qi5RaShhLCIvIixu
+KSl7aD0iZmlsZTovLy8iCnQ9M31lbHNle2g9ImZpbGU6Ly8iCnQ9Mn1hPWgrQy54Qi5OaihhLG4sZCkK
+cS09MApzPXQtMAptKz1zCmwrPXMKZD1hLmxlbmd0aApwPTcKbz03Cm49N31lbHNlIGlmKG49PT1tKXtn
+PW0rMTsrK2wKYT1DLnhCLmk3KGEsbixtLCIvIik7KytkCm09Z31qPSJmaWxlIn1lbHNlIGlmKEMueEIu
+UWkoYSwiaHR0cCIsMCkpe2lmKHMmJm8rMz09PW4mJkMueEIuUWkoYSwiODAiLG8rMSkpe2Y9bi0zCm0t
+PTMKbC09MwphPUMueEIuaTcoYSxvLG4sIiIpCmQtPTMKbj1mfWo9Imh0dHAifWVsc2Ugaj1lCmVsc2Ug
+aWYocT09PTUmJkoucTAoYSwiaHR0cHMiLDApKXtpZihzJiZvKzQ9PT1uJiZKLnEwKGEsIjQ0MyIsbysx
+KSl7Zj1uLTQKbS09NApsLT00CmE9Si5kZyhhLG8sbiwiIikKZC09MwpuPWZ9aj0iaHR0cHMifWVsc2Ug
+aj1lCms9ITB9fX1lbHNlIGo9ZQppZihrKXtzPWEubGVuZ3RoCmlmKGQ8cyl7YT1KLmxkKGEsMCxkKQpx
+LT0wCnAtPTAKby09MApuLT0wCm0tPTAKbC09MH1yZXR1cm4gbmV3IFAuVWYoYSxxLHAsbyxuLG0sbCxq
+KX1yZXR1cm4gUC5qdihhLDAsZCxxLHAsbyxuLG0sbCxqKX0sCk10OmZ1bmN0aW9uKGEpe0gueShhKQpy
+ZXR1cm4gUC5rdShhLDAsYS5sZW5ndGgsQy54TSwhMSl9LApXWDpmdW5jdGlvbihhKXt2YXIgdD11Lk4K
+cmV0dXJuIEMuTm0uTjAoSC5WTShhLnNwbGl0KCImIiksdS5zKSxQLkZsKHQsdCksbmV3IFAubjEoQy54
+TSksdS5mKX0sCkhoOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwsbD0iSVB2
+NCBhZGRyZXNzIHNob3VsZCBjb250YWluIGV4YWN0bHkgNCBwYXJ0cyIsaz0iZWFjaCBwYXJ0IG11c3Qg
+YmUgaW4gdGhlIHJhbmdlIDAuLjI1NSIsaj1uZXcgUC5jUyhhKSxpPW5ldyBVaW50OEFycmF5KDQpCmZv
+cih0PWkubGVuZ3RoLHM9YixyPXMscT0wO3M8YzsrK3Mpe3A9Qy54Qi5PMihhLHMpCmlmKHAhPT00Nil7
+aWYoKHBeNDgpPjkpai4kMigiaW52YWxpZCBjaGFyYWN0ZXIiLHMpfWVsc2V7aWYocT09PTMpai4kMihs
+LHMpCm89UC5RQShDLnhCLk5qKGEscixzKSxtLG0pCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJu
+IG8ub3MoKQppZihvPjI1NSlqLiQyKGsscikKbj1xKzEKaWYocT49dClyZXR1cm4gSC5PSChpLHEpCmlb
cV09bwpyPXMrMQpxPW59fWlmKHEhPT0zKWouJDIobCxjKQpvPVAuUUEoQy54Qi5OaihhLHIsYyksbSxt
KQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBvLm9zKCkKaWYobz4yNTUpai4kMihrLHIpCmlm
-KHE+PXQpcmV0dXJuIEguayhpLHEpCmlbcV09bwpyZXR1cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLkpU
-KGQsYSkKaWYoYS5sZW5ndGg8MilkLiQxKCJhZGRyZXNzIGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1
-LnQpCmZvcihzPWIscj1zLHE9ITEscD0hMTtzPGEwOysrcyl7bz1DLnhCLk8yKGEscykKaWYobz09PTU4
-KXtpZihzPT09Yil7KytzCmlmKEMueEIuTzIoYSxzKSE9PTU4KWQuJDIoImludmFsaWQgc3RhcnQgY29s
-b24uIixzKQpyPXN9aWYocz09PXIpe2lmKHEpZC4kMigib25seSBvbmUgd2lsZGNhcmQgYDo6YCBpcyBh
-bGxvd2VkIixzKQpDLk5tLkEodCwtMSkKcT0hMH1lbHNlIEMuTm0uQSh0LGMuJDIocixzKSkKcj1zKzF9
-ZWxzZSBpZihvPT09NDYpcD0hMH1pZih0Lmxlbmd0aD09PTApZC4kMSgidG9vIGZldyBwYXJ0cyIpCm49
-cj09PWEwCm09Qy5ObS5ncloodCkKaWYobiYmbSE9PS0xKWQuJDIoImV4cGVjdGVkIGEgcGFydCBhZnRl
-ciBsYXN0IGA6YCIsYTApCmlmKCFuKWlmKCFwKUMuTm0uQSh0LGMuJDIocixhMCkpCmVsc2V7bD1QLkho
-KGEscixhMCkKQy5ObS5BKHQsKGxbMF08PDh8bFsxXSk+Pj4wKQpDLk5tLkEodCwobFsyXTw8OHxsWzNd
-KT4+PjApfWlmKHEpe2lmKHQubGVuZ3RoPjcpZC4kMSgiYW4gYWRkcmVzcyB3aXRoIGEgd2lsZGNhcmQg
-bXVzdCBoYXZlIGxlc3MgdGhhbiA3IHBhcnRzIil9ZWxzZSBpZih0Lmxlbmd0aCE9PTgpZC4kMSgiYW4g
-YWRkcmVzcyB3aXRob3V0IGEgd2lsZGNhcmQgbXVzdCBjb250YWluIGV4YWN0bHkgOCBwYXJ0cyIpCms9
-bmV3IFVpbnQ4QXJyYXkoMTYpCmZvcihtPXQubGVuZ3RoLGo9ay5sZW5ndGgsaT05LW0scz0wLGg9MDtz
-PG07KytzKXtnPXRbc10KaWYoZz09PS0xKWZvcihmPTA7ZjxpOysrZil7aWYoaDwwfHxoPj1qKXJldHVy
-biBILmsoayxoKQprW2hdPTAKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5rKGssZSkKa1tlXT0wCmgrPTJ9
-ZWxzZXtlPUMuam4ud0coZyw4KQppZihoPDB8fGg+PWopcmV0dXJuIEguayhrLGgpCmtbaF09ZQplPWgr
-MQppZihlPj1qKXJldHVybiBILmsoayxlKQprW2VdPWcmMjU1CmgrPTJ9fXJldHVybiBrfSwKanY6ZnVu
-Y3Rpb24oYSxiLGMsZCxlLGYsZyxoLGksail7dmFyIHQscyxyLHEscCxvLG4sbT1udWxsCmlmKGo9PW51
-bGwpaWYoZD5iKWo9UC5QaShhLGIsZCkKZWxzZXtpZihkPT09YilQLlIzKGEsYiwiSW52YWxpZCBlbXB0
-eSBzY2hlbWUiKQpqPSIifWlmKGU+Yil7dD1kKzMKcz10PGU/UC56UihhLHQsZS0xKToiIgpyPVAuT2Uo
-YSxlLGYsITEpCmlmKHR5cGVvZiBmIT09Im51bWJlciIpcmV0dXJuIGYuaCgpCnE9ZisxCmlmKHR5cGVv
-ZiBnIT09Im51bWJlciIpcmV0dXJuIEgucFkoZykKcD1xPGc/UC53QihQLlFBKEoubGQoYSxxLGcpLG5l
-dyBQLmUxKGEsZiksbSksaik6bX1lbHNle3A9bQpyPXAKcz0iIn1vPVAua2EoYSxnLGgsbSxqLHIhPW51
-bGwpCmlmKHR5cGVvZiBoIT09Im51bWJlciIpcmV0dXJuIGguSigpCm49aDxpP1AubGUoYSxoKzEsaSxt
-KTptCnJldHVybiBuZXcgUC5EbihqLHMscixwLG8sbixpPGM/UC50RyhhLGkrMSxjKTptKX0sCndLOmZ1
-bmN0aW9uKGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJuIDgwCmlmKGE9PT0iaHR0cHMiKXJldHVybiA0NDMK
-cmV0dXJuIDB9LApSMzpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAucnIoYyxhLGIpKX0sCmtFOmZ1
-bmN0aW9uKGEsYil7Qy5ObS5VKGEsbmV3IFAuTlkoITEpKX0sCkhOOmZ1bmN0aW9uKGEsYixjKXt2YXIg
-dCxzLHIKZm9yKHQ9SC5xQyhhLGMsbnVsbCxILnQ2KGEpLmMpLHQ9bmV3IEguYTcodCx0LmdrKHQpLHQu
-JHRpLkMoImE3PGFMLkU+IikpO3QubSgpOyl7cz10LmQKcj1QLm51KCdbIiovOjw+P1xcXFx8XScpCnMu
-dG9TdHJpbmcKaWYoSC5tMihzLHIsMCkpe3Q9UC5MNCgiSWxsZWdhbCBjaGFyYWN0ZXIgaW4gcGF0aDog
-IitzKQp0aHJvdyBILmIodCl9fX0sCnJnOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoISg2NTw9YSYmYTw9
-OTApKXQ9OTc8PWEmJmE8PTEyMgplbHNlIHQ9ITAKaWYodClyZXR1cm4KdD1QLkw0KCJJbGxlZ2FsIGRy
-aXZlIGxldHRlciAiK1AuT28oYSkpCnRocm93IEguYih0KX0sCndCOmZ1bmN0aW9uKGEsYil7aWYoYSE9
-bnVsbCYmYT09PVAud0soYikpcmV0dXJuIG51bGwKcmV0dXJuIGF9LApPZTpmdW5jdGlvbihhLGIsYyxk
-KXt2YXIgdCxzLHIscSxwLG8KaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZihiPT09YylyZXR1cm4iIgpp
-ZihDLnhCLk8yKGEsYik9PT05MSl7aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gYy5ITigpCnQ9
-Yy0xCmlmKEMueEIuTzIoYSx0KSE9PTkzKVAuUjMoYSxiLCJNaXNzaW5nIGVuZCBgXWAgdG8gbWF0Y2gg
-YFtgIGluIGhvc3QiKQpzPWIrMQpyPVAudG8oYSxzLHQpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0
-dXJuIHIuSigpCmlmKHI8dCl7cT1yKzEKcD1QLk9BKGEsQy54Qi5RaShhLCIyNSIscSk/ciszOnEsdCwi
-JTI1Iil9ZWxzZSBwPSIiClAuZWcoYSxzLHIpCnJldHVybiBDLnhCLk5qKGEsYixyKS50b0xvd2VyQ2Fz
-ZSgpK3ArIl0ifWlmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKbz1iCmZvcig7bzxj
-OysrbylpZihDLnhCLk8yKGEsbyk9PT01OCl7cj1DLnhCLlhVKGEsIiUiLGIpCmlmKCEocj49YiYmcjxj
-KSlyPWMKaWYocjxjKXtxPXIrMQpwPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixxKT9yKzM6cSxjLCIlMjUi
-KX1lbHNlIHA9IiIKUC5lZyhhLGIscikKcmV0dXJuIlsiK0MueEIuTmooYSxiLHIpK3ArIl0ifXJldHVy
-biBQLk9MKGEsYixjKX0sCnRvOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPUMueEIuWFUoYSwiJSIsYikK
-aWYocz49Yil7aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQp0PXM8Y31lbHNlIHQ9
-ITEKcmV0dXJuIHQ/czpjfSwKT0E6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG4sbSxs
-LGs9ZCE9PSIiP25ldyBQLlJuKGQpOm51bGwKaWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5w
-WShjKQp0PWIKcz10CnI9ITAKZm9yKDt0PGM7KXtxPUMueEIuTzIoYSx0KQppZihxPT09Mzcpe3A9UC5y
-dihhLHQsITApCm89cD09bnVsbAppZihvJiZyKXt0Kz0zCmNvbnRpbnVlfWlmKGs9PW51bGwpaz1uZXcg
-UC5SbigiIikKbj1rLmErPUMueEIuTmooYSxzLHQpCmlmKG8pcD1DLnhCLk5qKGEsdCx0KzMpCmVsc2Ug
-aWYocD09PSIlIilQLlIzKGEsdCwiWm9uZUlEIHNob3VsZCBub3QgY29udGFpbiAlIGFueW1vcmUiKQpr
-LmE9bitwCnQrPTMKcz10CnI9ITB9ZWxzZXtpZihxPDEyNyl7bz1xPj4+NAppZihvPj04KXJldHVybiBI
-LmsoQy5GMyxvKQpvPShDLkYzW29dJjE8PChxJjE1KSkhPT0wfWVsc2Ugbz0hMQppZihvKXtpZihyJiY2
-NTw9cSYmOTA+PXEpe2lmKGs9PW51bGwpaz1uZXcgUC5SbigiIikKaWYoczx0KXtrLmErPUMueEIuTmoo
-YSxzLHQpCnM9dH1yPSExfSsrdH1lbHNle2lmKChxJjY0NTEyKT09PTU1Mjk2JiZ0KzE8Yyl7bT1DLnhC
-Lk8yKGEsdCsxKQppZigobSY2NDUxMik9PT01NjMyMCl7cT02NTUzNnwocSYxMDIzKTw8MTB8bSYxMDIz
-Cmw9Mn1lbHNlIGw9MX1lbHNlIGw9MQppZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9Qy54Qi5O
-aihhLHMsdCkKay5hKz1QLkhIKHEpCnQrPWwKcz10fX19aWYoaz09bnVsbClyZXR1cm4gQy54Qi5Oaihh
-LGIsYykKaWYoczxjKWsuYSs9Qy54Qi5OaihhLHMsYykKbz1rLmEKcmV0dXJuIG8uY2hhckNvZGVBdCgw
-KT09MD9vOm99LApPTDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssagppZih0
-eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj1udWxsCnE9ITAKZm9yKDt0
-PGM7KXtwPUMueEIuTzIoYSx0KQppZihwPT09Mzcpe289UC5ydihhLHQsITApCm49bz09bnVsbAppZihu
-JiZxKXt0Kz0zCmNvbnRpbnVlfWlmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKbT1DLnhCLk5qKGEscyx0
-KQpsPXIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0KaWYobil7bz1DLnhCLk5qKGEsdCx0KzMpCms9M31l
-bHNlIGlmKG89PT0iJSIpe289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpzPXQKcT0hMH1l
-bHNle2lmKHA8MTI3KXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguayhDLmVhLG4pCm49KEMuZWFbbl0m
-MTw8KHAmMTUpKSE9PTB9ZWxzZSBuPSExCmlmKG4pe2lmKHEmJjY1PD1wJiY5MD49cCl7aWYocj09bnVs
-bClyPW5ldyBQLlJuKCIiKQppZihzPHQpe3IuYSs9Qy54Qi5OaihhLHMsdCkKcz10fXE9ITF9Kyt0fWVs
-c2V7aWYocDw9OTMpe249cD4+PjQKaWYobj49OClyZXR1cm4gSC5rKEMuYWssbikKbj0oQy5ha1tuXSYx
-PDwocCYxNSkpIT09MH1lbHNlIG49ITEKaWYobilQLlIzKGEsdCwiSW52YWxpZCBjaGFyYWN0ZXIiKQpl
-bHNle2lmKChwJjY0NTEyKT09PTU1Mjk2JiZ0KzE8Yyl7aj1DLnhCLk8yKGEsdCsxKQppZigoaiY2NDUx
-Mik9PT01NjMyMCl7cD02NTUzNnwocCYxMDIzKTw8MTB8aiYxMDIzCms9Mn1lbHNlIGs9MX1lbHNlIGs9
-MQppZihyPT1udWxsKXI9bmV3IFAuUm4oIiIpCm09Qy54Qi5OaihhLHMsdCkKci5hKz0hcT9tLnRvTG93
-ZXJDYXNlKCk6bQpyLmErPVAuSEgocCkKdCs9awpzPXR9fX19aWYocj09bnVsbClyZXR1cm4gQy54Qi5O
-aihhLGIsYykKaWYoczxjKXttPUMueEIuTmooYSxzLGMpCnIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm19
-bj1yLmEKcmV0dXJuIG4uY2hhckNvZGVBdCgwKT09MD9uOm59LApQaTpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQscyxyLHEKaWYoYj09PWMpcmV0dXJuIiIKaWYoIVAuRXQoSi5yWShhKS5XZChhLGIpKSlQLlIzKGEs
-YiwiU2NoZW1lIG5vdCBzdGFydGluZyB3aXRoIGFscGhhYmV0aWMgY2hhcmFjdGVyIikKZm9yKHQ9Yixz
-PSExO3Q8YzsrK3Qpe3I9Qy54Qi5XZChhLHQpCmlmKHI8MTI4KXtxPXI+Pj40CmlmKHE+PTgpcmV0dXJu
-IEguayhDLm1LLHEpCnE9KEMubUtbcV0mMTw8KHImMTUpKSE9PTB9ZWxzZSBxPSExCmlmKCFxKVAuUjMo
-YSx0LCJJbGxlZ2FsIHNjaGVtZSBjaGFyYWN0ZXIiKQppZig2NTw9ciYmcjw9OTApcz0hMH1hPUMueEIu
-TmooYSxiLGMpCnJldHVybiBQLllhKHM/YS50b0xvd2VyQ2FzZSgpOmEpfSwKWWE6ZnVuY3Rpb24oYSl7
-aWYoYT09PSJodHRwIilyZXR1cm4iaHR0cCIKaWYoYT09PSJmaWxlIilyZXR1cm4iZmlsZSIKaWYoYT09
-PSJodHRwcyIpcmV0dXJuImh0dHBzIgppZihhPT09InBhY2thZ2UiKXJldHVybiJwYWNrYWdlIgpyZXR1
-cm4gYX0sCnpSOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiIiCnJldHVybiBQLnVPKGEs
-YixjLEMudG8sITEpfSwKa2E6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0LHM9ZT09PSJmaWxlIixy
-PXN8fGYscT1hPT1udWxsCmlmKHEmJiEwKXJldHVybiBzPyIvIjoiIgp0PSFxP1AudU8oYSxiLGMsQy5X
-ZCwhMCk6Qy5qTi5FMihkLG5ldyBQLlJaKCksdS5OKS56VigwLCIvIikKaWYodC5sZW5ndGg9PT0wKXtp
-ZihzKXJldHVybiIvIn1lbHNlIGlmKHImJiFDLnhCLm5DKHQsIi8iKSl0PSIvIit0CnJldHVybiBQLkpy
-KHQsZSxmKX0sCkpyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLmxlbmd0aD09PTAKaWYodCYmIWMmJiFD
-LnhCLm5DKGEsIi8iKSlyZXR1cm4gUC53RihhLCF0fHxjKQpyZXR1cm4gUC54ZShhKX0sCmxlOmZ1bmN0
-aW9uKGEsYixjLGQpe3ZhciB0LHM9e30KaWYoYSE9bnVsbCl7aWYoZCE9bnVsbCl0aHJvdyBILmIoUC54
-WSgiQm90aCBxdWVyeSBhbmQgcXVlcnlQYXJhbWV0ZXJzIHNwZWNpZmllZCIpKQpyZXR1cm4gUC51Tyhh
-LGIsYyxDLlZDLCEwKX1pZihkPT1udWxsKXJldHVybiBudWxsCnQ9bmV3IFAuUm4oIiIpCnMuYT0iIgpk
-LlUoMCxuZXcgUC55NShuZXcgUC5NRShzLHQpKSkKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09
-MD9zOnN9LAp0RzpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4gUC51
-TyhhLGIsYyxDLlZDLCEwKX0sCnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG89YisyCmlm
-KG8+PWEubGVuZ3RoKXJldHVybiIlIgp0PUMueEIuTzIoYSxiKzEpCnM9Qy54Qi5PMihhLG8pCnI9SC5v
-byh0KQpxPUgub28ocykKaWYocjwwfHxxPDApcmV0dXJuIiUiCnA9cioxNitxCmlmKHA8MTI3KXtvPUMu
-am4ud0cocCw0KQppZihvPj04KXJldHVybiBILmsoQy5GMyxvKQpvPShDLkYzW29dJjE8PChwJjE1KSkh
-PT0wfWVsc2Ugbz0hMQppZihvKXJldHVybiBILkx3KGMmJjY1PD1wJiY5MD49cD8ocHwzMik+Pj4wOnAp
-CmlmKHQ+PTk3fHxzPj05NylyZXR1cm4gQy54Qi5OaihhLGIsYiszKS50b1VwcGVyQ2FzZSgpCnJldHVy
-biBudWxsfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49IjAxMjM0NTY3ODlBQkNERUYi
-CmlmKGE8MTI4KXt0PW5ldyBBcnJheSgzKQp0LmZpeGVkJGxlbmd0aD1BcnJheQpzPUguVk0odCx1LnQp
-CkMuTm0udChzLDAsMzcpCkMuTm0udChzLDEsQy54Qi5XZChuLGE+Pj40KSkKQy5ObS50KHMsMixDLnhC
-LldkKG4sYSYxNSkpfWVsc2V7aWYoYT4yMDQ3KWlmKGE+NjU1MzUpe3I9MjQwCnE9NH1lbHNle3I9MjI0
-CnE9M31lbHNle3I9MTkyCnE9Mn10PW5ldyBBcnJheSgzKnEpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9
-SC5WTSh0LHUudCkKZm9yKHA9MDstLXEscT49MDtyPTEyOCl7bz1DLmpuLmJmKGEsNipxKSY2M3xyCkMu
-Tm0udChzLHAsMzcpCkMuTm0udChzLHArMSxDLnhCLldkKG4sbz4+PjQpKQpDLk5tLnQocyxwKzIsQy54
-Qi5XZChuLG8mMTUpKQpwKz0zfX1yZXR1cm4gUC5ITShzLDAsbnVsbCl9LAp1TzpmdW5jdGlvbihhLGIs
-YyxkLGUpe3ZhciB0PVAuVWwoYSxiLGMsZCxlKQpyZXR1cm4gdD09bnVsbD9DLnhCLk5qKGEsYixjKTp0
-fSwKVWw6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG89bnVsbCxuPSFlLG09YixsPW0s
-az1vCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQppZih0eXBlb2Yg
-YyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCmlmKCEobTxjKSlicmVhawpjJDA6e3Q9Qy54Qi5PMihh
-LG0pCmlmKHQ8MTI3KXtzPXQ+Pj40CmlmKHM+PTgpcmV0dXJuIEguayhkLHMpCnM9KGRbc10mMTw8KHQm
-MTUpKSE9PTB9ZWxzZSBzPSExCmlmKHMpKyttCmVsc2V7aWYodD09PTM3KXtyPVAucnYoYSxtLCExKQpp
-ZihyPT1udWxsKXttKz0zCmJyZWFrIGMkMH1pZigiJSI9PT1yKXtyPSIlMjUiCnE9MX1lbHNlIHE9M31l
-bHNle2lmKG4paWYodDw9OTMpe3M9dD4+PjQKaWYocz49OClyZXR1cm4gSC5rKEMuYWsscykKcz0oQy5h
-a1tzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKZWxzZSBzPSExCmlmKHMpe1AuUjMoYSxtLCJJbnZh
-bGlkIGNoYXJhY3RlciIpCnE9bwpyPXF9ZWxzZXtpZigodCY2NDUxMik9PT01NTI5Nil7cz1tKzEKaWYo
-czxjKXtwPUMueEIuTzIoYSxzKQppZigocCY2NDUxMik9PT01NjMyMCl7dD02NTUzNnwodCYxMDIzKTw8
-MTB8cCYxMDIzCnE9Mn1lbHNlIHE9MX1lbHNlIHE9MX1lbHNlIHE9MQpyPVAuSEgodCl9fWlmKGs9PW51
-bGwpaz1uZXcgUC5SbigiIikKay5hKz1DLnhCLk5qKGEsbCxtKQprLmErPUguZChyKQppZih0eXBlb2Yg
-cSE9PSJudW1iZXIiKXJldHVybiBILnBZKHEpCm0rPXEKbD1tfX19aWYoaz09bnVsbClyZXR1cm4gbwpp
-Zih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkooKQppZihsPGMpay5hKz1DLnhCLk5qKGEsbCxj
-KQpuPWsuYQpyZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0wP246bn0sCnlCOmZ1bmN0aW9uKGEpe2lmKEMu
-eEIubkMoYSwiLiIpKXJldHVybiEwCnJldHVybiBDLnhCLk9ZKGEsIi8uIikhPT0tMX0sCnhlOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuCmlmKCFQLnlCKGEpKXJldHVybiBhCnQ9SC5WTShbXSx1LnMp
-CmZvcihzPWEuc3BsaXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ape289c1twXQppZihK
-LlJNKG8sIi4uIikpe249dC5sZW5ndGgKaWYobiE9PTApe2lmKDA+PW4pcmV0dXJuIEguayh0LC0xKQp0
-LnBvcCgpCmlmKHQubGVuZ3RoPT09MClDLk5tLkEodCwiIil9cT0hMH1lbHNlIGlmKCIuIj09PW8pcT0h
-MAplbHNle0MuTm0uQSh0LG8pCnE9ITF9fWlmKHEpQy5ObS5BKHQsIiIpCnJldHVybiBDLk5tLnpWKHQs
-Ii8iKX0sCndGOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvCmlmKCFQLnlCKGEpKXJldHVybiFi
-P1AuQzEoYSk6YQp0PUguVk0oW10sdS5zKQpmb3Iocz1hLnNwbGl0KCIvIikscj1zLmxlbmd0aCxxPSEx
-LHA9MDtwPHI7KytwKXtvPXNbcF0KaWYoIi4uIj09PW8paWYodC5sZW5ndGghPT0wJiZDLk5tLmdyWih0
-KSE9PSIuLiIpe2lmKDA+PXQubGVuZ3RoKXJldHVybiBILmsodCwtMSkKdC5wb3AoKQpxPSEwfWVsc2V7
-Qy5ObS5BKHQsIi4uIikKcT0hMX1lbHNlIGlmKCIuIj09PW8pcT0hMAplbHNle0MuTm0uQSh0LG8pCnE9
-ITF9fXM9dC5sZW5ndGgKaWYocyE9PTApaWYocz09PTEpe2lmKDA+PXMpcmV0dXJuIEguayh0LDApCnM9
-dFswXS5sZW5ndGg9PT0wfWVsc2Ugcz0hMQplbHNlIHM9ITAKaWYocylyZXR1cm4iLi8iCmlmKHF8fEMu
-Tm0uZ3JaKHQpPT09Ii4uIilDLk5tLkEodCwiIikKaWYoIWIpe2lmKDA+PXQubGVuZ3RoKXJldHVybiBI
-LmsodCwwKQpDLk5tLnQodCwwLFAuQzEodFswXSkpfXJldHVybiBDLk5tLnpWKHQsIi8iKX0sCkMxOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscixxPWEubGVuZ3RoCmlmKHE+PTImJlAuRXQoSi5ReihhLDApKSlmb3Io
-dD0xO3Q8cTsrK3Qpe3M9Qy54Qi5XZChhLHQpCmlmKHM9PT01OClyZXR1cm4gQy54Qi5OaihhLDAsdCkr
-IiUzQSIrQy54Qi55bihhLHQrMSkKaWYoczw9MTI3KXtyPXM+Pj40CmlmKHI+PTgpcmV0dXJuIEguayhD
-Lm1LLHIpCnI9KEMubUtbcl0mMTw8KHMmMTUpKT09PTB9ZWxzZSByPSEwCmlmKHIpYnJlYWt9cmV0dXJu
-IGF9LAptbjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmdGaigpLHA9cS5sZW5ndGgKaWYocD4wJiZK
-LkgocVswXSk9PT0yJiZKLmE2KHFbMF0sMSk9PT01OCl7aWYoMD49cClyZXR1cm4gSC5rKHEsMCkKUC5y
-ZyhKLmE2KHFbMF0sMCksITEpClAuSE4ocSwhMSwxKQp0PSEwfWVsc2V7UC5ITihxLCExLDApCnQ9ITF9
-cz1hLmd0VCgpJiYhdD8iXFwiOiIiCmlmKGEuZ2NqKCkpe3I9YS5nSmYoYSkKaWYoci5sZW5ndGghPT0w
-KXM9cysiXFwiK3IrIlxcIn1zPVAudmcocyxxLCJcXCIpCnA9dCYmcD09PTE/cysiXFwiOnMKcmV0dXJu
-IHAuY2hhckNvZGVBdCgwKT09MD9wOnB9LApJaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgpmb3IodD0w
-LHM9MDtzPDI7KytzKXtyPUMueEIuV2QoYSxiK3MpCmlmKDQ4PD1yJiZyPD01Nyl0PXQqMTYrci00OApl
-bHNle3J8PTMyCmlmKDk3PD1yJiZyPD0xMDIpdD10KjE2K3ItODcKZWxzZSB0aHJvdyBILmIoUC54WSgi
-SW52YWxpZCBVUkwgZW5jb2RpbmciKSl9fXJldHVybiB0fSwKa3U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2
-YXIgdCxzLHIscSxwPUouclkoYSksbz1iCndoaWxlKCEwKXtpZighKG88Yykpe3Q9ITAKYnJlYWt9cz1w
-LldkKGEsbykKaWYoczw9MTI3KWlmKHMhPT0zNylyPWUmJnM9PT00MwplbHNlIHI9ITAKZWxzZSByPSEw
-CmlmKHIpe3Q9ITEKYnJlYWt9KytvfWlmKHQpe2lmKEMueE0hPT1kKXI9ITEKZWxzZSByPSEwCmlmKHIp
-cmV0dXJuIHAuTmooYSxiLGMpCmVsc2UgcT1uZXcgSC5xaihwLk5qKGEsYixjKSl9ZWxzZXtxPUguVk0o
-W10sdS50KQpmb3Iobz1iO288YzsrK28pe3M9cC5XZChhLG8pCmlmKHM+MTI3KXRocm93IEguYihQLnhZ
-KCJJbGxlZ2FsIHBlcmNlbnQgZW5jb2RpbmcgaW4gVVJJIikpCmlmKHM9PT0zNyl7aWYobyszPmEubGVu
-Z3RoKXRocm93IEguYihQLnhZKCJUcnVuY2F0ZWQgVVJJIikpCkMuTm0uQShxLFAuSWgoYSxvKzEpKQpv
-Kz0yfWVsc2UgaWYoZSYmcz09PTQzKUMuTm0uQShxLDMyKQplbHNlIEMuTm0uQShxLHMpfX11LkwuYShx
-KQpyZXR1cm4gbmV3IFAuR1koITEpLldKKHEpfSwKRXQ6ZnVuY3Rpb24oYSl7dmFyIHQ9YXwzMgpyZXR1
-cm4gOTc8PXQmJnQ8PTEyMn0sCktEOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9
-IkludmFsaWQgTUlNRSB0eXBlIixrPUguVk0oW2ItMV0sdS50KQpmb3IodD1hLmxlbmd0aCxzPWIscj0t
-MSxxPW51bGw7czx0Oysrcyl7cT1DLnhCLldkKGEscykKaWYocT09PTQ0fHxxPT09NTkpYnJlYWsKaWYo
-cT09PTQ3KXtpZihyPDApe3I9cwpjb250aW51ZX10aHJvdyBILmIoUC5ycihsLGEscykpfX1pZihyPDAm
-JnM+Yil0aHJvdyBILmIoUC5ycihsLGEscykpCmZvcig7cSE9PTQ0Oyl7Qy5ObS5BKGsscyk7KytzCmZv
-cihwPS0xO3M8dDsrK3Mpe3E9Qy54Qi5XZChhLHMpCmlmKHE9PT02MSl7aWYocDwwKXA9c31lbHNlIGlm
-KHE9PT01OXx8cT09PTQ0KWJyZWFrfWlmKHA+PTApQy5ObS5BKGsscCkKZWxzZXtvPUMuTm0uZ3JaKGsp
-CmlmKHEhPT00NHx8cyE9PW8rN3x8IUMueEIuUWkoYSwiYmFzZTY0IixvKzEpKXRocm93IEguYihQLnJy
-KCJFeHBlY3RpbmcgJz0nIixhLHMpKQpicmVha319Qy5ObS5BKGsscykKbj1zKzEKaWYoKGsubGVuZ3Ro
-JjEpPT09MSlhPUMuaDkueXIoMCxhLG4sdCkKZWxzZXttPVAuVWwoYSxuLHQsQy5WQywhMCkKaWYobSE9
-bnVsbClhPUMueEIuaTcoYSxuLHQsbSl9cmV0dXJuIG5ldyBQLlBFKGEsayxjKX0sCktOOmZ1bmN0aW9u
-KCl7dmFyIHQ9IjAxMjM0NTY3ODlBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1u
-b3BxcnN0dXZ3eHl6LS5ffiEkJicoKSorLDs9IixzPSIuIixyPSI6IixxPSIvIixwPSI/IixvPSIjIixu
-PXUuZ2MsbT1QLmRIKDIyLG5ldyBQLnEzKCksITAsbiksbD1uZXcgUC55SShtKSxrPW5ldyBQLmM2KCks
-aj1uZXcgUC5xZCgpLGk9bi5hKGwuJDIoMCwyMjUpKQprLiQzKGksdCwxKQprLiQzKGkscywxNCkKay4k
-MyhpLHIsMzQpCmsuJDMoaSxxLDMpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQy
-KDE0LDIyNSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxzLDE1KQprLiQzKGksciwzNCkKay4kMyhpLHEsMjM0
-KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxNSwyMjUpKQprLiQzKGksdCwx
-KQprLiQzKGksIiUiLDIyNSkKay4kMyhpLHIsMzQpCmsuJDMoaSxxLDkpCmsuJDMoaSxwLDE3MikKay4k
-MyhpLG8sMjA1KQppPW4uYShsLiQyKDEsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLHIsMzQpCmsuJDMo
-aSxxLDEwKQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigyLDIzNSkpCmsuJDMo
-aSx0LDEzOSkKay4kMyhpLHEsMTMxKQprLiQzKGkscywxNDYpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
-MjA1KQppPW4uYShsLiQyKDMsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDY4KQprLiQzKGkscywx
-OCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNCwyMjkpKQprLiQzKGksdCw1
-KQpqLiQzKGksIkFaIiwyMjkpCmsuJDMoaSxyLDEwMikKay4kMyhpLCJAIiw2OCkKay4kMyhpLCJbIiwy
-MzIpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNSwy
-MjkpKQprLiQzKGksdCw1KQpqLiQzKGksIkFaIiwyMjkpCmsuJDMoaSxyLDEwMikKay4kMyhpLCJAIiw2
-OCkKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMig2LDIz
-MSkpCmouJDMoaSwiMTkiLDcpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcy
-KQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNywyMzEpKQpqLiQzKGksIjA5Iiw3KQprLiQzKGksIkAi
-LDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQprLiQzKG4uYShsLiQy
-KDgsOCkpLCJdIiw1KQppPW4uYShsLiQyKDksMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE2KQpr
-LiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDE2LDIzNSkp
-CmsuJDMoaSx0LDExKQprLiQzKGkscywxNykKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIpCmsuJDMo
-aSxvLDIwNSkKaT1uLmEobC4kMigxNywyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHEsOSkKay4kMyhp
-LHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoMTAsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMo
-aSxzLDE4KQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQy
-KDE4LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscywxOSkKay4kMyhpLHEsMjM0KQprLiQzKGkscCwx
-NzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxOSwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHEs
-MjM0KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxMSwyMzUpKQprLiQzKGks
-dCwxMSkKay4kMyhpLHEsMTApCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDEy
-LDIzNikpCmsuJDMoaSx0LDEyKQprLiQzKGkscCwxMikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDEz
-LDIzNykpCmsuJDMoaSx0LDEzKQprLiQzKGkscCwxMykKai4kMyhuLmEobC4kMigyMCwyNDUpKSwiYXoi
-LDIxKQpsPW4uYShsLiQyKDIxLDI0NSkpCmouJDMobCwiYXoiLDIxKQpqLiQzKGwsIjA5IiwyMSkKay4k
-MyhsLCIrLS4iLDIxKQpyZXR1cm4gbX0sClVCOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEs
-cCxvPSQudlooKQpmb3IodD1KLnJZKGEpLHM9YjtzPGM7KytzKXtpZihkPDB8fGQ+PW8ubGVuZ3RoKXJl
-dHVybiBILmsobyxkKQpyPW9bZF0KcT10LldkKGEscyleOTYKaWYocT45NSlxPTMxCmlmKHE+PXIubGVu
-Z3RoKXJldHVybiBILmsocixxKQpwPXJbcV0KZD1wJjMxCkMuTm0udChlLHA+Pj41LHMpfXJldHVybiBk
-fSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7
-fSwKaVA6ZnVuY3Rpb24gaVAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0aW9uIENQKCl7
-fSwKWFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCkxLOmZ1bmN0
-aW9uIExLKCl7fSwKQVQ6ZnVuY3Rpb24gQVQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmM9YwpfLmQ9ZH0sCmJKOmZ1bmN0aW9uIGJKKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uZT1hCl8u
-Zj1iCl8uYT1jCl8uYj1kCl8uYz1lCl8uZD1mfSwKZVk6ZnVuY3Rpb24gZVkoYSxiLGMsZCxlKXt2YXIg
-Xz10aGlzCl8uZj1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKbXA6ZnVuY3Rpb24gbXAoYSxiLGMs
-ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCnViOmZ1bmN0aW9uIHViKGEpe3Ro
-aXMuYT1hfSwKZHM6ZnVuY3Rpb24gZHMoYSl7dGhpcy5hPWF9LApsajpmdW5jdGlvbiBsaihhKXt0aGlz
-LmE9YX0sClVWOmZ1bmN0aW9uIFVWKGEpe3RoaXMuYT1hfSwKazU6ZnVuY3Rpb24gazUoKXt9LApLWTpm
-dW5jdGlvbiBLWSgpe30sCnQ3OmZ1bmN0aW9uIHQ3KGEpe3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24gQ0Qo
-YSl7dGhpcy5hPWF9LAphRTpmdW5jdGlvbiBhRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
-PWN9LApFSDpmdW5jdGlvbiBFSCgpe30sCklmOmZ1bmN0aW9uIElmKCl7fSwKTHk6ZnVuY3Rpb24gTHko
-KXt9LApBbjpmdW5jdGlvbiBBbigpe30sCnpNOmZ1bmN0aW9uIHpNKCl7fSwKWjA6ZnVuY3Rpb24gWjAo
-KXt9LApOMzpmdW5jdGlvbiBOMyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCmM4
-OmZ1bmN0aW9uIGM4KCl7fSwKbGY6ZnVuY3Rpb24gbGYoKXt9LApNaDpmdW5jdGlvbiBNaCgpe30sCk9k
-OmZ1bmN0aW9uIE9kKCl7fSwKaWI6ZnVuY3Rpb24gaWIoKXt9LAp4dTpmdW5jdGlvbiB4dSgpe30sCkd6
-OmZ1bmN0aW9uIEd6KCl7fSwKWmQ6ZnVuY3Rpb24gWmQoKXt9LApxVTpmdW5jdGlvbiBxVSgpe30sClJu
-OmZ1bmN0aW9uIFJuKGEpe3RoaXMuYT1hfSwKR0Q6ZnVuY3Rpb24gR0QoKXt9LApuMTpmdW5jdGlvbiBu
-MShhKXt0aGlzLmE9YX0sCmNTOmZ1bmN0aW9uIGNTKGEpe3RoaXMuYT1hfSwKVkM6ZnVuY3Rpb24gVkMo
-YSl7dGhpcy5hPWF9LApKVDpmdW5jdGlvbiBKVChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKRG46ZnVu
-Y3Rpb24gRG4oYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApf
-LmU9ZQpfLmY9ZgpfLnI9ZwpfLlE9Xy56PV8ueT1fLng9bnVsbH0sCmUxOmZ1bmN0aW9uIGUxKGEsYil7
-dGhpcy5hPWEKdGhpcy5iPWJ9LApOWTpmdW5jdGlvbiBOWShhKXt0aGlzLmE9YX0sClJaOmZ1bmN0aW9u
-IFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9u
-IHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRo
-aXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2
-OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxk
-LGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5y
-PWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlz
-Cl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1u
-dWxsfSwKbVI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscAppZihhPT1udWxsKXJldHVybiBudWxsCnQ9
-UC5GbCh1Lk4sdS56KQpzPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGEpCmZvcihyPXMubGVuZ3Ro
-LHE9MDtxPHMubGVuZ3RoO3MubGVuZ3RoPT09cnx8KDAsSC5saykocyksKytxKXtwPUguYyhzW3FdKQp0
-LnQoMCxwLGFbcF0pfXJldHVybiB0fSwKaTY6ZnVuY3Rpb24gaTYoKXt9LApqZzpmdW5jdGlvbiBqZyhh
-LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
-Yn0sCmFKOmZ1bmN0aW9uIGFKKCl7fSwKSzU6ZnVuY3Rpb24gSzUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
-Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp6ZzpmdW5jdGlvbiB6Zyhh
-LGIpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz0hMX0sCmRNOmZ1bmN0aW9uIGRNKCl7fSwKR0U6ZnVu
-Y3Rpb24gR0UoYSl7dGhpcy5hPWF9LApONzpmdW5jdGlvbiBONyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
-fSwKdVE6ZnVuY3Rpb24gdVEoKXt9LApXMjpmdW5jdGlvbiBXMigpe30sCmUzOmZ1bmN0aW9uIGUzKCl7
-fSwKaEY6ZnVuY3Rpb24gaEYoKXt9LApCVjpmdW5jdGlvbiBCVigpe30sClI0OmZ1bmN0aW9uKGEsYixj
-LGQpe3ZhciB0LHMscgpILkU5KGIpCnUuai5hKGQpCmlmKEgub1QoYikpe3Q9W2NdCkMuTm0uRlYodCxk
-KQpkPXR9cz11LnoKcj1QLkNIKEouTTEoZCxQLncwKCkscyksITAscykKdS5aLmEoYSkKcmV0dXJuIFAu
-d1koSC5FayhhLHIsbnVsbCkpfSwKRG06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CnRyeXtpZihPYmplY3Qu
-aXNFeHRlbnNpYmxlKGEpJiYhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsYikp
-e09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLGIse3ZhbHVlOmN9KQpyZXR1cm4hMH19Y2F0Y2godCl7SC5S
-dSh0KX1yZXR1cm4hMX0sCk9tOmZ1bmN0aW9uKGEsYil7aWYoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Q
-cm9wZXJ0eS5jYWxsKGEsYikpcmV0dXJuIGFbYl0KcmV0dXJuIG51bGx9LAp3WTpmdW5jdGlvbihhKXtp
-ZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmluZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8SC5yUShhKSly
-ZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJuIGEK
-aWYodS5ELmIoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuaVApcmV0dXJuIEgubzIoYSkKaWYo
-dS5aLmIoYSkpcmV0dXJuIFAuYjMoYSwiJGRhcnRfanNGdW5jdGlvbiIsbmV3IFAuUEMoKSkKcmV0dXJu
-IFAuYjMoYSwiXyRkYXJ0X2pzT2JqZWN0IixuZXcgUC5tdCgkLmtJKCkpKX0sCmIzOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdD1QLk9tKGEsYikKaWYodD09bnVsbCl7dD1jLiQxKGEpClAuRG0oYSxiLHQpfXJldHVy
-biB0fSwKTDc6ZnVuY3Rpb24oYSl7dmFyIHQscwppZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmluZyJ8
-fHR5cGVvZiBhPT0ibnVtYmVyInx8dHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gYQplbHNlIGlmKGEg
-aW5zdGFuY2VvZiBPYmplY3QmJkguUjkoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2Jq
-ZWN0JiZ1LkQuYihhKSlyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBEYXRlKXt0PUguV1koYS5n
-ZXRUaW1lKCkpCnM9bmV3IFAuaVAodCwhMSkKcy5Yayh0LCExKQpyZXR1cm4gc31lbHNlIGlmKGEuY29u
-c3RydWN0b3I9PT0kLmtJKCkpcmV0dXJuIGEubwplbHNlIHJldHVybiBQLk5EKGEpfSwKTkQ6ZnVuY3Rp
-b24oYSl7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAuaVEoYSwkLndRKCksbmV3IFAuTnoo
-KSkKaWYoYSBpbnN0YW5jZW9mIEFycmF5KXJldHVybiBQLmlRKGEsJC5DcigpLG5ldyBQLm5wKCkpCnJl
-dHVybiBQLmlRKGEsJC5DcigpLG5ldyBQLlV0KCkpfSwKaVE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PVAu
-T20oYSxiKQppZih0PT1udWxsfHwhKGEgaW5zdGFuY2VvZiBPYmplY3QpKXt0PWMuJDEoYSkKUC5EbShh
-LGIsdCl9cmV0dXJuIHR9LApQQzpmdW5jdGlvbiBQQygpe30sCm10OmZ1bmN0aW9uIG10KGEpe3RoaXMu
-YT1hfSwKTno6ZnVuY3Rpb24gTnooKXt9LApucDpmdW5jdGlvbiBucCgpe30sClV0OmZ1bmN0aW9uIFV0
-KCl7fSwKRTQ6ZnVuY3Rpb24gRTQoYSl7dGhpcy5hPWF9LApyNzpmdW5jdGlvbiByNyhhKXt0aGlzLmE9
-YX0sClR6OmZ1bmN0aW9uIFR6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmNvOmZ1bmN0aW9uIGNv
-KCl7fSwKVTg6ZnVuY3Rpb24oYSxiKXt2YXIgdD1uZXcgUC52cygkLlgzLGIuQygidnM8MD4iKSkscz1u
-ZXcgUC5aZih0LGIuQygiWmY8MD4iKSkKYS50aGVuKEgudFIobmV3IFAudksocyxiKSwxKSxILnRSKG5l
-dyBQLnBVKHMpLDEpKQpyZXR1cm4gdH0sCnZLOmZ1bmN0aW9uIHZLKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApwVTpmdW5jdGlvbiBwVShhKXt0aGlzLmE9YX0sCklOOmZ1bmN0aW9uIElOKCl7fSwKdG46ZnVu
-Y3Rpb24gdG4oKXt9LAp1ajpmdW5jdGlvbiB1aigpe30sCngwOmZ1bmN0aW9uIHgwKCl7fSwKcTY6ZnVu
-Y3Rpb24gcTYoKXt9LAp1UDpmdW5jdGlvbiB1UCgpe30sCkxaOmZ1bmN0aW9uIExaKCl7fSwKRUQ6ZnVu
-Y3Rpb24gRUQoKXt9LApuZDpmdW5jdGlvbiBuZCgpe30sCktxOmZ1bmN0aW9uIEtxKCl7fSwKS2U6ZnVu
-Y3Rpb24gS2UoYSl7dGhpcy5hPWF9LApkNTpmdW5jdGlvbiBkNSgpe30sCnpZOmZ1bmN0aW9uIHpZKCl7
-fSwKTkM6ZnVuY3Rpb24gTkMoKXt9LApmVTpmdW5jdGlvbiBmVSgpe30sCkdDOmZ1bmN0aW9uIEdDKCl7
-fSwKakc6ZnVuY3Rpb24gakcoKXt9LApqUzpmdW5jdGlvbiBqUygpe30sCnhXOmZ1bmN0aW9uIHhXKCl7
-fSwKZFM6ZnVuY3Rpb24gZFMoKXt9LAp3ajpmdW5jdGlvbiB3aigpe30sCk1ZOmZ1bmN0aW9uIE1ZKCl7
-fSwKbjY6ZnVuY3Rpb24gbjYoKXt9LApyMjpmdW5jdGlvbiByMigpe30sCnJPOmZ1bmN0aW9uIHJPKCl7
-fSwKRFg6ZnVuY3Rpb24gRFgoKXt9LApxZjpmdW5jdGlvbiBxZihhKXt0aGlzLmE9YX0sCmZvOmZ1bmN0
-aW9uIGZvKCl7fSwKVjg6ZnVuY3Rpb24gVjgoKXt9LApHbjpmdW5jdGlvbiBHbigpe30sClUzOmZ1bmN0
-aW9uIFUzKCl7fSwKRm46ZnVuY3Rpb24gRm4oKXt9LAptbzpmdW5jdGlvbiBtbygpe30sCktnOmZ1bmN0
-aW9uIEtnKCl7fX0sVz17CngzOmZ1bmN0aW9uKCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7
-cmV0dXJuIGRvY3VtZW50fSwKVTk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PWRvY3VtZW50LmJvZHkscz0o
-dCYmQy5SWSkucjYodCxhLGIsYykKcy50b1N0cmluZwp0PXUuYWMKdD1uZXcgSC5VNShuZXcgVy5lNyhz
-KSx0LkMoImEyKGxELkUpIikuYShuZXcgVy5DdigpKSx0LkMoIlU1PGxELkU+IikpCnJldHVybiB1Lmgu
-YSh0LmdyOCh0KSl9LApyUzpmdW5jdGlvbihhKXt2YXIgdCxzLHI9ImVsZW1lbnQgdGFnIHVuYXZhaWxh
-YmxlIgp0cnl7dD1KLlJFKGEpCmlmKHR5cGVvZiB0LmducyhhKT09InN0cmluZyIpcj10LmducyhhKX1j
-YXRjaChzKXtILlJ1KHMpfXJldHVybiByfSwKcUQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPW5l
-dyBQLnZzKCQuWDMsdS5hbykscD1uZXcgUC5aZihxLHUuYmopLG89bmV3IFhNTEh0dHBSZXF1ZXN0KCkK
-Qy5EdC5lbyhvLGI9PW51bGw/IkdFVCI6YixhLCEwKQpjLlUoMCxuZXcgVy5iVShvKSkKdD11LmFuCnM9
-dC5hKG5ldyBXLmhIKG8scCkpCnUuTS5hKG51bGwpCnI9dS5wClcuSkUobywibG9hZCIscywhMSxyKQpX
-LkpFKG8sImVycm9yIix0LmEocC5nWUooKSksITEscikKby5zZW5kKCkKcmV0dXJuIHF9LApDMDpmdW5j
-dGlvbihhLGIpe2E9NTM2ODcwOTExJmErYgphPTUzNjg3MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0
-dXJuIGFeYT4+PjZ9LApyRTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1XLkMwKFcuQzAoVy5DMChXLkMw
-KDAsYSksYiksYyksZCkscz01MzY4NzA5MTEmdCsoKDY3MTA4ODYzJnQpPDwzKQpzXj1zPj4+MTEKcmV0
-dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1KX0sClROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-PWEuY2xhc3NMaXN0CmZvcih0PWIubGVuZ3RoLHM9MDtzPGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAs
-SC5saykoYiksKytzKXIuYWRkKGJbc10pfSwKSkU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1XLmFG
-KG5ldyBXLnZOKGMpLHUuQikKaWYodCE9bnVsbCYmITApSi5kWihhLGIsdCwhMSkKcmV0dXJuIG5ldyBX
-LnhDKGEsYix0LCExLGUuQygieEM8MD4iKSl9LApUdzpmdW5jdGlvbihhKXt2YXIgdD1kb2N1bWVudC5j
-cmVhdGVFbGVtZW50KCJhIikscz1uZXcgVy5tayh0LHdpbmRvdy5sb2NhdGlvbikKcz1uZXcgVy5KUShz
-KQpzLkNZKGEpCnJldHVybiBzfSwKVXc6ZnVuY3Rpb24oYSxiLGMsZCl7dS5oLmEoYSkKSC5jKGIpCkgu
-YyhjKQp1LmNyLmEoZCkKcmV0dXJuITB9LApuWjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdS5o
-LmEoYSkKSC5jKGIpCkguYyhjKQp0PXUuY3IuYShkKS5hCnM9dC5hCnMuaHJlZj1jCnI9cy5ob3N0bmFt
-ZQp0PXQuYgppZighKHI9PXQuaG9zdG5hbWUmJnMucG9ydD09dC5wb3J0JiZzLnByb3RvY29sPT10LnBy
-b3RvY29sKSlpZihyPT09IiIpaWYocy5wb3J0PT09IiIpe3Q9cy5wcm90b2NvbAp0PXQ9PT0iOiJ8fHQ9
-PT0iIn1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMApyZXR1cm4gdH0sCkJsOmZ1bmN0aW9uKCl7
-dmFyIHQ9dS5OLHM9UC50TShDLlF4LHQpLHI9dS5kRy5hKG5ldyBXLklBKCkpLHE9SC5WTShbIlRFTVBM
-QVRFIl0sdS5zKQp0PW5ldyBXLmN0KHMsUC5Mcyh0KSxQLkxzKHQpLFAuTHModCksbnVsbCkKdC5DWShu
-dWxsLG5ldyBILmxKKEMuUXgscix1LmR2KSxxLG51bGwpCnJldHVybiB0fSwKUHY6ZnVuY3Rpb24oYSl7
-aWYoYT09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4gVy5QMShhKX0sCnFjOmZ1bmN0aW9uKGEpe3ZhciB0
-CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoInBvc3RNZXNzYWdlIiBpbiBhKXt0PVcuUDEoYSkKcmV0
-dXJuIHR9ZWxzZSByZXR1cm4gdS5hUy5hKGEpfSwKUDE6ZnVuY3Rpb24oYSl7aWYoYT09PXdpbmRvdyly
-ZXR1cm4gdS5jaS5hKGEpCmVsc2UgcmV0dXJuIG5ldyBXLmRXKGEpfSwKelg6ZnVuY3Rpb24oYSl7aWYo
-YT09PXdpbmRvdy5sb2NhdGlvbilyZXR1cm4gYQplbHNlIHJldHVybiBuZXcgVy5GYigpfSwKYUY6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdD0kLlgzCmlmKHQ9PT1DLk5VKXJldHVybiBhCnJldHVybiB0LlB5KGEsYil9
-LApxRTpmdW5jdGlvbiBxRSgpe30sClllOmZ1bmN0aW9uIFllKCl7fSwKR2g6ZnVuY3Rpb24gR2goKXt9
-LApmWTpmdW5jdGlvbiBmWSgpe30sCm5COmZ1bmN0aW9uIG5CKCl7fSwKQXo6ZnVuY3Rpb24gQXooKXt9
-LApQVTpmdW5jdGlvbiBQVSgpe30sClFQOmZ1bmN0aW9uIFFQKCl7fSwKSUY6ZnVuY3Rpb24gSUYoKXt9
-LApueDpmdW5jdGlvbiBueCgpe30sClJkOmZ1bmN0aW9uIFJkKCl7fSwKa1I6ZnVuY3Rpb24ga1IoKXt9
-LApUZjpmdW5jdGlvbiBUZigpe30sCmx3OmZ1bmN0aW9uIGx3KCl7fSwKb0o6ZnVuY3Rpb24gb0ooKXt9
-LAppZDpmdW5jdGlvbiBpZCgpe30sCkJ3OmZ1bmN0aW9uIEJ3KCl7fSwKbzQ6ZnVuY3Rpb24gbzQoKXt9
-LApIUzpmdW5jdGlvbiBIUygpe30sClZvOmZ1bmN0aW9uIFZvKCl7fSwKRmg6ZnVuY3Rpb24gRmgoKXt9
-LApjeDpmdW5jdGlvbiBjeCgpe30sClNiOmZ1bmN0aW9uIFNiKCl7fSwKUUY6ZnVuY3Rpb24gUUYoKXt9
-LApOaDpmdW5jdGlvbiBOaCgpe30sCkZ2OmZ1bmN0aW9uIEZ2KCl7fSwKSUI6ZnVuY3Rpb24gSUIoKXt9
-LApZbDpmdW5jdGlvbiBZbCgpe30sCm43OmZ1bmN0aW9uIG43KCl7fSwKd3o6ZnVuY3Rpb24gd3ooYSxi
-KXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY3Y6ZnVuY3Rpb24gY3YoKXt9LApDdjpmdW5jdGlvbiBDdigp
-e30sCmVhOmZ1bmN0aW9uIGVhKCl7fSwKRDA6ZnVuY3Rpb24gRDAoKXt9LApUNTpmdW5jdGlvbiBUNSgp
-e30sClhWOmZ1bmN0aW9uIFhWKCl7fSwKd0o6ZnVuY3Rpb24gd0ooKXt9LApoNDpmdW5jdGlvbiBoNCgp
-e30sCkdPOmZ1bmN0aW9uIEdPKCl7fSwKSkM6ZnVuY3Rpb24gSkMoKXt9LApicjpmdW5jdGlvbiBicigp
-e30sCnhuOmZ1bmN0aW9uIHhuKCl7fSwKVmI6ZnVuY3Rpb24gVmIoKXt9LApmSjpmdW5jdGlvbiBmSigp
-e30sCmJVOmZ1bmN0aW9uIGJVKGEpe3RoaXMuYT1hfSwKaEg6ZnVuY3Rpb24gaEgoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCndhOmZ1bmN0aW9uIHdhKCl7fSwKU2c6ZnVuY3Rpb24gU2coKXt9LApKSzpmdW5j
-dGlvbiBKSygpe30sCkhMOmZ1bmN0aW9uIEhMKCl7fSwKd1A6ZnVuY3Rpb24gd1AoKXt9LAp1ODpmdW5j
-dGlvbiB1OCgpe30sCno2OmZ1bmN0aW9uIHo2KCl7fSwKQ2Y6ZnVuY3Rpb24gQ2YoKXt9LApRYjpmdW5j
-dGlvbiBRYigpe30sClMwOmZ1bmN0aW9uIFMwKCl7fSwKRkE6ZnVuY3Rpb24gRkEoYSl7dGhpcy5hPWF9
-LAp6MjpmdW5jdGlvbiB6Migpe30sCnVxOmZ1bmN0aW9uIHVxKGEpe3RoaXMuYT1hfSwKQVc6ZnVuY3Rp
-b24gQVcoKXt9LApETTpmdW5jdGlvbiBETSgpe30sCk9LOmZ1bmN0aW9uIE9LKCl7fSwKZTc6ZnVuY3Rp
-b24gZTcoYSl7dGhpcy5hPWF9LAp1SDpmdW5jdGlvbiB1SCgpe30sCkJIOmZ1bmN0aW9uIEJIKCl7fSwK
-UWw6ZnVuY3Rpb24gUWwoKXt9LApHWDpmdW5jdGlvbiBHWCgpe30sClNOOmZ1bmN0aW9uIFNOKCl7fSwK
-SEQ6ZnVuY3Rpb24gSEQoKXt9LApjbDpmdW5jdGlvbiBjbCgpe30sCkV2OmZ1bmN0aW9uIEV2KCl7fSwK
-THI6ZnVuY3Rpb24gTHIoKXt9LApLUjpmdW5jdGlvbiBLUigpe30sCmV3OmZ1bmN0aW9uIGV3KCl7fSwK
-cDg6ZnVuY3Rpb24gcDgoKXt9LAppaTpmdW5jdGlvbiBpaShhKXt0aGlzLmE9YX0sCmxwOmZ1bmN0aW9u
-IGxwKCl7fSwKU1Y6ZnVuY3Rpb24gU1YoKXt9LApNazpmdW5jdGlvbiBNaygpe30sClk0OmZ1bmN0aW9u
-IFk0KCl7fSwKTm46ZnVuY3Rpb24gTm4oKXt9LApsODpmdW5jdGlvbiBsOCgpe30sCkFzOmZ1bmN0aW9u
-IEFzKCl7fSwKY1g6ZnVuY3Rpb24gY1goYSl7dGhpcy5hPWF9LApiazpmdW5jdGlvbiBiaygpe30sCldX
-OmZ1bmN0aW9uIFdXKCl7fSwKVGI6ZnVuY3Rpb24gVGIoKXt9LApJdjpmdW5jdGlvbiBJdigpe30sCkJU
-OmZ1bmN0aW9uIEJUKCl7fSwKZlg6ZnVuY3Rpb24gZlgoKXt9LApGQjpmdW5jdGlvbiBGQigpe30sCkEx
-OmZ1bmN0aW9uIEExKCl7fSwKTU46ZnVuY3Rpb24gTU4oKXt9LApYMDpmdW5jdGlvbiBYMCgpe30sCm5K
-OmZ1bmN0aW9uIG5KKCl7fSwKbXo6ZnVuY3Rpb24gbXooKXt9LAphMzpmdW5jdGlvbiBhMygpe30sCmNp
-OmZ1bmN0aW9uIGNpKCl7fSwKY246ZnVuY3Rpb24gY24oKXt9LAp3NjpmdW5jdGlvbiB3Nigpe30sCkZq
-OmZ1bmN0aW9uIEZqKCl7fSwKdkY6ZnVuY3Rpb24gdkYoKXt9LApPaTpmdW5jdGlvbiBPaSgpe30sCkNt
-OmZ1bmN0aW9uIENtKCl7fSwKQ1E6ZnVuY3Rpb24gQ1EoKXt9LApQUjpmdW5jdGlvbiBQUigpe30sCnc0
-OmZ1bmN0aW9uIHc0KCl7fSwKRjI6ZnVuY3Rpb24gRjIoKXt9LApyaDpmdW5jdGlvbiByaCgpe30sCkxP
-OmZ1bmN0aW9uIExPKCl7fSwKYjE6ZnVuY3Rpb24gYjEoKXt9LAphVDpmdW5jdGlvbiBhVCgpe30sCmk3
-OmZ1bmN0aW9uIGk3KGEpe3RoaXMuYT1hfSwKU3k6ZnVuY3Rpb24gU3koYSl7dGhpcy5hPWF9LApLUzpm
-dW5jdGlvbiBLUyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQTM6ZnVuY3Rpb24gQTMoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCkk0OmZ1bmN0aW9uIEk0KGEpe3RoaXMuYT1hfSwKRms6ZnVuY3Rpb24gRmso
-YSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKUk86ZnVuY3Rpb24gUk8oYSxiLGMsZCl7dmFyIF89dGhp
-cwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKZXU6ZnVuY3Rpb24gZXUoYSxiLGMsZCl7dmFyIF89
-dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKeEM6ZnVuY3Rpb24geEMoYSxiLGMsZCxlKXt2
-YXIgXz10aGlzCl8uYj1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2TjpmdW5jdGlvbiB2Tihh
-KXt0aGlzLmE9YX0sCkpROmZ1bmN0aW9uIEpRKGEpe3RoaXMuYT1hfSwKR206ZnVuY3Rpb24gR20oKXt9
-LAp2RDpmdW5jdGlvbiB2RChhKXt0aGlzLmE9YX0sClV2OmZ1bmN0aW9uIFV2KGEpe3RoaXMuYT1hfSwK
-RWc6ZnVuY3Rpb24gRWcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKbTY6ZnVuY3Rp
-b24gbTYoKXt9LApFbzpmdW5jdGlvbiBFbygpe30sCldrOmZ1bmN0aW9uIFdrKCl7fSwKY3Q6ZnVuY3Rp
-b24gY3QoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uZT1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwK
-SUE6ZnVuY3Rpb24gSUEoKXt9LApPdzpmdW5jdGlvbiBPdygpe30sClc5OmZ1bmN0aW9uIFc5KGEsYixj
-KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0tMQpfLmQ9bnVsbApfLiR0aT1jfSwKZFc6ZnVuY3Rp
-b24gZFcoYSl7dGhpcy5hPWF9LApGYjpmdW5jdGlvbiBGYigpe30sCmtGOmZ1bmN0aW9uIGtGKCl7fSwK
-bWs6ZnVuY3Rpb24gbWsoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCktvOmZ1bmN0aW9uIEtvKGEpe3Ro
-aXMuYT1hCnRoaXMuYj0hMX0sCmZtOmZ1bmN0aW9uIGZtKGEpe3RoaXMuYT1hfSwKTGU6ZnVuY3Rpb24g
-TGUoKXt9LApKVTpmdW5jdGlvbiBKVSgpe30sCnhYOmZ1bmN0aW9uIHhYKCl7fSwKdmU6ZnVuY3Rpb24g
-dmUoKXt9LApiRzpmdW5jdGlvbiBiRygpe30sCnRJOmZ1bmN0aW9uIHRJKCl7fSwKZmc6ZnVuY3Rpb24g
-ZmcoKXt9LApjVzpmdW5jdGlvbiBjVygpe30sCkhXOmZ1bmN0aW9uIEhXKCl7fSwKbEc6ZnVuY3Rpb24g
-bEcoKXt9LApxczpmdW5jdGlvbiBxcygpe30sCmNzOmZ1bmN0aW9uIGNzKCl7fSwKS0I6ZnVuY3Rpb24g
-S0IoKXt9LApLNzpmdW5jdGlvbiBLNygpe30sCnJCOmZ1bmN0aW9uIHJCKCl7fSwKZlQ6ZnVuY3Rpb24g
-ZlQoKXt9LApmNzpmdW5jdGlvbiBmNygpe30sCmJnOmZ1bmN0aW9uIGJnKCl7fSwKb0g6ZnVuY3Rpb24g
-b0goKXt9LApDRTpmdW5jdGlvbiBDRSgpe30sCmFEOmZ1bmN0aW9uIGFEKCl7fSwKWng6ZnVuY3Rpb24g
-WngoKXt9LApPWDpmdW5jdGlvbiBPWCgpe30sClVqOmZ1bmN0aW9uIFVqKCl7fSwKak06ZnVuY3Rpb24g
-ak0oKXt9LApRVjpmdW5jdGlvbiBRVigpe30sCkF3OmZ1bmN0aW9uIEF3KCl7fSwKdHI6ZnVuY3Rpb24g
-dHIoKXt9LApPMzpmdW5jdGlvbiBPMygpe30sCk92OmZ1bmN0aW9uIE92KCl7fSwKY086ZnVuY3Rpb24g
-Y08oKXt9LApZRDpmdW5jdGlvbiBZRCgpe30sCkR4OmZ1bmN0aW9uIER4KCl7fSwKWFc6ZnVuY3Rpb24g
-WFcoKXt9LApvYTpmdW5jdGlvbiBvYSgpe30sClhVOmZ1bmN0aW9uIFhVKCl7fSwKbzM6ZnVuY3Rpb24g
-bzMoKXt9LAp6djpmdW5jdGlvbiB6digpe30sCm56OmZ1bmN0aW9uIG56KCl7fX0sVT17CmpmOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMscixxCmlmKGE9PW51bGwpdD1udWxsCmVsc2V7dD1ILlZNKFtdLHUuZkEpCmZv
-cihzPUouSVQodS5SLmEoYSkpO3MubSgpOyl7cj1zLmdSKHMpCnE9Si5VNihyKQpDLk5tLkEodCxuZXcg
-VS5TZShILmMocS5xKHIsImRlc2NyaXB0aW9uIikpLEguYyhxLnEociwiaHJlZiIpKSkpfX1yZXR1cm4g
-dH0sCk5kOmZ1bmN0aW9uKGEpe3ZhciB0LHMKaWYoYT09bnVsbCl0PW51bGwKZWxzZXt0PUguVk0oW10s
-dS5oaCkKZm9yKHM9Si5JVCh1LlIuYShhKSk7cy5tKCk7KUMuTm0uQSh0LFUuSmoocy5nUihzKSkpfXJl
-dHVybiB0fSwKSmo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvPSJkZXNjcmlwdGlvbiIsbj1KLlU2
-KGEpLG09SC5jKG4ucShhLG8pKSxsPUguVk0oW10sdS5hSikKZm9yKG49Si5JVCh1LlIuYShuLnEoYSwi
-ZW50cmllcyIpKSk7bi5tKCk7KXt0PW4uZ1IobikKcz1KLlU2KHQpCnI9SC5jKHMucSh0LG8pKQpxPUgu
-YyhzLnEodCwiZnVuY3Rpb24iKSkKcz1zLnEodCwibGluayIpCmlmKHM9PW51bGwpcz1udWxsCmVsc2V7
-cD1KLlU2KHMpCnM9bmV3IFUuTWwoSC5jKHAucShzLCJocmVmIikpLEguV1kocC5xKHMsImxpbmUiKSks
-SC5jKHAucShzLCJwYXRoIikpKX1DLk5tLkEobCxuZXcgVS53YihyLHEscykpfXJldHVybiBuZXcgVS55
-RChtLGwpfSwKZDI6ZnVuY3Rpb24gZDIoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8u
-Yz1jCl8uZD1kCl8uZT1lfSwKU2U6ZnVuY3Rpb24gU2UoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1s
-OmZ1bmN0aW9uIE1sKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnlEOmZ1bmN0aW9u
-IHlEKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp3YjpmdW5jdGlvbiB3YihhLGIsYyl7dGhpcy5hPWEK
-dGhpcy5iPWIKdGhpcy5jPWN9fSxCPXsKWWY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxs
-PUouVTYoYSksaz1ILmMobC5xKGEsInJlZ2lvbnMiKSksaj1ILmMobC5xKGEsIm5hdmlnYXRpb25Db250
-ZW50IikpLGk9SC5jKGwucShhLCJzb3VyY2VDb2RlIikpLGg9UC5GbCh1Lk4sdS5mNCkKZm9yKGw9Si5J
-VChKLlFNKGwucShhLCJlZGl0cyIpKSksdD11LlIscz11LmdpO2wubSgpOyl7cj1sLmdSKGwpCnE9Si5S
-RShyKQpwPUguYyhxLmdHMyhyKSkKbz1ILlZNKFtdLHMpCmZvcihxPUouSVQodC5hKHEuZ253KHIpKSk7
-cS5tKCk7KXtuPXEuZ1IocSkKbT1KLlU2KG4pCkMuTm0uQShvLG5ldyBCLmo4KEguV1kobS5xKG4sImxp
-bmUiKSksSC5jKG0ucShuLCJleHBsYW5hdGlvbiIpKSxILldZKG0ucShuLCJvZmZzZXQiKSkpKX1oLnQo
-MCxwLG8pfXJldHVybiBuZXcgQi5xcChrLGosaSxoKX0sCmo4OmZ1bmN0aW9uIGo4KGEsYixjKXt0aGlz
-LmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnFwOmZ1bmN0aW9uIHFwKGEsYixjLGQpe3ZhciBfPXRoaXMK
-Xy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApMdTpmdW5jdGlvbiBMdSgpe30sCk9TOmZ1bmN0aW9uKGEp
-e3ZhciB0CmlmKCEoYT49NjUmJmE8PTkwKSl0PWE+PTk3JiZhPD0xMjIKZWxzZSB0PSEwCnJldHVybiB0
-fSwKWXU6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hLmxlbmd0aCxzPWIrMgppZih0PHMpcmV0dXJuITEKaWYo
-IUIuT1MoQy54Qi5PMihhLGIpKSlyZXR1cm4hMQppZihDLnhCLk8yKGEsYisxKSE9PTU4KXJldHVybiEx
-CmlmKHQ9PT1zKXJldHVybiEwCnJldHVybiBDLnhCLk8yKGEscyk9PT00N319LFQ9e21ROmZ1bmN0aW9u
-IG1RKCl7fX0sTD17CkRlOmZ1bmN0aW9uKCl7Qy5CWi5CKGRvY3VtZW50LCJET01Db250ZW50TG9hZGVk
-IixuZXcgTC5lKCkpCkMub2wuQih3aW5kb3csInBvcHN0YXRlIixuZXcgTC5MKCkpfSwKa3o6ZnVuY3Rp
-b24oYSl7dmFyIHQscz11LmguYShhLnBhcmVudE5vZGUpLnF1ZXJ5U2VsZWN0b3IoIjpzY29wZSA+IHVs
-Iikscj1zLnN0eWxlLHE9IiIrQy5DRC56UShzLm9mZnNldEhlaWdodCkqMisicHgiCnIubWF4SGVpZ2h0
-PXEKcj1KLnFGKGEpCnE9ci4kdGkKdD1xLkMoIn4oMSkiKS5hKG5ldyBMLld4KHMsYSkpCnUuTS5hKG51
-bGwpClcuSkUoci5hLHIuYix0LCExLHEuYyl9LAp5WDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAs
-bz0icXVlcnlTZWxlY3RvckFsbCIsbj1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKGEpLG09dS5oCm4udG9T
-dHJpbmcKSC5EaChtLG0sIlQiLG8pCnQ9dS5VCnM9bmV3IFcud3oobi5xdWVyeVNlbGVjdG9yQWxsKCIu
-bmF2LWxpbmsiKSx0KQpzLlUocyxuZXcgTC5BTyhiKSkKSC5EaChtLG0sIlQiLG8pCnI9bmV3IFcud3oo
-bi5xdWVyeVNlbGVjdG9yQWxsKCIucmVnaW9uIiksdCkKaWYoci5nayhyKSE9PTApe3E9bi5xdWVyeVNl
-bGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKcS50b1N0cmluZwpyLlUocixuZXcgTC5IbyhxLmdldEF0
-dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHEpKS5ZKCJwYXRoIikpKSl9SC5EaChtLG0s
-IlQiLG8pCnA9bmV3IFcud3oobi5xdWVyeVNlbGVjdG9yQWxsKCIucG9zdC1saW5rIiksdCkKcC5VKHAs
-bmV3IEwuSUMoKSl9LApRNjpmdW5jdGlvbihhLGIpe3ZhciB0PXUuTgpyZXR1cm4gVy5xRChMLlE0KGEs
-YiksbnVsbCxQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYt
-OCJdLHQsdCkpfSwKdHk6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5OCnJldHVybiBXLnFEKEwuUTQoYSxQLkZs
-KHQsdCkpLCJQT1NUIixQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNl
-dD1VVEYtOCJdLHQsdCkpLlc3KG5ldyBMLkwxKCksdS5yKX0sCmFLOmZ1bmN0aW9uKGEpe3ZhciB0PVAu
-aEsoYSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LApH
-NjpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgpLnEoMCwib2Zmc2V0IikKcmV0dXJuIHQ9PW51
-bGw/bnVsbDpILkhwKHQsbnVsbCl9LAp0MjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG49
-e30sbT11LmguYShXLnFjKGEuY3VycmVudFRhcmdldCkpCmEucHJldmVudERlZmF1bHQoKQp0PW4uYT1t
-LmdldEF0dHJpYnV0ZSgiaHJlZiIpCmlmKEouemwodCwiPyIpKXtzPUMueEIuTmoodCwwLEMueEIuT1ko
-dCwiPyIpKQpuLmE9cwpyPXN9ZWxzZSByPXQKaWYoYyE9bnVsbCl7cT0kLm5VKCkKcj1uLmE9cS5vNSgw
-LEQubnIocS50TShjKSxyKSl9cD1MLkc2KHQpCm89TC5hSyh0KQppZihwIT1udWxsKUwuYWYocixwLG8s
-YixuZXcgTC5uVChuLHAsbykpCmVsc2UgTC5hZihyLG51bGwsbnVsbCxiLG5ldyBMLkJaKG4pKX0sCnVt
-OmZ1bmN0aW9uKGEpe3JldHVybiBMLlFTKHUuVi5hKGEpKX0sClFTOmZ1bmN0aW9uKGEpe3ZhciB0PTAs
-cz1QLkZYKHUueikscj0xLHEscD1bXSxvLG4sbSxsLGsKdmFyICRhc3luYyR1bT1QLmx6KGZ1bmN0aW9u
-KGIsYyl7aWYoYj09PTEpe3E9Ywp0PXJ9d2hpbGUodHJ1ZSlzd2l0Y2godCl7Y2FzZSAwOmw9dS5oLmEo
-Vy5xYyhhLmN1cnJlbnRUYXJnZXQpKS5nZXRBdHRyaWJ1dGUoImhyZWYiKQphLnByZXZlbnREZWZhdWx0
-KCkKcj0zCnQ9NgpyZXR1cm4gUC5qUShMLnR5KGwpLCRhc3luYyR1bSkKY2FzZSA2OnUuYV8uYShKLkdy
-KFcuUHYoZG9jdW1lbnQuZGVmYXVsdFZpZXcpKSkucmVsb2FkKCkKcj0xCnQ9NQpicmVhawpjYXNlIDM6
-cj0yCms9cQpvPUguUnUoaykKbj1ILnRzKGspCkwucUooImhhbmRsZVBvc3RMaW5rQ2xpY2s6ICIrSC5k
-KG8pLG4pCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIitILmQobCkrIiAoIitILmQobykrIiku
-IikKdD01CmJyZWFrCmNhc2UgMjp0PTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2Fz
-ZSAxOnJldHVybiBQLmYzKHEscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJHVtLHMpfSwKdlU6ZnVuY3Rp
-b24oKXt2YXIgdD1kb2N1bWVudCxzPXUuaApILkRoKHMscywiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0
-PW5ldyBXLnd6KHQucXVlcnlTZWxlY3RvckFsbCgiLmNvZGUiKSx1LlUpCnQuVSh0LG5ldyBMLkdIKCkp
-fSwKaFg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PXUuTgpMLlE2KGEsUC5FRihbInJlZ2lvbiIsInJlZ2lv
-biIsIm9mZnNldCIsSC5kKGIpXSx0LHQpKS5XNyhuZXcgTC5EVChhLGIsYyksdS5QKS5PQShuZXcgTC5l
-SChhKSl9LApHNzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0CmlmKCFKLnA0KGEsIi5kYXJ0Iikpe0wu
-QkUoYSxuZXcgQi5xcCgiIiwiIiwiIixDLkNNKSxkKQpMLkJYKGEsbnVsbCkKaWYoZSE9bnVsbCllLiQw
-KCkKcmV0dXJufXQ9dS5OCkwuUTYoYSxQLkVGKFsiaW5saW5lIiwidHJ1ZSJdLHQsdCkpLlc3KG5ldyBM
-Lnl1KGEsZCxiLGMsZSksdS5QKS5PQShuZXcgTC56RChhKSl9LApHZTpmdW5jdGlvbigpe3ZhciB0PSIv
-X3ByZXZpZXcvbmF2aWdhdGlvblRyZWUuanNvbiIKTC5RNih0LEMuV08pLlc3KG5ldyBMLlRXKCksdS5Q
-KS5PQShuZXcgTC54cih0KSl9LApxSjpmdW5jdGlvbihhLGIpe3ZhciB0CndpbmRvdwppZih0eXBlb2Yg
-Y29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IoYSkKd2luZG93CnQ9SC5kKGIp
-CmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS5lcnJvcih0KX0sCnFP
-OmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxyPUMuQ0QuelEoJC5m
-aSgpLm9mZnNldEhlaWdodCkscT13aW5kb3cuaW5uZXJIZWlnaHQscD1DLkNELnpRKCQuRFcoKS5vZmZz
-ZXRIZWlnaHQpCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuSE4oKQp0PXMuYm90dG9tCmlm
-KHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQub3MoKQppZih0PnEtKHArMTQpKUouZGgoYSkKZWxz
-ZXtxPXMudG9wCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuSigpCmlmKHE8cisxNClKLmRo
-KGEpfX0sCmZHOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmlmKGEhPW51bGwpe3Q9ZG9jdW1lbnQKcz10
-LmdldEVsZW1lbnRCeUlkKCJvIitILmQoYSkpCnI9dC5xdWVyeVNlbGVjdG9yKCIubGluZS0iK0guZChi
-KSkKaWYocyE9bnVsbCl7TC5xTyhzKQpKLmRSKHMpLkEoMCwidGFyZ2V0Iil9ZWxzZSBpZihyIT1udWxs
-KUwucU8oci5wYXJlbnRFbGVtZW50KQppZihyIT1udWxsKUouZFIodS5oLmEoci5wYXJlbnROb2RlKSku
-QSgwLCJoaWdobGlnaHQiKX1lbHNlIEwucU8oJC5EOSgpKX0sCmFmOmZ1bmN0aW9uKGEsYixjLGQsZSl7
-dmFyIHQscyxyPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpLHE9TC5hSyh3aW5kb3cubG9jYXRpb24u
-aHJlZikKaWYociE9bnVsbCl7dD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibyIrSC5kKHIpKQppZih0
-IT1udWxsKUouZFIodCkuUnooMCwidGFyZ2V0Iil9aWYocSE9bnVsbCl7cz1kb2N1bWVudC5xdWVyeVNl
-bGVjdG9yKCIubGluZS0iK0guZChxKSkKaWYocyE9bnVsbClKLmRSKHMucGFyZW50RWxlbWVudCkuUnoo
-MCwiaGlnaGxpZ2h0Iil9aWYoYT09d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lKXtMLmZHKGIsYykKZS4k
-MCgpfWVsc2UgTC5HNyhhLGIsYyxkLGUpfSwKUTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5oSyhh
-KSxxPXUuTgpxPVAuRmwocSxxKQpmb3IodD1yLmdoWSgpLHQ9dC5nUHUodCksdD10Lmd3KHQpO3QubSgp
-Oyl7cz10LmdSKHQpCnEudCgwLHMuYSxzLmIpfWZvcih0PWIuZ1B1KGIpLHQ9dC5ndyh0KTt0Lm0oKTsp
-e3M9dC5nUih0KQpxLnQoMCxzLmEscy5iKX1xLnQoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnJldHVybiBy
-Lm5tKDAscSkuWigwKX0sClQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbD0kLmhMKCkK
-Si5sNShsLCIiKQppZihhPT1udWxsKXt0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInAiKQp0LnRleHRD
-b250ZW50PSJTZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuIgpDLkx0LnNERCh0LEguVk0o
-WyJwbGFjZWhvbGRlciJdLHUucykpCkouZGgodS5oLmEobC5hcHBlbmRDaGlsZCh0KSkpCnJldHVybn1z
-PWEuZAp0PSQublUoKQpyPXQudE0ocykKcT1hLmIKcD1kb2N1bWVudApvPXQuSFAocyxKLlQwKHAucXVl
-cnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpCm49YS5jCnQ9cC5jcmVhdGVFbGVtZW50KCJw
-IikKbT11LmguYShsLmFwcGVuZENoaWxkKHQpKQptLmFwcGVuZENoaWxkKHAuY3JlYXRlVGV4dE5vZGUo
-SC5kKHEpKyIgYXQgIitILmQobykrIjoiK0guZChuKSsiLiIpKQpKLmRoKG0pCkwuQ0MoYSxsLHIpCkwu
-RnooYSxsKX0sCkxIOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxn
-LGY9JC55UCgpCkoubDUoZiwiIikKaWYoYi5nayhiKT09PTApe3Q9ZG9jdW1lbnQKcz10LmNyZWF0ZUVs
-ZW1lbnQoInAiKQp1LmguYShmLmFwcGVuZENoaWxkKHMpKS5hcHBlbmRDaGlsZCh0LmNyZWF0ZVRleHRO
-b2RlKCJObyBwcm9wb3NlZCBlZGl0cyIpKX1lbHNlIGZvcihmPWIuZ1B1KGIpLGY9Zi5ndyhmKSx0PXUu
-aSxzPXUuUSxyPXMuQygifigxKSIpLHE9dS5NLHM9cy5jLHA9dS5oO2YubSgpOyl7bz1mLmdSKGYpCm49
-JC55UCgpCm09ZG9jdW1lbnQKbD1tLmNyZWF0ZUVsZW1lbnQoInAiKQpwLmEobi5hcHBlbmRDaGlsZChs
-KSkuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZShILmQoby5hKSsiOiIpKQpsPW0uY3JlYXRlRWxl
-bWVudCgidWwiKQprPXAuYShuLmFwcGVuZENoaWxkKGwpKQpmb3Iobz1KLklUKG8uYik7by5tKCk7KXtu
-PW8uZ1IobykKbD1tLmNyZWF0ZUVsZW1lbnQoImxpIikKaj1wLmEoay5hcHBlbmRDaGlsZChsKSkKSi5k
-UihqKS5BKDAsImVkaXQiKQpsPW0uY3JlYXRlRWxlbWVudCgiYSIpCmk9dC5hKGouYXBwZW5kQ2hpbGQo
-bCkpCmkuY2xhc3NMaXN0LmFkZCgiZWRpdC1saW5rIikKaD1uLmMKbD1ILmQoaCkKaS5zZXRBdHRyaWJ1
-dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuWSgib2Zmc2V0IiksbCkKZz1uLmEKbD1ILmQo
-ZykKaS5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuWSgibGluZSIpLGwp
-CmkuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZSgibGluZSAiK0guZChnKSkpCmw9ci5hKG5ldyBM
-LkVFKGgsZyxhKSkKcS5hKG51bGwpClcuSkUoaSwiY2xpY2siLGwsITEscykKai5hcHBlbmRDaGlsZCht
-LmNyZWF0ZVRleHROb2RlKCI6ICIrSC5kKG4uYikpKX19aWYoYylMLlQxKG51bGwpfSwKRnI6ZnVuY3Rp
-b24oYSxiLGMpe3ZhciB0LHMscj13aW5kb3cubG9jYXRpb24scT1QLmhLKChyJiZDLkV4KS5nRHIocikr
-SC5kKGEpKQpyPXUuTgpyPVAuRmwocixyKQppZihiIT1udWxsKXIudCgwLCJvZmZzZXQiLEguZChiKSkK
-aWYoYyE9bnVsbClyLnQoMCwibGluZSIsSC5kKGMpKQpyLnQoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnE9
-cS5ubSgwLHIpCnI9d2luZG93Lmhpc3RvcnkKdD11LnoKcz1xLlooMCkKci50b1N0cmluZwpyLnB1c2hT
-dGF0ZShuZXcgUC5CZihbXSxbXSkuUHYoUC5GbCh0LHQpKSwiIixzKX0sCkVuOmZ1bmN0aW9uKGEpe3Zh
-ciB0PUoubShkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50LCIvIikKaWYo
-Qy54Qi5uQyhhLHQpKXJldHVybiBDLnhCLnluKGEsdC5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApCWDpm
-dW5jdGlvbihhLGIpe3ZhciB0LHMscj17fQpyLmE9YQphPUwuRW4oYSkKci5hPWEKJC5EOSgpLnRleHRD
-b250ZW50PWEKdD1kb2N1bWVudApzPXUuaApILkRoKHMscywiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0
-PW5ldyBXLnd6KHQucXVlcnlTZWxlY3RvckFsbCgiLm5hdi1wYW5lbCAubmF2LWxpbmsiKSx1LlUpCnQu
-VSh0LG5ldyBMLlZTKHIpKX0sCkJFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0iLnJlZ2lvbnMiLHM9ZG9j
-dW1lbnQscj1zLnF1ZXJ5U2VsZWN0b3IodCkscT1zLnF1ZXJ5U2VsZWN0b3IoIi5jb2RlIikKSi50SChy
-LGIuYSwkLktHKCkpCkoudEgocSxiLmIsJC5LRygpKQpMLkxIKGEsYi5kLGMpCkwudlUoKQpMLnlYKCIu
-Y29kZSIsITApCkwueVgodCwhMCl9LAp0WDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0s
-bCxrLGosaT1kb2N1bWVudCxoPWkuY3JlYXRlRWxlbWVudCgidWwiKSxnPXUuaCxmPWcuYShhLmFwcGVu
-ZENoaWxkKGgpKQpmb3IoaD1iLmxlbmd0aCx0PXUuTSxzPTA7czxiLmxlbmd0aDtiLmxlbmd0aD09PWh8
-fCgwLEgubGspKGIpLCsrcyl7cj1iW3NdCnE9aS5jcmVhdGVFbGVtZW50KCJsaSIpCnA9Zy5hKGYuYXBw
-ZW5kQ2hpbGQocSkpCnE9Si5SRShwKQppZihyLmE9PT1DLlkyKXtxLmdERChwKS5BKDAsImRpciIpCnE9
-aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKbz1nLmEocC5hcHBlbmRDaGlsZChxKSkKcT1KLlJFKG8pCnEu
-Z0REKG8pLkEoMCwiYXJyb3ciKQpxLnNoZihvLCImI3gyNUJDOyIpCnE9aS5jcmVhdGVFbGVtZW50KCJz
-cGFuIikKSi5sNShnLmEocC5hcHBlbmRDaGlsZChxKSksIiYjeDFGNEMxOyIpCnAuYXBwZW5kQ2hpbGQo
-aS5jcmVhdGVUZXh0Tm9kZShyLmIpKQpMLnRYKHAsci5jKQpMLmt6KG8pfWVsc2V7cS5zaGYocCwiJiN4
-MUY0QzQ7IikKcT1pLmNyZWF0ZUVsZW1lbnQoImEiKQpuPWcuYShwLmFwcGVuZENoaWxkKHEpKQpxPUou
-UkUobikKcS5nREQobikuQSgwLCJuYXYtbGluayIpCm4uc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcu
-U3kobmV3IFcuaTcobikpLlkoIm5hbWUiKSxyLmQpCm4uc2V0QXR0cmlidXRlKCJocmVmIixyLmUpCm4u
-YXBwZW5kQ2hpbGQoaS5jcmVhdGVUZXh0Tm9kZShyLmIpKQpxPXEuZ1ZsKG4pCm09cS4kdGkKbD1tLkMo
-In4oMSkiKS5hKG5ldyBMLlREKCkpCnQuYShudWxsKQpXLkpFKHEuYSxxLmIsbCwhMSxtLmMpCms9ci5m
-CmlmKHR5cGVvZiBrIT09Im51bWJlciIpcmV0dXJuIGsub3MoKQppZihrPjApe3E9aS5jcmVhdGVFbGVt
-ZW50KCJzcGFuIikKaj1nLmEocC5hcHBlbmRDaGlsZChxKSkKSi5kUihqKS5BKDAsImVkaXQtY291bnQi
-KQpxPSIiK2srIiAiCmlmKGs9PT0xKW09ImVkaXQiCmVsc2UgbT0iZWRpdHMiCmouc2V0QXR0cmlidXRl
-KCJ0aXRsZSIscSttKQpqLmFwcGVuZENoaWxkKGkuY3JlYXRlVGV4dE5vZGUoQy5qbi5aKGspKSl9fX19
-LApGejpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1hLmEKaWYoaSE9bnVs
-bCl7dD1kb2N1bWVudApzPXQuY3JlYXRlRWxlbWVudCgicCIpCnI9dS5oCnE9ci5hKGIuYXBwZW5kQ2hp
-bGQocykpCmZvcihzPWkubGVuZ3RoLHA9dS5zLG89dS5YLG49MDtuPGkubGVuZ3RoO2kubGVuZ3RoPT09
-c3x8KDAsSC5saykoaSksKytuKXttPWlbbl0KbD10LmNyZWF0ZUVsZW1lbnQoImEiKQprPXIuYShxLmFw
-cGVuZENoaWxkKGwpKQprLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUobS5hKSkKay5zZXRBdHRy
-aWJ1dGUoImhyZWYiLG0uYikKbD1vLmEoSC5WTShbInBvc3QtbGluayIsImJlZm9yZS1hcHBseSJdLHAp
-KQpqPUouZFIoaykKai5WMSgwKQpqLkZWKDAsbCl9fX0sCkNDOmZ1bmN0aW9uKGEzLGE0LGE1KXt2YXIg
-dCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhLGEwLGExLGEyPW51bGwKZm9yKHQ9
-YTMuZSxzPXQubGVuZ3RoLHI9dS5zLHE9dS5YLHA9dS5oLG89dS5pLG49MDtuPHQubGVuZ3RoO3QubGVu
-Z3RoPT09c3x8KDAsSC5saykodCksKytuKXttPXRbbl0KbD1kb2N1bWVudAprPWwuY3JlYXRlRWxlbWVu
-dCgicCIpCmo9cS5hKEguVk0oWyJ0cmFjZSJdLHIpKQppPUouZFIoaykKaS5WMSgwKQppLkZWKDAsaikK
-aD1hNC5hcHBlbmRDaGlsZChrKQprPWwuY3JlYXRlRWxlbWVudCgic3BhbiIpCmo9cS5hKEguVk0oWyJ0
-eXBlLWRlc2NyaXB0aW9uIl0scikpCmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKQprLmFwcGVuZENo
-aWxkKGwuY3JlYXRlVGV4dE5vZGUobS5hKSkKaC5hcHBlbmRDaGlsZChrKQpoLmFwcGVuZENoaWxkKGwu
-Y3JlYXRlVGV4dE5vZGUoIjoiKSkKaz1sLmNyZWF0ZUVsZW1lbnQoInVsIikKaj1xLmEoSC5WTShbInRy
-YWNlIl0scikpCmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKQpnPWguYXBwZW5kQ2hpbGQoaykKZm9y
-KGs9bS5iLGo9ay5sZW5ndGgsZj0wO2Y8ay5sZW5ndGg7ay5sZW5ndGg9PT1qfHwoMCxILmxrKShrKSwr
-K2Ype2U9a1tmXQpkPWwuY3JlYXRlRWxlbWVudCgibGkiKQpKLmw1KGQsIiYjeDI3NEY7ICIpCmM9cC5h
-KGcuYXBwZW5kQ2hpbGQoZCkpCmQ9bC5jcmVhdGVFbGVtZW50KCJzcGFuIikKYj1xLmEoSC5WTShbImZ1
-bmN0aW9uIl0scikpCmk9Si5kUihkKQppLlYxKDApCmkuRlYoMCxiKQpiPWUuYgpMLmtEKGQsYj09bnVs
-bD8idW5rbm93biI6YikKYy5hcHBlbmRDaGlsZChkKQphPWUuYwppZihhIT1udWxsKXtjLmFwcGVuZENo
-aWxkKGwuY3JlYXRlVGV4dE5vZGUoIiAoIikpCmEwPWEuYgpkPWwuY3JlYXRlRWxlbWVudCgiYSIpCm8u
-YShkKQpkLmFwcGVuZENoaWxkKGwuY3JlYXRlVGV4dE5vZGUoSC5kKGEuYykrIjoiK0guZChhMCkpKQph
-MT1hLmEKYj0kLm5VKCkKZC5zZXRBdHRyaWJ1dGUoImhyZWYiLGIubzUoMCxiLnE3KDAsYTUsYTEsYTIs
-YTIsYTIsYTIsYTIsYTIpKSkKZC5jbGFzc0xpc3QuYWRkKCJuYXYtbGluayIpCmMuYXBwZW5kQ2hpbGQo
-ZCkKYy5hcHBlbmRDaGlsZChsLmNyZWF0ZVRleHROb2RlKCIpIikpfWMuYXBwZW5kQ2hpbGQobC5jcmVh
-dGVUZXh0Tm9kZSgiOiAiKSkKZD1lLmEKTC5rRChjLGQ9PW51bGw/InVua25vd24iOmQpfX19LAprRDpm
-dW5jdGlvbihhLGIpe3ZhciB0LHMscj1ILlZNKGIuc3BsaXQoIi4iKSx1LnMpLHE9Qy5ObS5ndEgociks
-cD1kb2N1bWVudAphLmFwcGVuZENoaWxkKHAuY3JlYXRlVGV4dE5vZGUocSkpCmZvcihxPUgucUMociwx
-LG51bGwsdS5OKSxxPW5ldyBILmE3KHEscS5nayhxKSxxLiR0aS5DKCJhNzxhTC5FPiIpKSx0PUouUkUo
-YSk7cS5tKCk7KXtzPXEuZAp0Lm56KGEsImJlZm9yZWVuZCIsIiYjODIwMzsuIixudWxsLG51bGwpCmEu
-YXBwZW5kQ2hpbGQocC5jcmVhdGVUZXh0Tm9kZShzKSl9fSwKZTpmdW5jdGlvbiBlKCl7fSwKVlc6ZnVu
-Y3Rpb24gVlcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKb1o6ZnVuY3Rpb24gb1oo
-KXt9LApqcjpmdW5jdGlvbiBqcigpe30sCnFsOmZ1bmN0aW9uIHFsKCl7fSwKeTg6ZnVuY3Rpb24geTgo
-KXt9LApMOmZ1bmN0aW9uIEwoKXt9LApXeDpmdW5jdGlvbiBXeChhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
-fSwKQU86ZnVuY3Rpb24gQU8oYSl7dGhpcy5hPWF9LApkTjpmdW5jdGlvbiBkTihhKXt0aGlzLmE9YX0s
-CkhvOmZ1bmN0aW9uIEhvKGEpe3RoaXMuYT1hfSwKeHo6ZnVuY3Rpb24geHooYSxiKXt0aGlzLmE9YQp0
-aGlzLmI9Yn0sCklDOmZ1bmN0aW9uIElDKCl7fSwKTDE6ZnVuY3Rpb24gTDEoKXt9LApuVDpmdW5jdGlv
-biBuVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApCWjpmdW5jdGlvbiBCWihhKXt0
-aGlzLmE9YX0sCkdIOmZ1bmN0aW9uIEdIKCl7fSwKRFQ6ZnVuY3Rpb24gRFQoYSxiLGMpe3RoaXMuYT1h
-CnRoaXMuYj1iCnRoaXMuYz1jfSwKZUg6ZnVuY3Rpb24gZUgoYSl7dGhpcy5hPWF9LAp5dTpmdW5jdGlv
-biB5dShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWV9LAp6
-RDpmdW5jdGlvbiB6RChhKXt0aGlzLmE9YX0sClRXOmZ1bmN0aW9uIFRXKCl7fSwKeHI6ZnVuY3Rpb24g
-eHIoYSl7dGhpcy5hPWF9LApFRTpmdW5jdGlvbiBFRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
-cy5jPWN9LApRTDpmdW5jdGlvbiBRTChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVlM6ZnVuY3Rpb24g
-VlMoYSl7dGhpcy5hPWF9LApURDpmdW5jdGlvbiBURCgpe30sClhBOmZ1bmN0aW9uIFhBKCl7fSwKbUs6
-ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49SC5WTShbXSx1LmZoKQpmb3IodD1KLklUKHUuUi5h
-KGEpKTt0Lm0oKTspe3M9dC5nUih0KQpyPUouVTYocykKcT1MLnAyKEguYyhyLnEocywidHlwZSIpKSkK
-cD1ILmMoci5xKHMsIm5hbWUiKSkKbz1yLnEocywic3VidHJlZSIpCm89bz09bnVsbD9udWxsOkwubUso
-bykKQy5ObS5BKG4sbmV3IEwuWloocSxwLG8sSC5jKHIucShzLCJwYXRoIikpLEguYyhyLnEocywiaHJl
-ZiIpKSxILldZKHIucShzLCJlZGl0Q291bnQiKSkpKX1yZXR1cm4gbn0sCnAyOmZ1bmN0aW9uKGEpe3N3
-aXRjaChhKXtjYXNlImRpcmVjdG9yeSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpk
-ZWZhdWx0OnRocm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlw
-ZTogIitILmQoYSkpKX19LApaWjpmdW5jdGlvbiBaWihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9
-YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sCldBOmZ1bmN0aW9uIFdBKGEpe3RoaXMuYj1h
-fSwKSVY6ZnVuY3Rpb24gSVYoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9
-ZH19LE09ewpZRjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuCmZvcih0PWIubGVuZ3RoLHM9
-MTtzPHQ7KytzKXtpZihiW3NdPT1udWxsfHxiW3MtMV0hPW51bGwpY29udGludWUKZm9yKDt0Pj0xO3Q9
-cil7cj10LTEKaWYoYltyXSE9bnVsbClicmVha31xPW5ldyBQLlJuKCIiKQpwPWErIigiCnEuYT1wCm89
-SC5xQyhiLDAsdCxILnQ2KGIpLmMpCm49by4kdGkKbj1wK25ldyBILmxKKG8sbi5DKCJxVShhTC5FKSIp
-LmEobmV3IE0uTm8oKSksbi5DKCJsSjxhTC5FLHFVPiIpKS56VigwLCIsICIpCnEuYT1uCnEuYT1uKygi
-KTogcGFydCAiKyhzLTEpKyIgd2FzIG51bGwsIGJ1dCBwYXJ0ICIrcysiIHdhcyBub3QuIikKdGhyb3cg
-SC5iKFAueFkocS5aKDApKSl9fSwKbEk6ZnVuY3Rpb24gbEkoYSl7dGhpcy5hPWF9LApNaTpmdW5jdGlv
-biBNaSgpe30sCnE3OmZ1bmN0aW9uIHE3KCl7fSwKTm86ZnVuY3Rpb24gTm8oKXt9fSxYPXsKQ0w6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89Yi54WihhKQpiLmhLKGEpCmlmKG8hPW51bGwpYT1KLktW
-KGEsby5sZW5ndGgpCnQ9dS5zCnM9SC5WTShbXSx0KQpyPUguVk0oW10sdCkKdD1hLmxlbmd0aAppZih0
-IT09MCYmYi5yNChDLnhCLldkKGEsMCkpKXtpZigwPj10KXJldHVybiBILmsoYSwwKQpDLk5tLkEocixh
-WzBdKQpxPTF9ZWxzZXtDLk5tLkEociwiIikKcT0wfWZvcihwPXE7cDx0OysrcClpZihiLnI0KEMueEIu
-V2QoYSxwKSkpe0MuTm0uQShzLEMueEIuTmooYSxxLHApKQpDLk5tLkEocixhW3BdKQpxPXArMX1pZihx
-PHQpe0MuTm0uQShzLEMueEIueW4oYSxxKSkKQy5ObS5BKHIsIiIpfXJldHVybiBuZXcgWC5XRChiLG8s
-cyxyKX0sCldEOmZ1bmN0aW9uIFdEKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPWMK
-Xy5lPWR9LApxUjpmdW5jdGlvbiBxUihhKXt0aGlzLmE9YX0sCkk3OmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgWC5kdihhKX0sCmR2OmZ1bmN0aW9uIGR2KGEpe3RoaXMuYT1hfX0sTz17ClJoOmZ1bmN0aW9uKCl7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpPW51bGwKaWYoUC51bygpLmdGaSgpIT09ImZpbGUiKXJl
-dHVybiAkLkViKCkKdD1QLnVvKCkKaWYoIUMueEIuVGModC5nSWkodCksIi8iKSlyZXR1cm4gJC5FYigp
-CnM9UC5QaShpLDAsMCkKcj1QLnpSKGksMCwwKQpxPVAuT2UoaSwwLDAsITEpCnA9UC5sZShpLDAsMCxp
-KQpvPVAudEcoaSwwLDApCm49UC53QihpLHMpCm09cz09PSJmaWxlIgppZihxPT1udWxsKXQ9ci5sZW5n
-dGghPT0wfHxuIT1udWxsfHxtCmVsc2UgdD0hMQppZih0KXE9IiIKdD1xPT1udWxsCmw9IXQKaz1QLmth
-KCJhL2IiLDAsMyxpLHMsbCkKaj1zLmxlbmd0aD09PTAKaWYoaiYmdCYmIUMueEIubkMoaywiLyIpKWs9
-UC53RihrLCFqfHxsKQplbHNlIGs9UC54ZShrKQppZihuZXcgUC5EbihzLHIsdCYmQy54Qi5uQyhrLCIv
-LyIpPyIiOnEsbixrLHAsbykudDQoKT09PSJhXFxiIilyZXR1cm4gJC5LaygpCnJldHVybiAkLmJEKCl9
-LApPTzpmdW5jdGlvbiBPTygpe319LEU9e09GOmZ1bmN0aW9uIE9GKGEsYixjKXt0aGlzLmQ9YQp0aGlz
-LmU9Ygp0aGlzLmY9Y319LEY9e3J1OmZ1bmN0aW9uIHJ1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5kPWEK
-Xy5lPWIKXy5mPWMKXy5yPWR9fSxEPXsKUlg6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9UC51bygpCmlmKEou
-Uk0ociwkLkk2KSlyZXR1cm4gJC5GZgokLkk2PXIKaWYoJC5IaygpPT0kLkViKCkpcmV0dXJuICQuRmY9
-ci5aSSgiLiIpLlooMCkKZWxzZXt0PXIudDQoKQpzPXQubGVuZ3RoLTEKcmV0dXJuICQuRmY9cz09PTA/
-dDpDLnhCLk5qKHQsMCxzKX19LApucjpmdW5jdGlvbihhLGIpe3ZhciB0PW51bGwKcmV0dXJuICQublUo
-KS5xNygwLGEsYix0LHQsdCx0LHQsdCl9fQp2YXIgdz1bQyxILEosUCxXLFUsQixULEwsTSxYLE8sRSxG
-LERdCmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIgJD17fQpILkZL
-LnByb3RvdHlwZT17fQpKLnZCLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PT1i
-fSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIEguZVEoYSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiJJbnN0
-YW5jZSBvZiAnIitILmQoSC5saChhKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYShiKQp0aHJv
-dyBILmIoUC5scihhLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnByb3RvdHlwZT17Clo6
-ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBhPzUxOTAx
-ODoyMTgxNTl9LAokaWEyOjF9CkouWUUucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
-bnVsbD09Yn0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIm51bGwifSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJu
-IDB9LAplNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNqKGEsdS5vLmEoYikpfSwKJGljODoxfQpK
-Lk1GLnByb3RvdHlwZT17CmdpOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKWjpmdW5jdGlvbihhKXtyZXR1
-cm4gU3RyaW5nKGEpfSwKJGl2bToxfQpKLmlDLnByb3RvdHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpK
-LmM1LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9YVskLndRKCldCmlmKHQ9PW51bGwpcmV0
-dXJuIHRoaXMubihhKQpyZXR1cm4iSmF2YVNjcmlwdCBmdW5jdGlvbiBmb3IgIitILmQoSi5BYyh0KSl9
-LAokUzpmdW5jdGlvbigpe3JldHVybntmdW5jOjEsb3B0OlssLCwsLCwsLCwsLCwsLCwsXX19LAokaUVI
-OjF9CkouamQucHJvdG90eXBlPXsKQTpmdW5jdGlvbihhLGIpe0gudDYoYSkuYy5hKGIpCmlmKCEhYS5m
-aXhlZCRsZW5ndGgpSC5WaihQLkw0KCJhZGQiKSkKYS5wdXNoKGIpfSwKVzQ6ZnVuY3Rpb24oYSxiKXt2
-YXIgdAppZighIWEuZml4ZWQkbGVuZ3RoKUguVmooUC5MNCgicmVtb3ZlQXQiKSkKdD1hLmxlbmd0aApp
-ZihiPj10KXRocm93IEguYihQLk83KGIsbnVsbCkpCnJldHVybiBhLnNwbGljZShiLDEpWzBdfSwKVUc6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpILnQ2KGEpLkMoIkx5PDE+IikuYShjKQppZighIWEuZml4
-ZWQkbGVuZ3RoKUguVmooUC5MNCgiaW5zZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53QShiLDAsdCwiaW5k
-ZXgiKQpzPWMubGVuZ3RoCnRoaXMuc2soYSx0K3MpCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEs
-YikKdGhpcy52ZyhhLGIscixjKX0sCm12OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhlZCRsZW5ndGgpSC5W
-aihQLkw0KCJyZW1vdmVMYXN0IikpCmlmKGEubGVuZ3RoPT09MCl0aHJvdyBILmIoSC5IWShhLC0xKSkK
-cmV0dXJuIGEucG9wKCl9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0CkgudDYoYSkuQygiTHk8MT4iKS5h
-KGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC5WaihQLkw0KCJhZGRBbGwiKSkKZm9yKHQ9Si5JVChiKTt0
-Lm0oKTspYS5wdXNoKHQuZ1IodCkpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC50NihhKS5DKCJ+
-KDEpIikuYShiKQp0PWEubGVuZ3RoCmZvcihzPTA7czx0Oysrcyl7Yi4kMShhW3NdKQppZihhLmxlbmd0
-aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkpfX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILnQ2KGEp
-CnJldHVybiBuZXcgSC5sSihhLHQuSyhjKS5DKCIxKDIpIikuYShiKSx0LkMoIkA8MT4iKS5LKGMpLkMo
-ImxKPDEsMj4iKSl9LAp6VjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9bmV3IEFycmF5KGEubGVuZ3RoKQpz
-LmZpeGVkJGxlbmd0aD1BcnJheQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMudChzLHQsSC5kKGFb
-dF0pKQpyZXR1cm4gcy5qb2luKGIpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmQuYShi
-KQpILnQ2KGEpLksoZCkuQygiMSgxLDIpIikuYShjKQp0PWEubGVuZ3RoCmZvcihzPWIscj0wO3I8dDsr
-K3Ipe3M9Yy4kMihzLGFbcl0pCmlmKGEubGVuZ3RoIT09dCl0aHJvdyBILmIoUC5hNChhKSl9cmV0dXJu
-IHN9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0
-dXJuIGFbYl19LApENjpmdW5jdGlvbihhLGIsYyl7aWYoYjwwfHxiPmEubGVuZ3RoKXRocm93IEguYihQ
-LlRFKGIsMCxhLmxlbmd0aCwic3RhcnQiLG51bGwpKQppZihjPGJ8fGM+YS5sZW5ndGgpdGhyb3cgSC5i
-KFAuVEUoYyxiLGEubGVuZ3RoLCJlbmQiLG51bGwpKQppZihiPT09YylyZXR1cm4gSC5WTShbXSxILnQ2
-KGEpKQpyZXR1cm4gSC5WTShhLnNsaWNlKGIsYyksSC50NihhKSl9LApndEg6ZnVuY3Rpb24oYSl7aWYo
-YS5sZW5ndGg+MClyZXR1cm4gYVswXQp0aHJvdyBILmIoSC5XcCgpKX0sCmdyWjpmdW5jdGlvbihhKXt2
-YXIgdD1hLmxlbmd0aAppZih0PjApcmV0dXJuIGFbdC0xXQp0aHJvdyBILmIoSC5XcCgpKX0sCllXOmZ1
-bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyPUgudDYoYSkKci5DKCJMeTwxPiIpLmEoZCkKaWYoISFh
-LmltbXV0YWJsZSRsaXN0KUguVmooUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnQ9
-Yy1iCmlmKHQ9PT0wKXJldHVybgpQLmsxKGUsInNraXBDb3VudCIpCnIuQygiek08MT4iKS5hKGQpCnI9
-Si5VNihkKQppZihlK3Q+ci5nayhkKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIpZm9yKHM9dC0xO3M+
-PTA7LS1zKWFbYitzXT1yLnEoZCxlK3MpCmVsc2UgZm9yKHM9MDtzPHQ7KytzKWFbYitzXT1yLnEoZCxl
-K3MpfSwKdmc6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZyOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoImEyKDEpIikuYShiKQp0PWEubGVuZ3RoCmZvcihz
-PTA7czx0Oysrcyl7aWYoSC5vVChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXQpdGhy
-b3cgSC5iKFAuYTQoYSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD0wO3Q8
-YS5sZW5ndGg7Kyt0KWlmKEouUk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sClo6ZnVuY3Rpb24o
-YSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0iKX0sCmd3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSi5tMShh
-LGEubGVuZ3RoLEgudDYoYSkuQygibTE8MT4iKSl9LApnaTpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUShh
-KX0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnNrOmZ1bmN0aW9uKGEsYil7aWYoISFh
-LmZpeGVkJGxlbmd0aClILlZqKFAuTDQoInNldCBsZW5ndGgiKSkKaWYoYjwwKXRocm93IEguYihQLlRF
-KGIsMCxudWxsLCJuZXdMZW5ndGgiLG51bGwpKQphLmxlbmd0aD1ifSwKcTpmdW5jdGlvbihhLGIpe0gu
-V1koYikKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0s
-CnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKSC50NihhKS5jLmEoYykKaWYoISFhLmltbXV0YWJsZSRs
-aXN0KUguVmooUC5MNCgiaW5kZXhlZCBzZXQiKSkKaWYoIUgub2soYikpdGhyb3cgSC5iKEguSFkoYSxi
-KSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQphW2JdPWN9LAokaWJROjEs
-CiRpTHk6MSwKJGl6TToxfQpKLlBvLnByb3RvdHlwZT17fQpKLm0xLnByb3RvdHlwZT17CmdSOmZ1bmN0
-aW9uKGEpe3JldHVybiB0aGlzLmR9LAptOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9cy5hLHE9ci5s
-ZW5ndGgKaWYocy5iIT09cSl0aHJvdyBILmIoSC5sayhyKSkKdD1zLmMKaWYodD49cSl7cy5zSShudWxs
-KQpyZXR1cm4hMX1zLnNJKHJbdF0pOysrcy5jCnJldHVybiEwfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5k
-PXRoaXMuJHRpLmMuYShhKX0sCiRpQW46MX0KSi5xSS5wcm90b3R5cGU9ewp5dTpmdW5jdGlvbihhKXt2
-YXIgdAppZihhPj0tMjE0NzQ4MzY0OCYmYTw9MjE0NzQ4MzY0NylyZXR1cm4gYXwwCmlmKGlzRmluaXRl
-KGEpKXt0PWE8MD9NYXRoLmNlaWwoYSk6TWF0aC5mbG9vcihhKQpyZXR1cm4gdCswfXRocm93IEguYihQ
-Lkw0KCIiK2ErIi50b0ludCgpIikpfSwKelE6ZnVuY3Rpb24oYSl7aWYoYT4wKXtpZihhIT09MS8wKXJl
-dHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAwLU1hdGgucm91bmQoMC1hKQp0
-aHJvdyBILmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sCkQ4OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-LHEKaWYoYjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwzNiwicmFkaXgiLG51bGwpKQp0PWEudG9T
-dHJpbmcoYikKaWYoQy54Qi5PMih0LHQubGVuZ3RoLTEpIT09NDEpcmV0dXJuIHQKcz0vXihbXGRhLXpd
-KykoPzpcLihbXGRhLXpdKykpP1woZVwrKFxkKylcKSQvLmV4ZWModCkKaWYocz09bnVsbClILlZqKFAu
-TDQoIlVuZXhwZWN0ZWQgdG9TdHJpbmcgcmVzdWx0OiAiK3QpKQpyPXMubGVuZ3RoCmlmKDE+PXIpcmV0
-dXJuIEguayhzLDEpCnQ9c1sxXQppZigzPj1yKXJldHVybiBILmsocywzKQpxPStzWzNdCnI9c1syXQpp
-ZihyIT1udWxsKXt0Kz1yCnEtPXIubGVuZ3RofXJldHVybiB0K0MueEIuSXgoIjAiLHEpfSwKWjpmdW5j
-dGlvbihhKXtpZihhPT09MCYmMS9hPDApcmV0dXJuIi0wLjAiCmVsc2UgcmV0dXJuIiIrYX0sCmdpOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YXwwCmlmKGE9PT1wKXJldHVybiA1MzY4NzA5MTEmcAp0PU1h
-dGguYWJzKGEpCnM9TWF0aC5sb2codCkvMC42OTMxNDcxODA1NTk5NDUzfDAKcj1NYXRoLnBvdygyLHMp
-CnE9dDwxP3QvcjpyL3QKcmV0dXJuIDUzNjg3MDkxMSYoKHEqOTAwNzE5OTI1NDc0MDk5MnwwKSsocSoz
-NTQyMjQzMTgxMTc2NTIxfDApKSo1OTkxOTcrcyoxMjU5fSwKelk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1h
-JWIKaWYodD09PTApcmV0dXJuIDAKaWYodD4wKXJldHVybiB0CmlmKGI8MClyZXR1cm4gdC1iCmVsc2Ug
-cmV0dXJuIHQrYn0sCndHOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT4wKXQ9dGhpcy5wMyhhLGIpCmVs
-c2V7dD1iPjMxPzMxOmIKdD1hPj50Pj4+MH1yZXR1cm4gdH0sCmJmOmZ1bmN0aW9uKGEsYil7aWYoYjww
-KXRocm93IEguYihILnRMKGIpKQpyZXR1cm4gdGhpcy5wMyhhLGIpfSwKcDM6ZnVuY3Rpb24oYSxiKXty
-ZXR1cm4gYj4zMT8wOmE+Pj5ifSwKJGlDUDoxLAokaWxmOjF9CkoudXIucHJvdG90eXBlPXskaUlmOjF9
-CkouVkEucHJvdG90eXBlPXt9CkouRHIucHJvdG90eXBlPXsKTzI6ZnVuY3Rpb24oYSxiKXtpZihiPDAp
-dGhyb3cgSC5iKEguSFkoYSxiKSkKaWYoYj49YS5sZW5ndGgpSC5WaihILkhZKGEsYikpCnJldHVybiBh
-LmNoYXJDb2RlQXQoYil9LApXZDpmdW5jdGlvbihhLGIpe2lmKGI+PWEubGVuZ3RoKXRocm93IEguYihI
-LkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBu
-ZXcgSC5ORihiLGEsMCl9LApoOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJzdHJpbmciKXRocm93
-IEguYihQLkwzKGIsbnVsbCxudWxsKSkKcmV0dXJuIGErYn0sClRjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9
-Yi5sZW5ndGgscz1hLmxlbmd0aAppZih0PnMpcmV0dXJuITEKcmV0dXJuIGI9PT10aGlzLnluKGEscy10
-KX0sCmk3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKYz1QLmpCKGIsYyxhLmxlbmd0aCkKdD1hLnN1
-YnN0cmluZygwLGIpCnM9YS5zdWJzdHJpbmcoYykKcmV0dXJuIHQrZCtzfSwKUWk6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0CmlmKCFILm9rKGMpKUguVmooSC50TChjKSkKaWYodHlwZW9mIGMhPT0ibnVtYmVyIily
-ZXR1cm4gYy5KKCkKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxu
-dWxsLG51bGwpKQp0PWMrYi5sZW5ndGgKaWYodD5hLmxlbmd0aClyZXR1cm4hMQpyZXR1cm4gYj09PWEu
-c3Vic3RyaW5nKGMsdCl9LApuQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlFpKGEsYiwwKX0sCk5q
-OmZ1bmN0aW9uKGEsYixjKXtpZighSC5vayhiKSlILlZqKEgudEwoYikpCmlmKGM9PW51bGwpYz1hLmxl
-bmd0aAppZih0eXBlb2YgYiE9PSJudW1iZXIiKXJldHVybiBiLkooKQppZihiPDApdGhyb3cgSC5iKFAu
-TzcoYixudWxsKSkKaWYoYj5jKXRocm93IEguYihQLk83KGIsbnVsbCkpCmlmKGM+YS5sZW5ndGgpdGhy
-b3cgSC5iKFAuTzcoYyxudWxsKSkKcmV0dXJuIGEuc3Vic3RyaW5nKGIsYyl9LAp5bjpmdW5jdGlvbihh
-LGIpe3JldHVybiB0aGlzLk5qKGEsYixudWxsKX0sCmhjOmZ1bmN0aW9uKGEpe3JldHVybiBhLnRvTG93
-ZXJDYXNlKCl9LApiUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLnRyaW0oKSxwPXEubGVuZ3RoCmlm
-KHA9PT0wKXJldHVybiBxCmlmKHRoaXMuV2QocSwwKT09PTEzMyl7dD1KLm1tKHEsMSkKaWYodD09PXAp
-cmV0dXJuIiJ9ZWxzZSB0PTAKcz1wLTEKcj10aGlzLk8yKHEscyk9PT0xMzM/Si5jMShxLHMpOnAKaWYo
-dD09PTAmJnI9PT1wKXJldHVybiBxCnJldHVybiBxLnN1YnN0cmluZyh0LHIpfSwKSXg6ZnVuY3Rpb24o
-YSxiKXt2YXIgdCxzCmlmKDA+PWIpcmV0dXJuIiIKaWYoYj09PTF8fGEubGVuZ3RoPT09MClyZXR1cm4g
-YQppZihiIT09Yj4+PjApdGhyb3cgSC5iKEMuRXEpCmZvcih0PWEscz0iIjshMDspe2lmKChiJjEpPT09
-MSlzPXQrcwpiPWI+Pj4xCmlmKGI9PT0wKWJyZWFrCnQrPXR9cmV0dXJuIHN9LApYVTpmdW5jdGlvbihh
-LGIsYyl7dmFyIHQKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxu
-dWxsLG51bGwpKQp0PWEuaW5kZXhPZihiLGMpCnJldHVybiB0fSwKT1k6ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gdGhpcy5YVShhLGIsMCl9LApQazpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwppZihjPT1udWxsKWM9
-YS5sZW5ndGgKZWxzZSBpZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3Ro
-LG51bGwsbnVsbCkpCnQ9Yi5sZW5ndGgKcz1hLmxlbmd0aAppZihjK3Q+cyljPXMtdApyZXR1cm4gYS5s
-YXN0SW5kZXhPZihiLGMpfSwKY246ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5QayhhLGIsbnVsbCl9
-LApJczpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9YS5sZW5ndGgKaWYoYz50KXRocm93IEguYihQLlRFKGMs
-MCx0LG51bGwsbnVsbCkpCnJldHVybiBILm0yKGEsYixjKX0sCnRnOmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IHRoaXMuSXMoYSxiLDApfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gYX0sCmdpOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTAscj0wO3I8dDsrK3Ipe3M9NTM2ODcwOTExJnMrYS5jaGFy
-Q29kZUF0KHIpCnM9NTM2ODcwOTExJnMrKCg1MjQyODcmcyk8PDEwKQpzXj1zPj42fXM9NTM2ODcwOTEx
-JnMrKCg2NzEwODg2MyZzKTw8MykKc149cz4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8
-PDE1KX0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZ
-KGIpCmlmKGI+PWEubGVuZ3RofHwhMSl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0sCiRp
-dlg6MSwKJGlxVToxfQpILnFqLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEu
-bGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiBDLnhCLk8yKHRoaXMuYSxILldZKGIpKX19Ckgu
-YlEucHJvdG90eXBlPXt9CkguYUwucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwpy
-ZXR1cm4gbmV3IEguYTcodCx0LmdrKHQpLEguTGgodCkuQygiYTc8YUwuRT4iKSl9LAp6VjpmdW5jdGlv
-bihhLGIpe3ZhciB0LHMscixxPXRoaXMscD1xLmdrKHEpCmlmKGIubGVuZ3RoIT09MCl7aWYocD09PTAp
-cmV0dXJuIiIKdD1ILmQocS5XKDAsMCkpCmlmKHAhPT1xLmdrKHEpKXRocm93IEguYihQLmE0KHEpKQpm
-b3Iocz10LHI9MTtyPHA7KytyKXtzPXMrYitILmQocS5XKDAscikpCmlmKHAhPT1xLmdrKHEpKXRocm93
-IEguYihQLmE0KHEpKX1yZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c31lbHNle2ZvcihyPTAscz0i
-IjtyPHA7KytyKXtzKz1ILmQocS5XKDAscikpCmlmKHAhPT1xLmdrKHEpKXRocm93IEguYihQLmE0KHEp
-KX1yZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c319LApldjpmdW5jdGlvbihhLGIpe3JldHVybiB0
-aGlzLkdHKDAsSC5MaCh0aGlzKS5DKCJhMihhTC5FKSIpLmEoYikpfSwKRTI6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBILmxKKHRoaXMsdC5LKGMpLkMoIjEoYUwuRSkiKS5h
-KGIpLHQuQygiQDxhTC5FPiIpLksoYykuQygibEo8MSwyPiIpKX19CkgubkgucHJvdG90eXBlPXsKZ1VE
-OmZ1bmN0aW9uKCl7dmFyIHQ9Si5IKHRoaXMuYSkscz10aGlzLmMKaWYocz09bnVsbHx8cz50KXJldHVy
-biB0CnJldHVybiBzfSwKZ0FzOmZ1bmN0aW9uKCl7dmFyIHQ9Si5IKHRoaXMuYSkscz10aGlzLmIKaWYo
-cz50KXJldHVybiB0CnJldHVybiBzfSwKZ2s6ZnVuY3Rpb24oYSl7dmFyIHQscz1KLkgodGhpcy5hKSxy
-PXRoaXMuYgppZihyPj1zKXJldHVybiAwCnQ9dGhpcy5jCmlmKHQ9PW51bGx8fHQ+PXMpcmV0dXJuIHMt
-cgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkhOKCkKcmV0dXJuIHQtcn0sClc6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzPXRoaXMscj1zLmdBcygpK2IKaWYoYj49MCl7dD1zLmdVRCgpCmlmKHR5cGVv
-ZiB0IT09Im51bWJlciIpcmV0dXJuIEgucFkodCkKdD1yPj10fWVsc2UgdD0hMAppZih0KXRocm93IEgu
-YihQLnQoYixzLCJpbmRleCIsbnVsbCxudWxsKSkKcmV0dXJuIEouR0Eocy5hLHIpfX0KSC5hNy5wcm90
-b3R5cGU9ewpnUjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5kfSwKbTpmdW5jdGlvbigpe3ZhciB0LHM9
-dGhpcyxyPXMuYSxxPUouVTYocikscD1xLmdrKHIpCmlmKHMuYiE9PXApdGhyb3cgSC5iKFAuYTQocikp
-CnQ9cy5jCmlmKHQ+PXApe3Muc0kzKG51bGwpCnJldHVybiExfXMuc0kzKHEuVyhyLHQpKTsrK3MuYwpy
-ZXR1cm4hMH0sCnNJMzpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpI
-LmkxLnByb3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBI
-Lk1IKEouSVQodGhpcy5hKSx0aGlzLmIsdC5DKCJAPDE+IikuSyh0LlFbMV0pLkMoIk1IPDEsMj4iKSl9
-LApnazpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuYSl9fQpILnh5LnByb3RvdHlwZT17JGliUTox
-fQpILk1ILnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5iCmlmKHMubSgpKXt0
-LnNJMyh0LmMuJDEocy5nUihzKSkpCnJldHVybiEwfXQuc0kzKG51bGwpCnJldHVybiExfSwKZ1I6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCnNJMzpmdW5jdGlvbihhKXt0aGlzLmE9dGhpcy4kdGkuUVsx
-XS5hKGEpfX0KSC5sSi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuYSl9
-LApXOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYi4kMShKLkdBKHRoaXMuYSxiKSl9fQpILlU1LnBy
-b3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC52RyhKLklUKHRoaXMuYSksdGhpcy5i
-LHRoaXMuJHRpLkMoInZHPDE+IikpfX0KSC52Ry5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKCl7dmFyIHQs
-cwpmb3IodD10aGlzLmEscz10aGlzLmI7dC5tKCk7KWlmKEgub1Qocy4kMSh0LmdSKHQpKSkpcmV0dXJu
-ITAKcmV0dXJuITF9LApnUjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ1IodCl9fQpI
-LlNVLnByb3RvdHlwZT17fQpILlJlLnByb3RvdHlwZT17CnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikK
-SC5MaCh0aGlzKS5DKCJSZS5FIikuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSBhbiB1
-bm1vZGlmaWFibGUgbGlzdCIpKX19CkgudzIucHJvdG90eXBlPXt9Ckgud3YucHJvdG90eXBlPXsKZ2k6
-ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5faGFzaENvZGUKaWYodCE9bnVsbClyZXR1cm4gdAp0PTUzNjg3
-MDkxMSY2NjQ1OTcqSi5JKHRoaXMuYSkKdGhpcy5faGFzaENvZGU9dApyZXR1cm4gdH0sClo6ZnVuY3Rp
-b24oYSl7cmV0dXJuJ1N5bWJvbCgiJytILmQodGhpcy5hKSsnIiknfSwKRE46ZnVuY3Rpb24oYSxiKXtp
-ZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgSC53diYmdGhpcy5hPT1iLmF9LAok
-aUdEOjF9CkguUEQucHJvdG90eXBlPXt9CkguV1UucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1
-cm4gUC5uTyh0aGlzKX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguTGgodGhpcykKdC5jLmEoYikK
-dC5RWzFdLmEoYykKcmV0dXJuIEguZGMoKX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5xNChh
-LEguTGgodGhpcykuQygiTjM8MSwyPiIpKX0sCnE0OmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwpyZXR1
-cm4gUC5sMChmdW5jdGlvbigpe3ZhciBzPWEKdmFyIHI9MCxxPTEscCxvLG4sbQpyZXR1cm4gZnVuY3Rp
-b24gJGFzeW5jJGdQdShjLGQpe2lmKGM9PT0xKXtwPWQKcj1xfXdoaWxlKHRydWUpc3dpdGNoKHIpe2Nh
-c2UgMDpvPXQuZ3YodCksbz1vLmd3KG8pLG49SC5MaCh0KSxuPW4uQygiQDwxPiIpLksobi5RWzFdKS5D
-KCJOMzwxLDI+IikKY2FzZSAyOmlmKCFvLm0oKSl7cj0zCmJyZWFrfW09by5nUihvKQpyPTQKcmV0dXJu
-IG5ldyBQLk4zKG0sdC5xKDAsbSksbikKY2FzZSA0OnI9MgpicmVhawpjYXNlIDM6cmV0dXJuIFAuVGgo
-KQpjYXNlIDE6cmV0dXJuIFAuWW0ocCl9fX0sYil9LAokaVowOjF9CkguTFAucHJvdG90eXBlPXsKZ2s6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCng0OmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJz
-dHJpbmciKXJldHVybiExCmlmKCJfX3Byb3RvX18iPT09YilyZXR1cm4hMQpyZXR1cm4gdGhpcy5iLmhh
-c093blByb3BlcnR5KGIpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlzLng0KDAsYikpcmV0dXJuIG51
-bGwKcmV0dXJuIHRoaXMuRChiKX0sCkQ6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYltILmMoYSldfSwK
-VTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9SC5MaCh0aGlzKQpwLkMoIn4oMSwyKSIpLmEoYikK
-dD10aGlzLmMKZm9yKHM9dC5sZW5ndGgscD1wLlFbMV0scj0wO3I8czsrK3Ipe3E9dFtyXQpiLiQyKHEs
-cC5hKHRoaXMuRChxKSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5YUih0aGlzLEguTGgo
-dGhpcykuQygiWFI8MT4iKSl9fQpILlhSLnByb3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
-aXMuYS5jCnJldHVybiBuZXcgSi5tMSh0LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9LApnazpm
-dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmMubGVuZ3RofX0KSC5MSS5wcm90b3R5cGU9ewpnV2E6ZnVu
-Y3Rpb24oKXt2YXIgdD10aGlzLmEKcmV0dXJuIHR9LApnbmQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxw
-PXRoaXMKaWYocC5jPT09MSlyZXR1cm4gQy5kbgp0PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgtcC5m
-CmlmKHM9PT0wKXJldHVybiBDLmRuCnI9W10KZm9yKHE9MDtxPHM7KytxKXtpZihxPj10Lmxlbmd0aCly
-ZXR1cm4gSC5rKHQscSkKci5wdXNoKHRbcV0pfXJldHVybiBKLnVuKHIpfSwKZ1ZtOmZ1bmN0aW9uKCl7
-dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMKaWYobC5jIT09MClyZXR1cm4gQy5EeAp0PWwuZQpzPXQu
-bGVuZ3RoCnI9bC5kCnE9ci5sZW5ndGgtcy1sLmYKaWYocz09PTApcmV0dXJuIEMuRHgKcD1uZXcgSC5O
-NSh1LmVvKQpmb3Iobz0wO288czsrK28pe2lmKG8+PXQubGVuZ3RoKXJldHVybiBILmsodCxvKQpuPXRb
-b10KbT1xK28KaWYobTwwfHxtPj1yLmxlbmd0aClyZXR1cm4gSC5rKHIsbSkKcC50KDAsbmV3IEgud3Yo
-biksclttXSl9cmV0dXJuIG5ldyBILlBEKHAsdS5nRil9LAokaXZROjF9CkguQ2oucHJvdG90eXBlPXsK
-JDI6ZnVuY3Rpb24oYSxiKXt2YXIgdApILmMoYSkKdD10aGlzLmEKdC5iPXQuYisiJCIrSC5kKGEpCkMu
-Tm0uQSh0aGlzLmIsYSkKQy5ObS5BKHRoaXMuYyxiKTsrK3QuYX0sCiRTOjEzfQpILmY5LnByb3RvdHlw
-ZT17CnFTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9bmV3IFJlZ0V4cChyLmEpLmV4ZWMoYSkK
-aWYocT09bnVsbClyZXR1cm4gbnVsbAp0PU9iamVjdC5jcmVhdGUobnVsbCkKcz1yLmIKaWYocyE9PS0x
-KXQuYXJndW1lbnRzPXFbcysxXQpzPXIuYwppZihzIT09LTEpdC5hcmd1bWVudHNFeHByPXFbcysxXQpz
-PXIuZAppZihzIT09LTEpdC5leHByPXFbcysxXQpzPXIuZQppZihzIT09LTEpdC5tZXRob2Q9cVtzKzFd
-CnM9ci5mCmlmKHMhPT0tMSl0LnJlY2VpdmVyPXFbcysxXQpyZXR1cm4gdH19CkguVzAucHJvdG90eXBl
-PXsKWjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9k
-RXJyb3I6ICIrSC5kKHRoaXMuYSkKcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZv
-dW5kOiAnIit0KyInIG9uIG51bGwifX0KSC5hei5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0
-LHM9dGhpcyxyPSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5vdCBmb3VuZDogJyIscT1zLmIKaWYo
-cT09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIrSC5kKHMuYSkKdD1zLmMKaWYodD09bnVs
-bClyZXR1cm4gcitxKyInICgiK0guZChzLmEpKyIpIgpyZXR1cm4gcitxKyInIG9uICciK3QrIicgKCIr
-SC5kKHMuYSkrIikifX0KSC52Vi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpy
-ZXR1cm4gdC5sZW5ndGg9PT0wPyJFcnJvciI6IkVycm9yOiAiK3R9fQpILmJxLnByb3RvdHlwZT17fQpI
-LkFtLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe2lmKHUubS5iKGEpKWlmKGEuJHRocm93bkpzRXJy
-b3I9PW51bGwpYS4kdGhyb3duSnNFcnJvcj10aGlzLmEKcmV0dXJuIGF9LAokUzo0fQpILlhPLnByb3Rv
-dHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmIKaWYocyE9bnVsbClyZXR1cm4gcwpzPXRo
-aXMuYQp0PXMhPT1udWxsJiZ0eXBlb2Ygcz09PSJvYmplY3QiP3Muc3RhY2s6bnVsbApyZXR1cm4gdGhp
-cy5iPXQ9PW51bGw/IiI6dH0sCiRpR3o6MX0KSC5UcC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3Zh
-ciB0PXRoaXMuY29uc3RydWN0b3Iscz10PT1udWxsP251bGw6dC5uYW1lCnJldHVybiJDbG9zdXJlICci
-K0guTlEocz09bnVsbD8idW5rbm93biI6cykrIicifSwKJGlFSDoxLApnUWw6ZnVuY3Rpb24oKXtyZXR1
-cm4gdGhpc30sCiRDOiIkMSIsCiRSOjEsCiREOm51bGx9CkgubGMucHJvdG90eXBlPXt9CkguengucHJv
-dG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLiRzdGF0aWNfbmFtZQppZih0PT1udWxsKXJl
-dHVybiJDbG9zdXJlIG9mIHVua25vd24gc3RhdGljIG1ldGhvZCIKcmV0dXJuIkNsb3N1cmUgJyIrSC5O
-USh0KSsiJyJ9fQpILmp5LnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZihi
-PT1udWxsKXJldHVybiExCmlmKHQ9PT1iKXJldHVybiEwCmlmKCEoYiBpbnN0YW5jZW9mIEguankpKXJl
-dHVybiExCnJldHVybiB0LmE9PT1iLmEmJnQuYj09PWIuYiYmdC5jPT09Yi5jfSwKZ2k6ZnVuY3Rpb24o
-YSl7dmFyIHQscz10aGlzLmMKaWYocz09bnVsbCl0PUguZVEodGhpcy5hKQplbHNlIHQ9dHlwZW9mIHMh
-PT0ib2JqZWN0Ij9KLkkocyk6SC5lUShzKQpyZXR1cm4odF5ILmVRKHRoaXMuYikpPj4+MH0sClo6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpdD10aGlzLmEKcmV0dXJuIkNsb3N1cmUgJyIr
-SC5kKHRoaXMuZCkrIicgb2YgIisoIkluc3RhbmNlIG9mICciK0guZChILmxoKHQpKSsiJyIpfX0KSC5F
-cS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSdW50aW1lRXJyb3I6ICIrSC5kKHRoaXMu
-YSl9fQpILmtZLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkFzc2VydGlvbiBmYWlsZWQ6
-ICIrUC5oKHRoaXMuYSl9fQpILk41LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LmF9LApndjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguaTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+
-IikpfSwKeDQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD10aGlz
-LmIKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5YdSh0LGIpfWVsc2V7cz10aGlzLkNYKGIp
-CnJldHVybiBzfX0sCkNYOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiEx
-CnJldHVybiB0aGlzLkYodGhpcy5IKHQsSi5JKGEpJjB4M2ZmZmZmZiksYSk+PTB9LApxOmZ1bmN0aW9u
-KGEsYil7dmFyIHQscyxyLHEscD10aGlzLG89bnVsbAppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9cC5i
-CmlmKHQ9PW51bGwpcmV0dXJuIG8Kcz1wLmoodCxiKQpyPXM9PW51bGw/bzpzLmIKcmV0dXJuIHJ9ZWxz
-ZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjB4M2ZmZmZmZik9PT1iKXtxPXAuYwppZihxPT1udWxs
-KXJldHVybiBvCnM9cC5qKHEsYikKcj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgcmV0dXJuIHAu
-WChiKX0sClg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMuZAppZihyPT1udWxsKXJldHVybiBudWxs
-CnQ9dGhpcy5IKHIsSi5JKGEpJjB4M2ZmZmZmZikKcz10aGlzLkYodCxhKQppZihzPDApcmV0dXJuIG51
-bGwKcmV0dXJuIHRbc10uYn0sCnQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMs
-bT1ILkxoKG4pCm0uYy5hKGIpCm0uUVsxXS5hKGMpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD1uLmIK
-bi51KHQ9PW51bGw/bi5iPW4ubCgpOnQsYixjKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGIm
-MHgzZmZmZmZmKT09PWIpe3M9bi5jCm4udShzPT1udWxsP24uYz1uLmwoKTpzLGIsYyl9ZWxzZXtyPW4u
-ZAppZihyPT1udWxsKXI9bi5kPW4ubCgpCnE9Si5JKGIpJjB4M2ZmZmZmZgpwPW4uSChyLHEpCmlmKHA9
-PW51bGwpbi5FKHIscSxbbi5PKGIsYyldKQplbHNle289bi5GKHAsYikKaWYobz49MClwW29dLmI9Ywpl
-bHNlIHAucHVzaChuLk8oYixjKSl9fX0sClU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwpILkxo
-KHIpLkMoIn4oMSwyKSIpLmEoYikKdD1yLmUKcz1yLnIKZm9yKDt0IT1udWxsOyl7Yi4kMih0LmEsdC5i
-KQppZihzIT09ci5yKXRocm93IEguYihQLmE0KHIpKQp0PXQuY319LAp1OmZ1bmN0aW9uKGEsYixjKXt2
-YXIgdCxzPXRoaXMscj1ILkxoKHMpCnIuYy5hKGIpCnIuUVsxXS5hKGMpCnQ9cy5qKGEsYikKaWYodD09
-bnVsbClzLkUoYSxiLHMuTyhiLGMpKQplbHNlIHQuYj1jfSwKRzpmdW5jdGlvbigpe3RoaXMucj10aGlz
-LnIrMSY2NzEwODg2M30sCk86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILkxoKHMpLHE9bmV3
-IEgudmgoci5jLmEoYSksci5RWzFdLmEoYikpCmlmKHMuZT09bnVsbClzLmU9cy5mPXEKZWxzZXt0PXMu
-ZgpxLmQ9dApzLmY9dC5jPXF9KytzLmEKcy5HKCkKcmV0dXJuIHF9LApGOmZ1bmN0aW9uKGEsYil7dmFy
-IHQscwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0o
-YVtzXS5hLGIpKXJldHVybiBzCnJldHVybi0xfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlz
-KX0sCmo6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVtiXX0sCkg6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVti
-XX0sCkU6ZnVuY3Rpb24oYSxiLGMpe2FbYl09Y30sClY6ZnVuY3Rpb24oYSxiKXtkZWxldGUgYVtiXX0s
-Clh1OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuaihhLGIpIT1udWxsfSwKbDpmdW5jdGlvbigpe3Zh
-ciB0PSI8bm9uLWlkZW50aWZpZXIta2V5PiIscz1PYmplY3QuY3JlYXRlKG51bGwpCnRoaXMuRShzLHQs
-cykKdGhpcy5WKHMsdCkKcmV0dXJuIHN9LAokaUZvOjF9CkgudmgucHJvdG90eXBlPXt9CkguaTUucHJv
-dG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5hfSwKZ3c6ZnVuY3Rpb24oYSl7dmFy
-IHQ9dGhpcy5hLHM9bmV3IEguTjYodCx0LnIsdGhpcy4kdGkuQygiTjY8MT4iKSkKcy5jPXQuZQpyZXR1
-cm4gc319CkguTjYucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0sCm06ZnVu
-Y3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChzKSkKZWxz
-ZXtzPXQuYwppZihzPT1udWxsKXt0LnNNKG51bGwpCnJldHVybiExfWVsc2V7dC5zTShzLmEpCnQuYz10
-LmMuYwpyZXR1cm4hMH19fSwKc006ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmMuYShhKX0sCiRp
-QW46MX0KSC5yLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoYSl9LAokUzo0
-fQpILmRDLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6
-NDV9Ckgud04ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShILmMoYSkpfSwK
-JFM6Mjh9CkguVlIucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5h
+KHE+PXQpcmV0dXJuIEguT0goaSxxKQppW3FdPW8KcmV0dXJuIGl9LAplZzpmdW5jdGlvbihhLGIsYTAp
+e3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQ9bmV3IFAuVkMoYSksYz1uZXcgUC5K
+VChkLGEpCmlmKGEubGVuZ3RoPDIpZC4kMSgiYWRkcmVzcyBpcyB0b28gc2hvcnQiKQp0PUguVk0oW10s
+dS50KQpmb3Iocz1iLHI9cyxxPSExLHA9ITE7czxhMDsrK3Mpe289Qy54Qi5PMihhLHMpCmlmKG89PT01
+OCl7aWYocz09PWIpeysrcwppZihDLnhCLk8yKGEscykhPT01OClkLiQyKCJpbnZhbGlkIHN0YXJ0IGNv
+bG9uLiIscykKcj1zfWlmKHM9PT1yKXtpZihxKWQuJDIoIm9ubHkgb25lIHdpbGRjYXJkIGA6OmAgaXMg
+YWxsb3dlZCIscykKQy5ObS5BKHQsLTEpCnE9ITB9ZWxzZSBDLk5tLkEodCxjLiQyKHIscykpCnI9cysx
+fWVsc2UgaWYobz09PTQ2KXA9ITB9aWYodC5sZW5ndGg9PT0wKWQuJDEoInRvbyBmZXcgcGFydHMiKQpu
+PXI9PT1hMAptPUMuTm0uZ3JaKHQpCmlmKG4mJm0hPT0tMSlkLiQyKCJleHBlY3RlZCBhIHBhcnQgYWZ0
+ZXIgbGFzdCBgOmAiLGEwKQppZighbilpZighcClDLk5tLkEodCxjLiQyKHIsYTApKQplbHNle2w9UC5I
+aChhLHIsYTApCkMuTm0uQSh0LChsWzBdPDw4fGxbMV0pPj4+MCkKQy5ObS5BKHQsKGxbMl08PDh8bFsz
+XSk+Pj4wKX1pZihxKXtpZih0Lmxlbmd0aD43KWQuJDEoImFuIGFkZHJlc3Mgd2l0aCBhIHdpbGRjYXJk
+IG11c3QgaGF2ZSBsZXNzIHRoYW4gNyBwYXJ0cyIpfWVsc2UgaWYodC5sZW5ndGghPT04KWQuJDEoImFu
+IGFkZHJlc3Mgd2l0aG91dCBhIHdpbGRjYXJkIG11c3QgY29udGFpbiBleGFjdGx5IDggcGFydHMiKQpr
+PW5ldyBVaW50OEFycmF5KDE2KQpmb3IobT10Lmxlbmd0aCxqPWsubGVuZ3RoLGk9OS1tLHM9MCxoPTA7
+czxtOysrcyl7Zz10W3NdCmlmKGc9PT0tMSlmb3IoZj0wO2Y8aTsrK2Ype2lmKGg8MHx8aD49ailyZXR1
+cm4gSC5PSChrLGgpCmtbaF09MAplPWgrMQppZihlPj1qKXJldHVybiBILk9IKGssZSkKa1tlXT0wCmgr
+PTJ9ZWxzZXtlPUMuam4ud0coZyw4KQppZihoPDB8fGg+PWopcmV0dXJuIEguT0goayxoKQprW2hdPWUK
+ZT1oKzEKaWYoZT49ailyZXR1cm4gSC5PSChrLGUpCmtbZV09ZyYyNTUKaCs9Mn19cmV0dXJuIGt9LApq
+djpmdW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSxqKXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwKaWYo
+aj09bnVsbClpZihkPmIpaj1QLlBpKGEsYixkKQplbHNle2lmKGQ9PT1iKVAuUjMoYSxiLCJJbnZhbGlk
+IGVtcHR5IHNjaGVtZSIpCmo9IiJ9aWYoZT5iKXt0PWQrMwpzPXQ8ZT9QLnpSKGEsdCxlLTEpOiIiCnI9
+UC5PZShhLGUsZiwhMSkKaWYodHlwZW9mIGYhPT0ibnVtYmVyIilyZXR1cm4gZi5UKCkKcT1mKzEKaWYo
+dHlwZW9mIGchPT0ibnVtYmVyIilyZXR1cm4gSC5wWShnKQpwPXE8Zz9QLndCKFAuUUEoSi5sZChhLHEs
+ZyksbmV3IFAuZTEoYSxmKSxtKSxqKTptfWVsc2V7cD1tCnI9cApzPSIifW89UC5rYShhLGcsaCxtLGos
+ciE9bnVsbCkKaWYodHlwZW9mIGghPT0ibnVtYmVyIilyZXR1cm4gaC5KKCkKbj1oPGk/UC5sZShhLGgr
+MSxpLG0pOm0KcmV0dXJuIG5ldyBQLkRuKGoscyxyLHAsbyxuLGk8Yz9QLnRHKGEsaSsxLGMpOm0pfSwK
+d0s6ZnVuY3Rpb24oYSl7aWYoYT09PSJodHRwIilyZXR1cm4gODAKaWYoYT09PSJodHRwcyIpcmV0dXJu
+IDQ0MwpyZXR1cm4gMH0sClIzOmZ1bmN0aW9uKGEsYixjKXt0aHJvdyBILmIoUC5ycihjLGEsYikpfSwK
+a0U6ZnVuY3Rpb24oYSxiKXtDLk5tLlUoYSxuZXcgUC5OWSghMSkpfSwKSE46ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0LHMscgpmb3IodD1ILnFDKGEsYyxudWxsLEgudDYoYSkuZCksdD1uZXcgSC5hNyh0LHQuZ2go
+dCksdC4kdGkuQygiYTc8YUwuRT4iKSk7dC5tKCk7KXtzPXQuZApyPVAubnUoJ1siKi86PD4/XFxcXHxd
+JykKcy50b1N0cmluZwppZihILm0yKHMsciwwKSl7dD1QLkw0KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBw
+YXRoOiAiK3MpCnRocm93IEguYih0KX19fSwKcmc6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZighKDY1PD1h
+JiZhPD05MCkpdD05Nzw9YSYmYTw9MTIyCmVsc2UgdD0hMAppZih0KXJldHVybgp0PVAuTDQoIklsbGVn
+YWwgZHJpdmUgbGV0dGVyICIrUC5PbyhhKSkKdGhyb3cgSC5iKHQpfSwKd0I6ZnVuY3Rpb24oYSxiKXtp
+ZihhIT1udWxsJiZhPT09UC53SyhiKSlyZXR1cm4gbnVsbApyZXR1cm4gYX0sCk9lOmZ1bmN0aW9uKGEs
+YixjLGQpe3ZhciB0LHMscixxLHAsbwppZihhPT1udWxsKXJldHVybiBudWxsCmlmKGI9PT1jKXJldHVy
+biIiCmlmKEMueEIuTzIoYSxiKT09PTkxKXtpZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBjLkhO
+KCkKdD1jLTEKaWYoQy54Qi5PMihhLHQpIT09OTMpUC5SMyhhLGIsIk1pc3NpbmcgZW5kIGBdYCB0byBt
+YXRjaCBgW2AgaW4gaG9zdCIpCnM9YisxCnI9UC50byhhLHMsdCkKaWYodHlwZW9mIHIhPT0ibnVtYmVy
+IilyZXR1cm4gci5KKCkKaWYocjx0KXtxPXIrMQpwPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixxKT9yKzM6
+cSx0LCIlMjUiKX1lbHNlIHA9IiIKUC5lZyhhLHMscikKcmV0dXJuIEMueEIuTmooYSxiLHIpLnRvTG93
+ZXJDYXNlKCkrcCsiXSJ9aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQpvPWIKZm9y
+KDtvPGM7KytvKWlmKEMueEIuTzIoYSxvKT09PTU4KXtyPUMueEIuWFUoYSwiJSIsYikKaWYoIShyPj1i
+JiZyPGMpKXI9YwppZihyPGMpe3E9cisxCnA9UC5PQShhLEMueEIuUWkoYSwiMjUiLHEpP3IrMzpxLGMs
+IiUyNSIpfWVsc2UgcD0iIgpQLmVnKGEsYixyKQpyZXR1cm4iWyIrQy54Qi5OaihhLGIscikrcCsiXSJ9
+cmV0dXJuIFAuT0woYSxiLGMpfSwKdG86ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Qy54Qi5YVShhLCIl
+IixiKQppZihzPj1iKXtpZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9czxjfWVs
+c2UgdD0hMQpyZXR1cm4gdD9zOmN9LApPQTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8s
+bixtLGwsaz1kIT09IiI/bmV3IFAuUm4oZCk6bnVsbAppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVy
+biBILnBZKGMpCnQ9YgpzPXQKcj0hMApmb3IoO3Q8Yzspe3E9Qy54Qi5PMihhLHQpCmlmKHE9PT0zNyl7
+cD1QLnJ2KGEsdCwhMCkKbz1wPT1udWxsCmlmKG8mJnIpe3QrPTMKY29udGludWV9aWYoaz09bnVsbClr
+PW5ldyBQLlJuKCIiKQpuPWsuYSs9Qy54Qi5OaihhLHMsdCkKaWYobylwPUMueEIuTmooYSx0LHQrMykK
+ZWxzZSBpZihwPT09IiUiKVAuUjMoYSx0LCJab25lSUQgc2hvdWxkIG5vdCBjb250YWluICUgYW55bW9y
+ZSIpCmsuYT1uK3AKdCs9MwpzPXQKcj0hMH1lbHNle2lmKHE8MTI3KXtvPXE+Pj40CmlmKG8+PTgpcmV0
+dXJuIEguT0goQy5GMyxvKQpvPShDLkYzW29dJjE8PChxJjE1KSkhPT0wfWVsc2Ugbz0hMQppZihvKXtp
+ZihyJiY2NTw9cSYmOTA+PXEpe2lmKGs9PW51bGwpaz1uZXcgUC5SbigiIikKaWYoczx0KXtrLmErPUMu
+eEIuTmooYSxzLHQpCnM9dH1yPSExfSsrdH1lbHNle2lmKChxJjY0NTEyKT09PTU1Mjk2JiZ0KzE8Yyl7
+bT1DLnhCLk8yKGEsdCsxKQppZigobSY2NDUxMik9PT01NjMyMCl7cT02NTUzNnwocSYxMDIzKTw8MTB8
+bSYxMDIzCmw9Mn1lbHNlIGw9MX1lbHNlIGw9MQppZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9
+Qy54Qi5OaihhLHMsdCkKay5hKz1QLkhIKHEpCnQrPWwKcz10fX19aWYoaz09bnVsbClyZXR1cm4gQy54
+Qi5OaihhLGIsYykKaWYoczxjKWsuYSs9Qy54Qi5OaihhLHMsYykKbz1rLmEKcmV0dXJuIG8uY2hhckNv
+ZGVBdCgwKT09MD9vOm99LApPTDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
+agppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj1udWxsCnE9ITAK
+Zm9yKDt0PGM7KXtwPUMueEIuTzIoYSx0KQppZihwPT09Mzcpe289UC5ydihhLHQsITApCm49bz09bnVs
+bAppZihuJiZxKXt0Kz0zCmNvbnRpbnVlfWlmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKbT1DLnhCLk5q
+KGEscyx0KQpsPXIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0KaWYobil7bz1DLnhCLk5qKGEsdCx0KzMp
+Cms9M31lbHNlIGlmKG89PT0iJSIpe289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpzPXQK
+cT0hMH1lbHNle2lmKHA8MTI3KXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5lYSxuKQpuPShD
+LmVhW25dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKXtpZihxJiY2NTw9cCYmOTA+PXApe2lm
+KHI9PW51bGwpcj1uZXcgUC5SbigiIikKaWYoczx0KXtyLmErPUMueEIuTmooYSxzLHQpCnM9dH1xPSEx
+fSsrdH1lbHNle2lmKHA8PTkzKXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5hayxuKQpuPShD
+LmFrW25dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKVAuUjMoYSx0LCJJbnZhbGlkIGNoYXJh
+Y3RlciIpCmVsc2V7aWYoKHAmNjQ1MTIpPT09NTUyOTYmJnQrMTxjKXtqPUMueEIuTzIoYSx0KzEpCmlm
+KChqJjY0NTEyKT09PTU2MzIwKXtwPTY1NTM2fChwJjEwMjMpPDwxMHxqJjEwMjMKaz0yfWVsc2Ugaz0x
+fWVsc2Ugaz0xCmlmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKbT1DLnhCLk5qKGEscyx0KQpyLmErPSFx
+P20udG9Mb3dlckNhc2UoKTptCnIuYSs9UC5ISChwKQp0Kz1rCnM9dH19fX1pZihyPT1udWxsKXJldHVy
+biBDLnhCLk5qKGEsYixjKQppZihzPGMpe209Qy54Qi5OaihhLHMsYykKci5hKz0hcT9tLnRvTG93ZXJD
+YXNlKCk6bX1uPXIuYQpyZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0wP246bn0sClBpOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdCxzLHIscQppZihiPT09YylyZXR1cm4iIgppZighUC5FdChKLnJZKGEpLldkKGEsYikp
+KVAuUjMoYSxiLCJTY2hlbWUgbm90IHN0YXJ0aW5nIHdpdGggYWxwaGFiZXRpYyBjaGFyYWN0ZXIiKQpm
+b3IodD1iLHM9ITE7dDxjOysrdCl7cj1DLnhCLldkKGEsdCkKaWYocjwxMjgpe3E9cj4+PjQKaWYocT49
+OClyZXR1cm4gSC5PSChDLm1LLHEpCnE9KEMubUtbcV0mMTw8KHImMTUpKSE9PTB9ZWxzZSBxPSExCmlm
+KCFxKVAuUjMoYSx0LCJJbGxlZ2FsIHNjaGVtZSBjaGFyYWN0ZXIiKQppZig2NTw9ciYmcjw9OTApcz0h
+MH1hPUMueEIuTmooYSxiLGMpCnJldHVybiBQLllhKHM/YS50b0xvd2VyQ2FzZSgpOmEpfSwKWWE6ZnVu
+Y3Rpb24oYSl7aWYoYT09PSJodHRwIilyZXR1cm4iaHR0cCIKaWYoYT09PSJmaWxlIilyZXR1cm4iZmls
+ZSIKaWYoYT09PSJodHRwcyIpcmV0dXJuImh0dHBzIgppZihhPT09InBhY2thZ2UiKXJldHVybiJwYWNr
+YWdlIgpyZXR1cm4gYX0sCnpSOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiIiCnJldHVy
+biBQLnVPKGEsYixjLEMudG8sITEpfSwKa2E6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0LHM9ZT09
+PSJmaWxlIixyPXN8fGYscT1hPT1udWxsCmlmKHEmJiEwKXJldHVybiBzPyIvIjoiIgp0PSFxP1AudU8o
+YSxiLGMsQy5XZCwhMCk6Qy5qTi5FMihkLG5ldyBQLlJaKCksdS5OKS56VigwLCIvIikKaWYodC5sZW5n
+dGg9PT0wKXtpZihzKXJldHVybiIvIn1lbHNlIGlmKHImJiFDLnhCLm5DKHQsIi8iKSl0PSIvIit0CnJl
+dHVybiBQLkpyKHQsZSxmKX0sCkpyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLmxlbmd0aD09PTAKaWYo
+dCYmIWMmJiFDLnhCLm5DKGEsIi8iKSlyZXR1cm4gUC53RihhLCF0fHxjKQpyZXR1cm4gUC54ZShhKX0s
+CmxlOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHM9e30KaWYoYSE9bnVsbCl7aWYoZCE9bnVsbCl0aHJv
+dyBILmIoUC54WSgiQm90aCBxdWVyeSBhbmQgcXVlcnlQYXJhbWV0ZXJzIHNwZWNpZmllZCIpKQpyZXR1
+cm4gUC51TyhhLGIsYyxDLlZDLCEwKX1pZihkPT1udWxsKXJldHVybiBudWxsCnQ9bmV3IFAuUm4oIiIp
+CnMuYT0iIgpkLlUoMCxuZXcgUC55NShuZXcgUC5NRShzLHQpKSkKcz10LmEKcmV0dXJuIHMuY2hhckNv
+ZGVBdCgwKT09MD9zOnN9LAp0RzpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4gbnVsbApy
+ZXR1cm4gUC51TyhhLGIsYyxDLlZDLCEwKX0sCnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxw
+LG89YisyCmlmKG8+PWEubGVuZ3RoKXJldHVybiIlIgp0PUMueEIuTzIoYSxiKzEpCnM9Qy54Qi5PMihh
+LG8pCnI9SC5vbyh0KQpxPUgub28ocykKaWYocjwwfHxxPDApcmV0dXJuIiUiCnA9cioxNitxCmlmKHA8
+MTI3KXtvPUMuam4ud0cocCw0KQppZihvPj04KXJldHVybiBILk9IKEMuRjMsbykKbz0oQy5GM1tvXSYx
+PDwocCYxNSkpIT09MH1lbHNlIG89ITEKaWYobylyZXR1cm4gSC5MdyhjJiY2NTw9cCYmOTA+PXA/KHB8
+MzIpPj4+MDpwKQppZih0Pj05N3x8cz49OTcpcmV0dXJuIEMueEIuTmooYSxiLGIrMykudG9VcHBlckNh
+c2UoKQpyZXR1cm4gbnVsbH0sCkhIOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuPSIwMTIzNDU2
+Nzg5QUJDREVGIgppZihhPDEyOCl7dD1uZXcgQXJyYXkoMykKdC5maXhlZCRsZW5ndGg9QXJyYXkKcz1I
+LlZNKHQsdS50KQpDLk5tLlkocywwLDM3KQpDLk5tLlkocywxLEMueEIuV2QobixhPj4+NCkpCkMuTm0u
+WShzLDIsQy54Qi5XZChuLGEmMTUpKX1lbHNle2lmKGE+MjA0NylpZihhPjY1NTM1KXtyPTI0MApxPTR9
+ZWxzZXtyPTIyNApxPTN9ZWxzZXtyPTE5MgpxPTJ9dD1uZXcgQXJyYXkoMypxKQp0LmZpeGVkJGxlbmd0
+aD1BcnJheQpzPUguVk0odCx1LnQpCmZvcihwPTA7LS1xLHE+PTA7cj0xMjgpe289Qy5qbi5iZihhLDYq
+cSkmNjN8cgpDLk5tLlkocyxwLDM3KQpDLk5tLlkocyxwKzEsQy54Qi5XZChuLG8+Pj40KSkKQy5ObS5Z
+KHMscCsyLEMueEIuV2QobixvJjE1KSkKcCs9M319cmV0dXJuIFAuSE0ocywwLG51bGwpfSwKdU86ZnVu
+Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1QLlVsKGEsYixjLGQsZSkKcmV0dXJuIHQ9PW51bGw/Qy54Qi5O
+aihhLGIsYyk6dH0sClVsOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscCxvPW51bGwsbj0h
+ZSxtPWIsbD1tLGs9bwp3aGlsZSghMCl7aWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5KKCkK
+aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQppZighKG08YykpYnJlYWsKYyQwOnt0
+PUMueEIuTzIoYSxtKQppZih0PDEyNyl7cz10Pj4+NAppZihzPj04KXJldHVybiBILk9IKGQscykKcz0o
+ZFtzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKaWYocykrK20KZWxzZXtpZih0PT09Mzcpe3I9UC5y
+dihhLG0sITEpCmlmKHI9PW51bGwpe20rPTMKYnJlYWsgYyQwfWlmKCIlIj09PXIpe3I9IiUyNSIKcT0x
+fWVsc2UgcT0zfWVsc2V7aWYobilpZih0PD05Myl7cz10Pj4+NAppZihzPj04KXJldHVybiBILk9IKEMu
+YWsscykKcz0oQy5ha1tzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKZWxzZSBzPSExCmlmKHMpe1Au
+UjMoYSxtLCJJbnZhbGlkIGNoYXJhY3RlciIpCnE9bwpyPXF9ZWxzZXtpZigodCY2NDUxMik9PT01NTI5
+Nil7cz1tKzEKaWYoczxjKXtwPUMueEIuTzIoYSxzKQppZigocCY2NDUxMik9PT01NjMyMCl7dD02NTUz
+NnwodCYxMDIzKTw8MTB8cCYxMDIzCnE9Mn1lbHNlIHE9MX1lbHNlIHE9MX1lbHNlIHE9MQpyPVAuSEgo
+dCl9fWlmKGs9PW51bGwpaz1uZXcgUC5SbigiIikKay5hKz1DLnhCLk5qKGEsbCxtKQprLmErPUguZChy
+KQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBILnBZKHEpCm0rPXEKbD1tfX19aWYoaz09bnVs
+bClyZXR1cm4gbwppZih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkooKQppZihsPGMpay5hKz1D
+LnhCLk5qKGEsbCxjKQpuPWsuYQpyZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0wP246bn0sCnlCOmZ1bmN0
+aW9uKGEpe2lmKEMueEIubkMoYSwiLiIpKXJldHVybiEwCnJldHVybiBDLnhCLk9ZKGEsIi8uIikhPT0t
+MX0sCnhlOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuCmlmKCFQLnlCKGEpKXJldHVybiBhCnQ9
+SC5WTShbXSx1LnMpCmZvcihzPWEuc3BsaXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ap
+e289c1twXQppZihKLlJNKG8sIi4uIikpe249dC5sZW5ndGgKaWYobiE9PTApe2lmKDA+PW4pcmV0dXJu
+IEguT0godCwtMSkKdC5wb3AoKQppZih0Lmxlbmd0aD09PTApQy5ObS5BKHQsIiIpfXE9ITB9ZWxzZSBp
+ZigiLiI9PT1vKXE9ITAKZWxzZXtDLk5tLkEodCxvKQpxPSExfX1pZihxKUMuTm0uQSh0LCIiKQpyZXR1
+cm4gQy5ObS56Vih0LCIvIil9LAp3RjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbwppZighUC55
+QihhKSlyZXR1cm4hYj9QLkMxKGEpOmEKdD1ILlZNKFtdLHUucykKZm9yKHM9YS5zcGxpdCgiLyIpLHI9
+cy5sZW5ndGgscT0hMSxwPTA7cDxyOysrcCl7bz1zW3BdCmlmKCIuLiI9PT1vKWlmKHQubGVuZ3RoIT09
+MCYmQy5ObS5ncloodCkhPT0iLi4iKXtpZigwPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LC0xKQp0LnBv
+cCgpCnE9ITB9ZWxzZXtDLk5tLkEodCwiLi4iKQpxPSExfWVsc2UgaWYoIi4iPT09bylxPSEwCmVsc2V7
+Qy5ObS5BKHQsbykKcT0hMX19cz10Lmxlbmd0aAppZihzIT09MClpZihzPT09MSl7aWYoMD49cylyZXR1
+cm4gSC5PSCh0LDApCnM9dFswXS5sZW5ndGg9PT0wfWVsc2Ugcz0hMQplbHNlIHM9ITAKaWYocylyZXR1
+cm4iLi8iCmlmKHF8fEMuTm0uZ3JaKHQpPT09Ii4uIilDLk5tLkEodCwiIikKaWYoIWIpe2lmKDA+PXQu
+bGVuZ3RoKXJldHVybiBILk9IKHQsMCkKQy5ObS5ZKHQsMCxQLkMxKHRbMF0pKX1yZXR1cm4gQy5ObS56
+Vih0LCIvIil9LApDMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aAppZihxPj0yJiZQLkV0
+KEouUXooYSwwKSkpZm9yKHQ9MTt0PHE7Kyt0KXtzPUMueEIuV2QoYSx0KQppZihzPT09NTgpcmV0dXJu
+IEMueEIuTmooYSwwLHQpKyIlM0EiK0MueEIueW4oYSx0KzEpCmlmKHM8PTEyNyl7cj1zPj4+NAppZihy
+Pj04KXJldHVybiBILk9IKEMubUsscikKcj0oQy5tS1tyXSYxPDwocyYxNSkpPT09MH1lbHNlIHI9ITAK
+aWYocilicmVha31yZXR1cm4gYX0sCm1uOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEuZ0ZqKCkscD1x
+Lmxlbmd0aAppZihwPjAmJkouSG0ocVswXSk9PT0yJiZKLmE2KHFbMF0sMSk9PT01OCl7aWYoMD49cCly
+ZXR1cm4gSC5PSChxLDApClAucmcoSi5hNihxWzBdLDApLCExKQpQLkhOKHEsITEsMSkKdD0hMH1lbHNl
+e1AuSE4ocSwhMSwwKQp0PSExfXM9YS5ndFQoKSYmIXQ/IlxcIjoiIgppZihhLmdjaigpKXtyPWEuZ0pm
+KGEpCmlmKHIubGVuZ3RoIT09MClzPXMrIlxcIityKyJcXCJ9cz1QLnZnKHMscSwiXFwiKQpwPXQmJnA9
+PT0xP3MrIlxcIjpzCnJldHVybiBwLmNoYXJDb2RlQXQoMCk9PTA/cDpwfSwKSWg6ZnVuY3Rpb24oYSxi
+KXt2YXIgdCxzLHIKZm9yKHQ9MCxzPTA7czwyOysrcyl7cj1DLnhCLldkKGEsYitzKQppZig0ODw9ciYm
+cjw9NTcpdD10KjE2K3ItNDgKZWxzZXtyfD0zMgppZig5Nzw9ciYmcjw9MTAyKXQ9dCoxNityLTg3CmVs
+c2UgdGhyb3cgSC5iKFAueFkoIkludmFsaWQgVVJMIGVuY29kaW5nIikpfX1yZXR1cm4gdH0sCmt1OmZ1
+bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscD1KLnJZKGEpLG89Ygp3aGlsZSghMCl7aWYoIShv
+PGMpKXt0PSEwCmJyZWFrfXM9cC5XZChhLG8pCmlmKHM8PTEyNylpZihzIT09Mzcpcj1lJiZzPT09NDMK
+ZWxzZSByPSEwCmVsc2Ugcj0hMAppZihyKXt0PSExCmJyZWFrfSsrb31pZih0KXtpZihDLnhNIT09ZCly
+PSExCmVsc2Ugcj0hMAppZihyKXJldHVybiBwLk5qKGEsYixjKQplbHNlIHE9bmV3IEgucWoocC5Oaihh
+LGIsYykpfWVsc2V7cT1ILlZNKFtdLHUudCkKZm9yKG89YjtvPGM7KytvKXtzPXAuV2QoYSxvKQppZihz
+PjEyNyl0aHJvdyBILmIoUC54WSgiSWxsZWdhbCBwZXJjZW50IGVuY29kaW5nIGluIFVSSSIpKQppZihz
+PT09Mzcpe2lmKG8rMz5hLmxlbmd0aCl0aHJvdyBILmIoUC54WSgiVHJ1bmNhdGVkIFVSSSIpKQpDLk5t
+LkEocSxQLkloKGEsbysxKSkKbys9Mn1lbHNlIGlmKGUmJnM9PT00MylDLk5tLkEocSwzMikKZWxzZSBD
+Lk5tLkEocSxzKX19dS5MLmIocSkKcmV0dXJuIG5ldyBQLkdZKCExKS5XSihxKX0sCkV0OmZ1bmN0aW9u
+KGEpe3ZhciB0PWF8MzIKcmV0dXJuIDk3PD10JiZ0PD0xMjJ9LApLRDpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQscyxyLHEscCxvLG4sbSxsPSJJbnZhbGlkIE1JTUUgdHlwZSIsaz1ILlZNKFtiLTFdLHUudCkKZm9y
+KHQ9YS5sZW5ndGgscz1iLHI9LTEscT1udWxsO3M8dDsrK3Mpe3E9Qy54Qi5XZChhLHMpCmlmKHE9PT00
+NHx8cT09PTU5KWJyZWFrCmlmKHE9PT00Nyl7aWYocjwwKXtyPXMKY29udGludWV9dGhyb3cgSC5iKFAu
+cnIobCxhLHMpKX19aWYocjwwJiZzPmIpdGhyb3cgSC5iKFAucnIobCxhLHMpKQpmb3IoO3EhPT00NDsp
+e0MuTm0uQShrLHMpOysrcwpmb3IocD0tMTtzPHQ7KytzKXtxPUMueEIuV2QoYSxzKQppZihxPT09NjEp
+e2lmKHA8MClwPXN9ZWxzZSBpZihxPT09NTl8fHE9PT00NClicmVha31pZihwPj0wKUMuTm0uQShrLHAp
+CmVsc2V7bz1DLk5tLmdyWihrKQppZihxIT09NDR8fHMhPT1vKzd8fCFDLnhCLlFpKGEsImJhc2U2NCIs
+bysxKSl0aHJvdyBILmIoUC5ycigiRXhwZWN0aW5nICc9JyIsYSxzKSkKYnJlYWt9fUMuTm0uQShrLHMp
+Cm49cysxCmlmKChrLmxlbmd0aCYxKT09PTEpYT1DLmg5LnlyKDAsYSxuLHQpCmVsc2V7bT1QLlVsKGEs
+bix0LEMuVkMsITApCmlmKG0hPW51bGwpYT1DLnhCLmk3KGEsbix0LG0pfXJldHVybiBuZXcgUC5QRShh
+LGssYyl9LAp1eDpmdW5jdGlvbigpe3ZhciB0PSIwMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RV
+VldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei0uX34hJCYnKCkqKyw7PSIscz0iLiIscj0iOiIs
+cT0iLyIscD0iPyIsbz0iIyIsbj11LmdjLG09UC5kSCgyMixuZXcgUC5xMygpLCEwLG4pLGw9bmV3IFAu
+eUkobSksaz1uZXcgUC5jNigpLGo9bmV3IFAucWQoKSxpPW4uYihsLiQyKDAsMjI1KSkKay4kMyhpLHQs
+MSkKay4kMyhpLHMsMTQpCmsuJDMoaSxyLDM0KQprLiQzKGkscSwzKQprLiQzKGkscCwxNzIpCmsuJDMo
+aSxvLDIwNSkKaT1uLmIobC4kMigxNCwyMjUpKQprLiQzKGksdCwxKQprLiQzKGkscywxNSkKay4kMyhp
+LHIsMzQpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIo
+MTUsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLCIlIiwyMjUpCmsuJDMoaSxyLDM0KQprLiQzKGkscSw5
+KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMigxLDIyNSkpCmsuJDMoaSx0LDEp
+CmsuJDMoaSxyLDM0KQprLiQzKGkscSwxMCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5i
+KGwuJDIoMiwyMzUpKQprLiQzKGksdCwxMzkpCmsuJDMoaSxxLDEzMSkKay4kMyhpLHMsMTQ2KQprLiQz
+KGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMigzLDIzNSkpCmsuJDMoaSx0LDExKQprLiQz
+KGkscSw2OCkKay4kMyhpLHMsMTgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQy
+KDQsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJBWiIsMjI5KQprLiQzKGksciwxMDIpCmsuJDMoaSwi
+QCIsNjgpCmsuJDMoaSwiWyIsMjMyKQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
+MjA1KQppPW4uYihsLiQyKDUsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJBWiIsMjI5KQprLiQzKGks
+ciwxMDIpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywy
+MDUpCmk9bi5iKGwuJDIoNiwyMzEpKQpqLiQzKGksIjE5Iiw3KQprLiQzKGksIkAiLDY4KQprLiQzKGks
+cSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDcsMjMxKSkKai4kMyhp
+LCIwOSIsNykKay4kMyhpLCJAIiw2OCkKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxv
+LDIwNSkKay4kMyhuLmIobC4kMig4LDgpKSwiXSIsNSkKaT1uLmIobC4kMig5LDIzNSkpCmsuJDMoaSx0
+LDExKQprLiQzKGkscywxNikKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkK
+aT1uLmIobC4kMigxNiwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTcpCmsuJDMoaSxxLDIzNCkK
+ay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTcsMjM1KSkKay4kMyhpLHQsMTEp
+CmsuJDMoaSxxLDkpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDEwLDIzNSkp
+CmsuJDMoaSx0LDExKQprLiQzKGkscywxOCkKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIpCmsuJDMo
+aSxvLDIwNSkKaT1uLmIobC4kMigxOCwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTkpCmsuJDMo
+aSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTksMjM1KSkKay4k
+MyhpLHQsMTEpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwu
+JDIoMTEsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDEwKQprLiQzKGkscCwxNzIpCmsuJDMoaSxv
+LDIwNSkKaT1uLmIobC4kMigxMiwyMzYpKQprLiQzKGksdCwxMikKay4kMyhpLHAsMTIpCmsuJDMoaSxv
+LDIwNSkKaT1uLmIobC4kMigxMywyMzcpKQprLiQzKGksdCwxMykKay4kMyhpLHAsMTMpCmouJDMobi5i
+KGwuJDIoMjAsMjQ1KSksImF6IiwyMSkKbD1uLmIobC4kMigyMSwyNDUpKQpqLiQzKGwsImF6IiwyMSkK
+ai4kMyhsLCIwOSIsMjEpCmsuJDMobCwiKy0uIiwyMSkKcmV0dXJuIG19LApVQjpmdW5jdGlvbihhLGIs
+YyxkLGUpe3ZhciB0LHMscixxLHAsbz0kLnZaKCkKZm9yKHQ9Si5yWShhKSxzPWI7czxjOysrcyl7aWYo
+ZDwwfHxkPj1vLmxlbmd0aClyZXR1cm4gSC5PSChvLGQpCnI9b1tkXQpxPXQuV2QoYSxzKV45NgppZihx
+Pjk1KXE9MzEKaWYocT49ci5sZW5ndGgpcmV0dXJuIEguT0gocixxKQpwPXJbcV0KZD1wJjMxCkMuTm0u
+WShlLHA+Pj41LHMpfXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7fSwKaVA6ZnVuY3Rpb24gaVAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCkNQOmZ1bmN0aW9uIENQKCl7fSwKWFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpmdW5jdGlvbiBDNihh
+KXt0aGlzLmE9YX0sCm46ZnVuY3Rpb24gbigpe30sCnU6ZnVuY3Rpb24gdShhLGIsYyxkKXt2YXIgXz10
+aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKYko6ZnVuY3Rpb24gYkooYSxiLGMsZCxlLGYpe3Zh
+ciBfPXRoaXMKXy5lPWEKXy5mPWIKXy5hPWMKXy5iPWQKXy5jPWUKXy5kPWZ9LAplWTpmdW5jdGlvbiBl
+WShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5mPWEKXy5hPWIKXy5iPWMKXy5jPWQKXy5kPWV9LAptcDpm
+dW5jdGlvbiBtcChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKdWI6
+ZnVuY3Rpb24gdWIoYSl7dGhpcy5hPWF9LApkczpmdW5jdGlvbiBkcyhhKXt0aGlzLmE9YX0sCmxqOmZ1
+bmN0aW9uIGxqKGEpe3RoaXMuYT1hfSwKVVY6ZnVuY3Rpb24gVVYoYSl7dGhpcy5hPWF9LAprNTpmdW5j
+dGlvbiBrNSgpe30sCktZOmZ1bmN0aW9uIEtZKCl7fSwKYzpmdW5jdGlvbiBjKGEpe3RoaXMuYT1hfSwK
+Q0Q6ZnVuY3Rpb24gQ0QoYSl7dGhpcy5hPWF9LAphRTpmdW5jdGlvbiBhRShhLGIsYyl7dGhpcy5hPWEK
+dGhpcy5iPWIKdGhpcy5jPWN9LApFSDpmdW5jdGlvbiBFSCgpe30sCktOOmZ1bmN0aW9uIEtOKCl7fSwK
+Y1g6ZnVuY3Rpb24gY1goKXt9LApBbjpmdW5jdGlvbiBBbigpe30sCnpNOmZ1bmN0aW9uIHpNKCl7fSwK
+WjA6ZnVuY3Rpb24gWjAoKXt9LApOMzpmdW5jdGlvbiBOMyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIK
+dGhpcy4kdGk9Y30sCmM4OmZ1bmN0aW9uIGM4KCl7fSwKRks6ZnVuY3Rpb24gRksoKXt9LAprOmZ1bmN0
+aW9uIGsoKXt9LApPZDpmdW5jdGlvbiBPZCgpe30sCmliOmZ1bmN0aW9uIGliKCl7fSwKeHU6ZnVuY3Rp
+b24geHUoKXt9LApHejpmdW5jdGlvbiBHeigpe30sCnFVOmZ1bmN0aW9uIHFVKCl7fSwKUm46ZnVuY3Rp
+b24gUm4oYSl7dGhpcy5hPWF9LApHRDpmdW5jdGlvbiBHRCgpe30sCm4xOmZ1bmN0aW9uIG4xKGEpe3Ro
+aXMuYT1hfSwKY1M6ZnVuY3Rpb24gY1MoYSl7dGhpcy5hPWF9LApWQzpmdW5jdGlvbiBWQyhhKXt0aGlz
+LmE9YX0sCkpUOmZ1bmN0aW9uIEpUKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApEbjpmdW5jdGlvbiBE
+bihhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8u
+Zj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1udWxsfSwKZTE6ZnVuY3Rpb24gZTEoYSxiKXt0aGlzLmE9
+YQp0aGlzLmI9Yn0sCk5ZOmZ1bmN0aW9uIE5ZKGEpe3RoaXMuYT1hfSwKUlo6ZnVuY3Rpb24gUlooKXt9
+LApNRTpmdW5jdGlvbiBNRShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKeTU6ZnVuY3Rpb24geTUoYSl7
+dGhpcy5hPWF9LApQRTpmdW5jdGlvbiBQRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LApxMzpmdW5jdGlvbiBxMygpe30sCnlJOmZ1bmN0aW9uIHlJKGEpe3RoaXMuYT1hfSwKYzY6ZnVuY3Rp
+b24gYzYoKXt9LApxZDpmdW5jdGlvbiBxZCgpe30sClVmOmZ1bmN0aW9uIFVmKGEsYixjLGQsZSxmLGcs
+aCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9ZwpfLng9
+aApfLnk9bnVsbH0sCnFlOmZ1bmN0aW9uIHFlKGEsYixjLGQsZSxmLGcpe3ZhciBfPXRoaXMKXy5hPWEK
+Xy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy5RPV8uej1fLnk9Xy54PW51bGx9LApt
+UjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKdD1QLkZsKHUu
+Tix1LnopCnM9T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoYSkKZm9yKHI9cy5sZW5ndGgscT0wO3E8
+cy5sZW5ndGg7cy5sZW5ndGg9PT1yfHwoMCxILmxrKShzKSwrK3Epe3A9SC55KHNbcV0pCnQuWSgwLHAs
+YVtwXSl9cmV0dXJuIHR9LAppNjpmdW5jdGlvbiBpNigpe30sCmxSOmZ1bmN0aW9uIGxSKGEsYil7dGhp
+cy5hPWEKdGhpcy5iPWJ9LApqZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKYUo6
+ZnVuY3Rpb24gYUooKXt9LApLNTpmdW5jdGlvbiBLNShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQmY6
+ZnVuY3Rpb24gQmYoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnpnOmZ1bmN0aW9uIHpnKGEsYil7dGhp
+cy5hPWEKdGhpcy5iPWIKdGhpcy5jPSExfSwKZE06ZnVuY3Rpb24gZE0oKXt9LApHRTpmdW5jdGlvbiBH
+RShhKXt0aGlzLmE9YX0sCk43OmZ1bmN0aW9uIE43KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp1UTpm
+dW5jdGlvbiB1USgpe30sClcyOmZ1bmN0aW9uIFcyKCl7fSwKZTM6ZnVuY3Rpb24gZTMoKXt9LApoRjpm
+dW5jdGlvbiBoRigpe30sCkJWOmZ1bmN0aW9uIEJWKCl7fSwKUjQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQscyxyCkgueGQoYikKdS5qLmIoZCkKaWYoSC5vVChiKSl7dD1bY10KQy5ObS5GVih0LGQpCmQ9dH1z
+PXUuegpyPVAuQ0goSi5NMShkLFAudzAoKSxzKSwhMCxzKQp1LlouYihhKQpyZXR1cm4gUC53WShILkVr
+KGEscixudWxsKSl9LApEbTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKdHJ5e2lmKE9iamVjdC5pc0V4dGVu
+c2libGUoYSkmJiFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYSxiKSl7T2JqZWN0
+LmRlZmluZVByb3BlcnR5KGEsYix7dmFsdWU6Y30pCnJldHVybiEwfX1jYXRjaCh0KXtILlJ1KHQpfXJl
+dHVybiExfSwKT206ZnVuY3Rpb24oYSxiKXtpZihPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5
+LmNhbGwoYSxiKSlyZXR1cm4gYVtiXQpyZXR1cm4gbnVsbH0sCndZOmZ1bmN0aW9uKGEpe2lmKGE9PW51
+bGx8fHR5cGVvZiBhPT0ic3RyaW5nInx8dHlwZW9mIGE9PSJudW1iZXIifHxILmwoYSkpcmV0dXJuIGEK
+aWYoYSBpbnN0YW5jZW9mIFAuRTQpcmV0dXJuIGEuYQppZihILlI5KGEpKXJldHVybiBhCmlmKHUudy5j
+KGEpKXJldHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBILm8yKGEpCmlmKHUuWi5jKGEp
+KXJldHVybiBQLmIzKGEsIiRkYXJ0X2pzRnVuY3Rpb24iLG5ldyBQLlBDKCkpCnJldHVybiBQLmIzKGEs
+Il8kZGFydF9qc09iamVjdCIsbmV3IFAubXQoJC5rSSgpKSl9LApiMzpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQ9UC5PbShhLGIpCmlmKHQ9PW51bGwpe3Q9Yy4kMShhKQpQLkRtKGEsYix0KX1yZXR1cm4gdH0sCkw3
+OmZ1bmN0aW9uKGEpe3ZhciB0LHMKaWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2Yg
+YT09Im51bWJlciJ8fHR5cGVvZiBhPT0iYm9vbGVhbiIpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNl
+b2YgT2JqZWN0JiZILlI5KGEpKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIE9iamVjdCYmdS53
+LmMoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgRGF0ZSl7dD1ILlNjKGEuZ2V0VGltZSgp
+KQpzPW5ldyBQLmlQKHQsITEpCnMuWGsodCwhMSkKcmV0dXJuIHN9ZWxzZSBpZihhLmNvbnN0cnVjdG9y
+PT09JC5rSSgpKXJldHVybiBhLm8KZWxzZSByZXR1cm4gUC5ORChhKX0sCk5EOmZ1bmN0aW9uKGEpe2lm
+KHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBQLmlRKGEsJC53KCksbmV3IFAuTnooKSkKaWYoYSBp
+bnN0YW5jZW9mIEFycmF5KXJldHVybiBQLmlRKGEsJC5SOCgpLG5ldyBQLm5wKCkpCnJldHVybiBQLmlR
+KGEsJC5SOCgpLG5ldyBQLlV0KCkpfSwKaVE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PVAuT20oYSxiKQpp
+Zih0PT1udWxsfHwhKGEgaW5zdGFuY2VvZiBPYmplY3QpKXt0PWMuJDEoYSkKUC5EbShhLGIsdCl9cmV0
+dXJuIHR9LApQQzpmdW5jdGlvbiBQQygpe30sCm10OmZ1bmN0aW9uIG10KGEpe3RoaXMuYT1hfSwKTno6
+ZnVuY3Rpb24gTnooKXt9LApucDpmdW5jdGlvbiBucCgpe30sClV0OmZ1bmN0aW9uIFV0KCl7fSwKRTQ6
+ZnVuY3Rpb24gRTQoYSl7dGhpcy5hPWF9LApyNzpmdW5jdGlvbiByNyhhKXt0aGlzLmE9YX0sClR6OmZ1
+bmN0aW9uIFR6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmNvOmZ1bmN0aW9uIGNvKCl7fSwKVTg6
+ZnVuY3Rpb24oYSxiKXt2YXIgdD1uZXcgUC52cygkLlgzLGIuQygidnM8MD4iKSkscz1uZXcgUC5aZih0
+LGIuQygiWmY8MD4iKSkKYS50aGVuKEgudFIobmV3IFAudksocyxiKSwxKSxILnRSKG5ldyBQLnBVKHMp
+LDEpKQpyZXR1cm4gdH0sCnZLOmZ1bmN0aW9uIHZLKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApwVTpm
+dW5jdGlvbiBwVShhKXt0aGlzLmE9YX0sCklOOmZ1bmN0aW9uIElOKCl7fSwKdG46ZnVuY3Rpb24gdG4o
+KXt9LAp1ajpmdW5jdGlvbiB1aigpe30sCngwOmZ1bmN0aW9uIHgwKCl7fSwKcTY6ZnVuY3Rpb24gcTYo
+KXt9LAp1UDpmdW5jdGlvbiB1UCgpe30sCmZ6OmZ1bmN0aW9uIGZ6KCl7fSwKRUQ6ZnVuY3Rpb24gRUQo
+KXt9LApuZDpmdW5jdGlvbiBuZCgpe30sCktxOmZ1bmN0aW9uIEtxKCl7fSwKS2U6ZnVuY3Rpb24gS2Uo
+YSl7dGhpcy5hPWF9LApkNTpmdW5jdGlvbiBkNSgpe30sCnpZOmZ1bmN0aW9uIHpZKCl7fSwKTkM6ZnVu
+Y3Rpb24gTkMoKXt9LApmVTpmdW5jdGlvbiBmVSgpe30sCkdDOmZ1bmN0aW9uIEdDKCl7fSwKakc6ZnVu
+Y3Rpb24gakcoKXt9LApqUzpmdW5jdGlvbiBqUygpe30sCnhXOmZ1bmN0aW9uIHhXKCl7fSwKZFM6ZnVu
+Y3Rpb24gZFMoKXt9LAp3ajpmdW5jdGlvbiB3aigpe30sCk1ZOmZ1bmN0aW9uIE1ZKCl7fSwKbjY6ZnVu
+Y3Rpb24gbjYoKXt9LApyMjpmdW5jdGlvbiByMigpe30sCnJPOmZ1bmN0aW9uIHJPKCl7fSwKejg6ZnVu
+Y3Rpb24gejgoKXt9LApxZjpmdW5jdGlvbiBxZihhKXt0aGlzLmE9YX0sCmZvOmZ1bmN0aW9uIGZvKCl7
+fSwKVjg6ZnVuY3Rpb24gVjgoKXt9LApHbjpmdW5jdGlvbiBHbigpe30sClUzOmZ1bmN0aW9uIFUzKCl7
+fSwKRm46ZnVuY3Rpb24gRm4oKXt9LAptbzpmdW5jdGlvbiBtbygpe30sCktnOmZ1bmN0aW9uIEtnKCl7
+fX0sVz17CngzOmZ1bmN0aW9uKCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7cmV0dXJuIGRv
+Y3VtZW50fSwKVTk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PWRvY3VtZW50LmJvZHkscz0odCYmQy5SWSku
+cjYodCxhLGIsYykKcy50b1N0cmluZwp0PXUuYWMKdD1uZXcgSC5VNShuZXcgVy5lNyhzKSx0LkMoImEy
+KGxELkUpIikuYihuZXcgVy5DdigpKSx0LkMoIlU1PGxELkU+IikpCnJldHVybiB1LmguYih0LmdyOCh0
+KSl9LApyUzpmdW5jdGlvbihhKXt2YXIgdCxzLHI9ImVsZW1lbnQgdGFnIHVuYXZhaWxhYmxlIgp0cnl7
+dD1KLlJFKGEpCmlmKHR5cGVvZiB0LmducyhhKT09InN0cmluZyIpcj10LmducyhhKX1jYXRjaChzKXtI
+LlJ1KHMpfXJldHVybiByfSwKcUQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPW5ldyBQLnZzKCQu
+WDMsdS5hbykscD1uZXcgUC5aZihxLHUuYmopLG89bmV3IFhNTEh0dHBSZXF1ZXN0KCkKQy5EdC5lbyhv
+LGI9PW51bGw/IkdFVCI6YixhLCEwKQpjLlUoMCxuZXcgVy5iVShvKSkKdD11LmFuCnM9dC5iKG5ldyBX
+LmhIKG8scCkpCnUuTS5iKG51bGwpCnI9dS5wClcuSkUobywibG9hZCIscywhMSxyKQpXLkpFKG8sImVy
+cm9yIix0LmIocC5nWUooKSksITEscikKby5zZW5kKCkKcmV0dXJuIHF9LApDMDpmdW5jdGlvbihhLGIp
+e2E9NTM2ODcwOTExJmErYgphPTUzNjg3MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0dXJuIGFeYT4+
+PjZ9LApyRTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1XLkMwKFcuQzAoVy5DMChXLkMwKDAsYSksYiks
+YyksZCkscz01MzY4NzA5MTEmdCsoKDY3MTA4ODYzJnQpPDwzKQpzXj1zPj4+MTEKcmV0dXJuIDUzNjg3
+MDkxMSZzKygoMTYzODMmcyk8PDE1KX0sClROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPWEuY2xhc3NM
+aXN0CmZvcih0PWIubGVuZ3RoLHM9MDtzPGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAsSC5saykoYiks
+KytzKXIuYWRkKGJbc10pfSwKSkU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1XLmFGKG5ldyBXLnZO
+KGMpLHUuQikKaWYodCE9bnVsbCYmITApSi5kWihhLGIsdCwhMSkKcmV0dXJuIG5ldyBXLnhDKGEsYix0
+LCExLGUuQygieEM8MD4iKSl9LApUdzpmdW5jdGlvbihhKXt2YXIgdD1kb2N1bWVudC5jcmVhdGVFbGVt
+ZW50KCJhIikscz1uZXcgVy5tayh0LHdpbmRvdy5sb2NhdGlvbikKcz1uZXcgVy5KUShzKQpzLkNZKGEp
+CnJldHVybiBzfSwKVXc6ZnVuY3Rpb24oYSxiLGMsZCl7dS5oLmIoYSkKSC55KGIpCkgueShjKQp1LkUu
+YihkKQpyZXR1cm4hMH0sCm5aOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscgp1LmguYihhKQpILnko
+YikKSC55KGMpCnQ9dS5FLmIoZCkuYQpzPXQuYQpzLmhyZWY9YwpyPXMuaG9zdG5hbWUKdD10LmIKaWYo
+IShyPT10Lmhvc3RuYW1lJiZzLnBvcnQ9PXQucG9ydCYmcy5wcm90b2NvbD09dC5wcm90b2NvbCkpaWYo
+cj09PSIiKWlmKHMucG9ydD09PSIiKXt0PXMucHJvdG9jb2wKdD10PT09IjoifHx0PT09IiJ9ZWxzZSB0
+PSExCmVsc2UgdD0hMQplbHNlIHQ9ITAKcmV0dXJuIHR9LApCbDpmdW5jdGlvbigpe3ZhciB0PXUuTixz
+PVAudE0oQy5ReCx0KSxyPXUuZEcuYihuZXcgVy5JQSgpKSxxPUguVk0oWyJURU1QTEFURSJdLHUucykK
+dD1uZXcgVy5jdChzLFAuTHModCksUC5Mcyh0KSxQLkxzKHQpLG51bGwpCnQuQ1kobnVsbCxuZXcgSC5B
+OChDLlF4LHIsdS5kdikscSxudWxsKQpyZXR1cm4gdH0sCnVWOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwp
+cmV0dXJuIG51bGwKcmV0dXJuIFcuUDEoYSl9LApxYzpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxs
+KXJldHVybiBudWxsCmlmKCJwb3N0TWVzc2FnZSIgaW4gYSl7dD1XLlAxKGEpCnJldHVybiB0fWVsc2Ug
+cmV0dXJuIHUuYVMuYihhKX0sClAxOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cpcmV0dXJuIHUuY2ku
+YihhKQplbHNlIHJldHVybiBuZXcgVy5kVyhhKX0sCnpYOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cu
+bG9jYXRpb24pcmV0dXJuIGEKZWxzZSByZXR1cm4gbmV3IFcuRmIoKX0sCmFGOmZ1bmN0aW9uKGEsYil7
+dmFyIHQ9JC5YMwppZih0PT09Qy5OVSlyZXR1cm4gYQpyZXR1cm4gdC5QeShhLGIpfSwKcUU6ZnVuY3Rp
+b24gcUUoKXt9LApZZTpmdW5jdGlvbiBZZSgpe30sCkdoOmZ1bmN0aW9uIEdoKCl7fSwKZlk6ZnVuY3Rp
+b24gZlkoKXt9LApuQjpmdW5jdGlvbiBuQigpe30sCkF6OmZ1bmN0aW9uIEF6KCl7fSwKUFU6ZnVuY3Rp
+b24gUFUoKXt9LApRUDpmdW5jdGlvbiBRUCgpe30sCklGOmZ1bmN0aW9uIElGKCl7fSwKbng6ZnVuY3Rp
+b24gbngoKXt9LApSZDpmdW5jdGlvbiBSZCgpe30sCmtSOmZ1bmN0aW9uIGtSKCl7fSwKVGY6ZnVuY3Rp
+b24gVGYoKXt9LApsdzpmdW5jdGlvbiBsdygpe30sCm9KOmZ1bmN0aW9uIG9KKCl7fSwKaWQ6ZnVuY3Rp
+b24gaWQoKXt9LApCdzpmdW5jdGlvbiBCdygpe30sCm80OmZ1bmN0aW9uIG80KCl7fSwKSFM6ZnVuY3Rp
+b24gSFMoKXt9LApWbzpmdW5jdGlvbiBWbygpe30sCkZoOmZ1bmN0aW9uIEZoKCl7fSwKY3g6ZnVuY3Rp
+b24gY3goKXt9LApTYjpmdW5jdGlvbiBTYigpe30sClFGOmZ1bmN0aW9uIFFGKCl7fSwKTmg6ZnVuY3Rp
+b24gTmgoKXt9LApGdjpmdW5jdGlvbiBGdigpe30sCklCOmZ1bmN0aW9uIElCKCl7fSwKWWw6ZnVuY3Rp
+b24gWWwoKXt9LApuNzpmdW5jdGlvbiBuNygpe30sCnd6OmZ1bmN0aW9uIHd6KGEsYil7dGhpcy5hPWEK
+dGhpcy4kdGk9Yn0sCmN2OmZ1bmN0aW9uIGN2KCl7fSwKQ3Y6ZnVuY3Rpb24gQ3YoKXt9LApRSTpmdW5j
+dGlvbiBRSSgpe30sCmVhOmZ1bmN0aW9uIGVhKCl7fSwKRDA6ZnVuY3Rpb24gRDAoKXt9LApUNTpmdW5j
+dGlvbiBUNSgpe30sClhWOmZ1bmN0aW9uIFhWKCl7fSwKd0o6ZnVuY3Rpb24gd0ooKXt9LApoNDpmdW5j
+dGlvbiBoNCgpe30sCkdPOmZ1bmN0aW9uIEdPKCl7fSwKSkM6ZnVuY3Rpb24gSkMoKXt9LApicjpmdW5j
+dGlvbiBicigpe30sCnhuOmZ1bmN0aW9uIHhuKCl7fSwKVmI6ZnVuY3Rpb24gVmIoKXt9LApPNzpmdW5j
+dGlvbiBPNygpe30sCmJVOmZ1bmN0aW9uIGJVKGEpe3RoaXMuYT1hfSwKaEg6ZnVuY3Rpb24gaEgoYSxi
+KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCndhOmZ1bmN0aW9uIHdhKCl7fSwKU2c6ZnVuY3Rpb24gU2coKXt9
+LApKSzpmdW5jdGlvbiBKSygpe30sCkhMOmZ1bmN0aW9uIEhMKCl7fSwKd1A6ZnVuY3Rpb24gd1AoKXt9
+LAp1ODpmdW5jdGlvbiB1OCgpe30sCno2OmZ1bmN0aW9uIHo2KCl7fSwKbEs6ZnVuY3Rpb24gbEsoKXt9
+LApRYjpmdW5jdGlvbiBRYigpe30sClMwOmZ1bmN0aW9uIFMwKCl7fSwKRkE6ZnVuY3Rpb24gRkEoYSl7
+dGhpcy5hPWF9LAp6MjpmdW5jdGlvbiB6Migpe30sCnVxOmZ1bmN0aW9uIHVxKGEpe3RoaXMuYT1hfSwK
+QVc6ZnVuY3Rpb24gQVcoKXt9LApETTpmdW5jdGlvbiBETSgpe30sCkFqOmZ1bmN0aW9uIEFqKCl7fSwK
+ZTc6ZnVuY3Rpb24gZTcoYSl7dGhpcy5hPWF9LAp1SDpmdW5jdGlvbiB1SCgpe30sCkJIOmZ1bmN0aW9u
+IEJIKCl7fSwKUWw6ZnVuY3Rpb24gUWwoKXt9LApHWDpmdW5jdGlvbiBHWCgpe30sClNOOmZ1bmN0aW9u
+IFNOKCl7fSwKSEQ6ZnVuY3Rpb24gSEQoKXt9LApjbDpmdW5jdGlvbiBjbCgpe30sCkV2OmZ1bmN0aW9u
+IEV2KCl7fSwKTHI6ZnVuY3Rpb24gTHIoKXt9LApLUjpmdW5jdGlvbiBLUigpe30sCmV3OmZ1bmN0aW9u
+IGV3KCl7fSwKcDg6ZnVuY3Rpb24gcDgoKXt9LAppaTpmdW5jdGlvbiBpaShhKXt0aGlzLmE9YX0sCmxw
+OmZ1bmN0aW9uIGxwKCl7fSwKU1Y6ZnVuY3Rpb24gU1YoKXt9LApNazpmdW5jdGlvbiBNaygpe30sClk0
+OmZ1bmN0aW9uIFk0KCl7fSwKTm46ZnVuY3Rpb24gTm4oKXt9LApsODpmdW5jdGlvbiBsOCgpe30sCkFz
+OmZ1bmN0aW9uIEFzKCl7fSwKd1E6ZnVuY3Rpb24gd1EoYSl7dGhpcy5hPWF9LApiazpmdW5jdGlvbiBi
+aygpe30sCldXOmZ1bmN0aW9uIFdXKCl7fSwKVGI6ZnVuY3Rpb24gVGIoKXt9LApJdjpmdW5jdGlvbiBJ
+digpe30sCkJUOmZ1bmN0aW9uIEJUKCl7fSwKZlg6ZnVuY3Rpb24gZlgoKXt9LApGQjpmdW5jdGlvbiBG
+Qigpe30sCkExOmZ1bmN0aW9uIEExKCl7fSwKTU46ZnVuY3Rpb24gTU4oKXt9LApYMDpmdW5jdGlvbiBY
+MCgpe30sCm5KOmZ1bmN0aW9uIG5KKCl7fSwKbXo6ZnVuY3Rpb24gbXooKXt9LAphMzpmdW5jdGlvbiBh
+Mygpe30sCmNpOmZ1bmN0aW9uIGNpKCl7fSwKY246ZnVuY3Rpb24gY24oKXt9LAp3NjpmdW5jdGlvbiB3
+Nigpe30sCkZqOmZ1bmN0aW9uIEZqKCl7fSwKdkY6ZnVuY3Rpb24gdkYoKXt9LApPaTpmdW5jdGlvbiBP
+aSgpe30sCkNtOmZ1bmN0aW9uIENtKCl7fSwKQ1E6ZnVuY3Rpb24gQ1EoKXt9LApQUjpmdW5jdGlvbiBQ
+Uigpe30sCnc0OmZ1bmN0aW9uIHc0KCl7fSwKRjI6ZnVuY3Rpb24gRjIoKXt9LApyaDpmdW5jdGlvbiBy
+aCgpe30sCkxPOmZ1bmN0aW9uIExPKCl7fSwKYjE6ZnVuY3Rpb24gYjEoKXt9LAphVDpmdW5jdGlvbiBh
+VCgpe30sCmk3OmZ1bmN0aW9uIGk3KGEpe3RoaXMuYT1hfSwKU3k6ZnVuY3Rpb24gU3koYSl7dGhpcy5h
+PWF9LApLUzpmdW5jdGlvbiBLUyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQTM6ZnVuY3Rpb24gQTMo
+YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkk0OmZ1bmN0aW9uIEk0KGEpe3RoaXMuYT1hfSwKRms6ZnVu
+Y3Rpb24gRmsoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKUk86ZnVuY3Rpb24gUk8oYSxiLGMsZCl7
+dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKZXU6ZnVuY3Rpb24gZXUoYSxiLGMs
+ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKeEM6ZnVuY3Rpb24geEMoYSxi
+LGMsZCxlKXt2YXIgXz10aGlzCl8uYj1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2TjpmdW5j
+dGlvbiB2TihhKXt0aGlzLmE9YX0sCkpROmZ1bmN0aW9uIEpRKGEpe3RoaXMuYT1hfSwKR206ZnVuY3Rp
+b24gR20oKXt9LAp2RDpmdW5jdGlvbiB2RChhKXt0aGlzLmE9YX0sClV2OmZ1bmN0aW9uIFV2KGEpe3Ro
+aXMuYT1hfSwKRWc6ZnVuY3Rpb24gRWcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwK
+bTY6ZnVuY3Rpb24gbTYoKXt9LApFbzpmdW5jdGlvbiBFbygpe30sCldrOmZ1bmN0aW9uIFdrKCl7fSwK
+Y3Q6ZnVuY3Rpb24gY3QoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uZT1hCl8uYT1iCl8uYj1jCl8uYz1k
+Cl8uZD1lfSwKSUE6ZnVuY3Rpb24gSUEoKXt9LApPdzpmdW5jdGlvbiBPdygpe30sClc5OmZ1bmN0aW9u
+IFc5KGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0tMQpfLmQ9bnVsbApfLiR0aT1jfSwK
+ZFc6ZnVuY3Rpb24gZFcoYSl7dGhpcy5hPWF9LApGYjpmdW5jdGlvbiBGYigpe30sCmtGOmZ1bmN0aW9u
+IGtGKCl7fSwKbWs6ZnVuY3Rpb24gbWsoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCktvOmZ1bmN0aW9u
+IEtvKGEpe3RoaXMuYT1hfSwKZm06ZnVuY3Rpb24gZm0oYSl7dGhpcy5hPWF9LApMZTpmdW5jdGlvbiBM
+ZSgpe30sCkpVOmZ1bmN0aW9uIEpVKCl7fSwKeFg6ZnVuY3Rpb24geFgoKXt9LAp2ZTpmdW5jdGlvbiB2
+ZSgpe30sCmJHOmZ1bmN0aW9uIGJHKCl7fSwKdEk6ZnVuY3Rpb24gdEkoKXt9LApmZzpmdW5jdGlvbiBm
+Zygpe30sClo3OmZ1bmN0aW9uIFo3KCl7fSwKSFc6ZnVuY3Rpb24gSFcoKXt9LApsRzpmdW5jdGlvbiBs
+Rygpe30sCnFzOmZ1bmN0aW9uIHFzKCl7fSwKY3M6ZnVuY3Rpb24gY3MoKXt9LApLQjpmdW5jdGlvbiBL
+Qigpe30sCks3OmZ1bmN0aW9uIEs3KCl7fSwKckI6ZnVuY3Rpb24gckIoKXt9LApmVDpmdW5jdGlvbiBm
+VCgpe30sCmY3OmZ1bmN0aW9uIGY3KCl7fSwKYmc6ZnVuY3Rpb24gYmcoKXt9LApvSDpmdW5jdGlvbiBv
+SCgpe30sCkNFOmZ1bmN0aW9uIENFKCl7fSwKYUQ6ZnVuY3Rpb24gYUQoKXt9LApaeDpmdW5jdGlvbiBa
+eCgpe30sCk9YOmZ1bmN0aW9uIE9YKCl7fSwKVWo6ZnVuY3Rpb24gVWooKXt9LApqTTpmdW5jdGlvbiBq
+TSgpe30sClFWOmZ1bmN0aW9uIFFWKCl7fSwKQXc6ZnVuY3Rpb24gQXcoKXt9LAp0cjpmdW5jdGlvbiB0
+cigpe30sCk8zOmZ1bmN0aW9uIE8zKCl7fSwKT3Y6ZnVuY3Rpb24gT3YoKXt9LApjTzpmdW5jdGlvbiBj
+Tygpe30sCllEOmZ1bmN0aW9uIFlEKCl7fSwKRHg6ZnVuY3Rpb24gRHgoKXt9LApYVzpmdW5jdGlvbiBY
+Vygpe30sCm9hOmZ1bmN0aW9uIG9hKCl7fSwKWFU6ZnVuY3Rpb24gWFUoKXt9LApSeTpmdW5jdGlvbiBS
+eSgpe30sCnp2OmZ1bmN0aW9uIHp2KCl7fSwKbno6ZnVuY3Rpb24gbnooKXt9fSxVPXsKamY6ZnVuY3Rp
+b24oYSl7dmFyIHQscyxyLHEKaWYoYT09bnVsbCl0PW51bGwKZWxzZXt0PUguVk0oW10sdS5mQSkKZm9y
+KHM9Si5JVCh1LlIuYihhKSk7cy5tKCk7KXtyPXMuZ1IocykKcT1KLlU2KHIpCkMuTm0uQSh0LG5ldyBV
+LlNlKEgueShxLnEociwiZGVzY3JpcHRpb24iKSksSC55KHEucShyLCJocmVmIikpKSl9fXJldHVybiB0
+fSwKTmQ6ZnVuY3Rpb24oYSl7dmFyIHQscwppZihhPT1udWxsKXQ9bnVsbAplbHNle3Q9SC5WTShbXSx1
+LmhoKQpmb3Iocz1KLklUKHUuUi5iKGEpKTtzLm0oKTspQy5ObS5BKHQsVS5OZihzLmdSKHMpKSl9cmV0
+dXJuIHR9LApOZjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG89ImRlc2NyaXB0aW9uIixuPUouVTYo
+YSksbT1ILnkobi5xKGEsbykpLGw9SC5WTShbXSx1LmFKKQpmb3Iobj1KLklUKHUuUi5iKG4ucShhLCJl
+bnRyaWVzIikpKTtuLm0oKTspe3Q9bi5nUihuKQpzPUouVTYodCkKcj1ILnkocy5xKHQsbykpCnE9SC55
+KHMucSh0LCJmdW5jdGlvbiIpKQpzPXMucSh0LCJsaW5rIikKaWYocz09bnVsbClzPW51bGwKZWxzZXtw
+PUouVTYocykKcz1uZXcgVS5NbChILnkocC5xKHMsImhyZWYiKSksSC5TYyhwLnEocywibGluZSIpKSxI
+LnkocC5xKHMsInBhdGgiKSkpfUMuTm0uQShsLG5ldyBVLndiKHIscSxzKSl9cmV0dXJuIG5ldyBVLnlE
+KG0sbCl9LApkMjpmdW5jdGlvbiBkMihhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5j
+PWMKXy5kPWQKXy5lPWV9LApTZTpmdW5jdGlvbiBTZShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKTWw6
+ZnVuY3Rpb24gTWwoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKeUQ6ZnVuY3Rpb24g
+eUQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCndiOmZ1bmN0aW9uIHdiKGEsYixjKXt0aGlzLmE9YQp0
+aGlzLmI9Ygp0aGlzLmM9Y319LEI9ewpZZjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9
+Si5VNihhKSxrPUgueShsLnEoYSwicmVnaW9ucyIpKSxqPUgueShsLnEoYSwibmF2aWdhdGlvbkNvbnRl
+bnQiKSksaT1ILnkobC5xKGEsInNvdXJjZUNvZGUiKSksaD1QLkZsKHUuTix1LmY0KQpmb3IobD1KLklU
+KEouUU0obC5xKGEsImVkaXRzIikpKSx0PXUuUixzPXUuZ2k7bC5tKCk7KXtyPWwuZ1IobCkKcT1KLlJF
+KHIpCnA9SC55KHEuZ0czKHIpKQpvPUguVk0oW10scykKZm9yKHE9Si5JVCh0LmIocS5nbncocikpKTtx
+Lm0oKTspe249cS5nUihxKQptPUouVTYobikKQy5ObS5BKG8sbmV3IEIuajgoSC5TYyhtLnEobiwibGlu
+ZSIpKSxILnkobS5xKG4sImV4cGxhbmF0aW9uIikpLEguU2MobS5xKG4sIm9mZnNldCIpKSkpfWguWSgw
+LHAsbyl9cmV0dXJuIG5ldyBCLnFwKGssaixpLGgpfSwKajg6ZnVuY3Rpb24gajgoYSxiLGMpe3RoaXMu
+YT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcXA6ZnVuY3Rpb24gcXAoYSxiLGMsZCl7dmFyIF89dGhpcwpf
+LmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCkx1OmZ1bmN0aW9uIEx1KCl7fSwKT1M6ZnVuY3Rpb24oYSl7
+dmFyIHQKaWYoIShhPj02NSYmYTw9OTApKXQ9YT49OTcmJmE8PTEyMgplbHNlIHQ9ITAKcmV0dXJuIHR9
+LApZdTpmdW5jdGlvbihhLGIpe3ZhciB0PWEubGVuZ3RoLHM9YisyCmlmKHQ8cylyZXR1cm4hMQppZigh
+Qi5PUyhDLnhCLk8yKGEsYikpKXJldHVybiExCmlmKEMueEIuTzIoYSxiKzEpIT09NTgpcmV0dXJuITEK
+aWYodD09PXMpcmV0dXJuITAKcmV0dXJuIEMueEIuTzIoYSxzKT09PTQ3fX0sVD17bVE6ZnVuY3Rpb24g
+bVEoKXt9fSxMPXsKRGU6ZnVuY3Rpb24oKXtDLkJaLkIoZG9jdW1lbnQsIkRPTUNvbnRlbnRMb2FkZWQi
+LG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9wc3RhdGUiLG5ldyBMLkwoKSl9LAprejpmdW5jdGlv
+bihhKXt2YXIgdCxzPXUuaC5hKGEucGFyZW50Tm9kZSkucXVlcnlTZWxlY3RvcigiOnNjb3BlID4gdWwi
+KSxyPXMuc3R5bGUscT0iIitDLkNELnpRKHMub2Zmc2V0SGVpZ2h0KSoyKyJweCIKci5tYXhIZWlnaHQ9
+cQpyPUoucUYoYSkKcT1yLiR0aQp0PXEuQygifigxKSIpLmIobmV3IEwuV3gocyxhKSkKdS5NLmIobnVs
+bCkKVy5KRShyLmEsci5iLHQsITEscS5kKX0sCnlYOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxv
+PSJxdWVyeVNlbGVjdG9yQWxsIixuPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYSksbT11LmgKbi50b1N0
+cmluZwpILkRoKG0sbSwiVCIsbykKdD11LlMKcz1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5u
+YXYtbGluayIpLHQpCnMuVShzLG5ldyBMLkFPKGIpKQpILkRoKG0sbSwiVCIsbykKcj1uZXcgVy53eihu
+LnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdpb24iKSx0KQppZihyLmdoKHIpIT09MCl7cT1uLnF1ZXJ5U2Vs
+ZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQpxLnRvU3RyaW5nCnIuVShyLG5ldyBMLkhvKHEuZ2V0QXR0
+cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcocSkpLlMoInBhdGgiKSkpKX1ILkRoKG0sbSwi
+VCIsbykKcD1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5wb3N0LWxpbmsiKSx0KQpwLlUocCxu
+ZXcgTC5JQygpKX0sClE2OmZ1bmN0aW9uKGEsYil7dmFyIHQ9dS5OCnJldHVybiBXLnFEKEwuUTQoYSxi
+KSxudWxsLFAuRUYoWyJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PVVURi04
+Il0sdCx0KSl9LAp0eTpmdW5jdGlvbihhKXt2YXIgdD11Lk4KcmV0dXJuIFcucUQoTC5RNChhLFAuRmwo
+dCx0KSksIlBPU1QiLFAuRUYoWyJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0
+PVVURi04Il0sdCx0KSkuVzcobmV3IEwuTDEoKSx1LnIpfSwKYUs6ZnVuY3Rpb24oYSl7dmFyIHQ9UC5o
+SyhhKS5naFkoKS5xKDAsImxpbmUiKQpyZXR1cm4gdD09bnVsbD9udWxsOkguSHAodCxudWxsKX0sCkc2
+OmZ1bmN0aW9uKGEpe3ZhciB0PVAuaEsoYSkuZ2hZKCkucSgwLCJvZmZzZXQiKQpyZXR1cm4gdD09bnVs
+bD9udWxsOkguSHAodCxudWxsKX0sCnQyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbj17
+fSxtPXUuaC5iKFcucWMoYS5jdXJyZW50VGFyZ2V0KSkKYS5wcmV2ZW50RGVmYXVsdCgpCnQ9bi5hPW0u
+Z2V0QXR0cmlidXRlKCJocmVmIikKaWYoSi56bCh0LCI/Iikpe3M9Qy54Qi5Oaih0LDAsQy54Qi5PWSh0
+LCI/IikpCm4uYT1zCnI9c31lbHNlIHI9dAppZihjIT1udWxsKXtxPSQublUoKQpyPW4uYT1xLm81KDAs
+RC5ucihxLnRNKGMpLHIpKX1wPUwuRzYodCkKbz1MLmFLKHQpCmlmKHAhPW51bGwpTC5hZihyLHAsbyxi
+LG5ldyBMLm5UKG4scCxvKSkKZWxzZSBMLmFmKHIsbnVsbCxudWxsLGIsbmV3IEwuQloobikpfSwKdW06
+ZnVuY3Rpb24oYSl7cmV0dXJuIEwuUVModS5WLmIoYSkpfSwKUVM6ZnVuY3Rpb24oYSl7dmFyIHQ9MCxz
+PVAuRlgodS56KSxyPTEscSxwPVtdLG8sbixtLGwsawp2YXIgJGFzeW5jJHVtPVAubHooZnVuY3Rpb24o
+YixjKXtpZihiPT09MSl7cT1jCnQ9cn13aGlsZSh0cnVlKXN3aXRjaCh0KXtjYXNlIDA6bD11LmguYShX
+LnFjKGEuY3VycmVudFRhcmdldCkpLmdldEF0dHJpYnV0ZSgiaHJlZiIpCmEucHJldmVudERlZmF1bHQo
+KQpyPTMKdD02CnJldHVybiBQLmpRKEwudHkobCksJGFzeW5jJHVtKQpjYXNlIDY6dS5hXy5hKEouR3Io
+Vy51Vihkb2N1bWVudC5kZWZhdWx0VmlldykpKS5yZWxvYWQoKQpyPTEKdD01CmJyZWFrCmNhc2UgMzpy
+PTIKaz1xCm89SC5SdShrKQpuPUgudHMoaykKTC5xSigiaGFuZGxlUG9zdExpbmtDbGljazogIitILmQo
+byksbikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK0guZChsKSsiICgiK0guZChvKSsiKS4i
+KQp0PTUKYnJlYWsKY2FzZSAyOnQ9MQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxzKQpjYXNl
+IDE6cmV0dXJuIFAuZjMocSxzKX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkdW0scyl9LAp2VTpmdW5jdGlv
+bigpe3ZhciB0PWRvY3VtZW50LHM9dS5oCkguRGgocyxzLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnQ9
+bmV3IFcud3oodC5xdWVyeVNlbGVjdG9yQWxsKCIuY29kZSIpLHUuUykKdC5VKHQsbmV3IEwuR0goKSl9
+LApoWDpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9dS5OCkwuUTYoYSxQLkVGKFsicmVnaW9uIiwicmVnaW9u
+Iiwib2Zmc2V0IixILmQoYildLHQsdCkpLlc3KG5ldyBMLkRUKGEsYixjKSx1LlApLk9BKG5ldyBMLmVI
+KGEpKX0sCkc3OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQKaWYoIUouaHcoYSwiLmRhcnQiKSl7TC5C
+RShhLG5ldyBCLnFwKCIiLCIiLCIiLEMuQ00pLGQpCkwuQlgoYSxudWxsKQppZihlIT1udWxsKWUuJDAo
+KQpyZXR1cm59dD11Lk4KTC5RNihhLFAuRUYoWyJpbmxpbmUiLCJ0cnVlIl0sdCx0KSkuVzcobmV3IEwu
+eXUoYSxkLGIsYyxlKSx1LlApLk9BKG5ldyBMLnpEKGEpKX0sCkdlOmZ1bmN0aW9uKCl7dmFyIHQ9Ii9f
+cHJldmlldy9uYXZpZ2F0aW9uVHJlZS5qc29uIgpMLlE2KHQsQy5XTykuVzcobmV3IEwuVFcoKSx1LlAp
+Lk9BKG5ldyBMLnhyKHQpKX0sCnFKOmZ1bmN0aW9uKGEsYil7dmFyIHQKd2luZG93CmlmKHR5cGVvZiBj
+b25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS5lcnJvcihhKQp3aW5kb3cKdD1ILmQoYikK
+aWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKHQpfSwKcU86
+ZnVuY3Rpb24oYSl7dmFyIHQ9YS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxzPUMuQ0QuelEoJC5maSgp
+Lm9mZnNldEhlaWdodCkscj13aW5kb3cuaW5uZXJIZWlnaHQscT1DLkNELnpRKCQuRFcoKS5vZmZzZXRI
+ZWlnaHQpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuSE4oKQppZih0LmJvdHRvbT5yLShx
+KzE0KSlKLmRoKGEpCmVsc2UgaWYodC50b3A8cysxNClKLmRoKGEpfSwKZkc6ZnVuY3Rpb24oYSxiKXt2
+YXIgdCxzLHIKaWYoYSE9bnVsbCl7dD1kb2N1bWVudApzPXQuZ2V0RWxlbWVudEJ5SWQoIm8iK0guZChh
+KSkKcj10LnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5kKGIpKQppZihzIT1udWxsKXtMLnFPKHMpCkou
+ZFIocykuQSgwLCJ0YXJnZXQiKX1lbHNlIGlmKHIhPW51bGwpTC5xTyhyLnBhcmVudEVsZW1lbnQpCmlm
+KHIhPW51bGwpSi5kUih1LmguYShyLnBhcmVudE5vZGUpKS5BKDAsImhpZ2hsaWdodCIpfWVsc2UgTC5x
+TygkLkQ5KCkpfSwKYWY6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHI9TC5HNih3aW5kb3cubG9j
+YXRpb24uaHJlZikscT1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQppZihyIT1udWxsKXt0PWRvY3Vt
+ZW50LmdldEVsZW1lbnRCeUlkKCJvIitILmQocikpCmlmKHQhPW51bGwpSi5kUih0KS5SeigwLCJ0YXJn
+ZXQiKX1pZihxIT1udWxsKXtzPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5kKHEpKQpp
+ZihzIT1udWxsKUouZFIocy5wYXJlbnRFbGVtZW50KS5SeigwLCJoaWdobGlnaHQiKX1pZihhPT13aW5k
+b3cubG9jYXRpb24ucGF0aG5hbWUpe0wuZkcoYixjKQplLiQwKCl9ZWxzZSBMLkc3KGEsYixjLGQsZSl9
+LApRNDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1QLmhLKGEpLHE9dS5OCnE9UC5GbChxLHEpCmZvcih0
+PXIuZ2hZKCksdD10LmdQdSh0KSx0PXQuZ2t6KHQpO3QubSgpOyl7cz10LmdSKHQpCnEuWSgwLHMuYSxz
+LmIpfWZvcih0PWIuZ1B1KGIpLHQ9dC5na3oodCk7dC5tKCk7KXtzPXQuZ1IodCkKcS5ZKDAscy5hLHMu
+Yil9cS5ZKDAsImF1dGhUb2tlbiIsJC5VRSgpKQpyZXR1cm4gci5ubSgwLHEpLncoMCl9LApUMTpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9JC5oTCgpCkoubDUobCwiIikKaWYoYT09bnVsbCl7
+dD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJwIikKdC50ZXh0Q29udGVudD0iU2VlIGRldGFpbHMgYWJv
+dXQgYSBwcm9wb3NlZCBlZGl0LiIKQy5MdC5zREQodCxILlZNKFsicGxhY2Vob2xkZXIiXSx1LnMpKQpK
+LmRoKHUuaC5iKGwuYXBwZW5kQ2hpbGQodCkpKQpyZXR1cm59cz1hLmQKdD0kLm5VKCkKcj10LnRNKHMp
+CnE9YS5iCnA9ZG9jdW1lbnQKbz10LkhQKHMsSi5UMChwLnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4
+dENvbnRlbnQpKQpuPWEuYwp0PXAuY3JlYXRlRWxlbWVudCgicCIpCm09dS5oLmIobC5hcHBlbmRDaGls
+ZCh0KSkKbS5hcHBlbmRDaGlsZChwLmNyZWF0ZVRleHROb2RlKEguZChxKSsiIGF0ICIrSC5kKG8pKyI6
+IitILmQobikrIi4iKSkKSi5kaChtKQpMLkNDKGEsbCxyKQpMLkZ6KGEsbCl9LApMSDpmdW5jdGlvbihh
+LGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmPSQueVAoKQpKLmw1KGYsIiIpCmlm
+KGIuZ2goYik9PT0wKXt0PWRvY3VtZW50CnM9dC5jcmVhdGVFbGVtZW50KCJwIikKdS5oLmIoZi5hcHBl
+bmRDaGlsZChzKSkuYXBwZW5kQ2hpbGQodC5jcmVhdGVUZXh0Tm9kZSgiTm8gcHJvcG9zZWQgZWRpdHMi
+KSl9ZWxzZSBmb3IoZj1iLmdQdShiKSxmPWYuZ2t6KGYpLHQ9dS5pLHM9dS5RLHI9cy5DKCJ+KDEpIiks
+cT11Lk0scz1zLmQscD11Lmg7Zi5tKCk7KXtvPWYuZ1IoZikKbj0kLnlQKCkKbT1kb2N1bWVudApsPW0u
+Y3JlYXRlRWxlbWVudCgicCIpCnAuYihuLmFwcGVuZENoaWxkKGwpKS5hcHBlbmRDaGlsZChtLmNyZWF0
+ZVRleHROb2RlKEguZChvLmEpKyI6IikpCmw9bS5jcmVhdGVFbGVtZW50KCJ1bCIpCms9cC5iKG4uYXBw
+ZW5kQ2hpbGQobCkpCmZvcihvPUouSVQoby5iKTtvLm0oKTspe249by5nUihvKQpsPW0uY3JlYXRlRWxl
+bWVudCgibGkiKQpqPXAuYihrLmFwcGVuZENoaWxkKGwpKQpKLmRSKGopLkEoMCwiZWRpdCIpCmw9bS5j
+cmVhdGVFbGVtZW50KCJhIikKaT10LmIoai5hcHBlbmRDaGlsZChsKSkKaS5jbGFzc0xpc3QuYWRkKCJl
+ZGl0LWxpbmsiKQpoPW4uYwpsPUguZChoKQppLnNldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5l
+dyBXLmk3KGkpKS5TKCJvZmZzZXQiKSxsKQpnPW4uYQpsPUguZChnKQppLnNldEF0dHJpYnV0ZSgiZGF0
+YS0iK25ldyBXLlN5KG5ldyBXLmk3KGkpKS5TKCJsaW5lIiksbCkKaS5hcHBlbmRDaGlsZChtLmNyZWF0
+ZVRleHROb2RlKCJsaW5lICIrSC5kKGcpKSkKbD1yLmIobmV3IEwuRUUoaCxnLGEpKQpxLmIobnVsbCkK
+Vy5KRShpLCJjbGljayIsbCwhMSxzKQpqLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUoIjogIitI
+LmQobi5iKSkpfX1pZihjKUwuVDEobnVsbCl9LApGcjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPXdp
+bmRvdy5sb2NhdGlvbixxPVAuaEsoKHImJkMuRXgpLmdEcihyKStILmQoYSkpCnI9dS5OCnI9UC5GbChy
+LHIpCmlmKGIhPW51bGwpci5ZKDAsIm9mZnNldCIsSC5kKGIpKQppZihjIT1udWxsKXIuWSgwLCJsaW5l
+IixILmQoYykpCnIuWSgwLCJhdXRoVG9rZW4iLCQuVUUoKSkKcT1xLm5tKDAscikKcj13aW5kb3cuaGlz
+dG9yeQp0PXUuegpzPXEudygwKQpyLnRvU3RyaW5nCnIucHVzaFN0YXRlKG5ldyBQLkJmKFtdLFtdKS5Q
+dihQLkZsKHQsdCkpLCIiLHMpfSwKRW46ZnVuY3Rpb24oYSl7dmFyIHQ9Si5iYihkb2N1bWVudC5xdWVy
+eVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50LCIvIikKaWYoQy54Qi5uQyhhLHQpKXJldHVybiBD
+LnhCLnluKGEsdC5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApCWDpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
+cj17fQpyLmE9YQphPUwuRW4oYSkKci5hPWEKJC5EOSgpLnRleHRDb250ZW50PWEKdD1kb2N1bWVudApz
+PXUuaApILkRoKHMscywiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0PW5ldyBXLnd6KHQucXVlcnlTZWxl
+Y3RvckFsbCgiLm5hdi1wYW5lbCAubmF2LWxpbmsiKSx1LlMpCnQuVSh0LG5ldyBMLlZTKHIpKX0sCkJF
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0iLnJlZ2lvbnMiLHM9ZG9jdW1lbnQscj1zLnF1ZXJ5U2VsZWN0
+b3IodCkscT1zLnF1ZXJ5U2VsZWN0b3IoIi5jb2RlIikKSi50SChyLGIuYSwkLktHKCkpCkoudEgocSxi
+LmIsJC5LRygpKQpMLkxIKGEsYi5kLGMpCkwudlUoKQpMLnlYKCIuY29kZSIsITApCkwueVgodCwhMCl9
+LAp0WDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1kb2N1bWVudCxoPWku
+Y3JlYXRlRWxlbWVudCgidWwiKSxnPXUuaCxmPWcuYihhLmFwcGVuZENoaWxkKGgpKQpmb3IoaD1iLmxl
+bmd0aCx0PXUuTSxzPTA7czxiLmxlbmd0aDtiLmxlbmd0aD09PWh8fCgwLEgubGspKGIpLCsrcyl7cj1i
+W3NdCnE9aS5jcmVhdGVFbGVtZW50KCJsaSIpCnA9Zy5iKGYuYXBwZW5kQ2hpbGQocSkpCnE9Si5SRShw
+KQppZihyLmE9PT1DLlkyKXtxLmdERChwKS5BKDAsImRpciIpCnE9aS5jcmVhdGVFbGVtZW50KCJzcGFu
+IikKbz1nLmIocC5hcHBlbmRDaGlsZChxKSkKcT1KLlJFKG8pCnEuZ0REKG8pLkEoMCwiYXJyb3ciKQpx
+LnNoZihvLCImI3gyNUJDOyIpCnE9aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKSi5sNShnLmIocC5hcHBl
+bmRDaGlsZChxKSksIiYjeDFGNEMxOyIpCnAuYXBwZW5kQ2hpbGQoaS5jcmVhdGVUZXh0Tm9kZShyLmIp
+KQpMLnRYKHAsci5jKQpMLmt6KG8pfWVsc2V7cS5zaGYocCwiJiN4MUY0QzQ7IikKcT1pLmNyZWF0ZUVs
+ZW1lbnQoImEiKQpuPWcuYihwLmFwcGVuZENoaWxkKHEpKQpxPUouUkUobikKcS5nREQobikuQSgwLCJu
+YXYtbGluayIpCm4uc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcobikpLlMoIm5h
+bWUiKSxyLmQpCm4uc2V0QXR0cmlidXRlKCJocmVmIixyLmUpCm4uYXBwZW5kQ2hpbGQoaS5jcmVhdGVU
+ZXh0Tm9kZShyLmIpKQpxPXEuZ1ZsKG4pCm09cS4kdGkKbD1tLkMoIn4oMSkiKS5iKG5ldyBMLlREKCkp
+CnQuYihudWxsKQpXLkpFKHEuYSxxLmIsbCwhMSxtLmQpCms9ci5mCmlmKHR5cGVvZiBrIT09Im51bWJl
+ciIpcmV0dXJuIGsub3MoKQppZihrPjApe3E9aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKaj1nLmIocC5h
+cHBlbmRDaGlsZChxKSkKSi5kUihqKS5BKDAsImVkaXQtY291bnQiKQpxPSIiK2srIiAiCmlmKGs9PT0x
+KW09ImVkaXQiCmVsc2UgbT0iZWRpdHMiCmouc2V0QXR0cmlidXRlKCJ0aXRsZSIscSttKQpqLmFwcGVu
+ZENoaWxkKGkuY3JlYXRlVGV4dE5vZGUoQy5qbi53KGspKSl9fX19LApGejpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1hLmEKaWYoaSE9bnVsbCl7dD1kb2N1bWVudApzPXQuY3Jl
+YXRlRWxlbWVudCgicCIpCnI9dS5oCnE9ci5iKGIuYXBwZW5kQ2hpbGQocykpCmZvcihzPWkubGVuZ3Ro
+LHA9dS5zLG89dS5YLG49MDtuPGkubGVuZ3RoO2kubGVuZ3RoPT09c3x8KDAsSC5saykoaSksKytuKXtt
+PWlbbl0KbD10LmNyZWF0ZUVsZW1lbnQoImEiKQprPXIuYihxLmFwcGVuZENoaWxkKGwpKQprLmFwcGVu
+ZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUobS5hKSkKay5zZXRBdHRyaWJ1dGUoImhyZWYiLG0uYikKbD1v
+LmIoSC5WTShbInBvc3QtbGluayIsImJlZm9yZS1hcHBseSJdLHApKQpqPUouZFIoaykKai5WMSgwKQpq
+LkZWKDAsbCl9fX0sCkNDOmZ1bmN0aW9uKGEzLGE0LGE1KXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxq
+LGksaCxnLGYsZSxkLGMsYixhLGEwLGExLGEyPW51bGwKZm9yKHQ9YTMuZSxzPXQubGVuZ3RoLHI9dS5z
+LHE9dS5YLHA9dS5oLG89dS5pLG49MDtuPHQubGVuZ3RoO3QubGVuZ3RoPT09c3x8KDAsSC5saykodCks
+KytuKXttPXRbbl0KbD1kb2N1bWVudAprPWwuY3JlYXRlRWxlbWVudCgicCIpCmo9cS5iKEguVk0oWyJ0
+cmFjZSJdLHIpKQppPUouZFIoaykKaS5WMSgwKQppLkZWKDAsaikKaD1hNC5hcHBlbmRDaGlsZChrKQpr
+PWwuY3JlYXRlRWxlbWVudCgic3BhbiIpCmo9cS5iKEguVk0oWyJ0eXBlLWRlc2NyaXB0aW9uIl0scikp
+Cmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKQprLmFwcGVuZENoaWxkKGwuY3JlYXRlVGV4dE5vZGUo
+bS5hKSkKaC5hcHBlbmRDaGlsZChrKQpoLmFwcGVuZENoaWxkKGwuY3JlYXRlVGV4dE5vZGUoIjoiKSkK
+az1sLmNyZWF0ZUVsZW1lbnQoInVsIikKaj1xLmIoSC5WTShbInRyYWNlIl0scikpCmk9Si5kUihrKQpp
+LlYxKDApCmkuRlYoMCxqKQpnPWguYXBwZW5kQ2hpbGQoaykKZm9yKGs9bS5iLGo9ay5sZW5ndGgsZj0w
+O2Y8ay5sZW5ndGg7ay5sZW5ndGg9PT1qfHwoMCxILmxrKShrKSwrK2Ype2U9a1tmXQpkPWwuY3JlYXRl
+RWxlbWVudCgibGkiKQpKLmw1KGQsIiYjeDI3NEY7ICIpCmM9cC5iKGcuYXBwZW5kQ2hpbGQoZCkpCmQ9
+bC5jcmVhdGVFbGVtZW50KCJzcGFuIikKYj1xLmIoSC5WTShbImZ1bmN0aW9uIl0scikpCmk9Si5kUihk
+KQppLlYxKDApCmkuRlYoMCxiKQpiPWUuYgpMLmtEKGQsYj09bnVsbD8idW5rbm93biI6YikKYy5hcHBl
+bmRDaGlsZChkKQphPWUuYwppZihhIT1udWxsKXtjLmFwcGVuZENoaWxkKGwuY3JlYXRlVGV4dE5vZGUo
+IiAoIikpCmEwPWEuYgpkPWwuY3JlYXRlRWxlbWVudCgiYSIpCm8uYihkKQpkLmFwcGVuZENoaWxkKGwu
+Y3JlYXRlVGV4dE5vZGUoSC5kKGEuYykrIjoiK0guZChhMCkpKQphMT1hLmEKYj0kLm5VKCkKZC5zZXRB
+dHRyaWJ1dGUoImhyZWYiLGIubzUoMCxiLnE3KDAsYTUsYTEsYTIsYTIsYTIsYTIsYTIsYTIpKSkKZC5j
+bGFzc0xpc3QuYWRkKCJuYXYtbGluayIpCmMuYXBwZW5kQ2hpbGQoZCkKYy5hcHBlbmRDaGlsZChsLmNy
+ZWF0ZVRleHROb2RlKCIpIikpfWMuYXBwZW5kQ2hpbGQobC5jcmVhdGVUZXh0Tm9kZSgiOiAiKSkKZD1l
+LmEKTC5rRChjLGQ9PW51bGw/InVua25vd24iOmQpfX19LAprRDpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
+cj1ILlZNKGIuc3BsaXQoIi4iKSx1LnMpLHE9Qy5ObS5ndEgocikscD1kb2N1bWVudAphLmFwcGVuZENo
+aWxkKHAuY3JlYXRlVGV4dE5vZGUocSkpCmZvcihxPUgucUMociwxLG51bGwsdS5OKSxxPW5ldyBILmE3
+KHEscS5naChxKSxxLiR0aS5DKCJhNzxhTC5FPiIpKSx0PUouUkUoYSk7cS5tKCk7KXtzPXEuZAp0Lm56
+KGEsImJlZm9yZWVuZCIsIiYjODIwMzsuIixudWxsLG51bGwpCmEuYXBwZW5kQ2hpbGQocC5jcmVhdGVU
+ZXh0Tm9kZShzKSl9fSwKZTpmdW5jdGlvbiBlKCl7fSwKVlc6ZnVuY3Rpb24gVlcoYSxiLGMpe3RoaXMu
+YT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKb1o6ZnVuY3Rpb24gb1ooKXt9LApqcjpmdW5jdGlvbiBqcigp
+e30sCnFsOmZ1bmN0aW9uIHFsKCl7fSwKeTg6ZnVuY3Rpb24geTgoKXt9LApMOmZ1bmN0aW9uIEwoKXt9
+LApXeDpmdW5jdGlvbiBXeChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQU86ZnVuY3Rpb24gQU8oYSl7
+dGhpcy5hPWF9LApkTjpmdW5jdGlvbiBkTihhKXt0aGlzLmE9YX0sCkhvOmZ1bmN0aW9uIEhvKGEpe3Ro
+aXMuYT1hfSwKeHo6ZnVuY3Rpb24geHooYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCklDOmZ1bmN0aW9u
+IElDKCl7fSwKTDE6ZnVuY3Rpb24gTDEoKXt9LApuVDpmdW5jdGlvbiBuVChhLGIsYyl7dGhpcy5hPWEK
+dGhpcy5iPWIKdGhpcy5jPWN9LApCWjpmdW5jdGlvbiBCWihhKXt0aGlzLmE9YX0sCkdIOmZ1bmN0aW9u
+IEdIKCl7fSwKRFQ6ZnVuY3Rpb24gRFQoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwK
+ZUg6ZnVuY3Rpb24gZUgoYSl7dGhpcy5hPWF9LAp5dTpmdW5jdGlvbiB5dShhLGIsYyxkLGUpe3ZhciBf
+PXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWV9LAp6RDpmdW5jdGlvbiB6RChhKXt0aGlz
+LmE9YX0sClRXOmZ1bmN0aW9uIFRXKCl7fSwKeHI6ZnVuY3Rpb24geHIoYSl7dGhpcy5hPWF9LApFRTpm
+dW5jdGlvbiBFRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApRTDpmdW5jdGlvbiBR
+TChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVlM6ZnVuY3Rpb24gVlMoYSl7dGhpcy5hPWF9LApURDpm
+dW5jdGlvbiBURCgpe30sClhBOmZ1bmN0aW9uIFhBKCl7fSwKbUs6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
+LHEscCxvLG49SC5WTShbXSx1LmZoKQpmb3IodD1KLklUKHUuUi5iKGEpKTt0Lm0oKTspe3M9dC5nUih0
+KQpyPUouVTYocykKcT1MLnAyKEgueShyLnEocywidHlwZSIpKSkKcD1ILnkoci5xKHMsIm5hbWUiKSkK
+bz1yLnEocywic3VidHJlZSIpCm89bz09bnVsbD9udWxsOkwubUsobykKQy5ObS5BKG4sbmV3IEwuWloo
+cSxwLG8sSC55KHIucShzLCJwYXRoIikpLEgueShyLnEocywiaHJlZiIpKSxILlNjKHIucShzLCJlZGl0
+Q291bnQiKSkpKX1yZXR1cm4gbn0sCnAyOmZ1bmN0aW9uKGEpe3N3aXRjaChhKXtjYXNlImRpcmVjdG9y
+eSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpkZWZhdWx0OnRocm93IEguYihQLlBW
+KCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIitILmQoYSkpKX19LApaWjpm
+dW5jdGlvbiBaWihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApf
+LmU9ZQpfLmY9Zn0sCkJjOmZ1bmN0aW9uIEJjKGEpe3RoaXMuYj1hfSwKSVY6ZnVuY3Rpb24gSVYoYSxi
+LGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9ZH19LE09ewpZRjpmdW5jdGlvbihh
+LGIpe3ZhciB0LHMscixxLHAsbyxuCmZvcih0PWIubGVuZ3RoLHM9MTtzPHQ7KytzKXtpZihiW3NdPT1u
+dWxsfHxiW3MtMV0hPW51bGwpY29udGludWUKZm9yKDt0Pj0xO3Q9cil7cj10LTEKaWYoYltyXSE9bnVs
+bClicmVha31xPW5ldyBQLlJuKCIiKQpwPWErIigiCnEuYT1wCm89SC5xQyhiLDAsdCxILnQ2KGIpLmQp
+Cm49by4kdGkKbj1wK25ldyBILkE4KG8sbi5DKCJxVShhTC5FKSIpLmIobmV3IE0uTm8oKSksbi5DKCJB
+ODxhTC5FLHFVPiIpKS56VigwLCIsICIpCnEuYT1uCnEuYT1uKygiKTogcGFydCAiKyhzLTEpKyIgd2Fz
+IG51bGwsIGJ1dCBwYXJ0ICIrcysiIHdhcyBub3QuIikKdGhyb3cgSC5iKFAueFkocS53KDApKSl9fSwK
+bEk6ZnVuY3Rpb24gbEkoYSl7dGhpcy5hPWF9LApNaTpmdW5jdGlvbiBNaSgpe30sCnE3OmZ1bmN0aW9u
+IHE3KCl7fSwKTm86ZnVuY3Rpb24gTm8oKXt9fSxYPXsKQ0w6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIs
+cSxwLG89Yi54WihhKQpiLmhLKGEpCmlmKG8hPW51bGwpYT1KLktWKGEsby5sZW5ndGgpCnQ9dS5zCnM9
+SC5WTShbXSx0KQpyPUguVk0oW10sdCkKdD1hLmxlbmd0aAppZih0IT09MCYmYi5yNChDLnhCLldkKGEs
+MCkpKXtpZigwPj10KXJldHVybiBILk9IKGEsMCkKQy5ObS5BKHIsYVswXSkKcT0xfWVsc2V7Qy5ObS5B
+KHIsIiIpCnE9MH1mb3IocD1xO3A8dDsrK3ApaWYoYi5yNChDLnhCLldkKGEscCkpKXtDLk5tLkEocyxD
+LnhCLk5qKGEscSxwKSkKQy5ObS5BKHIsYVtwXSkKcT1wKzF9aWYocTx0KXtDLk5tLkEocyxDLnhCLnlu
+KGEscSkpCkMuTm0uQShyLCIiKX1yZXR1cm4gbmV3IFguV0QoYixvLHMscil9LApXRDpmdW5jdGlvbiBX
+RChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1jCl8uZT1kfSwKcVI6ZnVuY3Rpb24g
+cVIoYSl7dGhpcy5hPWF9LApJNzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFguZHYoYSl9LApkdjpmdW5j
+dGlvbiBkdihhKXt0aGlzLmE9YX19LE89ewpSaDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG0s
+bCxrLGosaT1udWxsCmlmKFAudW8oKS5nRmkoKSE9PSJmaWxlIilyZXR1cm4gJC5FYigpCnQ9UC51bygp
+CmlmKCFDLnhCLlRjKHQuZ0lpKHQpLCIvIikpcmV0dXJuICQuRWIoKQpzPVAuUGkoaSwwLDApCnI9UC56
+UihpLDAsMCkKcT1QLk9lKGksMCwwLCExKQpwPVAubGUoaSwwLDAsaSkKbz1QLnRHKGksMCwwKQpuPVAu
+d0IoaSxzKQptPXM9PT0iZmlsZSIKaWYocT09bnVsbCl0PXIubGVuZ3RoIT09MHx8biE9bnVsbHx8bQpl
+bHNlIHQ9ITEKaWYodClxPSIiCnQ9cT09bnVsbApsPSF0Cms9UC5rYSgiYS9iIiwwLDMsaSxzLGwpCmo9
+cy5sZW5ndGg9PT0wCmlmKGomJnQmJiFDLnhCLm5DKGssIi8iKSlrPVAud0Yoaywhanx8bCkKZWxzZSBr
+PVAueGUoaykKaWYobmV3IFAuRG4ocyxyLHQmJkMueEIubkMoaywiLy8iKT8iIjpxLG4sayxwLG8pLnQ0
+KCk9PT0iYVxcYiIpcmV0dXJuICQuS2soKQpyZXR1cm4gJC5iRCgpfSwKT086ZnVuY3Rpb24gT08oKXt9
+fSxFPXtPRjpmdW5jdGlvbiBPRihhLGIsYyl7dGhpcy5kPWEKdGhpcy5lPWIKdGhpcy5mPWN9fSxGPXty
+dTpmdW5jdGlvbiBydShhLGIsYyxkKXt2YXIgXz10aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0s
+RD17ClJYOmZ1bmN0aW9uKCl7dmFyIHQscyxyPVAudW8oKQppZihKLlJNKHIsJC5JNikpcmV0dXJuICQu
+RmYKJC5JNj1yCmlmKCQuSGsoKT09JC5FYigpKXJldHVybiAkLkZmPXIuWkkoIi4iKS53KDApCmVsc2V7
+dD1yLnQ0KCkKcz10Lmxlbmd0aC0xCnJldHVybiAkLkZmPXM9PT0wP3Q6Qy54Qi5Oaih0LDAscyl9fSwK
+bnI6ZnVuY3Rpb24oYSxiKXt2YXIgdD1udWxsCnJldHVybiAkLm5VKCkucTcoMCxhLGIsdCx0LHQsdCx0
+LHQpfX0KdmFyIHc9W0MsSCxKLFAsVyxVLEIsVCxMLE0sWCxPLEUsRixEXQpodW5rSGVscGVycy5zZXRG
+dW5jdGlvbk5hbWVzSWZOZWNlc3NhcnkodykKdmFyICQ9e30KSC5lby5wcm90b3R5cGU9e30KSi52Qi5w
+cm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3JldHVybiBhPT09Yn0sCmdpOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBILmVRKGEpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEguTShh
+KSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYihiKQp0aHJvdyBILmIoUC5scihhLGIuZ1dhKCks
+Yi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0
+cmluZyhhKX0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBhPzUxOTAxODoyMTgxNTl9LAokaWEyOjF9Ckou
+WUUucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbnVsbD09Yn0sCnc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIm51bGwifSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LAplNzpmdW5jdGlvbihhLGIp
+e3JldHVybiB0aGlzLlNqKGEsdS5vLmIoYikpfSwKJGljODoxfQpKLk1GLnByb3RvdHlwZT17CmdpOmZ1
+bmN0aW9uKGEpe3JldHVybiAwfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGl2bTox
+fQpKLmlDLnByb3RvdHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpKLmM1LnByb3RvdHlwZT17Cnc6ZnVu
+Y3Rpb24oYSl7dmFyIHQ9YVskLncoKV0KaWYodD09bnVsbClyZXR1cm4gdGhpcy50KGEpCnJldHVybiJK
+YXZhU2NyaXB0IGZ1bmN0aW9uIGZvciAiK0guZChKLmoodCkpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm57
+ZnVuYzoxLG9wdDpbLCwsLCwsLCwsLCwsLCwsLF19fSwKJGlFSDoxfQpKLmpkLnByb3RvdHlwZT17CkE6
+ZnVuY3Rpb24oYSxiKXtILnQ2KGEpLmQuYihiKQppZighIWEuZml4ZWQkbGVuZ3RoKUguVmooUC5MNCgi
+YWRkIikpCmEucHVzaChiKX0sClc0OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoISFhLmZpeGVkJGxlbmd0
+aClILlZqKFAuTDQoInJlbW92ZUF0IikpCnQ9YS5sZW5ndGgKaWYoYj49dCl0aHJvdyBILmIoUC54KGIs
+bnVsbCkpCnJldHVybiBhLnNwbGljZShiLDEpWzBdfSwKb0Y6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
+cgpILnQ2KGEpLkMoImNYPDE+IikuYihjKQppZighIWEuZml4ZWQkbGVuZ3RoKUguVmooUC5MNCgiaW5z
+ZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53QShiLDAsdCwiaW5kZXgiKQpzPWMubGVuZ3RoCnRoaXMuc2go
+YSx0K3MpCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEsYikKdGhpcy52ZyhhLGIscixjKX0sCm12
+OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhlZCRsZW5ndGgpSC5WaihQLkw0KCJyZW1vdmVMYXN0IikpCmlm
+KGEubGVuZ3RoPT09MCl0aHJvdyBILmIoSC5IWShhLC0xKSkKcmV0dXJuIGEucG9wKCl9LApGVjpmdW5j
+dGlvbihhLGIpe3ZhciB0CkgudDYoYSkuQygiY1g8MT4iKS5iKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgp
+SC5WaihQLkw0KCJhZGRBbGwiKSkKZm9yKHQ9Si5JVChiKTt0Lm0oKTspYS5wdXNoKHQuZ1IodCkpfSwK
+VTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC50NihhKS5DKCJ+KDEpIikuYihiKQp0PWEubGVuZ3RoCmZv
+cihzPTA7czx0Oysrcyl7Yi4kMShhW3NdKQppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkp
+fX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILnQ2KGEpCnJldHVybiBuZXcgSC5BOChhLHQuSyhj
+KS5DKCIxKDIpIikuYihiKSx0LkMoIkA8MT4iKS5LKGMpLkMoIkE4PDEsMj4iKSl9LAp6VjpmdW5jdGlv
+bihhLGIpe3ZhciB0LHM9bmV3IEFycmF5KGEubGVuZ3RoKQpzLmZpeGVkJGxlbmd0aD1BcnJheQpmb3Io
+dD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMuWShzLHQsSC5kKGFbdF0pKQpyZXR1cm4gcy5qb2luKGIpfSwK
+TjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmQuYihiKQpILnQ2KGEpLksoZCkuQygiMSgxLDIp
+IikuYihjKQp0PWEubGVuZ3RoCmZvcihzPWIscj0wO3I8dDsrK3Ipe3M9Yy4kMihzLGFbcl0pCmlmKGEu
+bGVuZ3RoIT09dCl0aHJvdyBILmIoUC5hNChhKSl9cmV0dXJuIHN9LApXOmZ1bmN0aW9uKGEsYil7aWYo
+YjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKRDY6ZnVuY3Rpb24o
+YSxiLGMpe2lmKGI8MHx8Yj5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShiLDAsYS5sZW5ndGgsInN0YXJ0
+IixudWxsKSkKaWYoYzxifHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsYixhLmxlbmd0aCwiZW5k
+IixudWxsKSkKaWYoYj09PWMpcmV0dXJuIEguVk0oW10sSC50NihhKSkKcmV0dXJuIEguVk0oYS5zbGlj
+ZShiLGMpLEgudDYoYSkpfSwKZ3RIOmZ1bmN0aW9uKGEpe2lmKGEubGVuZ3RoPjApcmV0dXJuIGFbMF0K
+dGhyb3cgSC5iKEguV3AoKSl9LApnclo6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKaWYodD4wKXJl
+dHVybiBhW3QtMV0KdGhyb3cgSC5iKEguV3AoKSl9LApZVzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0
+LHMscj1ILnQ2KGEpCnIuQygiY1g8MT4iKS5iKGQpCmlmKCEhYS5pbW11dGFibGUkbGlzdClILlZqKFAu
+TDQoInNldFJhbmdlIikpClAuakIoYixjLGEubGVuZ3RoKQp0PWMtYgppZih0PT09MClyZXR1cm4KUC5r
+MShlLCJza2lwQ291bnQiKQpyLkMoInpNPDE+IikuYihkKQpyPUouVTYoZCkKaWYoZSt0PnIuZ2goZCkp
+dGhyb3cgSC5iKEguYXIoKSkKaWYoZTxiKWZvcihzPXQtMTtzPj0wOy0tcylhW2Irc109ci5xKGQsZStz
+KQplbHNlIGZvcihzPTA7czx0OysrcylhW2Irc109ci5xKGQsZStzKX0sCnZnOmZ1bmN0aW9uKGEsYixj
+LGQpe3JldHVybiB0aGlzLllXKGEsYixjLGQsMCl9LApWcjpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC50
+NihhKS5DKCJhMigxKSIpLmIoYikKdD1hLmxlbmd0aApmb3Iocz0wO3M8dDsrK3Mpe2lmKEgub1QoYi4k
+MShhW3NdKSkpcmV0dXJuITAKaWYoYS5sZW5ndGghPT10KXRocm93IEguYihQLmE0KGEpKX1yZXR1cm4h
+MX0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQKZm9yKHQ9MDt0PGEubGVuZ3RoOysrdClpZihKLlJNKGFb
+dF0sYikpcmV0dXJuITAKcmV0dXJuITF9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJd
+Iil9LApna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBKLm0xKGEsYS5sZW5ndGgsSC50NihhKS5DKCJt
+MTwxPiIpKX0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKZ2g6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofSwKc2g6ZnVuY3Rpb24oYSxiKXtpZighIWEuZml4ZWQkbGVuZ3RoKUguVmooUC5M
+NCgic2V0IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLG51bGwsIm5ld0xlbmd0aCIs
+bnVsbCkpCmEubGVuZ3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj1hLmxlbmd0aHx8
+YjwwKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC5T
+YyhiKQpILnQ2KGEpLmQuYihjKQppZighIWEuaW1tdXRhYmxlJGxpc3QpSC5WaihQLkw0KCJpbmRleGVk
+IHNldCIpKQppZighSC5vayhiKSl0aHJvdyBILmIoSC5IWShhLGIpKQppZihiPj1hLmxlbmd0aHx8Yjww
+KXRocm93IEguYihILkhZKGEsYikpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkouUG8u
+cHJvdG90eXBlPXt9CkoubTEucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0s
+Cm06ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj1zLmEscT1yLmxlbmd0aAppZihzLmIhPT1xKXRocm93
+IEguYihILmxrKHIpKQp0PXMuYwppZih0Pj1xKXtzLnNNKG51bGwpCnJldHVybiExfXMuc00oclt0XSk7
+KytzLmMKcmV0dXJuITB9LApzTTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlB
+bjoxfQpKLnFJLnByb3RvdHlwZT17Cnl1OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE+PS0yMTQ3NDgzNjQ4
+JiZhPD0yMTQ3NDgzNjQ3KXJldHVybiBhfDAKaWYoaXNGaW5pdGUoYSkpe3Q9YTwwP01hdGguY2VpbChh
+KTpNYXRoLmZsb29yKGEpCnJldHVybiB0KzB9dGhyb3cgSC5iKFAuTDQoIiIrYSsiLnRvSW50KCkiKSl9
+LAp6UTpmdW5jdGlvbihhKXtpZihhPjApe2lmKGEhPT0xLzApcmV0dXJuIE1hdGgucm91bmQoYSl9ZWxz
+ZSBpZihhPi0xLzApcmV0dXJuIDAtTWF0aC5yb3VuZCgwLWEpCnRocm93IEguYihQLkw0KCIiK2ErIi5y
+b3VuZCgpIikpfSwKRDg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQppZihiPDJ8fGI+MzYpdGhyb3cg
+SC5iKFAuVEUoYiwyLDM2LCJyYWRpeCIsbnVsbCkpCnQ9YS50b1N0cmluZyhiKQppZihDLnhCLk8yKHQs
+dC5sZW5ndGgtMSkhPT00MSlyZXR1cm4gdApzPS9eKFtcZGEtel0rKSg/OlwuKFtcZGEtel0rKSk/XChl
+XCsoXGQrKVwpJC8uZXhlYyh0KQppZihzPT1udWxsKUguVmooUC5MNCgiVW5leHBlY3RlZCB0b1N0cmlu
+ZyByZXN1bHQ6ICIrdCkpCnI9cy5sZW5ndGgKaWYoMT49cilyZXR1cm4gSC5PSChzLDEpCnQ9c1sxXQpp
+ZigzPj1yKXJldHVybiBILk9IKHMsMykKcT0rc1szXQpyPXNbMl0KaWYociE9bnVsbCl7dCs9cgpxLT1y
+Lmxlbmd0aH1yZXR1cm4gdCtDLnhCLkl4KCIwIixxKX0sCnc6ZnVuY3Rpb24oYSl7aWYoYT09PTAmJjEv
+YTwwKXJldHVybiItMC4wIgplbHNlIHJldHVybiIiK2F9LApnaTpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
+cSxwPWF8MAppZihhPT09cClyZXR1cm4gNTM2ODcwOTExJnAKdD1NYXRoLmFicyhhKQpzPU1hdGgubG9n
+KHQpLzAuNjkzMTQ3MTgwNTU5OTQ1M3wwCnI9TWF0aC5wb3coMixzKQpxPXQ8MT90L3I6ci90CnJldHVy
+biA1MzY4NzA5MTEmKChxKjkwMDcxOTkyNTQ3NDA5OTJ8MCkrKHEqMzU0MjI0MzE4MTE3NjUyMXwwKSkq
+NTk5MTk3K3MqMTI1OX0sCnpZOmZ1bmN0aW9uKGEsYil7dmFyIHQ9YSViCmlmKHQ9PT0wKXJldHVybiAw
+CmlmKHQ+MClyZXR1cm4gdAppZihiPDApcmV0dXJuIHQtYgplbHNlIHJldHVybiB0K2J9LAp3RzpmdW5j
+dGlvbihhLGIpe3ZhciB0CmlmKGE+MCl0PXRoaXMucDMoYSxiKQplbHNle3Q9Yj4zMT8zMTpiCnQ9YT4+
+dD4+PjB9cmV0dXJuIHR9LApiZjpmdW5jdGlvbihhLGIpe2lmKGI8MCl0aHJvdyBILmIoSC50TChiKSkK
+cmV0dXJuIHRoaXMucDMoYSxiKX0sCnAzOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGI+MzE/MDphPj4+Yn0s
+CiRpQ1A6MSwKJGlGSzoxfQpKLnVyLnByb3RvdHlwZT17JGlLTjoxfQpKLlZBLnByb3RvdHlwZT17fQpK
+LkRyLnByb3RvdHlwZT17Ck8yOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihILkhZKGEsYikp
+CmlmKGI+PWEubGVuZ3RoKUguVmooSC5IWShhLGIpKQpyZXR1cm4gYS5jaGFyQ29kZUF0KGIpfSwKV2Q6
+ZnVuY3Rpb24oYSxiKXtpZihiPj1hLmxlbmd0aCl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYS5j
+aGFyQ29kZUF0KGIpfSwKZGQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEgudW4oYixhLDApfSwKVDpm
+dW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIil0aHJvdyBILmIoUC5MMyhiLG51bGwsbnVs
+bCkpCnJldHVybiBhK2J9LApUYzpmdW5jdGlvbihhLGIpe3ZhciB0PWIubGVuZ3RoLHM9YS5sZW5ndGgK
+aWYodD5zKXJldHVybiExCnJldHVybiBiPT09dGhpcy55bihhLHMtdCl9LAppNzpmdW5jdGlvbihhLGIs
+YyxkKXt2YXIgdCxzCmM9UC5qQihiLGMsYS5sZW5ndGgpCnQ9YS5zdWJzdHJpbmcoMCxiKQpzPWEuc3Vi
+c3RyaW5nKGMpCnJldHVybiB0K2Qrc30sClFpOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZighSC5vayhj
+KSlILlZqKEgudEwoYykpCmlmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIGMuSigpCmlmKGM8MHx8
+Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKdD1jK2IubGVu
+Z3RoCmlmKHQ+YS5sZW5ndGgpcmV0dXJuITEKcmV0dXJuIGI9PT1hLnN1YnN0cmluZyhjLHQpfSwKbkM6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5RaShhLGIsMCl9LApOajpmdW5jdGlvbihhLGIsYyl7aWYo
+IUgub2soYikpSC5WaihILnRMKGIpKQppZihjPT1udWxsKWM9YS5sZW5ndGgKaWYodHlwZW9mIGIhPT0i
+bnVtYmVyIilyZXR1cm4gYi5KKCkKaWYoYjwwKXRocm93IEguYihQLngoYixudWxsKSkKaWYoYj5jKXRo
+cm93IEguYihQLngoYixudWxsKSkKaWYoYz5hLmxlbmd0aCl0aHJvdyBILmIoUC54KGMsbnVsbCkpCnJl
+dHVybiBhLnN1YnN0cmluZyhiLGMpfSwKeW46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5OaihhLGIs
+bnVsbCl9LApoYzpmdW5jdGlvbihhKXtyZXR1cm4gYS50b0xvd2VyQ2FzZSgpfSwKYlM6ZnVuY3Rpb24o
+YSl7dmFyIHQscyxyLHE9YS50cmltKCkscD1xLmxlbmd0aAppZihwPT09MClyZXR1cm4gcQppZih0aGlz
+LldkKHEsMCk9PT0xMzMpe3Q9Si5tbShxLDEpCmlmKHQ9PT1wKXJldHVybiIifWVsc2UgdD0wCnM9cC0x
+CnI9dGhpcy5PMihxLHMpPT09MTMzP0ouYzEocSxzKTpwCmlmKHQ9PT0wJiZyPT09cClyZXR1cm4gcQpy
+ZXR1cm4gcS5zdWJzdHJpbmcodCxyKX0sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZigwPj1iKXJl
+dHVybiIiCmlmKGI9PT0xfHxhLmxlbmd0aD09PTApcmV0dXJuIGEKaWYoYiE9PWI+Pj4wKXRocm93IEgu
+YihDLkVxKQpmb3IodD1hLHM9IiI7ITA7KXtpZigoYiYxKT09PTEpcz10K3MKYj1iPj4+MQppZihiPT09
+MClicmVhawp0Kz10fXJldHVybiBzfSwKWFU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKGM8MHx8Yz5h
+Lmxlbmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKdD1hLmluZGV4T2Yo
+YixjKQpyZXR1cm4gdH0sCk9ZOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuWFUoYSxiLDApfSwKUGs6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoYz09bnVsbCljPWEubGVuZ3RoCmVsc2UgaWYoYzwwfHxj
+PmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxudWxsLG51bGwpKQp0PWIubGVuZ3Ro
+CnM9YS5sZW5ndGgKaWYoYyt0PnMpYz1zLXQKcmV0dXJuIGEubGFzdEluZGV4T2YoYixjKX0sCmNuOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuUGsoYSxiLG51bGwpfSwKSXM6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0PWEubGVuZ3RoCmlmKGM+dCl0aHJvdyBILmIoUC5URShjLDAsdCxudWxsLG51bGwpKQpyZXR1cm4g
+SC5tMihhLGIsYyl9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLklzKGEsYiwwKX0sCnc6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGF9LApnaTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKZm9yKHQ9YS5sZW5ndGgs
+cz0wLHI9MDtyPHQ7KytyKXtzPTUzNjg3MDkxMSZzK2EuY2hhckNvZGVBdChyKQpzPTUzNjg3MDkxMSZz
+KygoNTI0Mjg3JnMpPDwxMCkKc149cz4+Nn1zPTUzNjg3MDkxMSZzKygoNjcxMDg4NjMmcyk8PDMpCnNe
+PXM+PjExCnJldHVybiA1MzY4NzA5MTEmcysoKDE2MzgzJnMpPDwxNSl9LApnaDpmdW5jdGlvbihhKXty
+ZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj1hLmxlbmd0aHx8ITEp
+dGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0dXJuIGFbYl19LAokaXZYOjEsCiRpcVU6MX0KSC5xai5wcm90
+b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gQy54Qi5PMih0aGlzLmEsSC5TYyhiKSl9fQpILmJRLnByb3RvdHlwZT17fQpILmFMLnBy
+b3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzCnJldHVybiBuZXcgSC5hNyh0LHQuZ2go
+dCksSC5MaCh0KS5DKCJhNzxhTC5FPiIpKX0sCnpWOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9dGhp
+cyxwPXEuZ2gocSkKaWYoYi5sZW5ndGghPT0wKXtpZihwPT09MClyZXR1cm4iIgp0PUguZChxLlcoMCww
+KSkKaWYocCE9PXEuZ2gocSkpdGhyb3cgSC5iKFAuYTQocSkpCmZvcihzPXQscj0xO3I8cDsrK3Ipe3M9
+cytiK0guZChxLlcoMCxyKSkKaWYocCE9PXEuZ2gocSkpdGhyb3cgSC5iKFAuYTQocSkpfXJldHVybiBz
+LmNoYXJDb2RlQXQoMCk9PTA/czpzfWVsc2V7Zm9yKHI9MCxzPSIiO3I8cDsrK3Ipe3MrPUguZChxLlco
+MCxyKSkKaWYocCE9PXEuZ2gocSkpdGhyb3cgSC5iKFAuYTQocSkpfXJldHVybiBzLmNoYXJDb2RlQXQo
+MCk9PTA/czpzfX0sCmV2OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuR0coMCxILkxoKHRoaXMpLkMo
+ImEyKGFMLkUpIikuYihiKSl9LApFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQpyZXR1
+cm4gbmV3IEguQTgodGhpcyx0LksoYykuQygiMShhTC5FKSIpLmIoYiksdC5DKCJAPGFMLkU+IikuSyhj
+KS5DKCJBODwxLDI+IikpfX0KSC5uSC5wcm90b3R5cGU9ewpnVUQ6ZnVuY3Rpb24oKXt2YXIgdD1KLkht
+KHRoaXMuYSkscz10aGlzLmMKaWYocz09bnVsbHx8cz50KXJldHVybiB0CnJldHVybiBzfSwKZ0FzOmZ1
+bmN0aW9uKCl7dmFyIHQ9Si5IbSh0aGlzLmEpLHM9dGhpcy5iCmlmKHM+dClyZXR1cm4gdApyZXR1cm4g
+c30sCmdoOmZ1bmN0aW9uKGEpe3ZhciB0LHM9Si5IbSh0aGlzLmEpLHI9dGhpcy5iCmlmKHI+PXMpcmV0
+dXJuIDAKdD10aGlzLmMKaWYodD09bnVsbHx8dD49cylyZXR1cm4gcy1yCmlmKHR5cGVvZiB0IT09Im51
+bWJlciIpcmV0dXJuIHQuSE4oKQpyZXR1cm4gdC1yfSwKVzpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhp
+cyxyPXMuZ0FzKCkrYgppZihiPj0wKXt0PXMuZ1VEKCkKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1
+cm4gSC5wWSh0KQp0PXI+PXR9ZWxzZSB0PSEwCmlmKHQpdGhyb3cgSC5iKFAuQ2YoYixzLCJpbmRleCIs
+bnVsbCxudWxsKSkKcmV0dXJuIEouR0Eocy5hLHIpfX0KSC5hNy5wcm90b3R5cGU9ewpnUjpmdW5jdGlv
+bihhKXtyZXR1cm4gdGhpcy5kfSwKbTpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPXMuYSxxPUouVTYo
+cikscD1xLmdoKHIpCmlmKHMuYiE9PXApdGhyb3cgSC5iKFAuYTQocikpCnQ9cy5jCmlmKHQ+PXApe3Mu
+c0kobnVsbCkKcmV0dXJuITF9cy5zSShxLlcocix0KSk7KytzLmMKcmV0dXJuITB9LApzSTpmdW5jdGlv
+bihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlBbjoxfQpILmkxLnByb3RvdHlwZT17Cmdrejpm
+dW5jdGlvbihhKXt2YXIgdD1ILkxoKHRoaXMpCnJldHVybiBuZXcgSC5NSChKLklUKHRoaXMuYSksdGhp
+cy5iLHQuQygiQDwxPiIpLksodC5jaFsxXSkuQygiTUg8MSwyPiIpKX0sCmdoOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBKLkhtKHRoaXMuYSl9fQpILnh5LnByb3RvdHlwZT17JGliUToxfQpILk1ILnByb3RvdHlwZT17
+Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5iCmlmKHMubSgpKXt0LnNJKHQuYy4kMShzLmdSKHMp
+KSkKcmV0dXJuITB9dC5zSShudWxsKQpyZXR1cm4hMX0sCmdSOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LmF9LApzSTpmdW5jdGlvbihhKXt0aGlzLmE9dGhpcy4kdGkuY2hbMV0uYihhKX19CkguQTgucHJvdG90
+eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIEouSG0odGhpcy5hKX0sClc6ZnVuY3Rpb24oYSxiKXty
+ZXR1cm4gdGhpcy5iLiQxKEouR0EodGhpcy5hLGIpKX19CkguVTUucHJvdG90eXBlPXsKZ2t6OmZ1bmN0
+aW9uKGEpe3JldHVybiBuZXcgSC5TTyhKLklUKHRoaXMuYSksdGhpcy5iLHRoaXMuJHRpLkMoIlNPPDE+
+IikpfX0KSC5TTy5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKCl7dmFyIHQscwpmb3IodD10aGlzLmEscz10
+aGlzLmI7dC5tKCk7KWlmKEgub1Qocy4kMSh0LmdSKHQpKSkpcmV0dXJuITAKcmV0dXJuITF9LApnUjpm
+dW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ1IodCl9fQpILlNVLnByb3RvdHlwZT17fQpI
+LlJlLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxiLGMpe0guU2MoYikKSC5MaCh0aGlzKS5DKCJSZS5F
+IikuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSBhbiB1bm1vZGlmaWFibGUgbGlzdCIp
+KX19CkguWEMucHJvdG90eXBlPXt9Ckgud3YucHJvdG90eXBlPXsKZ2k6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcy5faGFzaENvZGUKaWYodCE9bnVsbClyZXR1cm4gdAp0PTUzNjg3MDkxMSY2NjQ1OTcqSi5oZih0
+aGlzLmEpCnRoaXMuX2hhc2hDb2RlPXQKcmV0dXJuIHR9LAp3OmZ1bmN0aW9uKGEpe3JldHVybidTeW1i
+b2woIicrSC5kKHRoaXMuYSkrJyIpJ30sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4h
+MQpyZXR1cm4gYiBpbnN0YW5jZW9mIEgud3YmJnRoaXMuYT09Yi5hfSwKJGlHRDoxfQpILlBELnByb3Rv
+dHlwZT17fQpILldVLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAubk8odGhpcyl9LApZ
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxoKHRoaXMpCnQuZC5iKGIpCnQuY2hbMV0uYihjKQpyZXR1
+cm4gSC5kYygpfSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnE0KGEsSC5MaCh0aGlzKS5DKCJO
+MzwxLDI+IikpfSwKcTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzCnJldHVybiBQLmwwKGZ1bmN0aW9u
+KCl7dmFyIHM9YQp2YXIgcj0wLHE9MSxwLG8sbixtCnJldHVybiBmdW5jdGlvbiAkYXN5bmMkZ1B1KGMs
+ZCl7aWYoYz09PTEpe3A9ZApyPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocil7Y2FzZSAwOm89dC5ndih0KSxv
+PW8uZ2t6KG8pLG49SC5MaCh0KSxuPW4uQygiQDwxPiIpLksobi5jaFsxXSkuQygiTjM8MSwyPiIpCmNh
+c2UgMjppZighby5tKCkpe3I9MwpicmVha31tPW8uZ1IobykKcj00CnJldHVybiBuZXcgUC5OMyhtLHQu
+cSgwLG0pLG4pCmNhc2UgNDpyPTIKYnJlYWsKY2FzZSAzOnJldHVybiBQLlRoKCkKY2FzZSAxOnJldHVy
+biBQLlltKHApfX19LGIpfSwKJGlaMDoxfQpILkxQLnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLmF9LAp4NDpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4h
+MQppZigiX19wcm90b19fIj09PWIpcmV0dXJuITEKcmV0dXJuIHRoaXMuYi5oYXNPd25Qcm9wZXJ0eShi
+KX0sCnE6ZnVuY3Rpb24oYSxiKXtpZighdGhpcy54NCgwLGIpKXJldHVybiBudWxsCnJldHVybiB0aGlz
+LkQoYil9LApEOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC55KGEpXX0sClU6ZnVuY3Rpb24oYSxi
+KXt2YXIgdCxzLHIscSxwPUguTGgodGhpcykKcC5DKCJ+KDEsMikiKS5iKGIpCnQ9dGhpcy5jCmZvcihz
+PXQubGVuZ3RoLHA9cC5jaFsxXSxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxwLmIodGhpcy5EKHEp
+KSl9fSwKZ3Y6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlhSKHRoaXMsSC5MaCh0aGlzKS5DKCJYUjwx
+PiIpKX19CkguWFIucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYS5jCnJldHVy
+biBuZXcgSi5tMSh0LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9LApnaDpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5hLmMubGVuZ3RofX0KSC5MSS5wcm90b3R5cGU9ewpnV2E6ZnVuY3Rpb24oKXt2YXIg
+dD10aGlzLmEKcmV0dXJuIHR9LApnbmQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMKaWYocC5j
+PT09MSlyZXR1cm4gQy5kbgp0PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgtcC5mCmlmKHM9PT0wKXJl
+dHVybiBDLmRuCnI9W10KZm9yKHE9MDtxPHM7KytxKXtpZihxPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0
+LHEpCnIucHVzaCh0W3FdKX1yZXR1cm4gSi56QyhyKX0sCmdWbTpmdW5jdGlvbigpe3ZhciB0LHMscixx
+LHAsbyxuLG0sbD10aGlzCmlmKGwuYyE9PTApcmV0dXJuIEMuRHgKdD1sLmUKcz10Lmxlbmd0aApyPWwu
+ZApxPXIubGVuZ3RoLXMtbC5mCmlmKHM9PT0wKXJldHVybiBDLkR4CnA9bmV3IEguTjUodS5lbykKZm9y
+KG89MDtvPHM7KytvKXtpZihvPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LG8pCm49dFtvXQptPXErbwpp
+ZihtPDB8fG0+PXIubGVuZ3RoKXJldHVybiBILk9IKHIsbSkKcC5ZKDAsbmV3IEgud3YobiksclttXSl9
+cmV0dXJuIG5ldyBILlBEKHAsdS5nRil9LAokaXZROjF9CkguQ2oucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
+b24oYSxiKXt2YXIgdApILnkoYSkKdD10aGlzLmEKdC5iPXQuYisiJCIrSC5kKGEpCkMuTm0uQSh0aGlz
+LmIsYSkKQy5ObS5BKHRoaXMuYyxiKTsrK3QuYX0sCiRTOjEzfQpILmY5LnByb3RvdHlwZT17CnFTOmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9bmV3IFJlZ0V4cChyLmEpLmV4ZWMoYSkKaWYocT09bnVs
+bClyZXR1cm4gbnVsbAp0PU9iamVjdC5jcmVhdGUobnVsbCkKcz1yLmIKaWYocyE9PS0xKXQuYXJndW1l
+bnRzPXFbcysxXQpzPXIuYwppZihzIT09LTEpdC5hcmd1bWVudHNFeHByPXFbcysxXQpzPXIuZAppZihz
+IT09LTEpdC5leHByPXFbcysxXQpzPXIuZQppZihzIT09LTEpdC5tZXRob2Q9cVtzKzFdCnM9ci5mCmlm
+KHMhPT0tMSl0LnJlY2VpdmVyPXFbcysxXQpyZXR1cm4gdH19CkguVzAucHJvdG90eXBlPXsKdzpmdW5j
+dGlvbihhKXt2YXIgdD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIr
+SC5kKHRoaXMuYSkKcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIit0
+KyInIG9uIG51bGwifX0KSC5hei5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxy
+PSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5vdCBmb3VuZDogJyIscT1zLmIKaWYocT09bnVsbCly
+ZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIrSC5kKHMuYSkKdD1zLmMKaWYodD09bnVsbClyZXR1cm4g
+citxKyInICgiK0guZChzLmEpKyIpIgpyZXR1cm4gcitxKyInIG9uICciK3QrIicgKCIrSC5kKHMuYSkr
+IikifX0KSC52Vi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdC5s
+ZW5ndGg9PT0wPyJFcnJvciI6IkVycm9yOiAiK3R9fQpILmJxLnByb3RvdHlwZT17fQpILkFtLnByb3Rv
+dHlwZT17CiQxOmZ1bmN0aW9uKGEpe2lmKHUuYlUuYyhhKSlpZihhLiR0aHJvd25Kc0Vycm9yPT1udWxs
+KWEuJHRocm93bkpzRXJyb3I9dGhpcy5hCnJldHVybiBhfSwKJFM6NH0KSC5YTy5wcm90b3R5cGU9ewp3
+OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5iCmlmKHMhPW51bGwpcmV0dXJuIHMKcz10aGlzLmEKdD1z
+IT09bnVsbCYmdHlwZW9mIHM9PT0ib2JqZWN0Ij9zLnN0YWNrOm51bGwKcmV0dXJuIHRoaXMuYj10PT1u
+dWxsPyIiOnR9LAokaUd6OjF9CkguVHAucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmNvbnN0cnVjdG9yLHM9dD09bnVsbD9udWxsOnQubmFtZQpyZXR1cm4iQ2xvc3VyZSAnIitILk5RKHM9
+PW51bGw/InVua25vd24iOnMpKyInIn0sCiRpRUg6MSwKZ1FsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9
+LAokQzoiJDEiLAokUjoxLAokRDpudWxsfQpILmxjLnByb3RvdHlwZT17fQpILnp4LnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy4kc3RhdGljX25hbWUKaWYodD09bnVsbClyZXR1cm4iQ2xv
+c3VyZSBvZiB1bmtub3duIHN0YXRpYyBtZXRob2QiCnJldHVybiJDbG9zdXJlICciK0guTlEodCkrIici
+fX0KSC5yVC5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMKaWYoYj09bnVsbCly
+ZXR1cm4hMQppZih0PT09YilyZXR1cm4hMAppZighKGIgaW5zdGFuY2VvZiBILnJUKSlyZXR1cm4hMQpy
+ZXR1cm4gdC5hPT09Yi5hJiZ0LmI9PT1iLmImJnQuYz09PWIuY30sCmdpOmZ1bmN0aW9uKGEpe3ZhciB0
+LHM9dGhpcy5jCmlmKHM9PW51bGwpdD1ILmVRKHRoaXMuYSkKZWxzZSB0PXR5cGVvZiBzIT09Im9iamVj
+dCI/Si5oZihzKTpILmVRKHMpCnJldHVybih0XkguZVEodGhpcy5iKSk+Pj4wfSwKdzpmdW5jdGlvbihh
+KXt2YXIgdD10aGlzLmMKaWYodD09bnVsbCl0PXRoaXMuYQpyZXR1cm4iQ2xvc3VyZSAnIitILmQodGhp
+cy5kKSsiJyBvZiAiKygiSW5zdGFuY2Ugb2YgJyIrSC5kKEguTSh0KSkrIiciKX19CkguRXEucHJvdG90
+eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUnVudGltZUVycm9yOiAiK0guZCh0aGlzLmEpfX0KSC5r
+WS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVkOiAiK1AucCh0
+aGlzLmEpfX0KSC5ONS5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKZ3Y6
+ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmk1KHRoaXMsSC5MaCh0aGlzKS5DKCJpNTwxPiIpKX0sCng0
+OmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9dGhpcy5iCmlmKHQ9
+PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMuWHUodCxiKX1lbHNle3M9dGhpcy5DWChiKQpyZXR1cm4g
+c319LApDWDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4g
+dGhpcy5GKHRoaXMuSCh0LEouaGYoYSkmMHgzZmZmZmZmKSxhKT49MH0sCnE6ZnVuY3Rpb24oYSxiKXt2
+YXIgdCxzLHIscSxwPXRoaXMsbz1udWxsCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD1wLmIKaWYodD09
+bnVsbClyZXR1cm4gbwpzPXAuaih0LGIpCnI9cz09bnVsbD9vOnMuYgpyZXR1cm4gcn1lbHNlIGlmKHR5
+cGVvZiBiPT0ibnVtYmVyIiYmKGImMHgzZmZmZmZmKT09PWIpe3E9cC5jCmlmKHE9PW51bGwpcmV0dXJu
+IG8Kcz1wLmoocSxiKQpyPXM9PW51bGw/bzpzLmIKcmV0dXJuIHJ9ZWxzZSByZXR1cm4gcC5rKGIpfSwK
+azpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcy5kCmlmKHI9PW51bGwpcmV0dXJuIG51bGwKdD10aGlz
+LkgocixKLmhmKGEpJjB4M2ZmZmZmZikKcz10aGlzLkYodCxhKQppZihzPDApcmV0dXJuIG51bGwKcmV0
+dXJuIHRbc10uYn0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMsbT1ILkxo
+KG4pCm0uZC5iKGIpCm0uY2hbMV0uYihjKQppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9bi5iCm4uRyh0
+PT1udWxsP24uYj1uLmwoKTp0LGIsYyl9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjB4M2Zm
+ZmZmZik9PT1iKXtzPW4uYwpuLkcocz09bnVsbD9uLmM9bi5sKCk6cyxiLGMpfWVsc2V7cj1uLmQKaWYo
+cj09bnVsbClyPW4uZD1uLmwoKQpxPUouaGYoYikmMHgzZmZmZmZmCnA9bi5IKHIscSkKaWYocD09bnVs
+bCluLkUocixxLFtuLk8oYixjKV0pCmVsc2V7bz1uLkYocCxiKQppZihvPj0wKXBbb10uYj1jCmVsc2Ug
+cC5wdXNoKG4uTyhiLGMpKX19fSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCkguTGgociku
+QygifigxLDIpIikuYihiKQp0PXIuZQpzPXIucgpmb3IoO3QhPW51bGw7KXtiLiQyKHQuYSx0LmIpCmlm
+KHMhPT1yLnIpdGhyb3cgSC5iKFAuYTQocikpCnQ9dC5jfX0sCkc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHM9dGhpcyxyPUguTGgocykKci5kLmIoYikKci5jaFsxXS5iKGMpCnQ9cy5qKGEsYikKaWYodD09bnVs
+bClzLkUoYSxiLHMuTyhiLGMpKQplbHNlIHQuYj1jfSwKWDpmdW5jdGlvbigpe3RoaXMucj10aGlzLnIr
+MSY2NzEwODg2M30sCk86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILkxoKHMpLHE9bmV3IEgu
+dmgoci5kLmIoYSksci5jaFsxXS5iKGIpKQppZihzLmU9PW51bGwpcy5lPXMuZj1xCmVsc2V7dD1zLmYK
+cS5kPXQKcy5mPXQuYz1xfSsrcy5hCnMuWCgpCnJldHVybiBxfSwKRjpmdW5jdGlvbihhLGIpe3ZhciB0
+LHMKaWYoYT09bnVsbClyZXR1cm4tMQp0PWEubGVuZ3RoCmZvcihzPTA7czx0OysrcylpZihKLlJNKGFb
+c10uYSxiKSlyZXR1cm4gcwpyZXR1cm4tMX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAubk8odGhpcyl9
+LApqOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFbYl19LApIOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFbYl19
+LApFOmZ1bmN0aW9uKGEsYixjKXthW2JdPWN9LApWOmZ1bmN0aW9uKGEsYil7ZGVsZXRlIGFbYl19LApY
+dTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmooYSxiKSE9bnVsbH0sCmw6ZnVuY3Rpb24oKXt2YXIg
+dD0iPG5vbi1pZGVudGlmaWVyLWtleT4iLHM9T2JqZWN0LmNyZWF0ZShudWxsKQp0aGlzLkUocyx0LHMp
+CnRoaXMuVihzLHQpCnJldHVybiBzfSwKJGlGbzoxfQpILnZoLnByb3RvdHlwZT17fQpILmk1LnByb3Rv
+dHlwZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYX0sCmdrejpmdW5jdGlvbihhKXt2YXIg
+dD10aGlzLmEscz1uZXcgSC5ONih0LHQucix0aGlzLiR0aS5DKCJONjwxPiIpKQpzLmM9dC5lCnJldHVy
+biBzfX0KSC5ONi5wcm90b3R5cGU9ewpnUjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5kfSwKbTpmdW5j
+dGlvbigpe3ZhciB0PXRoaXMscz10LmEKaWYodC5iIT09cy5yKXRocm93IEguYihQLmE0KHMpKQplbHNl
+e3M9dC5jCmlmKHM9PW51bGwpe3Quc04obnVsbCkKcmV0dXJuITF9ZWxzZXt0LnNOKHMuYSkKdC5jPXQu
+Yy5jCnJldHVybiEwfX19LApzTjpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlB
+bjoxfQpILmRDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoYSl9LAokUzo0
+fQpILndOLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6
+NDV9CkguVlgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShILnkoYSkpfSwK
+JFM6Mjh9CkguVlIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5h
KyIvIit0aGlzLmIuZmxhZ3N9LApnSGM6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jCmlmKHMhPW51
bGwpcmV0dXJuIHMKcz10LmIKcmV0dXJuIHQuYz1ILnY0KHQuYSxzLm11bHRpbGluZSwhcy5pZ25vcmVD
YXNlLHMudW5pY29kZSxzLmRvdEFsbCwhMCl9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5L
Vyh0aGlzLGIsMCl9LApVWjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5nSGMoKQpzLmxhc3RJbmRl
eD1iCnQ9cy5leGVjKGEpCmlmKHQ9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIG5ldyBILkVLKHQpfSwK
-JGl2WDoxLAokaXdMOjF9CkguRUsucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkguV1ko
-YikKdD10aGlzLmIKaWYoYj49dC5sZW5ndGgpcmV0dXJuIEguayh0LGIpCnJldHVybiB0W2JdfSwKJGlP
-ZDoxLAokaWliOjF9CkguS1cucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlBi
-KHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguUGIucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0
-dXJuIHRoaXMuZH0sCm06ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmIKaWYobz09bnVs
-bClyZXR1cm4hMQp0PXAuYwppZih0PD1vLmxlbmd0aCl7cz1wLmEKcj1zLlVaKG8sdCkKaWYociE9bnVs
-bCl7cC5kPXIKbz1yLmIKdD1vLmluZGV4CnE9dCtvWzBdLmxlbmd0aAppZih0PT09cSl7aWYocy5iLnVu
-aWNvZGUpe289cC5jCnQ9bysxCnM9cC5iCmlmKHQ8cy5sZW5ndGgpe289Si5yWShzKS5PMihzLG8pCmlm
-KG8+PTU1Mjk2JiZvPD01NjMxOSl7bz1DLnhCLk8yKHMsdCkKbz1vPj01NjMyMCYmbzw9NTczNDN9ZWxz
-ZSBvPSExfWVsc2Ugbz0hMX1lbHNlIG89ITEKcT0obz9xKzE6cSkrMX1wLmM9cQpyZXR1cm4hMH19cC5i
-PXAuZD1udWxsCnJldHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxi
-KXtILldZKGIpCmlmKGIhPT0wKUguVmooUC5PNyhiLG51bGwpKQpyZXR1cm4gdGhpcy5jfSwKJGlPZDox
-fQpILk5GLnByb3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TZCh0aGlzLmEsdGhp
-cy5iLHRoaXMuYyl9fQpILlNkLnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxx
-PXIuYyxwPXIuYixvPXAubGVuZ3RoLG49ci5hLG09bi5sZW5ndGgKaWYocStvPm0pe3IuZD1udWxsCnJl
-dHVybiExfXQ9bi5pbmRleE9mKHAscSkKaWYodDwwKXtyLmM9bSsxCnIuZD1udWxsCnJldHVybiExfXM9
-dCtvCnIuZD1uZXcgSC50USh0LHApCnIuYz1zPT09ci5jP3MrMTpzCnJldHVybiEwfSwKZ1I6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuZH0sCiRpQW46MX0KSC5XWi5wcm90b3R5cGU9eyRpV1o6MX0KSC5wRi5w
-cm90b3R5cGU9eyRpcEY6MSwkaUFTOjF9CkguYjAucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0
-dXJuIGEubGVuZ3RofSwKJGlYajoxfQpILkRnLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZ
-KGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1ko
-YikKSC5kaihjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGliUToxLAokaUx5OjEsCiRpek06
-MX0KSC5QZy5wcm90b3R5cGU9ewp0OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCkguV1koYykKSC5vZChi
-LGEsYS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGlMeToxLAokaXpNOjF9CkgueGoucHJvdG90eXBl
-PXsKcTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0K
-SC5kRS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkK
-cmV0dXJuIGFbYl19fQpILlpBLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCkgub2Qo
-YixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19Ckgud2YucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIp
-e0guV1koYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpx
-OmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVF
-LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxi
-KXtILldZKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsK
-Z2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5v
-ZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90eXBl
-PXt9CkguVlAucHJvdG90eXBlPXt9CkguV0IucHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9Ckgu
-SmMucHJvdG90eXBlPXsKQzpmdW5jdGlvbihhKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlz
-LGEpfSwKSzpmdW5jdGlvbihhKXtyZXR1cm4gSC52NSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfX0KSC5F
-VC5wcm90b3R5cGU9e30KSC5rUy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9
-fQpILngucHJvdG90eXBlPXt9ClAudGgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
-cy5hLHM9dC5hCnQuYT1udWxsCnMuJDAoKX0sCiRTOjE4fQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMKdGhpcy5hLmE9dS5NLmEoYSkKdD10aGlzLmIKcz10aGlzLmMKdC5maXJzdENo
-aWxkP3QucmVtb3ZlQ2hpbGQocyk6dC5hcHBlbmRDaGlsZChzKX0sCiRTOjM5fQpQLlZzLnByb3RvdHlw
-ZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0LnBy
-b3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQ
-LlczLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEsYil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXNl
-bGYuc2V0VGltZW91dChILnRSKG5ldyBQLnlIKHRoaXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIoUC5M
-NCgiYHNldFRpbWVvdXQoKWAgbm90IGZvdW5kLiIpKX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVuY3Rp
-b24oKXt0aGlzLmIuJDAoKX0sCiRDOiIkMCIsCiRSOjAsCiRTOjJ9ClAuaWgucHJvdG90eXBlPXsKYU06
-ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcy4kdGkKci5DKCIxLyIpLmEoYikKdD0hdGhpcy5ifHxy
-LkMoImI4PDE+IikuYihiKQpzPXRoaXMuYQppZih0KXMuWGYoYikKZWxzZSBzLlgyKHIuYy5hKGIpKX0s
-CncwOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYj09bnVsbCliPVAudjAoYSkKdD10aGlzLmEKaWYodGhp
-cy5iKXQuWkwoYSxiKQplbHNlIHQuTmsoYSxiKX19ClAuV00ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMuYS4kMigwLGEpfSwKJFM6MTB9ClAuU1gucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
-b24oYSxiKXt0aGlzLmEuJDIoMSxuZXcgSC5icShhLHUubC5hKGIpKSl9LAokQzoiJDIiLAokUjoyLAok
-Uzo0MH0KUC5Hcy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYShILldZKGEpLGIpfSwK
-JFM6NDN9ClAuRnkucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iSXRlcmF0aW9uTWFya2Vy
-KCIrdGhpcy5iKyIsICIrSC5kKHRoaXMuYSkrIikifSwKZ253OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LmF9fQpQLkdWLnByb3RvdHlwZT17CmdSOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwppZih0PT1udWxs
-KXJldHVybiB0aGlzLmIKcmV0dXJuIHRoaXMuJHRpLmMuYSh0LmdSKHQpKX0sCm06ZnVuY3Rpb24oKXt2
-YXIgdCxzLHIscSxwPXRoaXMKZm9yKDshMDspe3Q9cC5jCmlmKHQhPW51bGwpaWYodC5tKCkpcmV0dXJu
-ITAKZWxzZSBwLmM9bnVsbApzPWZ1bmN0aW9uKGEsYixjKXt2YXIgbyxuPWIKd2hpbGUodHJ1ZSl0cnl7
-cmV0dXJuIGEobixvKX1jYXRjaChtKXtvPW0Kbj1jfX0ocC5hLDAsMSkKaWYocyBpbnN0YW5jZW9mIFAu
-Rnkpe3I9cy5iCmlmKHI9PT0yKXt0PXAuZAppZih0PT1udWxsfHx0Lmxlbmd0aD09PTApe3Auc0VDKG51
-bGwpCnJldHVybiExfWlmKDA+PXQubGVuZ3RoKXJldHVybiBILmsodCwtMSkKcC5hPXQucG9wKCkKY29u
-dGludWV9ZWxzZXt0PXMuYQppZihyPT09Myl0aHJvdyB0CmVsc2V7cT1KLklUKHQpCmlmKHEgaW5zdGFu
-Y2VvZiBQLkdWKXt0PXAuZAppZih0PT1udWxsKXQ9cC5kPVtdCkMuTm0uQSh0LHAuYSkKcC5hPXEuYQpj
-b250aW51ZX1lbHNle3AuYz1xCmNvbnRpbnVlfX19fWVsc2V7cC5zRUMocykKcmV0dXJuITB9fXJldHVy
-biExfSwKc0VDOmZ1bmN0aW9uKGEpe3RoaXMuYj10aGlzLiR0aS5jLmEoYSl9LAokaUFuOjF9ClAucTQu
-cHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkdWKHRoaXMuYSgpLHRoaXMuJHRp
-LkMoIkdWPDE+IikpfX0KUC5iOC5wcm90b3R5cGU9e30KUC5QZi5wcm90b3R5cGU9ewp3MDpmdW5jdGlv
-bihhLGIpe3ZhciB0ClAuVUkoYSwiZXJyb3IiLHUuSykKdD10aGlzLmEKaWYodC5hIT09MCl0aHJvdyBI
-LmIoUC5QVigiRnV0dXJlIGFscmVhZHkgY29tcGxldGVkIikpCnQuTmsoYSxiPT1udWxsP1AudjAoYSk6
-Yil9LApwbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9
-ewphTTpmdW5jdGlvbihhLGIpe3ZhciB0CnRoaXMuJHRpLkMoIjEvIikuYShiKQp0PXRoaXMuYQppZih0
-LmEhPT0wKXRocm93IEguYihQLlBWKCJGdXR1cmUgYWxyZWFkeSBjb21wbGV0ZWQiKSkKdC5YZihiKX19
-ClAuRmUucHJvdG90eXBlPXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMuYyYxNSkhPT02KXJldHVybiEw
-CnJldHVybiB0aGlzLmIuYi5idih1LmFsLmEodGhpcy5kKSxhLmEsdS55LHUuSyl9LApLdzpmdW5jdGlv
-bihhKXt2YXIgdD10aGlzLmUscz11Lnoscj11LksscT10aGlzLiR0aS5DKCIyLyIpLHA9dGhpcy5iLmIK
-aWYodS5hZy5iKHQpKXJldHVybiBxLmEocC5ycCh0LGEuYSxhLmIscyxyLHUubCkpCmVsc2UgcmV0dXJu
-IHEuYShwLmJ2KHUuYkkuYSh0KSxhLmEscyxyKSl9fQpQLnZzLnByb3RvdHlwZT17ClNxOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdCxzLHIscT10aGlzLiR0aQpxLksoYykuQygiMS8oMikiKS5hKGEpCnQ9JC5YMwpp
-Zih0IT09Qy5OVSl7Yy5DKCJAPDAvPiIpLksocS5jKS5DKCIxKDIpIikuYShhKQppZihiIT1udWxsKWI9
-UC5WSChiLHQpfXM9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnI9Yj09bnVsbD8xOjMKdGhpcy54
-ZihuZXcgUC5GZShzLHIsYSxiLHEuQygiQDwxPiIpLksoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHN9
-LApXNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVsbCxiKX0sClFkOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdCxzPXRoaXMuJHRpCnMuSyhjKS5DKCIxLygyKSIpLmEoYSkKdD1uZXcgUC52cygkLlgz
-LGMuQygidnM8MD4iKSkKdGhpcy54ZihuZXcgUC5GZSh0LDE5LGEsYixzLkMoIkA8MT4iKS5LKGMpLkMo
-IkZlPDEsMj4iKSkpCnJldHVybiB0fSwKT0E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCnUuYmYuYShudWxs
-KQp0PXRoaXMuJHRpCnM9JC5YMwpyPW5ldyBQLnZzKHMsdCkKaWYocyE9PUMuTlUpYT1QLlZIKGEscykK
-dGhpcy54ZihuZXcgUC5GZShyLDIsbnVsbCxhLHQuQygiQDwxPiIpLksodC5jKS5DKCJGZTwxLDI+Iikp
-KQpyZXR1cm4gcn0sCnhmOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPXMuYQppZihyPD0xKXthLmE9
-dS54LmEocy5jKQpzLmM9YX1lbHNle2lmKHI9PT0yKXt0PXUuXy5hKHMuYykKcj10LmEKaWYocjw0KXt0
-LnhmKGEpCnJldHVybn1zLmE9cgpzLmM9dC5jfVAuVGsobnVsbCxudWxsLHMuYix1Lk0uYShuZXcgUC5k
-YShzLGEpKSl9fSwKalE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvPXRoaXMsbj17fQpuLmE9YQpp
-ZihhPT1udWxsKXJldHVybgp0PW8uYQppZih0PD0xKXtzPXUueC5hKG8uYykKcj1vLmM9YQppZihzIT1u
-dWxsKXtmb3IoO3E9ci5hLHEhPW51bGw7cj1xKTtyLmE9c319ZWxzZXtpZih0PT09Mil7cD11Ll8uYShv
-LmMpCnQ9cC5hCmlmKHQ8NCl7cC5qUShhKQpyZXR1cm59by5hPXQKby5jPXAuY31uLmE9by5OOChhKQpQ
-LlRrKG51bGwsbnVsbCxvLmIsdS5NLmEobmV3IFAub1EobixvKSkpfX0sCmFoOmZ1bmN0aW9uKCl7dmFy
-IHQ9dS54LmEodGhpcy5jKQp0aGlzLmM9bnVsbApyZXR1cm4gdGhpcy5OOCh0KX0sCk44OmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscgpmb3IodD1hLHM9bnVsbDt0IT1udWxsO3M9dCx0PXIpe3I9dC5hCnQuYT1zfXJl
-dHVybiBzfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9cy4kdGkKci5DKCIxLyIpLmEoYSkK
-aWYoci5DKCJiODwxPiIpLmIoYSkpaWYoci5iKGEpKVAuQTkoYSxzKQplbHNlIFAuazMoYSxzKQplbHNl
-e3Q9cy5haCgpCnIuYy5hKGEpCnMuYT00CnMuYz1hClAuSFoocyx0KX19LApYMjpmdW5jdGlvbihhKXt2
-YXIgdCxzPXRoaXMKcy4kdGkuYy5hKGEpCnQ9cy5haCgpCnMuYT00CnMuYz1hClAuSFoocyx0KX0sClpM
-OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMKdS5sLmEoYikKdD1yLmFoKCkKcz1QLlRsKGEsYikK
-ci5hPTgKci5jPXMKUC5IWihyLHQpfSwKWGY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPXQuJHRpCnMu
-QygiMS8iKS5hKGEpCmlmKHMuQygiYjg8MT4iKS5iKGEpKXt0LmNVKGEpCnJldHVybn10LmE9MQpQLlRr
-KG51bGwsbnVsbCx0LmIsdS5NLmEobmV3IFAuckgodCxhKSkpfSwKY1U6ZnVuY3Rpb24oYSl7dmFyIHQ9
-dGhpcyxzPXQuJHRpCnMuQygiYjg8MT4iKS5hKGEpCmlmKHMuYihhKSl7aWYoYS5hPT09OCl7dC5hPTEK
-UC5UayhudWxsLG51bGwsdC5iLHUuTS5hKG5ldyBQLktGKHQsYSkpKX1lbHNlIFAuQTkoYSx0KQpyZXR1
-cm59UC5rMyhhLHQpfSwKTms6ZnVuY3Rpb24oYSxiKXt0aGlzLmE9MQpQLlRrKG51bGwsbnVsbCx0aGlz
-LmIsdS5NLmEobmV3IFAuWkwodGhpcyxhLGIpKSl9LAokaWI4OjF9ClAuZGEucHJvdG90eXBlPXsKJDA6
-ZnVuY3Rpb24oKXtQLkhaKHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KUC5vUS5wcm90b3R5cGU9ewokMDpm
-dW5jdGlvbigpe1AuSFoodGhpcy5iLHRoaXMuYS5hKX0sCiRTOjB9ClAucFYucHJvdG90eXBlPXsKJDE6
-ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnQuYT0wCnQuSEgoYSl9LAokUzoxOH0KUC5VNy5wcm90b3R5
-cGU9ewokMjpmdW5jdGlvbihhLGIpe3UubC5hKGIpCnRoaXMuYS5aTChhLGIpfSwKJDE6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMuJDIoYSxudWxsKX0sCiRDOiIkMiIsCiREOmZ1bmN0aW9uKCl7cmV0dXJuW251
-bGxdfSwKJFM6MjZ9ClAudnIucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5i
-LHRoaXMuYyl9LAokUzowfQpQLnJILnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5h
-CnQuWDIodC4kdGkuYy5hKHRoaXMuYikpfSwKJFM6MH0KUC5LRi5wcm90b3R5cGU9ewokMDpmdW5jdGlv
-bigpe1AuQTkodGhpcy5iLHRoaXMuYSl9LAokUzowfQpQLlpMLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
-KCl7dGhpcy5hLlpMKHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KUC5SVC5wcm90b3R5cGU9ewokMDpmdW5j
-dGlvbigpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMsbT1udWxsCnRyeXtyPW4uYwptPXIuYi5iLnp6KHUu
-Zk8uYShyLmQpLHUueil9Y2F0Y2gocSl7dD1ILlJ1KHEpCnM9SC50cyhxKQppZihuLmQpe3I9dS5uLmEo
-bi5hLmEuYykuYQpwPXQKcD1yPT1udWxsP3A9PW51bGw6cj09PXAKcj1wfWVsc2Ugcj0hMQpwPW4uYgpp
-ZihyKXAuYj11Lm4uYShuLmEuYS5jKQplbHNlIHAuYj1QLlRsKHQscykKcC5hPSEwCnJldHVybn1pZih1
-LmMuYihtKSl7aWYobSBpbnN0YW5jZW9mIFAudnMmJm0uYT49NCl7aWYobS5hPT09OCl7cj1uLmIKci5i
-PXUubi5hKG0uYykKci5hPSEwfXJldHVybn1vPW4uYS5hCnI9bi5iCnIuYj1tLlc3KG5ldyBQLmpaKG8p
-LHUueikKci5hPSExfX0sCiRTOjJ9ClAualoucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHRoaXMuYX0sCiRTOjMwfQpQLnJxLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEs
-cCxvLG4sbT10aGlzCnRyeXtyPW0uYgpxPXIuJHRpCnA9cS5jCm89cC5hKG0uYykKbS5hLmI9ci5iLmIu
-YnYocS5DKCIyLygxKSIpLmEoci5kKSxvLHEuQygiMi8iKSxwKX1jYXRjaChuKXt0PUguUnUobikKcz1I
-LnRzKG4pCnI9bS5hCnIuYj1QLlRsKHQscykKci5hPSEwfX0sCiRTOjJ9ClAuUlcucHJvdG90eXBlPXsK
-JDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhpcwp0cnl7dD11Lm4uYShsLmEuYS5j
-KQpxPWwuYwppZihILm9UKHEuSFIodCkpJiZxLmUhPW51bGwpe3A9bC5iCnAuYj1xLkt3KHQpCnAuYT0h
-MX19Y2F0Y2gobyl7cz1ILlJ1KG8pCnI9SC50cyhvKQpxPXUubi5hKGwuYS5hLmMpCnA9cS5hCm49cwpt
-PWwuYgppZihwPT1udWxsP249PW51bGw6cD09PW4pbS5iPXEKZWxzZSBtLmI9UC5UbChzLHIpCm0uYT0h
-MH19LAokUzoyfQpQLk9NLnByb3RvdHlwZT17fQpQLnFoLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEp
-e3ZhciB0LHMscj10aGlzLHE9e30scD1uZXcgUC52cygkLlgzLHUuZkopCnEuYT0wCnQ9SC5MaChyKQpz
-PXQuQygifigxKSIpLmEobmV3IFAuQjUocSxyKSkKdS5NLmEobmV3IFAuUEkocSxwKSkKVy5KRShyLmEs
-ci5iLHMsITEsdC5jKQpyZXR1cm4gcH19ClAuQjUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC5M
-aCh0aGlzLmIpLmMuYShhKTsrK3RoaXMuYS5hfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gSC5MaCh0aGlz
-LmIpLkMoImM4KDEpIil9fQpQLlBJLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5iLkhIKHRo
-aXMuYS5hKX0sCiRTOjB9ClAuTU8ucHJvdG90eXBlPXt9ClAua1QucHJvdG90eXBlPXt9ClAueEkucHJv
-dG90eXBlPXt9ClAuT0gucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gSC5kKHRoaXMuYSl9
-LAokaVhTOjEsCmdJSTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJ9fQpQLm0wLnByb3RvdHlwZT17JGlK
-QjoxfQpQLnBLLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLmEscj1zLmIKaWYo
-cj09bnVsbCl0aHJvdyBILmIocy5hKQp0PUguYihzLmEpCnQuc3RhY2s9ci5aKDApCnRocm93IHR9LAok
-UzowfQpQLkppLnByb3RvdHlwZT17CmJIOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPW51bGwKdS5NLmEo
-YSkKdHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQwKCkKcmV0dXJufVAuVDgocSxxLHRoaXMsYSx1LkgpfWNh
-dGNoKHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5MMihxLHEsdGhpcyx0LHUubC5hKHMpKX19LApEbDpm
-dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9bnVsbApjLkMoIn4oMCkiKS5hKGEpCmMuYShiKQp0cnl7
-aWYoQy5OVT09PSQuWDMpe2EuJDEoYikKcmV0dXJufVAueXYocSxxLHRoaXMsYSxiLHUuSCxjKX1jYXRj
-aChyKXt0PUguUnUocikKcz1ILnRzKHIpClAuTDIocSxxLHRoaXMsdCx1LmwuYShzKSl9fSwKUlQ6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuaGoodGhpcyxiLkMoIjAoKSIpLmEoYSksYil9LApHWTpmdW5j
-dGlvbihhKXtyZXR1cm4gbmV3IFAuVnAodGhpcyx1Lk0uYShhKSl9LApQeTpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBuZXcgUC5PUih0aGlzLGIuQygifigwKSIpLmEoYSksYil9LApxOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIG51bGx9LAp6ejpmdW5jdGlvbihhLGIpe2IuQygiMCgpIikuYShhKQppZigkLlgzPT09Qy5OVSly
-ZXR1cm4gYS4kMCgpCnJldHVybiBQLlQ4KG51bGwsbnVsbCx0aGlzLGEsYil9LApidjpmdW5jdGlvbihh
-LGIsYyxkKXtjLkMoIkA8MD4iKS5LKGQpLkMoIjEoMikiKS5hKGEpCmQuYShiKQppZigkLlgzPT09Qy5O
-VSlyZXR1cm4gYS4kMShiKQpyZXR1cm4gUC55dihudWxsLG51bGwsdGhpcyxhLGIsYyxkKX0sCnJwOmZ1
-bmN0aW9uKGEsYixjLGQsZSxmKXtkLkMoIkA8MD4iKS5LKGUpLksoZikuQygiMSgyLDMpIikuYShhKQpl
-LmEoYikKZi5hKGMpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQyKGIsYykKcmV0dXJuIFAuUXgobnVs
-bCxudWxsLHRoaXMsYSxiLGMsZCxlLGYpfSwKTGo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGIuQygi
-QDwwPiIpLksoYykuSyhkKS5DKCIxKDIsMykiKS5hKGEpfX0KUC5oai5wcm90b3R5cGU9ewokMDpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmEuenoodGhpcy5iLHRoaXMuYyl9LAokUzpmdW5jdGlvbigpe3JldHVy
-biB0aGlzLmMuQygiMCgpIil9fQpQLlZwLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7cmV0dXJuIHRo
-aXMuYS5iSCh0aGlzLmIpfSwKJFM6Mn0KUC5PUi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-dD10aGlzLmMKcmV0dXJuIHRoaXMuYS5EbCh0aGlzLmIsdC5hKGEpLHQpfSwKJFM6ZnVuY3Rpb24oKXty
-ZXR1cm4gdGhpcy5jLkMoIn4oMCkiKX19ClAuYjYucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7dmFy
-IHQ9dGhpcyxzPW5ldyBQLmxtKHQsdC5yLEguTGgodCkuQygibG08MT4iKSkKcy5jPXQuZQpyZXR1cm4g
-c30sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0LHMK
-aWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3Q9dGhpcy5iCmlmKHQ9PW51bGwp
-cmV0dXJuITEKcmV0dXJuIHUuSi5hKHRbYl0pIT1udWxsfWVsc2V7cz10aGlzLlBSKGIpCnJldHVybiBz
-fX0sClBSOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiExCnJldHVybiB0
-aGlzLkRGKHRbdGhpcy5yayhhKV0sYSk+PTB9LApBOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMK
-SC5MaChyKS5jLmEoYikKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3Q9ci5i
-CnJldHVybiByLmNXKHQ9PW51bGw/ci5iPVAuVDIoKTp0LGIpfWVsc2UgaWYodHlwZW9mIGI9PSJudW1i
-ZXIiJiYoYiYxMDczNzQxODIzKT09PWIpe3M9ci5jCnJldHVybiByLmNXKHM9PW51bGw/ci5jPVAuVDIo
-KTpzLGIpfWVsc2UgcmV0dXJuIHIuQjcoMCxiKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9
-dGhpcwpILkxoKHEpLmMuYShiKQp0PXEuZAppZih0PT1udWxsKXQ9cS5kPVAuVDIoKQpzPXEucmsoYikK
-cj10W3NdCmlmKHI9PW51bGwpdFtzXT1bcS5kZyhiKV0KZWxzZXtpZihxLkRGKHIsYik+PTApcmV0dXJu
-ITEKci5wdXNoKHEuZGcoYikpfXJldHVybiEwfSwKUno6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzCmlm
-KHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXJldHVybiB0Lkg0KHQuYixiKQplbHNl
-IGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXJldHVybiB0Lkg0KHQuYyxi
-KQplbHNlIHJldHVybiB0LnFnKDAsYil9LApxZzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhp
-cyxvPXAuZAppZihvPT1udWxsKXJldHVybiExCnQ9cC5yayhiKQpzPW9bdF0Kcj1wLkRGKHMsYikKaWYo
-cjwwKXJldHVybiExCnE9cy5zcGxpY2UociwxKVswXQppZigwPT09cy5sZW5ndGgpZGVsZXRlIG9bdF0K
-cC5HUyhxKQpyZXR1cm4hMH0sCmNXOmZ1bmN0aW9uKGEsYil7SC5MaCh0aGlzKS5jLmEoYikKaWYodS5K
-LmEoYVtiXSkhPW51bGwpcmV0dXJuITEKYVtiXT10aGlzLmRnKGIpCnJldHVybiEwfSwKSDQ6ZnVuY3Rp
-b24oYSxiKXt2YXIgdAppZihhPT1udWxsKXJldHVybiExCnQ9dS5KLmEoYVtiXSkKaWYodD09bnVsbCly
-ZXR1cm4hMQp0aGlzLkdTKHQpCmRlbGV0ZSBhW2JdCnJldHVybiEwfSwKWEE6ZnVuY3Rpb24oKXt0aGlz
-LnI9MTA3Mzc0MTgyMyZ0aGlzLnIrMX0sCmRnOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPW5ldyBQ
-LmJuKEguTGgocykuYy5hKGEpKQppZihzLmU9PW51bGwpcy5lPXMuZj1yCmVsc2V7dD1zLmYKci5jPXQK
-cy5mPXQuYj1yfSsrcy5hCnMuWEEoKQpyZXR1cm4gcn0sCkdTOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMs
-cz1hLmMscj1hLmIKaWYocz09bnVsbCl0LmU9cgplbHNlIHMuYj1yCmlmKHI9PW51bGwpdC5mPXMKZWxz
-ZSByLmM9czstLXQuYQp0LlhBKCl9LApyazpmdW5jdGlvbihhKXtyZXR1cm4gSi5JKGEpJjEwNzM3NDE4
-MjN9LApERjpmdW5jdGlvbihhLGIpe3ZhciB0LHMKaWYoYT09bnVsbClyZXR1cm4tMQp0PWEubGVuZ3Ro
-CmZvcihzPTA7czx0OysrcylpZihKLlJNKGFbc10uYSxiKSlyZXR1cm4gcwpyZXR1cm4tMX19ClAuYm4u
-cHJvdG90eXBlPXt9ClAubG0ucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0s
-Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChz
-KSkKZWxzZXtzPXQuYwppZihzPT1udWxsKXt0LnNCYihudWxsKQpyZXR1cm4hMX1lbHNle3Quc0JiKHQu
-JHRpLmMuYShzLmEpKQp0LmM9dC5jLmIKcmV0dXJuITB9fX0sCnNCYjpmdW5jdGlvbihhKXt0aGlzLmQ9
-dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpQLm1XLnByb3RvdHlwZT17fQpQLkxVLnByb3RvdHlwZT17
-JGliUToxLCRpTHk6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7cmV0dXJu
-IG5ldyBILmE3KGEsdGhpcy5nayhhKSxILnEoYSkuQygiYTc8bEQuRT4iKSl9LApXOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIHRoaXMucShhLGIpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC5xKGEpLkMoIn4o
-bEQuRSkiKS5hKGIpCnQ9dGhpcy5nayhhKQpmb3Iocz0wO3M8dDsrK3Mpe2IuJDEodGhpcy5xKGEscykp
-CmlmKHQhPT10aGlzLmdrKGEpKXRocm93IEguYihQLmE0KGEpKX19LApFMjpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQ9SC5xKGEpCnJldHVybiBuZXcgSC5sSihhLHQuSyhjKS5DKCIxKGxELkUpIikuYShiKSx0LkMo
-IkA8bEQuRT4iKS5LKGMpLkMoImxKPDEsMj4iKSl9LApkdTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdApI
-LnEoYSkuQygibEQuRSIpLmEoZCkKUC5qQihiLGMsdGhpcy5nayhhKSkKZm9yKHQ9Yjt0PGM7Kyt0KXRo
-aXMudChhLHQsZCl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9fQpQLmlsLnBy
-b3RvdHlwZT17fQpQLnJhLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmEK
-aWYoIXMuYSl0aGlzLmIuYSs9IiwgIgpzLmE9ITEKcz10aGlzLmIKdD1zLmErPUguZChhKQpzLmE9dCsi
-OiAiCnMuYSs9SC5kKGIpfSwKJFM6MX0KUC5Zay5wcm90b3R5cGU9ewpVOmZ1bmN0aW9uKGEsYil7dmFy
-IHQscwpILnEoYSkuQygifihZay5LLFlrLlYpIikuYShiKQpmb3IodD1KLklUKHRoaXMuZ3YoYSkpO3Qu
-bSgpOyl7cz10LmdSKHQpCmIuJDIocyx0aGlzLnEoYSxzKSl9fSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVy
-biBKLk0xKHRoaXMuZ3YoYSksbmV3IFAueVEoYSksSC5xKGEpLkMoIk4zPFlrLkssWWsuVj4iKSl9LApn
-azpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuZ3YoYSkpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4g
-UC5uTyhhKX0sCiRpWjA6MX0KUC55US5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlz
-LmEscz1ILnEodCkKcy5DKCJZay5LIikuYShhKQpyZXR1cm4gbmV3IFAuTjMoYSxKLng5KHQsYSkscy5D
-KCJAPFlrLks+IikuSyhzLkMoIllrLlYiKSkuQygiTjM8MSwyPiIpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0
-dXJuIEgucSh0aGlzLmEpLkMoIk4zPFlrLkssWWsuVj4oWWsuSykiKX19ClAuS1AucHJvdG90eXBlPXsK
-dDpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQp0LmMuYShiKQp0LlFbMV0uYShjKQp0aHJv
-dyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUgbWFwIikpfX0KUC5Qbi5wcm90b3R5
-cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEoueDkodGhpcy5hLGIpfSwKdDpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHQ9SC5MaCh0aGlzKQpKLnU5KHRoaXMuYSx0LmMuYShiKSx0LlFbMV0uYShjKSl9LApVOmZ1
-bmN0aW9uKGEsYil7Si5oRSh0aGlzLmEsSC5MaCh0aGlzKS5DKCJ+KDEsMikiKS5hKGIpKX0sCmdrOmZ1
-bmN0aW9uKGEpe3JldHVybiBKLkgodGhpcy5hKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIEouQWModGhp
-cy5hKX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gSi5RTSh0aGlzLmEpfSwKJGlaMDoxfQpQLkdqLnBy
-b3RvdHlwZT17fQpQLk1hLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UodGhpcywi
-eyIsIn0iKX19ClAuUksucHJvdG90eXBlPXskaWJROjEsJGlMeToxLCRpeHU6MX0KUC5Ydi5wcm90b3R5
-cGU9ewpGVjpmdW5jdGlvbihhLGIpe3ZhciB0CmZvcih0PUouSVQoSC5MaCh0aGlzKS5DKCJMeTwxPiIp
-LmEoYikpO3QubSgpOyl0aGlzLkEoMCx0LmdSKHQpKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0Uo
-dGhpcywieyIsIn0iKX0sCnpWOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1QLnJqKHRoaXMsdGhpcy5yLEgu
-TGgodGhpcykuYykKaWYoIXMubSgpKXJldHVybiIiCmlmKGI9PT0iIil7dD0iIgpkbyB0Kz1ILmQocy5k
-KQp3aGlsZShzLm0oKSl9ZWxzZXt0PUguZChzLmQpCmZvcig7cy5tKCk7KXQ9dCtiK0guZChzLmQpfXJl
-dHVybiB0LmNoYXJDb2RlQXQoMCk9PTA/dDp0fSwKJGliUToxLAokaUx5OjEsCiRpeHU6MX0KUC5uWS5w
-cm90b3R5cGU9e30KUC5Mai5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90b3R5
-cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4gdGhpcy5j
-LnEoMCxiKQplbHNlIGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4gbnVsbAplbHNle3Q9c1tiXQpy
-ZXR1cm4gdHlwZW9mIHQ9PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6dH19LApnazpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5iPT1udWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5ndGh9LApndjpmdW5jdGlvbihh
-KXt2YXIgdAppZih0aGlzLmI9PW51bGwpe3Q9dGhpcy5jCnJldHVybiBuZXcgSC5pNSh0LEguTGgodCku
-QygiaTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKdDpmdW5jdGlvbihhLGIsYyl7dmFyIHQs
-cyxyPXRoaXMKaWYoci5iPT1udWxsKXIuYy50KDAsYixjKQplbHNlIGlmKHIueDQoMCxiKSl7dD1yLmIK
-dFtiXT1jCnM9ci5hCmlmKHM9PW51bGw/dCE9bnVsbDpzIT09dClzW2JdPW51bGx9ZWxzZSByLlhLKCku
-dCgwLGIsYyl9LAp4NDpmdW5jdGlvbihhLGIpe2lmKHRoaXMuYj09bnVsbClyZXR1cm4gdGhpcy5jLng0
-KDAsYikKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYil9
-LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuVC5hKGIpCmlmKHAuYj09bnVsbCly
-ZXR1cm4gcC5jLlUoMCxiKQp0PXAuQ2YoKQpmb3Iocz0wO3M8dC5sZW5ndGg7KytzKXtyPXRbc10KcT1w
-LmJbcl0KaWYodHlwZW9mIHE9PSJ1bmRlZmluZWQiKXtxPVAuUWUocC5hW3JdKQpwLmJbcl09cX1iLiQy
-KHIscSkKaWYodCE9PXAuYyl0aHJvdyBILmIoUC5hNChwKSl9fSwKQ2Y6ZnVuY3Rpb24oKXt2YXIgdD11
-LmouYSh0aGlzLmMpCmlmKHQ9PW51bGwpdD10aGlzLmM9SC5WTShPYmplY3Qua2V5cyh0aGlzLmEpLHUu
-cykKcmV0dXJuIHR9LApYSzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbz10aGlzCmlmKG8uYj09bnVs
-bClyZXR1cm4gby5jCnQ9UC5GbCh1Lk4sdS56KQpzPW8uQ2YoKQpmb3Iocj0wO3E9cy5sZW5ndGgscjxx
-Oysrcil7cD1zW3JdCnQudCgwLHAsby5xKDAscCkpfWlmKHE9PT0wKUMuTm0uQShzLG51bGwpCmVsc2Ug
-Qy5ObS5zayhzLDApCm8uYT1vLmI9bnVsbApyZXR1cm4gby5jPXR9LApmYjpmdW5jdGlvbihhKXt2YXIg
-dAppZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuYSxhKSlyZXR1cm4g
-bnVsbAp0PVAuUWUodGhpcy5hW2FdKQpyZXR1cm4gdGhpcy5iW2FdPXR9fQpQLmk4LnByb3RvdHlwZT17
-CmdrOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdC5nayh0KX0sClc6ZnVuY3Rpb24oYSxi
-KXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXQ9dC5ndih0KS5XKDAsYikKZWxzZXt0PXQuQ2YoKQpp
-ZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILmsodCxiKQp0PXRbYl19cmV0dXJuIHR9LApndzpmdW5j
-dGlvbihhKXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXt0PXQuZ3YodCkKdD10Lmd3KHQpfWVsc2V7
-dD10LkNmKCkKdD1uZXcgSi5tMSh0LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9cmV0dXJuIHR9
-fQpQLkNWLnByb3RvdHlwZT17CnlyOmZ1bmN0aW9uKGEsYTAsYTEsYTIpe3ZhciB0LHMscixxLHAsbyxu
-LG0sbCxrLGosaSxoLGcsZixlLGQsYyxiPSJJbnZhbGlkIGJhc2U2NCBlbmNvZGluZyBsZW5ndGggIgph
-Mj1QLmpCKGExLGEyLGEwLmxlbmd0aCkKdD0kLlY3KCkKZm9yKHM9YTEscj1zLHE9bnVsbCxwPS0xLG89
-LTEsbj0wO3M8YTI7cz1tKXttPXMrMQpsPUMueEIuV2QoYTAscykKaWYobD09PTM3KXtrPW0rMgppZihr
-PD1hMil7aj1ILm9vKEMueEIuV2QoYTAsbSkpCmk9SC5vbyhDLnhCLldkKGEwLG0rMSkpCmg9aioxNitp
-LShpJjI1NikKaWYoaD09PTM3KWg9LTEKbT1rfWVsc2UgaD0tMX1lbHNlIGg9bAppZigwPD1oJiZoPD0x
-Mjcpe2lmKGg8MHx8aD49dC5sZW5ndGgpcmV0dXJuIEguayh0LGgpCmc9dFtoXQppZihnPj0wKXtoPUMu
-eEIuTzIoIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXow
-MTIzNDU2Nzg5Ky8iLGcpCmlmKGg9PT1sKWNvbnRpbnVlCmw9aH1lbHNle2lmKGc9PT0tMSl7aWYocDww
-KXtmPXE9PW51bGw/bnVsbDpxLmEubGVuZ3RoCmlmKGY9PW51bGwpZj0wCnA9Zisocy1yKQpvPXN9Kytu
-CmlmKGw9PT02MSljb250aW51ZX1sPWh9aWYoZyE9PS0yKXtpZihxPT1udWxsKXE9bmV3IFAuUm4oIiIp
-CnEuYSs9Qy54Qi5OaihhMCxyLHMpCnEuYSs9SC5MdyhsKQpyPW0KY29udGludWV9fXRocm93IEguYihQ
-LnJyKCJJbnZhbGlkIGJhc2U2NCBkYXRhIixhMCxzKSl9aWYocSE9bnVsbCl7Zj1xLmErPUMueEIuTmoo
-YTAscixhMikKZT1mLmxlbmd0aAppZihwPj0wKVAueE0oYTAsbyxhMixwLG4sZSkKZWxzZXtkPUMuam4u
-elkoZS0xLDQpKzEKaWYoZD09PTEpdGhyb3cgSC5iKFAucnIoYixhMCxhMikpCmZvcig7ZDw0Oyl7Zis9
-Ij0iCnEuYT1mOysrZH19Zj1xLmEKcmV0dXJuIEMueEIuaTcoYTAsYTEsYTIsZi5jaGFyQ29kZUF0KDAp
-PT0wP2Y6Zil9Yz1hMi1hMQppZihwPj0wKVAueE0oYTAsbyxhMixwLG4sYykKZWxzZXtkPUMuam4uelko
-Yyw0KQppZihkPT09MSl0aHJvdyBILmIoUC5ycihiLGEwLGEyKSkKaWYoZD4xKWEwPUMueEIuaTcoYTAs
-YTIsYTIsZD09PTI/Ij09IjoiPSIpfXJldHVybiBhMH19ClAudkEucHJvdG90eXBlPXt9ClAuVWsucHJv
-dG90eXBlPXt9ClAud0kucHJvdG90eXBlPXt9ClAuWmkucHJvdG90eXBlPXt9ClAuYnkucHJvdG90eXBl
-PXsKcFc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CnUuZXAuYShjKQp0PVAuQlMoYix0aGlzLmdIZSgpLmEp
-CnJldHVybiB0fSwKZ0hlOmZ1bmN0aW9uKCl7cmV0dXJuIEMuQTN9fQpQLk14LnByb3RvdHlwZT17fQpQ
-LnU1LnByb3RvdHlwZT17CmdaRTpmdW5jdGlvbigpe3JldHVybiBDLlFrfX0KUC5FMy5wcm90b3R5cGU9
-ewpXSjpmdW5jdGlvbihhKXt2YXIgdCxzLHI9UC5qQigwLG51bGwsYS5sZW5ndGgpLHE9ci0wCmlmKHE9
-PT0wKXJldHVybiBuZXcgVWludDhBcnJheSgwKQp0PW5ldyBVaW50OEFycmF5KHEqMykKcz1uZXcgUC5S
-dyh0KQppZihzLkd4KGEsMCxyKSE9PXIpcy5PNihKLmE2KGEsci0xKSwwKQpyZXR1cm4gbmV3IFVpbnQ4
-QXJyYXkodC5zdWJhcnJheSgwLEguck0oMCxzLmIsdC5sZW5ndGgpKSl9fQpQLlJ3LnByb3RvdHlwZT17
-Ck82OmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLHI9cy5jLHE9cy5iLHA9cSsxLG89ci5sZW5ndGgK
-aWYoKGImNjQ1MTIpPT09NTYzMjApe3Q9NjU1MzYrKChhJjEwMjMpPDwxMCl8YiYxMDIzCnMuYj1wCmlm
-KHE+PW8pcmV0dXJuIEguayhyLHEpCnJbcV09MjQwfHQ+Pj4xOApxPXMuYj1wKzEKaWYocD49bylyZXR1
-cm4gSC5rKHIscCkKcltwXT0xMjh8dD4+PjEyJjYzCnA9cy5iPXErMQppZihxPj1vKXJldHVybiBILmso
-cixxKQpyW3FdPTEyOHx0Pj4+NiY2MwpzLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguayhyLHApCnJbcF09
-MTI4fHQmNjMKcmV0dXJuITB9ZWxzZXtzLmI9cAppZihxPj1vKXJldHVybiBILmsocixxKQpyW3FdPTIy
-NHxhPj4+MTIKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguayhyLHApCnJbcF09MTI4fGE+Pj42JjYz
-CnMuYj1xKzEKaWYocT49bylyZXR1cm4gSC5rKHIscSkKcltxXT0xMjh8YSY2MwpyZXR1cm4hMX19LApH
-eDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzCmlmKGIhPT1jJiYoQy54Qi5P
-MihhLGMtMSkmNjQ1MTIpPT09NTUyOTYpLS1jCmZvcih0PW0uYyxzPXQubGVuZ3RoLHI9YjtyPGM7Kyty
-KXtxPUMueEIuV2QoYSxyKQppZihxPD0xMjcpe3A9bS5iCmlmKHA+PXMpYnJlYWsKbS5iPXArMQp0W3Bd
-PXF9ZWxzZSBpZigocSY2NDUxMik9PT01NTI5Nil7aWYobS5iKzM+PXMpYnJlYWsKbz1yKzEKaWYobS5P
-NihxLEMueEIuV2QoYSxvKSkpcj1vfWVsc2UgaWYocTw9MjA0Nyl7cD1tLmIKbj1wKzEKaWYobj49cyli
-cmVhawptLmI9bgppZihwPj1zKXJldHVybiBILmsodCxwKQp0W3BdPTE5MnxxPj4+NgptLmI9bisxCnRb
+JGl2WDoxLAokaXdMOjF9CkguRUsucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkguU2Mo
+YikKdD10aGlzLmIKaWYoYj49dC5sZW5ndGgpcmV0dXJuIEguT0godCxiKQpyZXR1cm4gdFtiXX0sCiRp
+T2Q6MSwKJGlpYjoxfQpILktXLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEgu
+UGIodGhpcy5hLHRoaXMuYix0aGlzLmMpfX0KSC5QYi5wcm90b3R5cGU9ewpnUjpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5kfSwKbTpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcyxvPXAuYgppZihvPT1u
+dWxsKXJldHVybiExCnQ9cC5jCmlmKHQ8PW8ubGVuZ3RoKXtzPXAuYQpyPXMuVVoobyx0KQppZihyIT1u
+dWxsKXtwLmQ9cgpvPXIuYgp0PW8uaW5kZXgKcT10K29bMF0ubGVuZ3RoCmlmKHQ9PT1xKXtpZihzLmIu
+dW5pY29kZSl7bz1wLmMKdD1vKzEKcz1wLmIKaWYodDxzLmxlbmd0aCl7bz1KLnJZKHMpLk8yKHMsbykK
+aWYobz49NTUyOTYmJm88PTU2MzE5KXtvPUMueEIuTzIocyx0KQpvPW8+PTU2MzIwJiZvPD01NzM0M31l
+bHNlIG89ITF9ZWxzZSBvPSExfWVsc2Ugbz0hMQpxPShvP3ErMTpxKSsxfXAuYz1xCnJldHVybiEwfX1w
+LmI9cC5kPW51bGwKcmV0dXJuITF9LAokaUFuOjF9CkgudFEucHJvdG90eXBlPXsKcTpmdW5jdGlvbihh
+LGIpe0guU2MoYikKaWYoYiE9PTApSC5WaihQLngoYixudWxsKSkKcmV0dXJuIHRoaXMuY30sCiRpT2Q6
+MX0KSC51bi5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlNkKHRoaXMuYSx0
+aGlzLmIsdGhpcy5jKX19CkguU2QucHJvdG90eXBlPXsKbTpmdW5jdGlvbigpe3ZhciB0LHMscj10aGlz
+LHE9ci5jLHA9ci5iLG89cC5sZW5ndGgsbj1yLmEsbT1uLmxlbmd0aAppZihxK28+bSl7ci5kPW51bGwK
+cmV0dXJuITF9dD1uLmluZGV4T2YocCxxKQppZih0PDApe3IuYz1tKzEKci5kPW51bGwKcmV0dXJuITF9
+cz10K28Kci5kPW5ldyBILnRRKHQscCkKci5jPXM9PT1yLmM/cysxOnMKcmV0dXJuITB9LApnUjpmdW5j
+dGlvbihhKXtyZXR1cm4gdGhpcy5kfSwKJGlBbjoxfQpILldaLnByb3RvdHlwZT17JGlXWjoxfQpILkVU
+LnByb3RvdHlwZT17JGlFVDoxLCRpQVM6MX0KSC5kZi5wcm90b3R5cGU9eyRpV3k6MX0KSC5iMC5wcm90
+b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaVhqOjF9CkguRGcucHJvdG90
+eXBlPXsKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2Jd
+fSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhiKQpILklnKGMpCkgub2QoYixhLGEubGVuZ3RoKQphW2Jd
+PWN9LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpILlBnLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxi
+LGMpe0guU2MoYikKSC5TYyhjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGliUToxLAokaWNY
+OjEsCiRpek06MX0KSC54ai5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIs
+YSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmRFLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtI
+LlNjKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguWkEucHJvdG90eXBlPXsKcTpm
+dW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC53Zi5w
+cm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJu
+IGFbYl19fQpILlBxLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCkgub2QoYixhLGEu
+bGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguZUUucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVy
+biBhW2JdfX0KSC5WNi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApx
+OmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LAokaVY2
+OjEsCiRpbjY6MX0KSC5SRy5wcm90b3R5cGU9e30KSC5WUC5wcm90b3R5cGU9e30KSC5XQi5wcm90b3R5
+cGU9e30KSC5aRy5wcm90b3R5cGU9e30KSC5KYy5wcm90b3R5cGU9ewpDOmZ1bmN0aW9uKGEpe3JldHVy
+biBILmNFKHYudHlwZVVuaXZlcnNlLHRoaXMsYSl9LApLOmZ1bmN0aW9uKGEpe3JldHVybiBILnY1KHYu
+dHlwZVVuaXZlcnNlLHRoaXMsYSl9fQpILkcucHJvdG90eXBlPXt9CkgudTkucHJvdG90eXBlPXsKdzpm
+dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfX0KSC5oei5wcm90b3R5cGU9e30KSC5pTS5wcm90b3R5cGU9
+e30KUC50aC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEscz10LmEKdC5hPW51
+bGwKcy4kMCgpfSwKJFM6MTh9ClAuaGEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscwp0
+aGlzLmEuYT11Lk0uYihhKQp0PXRoaXMuYgpzPXRoaXMuYwp0LmZpcnN0Q2hpbGQ/dC5yZW1vdmVDaGls
+ZChzKTp0LmFwcGVuZENoaWxkKHMpfSwKJFM6Mzl9ClAuVnMucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24o
+KXt0aGlzLmEuJDAoKX0sCiRDOiIkMCIsCiRSOjAsCiRTOjB9ClAuRnQucHJvdG90eXBlPXsKJDA6ZnVu
+Y3Rpb24oKXt0aGlzLmEuJDAoKX0sCiRDOiIkMCIsCiRSOjAsCiRTOjB9ClAuVzMucHJvdG90eXBlPXsK
+Q1k6ZnVuY3Rpb24oYSxiKXtpZihzZWxmLnNldFRpbWVvdXQhPW51bGwpc2VsZi5zZXRUaW1lb3V0KEgu
+dFIobmV3IFAueUgodGhpcyxiKSwwKSxhKQplbHNlIHRocm93IEguYihQLkw0KCJgc2V0VGltZW91dCgp
+YCBub3QgZm91bmQuIikpfX0KUC55SC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYi4kMCgp
+fSwKJEM6IiQwIiwKJFI6MCwKJFM6Mn0KUC5paC5wcm90b3R5cGU9ewphTTpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscj10aGlzLiR0aQpyLkMoIjEvIikuYihiKQp0PSF0aGlzLmJ8fHIuQygiYjg8MT4iKS5jKGIp
+CnM9dGhpcy5hCmlmKHQpcy5YZihiKQplbHNlIHMuWDIoci5kLmIoYikpfSwKdzA6ZnVuY3Rpb24oYSxi
+KXt2YXIgdD10aGlzLmEKaWYodGhpcy5iKXQuWkwoYSxiKQplbHNlIHQuTmsoYSxiKX19ClAuV00ucHJv
+dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS4kMigwLGEpfSwKJFM6MTB9ClAuU1gu
+cHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuJDIoMSxuZXcgSC5icShhLHUubC5iKGIp
+KSl9LAokQzoiJDIiLAokUjoyLAokUzo0MH0KUC5Hcy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIp
+e3RoaXMuYShILlNjKGEpLGIpfSwKJFM6NDN9ClAuRnkucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXty
+ZXR1cm4iSXRlcmF0aW9uTWFya2VyKCIrdGhpcy5iKyIsICIrSC5kKHRoaXMuYSkrIikifSwKZ253OmZ1
+bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9fQpQLkdWLnByb3RvdHlwZT17CmdSOmZ1bmN0aW9uKGEpe3Zh
+ciB0PXRoaXMuYwppZih0PT1udWxsKXJldHVybiB0aGlzLmIKcmV0dXJuIHRoaXMuJHRpLmQuYih0LmdS
+KHQpKX0sCm06ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMKZm9yKDshMDspe3Q9cC5jCmlmKHQh
+PW51bGwpaWYodC5tKCkpcmV0dXJuITAKZWxzZSBwLmM9bnVsbApzPWZ1bmN0aW9uKGEsYixjKXt2YXIg
+byxuPWIKd2hpbGUodHJ1ZSl0cnl7cmV0dXJuIGEobixvKX1jYXRjaChtKXtvPW0Kbj1jfX0ocC5hLDAs
+MSkKaWYocyBpbnN0YW5jZW9mIFAuRnkpe3I9cy5iCmlmKHI9PT0yKXt0PXAuZAppZih0PT1udWxsfHx0
+Lmxlbmd0aD09PTApe3Auc0VDKG51bGwpCnJldHVybiExfWlmKDA+PXQubGVuZ3RoKXJldHVybiBILk9I
+KHQsLTEpCnAuYT10LnBvcCgpCmNvbnRpbnVlfWVsc2V7dD1zLmEKaWYocj09PTMpdGhyb3cgdAplbHNl
+e3E9Si5JVCh0KQppZihxIGluc3RhbmNlb2YgUC5HVil7dD1wLmQKaWYodD09bnVsbCl0PXAuZD1bXQpD
+Lk5tLkEodCxwLmEpCnAuYT1xLmEKY29udGludWV9ZWxzZXtwLmM9cQpjb250aW51ZX19fX1lbHNle3Au
+c0VDKHMpCnJldHVybiEwfX1yZXR1cm4hMX0sCnNFQzpmdW5jdGlvbihhKXt0aGlzLmI9dGhpcy4kdGku
+ZC5iKGEpfSwKJGlBbjoxfQpQLnE0LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3
+IFAuR1YodGhpcy5hKCksdGhpcy4kdGkuQygiR1Y8MT4iKSl9fQpQLmI4LnByb3RvdHlwZT17fQpQLlBm
+LnByb3RvdHlwZT17CncwOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09bnVsbClhPW5ldyBQLm4oKQp0
+PXRoaXMuYQppZih0LmEhPT0wKXRocm93IEguYihQLlBWKCJGdXR1cmUgYWxyZWFkeSBjb21wbGV0ZWQi
+KSkKdC5OayhhLGIpfSwKcG06ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMudzAoYSxudWxsKX19ClAuWmYu
+cHJvdG90eXBlPXsKYU06ZnVuY3Rpb24oYSxiKXt2YXIgdAp0aGlzLiR0aS5DKCIxLyIpLmIoYikKdD10
+aGlzLmEKaWYodC5hIT09MCl0aHJvdyBILmIoUC5QVigiRnV0dXJlIGFscmVhZHkgY29tcGxldGVkIikp
+CnQuWGYoYil9fQpQLkZlLnByb3RvdHlwZT17CkhSOmZ1bmN0aW9uKGEpe2lmKCh0aGlzLmMmMTUpIT09
+NilyZXR1cm4hMApyZXR1cm4gdGhpcy5iLmIuYnYodS5hbC5iKHRoaXMuZCksYS5hLHUuY0osdS5LKX0s
+Ckt3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZSxzPXUueixyPXUuSyxxPXRoaXMuJHRpLkMoIjIvIiks
+cD10aGlzLmIuYgppZih1LmFnLmModCkpcmV0dXJuIHEuYihwLnJwKHQsYS5hLGEuYixzLHIsdS5sKSkK
+ZWxzZSByZXR1cm4gcS5iKHAuYnYodS55LmIodCksYS5hLHMscikpfX0KUC52cy5wcm90b3R5cGU9ewpT
+cTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9dGhpcy4kdGkKcS5LKGMpLkMoIjEvKDIpIikuYihh
+KQp0PSQuWDMKaWYodCE9PUMuTlUpe2MuQygiQDwwLz4iKS5LKHEuZCkuQygiMSgyKSIpLmIoYSkKaWYo
+YiE9bnVsbCliPVAuVkgoYix0KX1zPW5ldyBQLnZzKCQuWDMsYy5DKCJ2czwwPiIpKQpyPWI9PW51bGw/
+MTozCnRoaXMueGYobmV3IFAuRmUocyxyLGEsYixxLkMoIkA8MT4iKS5LKGMpLkMoIkZlPDEsMj4iKSkp
+CnJldHVybiBzfSwKVzc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5TcShhLG51bGwsYil9LApRZDpm
+dW5jdGlvbihhLGIsYyl7dmFyIHQscz10aGlzLiR0aQpzLksoYykuQygiMS8oMikiKS5iKGEpCnQ9bmV3
+IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnRoaXMueGYobmV3IFAuRmUodCwoYj09bnVsbD8xOjMpfDE2
+LGEsYixzLkMoIkA8MT4iKS5LKGMpLkMoIkZlPDEsMj4iKSkpCnJldHVybiB0fSwKT0E6ZnVuY3Rpb24o
+YSl7dmFyIHQscyxyCnUuYmYuYihudWxsKQp0PXRoaXMuJHRpCnM9JC5YMwpyPW5ldyBQLnZzKHMsdCkK
+aWYocyE9PUMuTlUpYT1QLlZIKGEscykKdGhpcy54ZihuZXcgUC5GZShyLDIsbnVsbCxhLHQuQygiQDwx
+PiIpLksodC5kKS5DKCJGZTwxLDI+IikpKQpyZXR1cm4gcn0sCnhmOmZ1bmN0aW9uKGEpe3ZhciB0LHM9
+dGhpcyxyPXMuYQppZihyPD0xKXthLmE9dS54LmIocy5jKQpzLmM9YX1lbHNle2lmKHI9PT0yKXt0PXUu
+Xy5iKHMuYykKcj10LmEKaWYocjw0KXt0LnhmKGEpCnJldHVybn1zLmE9cgpzLmM9dC5jfVAuVGsobnVs
+bCxudWxsLHMuYix1Lk0uYihuZXcgUC5kYShzLGEpKSl9fSwKalE6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
+LHEscCxvPXRoaXMsbj17fQpuLmE9YQppZihhPT1udWxsKXJldHVybgp0PW8uYQppZih0PD0xKXtzPXUu
+eC5iKG8uYykKcj1vLmM9YQppZihzIT1udWxsKXtmb3IoO3E9ci5hLHEhPW51bGw7cj1xKTtyLmE9c319
+ZWxzZXtpZih0PT09Mil7cD11Ll8uYihvLmMpCnQ9cC5hCmlmKHQ8NCl7cC5qUShhKQpyZXR1cm59by5h
+PXQKby5jPXAuY31uLmE9by5OOChhKQpQLlRrKG51bGwsbnVsbCxvLmIsdS5NLmIobmV3IFAub1Eobixv
+KSkpfX0sCmFoOmZ1bmN0aW9uKCl7dmFyIHQ9dS54LmIodGhpcy5jKQp0aGlzLmM9bnVsbApyZXR1cm4g
+dGhpcy5OOCh0KX0sCk44OmZ1bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLHM9bnVsbDt0IT1udWxs
+O3M9dCx0PXIpe3I9dC5hCnQuYT1zfXJldHVybiBzfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlz
+LHI9cy4kdGkKci5DKCIxLyIpLmIoYSkKaWYoci5DKCJiODwxPiIpLmMoYSkpaWYoci5jKGEpKVAuQTko
+YSxzKQplbHNlIFAuazMoYSxzKQplbHNle3Q9cy5haCgpCnIuZC5iKGEpCnMuYT00CnMuYz1hClAuSFoo
+cyx0KX19LApYMjpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMKcy4kdGkuZC5iKGEpCnQ9cy5haCgpCnMu
+YT00CnMuYz1hClAuSFoocyx0KX0sClpMOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzCnUubC5iKGIp
+CnQ9cy5haCgpCnMuYT04CnMuYz1uZXcgUC5DdyhhLGIpClAuSFoocyx0KX0sClhmOmZ1bmN0aW9uKGEp
+e3ZhciB0PXRoaXMscz10LiR0aQpzLkMoIjEvIikuYihhKQppZihzLkMoImI4PDE+IikuYyhhKSl7dC5j
+VShhKQpyZXR1cm59dC5hPTEKUC5UayhudWxsLG51bGwsdC5iLHUuTS5iKG5ldyBQLnJIKHQsYSkpKX0s
+CmNVOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz10LiR0aQpzLkMoImI4PDE+IikuYihhKQppZihzLmMo
+YSkpe2lmKGEuYT09PTgpe3QuYT0xClAuVGsobnVsbCxudWxsLHQuYix1Lk0uYihuZXcgUC5LRih0LGEp
+KSl9ZWxzZSBQLkE5KGEsdCkKcmV0dXJufVAuazMoYSx0KX0sCk5rOmZ1bmN0aW9uKGEsYil7dGhpcy5h
+PTEKUC5UayhudWxsLG51bGwsdGhpcy5iLHUuTS5iKG5ldyBQLlpMKHRoaXMsYSxiKSkpfSwKJGliODox
+fQpQLmRhLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlzLmEsdGhpcy5iKX0sCiRTOjB9
+ClAub1EucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtQLkhaKHRoaXMuYix0aGlzLmEuYSl9LAokUzow
+fQpQLnBWLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQp0LmE9MAp0LkhIKGEp
+fSwKJFM6MTh9ClAuVTcucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt1LmwuYihiKQp0aGlzLmEu
+WkwoYSxiKX0sCiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLiQyKGEsbnVsbCl9LAokQzoiJDIiLAok
+RDpmdW5jdGlvbigpe3JldHVybltudWxsXX0sCiRTOjI2fQpQLnZyLnByb3RvdHlwZT17CiQwOmZ1bmN0
+aW9uKCl7dGhpcy5hLlpMKHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KUC5ySC5wcm90b3R5cGU9ewokMDpm
+dW5jdGlvbigpe3ZhciB0PXRoaXMuYQp0LlgyKHQuJHRpLmQuYih0aGlzLmIpKX0sCiRTOjB9ClAuS0Yu
+cHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtQLkE5KHRoaXMuYix0aGlzLmEpfSwKJFM6MH0KUC5aTC5w
+cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAu
+UlQucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzLG09bnVsbAp0
+cnl7cj1uLmMKbT1yLmIuYi56eih1LmZPLmIoci5kKSx1LnopfWNhdGNoKHEpe3Q9SC5SdShxKQpzPUgu
+dHMocSkKaWYobi5kKXtyPXUubi5iKG4uYS5hLmMpLmEKcD10CnA9cj09bnVsbD9wPT1udWxsOnI9PT1w
+CnI9cH1lbHNlIHI9ITEKcD1uLmIKaWYocilwLmI9dS5uLmIobi5hLmEuYykKZWxzZSBwLmI9bmV3IFAu
+Q3codCxzKQpwLmE9ITAKcmV0dXJufWlmKHUuYy5jKG0pKXtpZihtIGluc3RhbmNlb2YgUC52cyYmbS5h
+Pj00KXtpZihtLmE9PT04KXtyPW4uYgpyLmI9dS5uLmIobS5jKQpyLmE9ITB9cmV0dXJufW89bi5hLmEK
+cj1uLmIKci5iPW0uVzcobmV3IFAualoobyksdS56KQpyLmE9ITF9fSwKJFM6Mn0KUC5qWi5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKJFM6MzB9ClAucnEucHJvdG90eXBlPXsK
+JDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMKdHJ5e3I9bS5iCnE9ci4kdGkKcD1x
+LmQKbz1wLmIobS5jKQptLmEuYj1yLmIuYi5idihxLkMoIjIvKDEpIikuYihyLmQpLG8scS5DKCIyLyIp
+LHApfWNhdGNoKG4pe3Q9SC5SdShuKQpzPUgudHMobikKcj1tLmEKci5iPW5ldyBQLkN3KHQscykKci5h
+PSEwfX0sCiRTOjJ9ClAuUlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8s
+bixtLGw9dGhpcwp0cnl7dD11Lm4uYihsLmEuYS5jKQpxPWwuYwppZihILm9UKHEuSFIodCkpJiZxLmUh
+PW51bGwpe3A9bC5iCnAuYj1xLkt3KHQpCnAuYT0hMX19Y2F0Y2gobyl7cz1ILlJ1KG8pCnI9SC50cyhv
+KQpxPXUubi5iKGwuYS5hLmMpCnA9cS5hCm49cwptPWwuYgppZihwPT1udWxsP249PW51bGw6cD09PW4p
+bS5iPXEKZWxzZSBtLmI9bmV3IFAuQ3cocyxyKQptLmE9ITB9fSwKJFM6Mn0KUC5PTS5wcm90b3R5cGU9
+e30KUC5xaC5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcyxxPXt9LHA9bmV3
+IFAudnMoJC5YMyx1LmZKKQpxLmE9MAp0PUguTGgocikKcz10LkMoIn4oMSkiKS5iKG5ldyBQLkI1KHEs
+cikpCnUuTS5iKG5ldyBQLlBJKHEscCkpClcuSkUoci5hLHIuYixzLCExLHQuZCkKcmV0dXJuIHB9fQpQ
+LkI1LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guTGgodGhpcy5iKS5kLmIoYSk7Kyt0aGlzLmEu
+YX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEguTGgodGhpcy5iKS5DKCJjOCgxKSIpfX0KUC5QSS5wcm90
+b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYi5ISCh0aGlzLmEuYSl9LAokUzowfQpQLk1PLnByb3Rv
+dHlwZT17fQpQLmtULnByb3RvdHlwZT17fQpQLnhJLnByb3RvdHlwZT17fQpQLkN3LnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIEguZCh0aGlzLmEpfSwKJGlYUzoxfQpQLm0wLnByb3RvdHlwZT17
+JGlKQjoxfQpQLnBLLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLmEscj1zLmEK
+cz1yPT1udWxsP3MuYT1uZXcgUC5uKCk6cgpyPXRoaXMuYgppZihyPT1udWxsKXRocm93IEguYihzKQp0
+PUguYihzKQp0LnN0YWNrPXIudygwKQp0aHJvdyB0fSwKJFM6MH0KUC5KaS5wcm90b3R5cGU9ewpiSDpm
+dW5jdGlvbihhKXt2YXIgdCxzLHIscT1udWxsCnUuTS5iKGEpCnRyeXtpZihDLk5VPT09JC5YMyl7YS4k
+MCgpCnJldHVybn1QLlQ4KHEscSx0aGlzLGEsdS5IKX1jYXRjaChyKXt0PUguUnUocikKcz1ILnRzKHIp
+ClAuTDIocSxxLHRoaXMsdCx1LmwuYihzKSl9fSwKRGw6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixx
+PW51bGwKYy5DKCJ+KDApIikuYihhKQpjLmIoYikKdHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQxKGIpCnJl
+dHVybn1QLnl2KHEscSx0aGlzLGEsYix1LkgsYyl9Y2F0Y2gocil7dD1ILlJ1KHIpCnM9SC50cyhyKQpQ
+LkwyKHEscSx0aGlzLHQsdS5sLmIocykpfX0sClJUOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLmhq
+KHRoaXMsYi5DKCIwKCkiKS5iKGEpLGIpfSwKR1k6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLlZwKHRo
+aXMsdS5NLmIoYSkpfSwKUHk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuT1IodGhpcyxiLkMoIn4o
+MCkiKS5iKGEpLGIpfSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiBudWxsfSwKeno6ZnVuY3Rpb24oYSxi
+KXtiLkMoIjAoKSIpLmIoYSkKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDAoKQpyZXR1cm4gUC5UOChu
+dWxsLG51bGwsdGhpcyxhLGIpfSwKYnY6ZnVuY3Rpb24oYSxiLGMsZCl7Yy5DKCJAPDA+IikuSyhkKS5D
+KCIxKDIpIikuYihhKQpkLmIoYikKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDEoYikKcmV0dXJuIFAu
+eXYobnVsbCxudWxsLHRoaXMsYSxiLGMsZCl9LApycDpmdW5jdGlvbihhLGIsYyxkLGUsZil7ZC5DKCJA
+PDA+IikuSyhlKS5LKGYpLkMoIjEoMiwzKSIpLmIoYSkKZS5iKGIpCmYuYihjKQppZigkLlgzPT09Qy5O
+VSlyZXR1cm4gYS4kMihiLGMpCnJldHVybiBQLlF4KG51bGwsbnVsbCx0aGlzLGEsYixjLGQsZSxmKX0s
+CkxqOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBiLkMoIkA8MD4iKS5LKGMpLksoZCkuQygiMSgyLDMp
+IikuYihhKX19ClAuaGoucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLnp6KHRo
+aXMuYix0aGlzLmMpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jLkMoIjAoKSIpfX0KUC5WcC5w
+cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuYkgodGhpcy5iKX0sCiRTOjJ9ClAu
+T1IucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCnJldHVybiB0aGlzLmEuRGwo
+dGhpcy5iLHQuYihhKSx0KX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYy5DKCJ+KDApIil9fQpQ
+LmI2LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9bmV3IFAubG0odCx0LnIs
+SC5MaCh0KS5DKCJsbTwxPiIpKQpzLmM9dC5lCnJldHVybiBzfSwKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJu
+IHRoaXMuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZih0eXBlb2YgYj09InN0cmluZyImJmIh
+PT0iX19wcm90b19fIil7dD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdS5KLmIodFti
+XSkhPW51bGx9ZWxzZXtzPXRoaXMuUFIoYikKcmV0dXJuIHN9fSwKUFI6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMuREYodFt0aGlzLnJrKGEpXSxhKT49
+MH0sCkE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwpILkxoKHIpLmQuYihiKQppZih0eXBlb2Yg
+Yj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7dD1yLmIKcmV0dXJuIHIuY1codD09bnVsbD9yLmI9
+UC5UMigpOnQsYil9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjEwNzM3NDE4MjMpPT09Yil7
+cz1yLmMKcmV0dXJuIHIuY1cocz09bnVsbD9yLmM9UC5UMigpOnMsYil9ZWxzZSByZXR1cm4gci5CNygw
+LGIpfSwKQjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT10aGlzCkguTGgocSkuZC5iKGIpCnQ9cS5k
+CmlmKHQ9PW51bGwpdD1xLmQ9UC5UMigpCnM9cS5yayhiKQpyPXRbc10KaWYocj09bnVsbCl0W3NdPVtx
+LmRnKGIpXQplbHNle2lmKHEuREYocixiKT49MClyZXR1cm4hMQpyLnB1c2gocS5kZyhiKSl9cmV0dXJu
+ITB9LApSejpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09
+Il9fcHJvdG9fXyIpcmV0dXJuIHQuSDQodC5iLGIpCmVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYo
+YiYxMDczNzQxODIzKT09PWIpcmV0dXJuIHQuSDQodC5jLGIpCmVsc2UgcmV0dXJuIHQucWcoMCxiKX0s
+CnFnOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzLG89cC5kCmlmKG89PW51bGwpcmV0dXJu
+ITEKdD1wLnJrKGIpCnM9b1t0XQpyPXAuREYocyxiKQppZihyPDApcmV0dXJuITEKcT1zLnNwbGljZShy
+LDEpWzBdCmlmKDA9PT1zLmxlbmd0aClkZWxldGUgb1t0XQpwLkdTKHEpCnJldHVybiEwfSwKY1c6ZnVu
+Y3Rpb24oYSxiKXtILkxoKHRoaXMpLmQuYihiKQppZih1LkouYihhW2JdKSE9bnVsbClyZXR1cm4hMQph
+W2JdPXRoaXMuZGcoYikKcmV0dXJuITB9LApINDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwp
+cmV0dXJuITEKdD11LkouYihhW2JdKQppZih0PT1udWxsKXJldHVybiExCnRoaXMuR1ModCkKZGVsZXRl
+IGFbYl0KcmV0dXJuITB9LApYQTpmdW5jdGlvbigpe3RoaXMucj0xMDczNzQxODIzJnRoaXMucisxfSwK
+ZGc6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9bmV3IFAuYm4oSC5MaChzKS5kLmIoYSkpCmlmKHMu
+ZT09bnVsbClzLmU9cy5mPXIKZWxzZXt0PXMuZgpyLmM9dApzLmY9dC5iPXJ9KytzLmEKcy5YQSgpCnJl
+dHVybiByfSwKR1M6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWEuYyxyPWEuYgppZihzPT1udWxsKXQu
+ZT1yCmVsc2Ugcy5iPXIKaWYocj09bnVsbCl0LmY9cwplbHNlIHIuYz1zOy0tdC5hCnQuWEEoKX0sCnJr
+OmZ1bmN0aW9uKGEpe3JldHVybiBKLmhmKGEpJjEwNzM3NDE4MjN9LApERjpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMKaWYoYT09bnVsbClyZXR1cm4tMQp0PWEubGVuZ3RoCmZvcihzPTA7czx0OysrcylpZihKLlJN
+KGFbc10uYSxiKSlyZXR1cm4gcwpyZXR1cm4tMX19ClAuYm4ucHJvdG90eXBlPXt9ClAubG0ucHJvdG90
+eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0sCm06ZnVuY3Rpb24oKXt2YXIgdD10aGlz
+LHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChzKSkKZWxzZXtzPXQuYwppZihzPT1udWxs
+KXt0LnNCYihudWxsKQpyZXR1cm4hMX1lbHNle3Quc0JiKHQuJHRpLmQuYihzLmEpKQp0LmM9dC5jLmIK
+cmV0dXJuITB9fX0sCnNCYjpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlBbjox
+fQpQLm1XLnByb3RvdHlwZT17fQpQLkxVLnByb3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXpNOjF9ClAu
+bEQucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5hNyhhLHRoaXMuZ2goYSks
+SC56SyhhKS5DKCJhNzxsRC5FPiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9
+LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnpLKGEpLkMoIn4obEQuRSkiKS5iKGIpCnQ9dGhpcy5n
+aChhKQpmb3Iocz0wO3M8dDsrK3Mpe2IuJDEodGhpcy5xKGEscykpCmlmKHQhPT10aGlzLmdoKGEpKXRo
+cm93IEguYihQLmE0KGEpKX19LApFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC56SyhhKQpyZXR1cm4g
+bmV3IEguQTgoYSx0LksoYykuQygiMShsRC5FKSIpLmIoYiksdC5DKCJAPGxELkU+IikuSyhjKS5DKCJB
+ODwxLDI+IikpfSwKZHU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKSC56SyhhKS5DKCJsRC5FIikuYihk
+KQpQLmpCKGIsYyx0aGlzLmdoKGEpKQpmb3IodD1iO3Q8YzsrK3QpdGhpcy5ZKGEsdCxkKX0sCnc6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0iKX19ClAuaWwucHJvdG90eXBlPXt9ClAucmEucHJv
+dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZighcy5hKXRoaXMuYi5hKz0i
+LCAiCnMuYT0hMQpzPXRoaXMuYgp0PXMuYSs9SC5kKGEpCnMuYT10KyI6ICIKcy5hKz1ILmQoYil9LAok
+UzoxfQpQLllrLnByb3RvdHlwZT17ClU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCkgueksoYSkuQygifihZ
+ay5LLFlrLlYpIikuYihiKQpmb3IodD1KLklUKHRoaXMuZ3YoYSkpO3QubSgpOyl7cz10LmdSKHQpCmIu
+JDIocyx0aGlzLnEoYSxzKSl9fSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVybiBKLk0xKHRoaXMuZ3YoYSks
+bmV3IFAueVEoYSksSC56SyhhKS5DKCJOMzxZay5LLFlrLlY+IikpfSwKZ2g6ZnVuY3Rpb24oYSl7cmV0
+dXJuIEouSG0odGhpcy5ndihhKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKGEpfSwKJGlaMDox
+fQpQLnlRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYSxzPUgueksodCkKcy5D
+KCJZay5LIikuYihhKQpyZXR1cm4gbmV3IFAuTjMoYSxKLncyKHQsYSkscy5DKCJAPFlrLks+IikuSyhz
+LkMoIllrLlYiKSkuQygiTjM8MSwyPiIpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEgueksodGhpcy5h
+KS5DKCJOMzxZay5LLFlrLlY+KFlrLkspIil9fQpQLktQLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0PUguTGgodGhpcykKdC5kLmIoYikKdC5jaFsxXS5iKGMpCnRocm93IEguYihQLkw0KCJD
+YW5ub3QgbW9kaWZ5IHVubW9kaWZpYWJsZSBtYXAiKSl9fQpQLlBuLnByb3RvdHlwZT17CnE6ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gSi53Mih0aGlzLmEsYil9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxo
+KHRoaXMpCkouQjIodGhpcy5hLHQuZC5iKGIpLHQuY2hbMV0uYihjKSl9LApVOmZ1bmN0aW9uKGEsYil7
+Si5oRSh0aGlzLmEsSC5MaCh0aGlzKS5DKCJ+KDEsMikiKS5iKGIpKX0sCmdoOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBKLkhtKHRoaXMuYSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBKLmoodGhpcy5hKX0sCmdQdTpm
+dW5jdGlvbihhKXtyZXR1cm4gSi5RTSh0aGlzLmEpfSwKJGlaMDoxfQpQLkdqLnByb3RvdHlwZT17fQpQ
+LmxmLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UodGhpcywieyIsIn0iKX19ClAu
+UksucHJvdG90eXBlPXskaWJROjEsJGljWDoxLCRpeHU6MX0KUC5Ydi5wcm90b3R5cGU9ewpGVjpmdW5j
+dGlvbihhLGIpe3ZhciB0CmZvcih0PUouSVQoSC5MaCh0aGlzKS5DKCJjWDwxPiIpLmIoYikpO3QubSgp
+Oyl0aGlzLkEoMCx0LmdSKHQpKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UodGhpcywieyIsIn0i
+KX0sCnpWOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1QLnJqKHRoaXMsdGhpcy5yLEguTGgodGhpcykuZCkK
+aWYoIXMubSgpKXJldHVybiIiCmlmKGI9PT0iIil7dD0iIgpkbyB0Kz1ILmQocy5kKQp3aGlsZShzLm0o
+KSl9ZWxzZXt0PUguZChzLmQpCmZvcig7cy5tKCk7KXQ9dCtiK0guZChzLmQpfXJldHVybiB0LmNoYXJD
+b2RlQXQoMCk9PTA/dDp0fSwKJGliUToxLAokaWNYOjEsCiRpeHU6MX0KUC5uWS5wcm90b3R5cGU9e30K
+UC5XWS5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90b3R5cGU9ewpxOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4gdGhpcy5jLnEoMCxiKQplbHNl
+IGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4gbnVsbAplbHNle3Q9c1tiXQpyZXR1cm4gdHlwZW9m
+IHQ9PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6dH19LApnaDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5i
+PT1udWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5ndGh9LApndjpmdW5jdGlvbihhKXt2YXIgdAppZih0
+aGlzLmI9PW51bGwpe3Q9dGhpcy5jCnJldHVybiBuZXcgSC5pNSh0LEguTGgodCkuQygiaTU8MT4iKSl9
+cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPXRoaXMKaWYo
+ci5iPT1udWxsKXIuYy5ZKDAsYixjKQplbHNlIGlmKHIueDQoMCxiKSl7dD1yLmIKdFtiXT1jCnM9ci5h
+CmlmKHM9PW51bGw/dCE9bnVsbDpzIT09dClzW2JdPW51bGx9ZWxzZSByLlhLKCkuWSgwLGIsYyl9LAp4
+NDpmdW5jdGlvbihhLGIpe2lmKHRoaXMuYj09bnVsbClyZXR1cm4gdGhpcy5jLng0KDAsYikKcmV0dXJu
+IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYil9LApVOmZ1bmN0aW9u
+KGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuVC5iKGIpCmlmKHAuYj09bnVsbClyZXR1cm4gcC5jLlUo
+MCxiKQp0PXAuQ2YoKQpmb3Iocz0wO3M8dC5sZW5ndGg7KytzKXtyPXRbc10KcT1wLmJbcl0KaWYodHlw
+ZW9mIHE9PSJ1bmRlZmluZWQiKXtxPVAuUWUocC5hW3JdKQpwLmJbcl09cX1iLiQyKHIscSkKaWYodCE9
+PXAuYyl0aHJvdyBILmIoUC5hNChwKSl9fSwKQ2Y6ZnVuY3Rpb24oKXt2YXIgdD11LmouYih0aGlzLmMp
+CmlmKHQ9PW51bGwpdD10aGlzLmM9SC5WTShPYmplY3Qua2V5cyh0aGlzLmEpLHUucykKcmV0dXJuIHR9
+LApYSzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbz10aGlzCmlmKG8uYj09bnVsbClyZXR1cm4gby5j
+CnQ9UC5GbCh1Lk4sdS56KQpzPW8uQ2YoKQpmb3Iocj0wO3E9cy5sZW5ndGgscjxxOysrcil7cD1zW3Jd
+CnQuWSgwLHAsby5xKDAscCkpfWlmKHE9PT0wKUMuTm0uQShzLG51bGwpCmVsc2UgQy5ObS5zaChzLDAp
+Cm8uYT1vLmI9bnVsbApyZXR1cm4gby5jPXR9LApmYjpmdW5jdGlvbihhKXt2YXIgdAppZighT2JqZWN0
+LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuYSxhKSlyZXR1cm4gbnVsbAp0PVAuUWUo
+dGhpcy5hW2FdKQpyZXR1cm4gdGhpcy5iW2FdPXR9fQpQLmk4LnByb3RvdHlwZT17CmdoOmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdC5naCh0KX0sClc6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlz
+LmEKaWYodC5iPT1udWxsKXQ9dC5ndih0KS5XKDAsYikKZWxzZXt0PXQuQ2YoKQppZihiPDB8fGI+PXQu
+bGVuZ3RoKXJldHVybiBILk9IKHQsYikKdD10W2JdfXJldHVybiB0fSwKZ2t6OmZ1bmN0aW9uKGEpe3Zh
+ciB0PXRoaXMuYQppZih0LmI9PW51bGwpe3Q9dC5ndih0KQp0PXQuZ2t6KHQpfWVsc2V7dD10LkNmKCkK
+dD1uZXcgSi5tMSh0LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9cmV0dXJuIHR9fQpQLkNWLnBy
+b3RvdHlwZT17CnlyOmZ1bmN0aW9uKGEsYTAsYTEsYTIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGos
+aSxoLGcsZixlLGQsYyxiPSJJbnZhbGlkIGJhc2U2NCBlbmNvZGluZyBsZW5ndGggIgphMj1QLmpCKGEx
+LGEyLGEwLmxlbmd0aCkKdD0kLlY3KCkKZm9yKHM9YTEscj1zLHE9bnVsbCxwPS0xLG89LTEsbj0wO3M8
+YTI7cz1tKXttPXMrMQpsPUMueEIuV2QoYTAscykKaWYobD09PTM3KXtrPW0rMgppZihrPD1hMil7aj1I
+Lm9vKEMueEIuV2QoYTAsbSkpCmk9SC5vbyhDLnhCLldkKGEwLG0rMSkpCmg9aioxNitpLShpJjI1NikK
+aWYoaD09PTM3KWg9LTEKbT1rfWVsc2UgaD0tMX1lbHNlIGg9bAppZigwPD1oJiZoPD0xMjcpe2lmKGg8
+MHx8aD49dC5sZW5ndGgpcmV0dXJuIEguT0godCxoKQpnPXRbaF0KaWYoZz49MCl7aD1DLnhCLk8yKCJB
+QkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4
+OSsvIixnKQppZihoPT09bCljb250aW51ZQpsPWh9ZWxzZXtpZihnPT09LTEpe2lmKHA8MCl7Zj1xPT1u
+dWxsP251bGw6cS5hLmxlbmd0aAppZihmPT1udWxsKWY9MApwPWYrKHMtcikKbz1zfSsrbgppZihsPT09
+NjEpY29udGludWV9bD1ofWlmKGchPT0tMil7aWYocT09bnVsbClxPW5ldyBQLlJuKCIiKQpxLmErPUMu
+eEIuTmooYTAscixzKQpxLmErPUguTHcobCkKcj1tCmNvbnRpbnVlfX10aHJvdyBILmIoUC5ycigiSW52
+YWxpZCBiYXNlNjQgZGF0YSIsYTAscykpfWlmKHEhPW51bGwpe2Y9cS5hKz1DLnhCLk5qKGEwLHIsYTIp
+CmU9Zi5sZW5ndGgKaWYocD49MClQLnhNKGEwLG8sYTIscCxuLGUpCmVsc2V7ZD1DLmpuLnpZKGUtMSw0
+KSsxCmlmKGQ9PT0xKXRocm93IEguYihQLnJyKGIsYTAsYTIpKQpmb3IoO2Q8NDspe2YrPSI9IgpxLmE9
+ZjsrK2R9fWY9cS5hCnJldHVybiBDLnhCLmk3KGEwLGExLGEyLGYuY2hhckNvZGVBdCgwKT09MD9mOmYp
+fWM9YTItYTEKaWYocD49MClQLnhNKGEwLG8sYTIscCxuLGMpCmVsc2V7ZD1DLmpuLnpZKGMsNCkKaWYo
+ZD09PTEpdGhyb3cgSC5iKFAucnIoYixhMCxhMikpCmlmKGQ+MSlhMD1DLnhCLmk3KGEwLGEyLGEyLGQ9
+PT0yPyI9PSI6Ij0iKX1yZXR1cm4gYTB9fQpQLnZBLnByb3RvdHlwZT17fQpQLlVrLnByb3RvdHlwZT17
+fQpQLndJLnByb3RvdHlwZT17fQpQLlppLnByb3RvdHlwZT17fQpQLmJ5LnByb3RvdHlwZT17CnBXOmZ1
+bmN0aW9uKGEsYixjKXt2YXIgdAp1LmVwLmIoYykKdD1QLkJTKGIsdGhpcy5nSGUoKS5hKQpyZXR1cm4g
+dH0sCmdIZTpmdW5jdGlvbigpe3JldHVybiBDLkEzfX0KUC5NeC5wcm90b3R5cGU9e30KUC51NS5wcm90
+b3R5cGU9ewpnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMucHJvdG90eXBlPXsKV0o6ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyPVAuakIoMCxudWxsLGEubGVuZ3RoKSxxPXItMAppZihxPT09MClyZXR1
+cm4gbmV3IFVpbnQ4QXJyYXkoMCkKdD1uZXcgVWludDhBcnJheShxKjMpCnM9bmV3IFAuUncodCkKaWYo
+cy5HeChhLDAscikhPT1yKXMuTzYoSi5hNihhLHItMSksMCkKcmV0dXJuIG5ldyBVaW50OEFycmF5KHQu
+c3ViYXJyYXkoMCxILnJNKDAscy5iLHQubGVuZ3RoKSkpfX0KUC5Sdy5wcm90b3R5cGU9ewpPNjpmdW5j
+dGlvbihhLGIpe3ZhciB0LHM9dGhpcyxyPXMuYyxxPXMuYixwPXErMSxvPXIubGVuZ3RoCmlmKChiJjY0
+NTEyKT09PTU2MzIwKXt0PTY1NTM2KygoYSYxMDIzKTw8MTApfGImMTAyMwpzLmI9cAppZihxPj1vKXJl
+dHVybiBILk9IKHIscSkKcltxXT0yNDB8dD4+PjE4CnE9cy5iPXArMQppZihwPj1vKXJldHVybiBILk9I
+KHIscCkKcltwXT0xMjh8dD4+PjEyJjYzCnA9cy5iPXErMQppZihxPj1vKXJldHVybiBILk9IKHIscSkK
+cltxXT0xMjh8dD4+PjYmNjMKcy5iPXArMQppZihwPj1vKXJldHVybiBILk9IKHIscCkKcltwXT0xMjh8
+dCY2MwpyZXR1cm4hMH1lbHNle3MuYj1wCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTIyNHxh
+Pj4+MTIKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguT0gocixwKQpyW3BdPTEyOHxhPj4+NiY2Mwpz
+LmI9cSsxCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTEyOHxhJjYzCnJldHVybiExfX0sCkd4
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMKaWYoYiE9PWMmJihDLnhCLk8y
+KGEsYy0xKSY2NDUxMik9PT01NTI5NiktLWMKZm9yKHQ9bS5jLHM9dC5sZW5ndGgscj1iO3I8YzsrK3Ip
+e3E9Qy54Qi5XZChhLHIpCmlmKHE8PTEyNyl7cD1tLmIKaWYocD49cylicmVhawptLmI9cCsxCnRbcF09
+cX1lbHNlIGlmKChxJjY0NTEyKT09PTU1Mjk2KXtpZihtLmIrMz49cylicmVhawpvPXIrMQppZihtLk82
+KHEsQy54Qi5XZChhLG8pKSlyPW99ZWxzZSBpZihxPD0yMDQ3KXtwPW0uYgpuPXArMQppZihuPj1zKWJy
+ZWFrCm0uYj1uCmlmKHA+PXMpcmV0dXJuIEguT0godCxwKQp0W3BdPTE5MnxxPj4+NgptLmI9bisxCnRb
bl09MTI4fHEmNjN9ZWxzZXtwPW0uYgppZihwKzI+PXMpYnJlYWsKbj1tLmI9cCsxCmlmKHA+PXMpcmV0
-dXJuIEguayh0LHApCnRbcF09MjI0fHE+Pj4xMgpwPW0uYj1uKzEKaWYobj49cylyZXR1cm4gSC5rKHQs
-bikKdFtuXT0xMjh8cT4+PjYmNjMKbS5iPXArMQppZihwPj1zKXJldHVybiBILmsodCxwKQp0W3BdPTEy
-OHxxJjYzfX1yZXR1cm4gcn19ClAuR1kucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
-LHEscCxvLG4sbSxsCnUuTC5hKGEpCnQ9UC5reSghMSxhLDAsbnVsbCkKaWYodCE9bnVsbClyZXR1cm4g
-dApzPVAuakIoMCxudWxsLEouSChhKSkKcj1QLmNQKGEsMCxzKQppZihyPjApe3E9UC5ITShhLDAscikK
-aWYocj09PXMpcmV0dXJuIHEKcD1uZXcgUC5SbihxKQpvPXIKbj0hMX1lbHNle289MApwPW51bGwKbj0h
-MH1pZihwPT1udWxsKXA9bmV3IFAuUm4oIiIpCm09bmV3IFAuYnooITEscCkKbS5jPW4KbS5NRShhLG8s
-cykKaWYobS5lPjApe0guVmooUC5ycigiVW5maW5pc2hlZCBVVEYtOCBvY3RldCBzZXF1ZW5jZSIsYSxz
-KSkKcC5hKz1ILkx3KDY1NTMzKQptLmY9bS5lPW0uZD0wfWw9cC5hCnJldHVybiBsLmNoYXJDb2RlQXQo
-MCk9PTA/bDpsfX0KUC5iei5wcm90b3R5cGU9ewpNRTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEs
-cCxvLG4sbSxsLGssaixpLGg9dGhpcyxnPSJCYWQgVVRGLTggZW5jb2RpbmcgMHgiCnUuTC5hKGEpCnQ9
-aC5kCnM9aC5lCnI9aC5mCmguZj1oLmU9aC5kPTAKJGxhYmVsMCQwOmZvcihxPUouVTYoYSkscD1oLmIs
-bz1iOyEwO289ail7JGxhYmVsMSQxOmlmKHM+MCl7ZG97aWYobz09PWMpYnJlYWsgJGxhYmVsMCQwCm49
-cS5xKGEsbykKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi56TSgpCmlmKChuJjE5MikhPT0x
-Mjgpe209UC5ycihnK0Muam4uRDgobiwxNiksYSxvKQp0aHJvdyBILmIobSl9ZWxzZXt0PSh0PDw2fG4m
-NjMpPj4+MDstLXM7KytvfX13aGlsZShzPjApCm09ci0xCmlmKG08MHx8bT49NClyZXR1cm4gSC5rKEMu
-R2IsbSkKaWYodDw9Qy5HYlttXSl7bT1QLnJyKCJPdmVybG9uZyBlbmNvZGluZyBvZiAweCIrQy5qbi5E
-OCh0LDE2KSxhLG8tci0xKQp0aHJvdyBILmIobSl9aWYodD4xMTE0MTExKXttPVAucnIoIkNoYXJhY3Rl
-ciBvdXRzaWRlIHZhbGlkIFVuaWNvZGUgcmFuZ2U6IDB4IitDLmpuLkQ4KHQsMTYpLGEsby1yLTEpCnRo
-cm93IEguYihtKX1pZighaC5jfHx0IT09NjUyNzkpcC5hKz1ILkx3KHQpCmguYz0hMX1mb3IobT1vPGM7
-bTspe2w9UC5jUChhLG8sYykKaWYobD4wKXtoLmM9ITEKaz1vK2wKcC5hKz1QLkhNKGEsbyxrKQppZihr
-PT09YylicmVha31lbHNlIGs9bwpqPWsrMQpuPXEucShhLGspCmlmKHR5cGVvZiBuIT09Im51bWJlciIp
-cmV0dXJuIG4uSigpCmlmKG48MCl7aT1QLnJyKCJOZWdhdGl2ZSBVVEYtOCBjb2RlIHVuaXQ6IC0weCIr
-Qy5qbi5EOCgtbiwxNiksYSxqLTEpCnRocm93IEguYihpKX1lbHNle2lmKChuJjIyNCk9PT0xOTIpe3Q9
-biYzMQpzPTEKcj0xCmNvbnRpbnVlICRsYWJlbDAkMH1pZigobiYyNDApPT09MjI0KXt0PW4mMTUKcz0y
-CnI9Mgpjb250aW51ZSAkbGFiZWwwJDB9aWYoKG4mMjQ4KT09PTI0MCYmbjwyNDUpe3Q9biY3CnM9Mwpy
-PTMKY29udGludWUgJGxhYmVsMCQwfWk9UC5ycihnK0Muam4uRDgobiwxNiksYSxqLTEpCnRocm93IEgu
-YihpKX19YnJlYWsgJGxhYmVsMCQwfWlmKHM+MCl7aC5kPXQKaC5lPXMKaC5mPXJ9fX0KUC5XRi5wcm90
-b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgp1LmZvLmEoYSkKdD10aGlzLmIKcz10aGlz
-LmEKdC5hKz1zLmEKcj10LmErPUguZChhLmEpCnQuYT1yKyI6ICIKdC5hKz1QLmgoYikKcy5hPSIsICJ9
-LAokUzo0N30KUC5hMi5wcm90b3R5cGU9e30KUC5pUC5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIp
-e2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLmlQJiZ0aGlzLmE9PT1iLmEm
-JnRoaXMuYj09PWIuYn0sClhrOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmEKaWYoTWF0aC5hYnMo
-cyk8PTg2NGUxMyl0PSExCmVsc2UgdD0hMAppZih0KXRocm93IEguYihQLnhZKCJEYXRlVGltZSBpcyBv
-dXRzaWRlIHZhbGlkIHJhbmdlOiAiK3MpKQpQLlVJKHRoaXMuYiwiaXNVdGMiLHUueSl9LApnaTpmdW5j
-dGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuKHReQy5qbi53Ryh0LDMwKSkmMTA3Mzc0MTgyM30sClo6
-ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPVAuR3EoSC50Sih0KSkscj1QLmgwKEguTlModCkpLHE9UC5o
-MChILmpBKHQpKSxwPVAuaDAoSC5LTCh0KSksbz1QLmgwKEguY2godCkpLG49UC5oMChILkpkKHQpKSxt
-PVAuVngoSC5WYSh0KSkKaWYodC5iKXJldHVybiBzKyItIityKyItIitxKyIgIitwKyI6IitvKyI6Iitu
-KyIuIittKyJaIgplbHNlIHJldHVybiBzKyItIityKyItIitxKyIgIitwKyI6IitvKyI6IituKyIuIitt
-fX0KUC5DUC5wcm90b3R5cGU9e30KUC5YUy5wcm90b3R5cGU9ewpnSUk6ZnVuY3Rpb24oKXtyZXR1cm4g
-SC50cyh0aGlzLiR0aHJvd25Kc0Vycm9yKX19ClAuQzYucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2
-YXIgdD10aGlzLmEKaWYodCE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLmgodCkKcmV0
-dXJuIkFzc2VydGlvbiBmYWlsZWQifX0KUC5MSy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVy
-biJUaHJvdyBvZiBudWxsLiJ9fQpQLkFULnByb3RvdHlwZT17CmdaMjpmdW5jdGlvbigpe3JldHVybiJJ
-bnZhbGlkIGFyZ3VtZW50IisoIXRoaXMuYT8iKHMpIjoiIil9LApnTjpmdW5jdGlvbigpe3JldHVybiIi
-fSwKWjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysi
-KSI6IiIKbz1wLmQKdD1vPT1udWxsPyIiOiI6ICIrSC5kKG8pCnM9cC5nWjIoKStuK3QKaWYoIXAuYSly
-ZXR1cm4gcwpyPXAuZ04oKQpxPVAuaChwLmIpCnJldHVybiBzK3IrIjogIitxfX0KUC5iSi5wcm90b3R5
-cGU9ewpnWjI6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApnTjpmdW5jdGlvbigpe3ZhciB0
-LHMscj10aGlzLmUKaWYocj09bnVsbCl7cj10aGlzLmYKdD1yIT1udWxsPyI6IE5vdCBsZXNzIHRoYW4g
-b3IgZXF1YWwgdG8gIitILmQocik6IiJ9ZWxzZXtzPXRoaXMuZgppZihzPT1udWxsKXQ9IjogTm90IGdy
-ZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAiK0guZChyKQplbHNlIGlmKHM+cil0PSI6IE5vdCBpbiByYW5n
-ZSAiK0guZChyKSsiLi4iK0guZChzKSsiLCBpbmNsdXNpdmUiCmVsc2UgdD1zPHI/IjogVmFsaWQgdmFs
-dWUgcmFuZ2UgaXMgZW1wdHkiOiI6IE9ubHkgdmFsaWQgdmFsdWUgaXMgIitILmQocil9cmV0dXJuIHR9
-fQpQLmVZLnByb3RvdHlwZT17CmdaMjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmdOOmZ1
-bmN0aW9uKCl7dmFyIHQscz1ILldZKHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4g
-cy5KKCkKaWYoczwwKXJldHVybiI6IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgpp
-Zih0PT09MClyZXR1cm4iOiBubyBpbmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxk
-IGJlIGxlc3MgdGhhbiAiK0guZCh0KX0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1w
-LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxq
-PW5ldyBQLlJuKCIiKQprLmE9IiIKZm9yKHQ9bC5jLHM9dC5sZW5ndGgscj0wLHE9IiIscD0iIjtyPHM7
-KytyLHA9IiwgIil7bz10W3JdCmouYT1xK3AKcT1qLmErPVAuaChvKQprLmE9IiwgIn1sLmQuVSgwLG5l
-dyBQLldGKGssaikpCm49UC5oKGwuYSkKbT1qLlooMCkKdD0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhv
-ZCBub3QgZm91bmQ6ICciK0guZChsLmIuYSkrIidcblJlY2VpdmVyOiAiK24rIlxuQXJndW1lbnRzOiBb
-IittKyJdIgpyZXR1cm4gdH19ClAudWIucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iVW5z
-dXBwb3J0ZWQgb3BlcmF0aW9uOiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKWjpmdW5jdGlvbihh
-KXt2YXIgdD10aGlzLmEKcmV0dXJuIHQhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIit0OiJVbmlt
-cGxlbWVudGVkRXJyb3IifX0KUC5sai5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJCYWQg
-c3RhdGU6ICIrdGhpcy5hfX0KUC5VVi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMu
-YQppZih0PT1udWxsKXJldHVybiJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9u
-LiIKcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIrUC5oKHQp
-KyIuIn19ClAuazUucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9
-LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sCiRpWFM6MX0KUC5LWS5wcm90b3R5cGU9ewpaOmZ1
-bmN0aW9uKGEpe3JldHVybiJTdGFjayBPdmVyZmxvdyJ9LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVs
-bH0sCiRpWFM6MX0KUC50Ny5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1
-cm4gdD09bnVsbD8iUmVhZGluZyBzdGF0aWMgdmFyaWFibGUgZHVyaW5nIGl0cyBpbml0aWFsaXphdGlv
-biI6IlJlYWRpbmcgc3RhdGljIHZhcmlhYmxlICciK3QrIicgZHVyaW5nIGl0cyBpbml0aWFsaXphdGlv
-biJ9fQpQLkNELnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkV4Y2VwdGlvbjogIit0aGlz
-LmF9fQpQLmFFLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
-aixpLGg9dGhpcy5hLGc9aCE9bnVsbCYmIiIhPT1oPyJGb3JtYXRFeGNlcHRpb246ICIrSC5kKGgpOiJG
-b3JtYXRFeGNlcHRpb24iLGY9dGhpcy5jLGU9dGhpcy5iCmlmKHR5cGVvZiBlPT0ic3RyaW5nIil7aWYo
-ZiE9bnVsbCloPWY8MHx8Zj5lLmxlbmd0aAplbHNlIGg9ITEKaWYoaClmPW51bGwKaWYoZj09bnVsbCl7
-dD1lLmxlbmd0aD43OD9DLnhCLk5qKGUsMCw3NSkrIi4uLiI6ZQpyZXR1cm4gZysiXG4iK3R9Zm9yKHM9
-MSxyPTAscT0hMSxwPTA7cDxmOysrcCl7bz1DLnhCLldkKGUscCkKaWYobz09PTEwKXtpZihyIT09cHx8
-IXEpKytzCnI9cCsxCnE9ITF9ZWxzZSBpZihvPT09MTMpeysrcwpyPXArMQpxPSEwfX1nPXM+MT9nKygi
-IChhdCBsaW5lICIrcysiLCBjaGFyYWN0ZXIgIisoZi1yKzEpKyIpXG4iKTpnKygiIChhdCBjaGFyYWN0
-ZXIgIisoZisxKSsiKVxuIikKbj1lLmxlbmd0aApmb3IocD1mO3A8bjsrK3Ape289Qy54Qi5PMihlLHAp
-CmlmKG89PT0xMHx8bz09PTEzKXtuPXAKYnJlYWt9fWlmKG4tcj43OClpZihmLXI8NzUpe209cis3NQps
-PXIKaz0iIgpqPSIuLi4ifWVsc2V7aWYobi1mPDc1KXtsPW4tNzUKbT1uCmo9IiJ9ZWxzZXtsPWYtMzYK
-bT1mKzM2Cmo9Ii4uLiJ9az0iLi4uIn1lbHNle209bgpsPXIKaz0iIgpqPSIifWk9Qy54Qi5OaihlLGws
-bSkKcmV0dXJuIGcraytpK2orIlxuIitDLnhCLkl4KCIgIixmLWwray5sZW5ndGgpKyJeXG4ifWVsc2Ug
-cmV0dXJuIGYhPW51bGw/ZysoIiAoYXQgb2Zmc2V0ICIrSC5kKGYpKyIpIik6Z319ClAuRUgucHJvdG90
-eXBlPXt9ClAuSWYucHJvdG90eXBlPXt9ClAuTHkucHJvdG90eXBlPXsKRTI6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0PUguTGgodGhpcykKcmV0dXJuIEguSzEodGhpcyx0LksoYykuQygiMShMeS5FKSIpLmEoYiks
-dC5DKCJMeS5FIiksYyl9LApldjpmdW5jdGlvbihhLGIpe3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5l
-dyBILlU1KHRoaXMsdC5DKCJhMihMeS5FKSIpLmEoYiksdC5DKCJVNTxMeS5FPiIpKX0sCmdrOmZ1bmN0
-aW9uKGEpe3ZhciB0LHM9dGhpcy5ndyh0aGlzKQpmb3IodD0wO3MubSgpOykrK3QKcmV0dXJuIHR9LApn
-bDA6ZnVuY3Rpb24oYSl7cmV0dXJuIXRoaXMuZ3codGhpcykubSgpfSwKZ3I4OmZ1bmN0aW9uKGEpe3Zh
-ciB0LHM9dGhpcy5ndyh0aGlzKQppZighcy5tKCkpdGhyb3cgSC5iKEguV3AoKSkKdD1zLmdSKHMpCmlm
-KHMubSgpKXRocm93IEguYihILmRVKCkpCnJldHVybiB0fSwKVzpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
-cixxPSJpbmRleCIKUC5VSShiLHEsdS5TKQpQLmsxKGIscSkKZm9yKHQ9dGhpcy5ndyh0aGlzKSxzPTA7
-dC5tKCk7KXtyPXQuZ1IodCkKaWYoYj09PXMpcmV0dXJuIHI7KytzfXRocm93IEguYihQLnQoYix0aGlz
-LHEsbnVsbCxzKSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBQLkVQKHRoaXMsIigiLCIpIil9fQpQLkFu
-LnByb3RvdHlwZT17fQpQLnpNLnByb3RvdHlwZT17JGliUToxLCRpTHk6MX0KUC5aMC5wcm90b3R5cGU9
-e30KUC5OMy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJNYXBFbnRyeSgiK0guZCh0aGlz
-LmEpKyI6ICIrSC5kKHRoaXMuYikrIikifSwKZ0czOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LApn
-bnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYn19ClAuYzgucHJvdG90eXBlPXsKZ2k6ZnVuY3Rpb24o
-YSl7cmV0dXJuIFAuTWgucHJvdG90eXBlLmdpLmNhbGwodGhpcyx0aGlzKX0sClo6ZnVuY3Rpb24oYSl7
-cmV0dXJuIm51bGwifX0KUC5sZi5wcm90b3R5cGU9e30KUC5NaC5wcm90b3R5cGU9e2NvbnN0cnVjdG9y
-OlAuTWgsJGlNaDoxLApETjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzPT09Yn0sCmdpOmZ1bmN0aW9u
-KGEpe3JldHVybiBILmVRKHRoaXMpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIr
-SC5kKEgubGgodGhpcykpKyInIn0sCmU3OmZ1bmN0aW9uKGEsYil7dS5vLmEoYikKdGhyb3cgSC5iKFAu
-bHIodGhpcyxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfSwKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1
-cm4gdGhpcy5aKHRoaXMpfX0KUC5PZC5wcm90b3R5cGU9e30KUC5pYi5wcm90b3R5cGU9eyRpT2Q6MX0K
-UC54dS5wcm90b3R5cGU9e30KUC5Hei5wcm90b3R5cGU9e30KUC5aZC5wcm90b3R5cGU9ewpaOmZ1bmN0
-aW9uKGEpe3JldHVybiIifSwKJGlHejoxfQpQLnFVLnByb3RvdHlwZT17JGl2WDoxfQpQLlJuLnByb3Rv
-dHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwKWjpmdW5jdGlvbihhKXt2
-YXIgdD10aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaUJMOjF9ClAuR0QucHJv
-dG90eXBlPXt9ClAubjEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmYu
-YShhKQpILmMoYikKdD1KLnJZKGIpLk9ZKGIsIj0iKQppZih0PT09LTEpe2lmKGIhPT0iIilKLnU5KGEs
-UC5rdShiLDAsYi5sZW5ndGgsdGhpcy5hLCEwKSwiIil9ZWxzZSBpZih0IT09MCl7cz1DLnhCLk5qKGIs
-MCx0KQpyPUMueEIueW4oYix0KzEpCnE9dGhpcy5hCkoudTkoYSxQLmt1KHMsMCxzLmxlbmd0aCxxLCEw
-KSxQLmt1KHIsMCxyLmxlbmd0aCxxLCEwKSl9cmV0dXJuIGF9LAokUzoyNH0KUC5jUy5wcm90b3R5cGU9
-ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjQgYWRkcmVzcywgIith
-LHRoaXMuYSxiKSl9LAokUzo0OH0KUC5WQy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93
-IEguYihQLnJyKCJJbGxlZ2FsIElQdjYgYWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokMTpmdW5jdGlv
-bihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJFM6MzF9ClAuSlQucHJvdG90eXBlPXsKJDI6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdAppZihiLWE+NCl0aGlzLmEuJDIoImFuIElQdjYgcGFydCBjYW4gb25seSBj
-b250YWluIGEgbWF4aW11bSBvZiA0IGhleCBkaWdpdHMiLGEpCnQ9UC5RQShDLnhCLk5qKHRoaXMuYixh
-LGIpLG51bGwsMTYpCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCmlmKHQ8MHx8dD42
-NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSBvZiBgMHgwLi4weEZG
-RkZgIixhKQpyZXR1cm4gdH0sCiRTOjM1fQpQLkRuLnByb3RvdHlwZT17CmdrdTpmdW5jdGlvbigpe3Jl
-dHVybiB0aGlzLmJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpcmV0dXJu
-IiIKaWYoQy54Qi5uQyh0LCJbIikpcmV0dXJuIEMueEIuTmoodCwxLHQubGVuZ3RoLTEpCnJldHVybiB0
-fSwKZ3RwOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiBQLndLKHRoaXMu
-YSkKcmV0dXJuIHR9LApndFA6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5mCnJldHVybiB0PT1udWxsPyIi
-OnR9LApnS2E6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLnIKcmV0dXJuIHQ9PW51bGw/IiI6dH0sCm5tOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMKdS5YLmEobnVsbCkKdS5iLmEoYikK
-dD1sLmEKcz10PT09ImZpbGUiCnI9bC5iCnE9bC5kCnA9bC5jCmlmKCEocCE9bnVsbCkpcD1yLmxlbmd0
-aCE9PTB8fHEhPW51bGx8fHM/IiI6bnVsbApvPWwuZQppZighcyluPXAhPW51bGwmJm8ubGVuZ3RoIT09
-MAplbHNlIG49ITAKaWYobiYmIUMueEIubkMobywiLyIpKW89Ii8iK28KbT1QLmxlKG51bGwsMCwwLGIp
-CnJldHVybiBuZXcgUC5Ebih0LHIscCxxLG8sbSxsLnIpfSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHQscz10
-aGlzLngKaWYocyE9bnVsbClyZXR1cm4gcwp0PXRoaXMuZQppZih0Lmxlbmd0aCE9PTAmJkMueEIuV2Qo
-dCwwKT09PTQ3KXQ9Qy54Qi55bih0LDEpCnM9dD09PSIiP0MueEQ6UC5BRihuZXcgSC5sSihILlZNKHQu
-c3BsaXQoIi8iKSx1LnMpLHUuZE8uYShQLlBIKCkpLHUuZG8pLHUuTikKdGhpcy5zbzYocykKcmV0dXJu
-IHN9LApnaFk6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMKaWYocy5RPT1udWxsKXt0PXMuZgpzLnNSSChu
-ZXcgUC5HaihQLldYKHQ9PW51bGw/IiI6dCksdS5FKSl9cmV0dXJuIHMuUX0sCkpoOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscyxyLHEscCxvCmZvcih0PTAscz0wO0MueEIuUWkoYiwiLi4vIixzKTspe3MrPTM7Kyt0
-fXI9Qy54Qi5jbihhLCIvIikKd2hpbGUoITApe2lmKCEocj4wJiZ0PjApKWJyZWFrCnE9Qy54Qi5Qayhh
-LCIvIixyLTEpCmlmKHE8MClicmVhawpwPXItcQpvPXAhPT0yCmlmKCFvfHxwPT09MylpZihDLnhCLk8y
-KGEscSsxKT09PTQ2KW89IW98fEMueEIuTzIoYSxxKzIpPT09NDYKZWxzZSBvPSExCmVsc2Ugbz0hMQpp
-ZihvKWJyZWFrOy0tdApyPXF9cmV0dXJuIEMueEIuaTcoYSxyKzEsbnVsbCxDLnhCLnluKGIscy0zKnQp
-KX0sClpJOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLm1TKFAuaEsoYSkpfSwKbVM6ZnVuY3Rpb24oYSl7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGs9dGhpcyxqPW51bGwKaWYoYS5nRmkoKS5sZW5ndGghPT0wKXt0
-PWEuZ0ZpKCkKaWYoYS5nY2ooKSl7cz1hLmdrdSgpCnI9YS5nSmYoYSkKcT1hLmd4QSgpP2EuZ3RwKGEp
-Omp9ZWxzZXtxPWoKcj1xCnM9IiJ9cD1QLnhlKGEuZ0lpKGEpKQpvPWEuZ1FEKCk/YS5ndFAoYSk6an1l
-bHNle3Q9ay5hCmlmKGEuZ2NqKCkpe3M9YS5na3UoKQpyPWEuZ0pmKGEpCnE9UC53QihhLmd4QSgpP2Eu
-Z3RwKGEpOmosdCkKcD1QLnhlKGEuZ0lpKGEpKQpvPWEuZ1FEKCk/YS5ndFAoYSk6an1lbHNle3M9ay5i
-CnI9ay5jCnE9ay5kCmlmKGEuZ0lpKGEpPT09IiIpe3A9ay5lCm89YS5nUUQoKT9hLmd0UChhKTprLmZ9
-ZWxzZXtpZihhLmd0VCgpKXA9UC54ZShhLmdJaShhKSkKZWxzZXtuPWsuZQppZihuLmxlbmd0aD09PTAp
-aWYocj09bnVsbClwPXQubGVuZ3RoPT09MD9hLmdJaShhKTpQLnhlKGEuZ0lpKGEpKQplbHNlIHA9UC54
-ZSgiLyIrYS5nSWkoYSkpCmVsc2V7bT1rLkpoKG4sYS5nSWkoYSkpCmw9dC5sZW5ndGg9PT0wCmlmKCFs
-fHxyIT1udWxsfHxDLnhCLm5DKG4sIi8iKSlwPVAueGUobSkKZWxzZSBwPVAud0YobSwhbHx8ciE9bnVs
-bCl9fW89YS5nUUQoKT9hLmd0UChhKTpqfX19cmV0dXJuIG5ldyBQLkRuKHQscyxyLHEscCxvLGEuZ1o4
-KCk/YS5nS2EoKTpqKX0sCmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmMhPW51bGx9LApneEE6ZnVu
-Y3Rpb24oKXtyZXR1cm4gdGhpcy5kIT1udWxsfSwKZ1FEOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZiE9
-bnVsbH0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnIhPW51bGx9LApndFQ6ZnVuY3Rpb24oKXty
-ZXR1cm4gQy54Qi5uQyh0aGlzLmUsIi8iKX0sCnQ0OmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMscT1y
-LmEKaWYocSE9PSIiJiZxIT09ImZpbGUiKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZp
-bGUgcGF0aCBmcm9tIGEgIitILmQocSkrIiBVUkkiKSkKcT1yLmYKaWYoKHE9PW51bGw/IiI6cSkhPT0i
-Iil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRo
-IGEgcXVlcnkgY29tcG9uZW50IikpCnE9ci5yCmlmKChxPT1udWxsPyIiOnEpIT09IiIpdGhyb3cgSC5i
-KFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIGZyYWdtZW50
-IGNvbXBvbmVudCIpKQp0PSQuT3goKQppZihILm9UKHQpKXE9UC5tbihyKQplbHNle2lmKHIuYyE9bnVs
-bCYmci5nSmYocikhPT0iIilILlZqKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmls
-ZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1dGhvcml0eSIpKQpzPXIuZ0ZqKCkKUC5rRShz
-LCExKQpxPVAudmcoQy54Qi5uQyhyLmUsIi8iKT8iLyI6IiIscywiLyIpCnE9cS5jaGFyQ29kZUF0KDAp
-PT0wP3E6cX1yZXR1cm4gcX0sClo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhpcyxwPXEueQppZihw
-PT1udWxsKXtwPXEuYQp0PXAubGVuZ3RoIT09MD9wKyI6IjoiIgpzPXEuYwpyPXM9PW51bGwKaWYoIXJ8
-fHA9PT0iZmlsZSIpe3A9dCsiLy8iCnQ9cS5iCmlmKHQubGVuZ3RoIT09MClwPXArdCsiQCIKaWYoIXIp
-cCs9cwp0PXEuZAppZih0IT1udWxsKXA9cCsiOiIrSC5kKHQpfWVsc2UgcD10CnArPXEuZQp0PXEuZgpp
-Zih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgppZih0IT1udWxsKXA9cCsiIyIrdApwPXEueT1wLmNoYXJD
-b2RlQXQoMCk9PTA/cDpwfXJldHVybiBwfSwKRE46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwpp
-ZihiPT1udWxsKXJldHVybiExCmlmKHI9PT1iKXJldHVybiEwCmlmKHUuRi5iKGIpKWlmKHIuYT09Yi5n
-RmkoKSlpZihyLmMhPW51bGw9PT1iLmdjaigpKWlmKHIuYj09Yi5na3UoKSlpZihyLmdKZihyKT09Yi5n
-SmYoYikpaWYoci5ndHAocik9PWIuZ3RwKGIpKWlmKHIuZT09PWIuZ0lpKGIpKXt0PXIuZgpzPXQ9PW51
-bGwKaWYoIXM9PT1iLmdRRCgpKXtpZihzKXQ9IiIKaWYodD09PWIuZ3RQKGIpKXt0PXIucgpzPXQ9PW51
-bGwKaWYoIXM9PT1iLmdaOCgpKXtpZihzKXQ9IiIKdD10PT09Yi5nS2EoKX1lbHNlIHQ9ITF9ZWxzZSB0
-PSExfWVsc2UgdD0hMX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0
-PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKcmV0dXJuIHR9LApnaTpmdW5jdGlvbihhKXt2YXIgdD10aGlz
-LnoKcmV0dXJuIHQ9PW51bGw/dGhpcy56PUMueEIuZ2kodGhpcy5aKDApKTp0fSwKc282OmZ1bmN0aW9u
-KGEpe3RoaXMueD11LmEuYShhKX0sCnNSSDpmdW5jdGlvbihhKXt0aGlzLlE9dS5mLmEoYSl9LAokaWlE
-OjEsCmdGaTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmF9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
-aXMuZX19ClAuZTEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAucnIoIkludmFs
-aWQgcG9ydCIsdGhpcy5hLHRoaXMuYisxKSl9LAokUzoxNX0KUC5OWS5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXt2YXIgdD0iSWxsZWdhbCBwYXRoIGNoYXJhY3RlciAiCkguYyhhKQppZihKLnpsKGEsIi8i
-KSlpZih0aGlzLmEpdGhyb3cgSC5iKFAueFkodCthKSkKZWxzZSB0aHJvdyBILmIoUC5MNCh0K2EpKX0s
-CiRTOjE1fQpQLlJaLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBQLmVQKEMuWkosYSxD
-LnhNLCExKX0sCiRTOjV9ClAuTUUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlz
-LmIscz10aGlzLmEKdC5hKz1zLmEKcy5hPSImIgpzPXQuYSs9SC5kKFAuZVAoQy5GMyxhLEMueE0sITAp
-KQppZihiIT1udWxsJiZiLmxlbmd0aCE9PTApe3QuYT1zKyI9Igp0LmErPUguZChQLmVQKEMuRjMsYixD
-LnhNLCEwKSl9fSwKJFM6MTZ9ClAueTUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
-CkguYyhhKQppZihiPT1udWxsfHx0eXBlb2YgYj09InN0cmluZyIpdGhpcy5hLiQyKGEsSC5jKGIpKQpl
-bHNlIGZvcih0PUouSVQodS5SLmEoYikpLHM9dGhpcy5hO3QubSgpOylzLiQyKGEsSC5jKHQuZ1IodCkp
-KX0sCiRTOjEzfQpQLlBFLnByb3RvdHlwZT17CmdsUjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhp
-cyxvPW51bGwsbj1wLmMKaWYobiE9bnVsbClyZXR1cm4gbgpuPXAuYgppZigwPj1uLmxlbmd0aClyZXR1
-cm4gSC5rKG4sMCkKdD1wLmEKbj1uWzBdKzEKcz1DLnhCLlhVKHQsIj8iLG4pCnI9dC5sZW5ndGgKaWYo
-cz49MCl7cT1QLnVPKHQscysxLHIsQy5WQywhMSkKcj1zfWVsc2UgcT1vCnJldHVybiBwLmM9bmV3IFAu
-cWUoImRhdGEiLG8sbyxvLFAudU8odCxuLHIsQy5XZCwhMSkscSxvKX0sClo6ZnVuY3Rpb24oYSl7dmFy
-IHQscz10aGlzLmIKaWYoMD49cy5sZW5ndGgpcmV0dXJuIEguayhzLDApCnQ9dGhpcy5hCnJldHVybiBz
-WzBdPT09LTE/ImRhdGE6Iit0OnR9fQpQLnEzLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biBuZXcgVWludDhBcnJheSg5Nil9LAokUzoyMn0KUC55SS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
-LGIpe3ZhciB0PXRoaXMuYQppZihhPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQsYSkKdD10W2FdCkouQ00o
-dCwwLDk2LGIpCnJldHVybiB0fSwKJFM6NDl9ClAuYzYucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0LHMscixxCmZvcih0PWIubGVuZ3RoLHM9YS5sZW5ndGgscj0wO3I8dDsrK3Ipe3E9Qy54
-Qi5XZChiLHIpXjk2CmlmKHE+PXMpcmV0dXJuIEguayhhLHEpCmFbcV09Y319fQpQLnFkLnByb3RvdHlw
-ZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQpmb3IodD1DLnhCLldkKGIsMCkscz1DLnhC
-LldkKGIsMSkscj1hLmxlbmd0aDt0PD1zOysrdCl7cT0odF45Nik+Pj4wCmlmKHE+PXIpcmV0dXJuIEgu
-ayhhLHEpCmFbcV09Y319fQpQLlVmLnByb3RvdHlwZT17CmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlz
-LmM+MH0sCmd4QTpmdW5jdGlvbigpe3ZhciB0LHMKaWYodGhpcy5jPjApe3Q9dGhpcy5kCmlmKHR5cGVv
-ZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCnM9dGhpcy5lCmlmKHR5cGVvZiBzIT09Im51bWJlciIp
-cmV0dXJuIEgucFkocykKcz10KzE8cwp0PXN9ZWxzZSB0PSExCnJldHVybiB0fSwKZ1FEOmZ1bmN0aW9u
-KCl7dmFyIHQ9dGhpcy5mCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0
-PHRoaXMucn0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnI8dGhpcy5hLmxlbmd0aH0sCmdOdzpm
-dW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZDLnhCLm5DKHRoaXMuYSwiZmlsZSIpfSwKZ1daOmZ1
-bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMueEIubkModGhpcy5hLCJodHRwIil9LApnUmU6ZnVu
-Y3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NSYmQy54Qi5uQyh0aGlzLmEsImh0dHBzIil9LApndFQ6ZnVu
-Y3Rpb24oKXtyZXR1cm4gQy54Qi5RaSh0aGlzLmEsIi8iLHRoaXMuZSl9LApnRmk6ZnVuY3Rpb24oKXt2
-YXIgdCxzPXRoaXMscj0icGFja2FnZSIscT1zLmIKaWYocTw9MClyZXR1cm4iIgp0PXMueAppZih0IT1u
-dWxsKXJldHVybiB0CmlmKHMuZ1daKCkpcT1zLng9Imh0dHAiCmVsc2UgaWYocy5nUmUoKSl7cy54PSJo
-dHRwcyIKcT0iaHR0cHMifWVsc2UgaWYocy5nTncoKSl7cy54PSJmaWxlIgpxPSJmaWxlIn1lbHNlIGlm
-KHE9PT03JiZDLnhCLm5DKHMuYSxyKSl7cy54PXIKcT1yfWVsc2V7cT1DLnhCLk5qKHMuYSwwLHEpCnMu
-eD1xfXJldHVybiBxfSwKZ2t1OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5jLHM9dGhpcy5iKzMKcmV0dXJu
-IHQ+cz9DLnhCLk5qKHRoaXMuYSxzLHQtMSk6IiJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5j
-CnJldHVybiB0PjA/Qy54Qi5Oaih0aGlzLmEsdCx0aGlzLmQpOiIifSwKZ3RwOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHM9dGhpcwppZihzLmd4QSgpKXt0PXMuZAppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0
-LmgoKQpyZXR1cm4gUC5RQShDLnhCLk5qKHMuYSx0KzEscy5lKSxudWxsLG51bGwpfWlmKHMuZ1daKCkp
-cmV0dXJuIDgwCmlmKHMuZ1JlKCkpcmV0dXJuIDQ0MwpyZXR1cm4gMH0sCmdJaTpmdW5jdGlvbihhKXty
-ZXR1cm4gQy54Qi5Oaih0aGlzLmEsdGhpcy5lLHRoaXMuZil9LApndFA6ZnVuY3Rpb24oYSl7dmFyIHQ9
-dGhpcy5mLHM9dGhpcy5yCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0
-PHM/Qy54Qi5Oaih0aGlzLmEsdCsxLHMpOiIifSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yLHM9
-dGhpcy5hCnJldHVybiB0PHMubGVuZ3RoP0MueEIueW4ocyx0KzEpOiIifSwKZ0ZqOmZ1bmN0aW9uKCl7
-dmFyIHQscyxyPXRoaXMuZSxxPXRoaXMuZixwPXRoaXMuYQppZihDLnhCLlFpKHAsIi8iLHIpKXtpZih0
-eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLmgoKTsrK3J9aWYocj09cSlyZXR1cm4gQy54RAp0PUgu
-Vk0oW10sdS5zKQpzPXIKd2hpbGUoITApe2lmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSigp
-CmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgucFkocSkKaWYoIShzPHEpKWJyZWFrCmlmKEMu
-eEIuTzIocCxzKT09PTQ3KXtDLk5tLkEodCxDLnhCLk5qKHAscixzKSkKcj1zKzF9KytzfUMuTm0uQSh0
-LEMueEIuTmoocCxyLHEpKQpyZXR1cm4gUC5BRih0LHUuTil9LApnaFk6ZnVuY3Rpb24oKXt2YXIgdD10
-aGlzLHM9dC5mCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSigpCmlmKHM+PXQucilyZXR1
-cm4gQy5XTwpyZXR1cm4gbmV3IFAuR2ooUC5XWCh0Lmd0UCh0KSksdS5FKX0sCmtYOmZ1bmN0aW9uKGEp
-e3ZhciB0LHM9dGhpcy5kCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuaCgpCnQ9cysxCnJl
-dHVybiB0K2EubGVuZ3RoPT09dGhpcy5lJiZDLnhCLlFpKHRoaXMuYSxhLHQpfSwKTjk6ZnVuY3Rpb24o
-KXt2YXIgdD10aGlzLHM9dC5yLHI9dC5hCmlmKHM+PXIubGVuZ3RoKXJldHVybiB0CnJldHVybiBuZXcg
-UC5VZihDLnhCLk5qKHIsMCxzKSx0LmIsdC5jLHQuZCx0LmUsdC5mLHMsdC54KX0sCm5tOmZ1bmN0aW9u
-KGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaj10aGlzLGk9bnVsbAp1LlguYShudWxsKQp1LmIu
-YShiKQp0PWouZ0ZpKCkKcz10PT09ImZpbGUiCnI9ai5jCnE9cj4wP0MueEIuTmooai5hLGouYiszLHIp
-OiIiCnA9ai5neEEoKT9qLmd0cChqKTppCnI9ai5jCmlmKHI+MClvPUMueEIuTmooai5hLHIsai5kKQpl
-bHNlIG89cS5sZW5ndGghPT0wfHxwIT1udWxsfHxzPyIiOmkKcj1qLmEKbj1DLnhCLk5qKHIsai5lLGou
-ZikKaWYoIXMpbT1vIT1udWxsJiZuLmxlbmd0aCE9PTAKZWxzZSBtPSEwCmlmKG0mJiFDLnhCLm5DKG4s
-Ii8iKSluPSIvIituCmw9UC5sZShpLDAsMCxiKQptPWoucgprPW08ci5sZW5ndGg/Qy54Qi55bihyLG0r
-MSk6aQpyZXR1cm4gbmV3IFAuRG4odCxxLG8scCxuLGwsayl9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4g
-dGhpcy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVy
-biB0aGlzLnUxKHRoaXMsYSkKcmV0dXJuIHRoaXMudnMoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9Yi5iCmlmKGU+MClyZXR1cm4gYgp0PWIu
-YwppZih0PjApe3M9YS5iCmlmKHM8PTApcmV0dXJuIGIKaWYoYS5nTncoKSlyPWIuZSE9Yi5mCmVsc2Ug
-aWYoYS5nV1ooKSlyPSFiLmtYKCI4MCIpCmVsc2Ugcj0hYS5nUmUoKXx8IWIua1goIjQ0MyIpCmlmKHIp
-e3E9cysxCnA9Qy54Qi5OaihhLmEsMCxxKStDLnhCLnluKGIuYSxlKzEpCmU9Yi5kCmlmKHR5cGVvZiBl
-IT09Im51bWJlciIpcmV0dXJuIGUuaCgpCm89Yi5lCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJu
-IG8uaCgpCm49Yi5mCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uaCgpCnJldHVybiBuZXcg
-UC5VZihwLHMsdCtxLGUrcSxvK3EsbitxLGIucitxLGEueCl9ZWxzZSByZXR1cm4gdGhpcy52cygpLm1T
-KGIpfW09Yi5lCmU9Yi5mCmlmKG09PWUpe3Q9Yi5yCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJu
-IGUuSigpCmlmKGU8dCl7cz1hLmYKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCnE9
-cy1lCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHMpK0MueEIueW4oYi5hLGUpLGEuYixhLmMs
-YS5kLGEuZSxlK3EsdCtxLGEueCl9ZT1iLmEKaWYodDxlLmxlbmd0aCl7cz1hLnIKcmV0dXJuIG5ldyBQ
-LlVmKEMueEIuTmooYS5hLDAscykrQy54Qi55bihlLHQpLGEuYixhLmMsYS5kLGEuZSxhLmYsdCsocy10
-KSxhLngpfXJldHVybiBhLk45KCl9dD1iLmEKaWYoQy54Qi5RaSh0LCIvIixtKSl7cz1hLmUKaWYodHlw
-ZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJu
-IEgucFkobSkKcT1zLW0KcD1DLnhCLk5qKGEuYSwwLHMpK0MueEIueW4odCxtKQppZih0eXBlb2YgZSE9
-PSJudW1iZXIiKXJldHVybiBlLmgoKQpyZXR1cm4gbmV3IFAuVWYocCxhLmIsYS5jLGEuZCxzLGUrcSxi
-LnIrcSxhLngpfWw9YS5lCms9YS5mCmlmKGw9PWsmJmEuYz4wKXtmb3IoO0MueEIuUWkodCwiLi4vIixt
-KTspe2lmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIG0uaCgpCm0rPTN9aWYodHlwZW9mIGwhPT0i
-bnVtYmVyIilyZXR1cm4gbC5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkK
-cT1sLW0rMQpwPUMueEIuTmooYS5hLDAsbCkrIi8iK0MueEIueW4odCxtKQppZih0eXBlb2YgZSE9PSJu
-dW1iZXIiKXJldHVybiBlLmgoKQpyZXR1cm4gbmV3IFAuVWYocCxhLmIsYS5jLGEuZCxsLGUrcSxiLnIr
-cSxhLngpfWo9YS5hCmZvcihpPWw7Qy54Qi5RaShqLCIuLi8iLGkpOyl7aWYodHlwZW9mIGkhPT0ibnVt
-YmVyIilyZXR1cm4gaS5oKCkKaSs9M31oPTAKd2hpbGUoITApe2lmKHR5cGVvZiBtIT09Im51bWJlciIp
-cmV0dXJuIG0uaCgpCmc9bSszCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJuIEgucFkoZSkKaWYo
-IShnPD1lJiZDLnhCLlFpKHQsIi4uLyIsbSkpKWJyZWFrOysraAptPWd9Zj0iIgp3aGlsZSghMCl7aWYo
-dHlwZW9mIGshPT0ibnVtYmVyIilyZXR1cm4gay5vcygpCmlmKHR5cGVvZiBpIT09Im51bWJlciIpcmV0
-dXJuIEgucFkoaSkKaWYoIShrPmkpKWJyZWFrOy0tawppZihDLnhCLk8yKGosayk9PT00Nyl7aWYoaD09
-PTApe2Y9Ii8iCmJyZWFrfS0taApmPSIvIn19aWYoaz09PWkmJmEuYjw9MCYmIUMueEIuUWkoaiwiLyIs
-bCkpe20tPWgqMwpmPSIifXE9ay1tK2YubGVuZ3RoCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGosMCxr
-KStmK0MueEIueW4odCxtKSxhLmIsYS5jLGEuZCxsLGUrcSxiLnIrcSxhLngpfSwKdDQ6ZnVuY3Rpb24o
-KXt2YXIgdCxzLHIscSxwPXRoaXMKaWYocC5iPj0wJiYhcC5nTncoKSl0aHJvdyBILmIoUC5MNCgiQ2Fu
-bm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrSC5kKHAuZ0ZpKCkpKyIgVVJJIikpCnQ9cC5m
-CnM9cC5hCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCmlmKHQ8cy5sZW5ndGgpe2lm
-KHQ8cC5yKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJ
-IHdpdGggYSBxdWVyeSBjb21wb25lbnQiKSkKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEg
-ZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIGZyYWdtZW50IGNvbXBvbmVudCIpKX1yPSQuT3goKQpp
-ZihILm9UKHIpKXQ9UC5tbihwKQplbHNle3E9cC5kCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJu
-IEgucFkocSkKaWYocC5jPHEpSC5WaihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIG5vbi1XaW5kb3dzIGZp
-bGUgcGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0aCBhbiBhdXRob3JpdHkiKSkKdD1DLnhCLk5qKHMscC5l
-LHQpfXJldHVybiB0fSwKZ2k6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3Ro
-aXMueT1DLnhCLmdpKHRoaXMuYSk6dH0sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4h
-MQppZih0aGlzPT09YilyZXR1cm4hMApyZXR1cm4gdS5GLmIoYikmJnRoaXMuYT09PWIuWigwKX0sCnZz
-OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPW51bGwscj10LmdGaSgpLHE9dC5na3UoKSxwPXQuYz4wP3Qu
-Z0pmKHQpOnMsbz10Lmd4QSgpP3QuZ3RwKHQpOnMsbj10LmEsbT10LmYsbD1DLnhCLk5qKG4sdC5lLG0p
-LGs9dC5yCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIG0uSigpCm09bTxrP3QuZ3RQKHQpOnMK
-cmV0dXJuIG5ldyBQLkRuKHIscSxwLG8sbCxtLGs8bi5sZW5ndGg/dC5nS2EoKTpzKX0sClo6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuYX0sCiRpaUQ6MX0KUC5xZS5wcm90b3R5cGU9e30KVy5xRS5wcm90b3R5
-cGU9e30KVy5ZZS5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLkdo
-LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpR2g6MX0KVy5mWS5w
-cm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLm5CLnByb3RvdHlwZT17
-JGluQjoxfQpXLkF6LnByb3RvdHlwZT17JGlBejoxfQpXLlBVLnByb3RvdHlwZT17CmdudzpmdW5jdGlv
-bihhKXtyZXR1cm4gYS52YWx1ZX19ClcuUVAucHJvdG90eXBlPXskaVFQOjF9ClcuSUYucHJvdG90eXBl
-PXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5ueC5wcm90b3R5cGU9ewpnazpmdW5j
-dGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLlJkLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXty
-ZXR1cm4gYS52YWx1ZX19Clcua1IucHJvdG90eXBlPXt9ClcuVGYucHJvdG90eXBlPXsKZ2s6ZnVuY3Rp
-b24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5sdy5wcm90b3R5cGU9eyRpbHc6MX0KVy5vSi5wcm90b3R5
-cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmlkLnByb3RvdHlwZT17fQpXLkJ3
-LnByb3RvdHlwZT17fQpXLm80LnByb3RvdHlwZT17fQpXLkhTLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9u
-KGEpe3JldHVybiBhLmxlbmd0aH19ClcuVm8ucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVy
-biBhLnZhbHVlfX0KVy5GaC5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
-fQpXLmN4LnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuU2IucHJv
-dG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBhW0guV1koYildfX0KVy5RRi5wcm90b3R5cGU9e30KVy5OaC5wcm90b3R5cGU9ewpaOmZ1bmN0
-aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLkZ2LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5s
-ZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVu
-Y3Rpb24oYSxiLGMpe0guV1koYikKdS5xLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24g
-ZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1h
-Lmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeTox
-LAokaXpNOjF9ClcuSUIucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgi
-K0guZChhLmxlZnQpKyIsICIrSC5kKGEudG9wKSsiKSAiK0guZCh0aGlzLmdQKGEpKSsiIHggIitILmQo
-dGhpcy5nTChhKSl9LApETjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGI9PW51bGwpcmV0dXJuITEKaWYo
-dS5xLmIoYikpaWYoYS5sZWZ0PT1iLmxlZnQpaWYoYS50b3A9PWIudG9wKXt0PUouUkUoYikKdD10aGlz
-LmdQKGEpPT10LmdQKGIpJiZ0aGlzLmdMKGEpPT10LmdMKGIpfWVsc2UgdD0hMQplbHNlIHQ9ITEKZWxz
-ZSB0PSExCnJldHVybiB0fSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5JKGEubGVmdCksSi5J
-KGEudG9wKSxKLkkodGhpcy5nUChhKSksSi5JKHRoaXMuZ0woYSkpKX0sCmdMOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBhLmhlaWdodH0sCmdQOmZ1bmN0aW9uKGEpe3JldHVybiBhLndpZHRofSwKJGl0bjoxfQpXLlls
-LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxi
-KXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxu
-dWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKSC5jKGMpCnRo
-cm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwK
-VzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBh
-W2JdfSwKJGliUToxLAokaVhqOjEsCiRpTHk6MSwKJGl6TToxfQpXLm43LnByb3RvdHlwZT17CmdrOmZ1
-bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19
-Clcud3oucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1
-bmN0aW9uKGEsYil7dmFyIHQKSC5XWShiKQp0PXRoaXMuYQppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVy
-biBILmsodCxiKQpyZXR1cm4gdGhpcy4kdGkuYy5hKHRbYl0pfSwKdDpmdW5jdGlvbihhLGIsYyl7SC5X
-WShiKQp0aGlzLiR0aS5jLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19
-ClcuY3YucHJvdG90eXBlPXsKZ1FnOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5pNyhhKX0sCmdERDpm
-dW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuSTQoYSl9LApzREQ6ZnVuY3Rpb24oYSxiKXt2YXIgdAp1Llgu
-YShiKQp0PXRoaXMuZ0REKGEpCnQuVjEoMCkKdC5GVigwLGIpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4g
-YS5sb2NhbE5hbWV9LAp0bjpmdW5jdGlvbihhKXt2YXIgdD0hIWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRl
-ZAppZih0KWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgpCmVsc2UgYS5zY3JvbGxJbnRvVmlldygpfSwK
-bno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzPXRoaXMucjYoYSxjLGQsZSkKc3dpdGNoKGIudG9M
-b3dlckNhc2UoKSl7Y2FzZSJiZWZvcmViZWdpbiI6YS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShzLGEp
-CmJyZWFrCmNhc2UiYWZ0ZXJiZWdpbiI6dD1hLmNoaWxkTm9kZXMKYS5pbnNlcnRCZWZvcmUocyx0Lmxl
-bmd0aD4wP3RbMF06bnVsbCkKYnJlYWsKY2FzZSJiZWZvcmVlbmQiOmEuYXBwZW5kQ2hpbGQocykKYnJl
-YWsKY2FzZSJhZnRlcmVuZCI6YS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShzLGEubmV4dFNpYmxpbmcp
-CmJyZWFrCmRlZmF1bHQ6SC5WaihQLnhZKCJJbnZhbGlkIHBvc2l0aW9uICIrYikpfX0sCnI2OmZ1bmN0
-aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKGM9PW51bGwpe2lmKGQ9PW51bGwpe3Q9JC5sdAppZih0
-PT1udWxsKXt0PUguVk0oW10sdS51KQpzPW5ldyBXLnZEKHQpCkMuTm0uQSh0LFcuVHcobnVsbCkpCkMu
-Tm0uQSh0LFcuQmwoKSkKJC5sdD1zCmQ9c31lbHNlIGQ9dH10PSQuRVUKaWYodD09bnVsbCl7dD1uZXcg
-Vy5LbyhkKQokLkVVPXQKYz10fWVsc2V7dC5hPWQKYz10fX1lbHNlIGlmKGQhPW51bGwpdGhyb3cgSC5i
-KFAueFkoInZhbGlkYXRvciBjYW4gb25seSBiZSBwYXNzZWQgaWYgdHJlZVNhbml0aXplciBpcyBudWxs
-IikpCmlmKCQueG89PW51bGwpe3Q9ZG9jdW1lbnQKcz10LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxE
-b2N1bWVudCgiIikKJC54bz1zCiQuQk89cy5jcmVhdGVSYW5nZSgpCnM9JC54by5jcmVhdGVFbGVtZW50
-KCJiYXNlIikKdS5jUi5hKHMpCnMuaHJlZj10LmJhc2VVUkkKJC54by5oZWFkLmFwcGVuZENoaWxkKHMp
-fXQ9JC54bwppZih0LmJvZHk9PW51bGwpe3M9dC5jcmVhdGVFbGVtZW50KCJib2R5IikKdC5ib2R5PXUu
-ay5hKHMpfXQ9JC54bwppZih1LmsuYihhKSlyPXQuYm9keQplbHNle3I9dC5jcmVhdGVFbGVtZW50KGEu
-dGFnTmFtZSkKJC54by5ib2R5LmFwcGVuZENoaWxkKHIpfWlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21l
-bnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUmJiFDLk5tLnRnKEMuU3EsYS50YWdOYW1lKSl7JC5C
-Ty5zZWxlY3ROb2RlQ29udGVudHMocikKcT0kLkJPLmNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudChiKX1l
-bHNle3IuaW5uZXJIVE1MPWIKcT0kLnhvLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpmb3IoO3Q9ci5m
-aXJzdENoaWxkLHQhPW51bGw7KXEuYXBwZW5kQ2hpbGQodCl9dD0kLnhvLmJvZHkKaWYocj09bnVsbD90
-IT1udWxsOnIhPT10KUouTHQocikKYy5QbihxKQpkb2N1bWVudC5hZG9wdE5vZGUocSkKcmV0dXJuIHF9
-LApBSDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHRoaXMucjYoYSxiLGMsbnVsbCl9LApzaGY6ZnVuY3Rp
-b24oYSxiKXt0aGlzLllDKGEsYil9LApwazpmdW5jdGlvbihhLGIsYyl7YS50ZXh0Q29udGVudD1udWxs
-CmEuYXBwZW5kQ2hpbGQodGhpcy5yNihhLGIsbnVsbCxjKSl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVy
-biB0aGlzLnBrKGEsYixudWxsKX0sCmduczpmdW5jdGlvbihhKXtyZXR1cm4gYS50YWdOYW1lfSwKZ1Zs
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5ldShhLCJjbGljayIsITEsdS5RKX0sCiRpY3Y6MX0KVy5D
-di5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5oLmIodS5BLmEoYSkpfSwKJFM6MjV9
-ClcuZWEucHJvdG90eXBlPXskaWVhOjF9ClcuRDAucHJvdG90eXBlPXsKT246ZnVuY3Rpb24oYSxiLGMs
-ZCl7dS5lNi5hKGMpCmlmKGMhPW51bGwpdGhpcy52MChhLGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxiLGMp
-e3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjA6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEu
-YWRkRXZlbnRMaXN0ZW5lcihiLEgudFIodS5lNi5hKGMpLDEpLGQpfSwKJGlEMDoxfQpXLlQ1LnByb3Rv
-dHlwZT17JGlUNToxfQpXLlhWLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0
-aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cg
-SC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMp
-e0guV1koYikKdS5PLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBp
-bW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1
-cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjEsCiRp
-WFY6MX0KVy53Si5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmg0
-LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuR08ucHJvdG90eXBl
-PXskaUdPOjF9ClcuSkMucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0K
-Vy5ici5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLnhuLnByb3Rv
-dHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZ
-KGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51
-bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5BLmEoYykKdGhyb3cg
-SC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1
-bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19
-LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9ClcuVmIucHJvdG90eXBlPXt9ClcuZkoucHJv
-dG90eXBlPXsKZW86ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEub3BlbihiLGMsITApfSwKJGlmSjox
-fQpXLmJVLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLnNldFJlcXVlc3RIZWFkZXIo
-SC5jKGEpLEguYyhiKSl9LAokUzoxMn0KVy5oSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIscSxwCnUucC5hKGEpCnQ9dGhpcy5hCnM9dC5zdGF0dXMKaWYodHlwZW9mIHMhPT0ibnVtYmVy
-IilyZXR1cm4gcy50QigpCnI9cz49MjAwJiZzPDMwMApxPXM+MzA3JiZzPDQwMApzPXJ8fHM9PT0wfHxz
-PT09MzA0fHxxCnA9dGhpcy5iCmlmKHMpcC5hTSgwLHQpCmVsc2UgcC5wbShhKX0sCiRTOjI3fQpXLndh
-LnByb3RvdHlwZT17fQpXLlNnLnByb3RvdHlwZT17JGlTZzoxfQpXLkpLLnByb3RvdHlwZT17Cmdudzpm
-dW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gYS53ZWJraXRF
-bnRyaWVzfX0KVy5ITC5wcm90b3R5cGU9ewpnRzM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEua2V5fX0KVy53
-UC5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9fQpXLnU4LnByb3RvdHlw
-ZT17CmdEcjpmdW5jdGlvbihhKXtpZigib3JpZ2luIiBpbiBhKXJldHVybiBhLm9yaWdpbgpyZXR1cm4g
-SC5kKGEucHJvdG9jb2wpKyIvLyIrSC5kKGEuaG9zdCl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJp
-bmcoYSl9LAokaXU4OjF9ClcuejYucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVu
-Z3RofX0KVy5DZi5wcm90b3R5cGU9eyRpQ2Y6MX0KVy5RYi5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24o
-YSl7cmV0dXJuIGEudmFsdWV9fQpXLlMwLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
-UC5tUihhLmdldChILmMoYikpKX0sClU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnUuVC5hKGIpCnQ9YS5l
-bnRyaWVzKCkKZm9yKDshMDspe3M9dC5uZXh0KCkKaWYocy5kb25lKXJldHVybgpiLiQyKHMudmFsdWVb
-MF0sUC5tUihzLnZhbHVlWzFdKSl9fSwKZ3Y6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5WTShbXSx1LnMpCnRo
-aXMuVShhLG5ldyBXLkZBKHQpKQpyZXR1cm4gdH0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLnNpemV9
-LAp0OmZ1bmN0aW9uKGEsYixjKXt0aHJvdyBILmIoUC5MNCgiTm90IHN1cHBvcnRlZCIpKX0sCiRpWjA6
-MX0KVy5GQS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3JldHVybiBDLk5tLkEodGhpcy5hLGEp
-fSwKJFM6OH0KVy56Mi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQo
-SC5jKGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp1LlQuYShiKQp0PWEuZW50cmllcygpCmZv
-cig7ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52
-YWx1ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcg
-Vy51cSh0KSkKcmV0dXJuIHR9LApnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5zaXplfSwKdDpmdW5jdGlv
-bihhLGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBwb3J0ZWQiKSl9LAokaVowOjF9ClcudXEucHJv
-dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9Clcu
-QVcucHJvdG90eXBlPXskaUFXOjF9ClcuRE0ucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJu
-IGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0
-aCl0aHJvdyBILmIoUC50KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKdDpmdW5jdGlv
-bihhLGIsYyl7SC5XWShiKQp1LmNJLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxl
-bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
-bmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAok
-aXpNOjF9ClcuT0sucHJvdG90eXBlPXskaU9LOjF9ClcuZTcucHJvdG90eXBlPXsKZ3I4OmZ1bmN0aW9u
-KGEpe3ZhciB0PXRoaXMuYSxzPXQuY2hpbGROb2Rlcy5sZW5ndGgKaWYocz09PTApdGhyb3cgSC5iKFAu
-UFYoIk5vIGVsZW1lbnRzIikpCmlmKHM+MSl0aHJvdyBILmIoUC5QVigiTW9yZSB0aGFuIG9uZSBlbGVt
-ZW50IikpCnJldHVybiB0LmZpcnN0Q2hpbGR9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUu
-ZWguYShiKQp0PWIuYQpzPXRoaXMuYQppZih0IT09cylmb3Iocj10LmNoaWxkTm9kZXMubGVuZ3RoLHE9
-MDtxPHI7KytxKXMuYXBwZW5kQ2hpbGQodC5maXJzdENoaWxkKQpyZXR1cm59LAp0OmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdApILldZKGIpCnQ9dGhpcy5hCnQucmVwbGFjZUNoaWxkKHUuQS5hKGMpLEMudDUucSh0
-LmNoaWxkTm9kZXMsYikpfSwKZ3c6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLmNoaWxkTm9kZXMKcmV0
-dXJuIG5ldyBXLlc5KHQsdC5sZW5ndGgsSC5xKHQpLkMoIlc5PEdtLkU+IikpfSwKZ2s6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMuYS5jaGlsZE5vZGVzLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIp
-CnJldHVybiBDLnQ1LnEodGhpcy5hLmNoaWxkTm9kZXMsYil9fQpXLnVILnByb3RvdHlwZT17CndnOmZ1
-bmN0aW9uKGEpe3ZhciB0PWEucGFyZW50Tm9kZQppZih0IT1udWxsKXQucmVtb3ZlQ2hpbGQoYSl9LApE
-NDpmdW5jdGlvbihhKXt2YXIgdApmb3IoO3Q9YS5maXJzdENoaWxkLHQhPW51bGw7KWEucmVtb3ZlQ2hp
-bGQodCl9LApaOmZ1bmN0aW9uKGEpe3ZhciB0PWEubm9kZVZhbHVlCnJldHVybiB0PT1udWxsP3RoaXMu
-VChhKTp0fSwKJGl1SDoxfQpXLkJILnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxl
-bmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhy
-b3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxi
-LGMpe0guV1koYikKdS5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBv
-ZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aCly
-ZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9
-ClcuUWwucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5HWC5wcm90
-b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9fQpXLlNOLnByb3RvdHlwZT17fQpX
-LkhELnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuY2wucHJvdG90
-eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKJGljbDoxfQpXLkV2LnByb3RvdHlw
-ZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIp
-CmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwp
-KQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5oZS5hKGMpCnRocm93IEgu
-YihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5j
-dGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwK
-JGliUToxLAokaVhqOjEsCiRpTHk6MSwKJGl6TToxfQpXLkxyLnByb3RvdHlwZT17CmdudzpmdW5jdGlv
-bihhKXtyZXR1cm4gYS52YWx1ZX19ClcuS1IucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVy
-biBhLnZhbHVlfX0KVy5ldy5wcm90b3R5cGU9eyRpZXc6MX0KVy5wOC5wcm90b3R5cGU9ewpxOmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQoSC5jKGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQs
-cwp1LlQuYShiKQp0PWEuZW50cmllcygpCmZvcig7ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1
-cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52YWx1ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0
-PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcgVy5paSh0KSkKcmV0dXJuIHR9LApnazpmdW5jdGlvbihh
-KXtyZXR1cm4gYS5zaXplfSwKdDpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBw
-b3J0ZWQiKSl9LAokaVowOjF9ClcuaWkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
-Qy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9ClcubHAucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0
-dXJuIGEubGVuZ3RofSwKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5TVi5wcm90b3R5
-cGU9eyRpU1Y6MX0KVy5Nay5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
-LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEgu
-YihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0OmZ1bmN0aW9uKGEsYixjKXtI
-LldZKGIpCnUuZlkuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGlt
-bXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVy
-biBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaUx5OjEsCiRpek06MX0KVy5Z
-NC5wcm90b3R5cGU9eyRpWTQ6MX0KVy5Obi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4g
-YS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3Ro
-KXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0OmZ1bmN0aW9u
-KGEsYixjKXtILldZKGIpCnUuZjcuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
+dXJuIEguT0godCxwKQp0W3BdPTIyNHxxPj4+MTIKcD1tLmI9bisxCmlmKG4+PXMpcmV0dXJuIEguT0go
+dCxuKQp0W25dPTEyOHxxPj4+NiY2MwptLmI9cCsxCmlmKHA+PXMpcmV0dXJuIEguT0godCxwKQp0W3Bd
+PTEyOHxxJjYzfX1yZXR1cm4gcn19ClAuR1kucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyLHEscCxvLG4sbSxsCnUuTC5iKGEpCnQ9UC5reSghMSxhLDAsbnVsbCkKaWYodCE9bnVsbClyZXR1
+cm4gdApzPVAuakIoMCxudWxsLEouSG0oYSkpCnI9UC5jUChhLDAscykKaWYocj4wKXtxPVAuSE0oYSww
+LHIpCmlmKHI9PT1zKXJldHVybiBxCnA9bmV3IFAuUm4ocSkKbz1yCm49ITF9ZWxzZXtvPTAKcD1udWxs
+Cm49ITB9aWYocD09bnVsbClwPW5ldyBQLlJuKCIiKQptPW5ldyBQLmJ6KCExLHApCm0uYz1uCm0uTUUo
+YSxvLHMpCmlmKG0uZT4wKXtILlZqKFAucnIoIlVuZmluaXNoZWQgVVRGLTggb2N0ZXQgc2VxdWVuY2Ui
+LGEscykpCnAuYSs9SC5Mdyg2NTUzMykKbS5mPW0uZT1tLmQ9MH1sPXAuYQpyZXR1cm4gbC5jaGFyQ29k
+ZUF0KDApPT0wP2w6bH19ClAuYnoucHJvdG90eXBlPXsKTUU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
+cixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMsZz0iQmFkIFVURi04IGVuY29kaW5nIDB4Igp1LkwuYihh
+KQp0PWguZApzPWguZQpyPWguZgpoLmY9aC5lPWguZD0wCiRsYWJlbDAkMDpmb3IocT1KLlU2KGEpLHA9
+aC5iLG89YjshMDtvPWopeyRsYWJlbDEkMTppZihzPjApe2Rve2lmKG89PT1jKWJyZWFrICRsYWJlbDAk
+MApuPXEucShhLG8pCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uek0oKQppZigobiYxOTIp
+IT09MTI4KXttPVAucnIoZytDLmpuLkQ4KG4sMTYpLGEsbykKdGhyb3cgSC5iKG0pfWVsc2V7dD0odDw8
+NnxuJjYzKT4+PjA7LS1zOysrb319d2hpbGUocz4wKQptPXItMQppZihtPDB8fG0+PTQpcmV0dXJuIEgu
+T0goQy5HYixtKQppZih0PD1DLkdiW21dKXttPVAucnIoIk92ZXJsb25nIGVuY29kaW5nIG9mIDB4IitD
+LmpuLkQ4KHQsMTYpLGEsby1yLTEpCnRocm93IEguYihtKX1pZih0PjExMTQxMTEpe209UC5ycigiQ2hh
+cmFjdGVyIG91dHNpZGUgdmFsaWQgVW5pY29kZSByYW5nZTogMHgiK0Muam4uRDgodCwxNiksYSxvLXIt
+MSkKdGhyb3cgSC5iKG0pfWlmKCFoLmN8fHQhPT02NTI3OSlwLmErPUguTHcodCkKaC5jPSExfWZvciht
+PW88YzttOyl7bD1QLmNQKGEsbyxjKQppZihsPjApe2guYz0hMQprPW8rbApwLmErPVAuSE0oYSxvLGsp
+CmlmKGs9PT1jKWJyZWFrfWVsc2Ugaz1vCmo9aysxCm49cS5xKGEsaykKaWYodHlwZW9mIG4hPT0ibnVt
+YmVyIilyZXR1cm4gbi5KKCkKaWYobjwwKXtpPVAucnIoIk5lZ2F0aXZlIFVURi04IGNvZGUgdW5pdDog
+LTB4IitDLmpuLkQ4KC1uLDE2KSxhLGotMSkKdGhyb3cgSC5iKGkpfWVsc2V7aWYoKG4mMjI0KT09PTE5
+Mil7dD1uJjMxCnM9MQpyPTEKY29udGludWUgJGxhYmVsMCQwfWlmKChuJjI0MCk9PT0yMjQpe3Q9biYx
+NQpzPTIKcj0yCmNvbnRpbnVlICRsYWJlbDAkMH1pZigobiYyNDgpPT09MjQwJiZuPDI0NSl7dD1uJjcK
+cz0zCnI9Mwpjb250aW51ZSAkbGFiZWwwJDB9aT1QLnJyKGcrQy5qbi5EOChuLDE2KSxhLGotMSkKdGhy
+b3cgSC5iKGkpfX1icmVhayAkbGFiZWwwJDB9aWYocz4wKXtoLmQ9dApoLmU9cwpoLmY9cn19fQpQLldG
+LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCnUuZm8uYihhKQp0PXRoaXMuYgpz
+PXRoaXMuYQp0LmErPXMuYQpyPXQuYSs9SC5kKGEuYSkKdC5hPXIrIjogIgp0LmErPVAucChiKQpzLmE9
+IiwgIn0sCiRTOjQ3fQpQLmEyLnByb3RvdHlwZT17fQpQLmlQLnByb3RvdHlwZT17CkROOmZ1bmN0aW9u
+KGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0YW5jZW9mIFAuaVAmJnRoaXMuYT09
+PWIuYSYmdGhpcy5iPT09Yi5ifSwKWGs6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZihNYXRo
+LmFicyhzKTw9ODY0ZTEzKXQ9ITEKZWxzZSB0PSEwCmlmKHQpdGhyb3cgSC5iKFAueFkoIkRhdGVUaW1l
+IGlzIG91dHNpZGUgdmFsaWQgcmFuZ2U6ICIrcykpfSwKZ2k6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5h
+CnJldHVybih0XkMuam4ud0codCwzMCkpJjEwNzM3NDE4MjN9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMscz1QLkdxKEgudEoodCkpLHI9UC5oMChILk5TKHQpKSxxPVAuaDAoSC5qQSh0KSkscD1QLmgwKEgu
+S0wodCkpLG89UC5oMChILmNoKHQpKSxuPVAuaDAoSC5KZCh0KSksbT1QLlZ4KEgubzEodCkpCmlmKHQu
+YilyZXR1cm4gcysiLSIrcisiLSIrcSsiICIrcCsiOiIrbysiOiIrbisiLiIrbSsiWiIKZWxzZSByZXR1
+cm4gcysiLSIrcisiLSIrcSsiICIrcCsiOiIrbysiOiIrbisiLiIrbX19ClAuQ1AucHJvdG90eXBlPXt9
+ClAuWFMucHJvdG90eXBlPXt9ClAuQzYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmEKaWYodCE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAodCkKcmV0dXJuIkFzc2Vy
+dGlvbiBmYWlsZWQifX0KUC5uLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93IG9m
+IG51bGwuIn19ClAudS5wcm90b3R5cGU9ewpnWjpmdW5jdGlvbigpe3JldHVybiJJbnZhbGlkIGFyZ3Vt
+ZW50IisoIXRoaXMuYT8iKHMpIjoiIil9LApndTpmdW5jdGlvbigpe3JldHVybiIifSwKdzpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysiKSI6IiIKbz1wLmQK
+dD1vPT1udWxsPyIiOiI6ICIrSC5kKG8pCnM9cC5nWigpK24rdAppZighcC5hKXJldHVybiBzCnI9cC5n
+dSgpCnE9UC5wKHAuYikKcmV0dXJuIHMrcisiOiAiK3F9fQpQLmJKLnByb3RvdHlwZT17CmdaOmZ1bmN0
+aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcy5lCmlm
+KHI9PW51bGwpe3I9dGhpcy5mCnQ9ciE9bnVsbD8iOiBOb3QgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICIr
+SC5kKHIpOiIifWVsc2V7cz10aGlzLmYKaWYocz09bnVsbCl0PSI6IE5vdCBncmVhdGVyIHRoYW4gb3Ig
+ZXF1YWwgdG8gIitILmQocikKZWxzZSBpZihzPnIpdD0iOiBOb3QgaW4gcmFuZ2UgIitILmQocikrIi4u
+IitILmQocykrIiwgaW5jbHVzaXZlIgplbHNlIHQ9czxyPyI6IFZhbGlkIHZhbHVlIHJhbmdlIGlzIGVt
+cHR5IjoiOiBPbmx5IHZhbGlkIHZhbHVlIGlzICIrSC5kKHIpfXJldHVybiB0fX0KUC5lWS5wcm90b3R5
+cGU9ewpnWjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFyIHQs
+cz1ILlNjKHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkKaWYoczwwKXJl
+dHVybiI6IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgppZih0PT09MClyZXR1cm4i
+OiBubyBpbmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhhbiAi
+K0guZCh0KX0sCmdoOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1wLnByb3RvdHlwZT17Cnc6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxqPW5ldyBQLlJuKCIiKQpr
+LmE9IiIKZm9yKHQ9bC5jLHM9dC5sZW5ndGgscj0wLHE9IiIscD0iIjtyPHM7KytyLHA9IiwgIil7bz10
+W3JdCmouYT1xK3AKcT1qLmErPVAucChvKQprLmE9IiwgIn1sLmQuVSgwLG5ldyBQLldGKGssaikpCm49
+UC5wKGwuYSkKbT1qLncoMCkKdD0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICci
+K0guZChsLmIuYSkrIidcblJlY2VpdmVyOiAiK24rIlxuQXJndW1lbnRzOiBbIittKyJdIgpyZXR1cm4g
+dH19ClAudWIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iVW5zdXBwb3J0ZWQgb3BlcmF0
+aW9uOiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEK
+cmV0dXJuIHQhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIit0OiJVbmltcGxlbWVudGVkRXJyb3Ii
+fX0KUC5sai5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJCYWQgc3RhdGU6ICIrdGhpcy5h
+fX0KUC5VVi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQppZih0PT1udWxsKXJl
+dHVybiJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9uLiIKcmV0dXJuIkNvbmN1
+cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIrUC5wKHQpKyIuIn19ClAuazUucHJv
+dG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9LAokaVhTOjF9ClAuS1ku
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iU3RhY2sgT3ZlcmZsb3cifSwKJGlYUzoxfQpQ
+LmMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQ9PW51bGw/IlJl
+YWRpbmcgc3RhdGljIHZhcmlhYmxlIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24iOiJSZWFkaW5nIHN0
+YXRpYyB2YXJpYWJsZSAnIit0KyInIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24ifX0KUC5DRC5wcm90
+b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJFeGNlcHRpb246ICIrdGhpcy5hfX0KUC5hRS5wcm90
+b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMuYSxn
+PWghPW51bGwmJiIiIT09aD8iRm9ybWF0RXhjZXB0aW9uOiAiK0guZChoKToiRm9ybWF0RXhjZXB0aW9u
+IixmPXRoaXMuYyxlPXRoaXMuYgppZih0eXBlb2YgZT09InN0cmluZyIpe2lmKGYhPW51bGwpaD1mPDB8
+fGY+ZS5sZW5ndGgKZWxzZSBoPSExCmlmKGgpZj1udWxsCmlmKGY9PW51bGwpe3Q9ZS5sZW5ndGg+Nzg/
+Qy54Qi5OaihlLDAsNzUpKyIuLi4iOmUKcmV0dXJuIGcrIlxuIit0fWZvcihzPTEscj0wLHE9ITEscD0w
+O3A8ZjsrK3Ape289Qy54Qi5XZChlLHApCmlmKG89PT0xMCl7aWYociE9PXB8fCFxKSsrcwpyPXArMQpx
+PSExfWVsc2UgaWYobz09PTEzKXsrK3MKcj1wKzEKcT0hMH19Zz1zPjE/ZysoIiAoYXQgbGluZSAiK3Mr
+IiwgY2hhcmFjdGVyICIrKGYtcisxKSsiKVxuIik6ZysoIiAoYXQgY2hhcmFjdGVyICIrKGYrMSkrIilc
+biIpCm49ZS5sZW5ndGgKZm9yKHA9ZjtwPG47KytwKXtvPUMueEIuTzIoZSxwKQppZihvPT09MTB8fG89
+PT0xMyl7bj1wCmJyZWFrfX1pZihuLXI+NzgpaWYoZi1yPDc1KXttPXIrNzUKbD1yCms9IiIKaj0iLi4u
+In1lbHNle2lmKG4tZjw3NSl7bD1uLTc1Cm09bgpqPSIifWVsc2V7bD1mLTM2Cm09ZiszNgpqPSIuLi4i
+fWs9Ii4uLiJ9ZWxzZXttPW4KbD1yCms9IiIKaj0iIn1pPUMueEIuTmooZSxsLG0pCnJldHVybiBnK2sr
+aStqKyJcbiIrQy54Qi5JeCgiICIsZi1sK2subGVuZ3RoKSsiXlxuIn1lbHNlIHJldHVybiBmIT1udWxs
+P2crKCIgKGF0IG9mZnNldCAiK0guZChmKSsiKSIpOmd9fQpQLkVILnByb3RvdHlwZT17fQpQLktOLnBy
+b3RvdHlwZT17fQpQLmNYLnByb3RvdHlwZT17CkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxoKHRo
+aXMpCnJldHVybiBILksxKHRoaXMsdC5LKGMpLkMoIjEoY1guRSkiKS5iKGIpLHQuQygiY1guRSIpLGMp
+fSwKZXY6ZnVuY3Rpb24oYSxiKXt2YXIgdD1ILkxoKHRoaXMpCnJldHVybiBuZXcgSC5VNSh0aGlzLHQu
+QygiYTIoY1guRSkiKS5iKGIpLHQuQygiVTU8Y1guRT4iKSl9LApnaDpmdW5jdGlvbihhKXt2YXIgdCxz
+PXRoaXMuZ2t6KHRoaXMpCmZvcih0PTA7cy5tKCk7KSsrdApyZXR1cm4gdH0sCmdsMDpmdW5jdGlvbihh
+KXtyZXR1cm4hdGhpcy5na3oodGhpcykubSgpfSwKZ3I4OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5n
+a3oodGhpcykKaWYoIXMubSgpKXRocm93IEguYihILldwKCkpCnQ9cy5nUihzKQppZihzLm0oKSl0aHJv
+dyBILmIoSC5kVSgpKQpyZXR1cm4gdH0sClc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKUC5rMShiLCJp
+bmRleCIpCmZvcih0PXRoaXMuZ2t6KHRoaXMpLHM9MDt0Lm0oKTspe3I9dC5nUih0KQppZihiPT09cyly
+ZXR1cm4gcjsrK3N9dGhyb3cgSC5iKFAuQ2YoYix0aGlzLCJpbmRleCIsbnVsbCxzKSl9LAp3OmZ1bmN0
+aW9uKGEpe3JldHVybiBQLkVQKHRoaXMsIigiLCIpIil9fQpQLkFuLnByb3RvdHlwZT17fQpQLnpNLnBy
+b3RvdHlwZT17JGliUToxLCRpY1g6MX0KUC5aMC5wcm90b3R5cGU9e30KUC5OMy5wcm90b3R5cGU9ewp3
+OmZ1bmN0aW9uKGEpe3JldHVybiJNYXBFbnRyeSgiK0guZCh0aGlzLmEpKyI6ICIrSC5kKHRoaXMuYikr
+IikifSwKZ0czOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LApnbnc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IHRoaXMuYn19ClAuYzgucHJvdG90eXBlPXsKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuay5wcm90b3R5
+cGUuZ2kuY2FsbCh0aGlzLHRoaXMpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4ibnVsbCJ9fQpQLkZLLnBy
+b3RvdHlwZT17fQpQLmsucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpQLmssJGlrOjEsCkROOmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIHRoaXM9PT1ifSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIEguZVEodGhpcyl9LAp3
+OmZ1bmN0aW9uKGEpe3JldHVybiJJbnN0YW5jZSBvZiAnIitILmQoSC5NKHRoaXMpKSsiJyJ9LAplNzpm
+dW5jdGlvbihhLGIpe3Uuby5iKGIpCnRocm93IEguYihQLmxyKHRoaXMsYi5nV2EoKSxiLmduZCgpLGIu
+Z1ZtKCkpKX0sCnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudyh0aGlzKX19ClAuT2QucHJv
+dG90eXBlPXt9ClAuaWIucHJvdG90eXBlPXskaU9kOjF9ClAueHUucHJvdG90eXBlPXt9ClAuR3oucHJv
+dG90eXBlPXt9ClAucVUucHJvdG90eXBlPXskaXZYOjF9ClAuUm4ucHJvdG90eXBlPXsKZ2g6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1
+cm4gdC5jaGFyQ29kZUF0KDApPT0wP3Q6dH0sCiRpQkw6MX0KUC5HRC5wcm90b3R5cGU9e30KUC5uMS5w
+cm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUuZi5iKGEpCkgueShiKQp0PUou
+clkoYikuT1koYiwiPSIpCmlmKHQ9PT0tMSl7aWYoYiE9PSIiKUouQjIoYSxQLmt1KGIsMCxiLmxlbmd0
+aCx0aGlzLmEsITApLCIiKX1lbHNlIGlmKHQhPT0wKXtzPUMueEIuTmooYiwwLHQpCnI9Qy54Qi55bihi
+LHQrMSkKcT10aGlzLmEKSi5CMihhLFAua3UocywwLHMubGVuZ3RoLHEsITApLFAua3UociwwLHIubGVu
+Z3RoLHEsITApKX1yZXR1cm4gYX0sCiRTOjI0fQpQLmNTLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEs
+Yil7dGhyb3cgSC5iKFAucnIoIklsbGVnYWwgSVB2NCBhZGRyZXNzLCAiK2EsdGhpcy5hLGIpKX0sCiRT
+OjQ4fQpQLlZDLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAucnIoIklsbGVn
+YWwgSVB2NiBhZGRyZXNzLCAiK2EsdGhpcy5hLGIpKX0sCiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LiQyKGEsbnVsbCl9LAokUzozMX0KUC5KVC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0
+CmlmKGItYT40KXRoaXMuYS4kMigiYW4gSVB2NiBwYXJ0IGNhbiBvbmx5IGNvbnRhaW4gYSBtYXhpbXVt
+IG9mIDQgaGV4IGRpZ2l0cyIsYSkKdD1QLlFBKEMueEIuTmoodGhpcy5iLGEsYiksbnVsbCwxNikKaWYo
+dHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5KKCkKaWYodDwwfHx0PjY1NTM1KXRoaXMuYS4kMigi
+ZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIG9mIGAweDAuLjB4RkZGRmAiLGEpCnJldHVybiB0
+fSwKJFM6MzV9ClAuRG4ucHJvdG90eXBlPXsKZ2t1OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYn0sCmdK
+ZjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmMKaWYodD09bnVsbClyZXR1cm4iIgppZihDLnhCLm5DKHQs
+IlsiKSlyZXR1cm4gQy54Qi5Oaih0LDEsdC5sZW5ndGgtMSkKcmV0dXJuIHR9LApndHA6ZnVuY3Rpb24o
+YSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuIFAud0sodGhpcy5hKQpyZXR1cm4gdH0sCmd0
+UDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmYKcmV0dXJuIHQ9PW51bGw/IiI6dH0sCmdLYTpmdW5jdGlv
+bigpe3ZhciB0PXRoaXMucgpyZXR1cm4gdD09bnVsbD8iIjp0fSwKbm06ZnVuY3Rpb24oYSxiKXt2YXIg
+dCxzLHIscSxwLG8sbixtLGw9dGhpcwp1LlguYihudWxsKQp1LmIuYihiKQp0PWwuYQpzPXQ9PT0iZmls
+ZSIKcj1sLmIKcT1sLmQKcD1sLmMKaWYoIShwIT1udWxsKSlwPXIubGVuZ3RoIT09MHx8cSE9bnVsbHx8
+cz8iIjpudWxsCm89bC5lCmlmKCFzKW49cCE9bnVsbCYmby5sZW5ndGghPT0wCmVsc2Ugbj0hMAppZihu
+JiYhQy54Qi5uQyhvLCIvIikpbz0iLyIrbwptPVAubGUobnVsbCwwLDAsYikKcmV0dXJuIG5ldyBQLkRu
+KHQscixwLHEsbyxtLGwucil9LApnRmo6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMueAppZihzIT1udWxs
+KXJldHVybiBzCnQ9dGhpcy5lCmlmKHQubGVuZ3RoIT09MCYmQy54Qi5XZCh0LDApPT09NDcpdD1DLnhC
+LnluKHQsMSkKcz10PT09IiI/Qy54RDpQLkFGKG5ldyBILkE4KEguVk0odC5zcGxpdCgiLyIpLHUucyks
+dS5kTy5iKFAuUEgoKSksdS5kbyksdS5OKQp0aGlzLnNvNihzKQpyZXR1cm4gc30sCmdoWTpmdW5jdGlv
+bigpe3ZhciB0LHM9dGhpcwppZihzLlE9PW51bGwpe3Q9cy5mCnMuc1JIKG5ldyBQLkdqKFAuV1godD09
+bnVsbD8iIjp0KSx1LlcpKX1yZXR1cm4gcy5RfSwKSmg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
+LG8KZm9yKHQ9MCxzPTA7Qy54Qi5RaShiLCIuLi8iLHMpOyl7cys9MzsrK3R9cj1DLnhCLmNuKGEsIi8i
+KQp3aGlsZSghMCl7aWYoIShyPjAmJnQ+MCkpYnJlYWsKcT1DLnhCLlBrKGEsIi8iLHItMSkKaWYocTww
+KWJyZWFrCnA9ci1xCm89cCE9PTIKaWYoIW98fHA9PT0zKWlmKEMueEIuTzIoYSxxKzEpPT09NDYpbz0h
+b3x8Qy54Qi5PMihhLHErMik9PT00NgplbHNlIG89ITEKZWxzZSBvPSExCmlmKG8pYnJlYWs7LS10CnI9
+cX1yZXR1cm4gQy54Qi5pNyhhLHIrMSxudWxsLEMueEIueW4oYixzLTMqdCkpfSwKWkk6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8s
+bixtLGwsaz10aGlzLGo9bnVsbAppZihhLmdGaSgpLmxlbmd0aCE9PTApe3Q9YS5nRmkoKQppZihhLmdj
+aigpKXtzPWEuZ2t1KCkKcj1hLmdKZihhKQpxPWEuZ3hBKCk/YS5ndHAoYSk6an1lbHNle3E9agpyPXEK
+cz0iIn1wPVAueGUoYS5nSWkoYSkpCm89YS5nUUQoKT9hLmd0UChhKTpqfWVsc2V7dD1rLmEKaWYoYS5n
+Y2ooKSl7cz1hLmdrdSgpCnI9YS5nSmYoYSkKcT1QLndCKGEuZ3hBKCk/YS5ndHAoYSk6aix0KQpwPVAu
+eGUoYS5nSWkoYSkpCm89YS5nUUQoKT9hLmd0UChhKTpqfWVsc2V7cz1rLmIKcj1rLmMKcT1rLmQKaWYo
+YS5nSWkoYSk9PT0iIil7cD1rLmUKbz1hLmdRRCgpP2EuZ3RQKGEpOmsuZn1lbHNle2lmKGEuZ3RUKCkp
+cD1QLnhlKGEuZ0lpKGEpKQplbHNle249ay5lCmlmKG4ubGVuZ3RoPT09MClpZihyPT1udWxsKXA9dC5s
+ZW5ndGg9PT0wP2EuZ0lpKGEpOlAueGUoYS5nSWkoYSkpCmVsc2UgcD1QLnhlKCIvIithLmdJaShhKSkK
+ZWxzZXttPWsuSmgobixhLmdJaShhKSkKbD10Lmxlbmd0aD09PTAKaWYoIWx8fHIhPW51bGx8fEMueEIu
+bkMobiwiLyIpKXA9UC54ZShtKQplbHNlIHA9UC53RihtLCFsfHxyIT1udWxsKX19bz1hLmdRRCgpP2Eu
+Z3RQKGEpOmp9fX1yZXR1cm4gbmV3IFAuRG4odCxzLHIscSxwLG8sYS5nWjgoKT9hLmdLYSgpOmopfSwK
+Z2NqOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYyE9bnVsbH0sCmd4QTpmdW5jdGlvbigpe3JldHVybiB0
+aGlzLmQhPW51bGx9LApnUUQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mIT1udWxsfSwKZ1o4OmZ1bmN0
+aW9uKCl7cmV0dXJuIHRoaXMuciE9bnVsbH0sCmd0VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLm5DKHRo
+aXMuZSwiLyIpfSwKdDQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxxPXIuYQppZihxIT09IiImJnEh
+PT0iZmlsZSIpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSAi
+K0guZChxKSsiIFVSSSIpKQpxPXIuZgppZigocT09bnVsbD8iIjpxKSE9PSIiKXRocm93IEguYihQLkw0
+KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25l
+bnQiKSkKcT1yLnIKaWYoKHE9PW51bGw/IiI6cSkhPT0iIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4
+dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IikpCnQ9
+JC5PeCgpCmlmKEgub1QodCkpcT1QLm1uKHIpCmVsc2V7aWYoci5jIT1udWxsJiZyLmdKZihyKSE9PSIi
+KUguVmooUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBub24tV2luZG93cyBmaWxlIHBhdGggZnJvbSBhIGZp
+bGUgVVJJIHdpdGggYW4gYXV0aG9yaXR5IikpCnM9ci5nRmooKQpQLmtFKHMsITEpCnE9UC52ZyhDLnhC
+Lm5DKHIuZSwiLyIpPyIvIjoiIixzLCIvIikKcT1xLmNoYXJDb2RlQXQoMCk9PTA/cTpxfXJldHVybiBx
+fSwKdzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT10aGlzLHA9cS55CmlmKHA9PW51bGwpe3A9cS5hCnQ9
+cC5sZW5ndGghPT0wP3ArIjoiOiIiCnM9cS5jCnI9cz09bnVsbAppZighcnx8cD09PSJmaWxlIil7cD10
+KyIvLyIKdD1xLmIKaWYodC5sZW5ndGghPT0wKXA9cCt0KyJAIgppZighcilwKz1zCnQ9cS5kCmlmKHQh
+PW51bGwpcD1wKyI6IitILmQodCl9ZWxzZSBwPXQKcCs9cS5lCnQ9cS5mCmlmKHQhPW51bGwpcD1wKyI/
+Iit0CnQ9cS5yCmlmKHQhPW51bGwpcD1wKyIjIit0CnA9cS55PXAuY2hhckNvZGVBdCgwKT09MD9wOnB9
+cmV0dXJuIHB9LApETjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCmlmKGI9PW51bGwpcmV0dXJu
+ITEKaWYocj09PWIpcmV0dXJuITAKaWYodS5ELmMoYikpaWYoci5hPT1iLmdGaSgpKWlmKHIuYyE9bnVs
+bD09PWIuZ2NqKCkpaWYoci5iPT1iLmdrdSgpKWlmKHIuZ0pmKHIpPT1iLmdKZihiKSlpZihyLmd0cChy
+KT09Yi5ndHAoYikpaWYoci5lPT09Yi5nSWkoYikpe3Q9ci5mCnM9dD09bnVsbAppZighcz09PWIuZ1FE
+KCkpe2lmKHMpdD0iIgppZih0PT09Yi5ndFAoYikpe3Q9ci5yCnM9dD09bnVsbAppZighcz09PWIuZ1o4
+KCkpe2lmKHMpdD0iIgp0PXQ9PT1iLmdLYSgpfWVsc2UgdD0hMX1lbHNlIHQ9ITF9ZWxzZSB0PSExfWVs
+c2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVs
+c2UgdD0hMQpyZXR1cm4gdH0sCmdpOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuegpyZXR1cm4gdD09bnVs
+bD90aGlzLno9Qy54Qi5naSh0aGlzLncoMCkpOnR9LApzbzY6ZnVuY3Rpb24oYSl7dGhpcy54PXUuYS5i
+KGEpfSwKc1JIOmZ1bmN0aW9uKGEpe3RoaXMuUT11LmYuYihhKX0sCiRpaUQ6MSwKZ0ZpOmZ1bmN0aW9u
+KCl7cmV0dXJuIHRoaXMuYX0sCmdJaTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5lfX0KUC5lMS5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXt0aHJvdyBILmIoUC5ycigiSW52YWxpZCBwb3J0Iix0aGlzLmEs
+dGhpcy5iKzEpKX0sCiRTOjE1fQpQLk5ZLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PSJJ
+bGxlZ2FsIHBhdGggY2hhcmFjdGVyICIKSC55KGEpCmlmKEouemwoYSwiLyIpKWlmKHRoaXMuYSl0aHJv
+dyBILmIoUC54WSh0K2EpKQplbHNlIHRocm93IEguYihQLkw0KHQrYSkpfSwKJFM6MTV9ClAuUloucHJv
+dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuZVAoQy5aSixhLEMueE0sITEpfSwKJFM6NX0K
+UC5NRS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYixzPXRoaXMuYQp0LmEr
+PXMuYQpzLmE9IiYiCnM9dC5hKz1ILmQoUC5lUChDLkYzLGEsQy54TSwhMCkpCmlmKGIhPW51bGwmJmIu
+bGVuZ3RoIT09MCl7dC5hPXMrIj0iCnQuYSs9SC5kKFAuZVAoQy5GMyxiLEMueE0sITApKX19LAokUzox
+Nn0KUC55NS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC55KGEpCmlmKGI9PW51
+bGx8fHR5cGVvZiBiPT0ic3RyaW5nIil0aGlzLmEuJDIoYSxILnkoYikpCmVsc2UgZm9yKHQ9Si5JVCh1
+LlIuYihiKSkscz10aGlzLmE7dC5tKCk7KXMuJDIoYSxILnkodC5nUih0KSkpfSwKJFM6MTN9ClAuUEUu
+cHJvdG90eXBlPXsKZ2xSOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzLG89bnVsbCxuPXAuYwpp
+ZihuIT1udWxsKXJldHVybiBuCm49cC5iCmlmKDA+PW4ubGVuZ3RoKXJldHVybiBILk9IKG4sMCkKdD1w
+LmEKbj1uWzBdKzEKcz1DLnhCLlhVKHQsIj8iLG4pCnI9dC5sZW5ndGgKaWYocz49MCl7cT1QLnVPKHQs
+cysxLHIsQy5WQywhMSkKcj1zfWVsc2UgcT1vCnJldHVybiBwLmM9bmV3IFAucWUoImRhdGEiLG8sbyxv
+LFAudU8odCxuLHIsQy5XZCwhMSkscSxvKX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmIKaWYo
+MD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywwKQp0PXRoaXMuYQpyZXR1cm4gc1swXT09PS0xPyJkYXRh
+OiIrdDp0fX0KUC5xMy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFVpbnQ4QXJy
+YXkoOTYpfSwKJFM6MjJ9ClAueUkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlz
+LmEKaWYoYT49dC5sZW5ndGgpcmV0dXJuIEguT0godCxhKQp0PXRbYV0KSi5DTSh0LDAsOTYsYikKcmV0
+dXJuIHR9LAokUzo0OX0KUC5jNi5wcm90b3R5cGU9ewokMzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxy
+LHEKZm9yKHQ9Yi5sZW5ndGgscz1hLmxlbmd0aCxyPTA7cjx0Oysrcil7cT1DLnhCLldkKGIscileOTYK
+aWYocT49cylyZXR1cm4gSC5PSChhLHEpCmFbcV09Y319fQpQLnFkLnByb3RvdHlwZT17CiQzOmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdCxzLHIscQpmb3IodD1DLnhCLldkKGIsMCkscz1DLnhCLldkKGIsMSkscj1h
+Lmxlbmd0aDt0PD1zOysrdCl7cT0odF45Nik+Pj4wCmlmKHE+PXIpcmV0dXJuIEguT0goYSxxKQphW3Fd
+PWN9fX0KUC5VZi5wcm90b3R5cGU9ewpnY2o6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jPjB9LApneEE6
+ZnVuY3Rpb24oKXt2YXIgdCxzCmlmKHRoaXMuYz4wKXt0PXRoaXMuZAppZih0eXBlb2YgdCE9PSJudW1i
+ZXIiKXJldHVybiB0LlQoKQpzPXRoaXMuZQppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBILnBZ
+KHMpCnM9dCsxPHMKdD1zfWVsc2UgdD0hMQpyZXR1cm4gdH0sCmdRRDpmdW5jdGlvbigpe3ZhciB0PXRo
+aXMuZgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkooKQpyZXR1cm4gdDx0aGlzLnJ9LApn
+Wjg6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5yPHRoaXMuYS5sZW5ndGh9LApnTnc6ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpcy5iPT09NCYmQy54Qi5uQyh0aGlzLmEsImZpbGUiKX0sCmdXWjpmdW5jdGlvbigpe3Jl
+dHVybiB0aGlzLmI9PT00JiZDLnhCLm5DKHRoaXMuYSwiaHR0cCIpfSwKZ1JlOmZ1bmN0aW9uKCl7cmV0
+dXJuIHRoaXMuYj09PTUmJkMueEIubkModGhpcy5hLCJodHRwcyIpfSwKZ3RUOmZ1bmN0aW9uKCl7cmV0
+dXJuIEMueEIuUWkodGhpcy5hLCIvIix0aGlzLmUpfSwKZ0ZpOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlz
+LHI9InBhY2thZ2UiLHE9cy5iCmlmKHE8PTApcmV0dXJuIiIKdD1zLngKaWYodCE9bnVsbClyZXR1cm4g
+dAppZihzLmdXWigpKXE9cy54PSJodHRwIgplbHNlIGlmKHMuZ1JlKCkpe3MueD0iaHR0cHMiCnE9Imh0
+dHBzIn1lbHNlIGlmKHMuZ053KCkpe3MueD0iZmlsZSIKcT0iZmlsZSJ9ZWxzZSBpZihxPT09NyYmQy54
+Qi5uQyhzLmEscikpe3MueD1yCnE9cn1lbHNle3E9Qy54Qi5OaihzLmEsMCxxKQpzLng9cX1yZXR1cm4g
+cX0sCmdrdTpmdW5jdGlvbigpe3ZhciB0PXRoaXMuYyxzPXRoaXMuYiszCnJldHVybiB0PnM/Qy54Qi5O
+aih0aGlzLmEscyx0LTEpOiIifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwpyZXR1cm4gdD4w
+P0MueEIuTmoodGhpcy5hLHQsdGhpcy5kKToiIn0sCmd0cDpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMK
+aWYocy5neEEoKSl7dD1zLmQKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5UKCkKcmV0dXJu
+IFAuUUEoQy54Qi5OaihzLmEsdCsxLHMuZSksbnVsbCxudWxsKX1pZihzLmdXWigpKXJldHVybiA4MApp
+ZihzLmdSZSgpKXJldHVybiA0NDMKcmV0dXJuIDB9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIu
+TmoodGhpcy5hLHRoaXMuZSx0aGlzLmYpfSwKZ3RQOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZixzPXRo
+aXMucgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkooKQpyZXR1cm4gdDxzP0MueEIuTmoo
+dGhpcy5hLHQrMSxzKToiIn0sCmdLYTpmdW5jdGlvbigpe3ZhciB0PXRoaXMucixzPXRoaXMuYQpyZXR1
+cm4gdDxzLmxlbmd0aD9DLnhCLnluKHMsdCsxKToiIn0sCmdGajpmdW5jdGlvbigpe3ZhciB0LHMscj10
+aGlzLmUscT10aGlzLmYscD10aGlzLmEKaWYoQy54Qi5RaShwLCIvIixyKSl7aWYodHlwZW9mIHIhPT0i
+bnVtYmVyIilyZXR1cm4gci5UKCk7KytyfWlmKHI9PXEpcmV0dXJuIEMueEQKdD1ILlZNKFtdLHUucykK
+cz1yCndoaWxlKCEwKXtpZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkooKQppZih0eXBlb2Yg
+cSE9PSJudW1iZXIiKXJldHVybiBILnBZKHEpCmlmKCEoczxxKSlicmVhawppZihDLnhCLk8yKHAscyk9
+PT00Nyl7Qy5ObS5BKHQsQy54Qi5OaihwLHIscykpCnI9cysxfSsrc31DLk5tLkEodCxDLnhCLk5qKHAs
+cixxKSkKcmV0dXJuIFAuQUYodCx1Lk4pfSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuZgpp
+Zih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkooKQppZihzPj10LnIpcmV0dXJuIEMuV08KcmV0
+dXJuIG5ldyBQLkdqKFAuV1godC5ndFAodCkpLHUuVyl9LAprWDpmdW5jdGlvbihhKXt2YXIgdCxzPXRo
+aXMuZAppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLlQoKQp0PXMrMQpyZXR1cm4gdCthLmxl
+bmd0aD09PXRoaXMuZSYmQy54Qi5RaSh0aGlzLmEsYSx0KX0sCk45OmZ1bmN0aW9uKCl7dmFyIHQ9dGhp
+cyxzPXQucixyPXQuYQppZihzPj1yLmxlbmd0aClyZXR1cm4gdApyZXR1cm4gbmV3IFAuVWYoQy54Qi5O
+aihyLDAscyksdC5iLHQuYyx0LmQsdC5lLHQuZixzLHQueCl9LApubTpmdW5jdGlvbihhLGIpe3ZhciB0
+LHMscixxLHAsbyxuLG0sbCxrLGo9dGhpcyxpPW51bGwKdS5YLmIobnVsbCkKdS5iLmIoYikKdD1qLmdG
+aSgpCnM9dD09PSJmaWxlIgpyPWouYwpxPXI+MD9DLnhCLk5qKGouYSxqLmIrMyxyKToiIgpwPWouZ3hB
+KCk/ai5ndHAoaik6aQpyPWouYwppZihyPjApbz1DLnhCLk5qKGouYSxyLGouZCkKZWxzZSBvPXEubGVu
+Z3RoIT09MHx8cCE9bnVsbHx8cz8iIjppCnI9ai5hCm49Qy54Qi5OaihyLGouZSxqLmYpCmlmKCFzKW09
+byE9bnVsbCYmbi5sZW5ndGghPT0wCmVsc2UgbT0hMAppZihtJiYhQy54Qi5uQyhuLCIvIikpbj0iLyIr
+bgpsPVAubGUoaSwwLDAsYikKbT1qLnIKaz1tPHIubGVuZ3RoP0MueEIueW4ocixtKzEpOmkKcmV0dXJu
+IG5ldyBQLkRuKHQscSxvLHAsbixsLGspfSwKWkk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMubVMoUC5o
+SyhhKSl9LAptUzpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNlb2YgUC5VZilyZXR1cm4gdGhpcy51MSh0
+aGlzLGEpCnJldHVybiB0aGlzLnZzKCkubVMoYSl9LAp1MTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixx
+LHAsbyxuLG0sbCxrLGosaSxoLGcsZixlPWIuYgppZihlPjApcmV0dXJuIGIKdD1iLmMKaWYodD4wKXtz
+PWEuYgppZihzPD0wKXJldHVybiBiCmlmKGEuZ053KCkpcj1iLmUhPWIuZgplbHNlIGlmKGEuZ1daKCkp
+cj0hYi5rWCgiODAiKQplbHNlIHI9IWEuZ1JlKCl8fCFiLmtYKCI0NDMiKQppZihyKXtxPXMrMQpwPUMu
+eEIuTmooYS5hLDAscSkrQy54Qi55bihiLmEsZSsxKQplPWIuZAppZih0eXBlb2YgZSE9PSJudW1iZXIi
+KXJldHVybiBlLlQoKQpvPWIuZQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBvLlQoKQpuPWIu
+ZgppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVybiBuLlQoKQpyZXR1cm4gbmV3IFAuVWYocCxzLHQr
+cSxlK3EsbytxLG4rcSxiLnIrcSxhLngpfWVsc2UgcmV0dXJuIHRoaXMudnMoKS5tUyhiKX1tPWIuZQpl
+PWIuZgppZihtPT1lKXt0PWIucgppZih0eXBlb2YgZSE9PSJudW1iZXIiKXJldHVybiBlLkooKQppZihl
+PHQpe3M9YS5mCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSE4oKQpxPXMtZQpyZXR1cm4g
+bmV3IFAuVWYoQy54Qi5OaihhLmEsMCxzKStDLnhCLnluKGIuYSxlKSxhLmIsYS5jLGEuZCxhLmUsZStx
+LHQrcSxhLngpfWU9Yi5hCmlmKHQ8ZS5sZW5ndGgpe3M9YS5yCnJldHVybiBuZXcgUC5VZihDLnhCLk5q
+KGEuYSwwLHMpK0MueEIueW4oZSx0KSxhLmIsYS5jLGEuZCxhLmUsYS5mLHQrKHMtdCksYS54KX1yZXR1
+cm4gYS5OOSgpfXQ9Yi5hCmlmKEMueEIuUWkodCwiLyIsbSkpe3M9YS5lCmlmKHR5cGVvZiBzIT09Im51
+bWJlciIpcmV0dXJuIHMuSE4oKQppZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBILnBZKG0pCnE9
+cy1tCnA9Qy54Qi5OaihhLmEsMCxzKStDLnhCLnluKHQsbSkKaWYodHlwZW9mIGUhPT0ibnVtYmVyIily
+ZXR1cm4gZS5UKCkKcmV0dXJuIG5ldyBQLlVmKHAsYS5iLGEuYyxhLmQscyxlK3EsYi5yK3EsYS54KX1s
+PWEuZQprPWEuZgppZihsPT1rJiZhLmM+MCl7Zm9yKDtDLnhCLlFpKHQsIi4uLyIsbSk7KXtpZih0eXBl
+b2YgbSE9PSJudW1iZXIiKXJldHVybiBtLlQoKQptKz0zfWlmKHR5cGVvZiBsIT09Im51bWJlciIpcmV0
+dXJuIGwuSE4oKQppZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBILnBZKG0pCnE9bC1tKzEKcD1D
+LnhCLk5qKGEuYSwwLGwpKyIvIitDLnhCLnluKHQsbSkKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1
+cm4gZS5UKCkKcmV0dXJuIG5ldyBQLlVmKHAsYS5iLGEuYyxhLmQsbCxlK3EsYi5yK3EsYS54KX1qPWEu
+YQpmb3IoaT1sO0MueEIuUWkoaiwiLi4vIixpKTspe2lmKHR5cGVvZiBpIT09Im51bWJlciIpcmV0dXJu
+IGkuVCgpCmkrPTN9aD0wCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLlQo
+KQpnPW0rMwppZih0eXBlb2YgZSE9PSJudW1iZXIiKXJldHVybiBILnBZKGUpCmlmKCEoZzw9ZSYmQy54
+Qi5RaSh0LCIuLi8iLG0pKSlicmVhazsrK2gKbT1nfWY9IiIKd2hpbGUoITApe2lmKHR5cGVvZiBrIT09
+Im51bWJlciIpcmV0dXJuIGsub3MoKQppZih0eXBlb2YgaSE9PSJudW1iZXIiKXJldHVybiBILnBZKGkp
+CmlmKCEoaz5pKSlicmVhazstLWsKaWYoQy54Qi5PMihqLGspPT09NDcpe2lmKGg9PT0wKXtmPSIvIgpi
+cmVha30tLWgKZj0iLyJ9fWlmKGs9PT1pJiZhLmI8PTAmJiFDLnhCLlFpKGosIi8iLGwpKXttLT1oKjMK
+Zj0iIn1xPWstbStmLmxlbmd0aApyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihqLDAsaykrZitDLnhCLnlu
+KHQsbSksYS5iLGEuYyxhLmQsbCxlK3EsYi5yK3EsYS54KX0sCnQ0OmZ1bmN0aW9uKCl7dmFyIHQscyxy
+LHEscD10aGlzCmlmKHAuYj49MCYmIXAuZ053KCkpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0
+IGEgZmlsZSBwYXRoIGZyb20gYSAiK0guZChwLmdGaSgpKSsiIFVSSSIpKQp0PXAuZgpzPXAuYQppZih0
+eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkooKQppZih0PHMubGVuZ3RoKXtpZih0PHAucil0aHJv
+dyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgcXVl
+cnkgY29tcG9uZW50IikpCnRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBm
+cm9tIGEgVVJJIHdpdGggYSBmcmFnbWVudCBjb21wb25lbnQiKSl9cj0kLk94KCkKaWYoSC5vVChyKSl0
+PVAubW4ocCkKZWxzZXtxPXAuZAppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBILnBZKHEpCmlm
+KHAuYzxxKUguVmooUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBub24tV2luZG93cyBmaWxlIHBhdGggZnJv
+bSBhIGZpbGUgVVJJIHdpdGggYW4gYXV0aG9yaXR5IikpCnQ9Qy54Qi5OaihzLHAuZSx0KX1yZXR1cm4g
+dH0sCmdpOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMueQpyZXR1cm4gdD09bnVsbD90aGlzLnk9Qy54Qi5n
+aSh0aGlzLmEpOnR9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKaWYodGhpcz09
+PWIpcmV0dXJuITAKcmV0dXJuIHUuRC5jKGIpJiZ0aGlzLmE9PT1iLncoMCl9LAp2czpmdW5jdGlvbigp
+e3ZhciB0PXRoaXMscz1udWxsLHI9dC5nRmkoKSxxPXQuZ2t1KCkscD10LmM+MD90LmdKZih0KTpzLG89
+dC5neEEoKT90Lmd0cCh0KTpzLG49dC5hLG09dC5mLGw9Qy54Qi5OaihuLHQuZSxtKSxrPXQucgppZih0
+eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQptPW08az90Lmd0UCh0KTpzCnJldHVybiBuZXcg
+UC5EbihyLHEscCxvLGwsbSxrPG4ubGVuZ3RoP3QuZ0thKCk6cyl9LAp3OmZ1bmN0aW9uKGEpe3JldHVy
+biB0aGlzLmF9LAokaWlEOjF9ClAucWUucHJvdG90eXBlPXt9ClcucUUucHJvdG90eXBlPXt9ClcuWWUu
+cHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5HaC5wcm90b3R5cGU9
+ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAokaUdoOjF9ClcuZlkucHJvdG90eXBlPXsK
+dzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfX0KVy5uQi5wcm90b3R5cGU9eyRpbkI6MX0KVy5B
+ei5wcm90b3R5cGU9eyRpQXo6MX0KVy5QVS5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEudmFsdWV9fQpXLlFQLnByb3RvdHlwZT17JGlRUDoxfQpXLklGLnByb3RvdHlwZT17CmdudzpmdW5j
+dGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcubngucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofX0KVy5SZC5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFs
+dWV9fQpXLmtSLnByb3RvdHlwZT17JGlrUjoxfQpXLlRmLnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEp
+e3JldHVybiBhLmxlbmd0aH19ClcubHcucHJvdG90eXBlPXskaWx3OjF9Clcub0oucHJvdG90eXBlPXsK
+Z2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5pZC5wcm90b3R5cGU9e30KVy5Cdy5wcm90
+b3R5cGU9e30KVy5vNC5wcm90b3R5cGU9e30KVy5IUy5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXty
+ZXR1cm4gYS5sZW5ndGh9fQpXLlZvLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52
+YWx1ZX19ClcuRmgucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5j
+eC5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9fQpXLlNiLnByb3RvdHlw
+ZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVtILlNjKGIpXX0sCmdoOmZ1bmN0aW9uKGEpe3JldHVy
+biBhLmxlbmd0aH19ClcuUUYucHJvdG90eXBlPXt9ClcuTmgucHJvdG90eXBlPXsKdzpmdW5jdGlvbihh
+KXtyZXR1cm4gU3RyaW5nKGEpfX0KVy5Gdi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4g
+YS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3Ro
+KXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlv
+bihhLGIsYyl7SC5TYyhiKQp1LnEuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
ZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVu
-Z3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaUx5OjEsCiRp
-ek06MX0KVy5sOC5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaWw4
-OjF9ClcuQXMucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3JldHVybiBhLmdldEl0ZW0oSC5jKGIp
-KX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe2Euc2V0SXRlbShiLGMpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0
-LHMKdS5XLmEoYikKZm9yKHQ9MDshMDsrK3Qpe3M9YS5rZXkodCkKaWYocz09bnVsbClyZXR1cm4KYi4k
-MihzLGEuZ2V0SXRlbShzKSl9fSwKZ3Y6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5WTShbXSx1LnMpCnRoaXMu
-VShhLG5ldyBXLmNYKHQpKQpyZXR1cm4gdH0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
-CiRpWjA6MX0KVy5jWC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3JldHVybiBDLk5tLkEodGhp
-cy5hLGEpfSwKJFM6MTZ9ClcuYmsucHJvdG90eXBlPXsKZ0czOmZ1bmN0aW9uKGEpe3JldHVybiBhLmtl
-eX19ClcuV1cucHJvdG90eXBlPXskaVdXOjF9ClcuVGIucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxi
-LGMsZCl7dmFyIHQscwppZigiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2Uu
-cHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixjLGQpCnQ9Vy5VOSgiPHRhYmxlPiIrSC5kKGIpKyI8
-L3RhYmxlPiIsYyxkKQpzPWRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpzLnRvU3RyaW5n
-CnQudG9TdHJpbmcKbmV3IFcuZTcocykuRlYoMCxuZXcgVy5lNyh0KSkKcmV0dXJuIHN9fQpXLkl2LnBy
-b3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKCJjcmVhdGVDb250ZXh0
-dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMs
-ZCkKdD1kb2N1bWVudApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0
-ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQp
-CnIudG9TdHJpbmcKdD1uZXcgVy5lNyhyKQpxPXQuZ3I4KHQpCnMudG9TdHJpbmcKcS50b1N0cmluZwpu
-ZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHEpKQpyZXR1cm4gc319ClcuQlQucHJvdG90eXBlPXsKcjY6
-ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGlu
-IHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1kb2N1bWVudApz
-PXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0ZUVsZW1lbnQoInRhYmxl
-IiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQpCnMudG9TdHJpbmcKci50
-b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHIpKQpyZXR1cm4gc319ClcuZlgucHJvdG90
-eXBlPXsKcGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKYS50ZXh0Q29udGVudD1udWxsCnQ9YS5jb250
-ZW50CnQudG9TdHJpbmcKSi5iVCh0KQpzPXRoaXMucjYoYSxiLG51bGwsYykKYS5jb250ZW50LmFwcGVu
-ZENoaWxkKHMpfSwKWUM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LAokaWZY
-OjF9ClcuRkIucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5BMS5w
-cm90b3R5cGU9eyRpQTE6MX0KVy5NTi5wcm90b3R5cGU9eyRpTU46MX0KVy5YMC5wcm90b3R5cGU9ewpn
-azpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihi
-Pj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0
-dXJuIGFbYl19LAp0OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCnUuYzcuYShjKQp0aHJvdyBILmIoUC5M
-NCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24o
-YSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6
-MSwKJGlYajoxLAokaUx5OjEsCiRpek06MX0KVy5uSi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXty
-ZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEu
-bGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0OmZ1
-bmN0aW9uKGEsYixjKXtILldZKGIpCnUuYTAuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2ln
-biBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+
-PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaUx5
-OjEsCiRpek06MX0KVy5tei5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
-fQpXLmEzLnByb3RvdHlwZT17JGlhMzoxfQpXLmNpLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5s
-ZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVu
-Y3Rpb24oYSxiLGMpe0guV1koYikKdS5hSy5hKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWdu
-IGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49
-YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpTHk6
-MSwKJGl6TToxfQpXLmNuLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19
-ClcudzYucHJvdG90eXBlPXt9ClcuRmoucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gU3Ry
-aW5nKGEpfX0KVy52Ri5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpX
-Lk9pLnByb3RvdHlwZT17CmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhdGlvbn0sCiRpT2k6MSwK
-JGl2NjoxfQpXLkNtLnByb3RvdHlwZT17JGlDbToxfQpXLkNRLnByb3RvdHlwZT17CmdudzpmdW5jdGlv
-bihhKXtyZXR1cm4gYS52YWx1ZX0sCiRpQ1E6MX0KVy5QUi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihh
-KXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+
-PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0
-OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCnUuZzUuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFz
-c2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8
-fGI+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAok
-aUx5OjEsCiRpek06MX0KVy53NC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5n
-bGUgKCIrSC5kKGEubGVmdCkrIiwgIitILmQoYS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0gu
-ZChhLmhlaWdodCl9LApETjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGI9PW51bGwpcmV0dXJuITEKaWYo
-dS5xLmIoYikpaWYoYS5sZWZ0PT1iLmxlZnQpaWYoYS50b3A9PWIudG9wKXt0PUouUkUoYikKdD1hLndp
-ZHRoPT10LmdQKGIpJiZhLmhlaWdodD09dC5nTChiKX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0h
-MQpyZXR1cm4gdH0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBXLnJFKEouSShhLmxlZnQpLEouSShhLnRv
-cCksSi5JKGEud2lkdGgpLEouSShhLmhlaWdodCkpfSwKZ0w6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuaGVp
-Z2h0fSwKZ1A6ZnVuY3Rpb24oYSl7cmV0dXJuIGEud2lkdGh9fQpXLkYyLnByb3RvdHlwZT17CmdrOmZ1
-bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4w
-IT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4g
-YVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5kUC5hKGMpCnRocm93IEguYihQLkw0KCJD
+Z3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAok
+aXpNOjF9ClcuSUIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgiK0gu
+ZChhLmxlZnQpKyIsICIrSC5kKGEudG9wKSsiKSAiK0guZCh0aGlzLmdQKGEpKSsiIHggIitILmQodGhp
+cy5nTChhKSl9LApETjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGI9PW51bGwpcmV0dXJuITEKaWYodS5x
+LmMoYikpaWYoYS5sZWZ0PT09Yi5sZWZ0KWlmKGEudG9wPT09Yi50b3Ape3Q9Si5SRShiKQp0PXRoaXMu
+Z1AoYSk9PT10LmdQKGIpJiZ0aGlzLmdMKGEpPT09dC5nTChiKX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVs
+c2UgdD0hMQpyZXR1cm4gdH0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBXLnJFKEMuQ0QuZ2koYS5sZWZ0
+KSxDLkNELmdpKGEudG9wKSxDLkNELmdpKHRoaXMuZ1AoYSkpLEMuQ0QuZ2kodGhpcy5nTChhKSkpfSwK
+Z0w6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuaGVpZ2h0fSwKZ1A6ZnVuY3Rpb24oYSl7cmV0dXJuIGEud2lk
+dGh9LAokaXRuOjF9ClcuWWwucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3Ro
+fSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBI
+LmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMp
+e0guU2MoYikKSC55KGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1t
+dXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJu
+IEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5u
+Ny5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApnbnc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIGEudmFsdWV9fQpXLnd6LnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLmEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkguU2MoYikKdD10aGlzLmEKaWYoYjww
+fHxiPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LGIpCnJldHVybiB0aGlzLiR0aS5kLmIodFtiXSl9LApZ
+OmZ1bmN0aW9uKGEsYixjKXtILlNjKGIpCnRoaXMuJHRpLmQuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fu
+bm90IG1vZGlmeSBsaXN0IikpfX0KVy5jdi5wcm90b3R5cGU9ewpnUWc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IG5ldyBXLmk3KGEpfSwKZ0REOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5JNChhKX0sCnNERDpmdW5j
+dGlvbihhLGIpe3ZhciB0CnUuWC5iKGIpCnQ9dGhpcy5nREQoYSkKdC5WMSgwKQp0LkZWKDAsYil9LAp3
+OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxvY2FsTmFtZX0sCnRuOmZ1bmN0aW9uKGEpe3ZhciB0PSEhYS5z
+Y3JvbGxJbnRvVmlld0lmTmVlZGVkCmlmKHQpYS5zY3JvbGxJbnRvVmlld0lmTmVlZGVkKCkKZWxzZSBh
+LnNjcm9sbEludG9WaWV3KCl9LApuejpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHM9dGhpcy5yNihh
+LGMsZCxlKQpzd2l0Y2goYi50b0xvd2VyQ2FzZSgpKXtjYXNlImJlZm9yZWJlZ2luIjphLnBhcmVudE5v
+ZGUuaW5zZXJ0QmVmb3JlKHMsYSkKYnJlYWsKY2FzZSJhZnRlcmJlZ2luIjp0PWEuY2hpbGROb2Rlcwph
+Lmluc2VydEJlZm9yZShzLHQubGVuZ3RoPjA/dFswXTpudWxsKQpicmVhawpjYXNlImJlZm9yZWVuZCI6
+YS5hcHBlbmRDaGlsZChzKQpicmVhawpjYXNlImFmdGVyZW5kIjphLnBhcmVudE5vZGUuaW5zZXJ0QmVm
+b3JlKHMsYS5uZXh0U2libGluZykKYnJlYWsKZGVmYXVsdDpILlZqKFAueFkoIkludmFsaWQgcG9zaXRp
+b24gIitiKSl9fSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoYz09bnVsbCl7aWYo
+ZD09bnVsbCl7dD0kLmx0CmlmKHQ9PW51bGwpe3Q9SC5WTShbXSx1Lm0pCnM9bmV3IFcudkQodCkKQy5O
+bS5BKHQsVy5UdyhudWxsKSkKQy5ObS5BKHQsVy5CbCgpKQokLmx0PXMKZD1zfWVsc2UgZD10fXQ9JC5F
+VQppZih0PT1udWxsKXt0PW5ldyBXLktvKGQpCiQuRVU9dApjPXR9ZWxzZXt0LmE9ZApjPXR9fWVsc2Ug
+aWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9yIGNhbiBvbmx5IGJlIHBhc3NlZCBpZiB0
+cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVsbCl7dD1kb2N1bWVudApzPXQuaW1wbGVt
+ZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKQokLnhvPXMKJC5CTz1zLmNyZWF0ZVJhbmdlKCkK
+cz0kLnhvLmNyZWF0ZUVsZW1lbnQoImJhc2UiKQp1LmNSLmIocykKcy5ocmVmPXQuYmFzZVVSSQokLnhv
+LmhlYWQuYXBwZW5kQ2hpbGQocyl9dD0kLnhvCmlmKHQuYm9keT09bnVsbCl7cz10LmNyZWF0ZUVsZW1l
+bnQoImJvZHkiKQp0LmJvZHk9dS5rLmIocyl9dD0kLnhvCmlmKHUuay5jKGEpKXI9dC5ib2R5CmVsc2V7
+cj10LmNyZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5kQ2hpbGQocil9aWYoImNy
+ZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSYmIUMuTm0udGco
+Qy5TcSxhLnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhyKQpxPSQuQk8uY3JlYXRlQ29u
+dGV4dHVhbEZyYWdtZW50KGIpfWVsc2V7ci5pbm5lckhUTUw9YgpxPSQueG8uY3JlYXRlRG9jdW1lbnRG
+cmFnbWVudCgpCmZvcig7dD1yLmZpcnN0Q2hpbGQsdCE9bnVsbDspcS5hcHBlbmRDaGlsZCh0KX10PSQu
+eG8uYm9keQppZihyPT1udWxsP3QhPW51bGw6ciE9PXQpSi5MdChyKQpjLlBuKHEpCmRvY3VtZW50LmFk
+b3B0Tm9kZShxKQpyZXR1cm4gcX0sCkFIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhpcy5yNihhLGIs
+YyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnBrOmZ1bmN0aW9uKGEsYixj
+KXthLnRleHRDb250ZW50PW51bGwKYS5hcHBlbmRDaGlsZCh0aGlzLnI2KGEsYixudWxsLGMpKX0sCllD
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKZ1ZsOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBuZXcgVy5ldShhLCJjbGljayIsITEsdS5RKX0sCiRpY3Y6MSwKZ25zOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLnRhZ05hbWV9fQpXLkN2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB1Lmgu
+Yyh1LkEuYihhKSl9LAokUzoyNX0KVy5RSS5wcm90b3R5cGU9eyRpUUk6MX0KVy5lYS5wcm90b3R5cGU9
+eyRpZWE6MX0KVy5EMC5wcm90b3R5cGU9ewpPbjpmdW5jdGlvbihhLGIsYyxkKXt1LkYuYihjKQppZihj
+IT1udWxsKXRoaXMubihhLGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLk9uKGEs
+YixjLG51bGwpfSwKbjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5hZGRFdmVudExpc3RlbmVyKGIs
+SC50Uih1LkYuYihjKSwxKSxkKX0sCiRpRDA6MX0KVy5UNS5wcm90b3R5cGU9eyRpVDU6MX0KVy5YVi5w
+cm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7
+SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51
+bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhiKQp1Lk8uYihjKQp0
+aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0s
+Clc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJu
+IGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjEsCiRpWFY6MX0KVy53Si5wcm90b3R5
+cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmg0LnByb3RvdHlwZT17CmdoOmZ1
+bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuR08ucHJvdG90eXBlPXskaUdPOjF9ClcuSkMucHJv
+dG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5ici5wcm90b3R5cGU9ewpn
+aDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLnhuLnByb3RvdHlwZT17CmdoOmZ1bmN0aW9u
+KGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlmKGI+Pj4wIT09Ynx8
+Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19
+LApZOmZ1bmN0aW9uKGEsYixjKXtILlNjKGIpCnUuQS5iKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3Qg
+YXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI8
+MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajox
+LAokaWNYOjEsCiRpek06MX0KVy5WYi5wcm90b3R5cGU9e30KVy5PNy5wcm90b3R5cGU9ewplbzpmdW5j
+dGlvbihhLGIsYyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaU83OjF9ClcuYlUucHJvdG90eXBl
+PXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuc2V0UmVxdWVzdEhlYWRlcihILnkoYSksSC55KGIpKX0s
+CiRTOjEyfQpXLmhILnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAKdS5wLmIo
+YSkKdD10aGlzLmEKcz10LnN0YXR1cwppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLnRCKCkK
+cj1zPj0yMDAmJnM8MzAwCnE9cz4zMDcmJnM8NDAwCnM9cnx8cz09PTB8fHM9PT0zMDR8fHEKcD10aGlz
+LmIKaWYocylwLmFNKDAsdCkKZWxzZSBwLnBtKGEpfSwKJFM6Mjd9Clcud2EucHJvdG90eXBlPXt9Clcu
+U2cucHJvdG90eXBlPXskaVNnOjF9ClcuSksucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVy
+biBhLnZhbHVlfSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVybiBhLndlYmtpdEVudHJpZXN9fQpXLkhMLnBy
+b3RvdHlwZT17CmdHMzpmdW5jdGlvbihhKXtyZXR1cm4gYS5rZXl9fQpXLndQLnByb3RvdHlwZT17Cmdu
+dzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcudTgucHJvdG90eXBlPXsKZ0RyOmZ1bmN0aW9u
+KGEpe2lmKCJvcmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILmQoYS5wcm90b2NvbCkr
+Ii8vIitILmQoYS5ob3N0KX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpdTg6MX0K
+Vy56Ni5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmxLLnByb3Rv
+dHlwZT17JGlsSzoxfQpXLlFiLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1
+ZX19ClcuUzAucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3JldHVybiBQLm1SKGEuZ2V0KEgueShi
+KSkpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKdS5ULmIoYikKdD1hLmVudHJpZXMoKQpmb3IoOyEw
+Oyl7cz10Lm5leHQoKQppZihzLmRvbmUpcmV0dXJuCmIuJDIocy52YWx1ZVswXSxQLm1SKHMudmFsdWVb
+MV0pKX19LApndjpmdW5jdGlvbihhKXt2YXIgdD1ILlZNKFtdLHUucykKdGhpcy5VKGEsbmV3IFcuRkEo
+dCkpCnJldHVybiB0fSwKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuc2l6ZX0sClk6ZnVuY3Rpb24oYSxi
+LGMpe3Rocm93IEguYihQLkw0KCJOb3Qgc3VwcG9ydGVkIikpfSwKJGlaMDoxfQpXLkZBLnByb3RvdHlw
+ZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEMuTm0uQSh0aGlzLmEsYSl9LAokUzo4fQpXLnoyLnBy
+b3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gUC5tUihhLmdldChILnkoYikpKX0sClU6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzCnUuVC5iKGIpCnQ9YS5lbnRyaWVzKCkKZm9yKDshMDspe3M9dC5uZXh0
+KCkKaWYocy5kb25lKXJldHVybgpiLiQyKHMudmFsdWVbMF0sUC5tUihzLnZhbHVlWzFdKSl9fSwKZ3Y6
+ZnVuY3Rpb24oYSl7dmFyIHQ9SC5WTShbXSx1LnMpCnRoaXMuVShhLG5ldyBXLnVxKHQpKQpyZXR1cm4g
+dH0sCmdoOmZ1bmN0aW9uKGEpe3JldHVybiBhLnNpemV9LApZOmZ1bmN0aW9uKGEsYixjKXt0aHJvdyBI
+LmIoUC5MNCgiTm90IHN1cHBvcnRlZCIpKX0sCiRpWjA6MX0KVy51cS5wcm90b3R5cGU9ewokMjpmdW5j
+dGlvbihhLGIpe3JldHVybiBDLk5tLkEodGhpcy5hLGEpfSwKJFM6OH0KVy5BVy5wcm90b3R5cGU9eyRp
+QVc6MX0KVy5ETS5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1
+bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLkNm
+KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhi
+KQp1LmNJLmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFi
+bGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5P
+SChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6MSwKJGl6TToxfQpXLkFqLnBy
+b3RvdHlwZT17JGlBajoxfQpXLmU3LnByb3RvdHlwZT17CmdyODpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmEscz10LmNoaWxkTm9kZXMubGVuZ3RoCmlmKHM9PT0wKXRocm93IEguYihQLlBWKCJObyBlbGVtZW50
+cyIpKQppZihzPjEpdGhyb3cgSC5iKFAuUFYoIk1vcmUgdGhhbiBvbmUgZWxlbWVudCIpKQpyZXR1cm4g
+dC5maXJzdENoaWxkfSwKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmVoLmIoYikKdD1iLmEK
+cz10aGlzLmEKaWYodCE9PXMpZm9yKHI9dC5jaGlsZE5vZGVzLmxlbmd0aCxxPTA7cTxyOysrcSlzLmFw
+cGVuZENoaWxkKHQuZmlyc3RDaGlsZCkKcmV0dXJufSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKSC5T
+YyhiKQp0PXRoaXMuYQp0LnJlcGxhY2VDaGlsZCh1LkEuYihjKSxDLnQ1LnEodC5jaGlsZE5vZGVzLGIp
+KX0sCmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEuY2hpbGROb2RlcwpyZXR1cm4gbmV3IFcuVzko
+dCx0Lmxlbmd0aCxILnpLKHQpLkMoIlc5PEdtLkU+IikpfSwKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
+aXMuYS5jaGlsZE5vZGVzLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCnJldHVybiBDLnQ1
+LnEodGhpcy5hLmNoaWxkTm9kZXMsYil9fQpXLnVILnByb3RvdHlwZT17CndnOmZ1bmN0aW9uKGEpe3Zh
+ciB0PWEucGFyZW50Tm9kZQppZih0IT1udWxsKXQucmVtb3ZlQ2hpbGQoYSl9LApENDpmdW5jdGlvbihh
+KXt2YXIgdApmb3IoO3Q9YS5maXJzdENoaWxkLHQhPW51bGw7KWEucmVtb3ZlQ2hpbGQodCl9LAp3OmZ1
+bmN0aW9uKGEpe3ZhciB0PWEubm9kZVZhbHVlCnJldHVybiB0PT1udWxsP3RoaXMuVUcoYSk6dH0sCiRp
+dUg6MX0KVy5CSC5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1
+bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLkNm
+KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhi
+KQp1LkEuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJs
+ZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILk9I
+KGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9ClcuUWwucHJv
+dG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5HWC5wcm90b3R5cGU9ewpn
+bnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9fQpXLlNOLnByb3RvdHlwZT17fQpXLkhELnByb3Rv
+dHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuY2wucHJvdG90eXBlPXskaWNs
+OjEsCmdoOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuRXYucHJvdG90eXBlPXsKZ2g6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAh
+PT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4g
+YVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe0guU2MoYikKdS5oZS5iKGMpCnRocm93IEguYihQLkw0KCJD
YW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIp
-e2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAok
-aVhqOjEsCiRpTHk6MSwKJGl6TToxfQpXLnJoLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVy
-biBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5n
-dGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rp
-b24oYSxiLGMpe0guV1koYikKdS5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxl
-bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
-bmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAok
-aXpNOjF9ClcuTE8ucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpm
-dW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50
-KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKdDpmdW5jdGlvbihhLGIsYyl7SC5XWShi
-KQp1LmdmLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFi
-bGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5r
-KGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9ClcuYjEucHJv
-dG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gu
-V1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50KGIsYSxudWxsLG51bGws
-bnVsbCkpCnJldHVybiBhW2JdfSwKdDpmdW5jdGlvbihhLGIsYyl7SC5XWShiKQp1LmduLmEoYykKdGhy
+e2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwK
+JGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5Mci5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEudmFsdWV9fQpXLktSLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1
+ZX19ClcuZXcucHJvdG90eXBlPXskaWV3OjF9ClcucDgucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIp
+e3JldHVybiBQLm1SKGEuZ2V0KEgueShiKSkpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKdS5ULmIo
+YikKdD1hLmVudHJpZXMoKQpmb3IoOyEwOyl7cz10Lm5leHQoKQppZihzLmRvbmUpcmV0dXJuCmIuJDIo
+cy52YWx1ZVswXSxQLm1SKHMudmFsdWVbMV0pKX19LApndjpmdW5jdGlvbihhKXt2YXIgdD1ILlZNKFtd
+LHUucykKdGhpcy5VKGEsbmV3IFcuaWkodCkpCnJldHVybiB0fSwKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEuc2l6ZX0sClk6ZnVuY3Rpb24oYSxiLGMpe3Rocm93IEguYihQLkw0KCJOb3Qgc3VwcG9ydGVkIikp
+fSwKJGlaMDoxfQpXLmlpLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEMuTm0uQSh0
+aGlzLmEsYSl9LAokUzo4fQpXLmxwLnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxl
+bmd0aH0sCmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuU1YucHJvdG90eXBlPXskaVNW
+OjF9ClcuTWsucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5j
+dGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihi
+LGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe0guU2MoYikK
+dS5mWS5iKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxl
+IExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0go
+YSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5ZNC5wcm90
+b3R5cGU9eyRpWTQ6MX0KVy5Obi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
+dGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93
+IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIs
+Yyl7SC5TYyhiKQp1LmY3LmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBv
+ZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aCly
+ZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6MSwKJGl6TTox
+fQpXLmw4LnByb3RvdHlwZT17JGlsODoxLApnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpX
+LkFzLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5nZXRJdGVtKEgueShiKSl9LApZ
+OmZ1bmN0aW9uKGEsYixjKXthLnNldEl0ZW0oYixjKX0sClU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnUu
+VS5iKGIpCmZvcih0PTA7ITA7Kyt0KXtzPWEua2V5KHQpCmlmKHM9PW51bGwpcmV0dXJuCmIuJDIocyxh
+LmdldEl0ZW0ocykpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLlUoYSxu
+ZXcgVy53USh0KSkKcmV0dXJuIHR9LApnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaVow
+OjF9Clcud1EucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy5ObS5BKHRoaXMuYSxh
+KX0sCiRTOjE2fQpXLmJrLnByb3RvdHlwZT17CmdHMzpmdW5jdGlvbihhKXtyZXR1cm4gYS5rZXl9fQpX
+LldXLnByb3RvdHlwZT17JGlXVzoxfQpXLlRiLnByb3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixjLGQp
+e3ZhciB0LHMKaWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3Rv
+dHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIsYyxkKQp0PVcuVTkoIjx0YWJsZT4iK0guZChiKSsiPC90YWJs
+ZT4iLGMsZCkKcz1kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKcy50b1N0cmluZwp0LnRv
+U3RyaW5nCm5ldyBXLmU3KHMpLkZWKDAsbmV3IFcuZTcodCkpCnJldHVybiBzfX0KVy5Jdi5wcm90b3R5
+cGU9ewpyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscQppZigiY3JlYXRlQ29udGV4dHVhbEZy
+YWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixjLGQpCnQ9
+ZG9jdW1lbnQKcz10LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQp0PUMuSWUucjYodC5jcmVhdGVFbGVt
+ZW50KCJ0YWJsZSIpLGIsYyxkKQp0LnRvU3RyaW5nCnQ9bmV3IFcuZTcodCkKcj10LmdyOCh0KQpyLnRv
+U3RyaW5nCnQ9bmV3IFcuZTcocikKcT10LmdyOCh0KQpzLnRvU3RyaW5nCnEudG9TdHJpbmcKbmV3IFcu
+ZTcocykuRlYoMCxuZXcgVy5lNyhxKSkKcmV0dXJuIHN9fQpXLkJULnByb3RvdHlwZT17CnI2OmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciB0LHMscgppZigiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5k
+b3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixjLGQpCnQ9ZG9jdW1lbnQKcz10LmNy
+ZWF0ZURvY3VtZW50RnJhZ21lbnQoKQp0PUMuSWUucjYodC5jcmVhdGVFbGVtZW50KCJ0YWJsZSIpLGIs
+YyxkKQp0LnRvU3RyaW5nCnQ9bmV3IFcuZTcodCkKcj10LmdyOCh0KQpzLnRvU3RyaW5nCnIudG9TdHJp
+bmcKbmV3IFcuZTcocykuRlYoMCxuZXcgVy5lNyhyKSkKcmV0dXJuIHN9fQpXLmZYLnByb3RvdHlwZT17
+CnBrOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCmEudGV4dENvbnRlbnQ9bnVsbAp0PWEuY29udGVudAp0
+LnRvU3RyaW5nCkouYlQodCkKcz10aGlzLnI2KGEsYixudWxsLGMpCmEuY29udGVudC5hcHBlbmRDaGls
+ZChzKX0sCllDOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKJGlmWDoxfQpX
+LkZCLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuQTEucHJvdG90
+eXBlPXskaUExOjF9ClcuTU4ucHJvdG90eXBlPXskaU1OOjF9ClcuWDAucHJvdG90eXBlPXsKZ2g6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAh
+PT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4g
+YVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe0guU2MoYikKdS5jNy5iKGMpCnRocm93IEguYihQLkw0KCJD
+YW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIp
+e2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwK
+JGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5uSi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1
+cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVu
+Z3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5j
+dGlvbihhLGIsYyl7SC5TYyhiKQp1LmEwLmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24g
+ZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1h
+Lmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6
+MSwKJGl6TToxfQpXLm16LnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19
+ClcuYTMucHJvdG90eXBlPXskaWEzOjF9ClcuY2kucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxl
+bmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sClk6ZnVu
+Y3Rpb24oYSxiLGMpe0guU2MoYikKdS5hSy5iKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWdu
+IGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49
+YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaWNY
+OjEsCiRpek06MX0KVy5jbi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
+fQpXLnc2LnByb3RvdHlwZT17fQpXLkZqLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0
+cmluZyhhKX19ClcudkYucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0K
+Vy5PaS5wcm90b3R5cGU9ewpnbVc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubG9jYXRpb259LAokaU9pOjEs
+CiRpdjY6MX0KVy5DbS5wcm90b3R5cGU9eyRpQ206MX0KVy5DUS5wcm90b3R5cGU9eyRpQ1E6MSwKZ253
+OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5QUi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihh
+KXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+
+PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwK
+WTpmdW5jdGlvbihhLGIsYyl7SC5TYyhiKQp1Lmc1LmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBh
+c3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjww
+fHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEs
+CiRpY1g6MSwKJGl6TToxfQpXLnc0LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJlY3Rh
+bmdsZSAoIitILmQoYS5sZWZ0KSsiLCAiK0guZChhLnRvcCkrIikgIitILmQoYS53aWR0aCkrIiB4ICIr
+SC5kKGEuaGVpZ2h0KX0sCkROOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYj09bnVsbClyZXR1cm4hMQpp
+Zih1LnEuYyhiKSlpZihhLmxlZnQ9PT1iLmxlZnQpaWYoYS50b3A9PT1iLnRvcCl7dD1KLlJFKGIpCnQ9
+YS53aWR0aD09PXQuZ1AoYikmJmEuaGVpZ2h0PT09dC5nTChiKX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVs
+c2UgdD0hMQpyZXR1cm4gdH0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBXLnJFKEMuQ0QuZ2koYS5sZWZ0
+KSxDLkNELmdpKGEudG9wKSxDLkNELmdpKGEud2lkdGgpLEMuQ0QuZ2koYS5oZWlnaHQpKX0sCmdMOmZ1
+bmN0aW9uKGEpe3JldHVybiBhLmhlaWdodH0sCmdQOmZ1bmN0aW9uKGEpe3JldHVybiBhLndpZHRofX0K
+Vy5GMi5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9u
+KGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxu
+dWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhiKQp1LmRQ
+LmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlz
+dC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIp
+CnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6MSwKJGl6TToxfQpXLnJoLnByb3RvdHlw
+ZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIp
+CmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxs
+KSkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXtILlNjKGIpCnUuQS5iKGMpCnRocm93IEgu
+YihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5j
+dGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0s
+CiRpYlE6MSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5MTy5wcm90b3R5cGU9ewpnaDpmdW5jdGlv
+bihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8
+fGI+PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2Jd
+fSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhiKQp1LmdmLmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5v
+dCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYo
+YjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhq
+OjEsCiRpY1g6MSwKJGl6TToxfQpXLmIxLnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiBh
+Lmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgp
+dGhyb3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9u
+KGEsYixjKXtILlNjKGIpCnUuZ24uYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
+ZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVu
+Z3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAok
+aXpNOjF9ClcuYVQucHJvdG90eXBlPXsKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAKdS5VLmIo
+YikKZm9yKHQ9dGhpcy5ndih0aGlzKSxzPXQubGVuZ3RoLHI9dGhpcy5hLHE9MDtxPHQubGVuZ3RoO3Qu
+bGVuZ3RoPT09c3x8KDAsSC5saykodCksKytxKXtwPXRbcV0KYi4kMihwLHIuZ2V0QXR0cmlidXRlKHAp
+KX19LApndjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMuYS5hdHRyaWJ1dGVzLG89SC5WTShb
+XSx1LnMpCmZvcih0PXAubGVuZ3RoLHM9dS5oOSxyPTA7cjx0Oysrcil7aWYocj49cC5sZW5ndGgpcmV0
+dXJuIEguT0gocCxyKQpxPXMuYihwW3JdKQppZihxLm5hbWVzcGFjZVVSST09bnVsbClDLk5tLkEobyxx
+Lm5hbWUpfXJldHVybiBvfX0KVy5pNy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRo
+aXMuYS5nZXRBdHRyaWJ1dGUoSC55KGIpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5zZXRBdHRy
+aWJ1dGUoYixjKX0sCmdoOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmd2KHRoaXMpLmxlbmd0aH19Clcu
+U3kucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEuYS5nZXRBdHRyaWJ1dGUo
+ImRhdGEtIit0aGlzLlMoSC55KGIpKSl9LApZOmZ1bmN0aW9uKGEsYixjKXt0aGlzLmEuYS5zZXRBdHRy
+aWJ1dGUoImRhdGEtIit0aGlzLlMoYiksYyl9LApVOmZ1bmN0aW9uKGEsYil7dGhpcy5hLlUoMCxuZXcg
+Vy5LUyh0aGlzLHUuVS5iKGIpKSl9LApndjpmdW5jdGlvbihhKXt2YXIgdD1ILlZNKFtdLHUucykKdGhp
+cy5hLlUoMCxuZXcgVy5BMyh0aGlzLHQpKQpyZXR1cm4gdH0sCmdoOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLmd2KHRoaXMpLmxlbmd0aH0sCnhxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1ILlZNKGEuc3BsaXQo
+Ii0iKSx1LnMpCmZvcih0PTE7dDxyLmxlbmd0aDsrK3Qpe3M9clt0XQppZihzLmxlbmd0aD4wKUMuTm0u
+WShyLHQsc1swXS50b1VwcGVyQ2FzZSgpK0ouS1YocywxKSl9cmV0dXJuIEMuTm0uelYociwiIil9LApT
+OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAKZm9yKHQ9YS5sZW5ndGgscz0wLHI9IiI7czx0Oysrcyl7
+cT1hW3NdCnA9cS50b0xvd2VyQ2FzZSgpCnI9KHEhPT1wJiZzPjA/cisiLSI6cikrcH1yZXR1cm4gci5j
+aGFyQ29kZUF0KDApPT0wP3I6cn19ClcuS1MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihK
+LnJZKGEpLm5DKGEsImRhdGEtIikpdGhpcy5iLiQyKHRoaXMuYS54cShDLnhCLnluKGEsNSkpLGIpfSwK
+JFM6MTJ9ClcuQTMucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihKLnJZKGEpLm5DKGEsImRh
+dGEtIikpQy5ObS5BKHRoaXMuYix0aGlzLmEueHEoQy54Qi55bihhLDUpKSl9LAokUzoxMn0KVy5JNC5w
+cm90b3R5cGU9ewpERzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9UC5Mcyh1Lk4pCmZvcih0PXRoaXMu
+YS5jbGFzc05hbWUuc3BsaXQoIiAiKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtxPUouVDAodFtyXSkK
+aWYocS5sZW5ndGghPT0wKXAuQSgwLHEpfXJldHVybiBwfSwKcDU6ZnVuY3Rpb24oYSl7dGhpcy5hLmNs
+YXNzTmFtZT11LkMuYihhKS56VigwLCIgIil9LApnaDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNs
+YXNzTGlzdC5sZW5ndGh9LApWMTpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPSIifSwKdGc6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdD10aGlzLmEuY2xhc3NMaXN0LmNvbnRhaW5zKGIpCnJldHVybiB0fSwKQTpm
+dW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYS5jbGFzc0xpc3Qscz10LmNvbnRhaW5zKGIpCnQuYWRkKGIp
+CnJldHVybiFzfSwKUno6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEuY2xhc3NMaXN0LHM9dC5jb250
+YWlucyhiKQp0LnJlbW92ZShiKQpyZXR1cm4gc30sCkZWOmZ1bmN0aW9uKGEsYil7Vy5UTih0aGlzLmEs
+dS5YLmIoYikpfX0KVy5Gay5wcm90b3R5cGU9e30KVy5STy5wcm90b3R5cGU9e30KVy5ldS5wcm90b3R5
+cGU9e30KVy54Qy5wcm90b3R5cGU9e30KVy52Ti5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1
+cm4gdGhpcy5hLiQxKHUuQi5iKGEpKX0sCiRTOjI5fQpXLkpRLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9u
+KGEpe3ZhciB0CmlmKCQub3IuYT09PTApe2Zvcih0PTA7dDwyNjI7Kyt0KSQub3IuWSgwLEMuY21bdF0s
+Vy5wUygpKQpmb3IodD0wO3Q8MTI7Kyt0KSQub3IuWSgwLEMuQklbdF0sVy5WNCgpKX19LAppMDpmdW5j
+dGlvbihhKXtyZXR1cm4gJC5BTigpLnRnKDAsVy5yUyhhKSl9LApFYjpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQ9JC5vci5xKDAsSC5kKFcuclMoYSkpKyI6OiIrYikKaWYodD09bnVsbCl0PSQub3IucSgwLCIqOjoi
+K2IpCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIEgueGQodC4kNChhLGIsYyx0aGlzKSl9LAokaWtG
+OjF9ClcuR20ucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5XOShhLHRoaXMu
+Z2goYSksSC56SyhhKS5DKCJXOTxHbS5FPiIpKX19ClcudkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24o
+YSl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBXLlV2KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXty
+ZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuRWcoYSxiLGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5lLmIoYSkuaTAodGhpcy5hKX0sCiRTOjE3fQpXLkVn
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB1LmUuYihhKS5FYih0aGlzLmEsdGhpcy5i
+LHRoaXMuYyl9LAokUzoxN30KVy5tNi5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIsYyxkKXt2YXIg
+dCxzLHIKdGhpcy5hLkZWKDAsYykKdD1iLmV2KDAsbmV3IFcuRW8oKSkKcz1iLmV2KDAsbmV3IFcuV2so
+KSkKdGhpcy5iLkZWKDAsdCkKcj10aGlzLmMKci5GVigwLEMueEQpCnIuRlYoMCxzKX0sCmkwOmZ1bmN0
+aW9uKGEpe3JldHVybiB0aGlzLmEudGcoMCxXLnJTKGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dD10aGlzLHM9Vy5yUyhhKSxyPXQuYwppZihyLnRnKDAsSC5kKHMpKyI6OiIrYikpcmV0dXJuIHQuZC5E
+dChjKQplbHNlIGlmKHIudGcoMCwiKjo6IitiKSlyZXR1cm4gdC5kLkR0KGMpCmVsc2V7cj10LmIKaWYo
+ci50ZygwLEguZChzKSsiOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLCIqOjoiK2IpKXJldHVy
+biEwCmVsc2UgaWYoci50ZygwLEguZChzKSsiOjoqIikpcmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6
+OioiKSlyZXR1cm4hMH1yZXR1cm4hMX0sCiRpa0Y6MX0KVy5Fby5wcm90b3R5cGU9ewokMTpmdW5jdGlv
+bihhKXtyZXR1cm4hQy5ObS50ZyhDLkJJLEgueShhKSl9LAokUzo5fQpXLldrLnByb3RvdHlwZT17CiQx
+OmZ1bmN0aW9uKGEpe3JldHVybiBDLk5tLnRnKEMuQkksSC55KGEpKX0sCiRTOjl9ClcuY3QucHJvdG90
+eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe2lmKHRoaXMuakYoYSxiLGMpKXJldHVybiEwCmlmKGI9PT0i
+dGVtcGxhdGUiJiZjPT09IiIpcmV0dXJuITAKaWYoYS5nZXRBdHRyaWJ1dGUoInRlbXBsYXRlIik9PT0i
+IilyZXR1cm4gdGhpcy5lLnRnKDAsYikKcmV0dXJuITF9fQpXLklBLnByb3RvdHlwZT17CiQxOmZ1bmN0
+aW9uKGEpe3JldHVybiJURU1QTEFURTo6IitILmQoSC55KGEpKX0sCiRTOjV9ClcuT3cucHJvdG90eXBl
+PXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5ldy5jKGEpKXJldHVybiExCnQ9dS5nNy5jKGEpCmlm
+KHQmJlcuclMoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0dXJuITEKaWYodClyZXR1cm4hMApyZXR1cm4h
+MX0sCkViOmZ1bmN0aW9uKGEsYixjKXtpZihiPT09ImlzInx8Qy54Qi5uQyhiLCJvbiIpKXJldHVybiEx
+CnJldHVybiB0aGlzLmkwKGEpfSwKJGlrRjoxfQpXLlc5LnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2
+YXIgdD10aGlzLHM9dC5jKzEscj10LmIKaWYoczxyKXt0LnNwKEoudzIodC5hLHMpKQp0LmM9cwpyZXR1
+cm4hMH10LnNwKG51bGwpCnQuYz1yCnJldHVybiExfSwKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
+ZH0sCnNwOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0aS5kLmIoYSl9LAokaUFuOjF9ClcuZFcucHJv
+dG90eXBlPXsKZ21XOmZ1bmN0aW9uKGEpe3JldHVybiBXLnpYKHRoaXMuYS5sb2NhdGlvbil9LAokaUQw
+OjEsCiRpdjY6MX0KVy5GYi5wcm90b3R5cGU9e30KVy5rRi5wcm90b3R5cGU9e30KVy5tay5wcm90b3R5
+cGU9eyRpV1E6MX0KVy5Lby5wcm90b3R5cGU9ewpQbjpmdW5jdGlvbihhKXtuZXcgVy5mbSh0aGlzKS4k
+MihhLG51bGwpfSwKRVA6ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKUouTHQoYSkKZWxzZSBiLnJlbW92
+ZUNoaWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89ITAsbj1udWxsLG09bnVs
+bAp0cnl7bj1KLmlnKGEpCm09bi5hLmdldEF0dHJpYnV0ZSgiaXMiKQp1LmguYihhKQp0PWZ1bmN0aW9u
+KGMpe2lmKCEoYy5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2RlTWFwKSlyZXR1cm4gdHJ1ZQp2
+YXIgbD1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hpbGQmJmMubGFzdENoaWxkIT09bFtsLmxlbmd0aC0x
+XSlyZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlmKCEoYy5jaGlsZHJlbiBpbnN0YW5jZW9mIEhUTUxD
+b2xsZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNlb2YgTm9kZUxpc3QpKXJldHVybiB0cnVlCnZhciBr
+PTAKaWYoYy5jaGlsZHJlbilrPWMuY2hpbGRyZW4ubGVuZ3RoCmZvcih2YXIgaj0wO2o8aztqKyspe3Zh
+ciBpPWMuY2hpbGRyZW5bal0KaWYoaS5pZD09J2F0dHJpYnV0ZXMnfHxpLm5hbWU9PSdhdHRyaWJ1dGVz
+J3x8aS5pZD09J2xhc3RDaGlsZCd8fGkubmFtZT09J2xhc3RDaGlsZCd8fGkuaWQ9PSdjaGlsZHJlbid8
+fGkubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZX1yZXR1cm4gZmFsc2V9KGEpCm89SC5vVCh0KT8h
+MDohKGEuYXR0cmlidXRlcyBpbnN0YW5jZW9mIE5hbWVkTm9kZU1hcCl9Y2F0Y2gocSl7SC5SdShxKX1z
+PSJlbGVtZW50IHVucHJpbnRhYmxlIgp0cnl7cz1KLmooYSl9Y2F0Y2gocSl7SC5SdShxKX10cnl7cj1X
+LnJTKGEpCnRoaXMua1IodS5oLmIoYSksYixvLHMscix1LkcuYihuKSxILnkobSkpfWNhdGNoKHEpe2lm
+KEguUnUocSkgaW5zdGFuY2VvZiBQLnUpdGhyb3cgcQplbHNle3RoaXMuRVAoYSxiKQp3aW5kb3cKcD0i
+UmVtb3ZpbmcgY29ycnVwdGVkIGVsZW1lbnQgIitILmQocykKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRl
+ZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCl9fX0sCmtSOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcp
+e3ZhciB0LHMscixxLHAsbyxuPXRoaXMKaWYoYyl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBl
+bGVtZW50IGR1ZSB0byBjb3JydXB0ZWQgYXR0cmlidXRlcyBvbiA8IitkKyI+IgppZih0eXBlb2YgY29u
+c29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59aWYoIW4uYS5pMChh
+KSl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIGVsZW1lbnQgPCIrSC5kKGUp
+KyI+IGZyb20gIitILmQoYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25z
+b2xlLndhcm4odCkKcmV0dXJufWlmKGchPW51bGwpaWYoIW4uYS5FYihhLCJpcyIsZykpe24uRVAoYSxi
+KQp3aW5kb3cKdD0iUmVtb3ZpbmcgZGlzYWxsb3dlZCB0eXBlIGV4dGVuc2lvbiA8IitILmQoZSkrJyBp
+cz0iJytnKyciPicKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndh
+cm4odCkKcmV0dXJufXQ9Zi5ndihmKQpzPUguVk0odC5zbGljZSgwKSxILnQ2KHQpLkMoImpkPDE+Iikp
+CmZvcihyPWYuZ3YoZikubGVuZ3RoLTEsdD1mLmE7cj49MDstLXIpe2lmKHI+PXMubGVuZ3RoKXJldHVy
+biBILk9IKHMscikKcT1zW3JdCnA9bi5hCm89Si5jSChxKQpILnkocSkKaWYoIXAuRWIoYSxvLHQuZ2V0
+QXR0cmlidXRlKHEpKSl7d2luZG93CnA9IlJlbW92aW5nIGRpc2FsbG93ZWQgYXR0cmlidXRlIDwiK0gu
+ZChlKSsiICIrcSsnPSInK0guZCh0LmdldEF0dHJpYnV0ZShxKSkrJyI+JwppZih0eXBlb2YgY29uc29s
+ZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKQp0LnJlbW92ZUF0dHJpYnV0ZShxKX19
+aWYodS5hVy5jKGEpKW4uUG4oYS5jb250ZW50KX0sCiRpb246MX0KVy5mbS5wcm90b3R5cGU9ewokMjpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhpcy5hCnN3aXRjaChhLm5vZGVUeXBlKXtjYXNlIDE6
+cC5JNChhLGIpCmJyZWFrCmNhc2UgODpjYXNlIDExOmNhc2UgMzpjYXNlIDQ6YnJlYWsKZGVmYXVsdDpw
+LkVQKGEsYil9dD1hLmxhc3RDaGlsZApmb3IocD11LkE7bnVsbCE9dDspe3M9bnVsbAp0cnl7cz10LnBy
+ZXZpb3VzU2libGluZ31jYXRjaChyKXtILlJ1KHIpCnE9cC5iKHQpCmEucmVtb3ZlQ2hpbGQocSkKdD1u
+dWxsCnM9YS5sYXN0Q2hpbGR9aWYodCE9bnVsbCl0aGlzLiQyKHQsYSkKdD1wLmIocyl9fSwKJFM6NDF9
+ClcuTGUucHJvdG90eXBlPXt9ClcuSlUucHJvdG90eXBlPXt9ClcueFgucHJvdG90eXBlPXt9ClcudmUu
+cHJvdG90eXBlPXt9ClcuYkcucHJvdG90eXBlPXt9ClcudEkucHJvdG90eXBlPXt9ClcuZmcucHJvdG90
+eXBlPXt9ClcuWjcucHJvdG90eXBlPXt9ClcuSFcucHJvdG90eXBlPXt9ClcubEcucHJvdG90eXBlPXt9
+ClcucXMucHJvdG90eXBlPXt9ClcuY3MucHJvdG90eXBlPXt9ClcuS0IucHJvdG90eXBlPXt9ClcuSzcu
+cHJvdG90eXBlPXt9ClcuckIucHJvdG90eXBlPXt9ClcuZlQucHJvdG90eXBlPXt9ClcuZjcucHJvdG90
+eXBlPXt9ClcuYmcucHJvdG90eXBlPXt9Clcub0gucHJvdG90eXBlPXt9ClcuQ0UucHJvdG90eXBlPXt9
+ClcuYUQucHJvdG90eXBlPXt9ClcuWngucHJvdG90eXBlPXt9ClcuT1gucHJvdG90eXBlPXt9ClcuVWou
+cHJvdG90eXBlPXt9Clcuak0ucHJvdG90eXBlPXt9ClcuUVYucHJvdG90eXBlPXt9ClcuQXcucHJvdG90
+eXBlPXt9ClcudHIucHJvdG90eXBlPXt9ClcuTzMucHJvdG90eXBlPXt9ClcuT3YucHJvdG90eXBlPXt9
+ClcuY08ucHJvdG90eXBlPXt9ClcuWUQucHJvdG90eXBlPXt9ClcuRHgucHJvdG90eXBlPXt9ClcuWFcu
+cHJvdG90eXBlPXt9Clcub2EucHJvdG90eXBlPXt9ClcuWFUucHJvdG90eXBlPXt9ClcuUnkucHJvdG90
+eXBlPXt9ClcuenYucHJvdG90eXBlPXt9ClcubnoucHJvdG90eXBlPXt9ClAuaTYucHJvdG90eXBlPXsK
+Vkg6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmEscj1zLmxlbmd0aApmb3IodD0wO3Q8cjsrK3QpaWYo
+c1t0XT09PWEpcmV0dXJuIHQKQy5ObS5BKHMsYSkKQy5ObS5BKHRoaXMuYixudWxsKQpyZXR1cm4gcn0s
+ClB2OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPXRoaXMscD17fQppZihhPT1udWxsKXJldHVybiBhCmlm
+KEgubChhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYodHlwZW9mIGE9
+PSJzdHJpbmciKXJldHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBuZXcgRGF0ZShhLmEp
+CmlmKHUuZnYuYyhhKSl0aHJvdyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAiKSkK
+aWYodS5PLmMoYSkpcmV0dXJuIGEKaWYodS5kLmMoYSkpcmV0dXJuIGEKaWYodS5iWC5jKGEpKXJldHVy
+biBhCmlmKHUuSS5jKGEpKXJldHVybiBhCmlmKHUuYlouYyhhKXx8dS5kRC5jKGEpfHx1LmJLLmMoYSkp
+cmV0dXJuIGEKaWYodS5HLmMoYSkpe3Q9cS5WSChhKQpzPXEuYgppZih0Pj1zLmxlbmd0aClyZXR1cm4g
+SC5PSChzLHQpCnI9cC5hPXNbdF0KaWYociE9bnVsbClyZXR1cm4gcgpyPXt9CnAuYT1yCkMuTm0uWShz
+LHQscikKSi5oRShhLG5ldyBQLmxSKHAscSkpCnJldHVybiBwLmF9aWYodS5qLmMoYSkpe3Q9cS5WSChh
+KQpwPXEuYgppZih0Pj1wLmxlbmd0aClyZXR1cm4gSC5PSChwLHQpCnI9cFt0XQppZihyIT1udWxsKXJl
+dHVybiByCnJldHVybiBxLmVrKGEsdCl9aWYodS5lSC5jKGEpKXt0PXEuVkgoYSkKcz1xLmIKaWYodD49
+cy5sZW5ndGgpcmV0dXJuIEguT0gocyx0KQpyPXAuYj1zW3RdCmlmKHIhPW51bGwpcmV0dXJuIHIKcj17
+fQpwLmI9cgpDLk5tLlkocyx0LHIpCnEuaW0oYSxuZXcgUC5qZyhwLHEpKQpyZXR1cm4gcC5ifXRocm93
+IEguYihQLlNZKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIG90aGVyIHR5cGUiKSl9LAplazpmdW5jdGlvbihh
+LGIpe3ZhciB0LHM9Si5VNihhKSxyPXMuZ2goYSkscT1uZXcgQXJyYXkocikKQy5ObS5ZKHRoaXMuYixi
+LHEpCmZvcih0PTA7dDxyOysrdClDLk5tLlkocSx0LHRoaXMuUHYocy5xKGEsdCkpKQpyZXR1cm4gcX19
+ClAubFIucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYVthXT10aGlzLmIuUHYoYil9
+LAokUzoxfQpQLmpnLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmJbYV09dGhpcy5i
+LlB2KGIpfSwKJFM6MX0KUC5hSi5wcm90b3R5cGU9ewpWSDpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMu
+YSxyPXMubGVuZ3RoCmZvcih0PTA7dDxyOysrdClpZihzW3RdPT09YSlyZXR1cm4gdApDLk5tLkEocyxh
+KQpDLk5tLkEodGhpcy5iLG51bGwpCnJldHVybiByfSwKUHY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEs
+cCxvLG4sbSxsLGs9dGhpcyxqPXt9CmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoSC5sKGEpKXJldHVybiBh
+CmlmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJu
+IGEKaWYoYSBpbnN0YW5jZW9mIERhdGUpe3Q9YS5nZXRUaW1lKCkKcz1uZXcgUC5pUCh0LCEwKQpzLlhr
+KHQsITApCnJldHVybiBzfWlmKGEgaW5zdGFuY2VvZiBSZWdFeHApdGhyb3cgSC5iKFAuU1koInN0cnVj
+dHVyZWQgY2xvbmUgb2YgUmVnRXhwIikpCmlmKHR5cGVvZiBQcm9taXNlIT0idW5kZWZpbmVkIiYmYSBp
+bnN0YW5jZW9mIFByb21pc2UpcmV0dXJuIFAuVTgoYSx1LnopCnI9T2JqZWN0LmdldFByb3RvdHlwZU9m
+KGEpCmlmKHI9PT1PYmplY3QucHJvdG90eXBlfHxyPT09bnVsbCl7cT1rLlZIKGEpCnM9ay5iCmlmKHE+
+PXMubGVuZ3RoKXJldHVybiBILk9IKHMscSkKcD1qLmE9c1txXQppZihwIT1udWxsKXJldHVybiBwCm89
+dS56CnA9UC5GbChvLG8pCmouYT1wCkMuTm0uWShzLHEscCkKay5IcChhLG5ldyBQLks1KGosaykpCnJl
+dHVybiBqLmF9aWYoYSBpbnN0YW5jZW9mIEFycmF5KXtuPWEKcT1rLlZIKG4pCnM9ay5iCmlmKHE+PXMu
+bGVuZ3RoKXJldHVybiBILk9IKHMscSkKcD1zW3FdCmlmKHAhPW51bGwpcmV0dXJuIHAKbz1KLlU2KG4p
+Cm09by5naChuKQpDLk5tLlkocyxxLG4pCmZvcihsPTA7bDxtOysrbClvLlkobixsLGsuUHYoby5xKG4s
+bCkpKQpyZXR1cm4gbn1yZXR1cm4gYX19ClAuSzUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2
+YXIgdD10aGlzLmEuYSxzPXRoaXMuYi5QdihiKQpKLkIyKHQsYSxzKQpyZXR1cm4gc30sCiRTOjMzfQpQ
+LkJmLnByb3RvdHlwZT17CmltOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5ZLmIoYikKZm9yKHQ9
+T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0aCxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxhW3FdKX19
+fQpQLnpnLnByb3RvdHlwZT17CkhwOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5ZLmIoYikKZm9y
+KHQ9T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0aCxyPTA7cjx0Lmxlbmd0aDt0Lmxlbmd0aD09PXN8fCgw
+LEgubGspKHQpLCsrcil7cT10W3JdCmIuJDIocSxhW3FdKX19fQpQLmRNLnByb3RvdHlwZT17ClZMOmZ1
+bmN0aW9uKGEpe3ZhciB0CkgueShhKQp0PSQuaEcoKS5iCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILlZq
+KEgudEwoYSkpCmlmKHQudGVzdChhKSlyZXR1cm4gYQp0aHJvdyBILmIoUC5MMyhhLCJ2YWx1ZSIsIk5v
+dCBhIHZhbGlkIGNsYXNzIHRva2VuIikpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ERygpLnpW
+KDAsIiAiKX0sCmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLkRHKCkKcmV0dXJuIFAucmoodCx0LnIs
+SC5MaCh0KS5kKX0sCmdoOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkRHKCkuYX0sCnRnOmZ1bmN0aW9u
+KGEsYil7dGhpcy5WTChiKQpyZXR1cm4gdGhpcy5ERygpLnRnKDAsYil9LApBOmZ1bmN0aW9uKGEsYil7
+dGhpcy5WTChiKQpyZXR1cm4gSC54ZCh0aGlzLk9TKDAsbmV3IFAuR0UoYikpKX0sClJ6OmZ1bmN0aW9u
+KGEsYil7dmFyIHQscwp0aGlzLlZMKGIpCnQ9dGhpcy5ERygpCnM9dC5SeigwLGIpCnRoaXMucDUodCkK
+cmV0dXJuIHN9LApGVjpmdW5jdGlvbihhLGIpe3RoaXMuT1MoMCxuZXcgUC5ONyh0aGlzLHUuWC5iKGIp
+KSl9LApWMTpmdW5jdGlvbihhKXt0aGlzLk9TKDAsbmV3IFAudVEoKSl9LApPUzpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMKdS5jaC5iKGIpCnQ9dGhpcy5ERygpCnM9Yi4kMSh0KQp0aGlzLnA1KHQpCnJldHVybiBz
+fX0KUC5HRS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5DLmIoYSkuQSgwLHRoaXMu
+YSl9LAokUzozNH0KUC5ONy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIscz1I
+LnQ2KHQpCnJldHVybiB1LkMuYihhKS5GVigwLG5ldyBILkE4KHQscy5DKCJxVSgxKSIpLmIodGhpcy5h
+Lmd1TSgpKSxzLkMoIkE4PDEscVU+IikpKX0sCiRTOjE0fQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0
+aW9uKGEpe3UuQy5iKGEpCmlmKGEuYT4wKXthLmI9YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5Y
+QSgpfXJldHVybiBudWxsfSwKJFM6MTR9ClAuVzIucHJvdG90eXBlPXsKZ0czOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmtleX19ClAuZTMucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC56
+ZyhbXSxbXSkuUHYoYS52YWx1ZSl9fQpQLmhGLnByb3RvdHlwZT17JGloRjoxfQpQLkJWLnByb3RvdHlw
+ZT17CmdHMzpmdW5jdGlvbihhKXtyZXR1cm4gYS5rZXl9LApnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
+dmFsdWV9fQpQLlBDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuWi5iKGEpCnQ9ZnVu
+Y3Rpb24oYixjLGQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBiKGMsZCx0aGlzLEFycmF5LnByb3Rv
+dHlwZS5zbGljZS5hcHBseShhcmd1bWVudHMpKX19KFAuUjQsYSwhMSkKUC5EbSh0LCQudygpLGEpCnJl
+dHVybiB0fSwKJFM6NH0KUC5tdC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IHRo
+aXMuYShhKX0sCiRTOjR9ClAuTnoucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQ
+LnI3KGEpfSwKJFM6MzZ9ClAubnAucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQ
+LlR6KGEsdS5hbSl9LAokUzozN30KUC5VdC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IFAuRTQoYSl9LAokUzozOH0KUC5FNC5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7aWYodHlw
+ZW9mIGIhPSJzdHJpbmciJiZ0eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5
+IGlzIG5vdCBhIFN0cmluZyBvciBudW0iKSkKcmV0dXJuIFAuTDcodGhpcy5hW2JdKX0sClk6ZnVuY3Rp
+b24oYSxiLGMpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIhPSJudW1iZXIiKXRocm93IEgu
+YihQLnhZKCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikpCnRoaXMuYVtiXT1QLndZKGMp
+fSwKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2Yg
+UC5FNCYmdGhpcy5hPT09Yi5hfSwKdzpmdW5jdGlvbihhKXt2YXIgdCxzCnRyeXt0PVN0cmluZyh0aGlz
+LmEpCnJldHVybiB0fWNhdGNoKHMpe0guUnUocykKdD10aGlzLnhiKDApCnJldHVybiB0fX0sClY3OmZ1
+bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmEKaWYoYj09bnVsbCl0PW51bGwKZWxzZXt0PUgudDYoYikK
+dD1QLkNIKG5ldyBILkE4KGIsdC5DKCJAKDEpIikuYihQLmlHKCkpLHQuQygiQTg8MSxAPiIpKSwhMCx1
+LnopfXJldHVybiBQLkw3KHNbYV0uYXBwbHkocyx0KSl9LApnaTpmdW5jdGlvbihhKXtyZXR1cm4gMH19
+ClAucjcucHJvdG90eXBlPXt9ClAuVHoucHJvdG90eXBlPXsKY1A6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
+cyxzPWE8MHx8YT49dC5naCh0KQppZihzKXRocm93IEguYihQLlRFKGEsMCx0LmdoKHQpLG51bGwsbnVs
+bCkpfSwKcTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiPT0ibnVtYmVyIiYmYj09PUMuam4ueXUoYikp
+dGhpcy5jUChILlNjKGIpKQpyZXR1cm4gdGhpcy4kdGkuZC5iKHRoaXMuVXIoMCxiKSl9LApZOmZ1bmN0
+aW9uKGEsYixjKXt0aGlzLiR0aS5kLmIoYykKaWYodHlwZW9mIGI9PSJudW1iZXIiJiZiPT09Qy5DRC55
+dShiKSl0aGlzLmNQKEguU2MoYikpCnRoaXMuZTQoMCxiLGMpfSwKZ2g6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcy5hLmxlbmd0aAppZih0eXBlb2YgdD09PSJudW1iZXIiJiZ0Pj4+MD09PXQpcmV0dXJuIHQKdGhy
+b3cgSC5iKFAuUFYoIkJhZCBKc0FycmF5IGxlbmd0aCIpKX0sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9
+ClAuY28ucHJvdG90eXBlPXt9ClAudksucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
+aXMuYS5hTSgwLHRoaXMuYi5DKCIwLyIpLmIoYSkpfSwKJFM6MTB9ClAucFUucHJvdG90eXBlPXsKJDE6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5wbShhKX0sCiRTOjEwfQpQLklOLnByb3RvdHlwZT17fQpQ
+LnRuLnByb3RvdHlwZT17fQpQLnVqLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52
+YWx1ZX19ClAueDAucHJvdG90eXBlPXskaXgwOjEsCmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1
+ZX19ClAucTYucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5j
+dGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihi
+LGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYS5nZXRJdGVtKGIpfSwKWTpmdW5jdGlvbihhLGIsYyl7
+SC5TYyhiKQp1LmJHLmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBp
+bW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucShhLGIpfSwKJGli
+UToxLAokaWNYOjEsCiRpek06MX0KUC51UC5wcm90b3R5cGU9eyRpdVA6MSwKZ253OmZ1bmN0aW9uKGEp
+e3JldHVybiBhLnZhbHVlfX0KUC5mei5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihhKXtyZXR1cm4gYS5s
+ZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRo
+cm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhLmdldEl0ZW0oYil9LApZOmZ1
+bmN0aW9uKGEsYixjKXtILlNjKGIpCnUuY2suYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2ln
+biBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhp
+cy5xKGEsYil9LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpQLkVELnByb3RvdHlwZT17CmdoOmZ1bmN0
+aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClAubmQucHJvdG90eXBlPXskaW5kOjF9ClAuS3EucHJvdG90
+eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2Mo
+YikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51
+bGwpKQpyZXR1cm4gYS5nZXRJdGVtKGIpfSwKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhiKQpILnkoYykK
+dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9
+LApXOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucShhLGIpfSwKJGliUToxLAokaWNYOjEsCiRpek06
+MX0KUC5LZS5wcm90b3R5cGU9ewpERzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcy5hLmdldEF0
+dHJpYnV0ZSgiY2xhc3MiKSxvPVAuTHModS5OKQppZihwPT1udWxsKXJldHVybiBvCmZvcih0PXAuc3Bs
+aXQoIiAiKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtxPUouVDAodFtyXSkKaWYocS5sZW5ndGghPT0w
+KW8uQSgwLHEpfXJldHVybiBvfSwKcDU6ZnVuY3Rpb24oYSl7dGhpcy5hLnNldEF0dHJpYnV0ZSgiY2xh
+c3MiLGEuelYoMCwiICIpKX19ClAuZDUucHJvdG90eXBlPXsKZ0REOmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgUC5LZShhKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnI2OmZ1bmN0aW9uKGEs
+YixjLGQpe3ZhciB0LHMscixxLHAsbwppZihkPT1udWxsKXt0PUguVk0oW10sdS5tKQpkPW5ldyBXLnZE
+KHQpCkMuTm0uQSh0LFcuVHcobnVsbCkpCkMuTm0uQSh0LFcuQmwoKSkKQy5ObS5BKHQsbmV3IFcuT3co
+KSl9Yz1uZXcgVy5LbyhkKQpzPSc8c3ZnIHZlcnNpb249IjEuMSI+JytILmQoYikrIjwvc3ZnPiIKdD1k
+b2N1bWVudApyPXQuYm9keQpxPShyJiZDLlJZKS5BSChyLHMsYykKcD10LmNyZWF0ZURvY3VtZW50RnJh
+Z21lbnQoKQpxLnRvU3RyaW5nCnQ9bmV3IFcuZTcocSkKbz10LmdyOCh0KQpmb3IoO3Q9by5maXJzdENo
+aWxkLHQhPW51bGw7KXAuYXBwZW5kQ2hpbGQodCkKcmV0dXJuIHB9LApuejpmdW5jdGlvbihhLGIsYyxk
+LGUpe3Rocm93IEguYihQLkw0KCJDYW5ub3QgaW52b2tlIGluc2VydEFkamFjZW50SHRtbCBvbiBTVkcu
+IikpfSwKZ1ZsOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5ldShhLCJjbGljayIsITEsdS5RKX0sCiRp
+ZDU6MX0KUC56WS5wcm90b3R5cGU9eyRpelk6MX0KUC5OQy5wcm90b3R5cGU9ewpnaDpmdW5jdGlvbihh
+KXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+
+PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhLmdldEl0
+ZW0oYil9LApZOmZ1bmN0aW9uKGEsYixjKXtILlNjKGIpCnUuY00uYihjKQp0aHJvdyBILmIoUC5MNCgi
+Q2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gdGhpcy5xKGEsYil9LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpQLmZVLnByb3RvdHlw
+ZT17fQpQLkdDLnByb3RvdHlwZT17fQpQLmpHLnByb3RvdHlwZT17fQpQLmpTLnByb3RvdHlwZT17fQpQ
+LnhXLnByb3RvdHlwZT17fQpQLmRTLnByb3RvdHlwZT17fQpQLndqLnByb3RvdHlwZT17fQpQLk1ZLnBy
+b3RvdHlwZT17fQpQLm42LnByb3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXpNOjEsJGlBUzoxfQpQLnIy
+LnByb3RvdHlwZT17CmdoOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClAuck8ucHJvdG90eXBl
+PXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KUC56OC5wcm90b3R5cGU9ewpxOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQoSC55KGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cwp1LlQuYihiKQp0PWEuZW50cmllcygpCmZvcig7ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1
+cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52YWx1ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0
+PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcgUC5xZih0KSkKcmV0dXJuIHR9LApnaDpmdW5jdGlvbihh
+KXtyZXR1cm4gYS5zaXplfSwKWTpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBw
+b3J0ZWQiKSl9LAokaVowOjF9ClAucWYucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+Qy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9ClAuZm8ucHJvdG90eXBlPXsKZ2g6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofX0KUC5WOC5wcm90b3R5cGU9e30KUC5Hbi5wcm90b3R5cGU9ewpnaDpmdW5jdGlv
+bihhKXtyZXR1cm4gYS5sZW5ndGh9fQpQLlUzLnByb3RvdHlwZT17fQpQLkZuLnByb3RvdHlwZT17Cmdo
+OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlmKGI+
+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0
+dXJuIFAubVIoYS5pdGVtKGIpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe0guU2MoYikKdS5HLmIoYykKdGhy
b3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApX
-OmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFb
-Yl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9ClcuYVQucHJvdG90eXBlPXsKVTpmdW5j
-dGlvbihhLGIpe3ZhciB0LHMscixxLHAKdS5XLmEoYikKZm9yKHQ9dGhpcy5ndih0aGlzKSxzPXQubGVu
-Z3RoLHI9dGhpcy5hLHE9MDtxPHQubGVuZ3RoO3QubGVuZ3RoPT09c3x8KDAsSC5saykodCksKytxKXtw
-PXRbcV0KYi4kMihwLHIuZ2V0QXR0cmlidXRlKHApKX19LApndjpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
-cSxwPXRoaXMuYS5hdHRyaWJ1dGVzLG89SC5WTShbXSx1LnMpCmZvcih0PXAubGVuZ3RoLHM9dS5oOSxy
-PTA7cjx0Oysrcil7aWYocj49cC5sZW5ndGgpcmV0dXJuIEguayhwLHIpCnE9cy5hKHBbcl0pCmlmKHEu
-bmFtZXNwYWNlVVJJPT1udWxsKUMuTm0uQShvLHEubmFtZSl9cmV0dXJuIG99fQpXLmk3LnByb3RvdHlw
-ZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLmdldEF0dHJpYnV0ZShILmMoYikpfSwKdDpm
-dW5jdGlvbihhLGIsYyl7dGhpcy5hLnNldEF0dHJpYnV0ZShiLGMpfSwKZ2s6ZnVuY3Rpb24oYSl7cmV0
-dXJuIHRoaXMuZ3YodGhpcykubGVuZ3RofX0KVy5TeS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7
-cmV0dXJuIHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuWShILmMoYikpKX0sCnQ6ZnVu
-Y3Rpb24oYSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuWShiKSxjKX0sClU6
-ZnVuY3Rpb24oYSxiKXt0aGlzLmEuVSgwLG5ldyBXLktTKHRoaXMsdS5XLmEoYikpKX0sCmd2OmZ1bmN0
-aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLmEuVSgwLG5ldyBXLkEzKHRoaXMsdCkpCnJldHVy
-biB0fSwKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ3YodGhpcykubGVuZ3RofSwKeHE6ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyPUguVk0oYS5zcGxpdCgiLSIpLHUucykKZm9yKHQ9MTt0PHIubGVuZ3RoOysr
-dCl7cz1yW3RdCmlmKHMubGVuZ3RoPjApQy5ObS50KHIsdCxzWzBdLnRvVXBwZXJDYXNlKCkrSi5LVihz
-LDEpKX1yZXR1cm4gQy5ObS56VihyLCIiKX0sClk6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscApmb3Io
-dD1hLmxlbmd0aCxzPTAscj0iIjtzPHQ7KytzKXtxPWFbc10KcD1xLnRvTG93ZXJDYXNlKCkKcj0ocSE9
-PXAmJnM+MD9yKyItIjpyKStwfXJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfX0KVy5LUy5wcm90
-b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSkubkMoYSwiZGF0YS0iKSl0aGlzLmIuJDIo
-dGhpcy5hLnhxKEMueEIueW4oYSw1KSksYil9LAokUzoxMn0KVy5BMy5wcm90b3R5cGU9ewokMjpmdW5j
-dGlvbihhLGIpe2lmKEouclkoYSkubkMoYSwiZGF0YS0iKSlDLk5tLkEodGhpcy5iLHRoaXMuYS54cShD
-LnhCLnluKGEsNSkpKX0sCiRTOjEyfQpXLkk0LnByb3RvdHlwZT17CkRHOmZ1bmN0aW9uKCl7dmFyIHQs
-cyxyLHEscD1QLkxzKHUuTikKZm9yKHQ9dGhpcy5hLmNsYXNzTmFtZS5zcGxpdCgiICIpLHM9dC5sZW5n
-dGgscj0wO3I8czsrK3Ipe3E9Si5UMCh0W3JdKQppZihxLmxlbmd0aCE9PTApcC5BKDAscSl9cmV0dXJu
-IHB9LApwNTpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPXUuQy5hKGEpLnpWKDAsIiAiKX0sCmdr
-OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0aH0sClYxOmZ1bmN0aW9uKGEp
-e3RoaXMuYS5jbGFzc05hbWU9IiJ9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYS5jbGFzc0xp
-c3QuY29udGFpbnMoYikKcmV0dXJuIHR9LApBOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNz
-TGlzdCxzPXQuY29udGFpbnMoYikKdC5hZGQoYikKcmV0dXJuIXN9LApSejpmdW5jdGlvbihhLGIpe3Zh
-ciB0PXRoaXMuYS5jbGFzc0xpc3Qscz10LmNvbnRhaW5zKGIpCnQucmVtb3ZlKGIpCnJldHVybiBzfSwK
-RlY6ZnVuY3Rpb24oYSxiKXtXLlROKHRoaXMuYSx1LlguYShiKSl9fQpXLkZrLnByb3RvdHlwZT17fQpX
-LlJPLnByb3RvdHlwZT17fQpXLmV1LnByb3RvdHlwZT17fQpXLnhDLnByb3RvdHlwZT17fQpXLnZOLnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDEodS5CLmEoYSkpfSwKJFM6Mjl9
-ClcuSlEucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoJC5vci5hPT09MCl7Zm9yKHQ9
-MDt0PDI2MjsrK3QpJC5vci50KDAsQy5jbVt0XSxXLnBTKCkpCmZvcih0PTA7dDwxMjsrK3QpJC5vci50
-KDAsQy5CSVt0XSxXLlY0KCkpfX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiAkLkFOKCkudGcoMCxXLnJT
-KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0kLm9yLnEoMCxILmQoVy5yUyhhKSkrIjo6Iiti
-KQppZih0PT1udWxsKXQ9JC5vci5xKDAsIio6OiIrYikKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4g
-SC5FOSh0LiQ0KGEsYixjLHRoaXMpKX0sCiRpa0Y6MX0KVy5HbS5wcm90b3R5cGU9ewpndzpmdW5jdGlv
-bihhKXtyZXR1cm4gbmV3IFcuVzkoYSx0aGlzLmdrKGEpLEgucShhKS5DKCJXOTxHbS5FPiIpKX19Clcu
-dkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBXLlV2
-KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuRWcoYSxi
-LGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5lLmEo
-YSkuaTAodGhpcy5hKX0sCiRTOjE3fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biB1LmUuYShhKS5FYih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxN30KVy5tNi5wcm90b3R5cGU9
-ewpDWTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdGhpcy5hLkZWKDAsYykKdD1iLmV2KDAsbmV3
-IFcuRW8oKSkKcz1iLmV2KDAsbmV3IFcuV2soKSkKdGhpcy5iLkZWKDAsdCkKcj10aGlzLmMKci5GVigw
-LEMueEQpCnIuRlYoMCxzKX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEudGcoMCxXLnJTKGEp
-KX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD10aGlzLHM9Vy5yUyhhKSxyPXQuYwppZihyLnRnKDAs
-SC5kKHMpKyI6OiIrYikpcmV0dXJuIHQuZC5EdChjKQplbHNlIGlmKHIudGcoMCwiKjo6IitiKSlyZXR1
-cm4gdC5kLkR0KGMpCmVsc2V7cj10LmIKaWYoci50ZygwLEguZChzKSsiOjoiK2IpKXJldHVybiEwCmVs
-c2UgaWYoci50ZygwLCIqOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLEguZChzKSsiOjoqIikp
-cmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6OioiKSlyZXR1cm4hMH1yZXR1cm4hMX0sCiRpa0Y6MX0K
-Vy5Fby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4hQy5ObS50ZyhDLkJJLEguYyhhKSl9
-LAokUzo5fQpXLldrLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBDLk5tLnRnKEMuQkks
-SC5jKGEpKX0sCiRTOjl9ClcuY3QucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe2lmKHRoaXMu
-akYoYSxiLGMpKXJldHVybiEwCmlmKGI9PT0idGVtcGxhdGUiJiZjPT09IiIpcmV0dXJuITAKaWYoYS5n
-ZXRBdHRyaWJ1dGUoInRlbXBsYXRlIik9PT0iIilyZXR1cm4gdGhpcy5lLnRnKDAsYikKcmV0dXJuITF9
-fQpXLklBLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiJURU1QTEFURTo6IitILmQoSC5j
-KGEpKX0sCiRTOjV9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5ldy5i
-KGEpKXJldHVybiExCnQ9dS5nNy5iKGEpCmlmKHQmJlcuclMoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0
-dXJuITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixjKXtpZihiPT09Imlz
-Inx8Qy54Qi5uQyhiLCJvbiIpKXJldHVybiExCnJldHVybiB0aGlzLmkwKGEpfSwKJGlrRjoxfQpXLlc5
-LnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jKzEscj10LmIKaWYoczxyKXt0
-LnNwKEoueDkodC5hLHMpKQp0LmM9cwpyZXR1cm4hMH10LnNwKG51bGwpCnQuYz1yCnJldHVybiExfSwK
-Z1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0sCnNwOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0
-aS5jLmEoYSl9LAokaUFuOjF9ClcuZFcucHJvdG90eXBlPXsKZ21XOmZ1bmN0aW9uKGEpe3JldHVybiBX
-LnpYKHRoaXMuYS5sb2NhdGlvbil9LAokaUQwOjEsCiRpdjY6MX0KVy5GYi5wcm90b3R5cGU9e30KVy5r
-Ri5wcm90b3R5cGU9e30KVy5tay5wcm90b3R5cGU9eyRpV1E6MX0KVy5Lby5wcm90b3R5cGU9ewpQbjpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLHM9bmV3IFcuZm0odCkKdC5iPSExCnMuJDIoYSxudWxsKQpmb3Io
-O3QuYjspe3QuYj0hMQpzLiQyKGEsbnVsbCl9fSwKRVA6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmI9
-ITAKaWYoYiE9bnVsbD9iIT09YS5wYXJlbnROb2RlOnQpSi5MdChhKQplbHNlIGIucmVtb3ZlQ2hpbGQo
-YSl9LApJNDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz0hMCxuPW51bGwsbT1udWxsCnRyeXtu
-PUouaWcoYSkKbT1uLmEuZ2V0QXR0cmlidXRlKCJpcyIpCnUuaC5hKGEpCnQ9ZnVuY3Rpb24oYyl7aWYo
-IShjLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApKXJldHVybiB0cnVlCmlmKGMuaWQ9
-PSdsYXN0Q2hpbGQnfHxjLm5hbWU9PSdsYXN0Q2hpbGQnfHxjLmlkPT0ncHJldmlvdXNTaWJsaW5nJ3x8
-Yy5uYW1lPT0ncHJldmlvdXNTaWJsaW5nJ3x8Yy5pZD09J2NoaWxkcmVuJ3x8Yy5uYW1lPT0nY2hpbGRy
-ZW4nKXJldHVybiB0cnVlCnZhciBsPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGlsZCYmYy5sYXN0Q2hp
-bGQhPT1sW2wubGVuZ3RoLTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYoIShjLmNoaWxkcmVu
-IGluc3RhbmNlb2YgSFRNTENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2VvZiBOb2RlTGlzdCkp
-cmV0dXJuIHRydWUKdmFyIGs9MAppZihjLmNoaWxkcmVuKWs9Yy5jaGlsZHJlbi5sZW5ndGgKZm9yKHZh
-ciBqPTA7ajxrO2orKyl7dmFyIGk9Yy5jaGlsZHJlbltqXQppZihpLmlkPT0nYXR0cmlidXRlcyd8fGku
-bmFtZT09J2F0dHJpYnV0ZXMnfHxpLmlkPT0nbGFzdENoaWxkJ3x8aS5uYW1lPT0nbGFzdENoaWxkJ3x8
-aS5pZD09J3ByZXZpb3VzU2libGluZyd8fGkubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGkuaWQ9PSdj
-aGlsZHJlbid8fGkubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZX1yZXR1cm4gZmFsc2V9KGEpCm89
-SC5vVCh0KT8hMDohKGEuYXR0cmlidXRlcyBpbnN0YW5jZW9mIE5hbWVkTm9kZU1hcCl9Y2F0Y2gocSl7
-SC5SdShxKX1zPSJlbGVtZW50IHVucHJpbnRhYmxlIgp0cnl7cz1KLkFjKGEpfWNhdGNoKHEpe0guUnUo
-cSl9dHJ5e3I9Vy5yUyhhKQp0aGlzLmtSKHUuaC5hKGEpLGIsbyxzLHIsdS5HLmEobiksSC5jKG0pKX1j
-YXRjaChxKXtpZihILlJ1KHEpIGluc3RhbmNlb2YgUC5BVCl0aHJvdyBxCmVsc2V7dGhpcy5FUChhLGIp
-CndpbmRvdwpwPSJSZW1vdmluZyBjb3JydXB0ZWQgZWxlbWVudCAiK0guZChzKQppZih0eXBlb2YgY29u
-c29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKX19fSwKa1I6ZnVuY3Rpb24oYSxi
-LGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG49dGhpcwppZihjKXtuLkVQKGEsYikKd2luZG93CnQ9
-IlJlbW92aW5nIGVsZW1lbnQgZHVlIHRvIGNvcnJ1cHRlZCBhdHRyaWJ1dGVzIG9uIDwiK2QrIj4iCmlm
-KHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHQpCnJldHVybn1p
-Zighbi5hLmkwKGEpKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5nIGRpc2FsbG93ZWQgZWxlbWVu
-dCA8IitILmQoZSkrIj4gZnJvbSAiK0guZChiKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIp
-d2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59aWYoZyE9bnVsbClpZighbi5hLkViKGEsImlzIixn
-KSl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIHR5cGUgZXh0ZW5zaW9uIDwi
-K0guZChlKSsnIGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93
-LmNvbnNvbGUud2Fybih0KQpyZXR1cm59dD1mLmd2KGYpCnM9SC5WTSh0LnNsaWNlKDApLEgudDYodCku
-QygiamQ8MT4iKSkKZm9yKHI9Zi5ndihmKS5sZW5ndGgtMSx0PWYuYTtyPj0wOy0tcil7aWYocj49cy5s
-ZW5ndGgpcmV0dXJuIEguayhzLHIpCnE9c1tyXQpwPW4uYQpvPUouY0gocSkKSC5jKHEpCmlmKCFwLkVi
-KGEsbyx0LmdldEF0dHJpYnV0ZShxKSkpe3dpbmRvdwpwPSJSZW1vdmluZyBkaXNhbGxvd2VkIGF0dHJp
-YnV0ZSA8IitILmQoZSkrIiAiK3ErJz0iJytILmQodC5nZXRBdHRyaWJ1dGUocSkpKyciPicKaWYodHlw
-ZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCkKdC5yZW1vdmVBdHRy
-aWJ1dGUocSl9fWlmKHUuYVcuYihhKSluLlBuKGEuY29udGVudCl9LAokaW9uOjF9ClcuZm0ucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzLmEKc3dpdGNoKGEubm9k
-ZVR5cGUpe2Nhc2UgMTpuLkk0KGEsYikKYnJlYWsKY2FzZSA4OmNhc2UgMTE6Y2FzZSAzOmNhc2UgNDpi
-cmVhawpkZWZhdWx0Om4uRVAoYSxiKX10PWEubGFzdENoaWxkCmZvcihyPXUuQTtudWxsIT10Oyl7cz1u
-dWxsCnRyeXtzPXQucHJldmlvdXNTaWJsaW5nCmlmKHMhPW51bGwpe3E9cy5uZXh0U2libGluZwpwPXQK
-cD1xPT1udWxsP3AhPW51bGw6cSE9PXAKcT1wfWVsc2UgcT0hMQppZihxKXtxPVAuUFYoIkNvcnJ1cHQg
-SFRNTCIpCnRocm93IEguYihxKX19Y2F0Y2gobyl7SC5SdShvKQpxPXIuYSh0KQpuLmI9ITAKcD1xLnBh
-cmVudE5vZGUKcD1hPT1udWxsP3AhPW51bGw6YSE9PXAKaWYocCl7cD1xLnBhcmVudE5vZGUKaWYocCE9
-bnVsbClwLnJlbW92ZUNoaWxkKHEpfWVsc2UgYS5yZW1vdmVDaGlsZChxKQp0PW51bGwKcz1hLmxhc3RD
-aGlsZH1pZih0IT1udWxsKXRoaXMuJDIodCxhKQp0PXN9fSwKJFM6NDF9ClcuTGUucHJvdG90eXBlPXt9
-ClcuSlUucHJvdG90eXBlPXt9ClcueFgucHJvdG90eXBlPXt9ClcudmUucHJvdG90eXBlPXt9ClcuYkcu
-cHJvdG90eXBlPXt9ClcudEkucHJvdG90eXBlPXt9ClcuZmcucHJvdG90eXBlPXt9ClcuY1cucHJvdG90
-eXBlPXt9ClcuSFcucHJvdG90eXBlPXt9ClcubEcucHJvdG90eXBlPXt9ClcucXMucHJvdG90eXBlPXt9
-ClcuY3MucHJvdG90eXBlPXt9ClcuS0IucHJvdG90eXBlPXt9ClcuSzcucHJvdG90eXBlPXt9ClcuckIu
-cHJvdG90eXBlPXt9ClcuZlQucHJvdG90eXBlPXt9ClcuZjcucHJvdG90eXBlPXt9ClcuYmcucHJvdG90
-eXBlPXt9Clcub0gucHJvdG90eXBlPXt9ClcuQ0UucHJvdG90eXBlPXt9ClcuYUQucHJvdG90eXBlPXt9
-ClcuWngucHJvdG90eXBlPXt9ClcuT1gucHJvdG90eXBlPXt9ClcuVWoucHJvdG90eXBlPXt9Clcuak0u
-cHJvdG90eXBlPXt9ClcuUVYucHJvdG90eXBlPXt9ClcuQXcucHJvdG90eXBlPXt9ClcudHIucHJvdG90
-eXBlPXt9ClcuTzMucHJvdG90eXBlPXt9ClcuT3YucHJvdG90eXBlPXt9ClcuY08ucHJvdG90eXBlPXt9
-ClcuWUQucHJvdG90eXBlPXt9ClcuRHgucHJvdG90eXBlPXt9ClcuWFcucHJvdG90eXBlPXt9Clcub2Eu
-cHJvdG90eXBlPXt9ClcuWFUucHJvdG90eXBlPXt9ClcubzMucHJvdG90eXBlPXt9ClcuenYucHJvdG90
-eXBlPXt9ClcubnoucHJvdG90eXBlPXt9ClAuaTYucHJvdG90eXBlPXsKVkg6ZnVuY3Rpb24oYSl7dmFy
-IHQscz10aGlzLmEscj1zLmxlbmd0aApmb3IodD0wO3Q8cjsrK3QpaWYoc1t0XT09PWEpcmV0dXJuIHQK
-Qy5ObS5BKHMsYSkKQy5ObS5BKHRoaXMuYixudWxsKQpyZXR1cm4gcn0sClB2OmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxPXRoaXMscD17fQppZihhPT1udWxsKXJldHVybiBhCmlmKEguclEoYSkpcmV0dXJuIGEK
-aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4g
-YQppZihhIGluc3RhbmNlb2YgUC5pUClyZXR1cm4gbmV3IERhdGUoYS5hKQppZih1LmZ2LmIoYSkpdGhy
-b3cgSC5iKFAubigic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAiKSkKaWYodS5PLmIoYSkpcmV0dXJu
-IGEKaWYodS5kLmIoYSkpcmV0dXJuIGEKaWYodS5iWC5iKGEpKXJldHVybiBhCmlmKHUuSS5iKGEpKXJl
-dHVybiBhCmlmKHUuYlouYihhKXx8dS5kRC5iKGEpfHx1LmJLLmIoYSkpcmV0dXJuIGEKaWYodS5HLmIo
-YSkpe3Q9cS5WSChhKQpzPXEuYgppZih0Pj1zLmxlbmd0aClyZXR1cm4gSC5rKHMsdCkKcj1wLmE9c1t0
-XQppZihyIT1udWxsKXJldHVybiByCnI9e30KcC5hPXIKQy5ObS50KHMsdCxyKQpKLmhFKGEsbmV3IFAu
-amcocCxxKSkKcmV0dXJuIHAuYX1pZih1LmouYihhKSl7dD1xLlZIKGEpCnA9cS5iCmlmKHQ+PXAubGVu
-Z3RoKXJldHVybiBILmsocCx0KQpyPXBbdF0KaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gcS5layhh
-LHQpfWlmKHUuZUguYihhKSl7dD1xLlZIKGEpCnM9cS5iCmlmKHQ+PXMubGVuZ3RoKXJldHVybiBILmso
-cyx0KQpyPXAuYj1zW3RdCmlmKHIhPW51bGwpcmV0dXJuIHIKcj17fQpwLmI9cgpDLk5tLnQocyx0LHIp
-CnEuaW0oYSxuZXcgUC5UYShwLHEpKQpyZXR1cm4gcC5ifXRocm93IEguYihQLm4oInN0cnVjdHVyZWQg
-Y2xvbmUgb2Ygb3RoZXIgdHlwZSIpKX0sCmVrOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1KLlU2KGEpLHI9
-cy5nayhhKSxxPW5ldyBBcnJheShyKQpDLk5tLnQodGhpcy5iLGIscSkKZm9yKHQ9MDt0PHI7Kyt0KUMu
-Tm0udChxLHQsdGhpcy5QdihzLnEoYSx0KSkpCnJldHVybiBxfX0KUC5qZy5wcm90b3R5cGU9ewokMjpm
-dW5jdGlvbihhLGIpe3RoaXMuYS5hW2FdPXRoaXMuYi5QdihiKX0sCiRTOjF9ClAuVGEucHJvdG90eXBl
-PXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYlthXT10aGlzLmIuUHYoYil9LAokUzoxfQpQLmFKLnBy
-b3RvdHlwZT17ClZIOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5hLHI9cy5sZW5ndGgKZm9yKHQ9MDt0
-PHI7Kyt0KWlmKHNbdF09PT1hKXJldHVybiB0CkMuTm0uQShzLGEpCkMuTm0uQSh0aGlzLmIsbnVsbCkK
-cmV0dXJuIHJ9LApQdjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz10aGlzLGo9e30K
-aWYoYT09bnVsbClyZXR1cm4gYQppZihILnJRKGEpKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ibnVtYmVy
-IilyZXR1cm4gYQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIERh
-dGUpe3Q9YS5nZXRUaW1lKCkKcz1uZXcgUC5pUCh0LCEwKQpzLlhrKHQsITApCnJldHVybiBzfWlmKGEg
-aW5zdGFuY2VvZiBSZWdFeHApdGhyb3cgSC5iKFAubigic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAi
-KSkKaWYodHlwZW9mIFByb21pc2UhPSJ1bmRlZmluZWQiJiZhIGluc3RhbmNlb2YgUHJvbWlzZSlyZXR1
-cm4gUC5VOChhLHUueikKcj1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkKaWYocj09PU9iamVjdC5wcm90
-b3R5cGV8fHI9PT1udWxsKXtxPWsuVkgoYSkKcz1rLmIKaWYocT49cy5sZW5ndGgpcmV0dXJuIEguayhz
-LHEpCnA9ai5hPXNbcV0KaWYocCE9bnVsbClyZXR1cm4gcApvPXUuegpwPVAuRmwobyxvKQpqLmE9cApD
-Lk5tLnQocyxxLHApCmsuSHAoYSxuZXcgUC5LNShqLGspKQpyZXR1cm4gai5hfWlmKGEgaW5zdGFuY2Vv
-ZiBBcnJheSl7bj1hCnE9ay5WSChuKQpzPWsuYgppZihxPj1zLmxlbmd0aClyZXR1cm4gSC5rKHMscSkK
-cD1zW3FdCmlmKHAhPW51bGwpcmV0dXJuIHAKbz1KLlU2KG4pCm09by5nayhuKQpDLk5tLnQocyxxLG4p
-CmZvcihsPTA7bDxtOysrbClvLnQobixsLGsuUHYoby5xKG4sbCkpKQpyZXR1cm4gbn1yZXR1cm4gYX19
-ClAuSzUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEuYSxzPXRoaXMuYi5Q
-dihiKQpKLnU5KHQsYSxzKQpyZXR1cm4gc30sCiRTOjMzfQpQLkJmLnByb3RvdHlwZT17CmltOmZ1bmN0
-aW9uKGEsYil7dmFyIHQscyxyLHEKdS5ZLmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0
-aCxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxhW3FdKX19fQpQLnpnLnByb3RvdHlwZT17CkhwOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5ZLmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxl
-bmd0aCxyPTA7cjx0Lmxlbmd0aDt0Lmxlbmd0aD09PXN8fCgwLEgubGspKHQpLCsrcil7cT10W3JdCmIu
-JDIocSxhW3FdKX19fQpQLmRNLnByb3RvdHlwZT17ClM6ZnVuY3Rpb24oYSl7dmFyIHQKSC5jKGEpCnQ9
-JC5FZSgpLmIKaWYodHlwZW9mIGEhPSJzdHJpbmciKUguVmooSC50TChhKSkKaWYodC50ZXN0KGEpKXJl
-dHVybiBhCnRocm93IEguYihQLkwzKGEsInZhbHVlIiwiTm90IGEgdmFsaWQgY2xhc3MgdG9rZW4iKSl9
-LApaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkRHKCkuelYoMCwiICIpfSwKZ3c6ZnVuY3Rpb24oYSl7
-dmFyIHQ9dGhpcy5ERygpCnJldHVybiBQLnJqKHQsdC5yLEguTGgodCkuYyl9LApnazpmdW5jdGlvbihh
-KXtyZXR1cm4gdGhpcy5ERygpLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3RoaXMuUyhiKQpyZXR1cm4gdGhp
-cy5ERygpLnRnKDAsYil9LApBOmZ1bmN0aW9uKGEsYil7dGhpcy5TKGIpCnJldHVybiBILkU5KHRoaXMu
-T1MoMCxuZXcgUC5HRShiKSkpfSwKUno6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnRoaXMuUyhiKQp0PXRo
-aXMuREcoKQpzPXQuUnooMCxiKQp0aGlzLnA1KHQpCnJldHVybiBzfSwKRlY6ZnVuY3Rpb24oYSxiKXt0
-aGlzLk9TKDAsbmV3IFAuTjcodGhpcyx1LlguYShiKSkpfSwKVjE6ZnVuY3Rpb24oYSl7dGhpcy5PUygw
-LG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnUuYlUuYShiKQp0PXRoaXMuREco
-KQpzPWIuJDEodCkKdGhpcy5wNSh0KQpyZXR1cm4gc319ClAuR0UucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHUuQy5hKGEpLkEoMCx0aGlzLmEpfSwKJFM6MzR9ClAuTjcucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5iLHM9SC50Nih0KQpyZXR1cm4gdS5DLmEoYSkuRlYoMCxu
-ZXcgSC5sSih0LHMuQygicVUoMSkiKS5hKHRoaXMuYS5ndU0oKSkscy5DKCJsSjwxLHFVPiIpKSl9LAok
-UzoxNH0KUC51US5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LkMuYShhKQppZihhLmE+MCl7YS5i
-PWEuYz1hLmQ9YS5lPWEuZj1udWxsCmEuYT0wCmEuWEEoKX1yZXR1cm4gbnVsbH0sCiRTOjE0fQpQLlcy
-LnByb3RvdHlwZT17CmdHMzpmdW5jdGlvbihhKXtyZXR1cm4gYS5rZXl9fQpQLmUzLnByb3RvdHlwZT17
-CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuemcoW10sW10pLlB2KGEudmFsdWUpfX0KUC5oRi5w
-cm90b3R5cGU9eyRpaEY6MX0KUC5CVi5wcm90b3R5cGU9ewpnRzM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-a2V5fSwKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KUC5QQy5wcm90b3R5cGU9ewokMTpm
-dW5jdGlvbihhKXt2YXIgdAp1LlouYShhKQp0PWZ1bmN0aW9uKGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24o
-KXtyZXR1cm4gYihjLGQsdGhpcyxBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoYXJndW1lbnRzKSl9
-fShQLlI0LGEsITEpClAuRG0odCwkLndRKCksYSkKcmV0dXJuIHR9LAokUzo0fQpQLm10LnByb3RvdHlw
-ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6NH0KUC5Oei5wcm90b3R5
-cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAucjcoYSl9LAokUzozNn0KUC5ucC5wcm90b3R5
-cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVHooYSx1LmFtKX0sCiRTOjM3fQpQLlV0LnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjM4fQpQLkU0LnBy
-b3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0i
-bnVtYmVyIil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpy
-ZXR1cm4gUC5MNyh0aGlzLmFbYl0pfSwKdDpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJp
-bmciJiZ0eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0
-cmluZyBvciBudW0iKSkKdGhpcy5hW2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51
-bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LApaOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMKdHJ5e3Q9U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShz
-KQp0PXRoaXMueGIoMCkKcmV0dXJuIHR9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQpp
-ZihiPT1udWxsKXQ9bnVsbAplbHNle3Q9SC50NihiKQp0PVAuQ0gobmV3IEgubEooYix0LkMoIkAoMSki
-KS5hKFAuaUcoKSksdC5DKCJsSjwxLEA+IikpLCEwLHUueil9cmV0dXJuIFAuTDcoc1thXS5hcHBseShz
-LHQpKX0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiAwfX0KUC5yNy5wcm90b3R5cGU9e30KUC5Uei5wcm90
-b3R5cGU9ewpjUDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9YTwwfHxhPj10LmdrKHQpCmlmKHMpdGhy
-b3cgSC5iKFAuVEUoYSwwLHQuZ2sodCksbnVsbCxudWxsKSl9LApxOmZ1bmN0aW9uKGEsYil7aWYodHlw
-ZW9mIGI9PSJudW1iZXIiJiZiPT09Qy5qbi55dShiKSl0aGlzLmNQKEguV1koYikpCnJldHVybiB0aGlz
-LiR0aS5jLmEodGhpcy5VcigwLGIpKX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuJHRpLmMuYShjKQpp
-Zih0eXBlb2YgYj09Im51bWJlciImJmI9PT1DLkNELnl1KGIpKXRoaXMuY1AoSC5XWShiKSkKdGhpcy5l
-NCgwLGIsYyl9LApnazpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEubGVuZ3RoCmlmKHR5cGVvZiB0PT09
-Im51bWJlciImJnQ+Pj4wPT09dClyZXR1cm4gdAp0aHJvdyBILmIoUC5QVigiQmFkIEpzQXJyYXkgbGVu
-Z3RoIikpfSwKJGliUToxLAokaUx5OjEsCiRpek06MX0KUC5jby5wcm90b3R5cGU9e30KUC52Sy5wcm90
-b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmFNKDAsdGhpcy5iLkMoIjAvIikuYShh
-KSl9LAokUzoxMH0KUC5wVS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLnBt
-KGEpfSwKJFM6MTB9ClAuSU4ucHJvdG90eXBlPXt9ClAudG4ucHJvdG90eXBlPXt9ClAudWoucHJvdG90
-eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KUC54MC5wcm90b3R5cGU9ewpnbnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9LAokaXgwOjF9ClAucTYucHJvdG90eXBlPXsKZ2s6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAh
-PT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBh
-LmdldEl0ZW0oYil9LAp0OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCnUuYkcuYShjKQp0aHJvdyBILmIo
-UC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LAokaWJROjEsCiRpTHk6MSwKJGl6TToxfQpQLnVQLnBy
-b3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX0sCiRpdVA6MX0KUC5MWi5wcm90
-b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5X
-WShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxu
-dWxsKSkKcmV0dXJuIGEuZ2V0SXRlbShiKX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5jay5h
-KGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3Qu
-IikpfSwKVzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnEoYSxiKX0sCiRpYlE6MSwKJGlMeToxLAok
-aXpNOjF9ClAuRUQucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KUC5u
-ZC5wcm90b3R5cGU9eyRpbmQ6MX0KUC5LcS5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4g
-YS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3Ro
-KXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGEuZ2V0SXRlbShiKX0sCnQ6
-ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKSC5jKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWdu
-IGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
-LnEoYSxiKX0sCiRpYlE6MSwKJGlMeToxLAokaXpNOjF9ClAuS2UucHJvdG90eXBlPXsKREc6ZnVuY3Rp
-b24oKXt2YXIgdCxzLHIscSxwPXRoaXMuYS5nZXRBdHRyaWJ1dGUoImNsYXNzIiksbz1QLkxzKHUuTikK
-aWYocD09bnVsbClyZXR1cm4gbwpmb3IodD1wLnNwbGl0KCIgIikscz10Lmxlbmd0aCxyPTA7cjxzOysr
-cil7cT1KLlQwKHRbcl0pCmlmKHEubGVuZ3RoIT09MClvLkEoMCxxKX1yZXR1cm4gb30sCnA1OmZ1bmN0
-aW9uKGEpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoImNsYXNzIixhLnpWKDAsIiAiKSl9fQpQLmQ1LnByb3Rv
-dHlwZT17CmdERDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuS2UoYSl9LApzaGY6ZnVuY3Rpb24oYSxi
-KXt0aGlzLllDKGEsYil9LApyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8KaWYoZD09
-bnVsbCl7dD1ILlZNKFtdLHUudSkKZD1uZXcgVy52RCh0KQpDLk5tLkEodCxXLlR3KG51bGwpKQpDLk5t
-LkEodCxXLkJsKCkpCkMuTm0uQSh0LG5ldyBXLk93KCkpfWM9bmV3IFcuS28oZCkKcz0nPHN2ZyB2ZXJz
-aW9uPSIxLjEiPicrSC5kKGIpKyI8L3N2Zz4iCnQ9ZG9jdW1lbnQKcj10LmJvZHkKcT0ociYmQy5SWSku
-QUgocixzLGMpCnA9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKcS50b1N0cmluZwp0PW5ldyBXLmU3
-KHEpCm89dC5ncjgodCkKZm9yKDt0PW8uZmlyc3RDaGlsZCx0IT1udWxsOylwLmFwcGVuZENoaWxkKHQp
-CnJldHVybiBwfSwKbno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGlu
-dm9rZSBpbnNlcnRBZGphY2VudEh0bWwgb24gU1ZHLiIpKX0sCmdWbDpmdW5jdGlvbihhKXtyZXR1cm4g
-bmV3IFcuZXUoYSwiY2xpY2siLCExLHUuUSl9LAokaWQ1OjF9ClAuelkucHJvdG90eXBlPXskaXpZOjF9
-ClAuTkMucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlv
-bihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50KGIsYSxu
-dWxsLG51bGwsbnVsbCkpCnJldHVybiBhLmdldEl0ZW0oYil9LAp0OmZ1bmN0aW9uKGEsYixjKXtILldZ
-KGIpCnUuY00uYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0
-YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LAokaWJROjEs
-CiRpTHk6MSwKJGl6TToxfQpQLmZVLnByb3RvdHlwZT17fQpQLkdDLnByb3RvdHlwZT17fQpQLmpHLnBy
-b3RvdHlwZT17fQpQLmpTLnByb3RvdHlwZT17fQpQLnhXLnByb3RvdHlwZT17fQpQLmRTLnByb3RvdHlw
-ZT17fQpQLndqLnByb3RvdHlwZT17fQpQLk1ZLnByb3RvdHlwZT17fQpQLm42LnByb3RvdHlwZT17JGli
-UToxLCRpTHk6MSwkaXpNOjEsJGlBUzoxfQpQLnIyLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBhLmxlbmd0aH19ClAuck8ucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZh
-bHVlfX0KUC5EWC5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQoSC5j
-KGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp1LlQuYShiKQp0PWEuZW50cmllcygpCmZvcig7
-ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52YWx1
-ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcgUC5x
-Zih0KSkKcmV0dXJuIHR9LApnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5zaXplfSwKdDpmdW5jdGlvbihh
-LGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBwb3J0ZWQiKSl9LAokaVowOjF9ClAucWYucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9ClAuZm8u
-cHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KUC5WOC5wcm90b3R5cGU9
-e30KUC5Hbi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpQLlUzLnBy
-b3RvdHlwZT17fQpQLkZuLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
-CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5i
-KFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gUC5tUihhLml0ZW0oYikpfSwKdDpmdW5jdGlv
-bihhLGIsYyl7SC5XWShiKQp1LkcuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
-ZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEs
-Yil9LAokaWJROjEsCiRpTHk6MSwKJGl6TToxfQpQLm1vLnByb3RvdHlwZT17fQpQLktnLnByb3RvdHlw
-ZT17fQpVLmQyLnByb3RvdHlwZT17fQpVLlNlLnByb3RvdHlwZT17fQpVLk1sLnByb3RvdHlwZT17fQpV
-LnlELnByb3RvdHlwZT17CmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ifX0KVS53Yi5wcm90b3R5
-cGU9e30KQi5qOC5wcm90b3R5cGU9e30KQi5xcC5wcm90b3R5cGU9e30KVC5tUS5wcm90b3R5cGU9e30K
-TC5lLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuCnUuQi5hKGEpCnQ9
-d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnM9TC5HNih3aW5kb3cubG9jYXRpb24uaHJlZikKcj1MLmFL
-KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpMLkdlKCkKaWYodCE9PSIvIiYmdCE9PUouVDAoZG9jdW1lbnQu
-cXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpTC5HNyh0LHMsciwhMCxuZXcgTC5WVyh0
-LHMscikpCnE9ZG9jdW1lbnQKcD1KLnFGKHEucXVlcnlTZWxlY3RvcigiLmFwcGx5LW1pZ3JhdGlvbiIp
-KQpvPXAuJHRpCm49by5DKCJ+KDEpIikuYShuZXcgTC5vWigpKQp1Lk0uYShudWxsKQpXLkpFKHAuYSxw
-LmIsbiwhMSxvLmMpCnE9Si5xRihxLnF1ZXJ5U2VsZWN0b3IoIi5yZXJ1bi1taWdyYXRpb24iKSkKbz1x
-LiR0aQpXLkpFKHEuYSxxLmIsby5DKCJ+KDEpIikuYShuZXcgTC55OCgpKSwhMSxvLmMpfSwKJFM6MjB9
-CkwuVlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0s
-CiRTOjB9Ckwub1oucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dS5WLmEoYSkKaWYoSC5vVCh3aW5k
-b3cuY29uZmlybSgiVGhpcyB3aWxsIGFwcGx5IHRoZSBjaGFuZ2VzIHlvdSd2ZSBwcmV2aWV3ZWQgdG8g
-eW91ciB3b3JraW5nIGRpcmVjdG9yeS4gSXQgaXMgcmVjb21tZW5kZWQgeW91IGNvbW1pdCBhbnkgY2hh
-bmdlcyB5b3UgbWFkZSBiZWZvcmUgZG9pbmcgdGhpcy4iKSkpTC50eSgiL2FwcGx5LW1pZ3JhdGlvbiIp
-Llc3KG5ldyBMLmpyKCksdS5QKS5PQShuZXcgTC5xbCgpKX0sCiRTOjZ9CkwuanIucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5yLmEoYSkKdD1kb2N1bWVudC5ib2R5CnQuY2xhc3NMaXN0LnJl
-bW92ZSgicHJvcG9zZWQiKQp0LmNsYXNzTGlzdC5hZGQoImFwcGxpZWQiKX0sCiRTOjd9CkwucWwucHJv
-dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFKKCJhcHBseSBtaWdyYXRpb24gZXJyb3I6ICIrSC5k
-KGEpLGIpCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGFwcGx5IG1pZ3JhdGlvbiAoIitILmQoYSkrIiku
-Iil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLnk4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB0aGlzLnhuKHUuVi5hKGEpKX0sCnhuOmZ1bmN0aW9uKGEpe3ZhciB0PTAscz1QLkZYKHUuUCks
-cj0xLHEscD1bXSxvLG4sbSxsCnZhciAkYXN5bmMkJDE9UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0x
-KXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDpyPTMKZG9jdW1lbnQuYm9keS5jbGFz
-c0xpc3QuYWRkKCJyZXJ1bm5pbmciKQp0PTYKcmV0dXJuIFAualEoTC50eSgiL3JlcnVuLW1pZ3JhdGlv
-biIpLCRhc3luYyQkMSkKY2FzZSA2OndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKQpwLnB1c2goNSkKdD00
-CmJyZWFrCmNhc2UgMzpyPTIKbD1xCm89SC5SdShsKQpuPUgudHMobCkKTC5xSigicmVydW4gbWlncmF0
-aW9uOiAiK0guZChvKSxuKQp3aW5kb3cuYWxlcnQoIkZhaWxlZCB0byByZXJ1biBtaWdyYXRpb246ICIr
-SC5kKG8pKyIuIikKcC5wdXNoKDUpCnQ9NApicmVhawpjYXNlIDI6cD1bMV0KY2FzZSA0OnI9MQpkb2N1
-bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoInJlcnVubmluZyIpCnQ9cC5wb3AoKQpicmVhawpjYXNl
-IDU6cmV0dXJuIFAueUMobnVsbCxzKQpjYXNlIDE6cmV0dXJuIFAuZjMocSxzKX19KQpyZXR1cm4gUC5E
-SSgkYXN5bmMkJDEscyl9LAokUzo0Mn0KTC5MLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0
-LHMscgp1LkIuYShhKQp0PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZQpzPUwuRzYod2luZG93LmxvY2F0
-aW9uLmhyZWYpCnI9TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikKaWYodC5sZW5ndGg+MSlMLkc3KHQs
-cyxyLCExLG51bGwpCmVsc2V7TC5CRSh0LG5ldyBCLnFwKCIiLCIiLCIiLEMuQ00pLCEwKQpMLkJYKCIm
-bmJzcDsiLG51bGwpfX0sCiRTOjIwfQpMLld4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0
-LHMscixxPSJjb2xsYXBzZWQiCnUuVi5hKGEpCnQ9dGhpcy5hCnM9Si5SRSh0KQpyPXRoaXMuYgppZigh
-cy5nREQodCkudGcoMCxxKSl7cy5nREQodCkuQSgwLHEpCkouZFIocikuQSgwLHEpfWVsc2V7cy5nREQo
-dCkuUnooMCxxKQpKLmRSKHIpLlJ6KDAscSl9fSwKJFM6Nn0KTC5BTy5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXt2YXIgdD1KLnFGKHUuaC5hKGEpKSxzPXQuJHRpLHI9cy5DKCJ+KDEpIikuYShuZXcgTC5k
-Tih0aGlzLmEpKQp1Lk0uYShudWxsKQpXLkpFKHQuYSx0LmIsciwhMSxzLmMpfSwKJFM6M30KTC5kTi5w
-cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1LlYuYShhKQp0PWRvY3VtZW50LnF1ZXJ5U2Vs
-ZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQp0LnRvU3RyaW5nCkwudDIoYSx0aGlzLmEsdC5nZXRBdHRy
-aWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyh0KSkuWSgicGF0aCIpKSl9LAokUzo2fQpMLkhv
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LmguYShhKQp0PUoucUYoYSkKcz10
-LiR0aQpyPXMuQygifigxKSIpLmEobmV3IEwueHooYSx0aGlzLmEpKQp1Lk0uYShudWxsKQpXLkpFKHQu
-YSx0LmIsciwhMSxzLmMpfSwKJFM6M30KTC54ei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-dCxzPW51bGwKdS5WLmEoYSkKdD10aGlzLmEKTC5oWCh0aGlzLmIsUC5RQSh0LmdldEF0dHJpYnV0ZSgi
-ZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHQpKS5ZKCJvZmZzZXQiKSkscyxzKSxQLlFBKHQuZ2V0QXR0
-cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcodCkpLlkoImxpbmUiKSkscyxzKSl9LAokUzo2
-fQpMLklDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PUoucUYodS5oLmEoYSkpLHM9dC4k
-dGkKcy5DKCJ+KDEpIikuYShMLkgwKCkpCnUuTS5hKG51bGwpClcuSkUodC5hLHQuYixMLkgwKCksITEs
-cy5jKX0sCiRTOjN9CkwuTDEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5yLmEoYSkK
-dD1hLnN0YXR1cwppZih0PT09MjAwKXJldHVybiBhCmVsc2UgdGhyb3cgSC5iKCJSZXF1ZXN0IGZhaWxl
-ZDsgc3RhdHVzIG9mICIrSC5kKHQpKX0sCiRTOjQ0fQpMLm5ULnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
-KCl7TC5Gcih0aGlzLmEuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjB9CkwuQloucHJvdG90eXBlPXsKJDA6
-ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYS5hLG51bGwsbnVsbCl9LAokUzowfQpMLkdILnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3UuaC5hKGEpCiQuekIoKS50b1N0cmluZwp1LncuYSgkLm93KCkucSgwLCJo
-bGpzIikpLlY3KCJoaWdobGlnaHRCbG9jayIsW2FdKX0sCiRTOjN9CkwuRFQucHJvdG90eXBlPXsKJDE6
-ZnVuY3Rpb24oYSl7dmFyIHQscwp1LnIuYShhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDApe3Q9Qy5DdC5w
-VygwLGEucmVzcG9uc2VUZXh0LG51bGwpCnM9Si5VNih0KQpMLlQxKG5ldyBVLmQyKFUuamYocy5xKHQs
-ImVkaXRzIikpLEguYyhzLnEodCwiZXhwbGFuYXRpb24iKSksSC5XWShzLnEodCwibGluZSIpKSxILmMo
-cy5xKHQsInBhdGgiKSksVS5OZChzLnEodCwidHJhY2VzIikpKSkKTC5Gcih0aGlzLmEsdGhpcy5iLHRo
-aXMuYykKTC55WCgiLmVkaXQtcGFuZWwgLnBhbmVsLWNvbnRlbnQiLCExKX1lbHNlIHdpbmRvdy5hbGVy
-dCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLmVILnByb3RvdHlw
-ZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZFJlZ2lvbkV4cGxhbmF0aW9uOiAiK0guZChhKSxi
-KQp3aW5kb3cuYWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrSC5kKHRoaXMuYSkrIiAoIitILmQoYSkrIiku
-Iil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLnl1LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscj10aGlzCnUuci5hKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7cz1yLmEKTC5CRShzLEIu
-WWYodS5iLmEoQy5DdC5wVygwLGEucmVzcG9uc2VUZXh0LG51bGwpKSksci5iKQp0PXIuYwpMLmZHKHQs
-ci5kKQpMLkJYKEMueEIudGcocywiPyIpP0MueEIuTmoocywwLEMueEIuT1kocywiPyIpKTpzLHQpCnQ9
-ci5lCmlmKHQhPW51bGwpdC4kMCgpfWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1ZXN0IGZhaWxlZDsgc3Rh
-dHVzIG9mICIrSC5kKHQpKX0sCiRTOjd9CkwuekQucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtM
-LnFKKCJsb2FkRmlsZTogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK3Ro
-aXMuYSsiICgiK0guZChhKSsiKS4iKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjF9CkwuVFcucHJvdG90eXBl
-PXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCnUuci5hKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7
-cz1DLkN0LnBXKDAsYS5yZXNwb25zZVRleHQsbnVsbCkKcj1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIu
-bmF2LXRyZWUiKQpKLmw1KHIsIiIpCkwudFgocixMLm1LKHMpKX1lbHNlIHdpbmRvdy5hbGVydCgiUmVx
-dWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLnhyLnByb3RvdHlwZT17CiQy
-OmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZE5hdmlnYXRpb25UcmVlOiAiK0guZChhKSxiKQp3aW5kb3cu
-YWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrdGhpcy5hKyIgKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwK
-JFI6MiwKJFM6MX0KTC5FRS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzCnUuVi5hKGEp
-CnQ9dGhpcy5hCnM9dGhpcy5iCkwuYWYod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHQscywhMCxuZXcg
-TC5RTCh0LHMpKQpMLmhYKHRoaXMuYyx0LHMpfSwKJFM6Nn0KTC5RTC5wcm90b3R5cGU9ewokMDpmdW5j
-dGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0K
-TC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzPSJzZWxlY3RlZC1maWxlIgp1Lmgu
-YShhKQphLnRvU3RyaW5nCnQ9Si5SRShhKQppZihhLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5
-KG5ldyBXLmk3KGEpKS5ZKCJuYW1lIikpPT09dGhpcy5hLmEpdC5nREQoYSkuQSgwLHMpCmVsc2UgdC5n
-REQoYSkuUnooMCxzKX0sCiRTOjN9CkwuVEQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEwudDIodS5WLmEoYSksITAsbnVsbCl9LAokUzoyMX0KTC5YQS5wcm90b3R5cGU9ewpFYjpmdW5jdGlv
-bihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCiRpa0Y6MX0KTC5aWi5w
-cm90b3R5cGU9e30KTC5XQS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpN
-LmxJLnByb3RvdHlwZT17CldPOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1udWxsCk0uWUYoImFic29sdXRl
-IixILlZNKFtiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSx1LnMpKQp0PXRoaXMuYQp0PXQu
-WXIoYik+MCYmIXQuaEsoYikKaWYodClyZXR1cm4gYgp0PUQuUlgoKQpyZXR1cm4gdGhpcy5xNygwLHQs
-YixzLHMscyxzLHMscyl9LAp0TTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9WC5DTChhLHRoaXMuYSkKci5J
-VigpCnQ9ci5kCnM9dC5sZW5ndGgKaWYocz09PTApe3Q9ci5iCnJldHVybiB0PT1udWxsPyIuIjp0fWlm
-KHM9PT0xKXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZigwPj1zKXJldHVybiBILmsodCwtMSkK
-dC5wb3AoKQpDLk5tLm12KHIuZSkKci5JVigpCnJldHVybiByLlooMCl9LApxNzpmdW5jdGlvbihhLGIs
-YyxkLGUsZixnLGgsaSl7dmFyIHQ9SC5WTShbYixjLGQsZSxmLGcsaCxpXSx1LnMpCk0uWUYoImpvaW4i
-LHQpCnJldHVybiB0aGlzLklQKG5ldyBILlU1KHQsdS5iQi5hKG5ldyBNLk1pKCkpLHUuY2MpKX0sCklQ
-OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbAp1LlguYShhKQpmb3IodD1hLiR0aSxzPXQu
-QygiYTIoTHkuRSkiKS5hKG5ldyBNLnE3KCkpLHI9YS5ndyhhKSx0PW5ldyBILnZHKHIscyx0LkMoInZH
-PEx5LkU+IikpLHM9dGhpcy5hLHE9ITEscD0hMSxvPSIiO3QubSgpOyl7bj1yLmdSKHIpCmlmKHMuaEso
-bikmJnApe209WC5DTChuLHMpCmw9by5jaGFyQ29kZUF0KDApPT0wP286bwpvPUMueEIuTmoobCwwLHMu
-U3AobCwhMCkpCm0uYj1vCmlmKHMuZHMobykpQy5ObS50KG0uZSwwLHMuZ21JKCkpCm89bS5aKDApfWVs
-c2UgaWYocy5ZcihuKT4wKXtwPSFzLmhLKG4pCm89SC5kKG4pfWVsc2V7aWYoIShuLmxlbmd0aD4wJiZz
-LlVkKG5bMF0pKSlpZihxKW8rPXMuZ21JKCkKbys9SC5kKG4pfXE9cy5kcyhuKX1yZXR1cm4gby5jaGFy
-Q29kZUF0KDApPT0wP286b30sCm81OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoIXRoaXMueTMoYikpcmV0
-dXJuIGIKdD1YLkNMKGIsdGhpcy5hKQp0LnJSKDApCnJldHVybiB0LlooMCl9LAp5MzpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIscSxwLG8sbixtLGwsawphLnRvU3RyaW5nCnQ9dGhpcy5hCnM9dC5ZcihhKQppZihz
-IT09MCl7aWYodD09PSQuS2soKSlmb3Iocj0wO3I8czsrK3IpaWYoQy54Qi5XZChhLHIpPT09NDcpcmV0
-dXJuITAKcT1zCnA9NDd9ZWxzZXtxPTAKcD1udWxsfWZvcihvPW5ldyBILnFqKGEpLmEsbj1vLmxlbmd0
-aCxyPXEsbT1udWxsO3I8bjsrK3IsbT1wLHA9bCl7bD1DLnhCLk8yKG8scikKaWYodC5yNChsKSl7aWYo
-dD09PSQuS2soKSYmbD09PTQ3KXJldHVybiEwCmlmKHAhPW51bGwmJnQucjQocCkpcmV0dXJuITAKaWYo
-cD09PTQ2KWs9bT09bnVsbHx8bT09PTQ2fHx0LnI0KG0pCmVsc2Ugaz0hMQppZihrKXJldHVybiEwfX1p
-ZihwPT1udWxsKXJldHVybiEwCmlmKHQucjQocCkpcmV0dXJuITAKaWYocD09PTQ2KXQ9bT09bnVsbHx8
-dC5yNChtKXx8bT09PTQ2CmVsc2UgdD0hMQppZih0KXJldHVybiEwCnJldHVybiExfSwKSFA6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIscSxwLG89dGhpcyxuPSdVbmFibGUgdG8gZmluZCBhIHBhdGggdG8gIicK
-Yj1vLldPKDAsYikKdD1vLmEKaWYodC5ZcihiKTw9MCYmdC5ZcihhKT4wKXJldHVybiBvLm81KDAsYSkK
-aWYodC5ZcihhKTw9MHx8dC5oSyhhKSlhPW8uV08oMCxhKQppZih0LllyKGEpPD0wJiZ0LllyKGIpPjAp
-dGhyb3cgSC5iKFguSTcobitILmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnM9WC5DTChiLHQp
-CnMuclIoMCkKcj1YLkNMKGEsdCkKci5yUigwKQpxPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0s
-Ii4iKSlyZXR1cm4gci5aKDApCnE9cy5iCnA9ci5iCmlmKHEhPXApcT1xPT1udWxsfHxwPT1udWxsfHwh
-dC5OYyhxLHApCmVsc2UgcT0hMQppZihxKXJldHVybiByLlooMCkKd2hpbGUoITApe3E9cy5kCmlmKHEu
-bGVuZ3RoPjApe3A9ci5kCnE9cC5sZW5ndGg+MCYmdC5OYyhxWzBdLHBbMF0pfWVsc2UgcT0hMQppZigh
-cSlicmVhawpDLk5tLlc0KHMuZCwwKQpDLk5tLlc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0
-KHIuZSwxKX1xPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4uIikpdGhyb3cgSC5iKFguSTco
-bitILmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnE9dS5OCkMuTm0uVUcoci5kLDAsUC5POChz
-LmQubGVuZ3RoLCIuLiIscSkpCkMuTm0udChyLmUsMCwiIikKQy5ObS5VRyhyLmUsMSxQLk84KHMuZC5s
-ZW5ndGgsdC5nbUkoKSxxKSkKdD1yLmQKcT10Lmxlbmd0aAppZihxPT09MClyZXR1cm4iLiIKaWYocT4x
-JiZKLlJNKEMuTm0uZ3JaKHQpLCIuIikpe3Q9ci5kCmlmKDA+PXQubGVuZ3RoKXJldHVybiBILmsodCwt
-MSkKdC5wb3AoKQp0PXIuZQpDLk5tLm12KHQpCkMuTm0ubXYodCkKQy5ObS5BKHQsIiIpfXIuYj0iIgpy
-LklWKCkKcmV0dXJuIHIuWigwKX19Ck0uTWkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEguYyhhKSE9bnVsbH0sCiRTOjl9Ck0ucTcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEguYyhhKSE9PSIifSwKJFM6OX0KTS5Oby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtILmMoYSkK
-cmV0dXJuIGE9PW51bGw/Im51bGwiOiciJythKyciJ30sCiRTOjV9CkIuTHUucHJvdG90eXBlPXsKeFo6
-ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLllyKGEpCmlmKHM+MClyZXR1cm4gSi5sZChhLDAscykKaWYo
-dGhpcy5oSyhhKSl7aWYoMD49YS5sZW5ndGgpcmV0dXJuIEguayhhLDApCnQ9YVswXX1lbHNlIHQ9bnVs
-bApyZXR1cm4gdH0sCk5jOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PWJ9fQpYLldELnByb3RvdHlwZT17
-CklWOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMKd2hpbGUoITApe3Q9ci5kCmlmKCEodC5sZW5ndGgh
-PT0wJiZKLlJNKEMuTm0uZ3JaKHQpLCIiKSkpYnJlYWsKdD1yLmQKaWYoMD49dC5sZW5ndGgpcmV0dXJu
-IEguayh0LC0xKQp0LnBvcCgpCkMuTm0ubXYoci5lKX10PXIuZQpzPXQubGVuZ3RoCmlmKHM+MClDLk5t
-LnQodCxzLTEsIiIpfSwKclI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzLGw9SC5W
-TShbXSx1LnMpCmZvcih0PW0uZCxzPXQubGVuZ3RoLHI9MCxxPTA7cTx0Lmxlbmd0aDt0Lmxlbmd0aD09
-PXN8fCgwLEgubGspKHQpLCsrcSl7cD10W3FdCm89Si5pYShwKQppZighKG8uRE4ocCwiLiIpfHxvLkRO
-KHAsIiIpKSlpZihvLkROKHAsIi4uIikpaWYobC5sZW5ndGg+MClsLnBvcCgpCmVsc2UgKytyCmVsc2Ug
-Qy5ObS5BKGwscCl9aWYobS5iPT1udWxsKUMuTm0uVUcobCwwLFAuTzgociwiLi4iLHUuTikpCmlmKGwu
-bGVuZ3RoPT09MCYmbS5iPT1udWxsKUMuTm0uQShsLCIuIikKbj1QLmRIKGwubGVuZ3RoLG5ldyBYLnFS
-KG0pLCEwLHUuTikKdD1tLmIKdD10IT1udWxsJiZsLmxlbmd0aD4wJiZtLmEuZHModCk/bS5hLmdtSSgp
-OiIiCkgudDYobikuYy5hKHQpCmlmKCEhbi5maXhlZCRsZW5ndGgpSC5WaihQLkw0KCJpbnNlcnQiKSkK
-bi5zcGxpY2UoMCwwLHQpCm0uc25KKGwpCm0uc1BoKG4pCnQ9bS5iCmlmKHQhPW51bGwmJm0uYT09PSQu
-S2soKSl7dC50b1N0cmluZwptLmI9SC55cyh0LCIvIiwiXFwiKX1tLklWKCl9LApaOmZ1bmN0aW9uKGEp
-e3ZhciB0LHMscj10aGlzLHE9ci5iCnE9cSE9bnVsbD9xOiIiCmZvcih0PTA7dDxyLmQubGVuZ3RoOysr
-dCl7cz1yLmUKaWYodD49cy5sZW5ndGgpcmV0dXJuIEguayhzLHQpCnM9cStILmQoc1t0XSkKcT1yLmQK
-aWYodD49cS5sZW5ndGgpcmV0dXJuIEguayhxLHQpCnE9cytILmQocVt0XSl9cSs9SC5kKEMuTm0uZ3Ja
-KHIuZSkpCnJldHVybiBxLmNoYXJDb2RlQXQoMCk9PTA/cTpxfSwKc25KOmZ1bmN0aW9uKGEpe3RoaXMu
-ZD11LmEuYShhKX0sCnNQaDpmdW5jdGlvbihhKXt0aGlzLmU9dS5hLmEoYSl9fQpYLnFSLnByb3RvdHlw
-ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYS5nbUkoKX0sCiRTOjQ2fQpYLmR2LnByb3Rv
-dHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIlBhdGhFeGNlcHRpb246ICIrdGhpcy5hfX0KTy5PTy5w
-cm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdvYyh0aGlzKX19CkUuT0YucHJvdG90
-eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3ZhciB0PWEubGVuZ3RoCnJldHVybiB0IT09MCYm
-Qy54Qi5PMihhLHQtMSkhPT00N30sClNwOmZ1bmN0aW9uKGEsYil7aWYoYS5sZW5ndGghPT0wJiZDLnhC
-LldkKGEsMCk9PT00NylyZXR1cm4gMQpyZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuITF9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4i
-cG9zaXgifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIi8ifX0KRi5ydS5wcm90b3R5cGU9ewpVZDpmdW5j
-dGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3
-fSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKaWYodD09PTApcmV0dXJuITEKaWYoQy54Qi5P
-MihhLHQtMSkhPT00NylyZXR1cm4hMApyZXR1cm4gQy54Qi5UYyhhLCI6Ly8iKSYmdGhpcy5ZcihhKT09
-PXR9LApTcDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9YS5sZW5ndGgKaWYocD09PTApcmV0dXJu
-IDAKaWYoQy54Qi5XZChhLDApPT09NDcpcmV0dXJuIDEKZm9yKHQ9MDt0PHA7Kyt0KXtzPUMueEIuV2Qo
-YSx0KQppZihzPT09NDcpcmV0dXJuIDAKaWYocz09PTU4KXtpZih0PT09MClyZXR1cm4gMApyPUMueEIu
-WFUoYSwiLyIsQy54Qi5RaShhLCIvLyIsdCsxKT90KzM6dCkKaWYocjw9MClyZXR1cm4gcAppZighYnx8
-cDxyKzMpcmV0dXJuIHIKaWYoIUMueEIubkMoYSwiZmlsZTovLyIpKXJldHVybiByCmlmKCFCLll1KGEs
-cisxKSlyZXR1cm4gcgpxPXIrMwpyZXR1cm4gcD09PXE/cTpyKzR9fXJldHVybiAwfSwKWXI6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGgh
-PT0wJiZDLnhCLldkKGEsMCk9PT00N30sCmdvYzpmdW5jdGlvbigpe3JldHVybiJ1cmwifSwKZ21JOmZ1
-bmN0aW9uKCl7cmV0dXJuIi8ifX0KTC5JVi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4g
-Qy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fHxhPT09OTJ9LApkczpm
-dW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQp0PUMueEIuTzIoYSx0LTEp
-CnJldHVybiEodD09PTQ3fHx0PT09OTIpfSwKU3A6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9YS5sZW5n
-dGgKaWYocj09PTApcmV0dXJuIDAKdD1DLnhCLldkKGEsMCkKaWYodD09PTQ3KXJldHVybiAxCmlmKHQ9
-PT05Mil7aWYocjwyfHxDLnhCLldkKGEsMSkhPT05MilyZXR1cm4gMQpzPUMueEIuWFUoYSwiXFwiLDIp
-CmlmKHM+MCl7cz1DLnhCLlhVKGEsIlxcIixzKzEpCmlmKHM+MClyZXR1cm4gc31yZXR1cm4gcn1pZihy
-PDMpcmV0dXJuIDAKaWYoIUIuT1ModCkpcmV0dXJuIDAKaWYoQy54Qi5XZChhLDEpIT09NTgpcmV0dXJu
-IDAKcj1DLnhCLldkKGEsMikKaWYoIShyPT09NDd8fHI9PT05MikpcmV0dXJuIDAKcmV0dXJuIDN9LApZ
-cjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiB0
-aGlzLllyKGEpPT09MX0sCk90OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09PWIpcmV0dXJuITAKaWYo
-YT09PTQ3KXJldHVybiBiPT09OTIKaWYoYT09PTkyKXJldHVybiBiPT09NDcKaWYoKGFeYikhPT0zMily
-ZXR1cm4hMQp0PWF8MzIKcmV0dXJuIHQ+PTk3JiZ0PD0xMjJ9LApOYzpmdW5jdGlvbihhLGIpe3ZhciB0
-LHMscgppZihhPT1iKXJldHVybiEwCnQ9YS5sZW5ndGgKaWYodCE9PWIubGVuZ3RoKXJldHVybiExCmZv
-cihzPUouclkoYikscj0wO3I8dDsrK3IpaWYoIXRoaXMuT3QoQy54Qi5XZChhLHIpLHMuV2QoYixyKSkp
-cmV0dXJuITEKcmV0dXJuITB9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4id2luZG93cyJ9LApnbUk6ZnVu
-Y3Rpb24oKXtyZXR1cm4iXFwifX07KGZ1bmN0aW9uIGFsaWFzZXMoKXt2YXIgdD1KLnZCLnByb3RvdHlw
-ZQp0LlQ9dC5aCnQuU2o9dC5lNwp0PUouTUYucHJvdG90eXBlCnQubj10LloKdD1QLkx5LnByb3RvdHlw
-ZQp0LkdHPXQuZXYKdD1QLk1oLnByb3RvdHlwZQp0LnhiPXQuWgp0PVcuY3YucHJvdG90eXBlCnQuRFc9
-dC5yNgp0PVcubTYucHJvdG90eXBlCnQuakY9dC5FYgp0PVAuRTQucHJvdG90eXBlCnQuVXI9dC5xCnQu
-ZTQ9dC50fSkoKTsoZnVuY3Rpb24gaW5zdGFsbFRlYXJPZmZzKCl7dmFyIHQ9aHVua0hlbHBlcnMuX3N0
-YXRpY18xLHM9aHVua0hlbHBlcnMuX3N0YXRpY18wLHI9aHVua0hlbHBlcnMuaW5zdGFsbEluc3RhbmNl
-VGVhck9mZixxPWh1bmtIZWxwZXJzLmluc3RhbGxTdGF0aWNUZWFyT2ZmLHA9aHVua0hlbHBlcnMuX2lu
-c3RhbmNlXzF1CnQoUCwiRVgiLCJaViIsMTEpCnQoUCwieXQiLCJxRyIsMTEpCnQoUCwicVciLCJCeiIs
-MTEpCnMoUCwiVjkiLCJlTiIsMikKcihQLlBmLnByb3RvdHlwZSwiZ1lKIiwwLDEsbnVsbCxbIiQyIiwi
-JDEiXSxbIncwIiwicG0iXSwyMywwKQp0KFAsIlBIIiwiTXQiLDUpCnEoVywicFMiLDQsbnVsbCxbIiQ0
-Il0sWyJVdyJdLDE5LDApCnEoVywiVjQiLDQsbnVsbCxbIiQ0Il0sWyJuWiJdLDE5LDApCnAoUC5kTS5w
-cm90b3R5cGUsImd1TSIsIlMiLDUpCnQoUCwiaUciLCJ3WSIsNCkKdChQLCJ3MCIsIkw3IiwzMikKdChM
-LCJIMCIsInVtIiwyMSl9KSgpOyhmdW5jdGlvbiBpbmhlcml0YW5jZSgpe3ZhciB0PWh1bmtIZWxwZXJz
-Lm1peGluLHM9aHVua0hlbHBlcnMuaW5oZXJpdCxyPWh1bmtIZWxwZXJzLmluaGVyaXRNYW55CnMoUC5N
-aCxudWxsKQpyKFAuTWgsW0guRkssSi52QixKLm0xLFAublksUC5MeSxILmE3LFAuQW4sSC5TVSxILlJl
-LEgud3YsUC5QbixILldVLEguTEksSC5UcCxILmY5LFAuWFMsSC5icSxILlhPLFAuWWssSC52aCxILk42
-LEguVlIsSC5FSyxILlBiLEgudFEsSC5TZCxILkpjLEguRVQsUC5XMyxQLmloLFAuRnksUC5HVixQLmI4
-LFAuUGYsUC5GZSxQLnZzLFAuT00sUC5xaCxQLk1PLFAua1QsUC54SSxQLk9ILFAubTAsUC5YdixQLmJu
-LFAubG0sUC5sRCxQLktQLFAuTWEsUC5MaixQLlVrLFAuUncsUC5ieixQLmEyLFAuaVAsUC5sZixQLms1
-LFAuS1ksUC5DRCxQLmFFLFAuRUgsUC56TSxQLlowLFAuTjMsUC5jOCxQLk9kLFAuaWIsUC5HeixQLlpk
-LFAucVUsUC5SbixQLkdELFAuRG4sUC5QRSxQLlVmLFcuaWQsVy5GayxXLkpRLFcuR20sVy52RCxXLm02
-LFcuT3csVy5XOSxXLmRXLFcuRmIsVy5rRixXLm1rLFcuS28sUC5pNixQLmFKLFAuRTQsUC5JTixQLm42
-LFUuZDIsVS5TZSxVLk1sLFUueUQsVS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwuWlosTC5XQSxNLmxJ
-LE8uT08sWC5XRCxYLmR2XSkKcihKLnZCLFtKLnlFLEouWUUsSi5NRixKLmpkLEoucUksSi5EcixILlda
-LEgucEYsVy5EMCxXLlllLFcuQXosVy5QVSxXLkJ3LFcubzQsVy5sdyxXLkxlLFcuU2IsVy5OaCxXLkpV
-LFcuSUIsVy52ZSxXLm43LFcuZWEsVy50SSxXLkdPLFcuSkMsVy5icixXLmNXLFcuU2csVy51OCxXLno2
-LFcubEcsVy5xcyxXLkFXLFcuY3MsVy5LNyxXLmNsLFcuZlQsVy5iZyxXLlk0LFcuYUQsVy5sOCxXLk9Y
-LFcuV1csVy5VaixXLm16LFcuYTMsVy50cixXLmNuLFcuRmosVy5PdixXLllELFcuWFcsVy5YVSxXLnp2
-LFAuVzIsUC5oRixQLkJWLFAudWosUC54MCxQLmZVLFAudVAsUC5qRyxQLkVELFAueFcsUC56WSxQLndq
-LFAucjIsUC5yTyxQLlUzLFAubW9dKQpyKEouTUYsW0ouaUMsSi5rZCxKLmM1XSkKcyhKLlBvLEouamQp
-CnIoSi5xSSxbSi51cixKLlZBXSkKcyhQLkxVLFAublkpCnIoUC5MVSxbSC53MixXLnd6LFcuZTddKQpz
-KEgucWosSC53MikKcihQLkx5LFtILmJRLEguaTEsSC5VNSxILlhSLFAubVcsSC5ORl0pCnIoSC5iUSxb
-SC5hTCxILmk1LFAueHVdKQpyKEguYUwsW0gubkgsSC5sSixQLmk4XSkKcyhILnh5LEguaTEpCnIoUC5B
-bixbSC5NSCxILnZHXSkKcyhQLlJVLFAuUG4pCnMoUC5HaixQLlJVKQpzKEguUEQsUC5HaikKcyhILkxQ
-LEguV1UpCnIoSC5UcCxbSC5DaixILkFtLEgubGMsSC5yLEguZEMsSC53TixQLnRoLFAuaGEsUC5WcyxQ
-LkZ0LFAueUgsUC5XTSxQLlNYLFAuR3MsUC5kYSxQLm9RLFAucFYsUC5VNyxQLnZyLFAuckgsUC5LRixQ
-LlpMLFAuUlQsUC5qWixQLnJxLFAuUlcsUC5CNSxQLlBJLFAucEssUC5oaixQLlZwLFAuT1IsUC5yYSxQ
-LnlRLFAuV0YsUC5uMSxQLmNTLFAuVkMsUC5KVCxQLmUxLFAuTlksUC5SWixQLk1FLFAueTUsUC5xMyxQ
-LnlJLFAuYzYsUC5xZCxXLkN2LFcuYlUsVy5oSCxXLkZBLFcudXEsVy5paSxXLmNYLFcuS1MsVy5BMyxX
-LnZOLFcuVXYsVy5FZyxXLkVvLFcuV2ssVy5JQSxXLmZtLFAuamcsUC5UYSxQLks1LFAuR0UsUC5ONyxQ
-LnVRLFAuUEMsUC5tdCxQLk56LFAubnAsUC5VdCxQLnZLLFAucFUsUC5xZixMLmUsTC5WVyxMLm9aLEwu
-anIsTC5xbCxMLnk4LEwuTCxMLld4LEwuQU8sTC5kTixMLkhvLEwueHosTC5JQyxMLkwxLEwublQsTC5C
-WixMLkdILEwuRFQsTC5lSCxMLnl1LEwuekQsTC5UVyxMLnhyLEwuRUUsTC5RTCxMLlZTLEwuVEQsTS5N
-aSxNLnE3LE0uTm8sWC5xUl0pCnIoUC5YUyxbSC5XMCxILmF6LEgudlYsSC5FcSxQLkM2LEgua1MsUC5M
-SyxQLkFULFAubXAsUC51YixQLmRzLFAubGosUC5VVixQLnQ3XSkKcihILmxjLFtILnp4LEguanldKQpz
-KEgua1ksUC5DNikKcyhQLmlsLFAuWWspCnIoUC5pbCxbSC5ONSxQLnV3LFcuYVQsVy5TeV0pCnIoUC5t
-VyxbSC5LVyxQLnE0XSkKcyhILmIwLEgucEYpCnIoSC5iMCxbSC5SRyxILldCXSkKcyhILlZQLEguUkcp
-CnMoSC5EZyxILlZQKQpzKEguWkcsSC5XQikKcyhILlBnLEguWkcpCnIoSC5QZyxbSC54aixILmRFLEgu
-WkEsSC53ZixILlBxLEguZUUsSC5WNl0pCnMoSC54LEgua1MpCnMoUC5aZixQLlBmKQpzKFAuSmksUC5t
-MCkKcyhQLmI2LFAuWHYpCnMoUC5SSyxQLkxqKQpyKFAuVWssW1AuQ1YsUC5aaSxQLmJ5XSkKcyhQLndJ
-LFAua1QpCnIoUC53SSxbUC52QSxQLk14LFAuRTMsUC5HWV0pCnMoUC51NSxQLlppKQpyKFAubGYsW1Au
-Q1AsUC5JZl0pCnIoUC5BVCxbUC5iSixQLmVZXSkKcyhQLnFlLFAuRG4pCnIoVy5EMCxbVy51SCxXLndK
-LFcud2EsVy5DZixXLkxyLFcuU1YsVy5vSCxXLkExLFcuTU4sVy5RVixXLnZGLFcuT2ksVy5DbSxQLmZv
-LFAuVjhdKQpyKFcudUgsW1cuY3YsVy5ueCxXLlFGLFcuQ1FdKQpyKFcuY3YsW1cucUUsUC5kNV0pCnIo
-Vy5xRSxbVy5HaCxXLmZZLFcubkIsVy5RUCxXLklGLFcuY3gsVy5oNCxXLkpLLFcud1AsVy5RYixXLlFs
-LFcuR1gsVy5TTixXLkhELFcuS1IsVy5scCxXLlRiLFcuSXYsVy5CVCxXLmZYLFcuRkJdKQpyKFcuQncs
-W1cuUmQsVy5rUixXLkhTLFcuRmhdKQpzKFcuVGYsVy5vNCkKcyhXLm9KLFcuTGUpCnMoVy5WbyxXLmtS
-KQpzKFcueFgsVy5KVSkKcyhXLkZ2LFcueFgpCnMoVy5iRyxXLnZlKQpzKFcuWWwsVy5iRykKcyhXLlQ1
-LFcuQXopCnMoVy5mZyxXLnRJKQpzKFcuWFYsVy5mZykKcyhXLkhXLFcuY1cpCnMoVy54bixXLkhXKQpz
-KFcuVmIsVy5RRikKcyhXLmZKLFcud2EpCnIoVy5lYSxbVy53NixXLmV3LFcuYmtdKQpyKFcudzYsW1cu
-SEwsVy5PS10pCnMoVy5TMCxXLmxHKQpzKFcuejIsVy5xcykKcyhXLktCLFcuY3MpCnMoVy5ETSxXLktC
-KQpzKFcuckIsVy5LNykKcyhXLkJILFcuckIpCnMoVy5mNyxXLmZUKQpzKFcuRXYsVy5mNykKcyhXLnA4
-LFcuYmcpCnMoVy5DRSxXLm9IKQpzKFcuTWssVy5DRSkKcyhXLlp4LFcuYUQpCnMoVy5ObixXLlp4KQpz
-KFcuQXMsVy5PWCkKcyhXLmpNLFcuVWopCnMoVy5YMCxXLmpNKQpzKFcuQXcsVy5RVikKcyhXLm5KLFcu
-QXcpCnMoVy5PMyxXLnRyKQpzKFcuY2ksVy5PMykKcyhXLmNPLFcuT3YpCnMoVy5QUixXLmNPKQpzKFcu
-dzQsVy5JQikKcyhXLkR4LFcuWUQpCnMoVy5GMixXLkR4KQpzKFcub2EsVy5YVykKcyhXLnJoLFcub2Ep
-CnMoVy5vMyxXLlhVKQpzKFcuTE8sVy5vMykKcyhXLm56LFcuenYpCnMoVy5iMSxXLm56KQpzKFcuaTcs
-Vy5hVCkKcyhQLmRNLFAuUkspCnIoUC5kTSxbVy5JNCxQLktlXSkKcyhXLlJPLFAucWgpCnMoVy5ldSxX
-LlJPKQpzKFcueEMsUC5NTykKcyhXLmN0LFcubTYpCnMoUC5CZixQLmk2KQpzKFAuemcsUC5hSikKcyhQ
-LmUzLFAuVzIpCnIoUC5FNCxbUC5yNyxQLmNvXSkKcyhQLlR6LFAuY28pCnMoUC50bixQLklOKQpzKFAu
-R0MsUC5mVSkKcyhQLnE2LFAuR0MpCnMoUC5qUyxQLmpHKQpzKFAuTFosUC5qUykKcyhQLm5kLFAuZDUp
-CnMoUC5kUyxQLnhXKQpzKFAuS3EsUC5kUykKcyhQLk1ZLFAud2opCnMoUC5OQyxQLk1ZKQpzKFAuRFgs
-UC5VMykKcyhQLkduLFAuVjgpCnMoUC5LZyxQLm1vKQpzKFAuRm4sUC5LZykKcyhCLkx1LE8uT08pCnIo
-Qi5MdSxbRS5PRixGLnJ1LEwuSVZdKQp0KEgudzIsSC5SZSkKdChILlJHLFAubEQpCnQoSC5WUCxILlNV
-KQp0KEguV0IsUC5sRCkKdChILlpHLEguU1UpCnQoUC5uWSxQLmxEKQp0KFAuTGosUC5NYSkKdChQLlJV
-LFAuS1ApCnQoVy5MZSxXLmlkKQp0KFcuSlUsUC5sRCkKdChXLnhYLFcuR20pCnQoVy52ZSxQLmxEKQp0
-KFcuYkcsVy5HbSkKdChXLnRJLFAubEQpCnQoVy5mZyxXLkdtKQp0KFcuY1csUC5sRCkKdChXLkhXLFcu
-R20pCnQoVy5sRyxQLllrKQp0KFcucXMsUC5ZaykKdChXLmNzLFAubEQpCnQoVy5LQixXLkdtKQp0KFcu
-SzcsUC5sRCkKdChXLnJCLFcuR20pCnQoVy5mVCxQLmxEKQp0KFcuZjcsVy5HbSkKdChXLmJnLFAuWWsp
-CnQoVy5vSCxQLmxEKQp0KFcuQ0UsVy5HbSkKdChXLmFELFAubEQpCnQoVy5aeCxXLkdtKQp0KFcuT1gs
-UC5ZaykKdChXLlVqLFAubEQpCnQoVy5qTSxXLkdtKQp0KFcuUVYsUC5sRCkKdChXLkF3LFcuR20pCnQo
-Vy50cixQLmxEKQp0KFcuTzMsVy5HbSkKdChXLk92LFAubEQpCnQoVy5jTyxXLkdtKQp0KFcuWUQsUC5s
-RCkKdChXLkR4LFcuR20pCnQoVy5YVyxQLmxEKQp0KFcub2EsVy5HbSkKdChXLlhVLFAubEQpCnQoVy5v
-MyxXLkdtKQp0KFcuenYsUC5sRCkKdChXLm56LFcuR20pCnQoUC5jbyxQLmxEKQp0KFAuZlUsUC5sRCkK
-dChQLkdDLFcuR20pCnQoUC5qRyxQLmxEKQp0KFAualMsVy5HbSkKdChQLnhXLFAubEQpCnQoUC5kUyxX
-LkdtKQp0KFAud2osUC5sRCkKdChQLk1ZLFcuR20pCnQoUC5VMyxQLllrKQp0KFAubW8sUC5sRCkKdChQ
-LktnLFcuR20pfSkoKQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30sZVQ6e30s
-dFBWOnt9LHNFQTpbXX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntJZjoiaW50IixDUDoiZG91YmxlIixsZjoi
-bnVtIixxVToiU3RyaW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xlZE5hbWVz
-Ont9LGdldFR5cGVGcm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBlczpbImM4
-KCkiLCJjOChALEApIiwifigpIiwiYzgoY3YpIiwiQChAKSIsInFVKHFVKSIsImM4KE9LKSIsImM4KGZK
-KSIsIn4ocVUsQCkiLCJhMihxVSkiLCJ+KEApIiwifih+KCkpIiwiYzgocVUscVUpIiwiYzgocVUsQCki
-LCJ+KHh1PHFVPikiLCJjOChxVSkiLCJ+KHFVLHFVKSIsImEyKGtGKSIsImM4KEApIiwiYTIoY3YscVUs
-cVUsSlEpIiwiYzgoZWEpIiwifihPSykiLCJuNihJZikiLCJ+KE1oW0d6XSkiLCJaMDxxVSxxVT4oWjA8
-cVUscVU+LHFVKSIsImEyKHVIKSIsImM4KEBbR3pdKSIsImM4KGV3KSIsIkAocVUpIiwiQChlYSkiLCJ2
-czxAPihAKSIsIn4ocVVbQF0pIiwiTWgoQCkiLCJAKEAsQCkiLCJhMih4dTxxVT4pIiwiSWYoSWYsSWYp
-IiwicjcoQCkiLCJUejxAPihAKSIsIkU0KEApIiwiYzgofigpKSIsImM4KEAsR3opIiwifih1SCx1SCki
-LCJiODxjOD4oT0spIiwiYzgoSWYsQCkiLCJmSihmSikiLCJAKEAscVUpIiwicVUoSWYpIiwiYzgoR0Qs
-QCkiLCJ+KHFVLElmKSIsIm42KEAsQCkiXSxpbnRlcmNlcHRvcnNCeVRhZzpudWxsLGxlYWZUYWdzOm51
-bGwsYXJyYXlSdGk6dHlwZW9mIFN5bWJvbD09ImZ1bmN0aW9uIiYmdHlwZW9mIFN5bWJvbCgpPT0ic3lt
-Ym9sIj9TeW1ib2woIiR0aSIpOiIkdGkifQpILnhiKHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3si
-YzUiOiJNRiIsImlDIjoiTUYiLCJrZCI6Ik1GIiwicngiOiJlYSIsImU1IjoiZWEiLCJXSyI6IlY4Iiwi
-YzAiOiJEMCIsImZ5IjoiRDAiLCJjZyI6IkQwIiwiWTAiOiJkNSIsInRwIjoiZDUiLCJHOCI6ImV3Iiwi
-TXIiOiJxRSIsImVMIjoicUUiLCJJMCI6InVIIiwiaHMiOiJ1SCIsIlhnIjoiUUYiLCJ5YyI6Ik9LIiwi
-ajYiOiJNTiIsInk0IjoidzYiLCJhUCI6IkNtIiwieGMiOiJueCIsImtKIjoibngiLCJqNyI6IndhIiwi
-UUgiOiJ4biIsIkg2IjoibHciLCJ6QyI6IldXIiwielUiOiJEZyIsImRmIjoicEYiLCJ5RSI6eyJhMiI6
-W119LCJZRSI6eyJjOCI6W119LCJNRiI6eyJ2bSI6W10sIkVIIjpbXX0sImpkIjp7InpNIjpbIjEiXSwi
-YlEiOlsiMSJdLCJMeSI6WyIxIl19LCJQbyI6eyJqZCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJd
-LCJMeSI6WyIxIl19LCJtMSI6eyJBbiI6WyIxIl19LCJxSSI6eyJDUCI6W10sImxmIjpbXX0sInVyIjp7
-IklmIjpbXSwiQ1AiOltdLCJsZiI6W119LCJWQSI6eyJDUCI6W10sImxmIjpbXX0sIkRyIjp7InFVIjpb
-XSwidlgiOltdfSwicWoiOnsiUmUiOlsiSWYiXSwibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwiYlEiOlsi
-SWYiXSwiTHkiOlsiSWYiXSwibEQuRSI6IklmIiwiUmUuRSI6IklmIn0sImJRIjp7Ikx5IjpbIjEiXX0s
-ImFMIjp7ImJRIjpbIjEiXSwiTHkiOlsiMSJdfSwibkgiOnsiYUwiOlsiMSJdLCJiUSI6WyIxIl0sIkx5
-IjpbIjEiXSwiYUwuRSI6IjEiLCJMeS5FIjoiMSJ9LCJhNyI6eyJBbiI6WyIxIl19LCJpMSI6eyJMeSI6
-WyIyIl0sIkx5LkUiOiIyIn0sInh5Ijp7ImkxIjpbIjEiLCIyIl0sImJRIjpbIjIiXSwiTHkiOlsiMiJd
-LCJMeS5FIjoiMiJ9LCJNSCI6eyJBbiI6WyIyIl19LCJsSiI6eyJhTCI6WyIyIl0sImJRIjpbIjIiXSwi
-THkiOlsiMiJdLCJhTC5FIjoiMiIsIkx5LkUiOiIyIn0sIlU1Ijp7Ikx5IjpbIjEiXSwiTHkuRSI6IjEi
-fSwidkciOnsiQW4iOlsiMSJdfSwidzIiOnsiUmUiOlsiMSJdLCJsRCI6WyIxIl0sInpNIjpbIjEiXSwi
-YlEiOlsiMSJdLCJMeSI6WyIxIl19LCJ3diI6eyJHRCI6W119LCJQRCI6eyJHaiI6WyIxIiwiMiJdLCJS
-VSI6WyIxIiwiMiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwi
-V1UiOnsiWjAiOlsiMSIsIjIiXX0sIkxQIjp7IldVIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJY
-UiI6eyJMeSI6WyIxIl0sIkx5LkUiOiIxIn0sIkxJIjp7InZRIjpbXX0sIlcwIjp7IlhTIjpbXX0sImF6
-Ijp7IlhTIjpbXX0sInZWIjp7IlhTIjpbXX0sIlhPIjp7Ikd6IjpbXX0sIlRwIjp7IkVIIjpbXX0sImxj
-Ijp7IkVIIjpbXX0sInp4Ijp7IkVIIjpbXX0sImp5Ijp7IkVIIjpbXX0sIkVxIjp7IlhTIjpbXX0sImtZ
-Ijp7IlhTIjpbXX0sIk41Ijp7IkZvIjpbIjEiLCIyIl0sIllrIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIy
-Il0sIllrLksiOiIxIiwiWWsuViI6IjIifSwiaTUiOnsiYlEiOlsiMSJdLCJMeSI6WyIxIl0sIkx5LkUi
-OiIxIn0sIk42Ijp7IkFuIjpbIjEiXX0sIlZSIjp7IndMIjpbXSwidlgiOltdfSwiRUsiOnsiaWIiOltd
-LCJPZCI6W119LCJLVyI6eyJMeSI6WyJpYiJdLCJMeS5FIjoiaWIifSwiUGIiOnsiQW4iOlsiaWIiXX0s
-InRRIjp7Ik9kIjpbXX0sIk5GIjp7Ikx5IjpbIk9kIl0sIkx5LkUiOiJPZCJ9LCJTZCI6eyJBbiI6WyJP
-ZCJdfSwicEYiOnsiQVMiOltdfSwiYjAiOnsiWGoiOlsiQCJdLCJwRiI6W10sIkFTIjpbXX0sIkRnIjp7
-ImxEIjpbIkNQIl0sIlhqIjpbIkAiXSwiek0iOlsiQ1AiXSwicEYiOltdLCJiUSI6WyJDUCJdLCJTVSI6
-WyJDUCJdLCJBUyI6W10sIkx5IjpbIkNQIl0sImxELkUiOiJDUCJ9LCJQZyI6eyJsRCI6WyJJZiJdLCJ6
-TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwiU1UiOlsiSWYiXSwiQVMiOltd
-LCJMeSI6WyJJZiJdfSwieGoiOnsibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwiWGoiOlsiQCJdLCJwRiI6
-W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpbXSwiTHkiOlsiSWYiXSwibEQuRSI6IklmIn0s
-ImRFIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwicEYiOltdLCJiUSI6WyJJZiJd
-LCJTVSI6WyJJZiJdLCJBUyI6W10sIkx5IjpbIklmIl0sImxELkUiOiJJZiJ9LCJaQSI6eyJsRCI6WyJJ
-ZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwiU1UiOlsiSWYiXSwi
-QVMiOltdLCJMeSI6WyJJZiJdLCJsRC5FIjoiSWYifSwid2YiOnsibEQiOlsiSWYiXSwiek0iOlsiSWYi
-XSwiWGoiOlsiQCJdLCJwRiI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpbXSwiTHkiOlsi
-SWYiXSwibEQuRSI6IklmIn0sIlBxIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwi
-cEYiOltdLCJiUSI6WyJJZiJdLCJTVSI6WyJJZiJdLCJBUyI6W10sIkx5IjpbIklmIl0sImxELkUiOiJJ
-ZiJ9LCJlRSI6eyJsRCI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsi
-SWYiXSwiU1UiOlsiSWYiXSwiQVMiOltdLCJMeSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiVjYiOnsibjYi
-OltdLCJsRCI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwi
-U1UiOlsiSWYiXSwiQVMiOltdLCJMeSI6WyJJZiJdLCJsRC5FIjoiSWYifSwia1MiOnsiWFMiOltdfSwi
-eCI6eyJYUyI6W119LCJHViI6eyJBbiI6WyIxIl19LCJxNCI6eyJMeSI6WyIxIl0sIkx5LkUiOiIxIn0s
-IlpmIjp7IlBmIjpbIjEiXX0sInZzIjp7ImI4IjpbIjEiXX0sIk9IIjp7IlhTIjpbXX0sIm0wIjp7IkpC
-IjpbXX0sIkppIjp7IkpCIjpbXX0sImI2Ijp7Ilh2IjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIxIl0s
-Ikx5IjpbIjEiXX0sImxtIjp7IkFuIjpbIjEiXX0sIm1XIjp7Ikx5IjpbIjEiXX0sIkxVIjp7ImxEIjpb
-IjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sIkx5IjpbIjEiXX0sImlsIjp7IllrIjpbIjEiLCIyIl0s
-IlowIjpbIjEiLCIyIl19LCJZayI6eyJaMCI6WyIxIiwiMiJdfSwiUG4iOnsiWjAiOlsiMSIsIjIiXX0s
-IkdqIjp7IlJVIjpbIjEiLCIyIl0sIlBuIjpbIjEiLCIyIl0sIktQIjpbIjEiLCIyIl0sIlowIjpbIjEi
-LCIyIl19LCJSSyI6eyJNYSI6WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsiMSJdLCJMeSI6WyIxIl19LCJY
-diI6eyJ4dSI6WyIxIl0sImJRIjpbIjEiXSwiTHkiOlsiMSJdfSwidXciOnsiWWsiOlsicVUiLCJAIl0s
-IlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5WIjoiQCJ9LCJpOCI6eyJhTCI6WyJxVSJdLCJi
-USI6WyJxVSJdLCJMeSI6WyJxVSJdLCJhTC5FIjoicVUiLCJMeS5FIjoicVUifSwiQ1YiOnsiVWsiOlsi
-ek08SWY+IiwicVUiXSwiVWsuUyI6InpNPElmPiJ9LCJ2QSI6eyJ3SSI6WyJ6TTxJZj4iLCJxVSJdfSwi
-WmkiOnsiVWsiOlsicVUiLCJ6TTxJZj4iXX0sImJ5Ijp7IlVrIjpbIk1oIiwicVUiXSwiVWsuUyI6Ik1o
-In0sIk14Ijp7IndJIjpbInFVIiwiTWgiXX0sInU1Ijp7IlVrIjpbInFVIiwiek08SWY+Il0sIlVrLlMi
-OiJxVSJ9LCJFMyI6eyJ3SSI6WyJxVSIsInpNPElmPiJdfSwiR1kiOnsid0kiOlsiek08SWY+IiwicVUi
-XX0sIkNQIjp7ImxmIjpbXX0sIkM2Ijp7IlhTIjpbXX0sIkxLIjp7IlhTIjpbXX0sIkFUIjp7IlhTIjpb
-XX0sImJKIjp7IlhTIjpbXX0sImVZIjp7IlhTIjpbXX0sIm1wIjp7IlhTIjpbXX0sInViIjp7IlhTIjpb
-XX0sImRzIjp7IlhTIjpbXX0sImxqIjp7IlhTIjpbXX0sIlVWIjp7IlhTIjpbXX0sIms1Ijp7IlhTIjpb
-XX0sIktZIjp7IlhTIjpbXX0sInQ3Ijp7IlhTIjpbXX0sIklmIjp7ImxmIjpbXX0sInpNIjp7ImJRIjpb
-IjEiXSwiTHkiOlsiMSJdfSwiaWIiOnsiT2QiOltdfSwieHUiOnsiYlEiOlsiMSJdLCJMeSI6WyIxIl19
-LCJaZCI6eyJHeiI6W119LCJxVSI6eyJ2WCI6W119LCJSbiI6eyJCTCI6W119LCJEbiI6eyJpRCI6W119
-LCJVZiI6eyJpRCI6W119LCJxZSI6eyJpRCI6W119LCJxRSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltd
-fSwiR2giOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sImZZIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6
-W119LCJuQiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiUVAiOnsiY3YiOltdLCJ1SCI6W10sIkQw
-IjpbXX0sIklGIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJueCI6eyJ1SCI6W10sIkQwIjpbXX0s
-ImN4Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJRRiI6eyJ1SCI6W10sIkQwIjpbXX0sIkZ2Ijp7
-IkdtIjpbInRuPGxmPiJdLCJsRCI6WyJ0bjxsZj4iXSwiWGoiOlsidG48bGY+Il0sInpNIjpbInRuPGxm
-PiJdLCJiUSI6WyJ0bjxsZj4iXSwiTHkiOlsidG48bGY+Il0sIkdtLkUiOiJ0bjxsZj4iLCJsRC5FIjoi
-dG48bGY+In0sIklCIjp7InRuIjpbImxmIl19LCJZbCI6eyJHbSI6WyJxVSJdLCJsRCI6WyJxVSJdLCJ6
-TSI6WyJxVSJdLCJYaiI6WyJxVSJdLCJiUSI6WyJxVSJdLCJMeSI6WyJxVSJdLCJHbS5FIjoicVUiLCJs
-RC5FIjoicVUifSwid3oiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiTHkiOlsiMSJd
-LCJsRC5FIjoiMSJ9LCJjdiI6eyJ1SCI6W10sIkQwIjpbXX0sIlQ1Ijp7IkF6IjpbXX0sIlhWIjp7Ikdt
-IjpbIlQ1Il0sImxEIjpbIlQ1Il0sIlhqIjpbIlQ1Il0sInpNIjpbIlQ1Il0sImJRIjpbIlQ1Il0sIkx5
-IjpbIlQ1Il0sIkdtLkUiOiJUNSIsImxELkUiOiJUNSJ9LCJ3SiI6eyJEMCI6W119LCJoNCI6eyJjdiI6
-W10sInVIIjpbXSwiRDAiOltdfSwieG4iOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsidUgi
-XSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiTHkiOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6InVI
-In0sIlZiIjp7InVIIjpbXSwiRDAiOltdfSwiZkoiOnsiRDAiOltdfSwid2EiOnsiRDAiOltdfSwiSksi
-OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkhMIjp7ImVhIjpbXX0sIndQIjp7ImN2IjpbXSwidUgi
-OltdLCJEMCI6W119LCJDZiI6eyJEMCI6W119LCJRYiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwi
-UzAiOnsiWWsiOlsicVUiLCJAIl0sIlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5WIjoiQCJ9
-LCJ6MiI6eyJZayI6WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllrLlYiOiJA
-In0sIkRNIjp7IkdtIjpbIkFXIl0sImxEIjpbIkFXIl0sIlhqIjpbIkFXIl0sInpNIjpbIkFXIl0sImJR
-IjpbIkFXIl0sIkx5IjpbIkFXIl0sIkdtLkUiOiJBVyIsImxELkUiOiJBVyJ9LCJPSyI6eyJlYSI6W119
-LCJlNyI6eyJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJMeSI6WyJ1SCJdLCJsRC5F
-IjoidUgifSwidUgiOnsiRDAiOltdfSwiQkgiOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsi
-dUgiXSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiTHkiOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6
-InVIIn0sIlFsIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJHWCI6eyJjdiI6W10sInVIIjpbXSwi
-RDAiOltdfSwiU04iOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkhEIjp7ImN2IjpbXSwidUgiOltd
-LCJEMCI6W119LCJFdiI6eyJHbSI6WyJjbCJdLCJsRCI6WyJjbCJdLCJ6TSI6WyJjbCJdLCJYaiI6WyJj
-bCJdLCJiUSI6WyJjbCJdLCJMeSI6WyJjbCJdLCJHbS5FIjoiY2wiLCJsRC5FIjoiY2wifSwiTHIiOnsi
-RDAiOltdfSwiS1IiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sImV3Ijp7ImVhIjpbXX0sInA4Ijp7
-IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsuViI6IkAifSwibHAi
-OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlNWIjp7IkQwIjpbXX0sIk1rIjp7IkdtIjpbIlNWIl0s
-ImxEIjpbIlNWIl0sInpNIjpbIlNWIl0sIlhqIjpbIlNWIl0sIkQwIjpbXSwiYlEiOlsiU1YiXSwiTHki
-OlsiU1YiXSwiR20uRSI6IlNWIiwibEQuRSI6IlNWIn0sIk5uIjp7IkdtIjpbIlk0Il0sImxEIjpbIlk0
-Il0sInpNIjpbIlk0Il0sIlhqIjpbIlk0Il0sImJRIjpbIlk0Il0sIkx5IjpbIlk0Il0sIkdtLkUiOiJZ
-NCIsImxELkUiOiJZNCJ9LCJBcyI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsu
-SyI6InFVIiwiWWsuViI6InFVIn0sImJrIjp7ImVhIjpbXX0sIlRiIjp7ImN2IjpbXSwidUgiOltdLCJE
-MCI6W119LCJJdiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiQlQiOnsiY3YiOltdLCJ1SCI6W10s
-IkQwIjpbXX0sImZYIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJGQiI6eyJjdiI6W10sInVIIjpb
-XSwiRDAiOltdfSwiQTEiOnsiRDAiOltdfSwiTU4iOnsiRDAiOltdfSwiWDAiOnsiR20iOlsiTU4iXSwi
-bEQiOlsiTU4iXSwiWGoiOlsiTU4iXSwiek0iOlsiTU4iXSwiYlEiOlsiTU4iXSwiTHkiOlsiTU4iXSwi
-R20uRSI6Ik1OIiwibEQuRSI6Ik1OIn0sIm5KIjp7IkdtIjpbIkExIl0sImxEIjpbIkExIl0sIlhqIjpb
-IkExIl0sInpNIjpbIkExIl0sIkQwIjpbXSwiYlEiOlsiQTEiXSwiTHkiOlsiQTEiXSwiR20uRSI6IkEx
-IiwibEQuRSI6IkExIn0sImNpIjp7IkdtIjpbImEzIl0sImxEIjpbImEzIl0sInpNIjpbImEzIl0sIlhq
-IjpbImEzIl0sImJRIjpbImEzIl0sIkx5IjpbImEzIl0sIkdtLkUiOiJhMyIsImxELkUiOiJhMyJ9LCJ3
-NiI6eyJlYSI6W119LCJ2RiI6eyJEMCI6W119LCJPaSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNtIjp7IkQw
-IjpbXX0sIkNRIjp7InVIIjpbXSwiRDAiOltdfSwiUFIiOnsiR20iOlsibHciXSwibEQiOlsibHciXSwi
-ek0iOlsibHciXSwiWGoiOlsibHciXSwiYlEiOlsibHciXSwiTHkiOlsibHciXSwiR20uRSI6Imx3Iiwi
-bEQuRSI6Imx3In0sInc0Ijp7InRuIjpbImxmIl19LCJGMiI6eyJHbSI6WyJHTyJdLCJsRCI6WyJHTyJd
-LCJYaiI6WyJHTyJdLCJ6TSI6WyJHTyJdLCJiUSI6WyJHTyJdLCJMeSI6WyJHTyJdLCJHbS5FIjoiR08i
-LCJsRC5FIjoiR08ifSwicmgiOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsidUgiXSwiWGoi
-OlsidUgiXSwiYlEiOlsidUgiXSwiTHkiOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6InVIIn0sIkxP
-Ijp7IkdtIjpbImw4Il0sImxEIjpbImw4Il0sInpNIjpbImw4Il0sIlhqIjpbImw4Il0sImJRIjpbImw4
-Il0sIkx5IjpbImw4Il0sIkdtLkUiOiJsOCIsImxELkUiOiJsOCJ9LCJiMSI6eyJHbSI6WyJXVyJdLCJs
-RCI6WyJXVyJdLCJYaiI6WyJXVyJdLCJ6TSI6WyJXVyJdLCJiUSI6WyJXVyJdLCJMeSI6WyJXVyJdLCJH
-bS5FIjoiV1ciLCJsRC5FIjoiV1cifSwiYVQiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFV
-Il19LCJpNyI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsu
-ViI6InFVIn0sIlN5Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUi
-LCJZay5WIjoicVUifSwiSTQiOnsiTWEiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiTHki
-OlsicVUiXX0sIlJPIjp7InFoIjpbIjEiXX0sImV1Ijp7IlJPIjpbIjEiXSwicWgiOlsiMSJdfSwieEMi
-OnsiTU8iOlsiMSJdfSwiSlEiOnsia0YiOltdfSwidkQiOnsia0YiOltdfSwibTYiOnsia0YiOltdfSwi
-Y3QiOnsia0YiOltdfSwiT3ciOnsia0YiOltdfSwiVzkiOnsiQW4iOlsiMSJdfSwiZFciOnsidjYiOltd
-LCJEMCI6W119LCJtayI6eyJXUSI6W119LCJLbyI6eyJvbiI6W119LCJkTSI6eyJNYSI6WyJxVSJdLCJ4
-dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJMeSI6WyJxVSJdfSwicjciOnsiRTQiOltdfSwiVHoiOnsibEQi
-OlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiRTQiOltdLCJMeSI6WyIxIl0sImxELkUiOiIxIn0s
-InE2Ijp7IkdtIjpbIngwIl0sImxEIjpbIngwIl0sInpNIjpbIngwIl0sImJRIjpbIngwIl0sIkx5Ijpb
-IngwIl0sIkdtLkUiOiJ4MCIsImxELkUiOiJ4MCJ9LCJMWiI6eyJHbSI6WyJ1UCJdLCJsRCI6WyJ1UCJd
-LCJ6TSI6WyJ1UCJdLCJiUSI6WyJ1UCJdLCJMeSI6WyJ1UCJdLCJHbS5FIjoidVAiLCJsRC5FIjoidVAi
-fSwibmQiOnsiZDUiOltdLCJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiS3EiOnsiR20iOlsicVUiXSwi
-bEQiOlsicVUiXSwiek0iOlsicVUiXSwiYlEiOlsicVUiXSwiTHkiOlsicVUiXSwiR20uRSI6InFVIiwi
-bEQuRSI6InFVIn0sIktlIjp7Ik1hIjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sIkx5Ijpb
-InFVIl19LCJkNSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiTkMiOnsiR20iOlsielkiXSwibEQi
-OlsielkiXSwiek0iOlsielkiXSwiYlEiOlsielkiXSwiTHkiOlsielkiXSwiR20uRSI6InpZIiwibEQu
-RSI6InpZIn0sIm42Ijp7InpNIjpbIklmIl0sImJRIjpbIklmIl0sIkFTIjpbXSwiTHkiOlsiSWYiXX0s
-IkRYIjp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsuViI6IkAi
-fSwiZm8iOnsiRDAiOltdfSwiVjgiOnsiRDAiOltdfSwiR24iOnsiRDAiOltdfSwiRm4iOnsiR20iOlsi
-WjA8QCxAPiJdLCJsRCI6WyJaMDxALEA+Il0sInpNIjpbIlowPEAsQD4iXSwiYlEiOlsiWjA8QCxAPiJd
-LCJMeSI6WyJaMDxALEA+Il0sIkdtLkUiOiJaMDxALEA+IiwibEQuRSI6IlowPEAsQD4ifSwiWEEiOnsi
-a0YiOltdfSwiT0YiOnsiTHUiOltdfSwicnUiOnsiTHUiOltdfSwiSVYiOnsiTHUiOltdfX0nKSkKSC5G
-Rih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNlKCd7ImJRIjoxLCJ3MiI6MSwiTU8iOjEsImtUIjoyLCJt
-VyI6MSwiTFUiOjEsImlsIjoyLCJSSyI6MSwiblkiOjEsIkxqIjoxLCJjbyI6MSwiSU4iOjF9JykpCnZh
-ciB1PShmdW5jdGlvbiBydGlpKCl7dmFyIHQ9SC5EUApyZXR1cm57aTp0KCJHaCIpLG46dCgiT0giKSxj
-Ujp0KCJuQiIpLGQ6dCgiQXoiKSxrOnQoIlFQIiksZ0Y6dCgiUEQ8R0QsQD4iKSxnNTp0KCJsdyIpLGd3
-OnQoImJRPEA+IiksaDp0KCJjdiIpLG06dCgiWFMiKSxCOnQoImVhIiksYVM6dCgiRDAiKSxPOnQoIlQ1
-IiksYlg6dCgiWFYiKSxaOnQoIkVIIiksYVE6dCgiYjg8Yzg+IiksYzp0KCJiODxAPiIpLGRQOnQoIkdP
-Iikscjp0KCJmSiIpLEk6dCgiU2ciKSxvOnQoInZRIiksZWg6dCgiTHk8dUg+IiksWDp0KCJMeTxxVT4i
-KSxSOnQoIkx5PEA+IiksZkE6dCgiamQ8U2U+IiksZ2k6dCgiamQ8ajg+IiksZmg6dCgiamQ8Wlo+Iiks
-dTp0KCJqZDxrRj4iKSxzOnQoImpkPHFVPiIpLGhoOnQoImpkPHlEPiIpLGFKOnQoImpkPHdiPiIpLHY6
-dCgiamQ8QD4iKSx0OnQoImpkPElmPiIpLGVIOnQoInZtIiksZzp0KCJjNSIpLGFVOnQoIlhqPEA+Iiks
-YW06dCgiVHo8QD4iKSxlbzp0KCJONTxHRCxAPiIpLHc6dCgiRTQiKSxkejp0KCJoRiIpLGJHOnQoIngw
-IiksZjQ6dCgiek08ajg+IiksYTp0KCJ6TTxxVT4iKSxqOnQoInpNPEA+IiksTDp0KCJ6TTxJZj4iKSxh
-Xzp0KCJ1OCIpLGY6dCgiWjA8cVUscVU+IiksYjp0KCJaMDxxVSxAPiIpLEc6dCgiWjA8QCxAPiIpLGR2
-OnQoImxKPHFVLHFVPiIpLGRvOnQoImxKPHFVLEA+IiksYks6dCgiQ2YiKSxjSTp0KCJBVyIpLFY6dCgi
-T0siKSxiWjp0KCJXWiIpLGREOnQoInBGIiksYm06dCgiVjYiKSxBOnQoInVIIiksZTp0KCJrRiIpLFA6
-dCgiYzgiKSxjazp0KCJ1UCIpLEs6dCgiTWgiKSxoZTp0KCJjbCIpLHA6dCgiZXciKSxxOnQoInRuPGxm
-PiIpLGZ2OnQoIndMIiksYXY6dCgiSmMiKSxldzp0KCJuZCIpLEM6dCgieHU8cVU+IiksZlk6dCgiU1Yi
-KSxmNzp0KCJZNCIpLGdmOnQoImw4IiksbDp0KCJHeiIpLE46dCgicVUiKSxkRzp0KCJxVShxVSkiKSxn
-bjp0KCJXVyIpLGc3OnQoImQ1IiksZm86dCgiR0QiKSxhVzp0KCJmWCIpLGEwOnQoIkExIiksYzc6dCgi
-TU4iKSxhSzp0KCJhMyIpLGNNOnQoInpZIiksRDp0KCJBUyIpLGdjOnQoIm42IiksYWs6dCgia2QiKSxF
-OnQoIkdqPHFVLHFVPiIpLEY6dCgiaUQiKSxjYzp0KCJVNTxxVT4iKSxnNDp0KCJPaSIpLGNpOnQoInY2
-IiksZzI6dCgiQ20iKSxiajp0KCJaZjxmSj4iKSxoOTp0KCJDUSIpLGFjOnQoImU3IiksUTp0KCJldTxP
-Sz4iKSxVOnQoInd6PGN2PiIpLHg6dCgiRmU8QCxAPiIpLGFvOnQoInZzPGZKPiIpLF86dCgidnM8QD4i
-KSxmSjp0KCJ2czxJZj4iKSxjcjp0KCJKUSIpLEo6dCgiYm4iKSx5OnQoImEyIiksYWw6dCgiYTIoTWgp
-IiksYkI6dCgiYTIocVUpIiksYmY6dCgiYTIoQCkiKSxnUjp0KCJDUCIpLHo6dCgiQCIpLGZPOnQoIkAo
-KSIpLGU2OnQoIkAoZWEpIiksYkk6dCgiQChNaCkiKSxlcDp0KCJAKE1oLE1oKSIpLGFnOnQoIkAoTWgs
-R3opIiksYlU6dCgiQCh4dTxxVT4pIiksZE86dCgiQChxVSkiKSxZOnQoIkAoQCxAKSIpLFM6dCgiSWYi
-KSxkaTp0KCJsZiIpLEg6dCgifiIpLE06dCgifigpIiksYW46dCgifihldykiKSxXOnQoIn4ocVUscVUp
-IiksVDp0KCJ+KHFVLEApIil9fSkoKTsoZnVuY3Rpb24gY29uc3RhbnRzKCl7dmFyIHQ9aHVua0hlbHBl
-cnMubWFrZUNvbnN0TGlzdApDLlJZPVcuUVAucHJvdG90eXBlCkMuQlo9Vy5WYi5wcm90b3R5cGUKQy5E
-dD1XLmZKLnByb3RvdHlwZQpDLk9rPUoudkIucHJvdG90eXBlCkMuTm09Si5qZC5wcm90b3R5cGUKQy5q
-bj1KLnVyLnByb3RvdHlwZQpDLmpOPUouWUUucHJvdG90eXBlCkMuQ0Q9Si5xSS5wcm90b3R5cGUKQy54
-Qj1KLkRyLnByb3RvdHlwZQpDLkRHPUouYzUucHJvdG90eXBlCkMuRXg9Vy51OC5wcm90b3R5cGUKQy50
-NT1XLkJILnByb3RvdHlwZQpDLkx0PVcuU04ucHJvdG90eXBlCkMuWlE9Si5pQy5wcm90b3R5cGUKQy5J
-ZT1XLlRiLnByb3RvdHlwZQpDLnZCPUoua2QucHJvdG90eXBlCkMub2w9Vy5PaS5wcm90b3R5cGUKQy55
-OD1uZXcgUC52QSgpCkMuaDk9bmV3IFAuQ1YoKQpDLndiPWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNrKG8p
-IHsKICB2YXIgcyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4gcy5z
-dWJzdHJpbmcoOCwgcy5sZW5ndGggLSAxKTsKfQpDLk80PWZ1bmN0aW9uKCkgewogIHZhciB0b1N0cmlu
-Z0Z1bmN0aW9uID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWcobykg
-ewogICAgdmFyIHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJzdHJp
-bmcoOCwgcy5sZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRh
-ZykgewogICAgaWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZhciBu
-YW1lID0gdG9TdHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJbb2Jq
-ZWN0IE9iamVjdF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICB9
-CiAgfQogIGZ1bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykgewog
-ICAgaWYgKHNlbGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHJl
-dHVybiAiSFRNTEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpOwog
-IH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRvdyA9
-PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09ICJ1
-bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwog
-ICAgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAgIHJl
-dHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3IodGFn
-KSB7IHJldHVybiBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9i
-amVjdCI7CiAgcmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzogaXNC
-cm93c2VyID8gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAgIHBy
-b3RvdHlwZUZvclRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3JpbWlu
-YXRvciB9Owp9CkMuZGs9ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rpb24o
-aG9va3MpIHsKICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9va3M7
-CiAgICB2YXIgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1bXBS
-ZW5kZXJUcmVlIikgPj0gMCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9tZSIp
-ID49IDApIHsKICAgICAgZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiB3
-aW5kb3cgPT0gIm9iamVjdCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAgICAg
-IH0KICAgICAgaWYgKGNvbmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50IikpIHJl
-dHVybiBob29rczsKICAgIH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07Cn0K
-Qy5ZcT1mdW5jdGlvbihob29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0
-VGFnICE9ICJmdW5jdGlvbiIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhwZXJp
-bWVudGFsRml4dXBHZXRUYWcoaG9va3MuZ2V0VGFnKTsKfQpDLktVPWZ1bmN0aW9uKGhvb2tzKSB7CiAg
-dmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3MucHJv
-dG90eXBlRm9yVGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBnZXRU
-YWcobyk7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJzaW9u
-KSByZXR1cm4gIiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9CiAg
-ICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsKICAg
-IGlmICh0YWcgPT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBlRm9y
-VGFnKHRhZyk7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3RvdHlw
-ZUZvclRhZyA9IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMueGk9ZnVuY3Rpb24oaG9va3MpIHsKICB2
-YXIgdXNlckFnZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2Vy
-QWdlbnQgOiAiIjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0dXJu
-IGhvb2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAg
-IkJlZm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJk
-IiwKICAgICJHZW9HZW9sb2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAiIUxv
-Y2F0aW9uIiwKICAgICJXb3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJYTUxE
-b2N1bWVudCI6ICIhRG9jdW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAgIHZh
-ciB0YWcgPSBnZXRUYWcobyk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQogIGhv
-b2tzLmdldFRhZyA9IGdldFRhZ0ZpcmVmb3g7Cn0KQy5pNz1mdW5jdGlvbihob29rcykgewogIHZhciB1
-c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2Vu
-dCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJuIGhv
-b2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJl
-Zm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwK
-ICAgICJIVE1MRERFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50IjogIkhU
-TUxFbGVtZW50IiwKICAgICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiUG9z
-aXRpb24iOiAiR2VvcG9zaXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2YXIg
-dGFnID0gZ2V0VGFnKG8pOwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAobmV3
-VGFnKSByZXR1cm4gbmV3VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAod2lu
-ZG93LkRhdGFWaWV3ICYmIChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJEYXRh
-VmlldyI7CiAgICB9CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdJ
-RSh0YWcpIHsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0cnVj
-dG9yID09IG51bGwpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsK
-ICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJv
-dG90eXBlRm9yVGFnSUU7Cn0KQy5mUT1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0KCkMu
-Q3Q9bmV3IFAuYnkoKQpDLkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAuRTMo
-KQpDLk5VPW5ldyBQLkppKCkKQy5wZD1uZXcgUC5aZCgpCkMuQTM9bmV3IFAuTXgobnVsbCkKQy5HYj1I
-LlZNKHQoWzEyNywyMDQ3LDY1NTM1LDExMTQxMTFdKSx1LnQpCkMuYWs9SC5WTSh0KFswLDAsMzI3NzYs
-MzM3OTIsMSwxMDI0MCwwLDBdKSx1LnQpCkMuY209SC5WTSh0KFsiKjo6Y2xhc3MiLCIqOjpkaXIiLCIq
-OjpkcmFnZ2FibGUiLCIqOjpoaWRkZW4iLCIqOjppZCIsIio6OmluZXJ0IiwiKjo6aXRlbXByb3AiLCIq
-OjppdGVtcmVmIiwiKjo6aXRlbXNjb3BlIiwiKjo6bGFuZyIsIio6OnNwZWxsY2hlY2siLCIqOjp0aXRs
-ZSIsIio6OnRyYW5zbGF0ZSIsIkE6OmFjY2Vzc2tleSIsIkE6OmNvb3JkcyIsIkE6OmhyZWZsYW5nIiwi
-QTo6bmFtZSIsIkE6OnNoYXBlIiwiQTo6dGFiaW5kZXgiLCJBOjp0YXJnZXQiLCJBOjp0eXBlIiwiQVJF
-QTo6YWNjZXNza2V5IiwiQVJFQTo6YWx0IiwiQVJFQTo6Y29vcmRzIiwiQVJFQTo6bm9ocmVmIiwiQVJF
-QTo6c2hhcGUiLCJBUkVBOjp0YWJpbmRleCIsIkFSRUE6OnRhcmdldCIsIkFVRElPOjpjb250cm9scyIs
-IkFVRElPOjpsb29wIiwiQVVESU86Om1lZGlhZ3JvdXAiLCJBVURJTzo6bXV0ZWQiLCJBVURJTzo6cHJl
-bG9hZCIsIkJETzo6ZGlyIiwiQk9EWTo6YWxpbmsiLCJCT0RZOjpiZ2NvbG9yIiwiQk9EWTo6bGluayIs
-IkJPRFk6OnRleHQiLCJCT0RZOjp2bGluayIsIkJSOjpjbGVhciIsIkJVVFRPTjo6YWNjZXNza2V5Iiwi
-QlVUVE9OOjpkaXNhYmxlZCIsIkJVVFRPTjo6bmFtZSIsIkJVVFRPTjo6dGFiaW5kZXgiLCJCVVRUT046
-OnR5cGUiLCJCVVRUT046OnZhbHVlIiwiQ0FOVkFTOjpoZWlnaHQiLCJDQU5WQVM6OndpZHRoIiwiQ0FQ
-VElPTjo6YWxpZ24iLCJDT0w6OmFsaWduIiwiQ09MOjpjaGFyIiwiQ09MOjpjaGFyb2ZmIiwiQ09MOjpz
-cGFuIiwiQ09MOjp2YWxpZ24iLCJDT0w6OndpZHRoIiwiQ09MR1JPVVA6OmFsaWduIiwiQ09MR1JPVVA6
-OmNoYXIiLCJDT0xHUk9VUDo6Y2hhcm9mZiIsIkNPTEdST1VQOjpzcGFuIiwiQ09MR1JPVVA6OnZhbGln
-biIsIkNPTEdST1VQOjp3aWR0aCIsIkNPTU1BTkQ6OmNoZWNrZWQiLCJDT01NQU5EOjpjb21tYW5kIiwi
-Q09NTUFORDo6ZGlzYWJsZWQiLCJDT01NQU5EOjpsYWJlbCIsIkNPTU1BTkQ6OnJhZGlvZ3JvdXAiLCJD
-T01NQU5EOjp0eXBlIiwiREFUQTo6dmFsdWUiLCJERUw6OmRhdGV0aW1lIiwiREVUQUlMUzo6b3BlbiIs
-IkRJUjo6Y29tcGFjdCIsIkRJVjo6YWxpZ24iLCJETDo6Y29tcGFjdCIsIkZJRUxEU0VUOjpkaXNhYmxl
-ZCIsIkZPTlQ6OmNvbG9yIiwiRk9OVDo6ZmFjZSIsIkZPTlQ6OnNpemUiLCJGT1JNOjphY2NlcHQiLCJG
-T1JNOjphdXRvY29tcGxldGUiLCJGT1JNOjplbmN0eXBlIiwiRk9STTo6bWV0aG9kIiwiRk9STTo6bmFt
-ZSIsIkZPUk06Om5vdmFsaWRhdGUiLCJGT1JNOjp0YXJnZXQiLCJGUkFNRTo6bmFtZSIsIkgxOjphbGln
-biIsIkgyOjphbGlnbiIsIkgzOjphbGlnbiIsIkg0OjphbGlnbiIsIkg1OjphbGlnbiIsIkg2OjphbGln
-biIsIkhSOjphbGlnbiIsIkhSOjpub3NoYWRlIiwiSFI6OnNpemUiLCJIUjo6d2lkdGgiLCJIVE1MOjp2
-ZXJzaW9uIiwiSUZSQU1FOjphbGlnbiIsIklGUkFNRTo6ZnJhbWVib3JkZXIiLCJJRlJBTUU6OmhlaWdo
-dCIsIklGUkFNRTo6bWFyZ2luaGVpZ2h0IiwiSUZSQU1FOjptYXJnaW53aWR0aCIsIklGUkFNRTo6d2lk
-dGgiLCJJTUc6OmFsaWduIiwiSU1HOjphbHQiLCJJTUc6OmJvcmRlciIsIklNRzo6aGVpZ2h0IiwiSU1H
-Ojpoc3BhY2UiLCJJTUc6OmlzbWFwIiwiSU1HOjpuYW1lIiwiSU1HOjp1c2VtYXAiLCJJTUc6OnZzcGFj
-ZSIsIklNRzo6d2lkdGgiLCJJTlBVVDo6YWNjZXB0IiwiSU5QVVQ6OmFjY2Vzc2tleSIsIklOUFVUOjph
-bGlnbiIsIklOUFVUOjphbHQiLCJJTlBVVDo6YXV0b2NvbXBsZXRlIiwiSU5QVVQ6OmF1dG9mb2N1cyIs
-IklOUFVUOjpjaGVja2VkIiwiSU5QVVQ6OmRpc2FibGVkIiwiSU5QVVQ6OmlucHV0bW9kZSIsIklOUFVU
-Ojppc21hcCIsIklOUFVUOjpsaXN0IiwiSU5QVVQ6Om1heCIsIklOUFVUOjptYXhsZW5ndGgiLCJJTlBV
-VDo6bWluIiwiSU5QVVQ6Om11bHRpcGxlIiwiSU5QVVQ6Om5hbWUiLCJJTlBVVDo6cGxhY2Vob2xkZXIi
-LCJJTlBVVDo6cmVhZG9ubHkiLCJJTlBVVDo6cmVxdWlyZWQiLCJJTlBVVDo6c2l6ZSIsIklOUFVUOjpz
-dGVwIiwiSU5QVVQ6OnRhYmluZGV4IiwiSU5QVVQ6OnR5cGUiLCJJTlBVVDo6dXNlbWFwIiwiSU5QVVQ6
-OnZhbHVlIiwiSU5TOjpkYXRldGltZSIsIktFWUdFTjo6ZGlzYWJsZWQiLCJLRVlHRU46OmtleXR5cGUi
-LCJLRVlHRU46Om5hbWUiLCJMQUJFTDo6YWNjZXNza2V5IiwiTEFCRUw6OmZvciIsIkxFR0VORDo6YWNj
-ZXNza2V5IiwiTEVHRU5EOjphbGlnbiIsIkxJOjp0eXBlIiwiTEk6OnZhbHVlIiwiTElOSzo6c2l6ZXMi
-LCJNQVA6Om5hbWUiLCJNRU5VOjpjb21wYWN0IiwiTUVOVTo6bGFiZWwiLCJNRU5VOjp0eXBlIiwiTUVU
-RVI6OmhpZ2giLCJNRVRFUjo6bG93IiwiTUVURVI6Om1heCIsIk1FVEVSOjptaW4iLCJNRVRFUjo6dmFs
-dWUiLCJPQkpFQ1Q6OnR5cGVtdXN0bWF0Y2giLCJPTDo6Y29tcGFjdCIsIk9MOjpyZXZlcnNlZCIsIk9M
-OjpzdGFydCIsIk9MOjp0eXBlIiwiT1BUR1JPVVA6OmRpc2FibGVkIiwiT1BUR1JPVVA6OmxhYmVsIiwi
-T1BUSU9OOjpkaXNhYmxlZCIsIk9QVElPTjo6bGFiZWwiLCJPUFRJT046OnNlbGVjdGVkIiwiT1BUSU9O
-Ojp2YWx1ZSIsIk9VVFBVVDo6Zm9yIiwiT1VUUFVUOjpuYW1lIiwiUDo6YWxpZ24iLCJQUkU6OndpZHRo
-IiwiUFJPR1JFU1M6Om1heCIsIlBST0dSRVNTOjptaW4iLCJQUk9HUkVTUzo6dmFsdWUiLCJTRUxFQ1Q6
-OmF1dG9jb21wbGV0ZSIsIlNFTEVDVDo6ZGlzYWJsZWQiLCJTRUxFQ1Q6Om11bHRpcGxlIiwiU0VMRUNU
-OjpuYW1lIiwiU0VMRUNUOjpyZXF1aXJlZCIsIlNFTEVDVDo6c2l6ZSIsIlNFTEVDVDo6dGFiaW5kZXgi
-LCJTT1VSQ0U6OnR5cGUiLCJUQUJMRTo6YWxpZ24iLCJUQUJMRTo6Ymdjb2xvciIsIlRBQkxFOjpib3Jk
-ZXIiLCJUQUJMRTo6Y2VsbHBhZGRpbmciLCJUQUJMRTo6Y2VsbHNwYWNpbmciLCJUQUJMRTo6ZnJhbWUi
-LCJUQUJMRTo6cnVsZXMiLCJUQUJMRTo6c3VtbWFyeSIsIlRBQkxFOjp3aWR0aCIsIlRCT0RZOjphbGln
-biIsIlRCT0RZOjpjaGFyIiwiVEJPRFk6OmNoYXJvZmYiLCJUQk9EWTo6dmFsaWduIiwiVEQ6OmFiYnIi
-LCJURDo6YWxpZ24iLCJURDo6YXhpcyIsIlREOjpiZ2NvbG9yIiwiVEQ6OmNoYXIiLCJURDo6Y2hhcm9m
-ZiIsIlREOjpjb2xzcGFuIiwiVEQ6OmhlYWRlcnMiLCJURDo6aGVpZ2h0IiwiVEQ6Om5vd3JhcCIsIlRE
-Ojpyb3dzcGFuIiwiVEQ6OnNjb3BlIiwiVEQ6OnZhbGlnbiIsIlREOjp3aWR0aCIsIlRFWFRBUkVBOjph
-Y2Nlc3NrZXkiLCJURVhUQVJFQTo6YXV0b2NvbXBsZXRlIiwiVEVYVEFSRUE6OmNvbHMiLCJURVhUQVJF
-QTo6ZGlzYWJsZWQiLCJURVhUQVJFQTo6aW5wdXRtb2RlIiwiVEVYVEFSRUE6Om5hbWUiLCJURVhUQVJF
-QTo6cGxhY2Vob2xkZXIiLCJURVhUQVJFQTo6cmVhZG9ubHkiLCJURVhUQVJFQTo6cmVxdWlyZWQiLCJU
-RVhUQVJFQTo6cm93cyIsIlRFWFRBUkVBOjp0YWJpbmRleCIsIlRFWFRBUkVBOjp3cmFwIiwiVEZPT1Q6
-OmFsaWduIiwiVEZPT1Q6OmNoYXIiLCJURk9PVDo6Y2hhcm9mZiIsIlRGT09UOjp2YWxpZ24iLCJUSDo6
-YWJiciIsIlRIOjphbGlnbiIsIlRIOjpheGlzIiwiVEg6OmJnY29sb3IiLCJUSDo6Y2hhciIsIlRIOjpj
-aGFyb2ZmIiwiVEg6OmNvbHNwYW4iLCJUSDo6aGVhZGVycyIsIlRIOjpoZWlnaHQiLCJUSDo6bm93cmFw
-IiwiVEg6OnJvd3NwYW4iLCJUSDo6c2NvcGUiLCJUSDo6dmFsaWduIiwiVEg6OndpZHRoIiwiVEhFQUQ6
-OmFsaWduIiwiVEhFQUQ6OmNoYXIiLCJUSEVBRDo6Y2hhcm9mZiIsIlRIRUFEOjp2YWxpZ24iLCJUUjo6
-YWxpZ24iLCJUUjo6Ymdjb2xvciIsIlRSOjpjaGFyIiwiVFI6OmNoYXJvZmYiLCJUUjo6dmFsaWduIiwi
-VFJBQ0s6OmRlZmF1bHQiLCJUUkFDSzo6a2luZCIsIlRSQUNLOjpsYWJlbCIsIlRSQUNLOjpzcmNsYW5n
-IiwiVUw6OmNvbXBhY3QiLCJVTDo6dHlwZSIsIlZJREVPOjpjb250cm9scyIsIlZJREVPOjpoZWlnaHQi
-LCJWSURFTzo6bG9vcCIsIlZJREVPOjptZWRpYWdyb3VwIiwiVklERU86Om11dGVkIiwiVklERU86OnBy
-ZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdS5zKQpDLlZDPUguVk0odChbMCwwLDY1NDkwLDQ1MDU1LDY1
-NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLm1LPUguVk0odChbMCwwLDI2NjI0LDEwMjMsNjU1
-MzQsMjA0Nyw2NTUzNCwyMDQ3XSksdS50KQpDLlNxPUguVk0odChbIkhFQUQiLCJBUkVBIiwiQkFTRSIs
-IkJBU0VGT05UIiwiQlIiLCJDT0wiLCJDT0xHUk9VUCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFNRVNFVCIs
-IkhSIiwiSU1BR0UiLCJJTUciLCJJTlBVVCIsIklTSU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBBUkFNIiwi
-U09VUkNFIiwiU1RZTEUiLCJUSVRMRSIsIldCUiJdKSx1LnMpCkMueEQ9SC5WTSh0KFtdKSx1LnMpCkMu
-ZG49SC5WTSh0KFtdKSx1LnYpCkMudG89SC5WTSh0KFswLDAsMzI3MjIsMTIyODcsNjU1MzQsMzQ4MTUs
-NjU1MzQsMTg0MzFdKSx1LnQpCkMuRjM9SC5WTSh0KFswLDAsMjQ1NzYsMTAyMyw2NTUzNCwzNDgxNSw2
-NTUzNCwxODQzMV0pLHUudCkKQy5lYT1ILlZNKHQoWzAsMCwzMjc1NCwxMTI2Myw2NTUzNCwzNDgxNSw2
-NTUzNCwxODQzMV0pLHUudCkKQy5aSj1ILlZNKHQoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNSwzNDgxNSw2
-NTUzNCwxODQzMV0pLHUudCkKQy5XZD1ILlZNKHQoWzAsMCw2NTQ5MCwxMjI4Nyw2NTUzNSwzNDgxNSw2
-NTUzNCwxODQzMV0pLHUudCkKQy5ReD1ILlZNKHQoWyJiaW5kIiwiaWYiLCJyZWYiLCJyZXBlYXQiLCJz
-eW50YXgiXSksdS5zKQpDLkJJPUguVk0odChbIkE6OmhyZWYiLCJBUkVBOjpocmVmIiwiQkxPQ0tRVU9U
-RTo6Y2l0ZSIsIkJPRFk6OmJhY2tncm91bmQiLCJDT01NQU5EOjppY29uIiwiREVMOjpjaXRlIiwiRk9S
-TTo6YWN0aW9uIiwiSU1HOjpzcmMiLCJJTlBVVDo6c3JjIiwiSU5TOjpjaXRlIiwiUTo6Y2l0ZSIsIlZJ
-REVPOjpwb3N0ZXIiXSksdS5zKQpDLkNNPW5ldyBILkxQKDAse30sQy54RCxILkRQKCJMUDxxVSx6TTxq
-OD4+IikpCkMuV089bmV3IEguTFAoMCx7fSxDLnhELEguRFAoIkxQPHFVLHFVPiIpKQpDLmhVPUguVk0o
-dChbXSksSC5EUCgiamQ8R0Q+IikpCkMuRHg9bmV3IEguTFAoMCx7fSxDLmhVLEguRFAoIkxQPEdELEA+
-IikpCkMuWTI9bmV3IEwuV0EoIk5hdmlnYXRpb25UcmVlTm9kZVR5cGUuZGlyZWN0b3J5IikKQy5yZj1u
-ZXcgTC5XQSgiTmF2aWdhdGlvblRyZWVOb2RlVHlwZS5maWxlIikKQy5UZT1uZXcgSC53digiY2FsbCIp
-CkMud1E9bmV3IFAuRnkobnVsbCwyKX0pKCk7KGZ1bmN0aW9uIHN0YXRpY0ZpZWxkcygpeyQueWo9MAok
-Lm1KPW51bGwKJC5QND1udWxsCiQueT1udWxsCiQudT1udWxsCiQueDc9bnVsbAokLmo9bnVsbAokLnY9
-bnVsbAokLks9bnVsbAokLlM2PW51bGwKJC5rOD1udWxsCiQubWc9bnVsbAokLlVEPSExCiQuWDM9Qy5O
-VQokLnhnPVtdCiQueG89bnVsbAokLkJPPW51bGwKJC5sdD1udWxsCiQuRVU9bnVsbAokLm9yPVAuRmwo
-dS5OLHUuWikKJC5JNj1udWxsCiQuRmY9bnVsbH0pKCk7KGZ1bmN0aW9uIGxhenlJbml0aWFsaXplcnMo
-KXt2YXIgdD1odW5rSGVscGVycy5sYXp5CnQoJCwiZmEiLCJ3USIsZnVuY3Rpb24oKXtyZXR1cm4gSC5Z
-ZygiXyRkYXJ0X2RhcnRDbG9zdXJlIil9KQp0KCQsIlkyIiwiQSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5Z
-ZygiXyRkYXJ0X2pzIil9KQp0KCQsIlUyIiwiU24iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh7
-CnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnQoJCwieHEiLCJscSIs
-ZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHskbWV0aG9kJDpudWxsLAp0b1N0cmluZzpmdW5jdGlv
-bigpe3JldHVybiIkcmVjZWl2ZXIkIn19KSl9KQp0KCQsIlIxIiwiTjkiLGZ1bmN0aW9uKCl7cmV0dXJu
-IEguY00oSC5TNyhudWxsKSl9KQp0KCQsImZOIiwiaUkiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVu
-Y3Rpb24oKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5e251bGwuJG1ldGhvZCQo
-JGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oKSl9KQp0KCQsInFpIiwi
-VU4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh2b2lkIDApKX0pCnQoJCwicloiLCJaaCIsZnVu
-Y3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVu
-dHMkJwp0cnl7KHZvaWQgMCkuJG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4g
-cy5tZXNzYWdlfX0oKSl9KQp0KCQsImtxIiwick4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5Naihu
-dWxsKSl9KQp0KCQsInR0IiwiYzMiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt0cnl7
-bnVsbC4kbWV0aG9kJH1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oKSl9KQp0KCQsImR0IiwiSEsi
-LGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5Naih2b2lkIDApKX0pCnQoJCwiQTciLCJyMSIsZnVuY3Rp
-b24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3RyeXsodm9pZCAwKS4kbWV0aG9kJH1jYXRjaChzKXty
-ZXR1cm4gcy5tZXNzYWdlfX0oKSl9KQp0KCQsIldjIiwidXQiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuT2oo
-KX0pCnQoJCwia2giLCJyZiIsZnVuY3Rpb24oKXtyZXR1cm4gUC5XSSgpfSkKdCgkLCJidCIsIlY3Iixm
-dW5jdGlvbigpe3JldHVybiBILkRRKEguWEYoSC5WTShbLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIs
-LTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIs
-LTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTEsLTIsLTIsLTIsLTIsLTIsNjIsLTIsNjIsLTIsNjMsNTIs
-NTMsNTQsNTUsNTYsNTcsNTgsNTksNjAsNjEsLTIsLTIsLTIsLTEsLTIsLTIsLTIsMCwxLDIsMyw0LDUs
-Niw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwxOSwyMCwyMSwyMiwyMywyNCwyNSwtMiwt
-MiwtMiwtMiw2MywtMiwyNiwyNywyOCwyOSwzMCwzMSwzMiwzMywzNCwzNSwzNiwzNywzOCwzOSw0MCw0
-MSw0Miw0Myw0NCw0NSw0Niw0Nyw0OCw0OSw1MCw1MSwtMiwtMiwtMiwtMiwtMl0sdS50KSkpfSkKdCgk
-LCJNNSIsIk94IixmdW5jdGlvbigpe3JldHVybiB0eXBlb2YgcHJvY2VzcyE9InVuZGVmaW5lZCImJk9i
-amVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChwcm9jZXNzKT09IltvYmplY3QgcHJvY2Vzc10iJiZw
-cm9jZXNzLnBsYXRmb3JtPT0id2luMzIifSkKdCgkLCJtZiIsIno0IixmdW5jdGlvbigpe3JldHVybiBQ
-Lm51KCJeW1xcLVxcLjAtOUEtWl9hLXp+XSokIil9KQp0KCQsIkF2IiwicDYiLGZ1bmN0aW9uKCl7cmV0
-dXJuIG5ldyBFcnJvcigpLnN0YWNrIT12b2lkIDB9KQp0KCQsIkpHIiwidloiLGZ1bmN0aW9uKCl7cmV0
-dXJuIFAuS04oKX0pCnQoJCwiU0MiLCJBTiIsZnVuY3Rpb24oKXtyZXR1cm4gUC50TShbIkEiLCJBQkJS
-IiwiQUNST05ZTSIsIkFERFJFU1MiLCJBUkVBIiwiQVJUSUNMRSIsIkFTSURFIiwiQVVESU8iLCJCIiwi
-QkRJIiwiQkRPIiwiQklHIiwiQkxPQ0tRVU9URSIsIkJSIiwiQlVUVE9OIiwiQ0FOVkFTIiwiQ0FQVElP
-TiIsIkNFTlRFUiIsIkNJVEUiLCJDT0RFIiwiQ09MIiwiQ09MR1JPVVAiLCJDT01NQU5EIiwiREFUQSIs
-IkRBVEFMSVNUIiwiREQiLCJERUwiLCJERVRBSUxTIiwiREZOIiwiRElSIiwiRElWIiwiREwiLCJEVCIs
-IkVNIiwiRklFTERTRVQiLCJGSUdDQVBUSU9OIiwiRklHVVJFIiwiRk9OVCIsIkZPT1RFUiIsIkZPUk0i
-LCJIMSIsIkgyIiwiSDMiLCJINCIsIkg1IiwiSDYiLCJIRUFERVIiLCJIR1JPVVAiLCJIUiIsIkkiLCJJ
-RlJBTUUiLCJJTUciLCJJTlBVVCIsIklOUyIsIktCRCIsIkxBQkVMIiwiTEVHRU5EIiwiTEkiLCJNQVAi
-LCJNQVJLIiwiTUVOVSIsIk1FVEVSIiwiTkFWIiwiTk9CUiIsIk9MIiwiT1BUR1JPVVAiLCJPUFRJT04i
-LCJPVVRQVVQiLCJQIiwiUFJFIiwiUFJPR1JFU1MiLCJRIiwiUyIsIlNBTVAiLCJTRUNUSU9OIiwiU0VM
-RUNUIiwiU01BTEwiLCJTT1VSQ0UiLCJTUEFOIiwiU1RSSUtFIiwiU1RST05HIiwiU1VCIiwiU1VNTUFS
-WSIsIlNVUCIsIlRBQkxFIiwiVEJPRFkiLCJURCIsIlRFWFRBUkVBIiwiVEZPT1QiLCJUSCIsIlRIRUFE
-IiwiVElNRSIsIlRSIiwiVFJBQ0siLCJUVCIsIlUiLCJVTCIsIlZBUiIsIlZJREVPIiwiV0JSIl0sdS5O
-KX0pCnQoJCwiVlEiLCJFZSIsZnVuY3Rpb24oKXtyZXR1cm4gUC5udSgiXlxcUyskIil9KQp0KCQsIndP
-Iiwib3ciLGZ1bmN0aW9uKCl7cmV0dXJuIHUudy5hKFAuTkQoc2VsZikpfSkKdCgkLCJrdCIsIkNyIixm
-dW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfZGFydE9iamVjdCIpfSkKdCgkLCJMRiIsImtJIixm
-dW5jdGlvbigpe3JldHVybiBmdW5jdGlvbiBEYXJ0T2JqZWN0KGEpe3RoaXMubz1hfX0pCnQoJCwicXQi
-LCJ6QiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFQubVEoKX0pCnQoJCwiT2wiLCJVRSIsZnVuY3Rpb24o
-KXtyZXR1cm4gUC5oSyhDLm9sLmdtVyhXLngzKCkpLmhyZWYpLmdoWSgpLnEoMCwiYXV0aFRva2VuIil9
-KQp0KCQsImhUIiwieVAiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRp
-dC1saXN0IC5wYW5lbC1jb250ZW50Iil9KQp0KCQsIlc2IiwiaEwiLGZ1bmN0aW9uKCl7cmV0dXJuIFcu
-WnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKdCgkLCJUUiIs
-IkRXIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9KQp0KCQs
-IkVZIiwiZmkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFkZXIiKX0p
-CnQoJCwiYWQiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1bml0
-LW5hbWUiKX0pCnQoJCwibXEiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnQoJCwi
-ZW8iLCJuVSIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnQoJCwiZTkiLCJiRCIs
-ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgiXi8i
-KSl9KQp0KCQsIllLIiwiS2siLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxcXF0i
-KSxQLm51KCJbXi9cXFxcXSQiKSxQLm51KCJeKFxcXFxcXFxcW15cXFxcXStcXFxcW15cXFxcL10rfFth
-LXpBLVpdOlsvXFxcXF0pIiksUC5udSgiXlsvXFxcXF0oPyFbL1xcXFxdKSIpKX0pCnQoJCwiYUMiLCJF
-YiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEYucnUoUC5udSgiLyIpLFAubnUoIiheW2EtekEtWl1bLSsu
-YS16QS1aXFxkXSo6Ly98W14vXSkkIiksUC5udSgiW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6Ly9bXi9d
-KiIpLFAubnUoIl4vIikpfSkKdCgkLCJscyIsIkhrIixmdW5jdGlvbigpe3JldHVybiBPLlJoKCl9KX0p
-KCk7KGZ1bmN0aW9uIG5hdGl2ZVN1cHBvcnQoKXshZnVuY3Rpb24oKXt2YXIgdD1mdW5jdGlvbihhKXt2
-YXIgbj17fQpuW2FdPTEKcmV0dXJuIE9iamVjdC5rZXlzKGh1bmtIZWxwZXJzLmNvbnZlcnRUb0Zhc3RP
-YmplY3QobikpWzBdfQp2LmdldElzb2xhdGVUYWc9ZnVuY3Rpb24oYSl7cmV0dXJuIHQoIl9fX2RhcnRf
-IithK3YuaXNvbGF0ZVRhZyl9CnZhciBzPSJfX19kYXJ0X2lzb2xhdGVfdGFnc18iCnZhciByPU9iamVj
-dFtzXXx8KE9iamVjdFtzXT1PYmplY3QuY3JlYXRlKG51bGwpKQp2YXIgcT0iX1p4WXhYIgpmb3IodmFy
-IHA9MDs7cCsrKXt2YXIgbz10KHErIl8iK3ArIl8iKQppZighKG8gaW4gcikpe3Jbb109MQp2Lmlzb2xh
-dGVUYWc9bwpicmVha319di5kaXNwYXRjaFByb3BlcnR5TmFtZT12LmdldElzb2xhdGVUYWcoImRpc3Bh
-dGNoX3JlY29yZCIpfSgpCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWcoe0Fu
-aW1hdGlvbkVmZmVjdFJlYWRPbmx5OkoudkIsQW5pbWF0aW9uRWZmZWN0VGltaW5nOkoudkIsQW5pbWF0
-aW9uRWZmZWN0VGltaW5nUmVhZE9ubHk6Si52QixBbmltYXRpb25UaW1lbGluZTpKLnZCLEFuaW1hdGlv
-bldvcmtsZXRHbG9iYWxTY29wZTpKLnZCLEF1dGhlbnRpY2F0b3JBc3NlcnRpb25SZXNwb25zZTpKLnZC
-LEF1dGhlbnRpY2F0b3JBdHRlc3RhdGlvblJlc3BvbnNlOkoudkIsQXV0aGVudGljYXRvclJlc3BvbnNl
-OkoudkIsQmFja2dyb3VuZEZldGNoRmV0Y2g6Si52QixCYWNrZ3JvdW5kRmV0Y2hNYW5hZ2VyOkoudkIs
-QmFja2dyb3VuZEZldGNoU2V0dGxlZEZldGNoOkoudkIsQmFyUHJvcDpKLnZCLEJhcmNvZGVEZXRlY3Rv
-cjpKLnZCLEJvZHk6Si52QixCdWRnZXRTdGF0ZTpKLnZCLENhY2hlU3RvcmFnZTpKLnZCLENhbnZhc0dy
-YWRpZW50OkoudkIsQ2FudmFzUGF0dGVybjpKLnZCLENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDpKLnZC
-LENsaWVudDpKLnZCLENsaWVudHM6Si52QixDb29raWVTdG9yZTpKLnZCLENvb3JkaW5hdGVzOkoudkIs
-Q3JlZGVudGlhbDpKLnZCLENyZWRlbnRpYWxVc2VyRGF0YTpKLnZCLENyZWRlbnRpYWxzQ29udGFpbmVy
-OkoudkIsQ3J5cHRvOkoudkIsQ3J5cHRvS2V5OkoudkIsQ1NTOkoudkIsQ1NTVmFyaWFibGVSZWZlcmVu
-Y2VWYWx1ZTpKLnZCLEN1c3RvbUVsZW1lbnRSZWdpc3RyeTpKLnZCLERhdGFUcmFuc2ZlcjpKLnZCLERh
-dGFUcmFuc2Zlckl0ZW06Si52QixEZXByZWNhdGVkU3RvcmFnZUluZm86Si52QixEZXByZWNhdGVkU3Rv
-cmFnZVF1b3RhOkoudkIsRGVwcmVjYXRpb25SZXBvcnQ6Si52QixEZXRlY3RlZEJhcmNvZGU6Si52QixE
-ZXRlY3RlZEZhY2U6Si52QixEZXRlY3RlZFRleHQ6Si52QixEZXZpY2VBY2NlbGVyYXRpb246Si52QixE
-ZXZpY2VSb3RhdGlvblJhdGU6Si52QixEaXJlY3RvcnlFbnRyeTpKLnZCLERpcmVjdG9yeVJlYWRlcjpK
-LnZCLERvY3VtZW50T3JTaGFkb3dSb290OkoudkIsRG9jdW1lbnRUaW1lbGluZTpKLnZCLERPTUVycm9y
-OkoudkIsRE9NSW1wbGVtZW50YXRpb246Si52QixJdGVyYXRvcjpKLnZCLERPTU1hdHJpeDpKLnZCLERP
-TU1hdHJpeFJlYWRPbmx5OkoudkIsRE9NUGFyc2VyOkoudkIsRE9NUG9pbnQ6Si52QixET01Qb2ludFJl
-YWRPbmx5OkoudkIsRE9NUXVhZDpKLnZCLERPTVN0cmluZ01hcDpKLnZCLEVudHJ5OkoudkIsRXh0ZXJu
-YWw6Si52QixGYWNlRGV0ZWN0b3I6Si52QixGZWRlcmF0ZWRDcmVkZW50aWFsOkoudkIsRmlsZUVudHJ5
-OkoudkIsRE9NRmlsZVN5c3RlbTpKLnZCLEZvbnRGYWNlOkoudkIsRm9udEZhY2VTb3VyY2U6Si52QixG
-b3JtRGF0YTpKLnZCLEdhbWVwYWRQb3NlOkoudkIsR2VvbG9jYXRpb246Si52QixQb3NpdGlvbjpKLnZC
-LEhlYWRlcnM6Si52QixIVE1MSHlwZXJsaW5rRWxlbWVudFV0aWxzOkoudkIsSWRsZURlYWRsaW5lOkou
-dkIsSW1hZ2VCaXRtYXA6Si52QixJbWFnZUJpdG1hcFJlbmRlcmluZ0NvbnRleHQ6Si52QixJbWFnZUNh
-cHR1cmU6Si52QixJbnB1dERldmljZUNhcGFiaWxpdGllczpKLnZCLEludGVyc2VjdGlvbk9ic2VydmVy
-OkoudkIsSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeTpKLnZCLEludGVydmVudGlvblJlcG9ydDpKLnZC
-LEtleWZyYW1lRWZmZWN0OkoudkIsS2V5ZnJhbWVFZmZlY3RSZWFkT25seTpKLnZCLE1lZGlhQ2FwYWJp
-bGl0aWVzOkoudkIsTWVkaWFDYXBhYmlsaXRpZXNJbmZvOkoudkIsTWVkaWFEZXZpY2VJbmZvOkoudkIs
-TWVkaWFFcnJvcjpKLnZCLE1lZGlhS2V5U3RhdHVzTWFwOkoudkIsTWVkaWFLZXlTeXN0ZW1BY2Nlc3M6
-Si52QixNZWRpYUtleXM6Si52QixNZWRpYUtleXNQb2xpY3k6Si52QixNZWRpYU1ldGFkYXRhOkoudkIs
-TWVkaWFTZXNzaW9uOkoudkIsTWVkaWFTZXR0aW5nc1JhbmdlOkoudkIsTWVtb3J5SW5mbzpKLnZCLE1l
-c3NhZ2VDaGFubmVsOkoudkIsTWV0YWRhdGE6Si52QixNdXRhdGlvbk9ic2VydmVyOkoudkIsV2ViS2l0
-TXV0YXRpb25PYnNlcnZlcjpKLnZCLE11dGF0aW9uUmVjb3JkOkoudkIsTmF2aWdhdGlvblByZWxvYWRN
-YW5hZ2VyOkoudkIsTmF2aWdhdG9yOkoudkIsTmF2aWdhdG9yQXV0b21hdGlvbkluZm9ybWF0aW9uOkou
-dkIsTmF2aWdhdG9yQ29uY3VycmVudEhhcmR3YXJlOkoudkIsTmF2aWdhdG9yQ29va2llczpKLnZCLE5h
-dmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsTm9kZUZpbHRlcjpKLnZCLE5vZGVJdGVyYXRvcjpKLnZC
-LE5vbkRvY3VtZW50VHlwZUNoaWxkTm9kZTpKLnZCLE5vbkVsZW1lbnRQYXJlbnROb2RlOkoudkIsTm9u
-Y2VkRWxlbWVudDpKLnZCLE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDpKLnZCLE92ZXJj
-b25zdHJhaW5lZEVycm9yOkoudkIsUGFpbnRSZW5kZXJpbmdDb250ZXh0MkQ6Si52QixQYWludFNpemU6
-Si52QixQYWludFdvcmtsZXRHbG9iYWxTY29wZTpKLnZCLFBhc3N3b3JkQ3JlZGVudGlhbDpKLnZCLFBh
-dGgyRDpKLnZCLFBheW1lbnRBZGRyZXNzOkoudkIsUGF5bWVudEluc3RydW1lbnRzOkoudkIsUGF5bWVu
-dE1hbmFnZXI6Si52QixQYXltZW50UmVzcG9uc2U6Si52QixQZXJmb3JtYW5jZUVudHJ5OkoudkIsUGVy
-Zm9ybWFuY2VMb25nVGFza1RpbWluZzpKLnZCLFBlcmZvcm1hbmNlTWFyazpKLnZCLFBlcmZvcm1hbmNl
-TWVhc3VyZTpKLnZCLFBlcmZvcm1hbmNlTmF2aWdhdGlvbjpKLnZCLFBlcmZvcm1hbmNlTmF2aWdhdGlv
-blRpbWluZzpKLnZCLFBlcmZvcm1hbmNlT2JzZXJ2ZXI6Si52QixQZXJmb3JtYW5jZU9ic2VydmVyRW50
-cnlMaXN0OkoudkIsUGVyZm9ybWFuY2VQYWludFRpbWluZzpKLnZCLFBlcmZvcm1hbmNlUmVzb3VyY2VU
-aW1pbmc6Si52QixQZXJmb3JtYW5jZVNlcnZlclRpbWluZzpKLnZCLFBlcmZvcm1hbmNlVGltaW5nOkou
-dkIsUGVybWlzc2lvbnM6Si52QixQaG90b0NhcGFiaWxpdGllczpKLnZCLFBvc2l0aW9uRXJyb3I6Si52
-QixQcmVzZW50YXRpb246Si52QixQcmVzZW50YXRpb25SZWNlaXZlcjpKLnZCLFB1YmxpY0tleUNyZWRl
-bnRpYWw6Si52QixQdXNoTWFuYWdlcjpKLnZCLFB1c2hNZXNzYWdlRGF0YTpKLnZCLFB1c2hTdWJzY3Jp
-cHRpb246Si52QixQdXNoU3Vic2NyaXB0aW9uT3B0aW9uczpKLnZCLFJhbmdlOkoudkIsUmVsYXRlZEFw
-cGxpY2F0aW9uOkoudkIsUmVwb3J0Qm9keTpKLnZCLFJlcG9ydGluZ09ic2VydmVyOkoudkIsUmVzaXpl
-T2JzZXJ2ZXI6Si52QixSZXNpemVPYnNlcnZlckVudHJ5OkoudkIsUlRDQ2VydGlmaWNhdGU6Si52QixS
-VENJY2VDYW5kaWRhdGU6Si52Qixtb3pSVENJY2VDYW5kaWRhdGU6Si52QixSVENMZWdhY3lTdGF0c1Jl
-cG9ydDpKLnZCLFJUQ1J0cENvbnRyaWJ1dGluZ1NvdXJjZTpKLnZCLFJUQ1J0cFJlY2VpdmVyOkoudkIs
-UlRDUnRwU2VuZGVyOkoudkIsUlRDU2Vzc2lvbkRlc2NyaXB0aW9uOkoudkIsbW96UlRDU2Vzc2lvbkRl
-c2NyaXB0aW9uOkoudkIsUlRDU3RhdHNSZXNwb25zZTpKLnZCLFNjcmVlbjpKLnZCLFNjcm9sbFN0YXRl
-OkoudkIsU2Nyb2xsVGltZWxpbmU6Si52QixTZWxlY3Rpb246Si52QixTaGFyZWRBcnJheUJ1ZmZlcjpK
-LnZCLFNwZWVjaFJlY29nbml0aW9uQWx0ZXJuYXRpdmU6Si52QixTcGVlY2hTeW50aGVzaXNWb2ljZTpK
-LnZCLFN0YXRpY1JhbmdlOkoudkIsU3RvcmFnZU1hbmFnZXI6Si52QixTdHlsZU1lZGlhOkoudkIsU3R5
-bGVQcm9wZXJ0eU1hcDpKLnZCLFN0eWxlUHJvcGVydHlNYXBSZWFkb25seTpKLnZCLFN5bmNNYW5hZ2Vy
-OkoudkIsVGFza0F0dHJpYnV0aW9uVGltaW5nOkoudkIsVGV4dERldGVjdG9yOkoudkIsVGV4dE1ldHJp
-Y3M6Si52QixUcmFja0RlZmF1bHQ6Si52QixUcmVlV2Fsa2VyOkoudkIsVHJ1c3RlZEhUTUw6Si52QixU
-cnVzdGVkU2NyaXB0VVJMOkoudkIsVHJ1c3RlZFVSTDpKLnZCLFVuZGVybHlpbmdTb3VyY2VCYXNlOkou
-dkIsVVJMU2VhcmNoUGFyYW1zOkoudkIsVlJDb29yZGluYXRlU3lzdGVtOkoudkIsVlJEaXNwbGF5Q2Fw
-YWJpbGl0aWVzOkoudkIsVlJFeWVQYXJhbWV0ZXJzOkoudkIsVlJGcmFtZURhdGE6Si52QixWUkZyYW1l
-T2ZSZWZlcmVuY2U6Si52QixWUlBvc2U6Si52QixWUlN0YWdlQm91bmRzOkoudkIsVlJTdGFnZUJvdW5k
-c1BvaW50OkoudkIsVlJTdGFnZVBhcmFtZXRlcnM6Si52QixWYWxpZGl0eVN0YXRlOkoudkIsVmlkZW9Q
-bGF5YmFja1F1YWxpdHk6Si52QixWaWRlb1RyYWNrOkoudkIsVlRUUmVnaW9uOkoudkIsV2luZG93Q2xp
-ZW50OkoudkIsV29ya2xldEFuaW1hdGlvbjpKLnZCLFdvcmtsZXRHbG9iYWxTY29wZTpKLnZCLFhQYXRo
-RXZhbHVhdG9yOkoudkIsWFBhdGhFeHByZXNzaW9uOkoudkIsWFBhdGhOU1Jlc29sdmVyOkoudkIsWFBh
-dGhSZXN1bHQ6Si52QixYTUxTZXJpYWxpemVyOkoudkIsWFNMVFByb2Nlc3NvcjpKLnZCLEJsdWV0b290
-aDpKLnZCLEJsdWV0b290aENoYXJhY3RlcmlzdGljUHJvcGVydGllczpKLnZCLEJsdWV0b290aFJlbW90
-ZUdBVFRTZXJ2ZXI6Si52QixCbHVldG9vdGhSZW1vdGVHQVRUU2VydmljZTpKLnZCLEJsdWV0b290aFVV
-SUQ6Si52QixCdWRnZXRTZXJ2aWNlOkoudkIsQ2FjaGU6Si52QixET01GaWxlU3lzdGVtU3luYzpKLnZC
-LERpcmVjdG9yeUVudHJ5U3luYzpKLnZCLERpcmVjdG9yeVJlYWRlclN5bmM6Si52QixFbnRyeVN5bmM6
-Si52QixGaWxlRW50cnlTeW5jOkoudkIsRmlsZVJlYWRlclN5bmM6Si52QixGaWxlV3JpdGVyU3luYzpK
-LnZCLEhUTUxBbGxDb2xsZWN0aW9uOkoudkIsTW9qbzpKLnZCLE1vam9IYW5kbGU6Si52QixNb2pvV2F0
-Y2hlcjpKLnZCLE5GQzpKLnZCLFBhZ2VQb3B1cENvbnRyb2xsZXI6Si52QixSZXBvcnQ6Si52QixSZXF1
-ZXN0OkoudkIsUmVzcG9uc2U6Si52QixTdWJ0bGVDcnlwdG86Si52QixVU0JBbHRlcm5hdGVJbnRlcmZh
-Y2U6Si52QixVU0JDb25maWd1cmF0aW9uOkoudkIsVVNCRGV2aWNlOkoudkIsVVNCRW5kcG9pbnQ6Si52
-QixVU0JJblRyYW5zZmVyUmVzdWx0OkoudkIsVVNCSW50ZXJmYWNlOkoudkIsVVNCSXNvY2hyb25vdXNJ
-blRyYW5zZmVyUGFja2V0OkoudkIsVVNCSXNvY2hyb25vdXNJblRyYW5zZmVyUmVzdWx0OkoudkIsVVNC
-SXNvY2hyb25vdXNPdXRUcmFuc2ZlclBhY2tldDpKLnZCLFVTQklzb2Nocm9ub3VzT3V0VHJhbnNmZXJS
-ZXN1bHQ6Si52QixVU0JPdXRUcmFuc2ZlclJlc3VsdDpKLnZCLFdvcmtlckxvY2F0aW9uOkoudkIsV29y
-a2VyTmF2aWdhdG9yOkoudkIsV29ya2xldDpKLnZCLElEQkZhY3Rvcnk6Si52QixJREJJbmRleDpKLnZC
-LElEQk9iamVjdFN0b3JlOkoudkIsSURCT2JzZXJ2ZXI6Si52QixJREJPYnNlcnZlckNoYW5nZXM6Si52
-QixTVkdBbmltYXRlZEFuZ2xlOkoudkIsU1ZHQW5pbWF0ZWRCb29sZWFuOkoudkIsU1ZHQW5pbWF0ZWRF
-bnVtZXJhdGlvbjpKLnZCLFNWR0FuaW1hdGVkSW50ZWdlcjpKLnZCLFNWR0FuaW1hdGVkTGVuZ3RoOkou
-dkIsU1ZHQW5pbWF0ZWRMZW5ndGhMaXN0OkoudkIsU1ZHQW5pbWF0ZWROdW1iZXI6Si52QixTVkdBbmlt
-YXRlZE51bWJlckxpc3Q6Si52QixTVkdBbmltYXRlZFByZXNlcnZlQXNwZWN0UmF0aW86Si52QixTVkdB
-bmltYXRlZFJlY3Q6Si52QixTVkdBbmltYXRlZFN0cmluZzpKLnZCLFNWR0FuaW1hdGVkVHJhbnNmb3Jt
-TGlzdDpKLnZCLFNWR01hdHJpeDpKLnZCLFNWR1BvaW50OkoudkIsU1ZHUHJlc2VydmVBc3BlY3RSYXRp
-bzpKLnZCLFNWR1JlY3Q6Si52QixTVkdVbml0VHlwZXM6Si52QixBdWRpb0xpc3RlbmVyOkoudkIsQXVk
-aW9UcmFjazpKLnZCLEF1ZGlvV29ya2xldEdsb2JhbFNjb3BlOkoudkIsQXVkaW9Xb3JrbGV0UHJvY2Vz
-c29yOkoudkIsUGVyaW9kaWNXYXZlOkoudkIsV2ViR0xBY3RpdmVJbmZvOkoudkIsQU5HTEVJbnN0YW5j
-ZWRBcnJheXM6Si52QixBTkdMRV9pbnN0YW5jZWRfYXJyYXlzOkoudkIsV2ViR0xCdWZmZXI6Si52QixX
-ZWJHTENhbnZhczpKLnZCLFdlYkdMQ29sb3JCdWZmZXJGbG9hdDpKLnZCLFdlYkdMQ29tcHJlc3NlZFRl
-eHR1cmVBU1RDOkoudkIsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUFUQzpKLnZCLFdFQkdMX2NvbXByZXNz
-ZWRfdGV4dHVyZV9hdGM6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlRVRDMTpKLnZCLFdFQkdMX2Nv
-bXByZXNzZWRfdGV4dHVyZV9ldGMxOkoudkIsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUVUQzpKLnZCLFdl
-YkdMQ29tcHJlc3NlZFRleHR1cmVQVlJUQzpKLnZCLFdFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9wdnJ0
-YzpKLnZCLFdlYkdMQ29tcHJlc3NlZFRleHR1cmVTM1RDOkoudkIsV0VCR0xfY29tcHJlc3NlZF90ZXh0
-dXJlX3MzdGM6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlUzNUQ3NSR0I6Si52QixXZWJHTERlYnVn
-UmVuZGVyZXJJbmZvOkoudkIsV0VCR0xfZGVidWdfcmVuZGVyZXJfaW5mbzpKLnZCLFdlYkdMRGVidWdT
-aGFkZXJzOkoudkIsV0VCR0xfZGVidWdfc2hhZGVyczpKLnZCLFdlYkdMRGVwdGhUZXh0dXJlOkoudkIs
-V0VCR0xfZGVwdGhfdGV4dHVyZTpKLnZCLFdlYkdMRHJhd0J1ZmZlcnM6Si52QixXRUJHTF9kcmF3X2J1
-ZmZlcnM6Si52QixFWFRzUkdCOkoudkIsRVhUX3NSR0I6Si52QixFWFRCbGVuZE1pbk1heDpKLnZCLEVY
-VF9ibGVuZF9taW5tYXg6Si52QixFWFRDb2xvckJ1ZmZlckZsb2F0OkoudkIsRVhUQ29sb3JCdWZmZXJI
-YWxmRmxvYXQ6Si52QixFWFREaXNqb2ludFRpbWVyUXVlcnk6Si52QixFWFREaXNqb2ludFRpbWVyUXVl
-cnlXZWJHTDI6Si52QixFWFRGcmFnRGVwdGg6Si52QixFWFRfZnJhZ19kZXB0aDpKLnZCLEVYVFNoYWRl
-clRleHR1cmVMT0Q6Si52QixFWFRfc2hhZGVyX3RleHR1cmVfbG9kOkoudkIsRVhUVGV4dHVyZUZpbHRl
-ckFuaXNvdHJvcGljOkoudkIsRVhUX3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljOkoudkIsV2ViR0xG
-cmFtZWJ1ZmZlcjpKLnZCLFdlYkdMR2V0QnVmZmVyU3ViRGF0YUFzeW5jOkoudkIsV2ViR0xMb3NlQ29u
-dGV4dDpKLnZCLFdlYkdMRXh0ZW5zaW9uTG9zZUNvbnRleHQ6Si52QixXRUJHTF9sb3NlX2NvbnRleHQ6
-Si52QixPRVNFbGVtZW50SW5kZXhVaW50OkoudkIsT0VTX2VsZW1lbnRfaW5kZXhfdWludDpKLnZCLE9F
-U1N0YW5kYXJkRGVyaXZhdGl2ZXM6Si52QixPRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXM6Si52QixPRVNU
-ZXh0dXJlRmxvYXQ6Si52QixPRVNfdGV4dHVyZV9mbG9hdDpKLnZCLE9FU1RleHR1cmVGbG9hdExpbmVh
-cjpKLnZCLE9FU190ZXh0dXJlX2Zsb2F0X2xpbmVhcjpKLnZCLE9FU1RleHR1cmVIYWxmRmxvYXQ6Si52
-QixPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0OkoudkIsT0VTVGV4dHVyZUhhbGZGbG9hdExpbmVhcjpKLnZC
-LE9FU190ZXh0dXJlX2hhbGZfZmxvYXRfbGluZWFyOkoudkIsT0VTVmVydGV4QXJyYXlPYmplY3Q6Si52
-QixPRVNfdmVydGV4X2FycmF5X29iamVjdDpKLnZCLFdlYkdMUHJvZ3JhbTpKLnZCLFdlYkdMUXVlcnk6
-Si52QixXZWJHTFJlbmRlcmJ1ZmZlcjpKLnZCLFdlYkdMUmVuZGVyaW5nQ29udGV4dDpKLnZCLFdlYkdM
-MlJlbmRlcmluZ0NvbnRleHQ6Si52QixXZWJHTFNhbXBsZXI6Si52QixXZWJHTFNoYWRlcjpKLnZCLFdl
-YkdMU2hhZGVyUHJlY2lzaW9uRm9ybWF0OkoudkIsV2ViR0xTeW5jOkoudkIsV2ViR0xUZXh0dXJlOkou
-dkIsV2ViR0xUaW1lclF1ZXJ5RVhUOkoudkIsV2ViR0xUcmFuc2Zvcm1GZWVkYmFjazpKLnZCLFdlYkdM
-VW5pZm9ybUxvY2F0aW9uOkoudkIsV2ViR0xWZXJ0ZXhBcnJheU9iamVjdDpKLnZCLFdlYkdMVmVydGV4
-QXJyYXlPYmplY3RPRVM6Si52QixXZWJHTDpKLnZCLFdlYkdMMlJlbmRlcmluZ0NvbnRleHRCYXNlOkou
-dkIsRGF0YWJhc2U6Si52QixTUUxFcnJvcjpKLnZCLFNRTFJlc3VsdFNldDpKLnZCLFNRTFRyYW5zYWN0
-aW9uOkoudkIsQXJyYXlCdWZmZXI6SC5XWixEYXRhVmlldzpILnBGLEFycmF5QnVmZmVyVmlldzpILnBG
-LEZsb2F0MzJBcnJheTpILkRnLEZsb2F0NjRBcnJheTpILkRnLEludDE2QXJyYXk6SC54aixJbnQzMkFy
-cmF5OkguZEUsSW50OEFycmF5OkguWkEsVWludDE2QXJyYXk6SC53ZixVaW50MzJBcnJheTpILlBxLFVp
-bnQ4Q2xhbXBlZEFycmF5OkguZUUsQ2FudmFzUGl4ZWxBcnJheTpILmVFLFVpbnQ4QXJyYXk6SC5WNixI
-VE1MQXVkaW9FbGVtZW50OlcucUUsSFRNTEJSRWxlbWVudDpXLnFFLEhUTUxDYW52YXNFbGVtZW50Olcu
-cUUsSFRNTENvbnRlbnRFbGVtZW50OlcucUUsSFRNTERMaXN0RWxlbWVudDpXLnFFLEhUTUxEYXRhTGlz
-dEVsZW1lbnQ6Vy5xRSxIVE1MRGV0YWlsc0VsZW1lbnQ6Vy5xRSxIVE1MRGlhbG9nRWxlbWVudDpXLnFF
-LEhUTUxEaXZFbGVtZW50OlcucUUsSFRNTEVtYmVkRWxlbWVudDpXLnFFLEhUTUxGaWVsZFNldEVsZW1l
-bnQ6Vy5xRSxIVE1MSFJFbGVtZW50OlcucUUsSFRNTEhlYWRFbGVtZW50OlcucUUsSFRNTEhlYWRpbmdF
-bGVtZW50OlcucUUsSFRNTEh0bWxFbGVtZW50OlcucUUsSFRNTElGcmFtZUVsZW1lbnQ6Vy5xRSxIVE1M
-SW1hZ2VFbGVtZW50OlcucUUsSFRNTExhYmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50Olcu
-cUUsSFRNTExpbmtFbGVtZW50OlcucUUsSFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50
-OlcucUUsSFRNTE1lbnVFbGVtZW50OlcucUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1vZEVsZW1l
-bnQ6Vy5xRSxIVE1MT0xpc3RFbGVtZW50OlcucUUsSFRNTE9iamVjdEVsZW1lbnQ6Vy5xRSxIVE1MT3B0
-R3JvdXBFbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUsSFRNTFByZUVsZW1lbnQ6Vy5x
-RSxIVE1MUXVvdGVFbGVtZW50OlcucUUsSFRNTFNjcmlwdEVsZW1lbnQ6Vy5xRSxIVE1MU2hhZG93RWxl
-bWVudDpXLnFFLEhUTUxTbG90RWxlbWVudDpXLnFFLEhUTUxTb3VyY2VFbGVtZW50OlcucUUsSFRNTFNw
-YW5FbGVtZW50OlcucUUsSFRNTFN0eWxlRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50
-OlcucUUsSFRNTFRhYmxlQ2VsbEVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6Vy5x
-RSxIVE1MVGFibGVIZWFkZXJDZWxsRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNvbEVsZW1lbnQ6Vy5xRSxI
-VE1MVGltZUVsZW1lbnQ6Vy5xRSxIVE1MVGl0bGVFbGVtZW50OlcucUUsSFRNTFRyYWNrRWxlbWVudDpX
-LnFFLEhUTUxVTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MVW5rbm93bkVsZW1lbnQ6Vy5xRSxIVE1MVmlkZW9F
-bGVtZW50OlcucUUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6Vy5xRSxIVE1MRm9udEVsZW1lbnQ6Vy5xRSxI
-VE1MRnJhbWVFbGVtZW50OlcucUUsSFRNTEZyYW1lU2V0RWxlbWVudDpXLnFFLEhUTUxNYXJxdWVlRWxl
-bWVudDpXLnFFLEhUTUxFbGVtZW50OlcucUUsQWNjZXNzaWJsZU5vZGVMaXN0OlcuWWUsSFRNTEFuY2hv
-ckVsZW1lbnQ6Vy5HaCxIVE1MQXJlYUVsZW1lbnQ6Vy5mWSxIVE1MQmFzZUVsZW1lbnQ6Vy5uQixCbG9i
-OlcuQXosQmx1ZXRvb3RoUmVtb3RlR0FUVERlc2NyaXB0b3I6Vy5QVSxIVE1MQm9keUVsZW1lbnQ6Vy5R
-UCxIVE1MQnV0dG9uRWxlbWVudDpXLklGLENEQVRBU2VjdGlvbjpXLm54LENoYXJhY3RlckRhdGE6Vy5u
-eCxDb21tZW50OlcubngsUHJvY2Vzc2luZ0luc3RydWN0aW9uOlcubngsVGV4dDpXLm54LENTU0tleXdv
-cmRWYWx1ZTpXLlJkLENTU051bWVyaWNWYWx1ZTpXLmtSLENTU1BlcnNwZWN0aXZlOlcuVGYsQ1NTQ2hh
-cnNldFJ1bGU6Vy5sdyxDU1NDb25kaXRpb25SdWxlOlcubHcsQ1NTRm9udEZhY2VSdWxlOlcubHcsQ1NT
-R3JvdXBpbmdSdWxlOlcubHcsQ1NTSW1wb3J0UnVsZTpXLmx3LENTU0tleWZyYW1lUnVsZTpXLmx3LE1v
-ekNTU0tleWZyYW1lUnVsZTpXLmx3LFdlYktpdENTU0tleWZyYW1lUnVsZTpXLmx3LENTU0tleWZyYW1l
-c1J1bGU6Vy5sdyxNb3pDU1NLZXlmcmFtZXNSdWxlOlcubHcsV2ViS2l0Q1NTS2V5ZnJhbWVzUnVsZTpX
-Lmx3LENTU01lZGlhUnVsZTpXLmx3LENTU05hbWVzcGFjZVJ1bGU6Vy5sdyxDU1NQYWdlUnVsZTpXLmx3
-LENTU1J1bGU6Vy5sdyxDU1NTdHlsZVJ1bGU6Vy5sdyxDU1NTdXBwb3J0c1J1bGU6Vy5sdyxDU1NWaWV3
-cG9ydFJ1bGU6Vy5sdyxDU1NTdHlsZURlY2xhcmF0aW9uOlcub0osTVNTdHlsZUNTU1Byb3BlcnRpZXM6
-Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLENTU0ltYWdlVmFsdWU6Vy5CdyxDU1NQb3NpdGlvblZhbHVl
-OlcuQncsQ1NTUmVzb3VyY2VWYWx1ZTpXLkJ3LENTU1VSTEltYWdlVmFsdWU6Vy5CdyxDU1NTdHlsZVZh
-bHVlOlcuQncsQ1NTTWF0cml4Q29tcG9uZW50OlcubzQsQ1NTUm90YXRpb246Vy5vNCxDU1NTY2FsZTpX
-Lm80LENTU1NrZXc6Vy5vNCxDU1NUcmFuc2xhdGlvbjpXLm80LENTU1RyYW5zZm9ybUNvbXBvbmVudDpX
-Lm80LENTU1RyYW5zZm9ybVZhbHVlOlcuSFMsQ1NTVW5pdFZhbHVlOlcuVm8sQ1NTVW5wYXJzZWRWYWx1
-ZTpXLkZoLEhUTUxEYXRhRWxlbWVudDpXLmN4LERhdGFUcmFuc2Zlckl0ZW1MaXN0OlcuU2IsWE1MRG9j
-dW1lbnQ6Vy5RRixEb2N1bWVudDpXLlFGLERPTUV4Y2VwdGlvbjpXLk5oLENsaWVudFJlY3RMaXN0Olcu
-RnYsRE9NUmVjdExpc3Q6Vy5GdixET01SZWN0UmVhZE9ubHk6Vy5JQixET01TdHJpbmdMaXN0OlcuWWws
-RE9NVG9rZW5MaXN0OlcubjcsRWxlbWVudDpXLmN2LEFib3J0UGF5bWVudEV2ZW50OlcuZWEsQW5pbWF0
-aW9uRXZlbnQ6Vy5lYSxBbmltYXRpb25QbGF5YmFja0V2ZW50OlcuZWEsQXBwbGljYXRpb25DYWNoZUVy
-cm9yRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNo
-RXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hlZEV2
-ZW50OlcuZWEsQmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OlcuZWEsQmVmb3JlVW5sb2FkRXZlbnQ6Vy5l
-YSxCbG9iRXZlbnQ6Vy5lYSxDYW5NYWtlUGF5bWVudEV2ZW50OlcuZWEsQ2xpcGJvYXJkRXZlbnQ6Vy5l
-YSxDbG9zZUV2ZW50OlcuZWEsQ3VzdG9tRXZlbnQ6Vy5lYSxEZXZpY2VNb3Rpb25FdmVudDpXLmVhLERl
-dmljZU9yaWVudGF0aW9uRXZlbnQ6Vy5lYSxFcnJvckV2ZW50OlcuZWEsRXh0ZW5kYWJsZUV2ZW50Olcu
-ZWEsRXh0ZW5kYWJsZU1lc3NhZ2VFdmVudDpXLmVhLEZldGNoRXZlbnQ6Vy5lYSxGb250RmFjZVNldExv
-YWRFdmVudDpXLmVhLEZvcmVpZ25GZXRjaEV2ZW50OlcuZWEsR2FtZXBhZEV2ZW50OlcuZWEsSGFzaENo
-YW5nZUV2ZW50OlcuZWEsSW5zdGFsbEV2ZW50OlcuZWEsTWVkaWFFbmNyeXB0ZWRFdmVudDpXLmVhLE1l
-ZGlhS2V5TWVzc2FnZUV2ZW50OlcuZWEsTWVkaWFRdWVyeUxpc3RFdmVudDpXLmVhLE1lZGlhU3RyZWFt
-RXZlbnQ6Vy5lYSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6Vy5lYSxNZXNzYWdlRXZlbnQ6Vy5lYSxNSURJ
-Q29ubmVjdGlvbkV2ZW50OlcuZWEsTUlESU1lc3NhZ2VFdmVudDpXLmVhLE11dGF0aW9uRXZlbnQ6Vy5l
-YSxOb3RpZmljYXRpb25FdmVudDpXLmVhLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxQYXltZW50UmVx
-dWVzdEV2ZW50OlcuZWEsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDpXLmVhLFBvcFN0YXRlRXZlbnQ6
-Vy5lYSxQcmVzZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6Vy5lYSxQcmVzZW50YXRpb25D
-b25uZWN0aW9uQ2xvc2VFdmVudDpXLmVhLFByb21pc2VSZWplY3Rpb25FdmVudDpXLmVhLFB1c2hFdmVu
-dDpXLmVhLFJUQ0RhdGFDaGFubmVsRXZlbnQ6Vy5lYSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OlcuZWEs
-UlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudDpXLmVhLFJUQ1RyYWNrRXZlbnQ6Vy5lYSxTZWN1cml0eVBv
-bGljeVZpb2xhdGlvbkV2ZW50OlcuZWEsU2Vuc29yRXJyb3JFdmVudDpXLmVhLFNwZWVjaFJlY29nbml0
-aW9uRXJyb3I6Vy5lYSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OlcuZWEsU3BlZWNoU3ludGhlc2lzRXZl
-bnQ6Vy5lYSxTeW5jRXZlbnQ6Vy5lYSxUcmFja0V2ZW50OlcuZWEsVHJhbnNpdGlvbkV2ZW50OlcuZWEs
-V2ViS2l0VHJhbnNpdGlvbkV2ZW50OlcuZWEsVlJEZXZpY2VFdmVudDpXLmVhLFZSRGlzcGxheUV2ZW50
-OlcuZWEsVlJTZXNzaW9uRXZlbnQ6Vy5lYSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OlcuZWEsVVNC
-Q29ubmVjdGlvbkV2ZW50OlcuZWEsSURCVmVyc2lvbkNoYW5nZUV2ZW50OlcuZWEsQXVkaW9Qcm9jZXNz
-aW5nRXZlbnQ6Vy5lYSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6Vy5lYSxXZWJHTENvbnRleHRF
-dmVudDpXLmVhLEV2ZW50OlcuZWEsSW5wdXRFdmVudDpXLmVhLEFic29sdXRlT3JpZW50YXRpb25TZW5z
-b3I6Vy5EMCxBY2NlbGVyb21ldGVyOlcuRDAsQWNjZXNzaWJsZU5vZGU6Vy5EMCxBbWJpZW50TGlnaHRT
-ZW5zb3I6Vy5EMCxBbmltYXRpb246Vy5EMCxBcHBsaWNhdGlvbkNhY2hlOlcuRDAsRE9NQXBwbGljYXRp
-b25DYWNoZTpXLkQwLE9mZmxpbmVSZXNvdXJjZUxpc3Q6Vy5EMCxCYWNrZ3JvdW5kRmV0Y2hSZWdpc3Ry
-YXRpb246Vy5EMCxCYXR0ZXJ5TWFuYWdlcjpXLkQwLEJyb2FkY2FzdENoYW5uZWw6Vy5EMCxDYW52YXND
-YXB0dXJlTWVkaWFTdHJlYW1UcmFjazpXLkQwLEV2ZW50U291cmNlOlcuRDAsRmlsZVJlYWRlcjpXLkQw
-LEZvbnRGYWNlU2V0OlcuRDAsR3lyb3Njb3BlOlcuRDAsTGluZWFyQWNjZWxlcmF0aW9uU2Vuc29yOlcu
-RDAsTWFnbmV0b21ldGVyOlcuRDAsTWVkaWFEZXZpY2VzOlcuRDAsTWVkaWFLZXlTZXNzaW9uOlcuRDAs
-TWVkaWFRdWVyeUxpc3Q6Vy5EMCxNZWRpYVJlY29yZGVyOlcuRDAsTWVkaWFTb3VyY2U6Vy5EMCxNZWRp
-YVN0cmVhbTpXLkQwLE1lZGlhU3RyZWFtVHJhY2s6Vy5EMCxNSURJQWNjZXNzOlcuRDAsTUlESUlucHV0
-OlcuRDAsTUlESU91dHB1dDpXLkQwLE1JRElQb3J0OlcuRDAsTmV0d29ya0luZm9ybWF0aW9uOlcuRDAs
-Tm90aWZpY2F0aW9uOlcuRDAsT2Zmc2NyZWVuQ2FudmFzOlcuRDAsT3JpZW50YXRpb25TZW5zb3I6Vy5E
-MCxQYXltZW50UmVxdWVzdDpXLkQwLFBlcmZvcm1hbmNlOlcuRDAsUGVybWlzc2lvblN0YXR1czpXLkQw
-LFByZXNlbnRhdGlvbkNvbm5lY3Rpb246Vy5EMCxQcmVzZW50YXRpb25Db25uZWN0aW9uTGlzdDpXLkQw
-LFByZXNlbnRhdGlvblJlcXVlc3Q6Vy5EMCxSZWxhdGl2ZU9yaWVudGF0aW9uU2Vuc29yOlcuRDAsUmVt
-b3RlUGxheWJhY2s6Vy5EMCxSVENEYXRhQ2hhbm5lbDpXLkQwLERhdGFDaGFubmVsOlcuRDAsUlRDRFRN
-RlNlbmRlcjpXLkQwLFJUQ1BlZXJDb25uZWN0aW9uOlcuRDAsd2Via2l0UlRDUGVlckNvbm5lY3Rpb246
-Vy5EMCxtb3pSVENQZWVyQ29ubmVjdGlvbjpXLkQwLFNjcmVlbk9yaWVudGF0aW9uOlcuRDAsU2Vuc29y
-OlcuRDAsU2VydmljZVdvcmtlcjpXLkQwLFNlcnZpY2VXb3JrZXJDb250YWluZXI6Vy5EMCxTZXJ2aWNl
-V29ya2VyUmVnaXN0cmF0aW9uOlcuRDAsU2hhcmVkV29ya2VyOlcuRDAsU3BlZWNoUmVjb2duaXRpb246
-Vy5EMCxTcGVlY2hTeW50aGVzaXM6Vy5EMCxTcGVlY2hTeW50aGVzaXNVdHRlcmFuY2U6Vy5EMCxWUjpX
-LkQwLFZSRGV2aWNlOlcuRDAsVlJEaXNwbGF5OlcuRDAsVlJTZXNzaW9uOlcuRDAsVmlzdWFsVmlld3Bv
-cnQ6Vy5EMCxXZWJTb2NrZXQ6Vy5EMCxXb3JrZXI6Vy5EMCxXb3JrZXJQZXJmb3JtYW5jZTpXLkQwLEJs
-dWV0b290aERldmljZTpXLkQwLEJsdWV0b290aFJlbW90ZUdBVFRDaGFyYWN0ZXJpc3RpYzpXLkQwLENs
-aXBib2FyZDpXLkQwLE1vam9JbnRlcmZhY2VJbnRlcmNlcHRvcjpXLkQwLFVTQjpXLkQwLElEQkRhdGFi
-YXNlOlcuRDAsSURCT3BlbkRCUmVxdWVzdDpXLkQwLElEQlZlcnNpb25DaGFuZ2VSZXF1ZXN0OlcuRDAs
-SURCUmVxdWVzdDpXLkQwLElEQlRyYW5zYWN0aW9uOlcuRDAsQW5hbHlzZXJOb2RlOlcuRDAsUmVhbHRp
-bWVBbmFseXNlck5vZGU6Vy5EMCxBdWRpb0J1ZmZlclNvdXJjZU5vZGU6Vy5EMCxBdWRpb0Rlc3RpbmF0
-aW9uTm9kZTpXLkQwLEF1ZGlvTm9kZTpXLkQwLEF1ZGlvU2NoZWR1bGVkU291cmNlTm9kZTpXLkQwLEF1
-ZGlvV29ya2xldE5vZGU6Vy5EMCxCaXF1YWRGaWx0ZXJOb2RlOlcuRDAsQ2hhbm5lbE1lcmdlck5vZGU6
-Vy5EMCxBdWRpb0NoYW5uZWxNZXJnZXI6Vy5EMCxDaGFubmVsU3BsaXR0ZXJOb2RlOlcuRDAsQXVkaW9D
-aGFubmVsU3BsaXR0ZXI6Vy5EMCxDb25zdGFudFNvdXJjZU5vZGU6Vy5EMCxDb252b2x2ZXJOb2RlOlcu
-RDAsRGVsYXlOb2RlOlcuRDAsRHluYW1pY3NDb21wcmVzc29yTm9kZTpXLkQwLEdhaW5Ob2RlOlcuRDAs
-QXVkaW9HYWluTm9kZTpXLkQwLElJUkZpbHRlck5vZGU6Vy5EMCxNZWRpYUVsZW1lbnRBdWRpb1NvdXJj
-ZU5vZGU6Vy5EMCxNZWRpYVN0cmVhbUF1ZGlvRGVzdGluYXRpb25Ob2RlOlcuRDAsTWVkaWFTdHJlYW1B
-dWRpb1NvdXJjZU5vZGU6Vy5EMCxPc2NpbGxhdG9yTm9kZTpXLkQwLE9zY2lsbGF0b3I6Vy5EMCxQYW5u
-ZXJOb2RlOlcuRDAsQXVkaW9QYW5uZXJOb2RlOlcuRDAsd2Via2l0QXVkaW9QYW5uZXJOb2RlOlcuRDAs
-U2NyaXB0UHJvY2Vzc29yTm9kZTpXLkQwLEphdmFTY3JpcHRBdWRpb05vZGU6Vy5EMCxTdGVyZW9QYW5u
-ZXJOb2RlOlcuRDAsV2F2ZVNoYXBlck5vZGU6Vy5EMCxFdmVudFRhcmdldDpXLkQwLEZpbGU6Vy5UNSxG
-aWxlTGlzdDpXLlhWLEZpbGVXcml0ZXI6Vy53SixIVE1MRm9ybUVsZW1lbnQ6Vy5oNCxHYW1lcGFkOlcu
-R08sR2FtZXBhZEJ1dHRvbjpXLkpDLEhpc3Rvcnk6Vy5icixIVE1MQ29sbGVjdGlvbjpXLnhuLEhUTUxG
-b3JtQ29udHJvbHNDb2xsZWN0aW9uOlcueG4sSFRNTE9wdGlvbnNDb2xsZWN0aW9uOlcueG4sSFRNTERv
-Y3VtZW50OlcuVmIsWE1MSHR0cFJlcXVlc3Q6Vy5mSixYTUxIdHRwUmVxdWVzdFVwbG9hZDpXLndhLFhN
-TEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6Vy53YSxJbWFnZURhdGE6Vy5TZyxIVE1MSW5wdXRFbGVtZW50
-OlcuSkssS2V5Ym9hcmRFdmVudDpXLkhMLEhUTUxMSUVsZW1lbnQ6Vy53UCxMb2NhdGlvbjpXLnU4LE1l
-ZGlhTGlzdDpXLno2LE1lc3NhZ2VQb3J0OlcuQ2YsSFRNTE1ldGVyRWxlbWVudDpXLlFiLE1JRElJbnB1
-dE1hcDpXLlMwLE1JRElPdXRwdXRNYXA6Vy56MixNaW1lVHlwZTpXLkFXLE1pbWVUeXBlQXJyYXk6Vy5E
-TSxNb3VzZUV2ZW50OlcuT0ssRHJhZ0V2ZW50OlcuT0ssUG9pbnRlckV2ZW50OlcuT0ssV2hlZWxFdmVu
-dDpXLk9LLERvY3VtZW50RnJhZ21lbnQ6Vy51SCxTaGFkb3dSb290OlcudUgsRG9jdW1lbnRUeXBlOlcu
-dUgsTm9kZTpXLnVILE5vZGVMaXN0OlcuQkgsUmFkaW9Ob2RlTGlzdDpXLkJILEhUTUxPcHRpb25FbGVt
-ZW50OlcuUWwsSFRNTE91dHB1dEVsZW1lbnQ6Vy5HWCxIVE1MUGFyYWdyYXBoRWxlbWVudDpXLlNOLEhU
-TUxQYXJhbUVsZW1lbnQ6Vy5IRCxQbHVnaW46Vy5jbCxQbHVnaW5BcnJheTpXLkV2LFByZXNlbnRhdGlv
-bkF2YWlsYWJpbGl0eTpXLkxyLEhUTUxQcm9ncmVzc0VsZW1lbnQ6Vy5LUixQcm9ncmVzc0V2ZW50Olcu
-ZXcsUmVzb3VyY2VQcm9ncmVzc0V2ZW50OlcuZXcsUlRDU3RhdHNSZXBvcnQ6Vy5wOCxIVE1MU2VsZWN0
-RWxlbWVudDpXLmxwLFNvdXJjZUJ1ZmZlcjpXLlNWLFNvdXJjZUJ1ZmZlckxpc3Q6Vy5NayxTcGVlY2hH
-cmFtbWFyOlcuWTQsU3BlZWNoR3JhbW1hckxpc3Q6Vy5ObixTcGVlY2hSZWNvZ25pdGlvblJlc3VsdDpX
-Lmw4LFN0b3JhZ2U6Vy5BcyxTdG9yYWdlRXZlbnQ6Vy5iayxDU1NTdHlsZVNoZWV0OlcuV1csU3R5bGVT
-aGVldDpXLldXLEhUTUxUYWJsZUVsZW1lbnQ6Vy5UYixIVE1MVGFibGVSb3dFbGVtZW50OlcuSXYsSFRN
-TFRhYmxlU2VjdGlvbkVsZW1lbnQ6Vy5CVCxIVE1MVGVtcGxhdGVFbGVtZW50OlcuZlgsSFRNTFRleHRB
-cmVhRWxlbWVudDpXLkZCLFRleHRUcmFjazpXLkExLFRleHRUcmFja0N1ZTpXLk1OLFZUVEN1ZTpXLk1O
-LFRleHRUcmFja0N1ZUxpc3Q6Vy5YMCxUZXh0VHJhY2tMaXN0OlcubkosVGltZVJhbmdlczpXLm16LFRv
-dWNoOlcuYTMsVG91Y2hMaXN0OlcuY2ksVHJhY2tEZWZhdWx0TGlzdDpXLmNuLENvbXBvc2l0aW9uRXZl
-bnQ6Vy53NixGb2N1c0V2ZW50OlcudzYsVGV4dEV2ZW50OlcudzYsVG91Y2hFdmVudDpXLnc2LFVJRXZl
-bnQ6Vy53NixVUkw6Vy5GaixWaWRlb1RyYWNrTGlzdDpXLnZGLFdpbmRvdzpXLk9pLERPTVdpbmRvdzpX
-Lk9pLERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOlcuQ20sU2VydmljZVdvcmtlckdsb2JhbFNjb3Bl
-OlcuQ20sU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxXb3JrZXJHbG9iYWxTY29wZTpXLkNtLEF0
-dHI6Vy5DUSxDU1NSdWxlTGlzdDpXLlBSLENsaWVudFJlY3Q6Vy53NCxET01SZWN0OlcudzQsR2FtZXBh
-ZExpc3Q6Vy5GMixOYW1lZE5vZGVNYXA6Vy5yaCxNb3pOYW1lZEF0dHJNYXA6Vy5yaCxTcGVlY2hSZWNv
-Z25pdGlvblJlc3VsdExpc3Q6Vy5MTyxTdHlsZVNoZWV0TGlzdDpXLmIxLElEQkN1cnNvcjpQLlcyLElE
-QkN1cnNvcldpdGhWYWx1ZTpQLmUzLElEQktleVJhbmdlOlAuaEYsSURCT2JzZXJ2YXRpb246UC5CVixT
-VkdBbmdsZTpQLnVqLFNWR0xlbmd0aDpQLngwLFNWR0xlbmd0aExpc3Q6UC5xNixTVkdOdW1iZXI6UC51
-UCxTVkdOdW1iZXJMaXN0OlAuTFosU1ZHUG9pbnRMaXN0OlAuRUQsU1ZHU2NyaXB0RWxlbWVudDpQLm5k
-LFNWR1N0cmluZ0xpc3Q6UC5LcSxTVkdBRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVFbGVtZW50OlAuZDUs
-U1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlVHJhbnNmb3JtRWxlbWVudDpQLmQ1
-LFNWR0FuaW1hdGlvbkVsZW1lbnQ6UC5kNSxTVkdDaXJjbGVFbGVtZW50OlAuZDUsU1ZHQ2xpcFBhdGhF
-bGVtZW50OlAuZDUsU1ZHRGVmc0VsZW1lbnQ6UC5kNSxTVkdEZXNjRWxlbWVudDpQLmQ1LFNWR0Rpc2Nh
-cmRFbGVtZW50OlAuZDUsU1ZHRWxsaXBzZUVsZW1lbnQ6UC5kNSxTVkdGRUJsZW5kRWxlbWVudDpQLmQ1
-LFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAuZDUsU1ZHRkVDb21wb25lbnRUcmFuc2ZlckVsZW1lbnQ6
-UC5kNSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6UC5kNSxTVkdGRUNvbnZvbHZlTWF0cml4RWxlbWVudDpQ
-LmQ1LFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNWR0ZFRGlzcGxhY2VtZW50TWFwRWxl
-bWVudDpQLmQ1LFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFRmxvb2RFbGVtZW50OlAu
-ZDUsU1ZHRkVGdW5jQUVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNCRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0dF
-bGVtZW50OlAuZDUsU1ZHRkVGdW5jUkVsZW1lbnQ6UC5kNSxTVkdGRUdhdXNzaWFuQmx1ckVsZW1lbnQ6
-UC5kNSxTVkdGRUltYWdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVyZ2VFbGVtZW50OlAuZDUsU1ZHRkVNZXJn
-ZU5vZGVFbGVtZW50OlAuZDUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDpQLmQ1LFNWR0ZFT2Zmc2V0RWxl
-bWVudDpQLmQ1LFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRVNwZWN1bGFyTGlnaHRpbmdF
-bGVtZW50OlAuZDUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVUaWxlRWxlbWVudDpQLmQ1
-LFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6UC5kNSxTVkdGaWx0ZXJFbGVtZW50OlAuZDUsU1ZHRm9yZWln
-bk9iamVjdEVsZW1lbnQ6UC5kNSxTVkdHRWxlbWVudDpQLmQ1LFNWR0dlb21ldHJ5RWxlbWVudDpQLmQ1
-LFNWR0dyYXBoaWNzRWxlbWVudDpQLmQ1LFNWR0ltYWdlRWxlbWVudDpQLmQ1LFNWR0xpbmVFbGVtZW50
-OlAuZDUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHTWFya2VyRWxlbWVudDpQLmQ1LFNW
-R01hc2tFbGVtZW50OlAuZDUsU1ZHTWV0YWRhdGFFbGVtZW50OlAuZDUsU1ZHUGF0aEVsZW1lbnQ6UC5k
-NSxTVkdQYXR0ZXJuRWxlbWVudDpQLmQ1LFNWR1BvbHlnb25FbGVtZW50OlAuZDUsU1ZHUG9seWxpbmVF
-bGVtZW50OlAuZDUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHUmVjdEVsZW1lbnQ6UC5k
-NSxTVkdTZXRFbGVtZW50OlAuZDUsU1ZHU3RvcEVsZW1lbnQ6UC5kNSxTVkdTdHlsZUVsZW1lbnQ6UC5k
-NSxTVkdTVkdFbGVtZW50OlAuZDUsU1ZHU3dpdGNoRWxlbWVudDpQLmQ1LFNWR1N5bWJvbEVsZW1lbnQ6
-UC5kNSxTVkdUU3BhbkVsZW1lbnQ6UC5kNSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6UC5kNSxTVkdUZXh0
-RWxlbWVudDpQLmQ1LFNWR1RleHRQYXRoRWxlbWVudDpQLmQ1LFNWR1RleHRQb3NpdGlvbmluZ0VsZW1l
-bnQ6UC5kNSxTVkdUaXRsZUVsZW1lbnQ6UC5kNSxTVkdVc2VFbGVtZW50OlAuZDUsU1ZHVmlld0VsZW1l
-bnQ6UC5kNSxTVkdHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdDb21wb25lbnRUcmFuc2ZlckZ1bmN0aW9u
-RWxlbWVudDpQLmQ1LFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6UC5kNSxTVkdNUGF0aEVsZW1lbnQ6UC5k
-NSxTVkdFbGVtZW50OlAuZDUsU1ZHVHJhbnNmb3JtOlAuelksU1ZHVHJhbnNmb3JtTGlzdDpQLk5DLEF1
-ZGlvQnVmZmVyOlAucjIsQXVkaW9QYXJhbTpQLnJPLEF1ZGlvUGFyYW1NYXA6UC5EWCxBdWRpb1RyYWNr
-TGlzdDpQLmZvLEF1ZGlvQ29udGV4dDpQLlY4LHdlYmtpdEF1ZGlvQ29udGV4dDpQLlY4LEJhc2VBdWRp
-b0NvbnRleHQ6UC5WOCxPZmZsaW5lQXVkaW9Db250ZXh0OlAuR24sU1FMUmVzdWx0U2V0Um93TGlzdDpQ
-LkZufSkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVMZWFmVGFncyh7QW5pbWF0aW9uRWZmZWN0UmVhZE9u
-bHk6dHJ1ZSxBbmltYXRpb25FZmZlY3RUaW1pbmc6dHJ1ZSxBbmltYXRpb25FZmZlY3RUaW1pbmdSZWFk
-T25seTp0cnVlLEFuaW1hdGlvblRpbWVsaW5lOnRydWUsQW5pbWF0aW9uV29ya2xldEdsb2JhbFNjb3Bl
-OnRydWUsQXV0aGVudGljYXRvckFzc2VydGlvblJlc3BvbnNlOnRydWUsQXV0aGVudGljYXRvckF0dGVz
-dGF0aW9uUmVzcG9uc2U6dHJ1ZSxBdXRoZW50aWNhdG9yUmVzcG9uc2U6dHJ1ZSxCYWNrZ3JvdW5kRmV0
-Y2hGZXRjaDp0cnVlLEJhY2tncm91bmRGZXRjaE1hbmFnZXI6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hTZXR0
-bGVkRmV0Y2g6dHJ1ZSxCYXJQcm9wOnRydWUsQmFyY29kZURldGVjdG9yOnRydWUsQm9keTp0cnVlLEJ1
-ZGdldFN0YXRlOnRydWUsQ2FjaGVTdG9yYWdlOnRydWUsQ2FudmFzR3JhZGllbnQ6dHJ1ZSxDYW52YXNQ
-YXR0ZXJuOnRydWUsQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEOnRydWUsQ2xpZW50OnRydWUsQ2xpZW50
-czp0cnVlLENvb2tpZVN0b3JlOnRydWUsQ29vcmRpbmF0ZXM6dHJ1ZSxDcmVkZW50aWFsOnRydWUsQ3Jl
-ZGVudGlhbFVzZXJEYXRhOnRydWUsQ3JlZGVudGlhbHNDb250YWluZXI6dHJ1ZSxDcnlwdG86dHJ1ZSxD
-cnlwdG9LZXk6dHJ1ZSxDU1M6dHJ1ZSxDU1NWYXJpYWJsZVJlZmVyZW5jZVZhbHVlOnRydWUsQ3VzdG9t
-RWxlbWVudFJlZ2lzdHJ5OnRydWUsRGF0YVRyYW5zZmVyOnRydWUsRGF0YVRyYW5zZmVySXRlbTp0cnVl
-LERlcHJlY2F0ZWRTdG9yYWdlSW5mbzp0cnVlLERlcHJlY2F0ZWRTdG9yYWdlUXVvdGE6dHJ1ZSxEZXBy
-ZWNhdGlvblJlcG9ydDp0cnVlLERldGVjdGVkQmFyY29kZTp0cnVlLERldGVjdGVkRmFjZTp0cnVlLERl
-dGVjdGVkVGV4dDp0cnVlLERldmljZUFjY2VsZXJhdGlvbjp0cnVlLERldmljZVJvdGF0aW9uUmF0ZTp0
-cnVlLERpcmVjdG9yeUVudHJ5OnRydWUsRGlyZWN0b3J5UmVhZGVyOnRydWUsRG9jdW1lbnRPclNoYWRv
-d1Jvb3Q6dHJ1ZSxEb2N1bWVudFRpbWVsaW5lOnRydWUsRE9NRXJyb3I6dHJ1ZSxET01JbXBsZW1lbnRh
-dGlvbjp0cnVlLEl0ZXJhdG9yOnRydWUsRE9NTWF0cml4OnRydWUsRE9NTWF0cml4UmVhZE9ubHk6dHJ1
-ZSxET01QYXJzZXI6dHJ1ZSxET01Qb2ludDp0cnVlLERPTVBvaW50UmVhZE9ubHk6dHJ1ZSxET01RdWFk
-OnRydWUsRE9NU3RyaW5nTWFwOnRydWUsRW50cnk6dHJ1ZSxFeHRlcm5hbDp0cnVlLEZhY2VEZXRlY3Rv
-cjp0cnVlLEZlZGVyYXRlZENyZWRlbnRpYWw6dHJ1ZSxGaWxlRW50cnk6dHJ1ZSxET01GaWxlU3lzdGVt
-OnRydWUsRm9udEZhY2U6dHJ1ZSxGb250RmFjZVNvdXJjZTp0cnVlLEZvcm1EYXRhOnRydWUsR2FtZXBh
-ZFBvc2U6dHJ1ZSxHZW9sb2NhdGlvbjp0cnVlLFBvc2l0aW9uOnRydWUsSGVhZGVyczp0cnVlLEhUTUxI
-eXBlcmxpbmtFbGVtZW50VXRpbHM6dHJ1ZSxJZGxlRGVhZGxpbmU6dHJ1ZSxJbWFnZUJpdG1hcDp0cnVl
-LEltYWdlQml0bWFwUmVuZGVyaW5nQ29udGV4dDp0cnVlLEltYWdlQ2FwdHVyZTp0cnVlLElucHV0RGV2
-aWNlQ2FwYWJpbGl0aWVzOnRydWUsSW50ZXJzZWN0aW9uT2JzZXJ2ZXI6dHJ1ZSxJbnRlcnNlY3Rpb25P
-YnNlcnZlckVudHJ5OnRydWUsSW50ZXJ2ZW50aW9uUmVwb3J0OnRydWUsS2V5ZnJhbWVFZmZlY3Q6dHJ1
-ZSxLZXlmcmFtZUVmZmVjdFJlYWRPbmx5OnRydWUsTWVkaWFDYXBhYmlsaXRpZXM6dHJ1ZSxNZWRpYUNh
-cGFiaWxpdGllc0luZm86dHJ1ZSxNZWRpYURldmljZUluZm86dHJ1ZSxNZWRpYUVycm9yOnRydWUsTWVk
-aWFLZXlTdGF0dXNNYXA6dHJ1ZSxNZWRpYUtleVN5c3RlbUFjY2Vzczp0cnVlLE1lZGlhS2V5czp0cnVl
-LE1lZGlhS2V5c1BvbGljeTp0cnVlLE1lZGlhTWV0YWRhdGE6dHJ1ZSxNZWRpYVNlc3Npb246dHJ1ZSxN
-ZWRpYVNldHRpbmdzUmFuZ2U6dHJ1ZSxNZW1vcnlJbmZvOnRydWUsTWVzc2FnZUNoYW5uZWw6dHJ1ZSxN
-ZXRhZGF0YTp0cnVlLE11dGF0aW9uT2JzZXJ2ZXI6dHJ1ZSxXZWJLaXRNdXRhdGlvbk9ic2VydmVyOnRy
-dWUsTXV0YXRpb25SZWNvcmQ6dHJ1ZSxOYXZpZ2F0aW9uUHJlbG9hZE1hbmFnZXI6dHJ1ZSxOYXZpZ2F0
-b3I6dHJ1ZSxOYXZpZ2F0b3JBdXRvbWF0aW9uSW5mb3JtYXRpb246dHJ1ZSxOYXZpZ2F0b3JDb25jdXJy
-ZW50SGFyZHdhcmU6dHJ1ZSxOYXZpZ2F0b3JDb29raWVzOnRydWUsTmF2aWdhdG9yVXNlck1lZGlhRXJy
-b3I6dHJ1ZSxOb2RlRmlsdGVyOnRydWUsTm9kZUl0ZXJhdG9yOnRydWUsTm9uRG9jdW1lbnRUeXBlQ2hp
-bGROb2RlOnRydWUsTm9uRWxlbWVudFBhcmVudE5vZGU6dHJ1ZSxOb25jZWRFbGVtZW50OnRydWUsT2Zm
-c2NyZWVuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1
-ZSxQYWludFJlbmRlcmluZ0NvbnRleHQyRDp0cnVlLFBhaW50U2l6ZTp0cnVlLFBhaW50V29ya2xldEds
-b2JhbFNjb3BlOnRydWUsUGFzc3dvcmRDcmVkZW50aWFsOnRydWUsUGF0aDJEOnRydWUsUGF5bWVudEFk
-ZHJlc3M6dHJ1ZSxQYXltZW50SW5zdHJ1bWVudHM6dHJ1ZSxQYXltZW50TWFuYWdlcjp0cnVlLFBheW1l
-bnRSZXNwb25zZTp0cnVlLFBlcmZvcm1hbmNlRW50cnk6dHJ1ZSxQZXJmb3JtYW5jZUxvbmdUYXNrVGlt
-aW5nOnRydWUsUGVyZm9ybWFuY2VNYXJrOnRydWUsUGVyZm9ybWFuY2VNZWFzdXJlOnRydWUsUGVyZm9y
-bWFuY2VOYXZpZ2F0aW9uOnRydWUsUGVyZm9ybWFuY2VOYXZpZ2F0aW9uVGltaW5nOnRydWUsUGVyZm9y
-bWFuY2VPYnNlcnZlcjp0cnVlLFBlcmZvcm1hbmNlT2JzZXJ2ZXJFbnRyeUxpc3Q6dHJ1ZSxQZXJmb3Jt
-YW5jZVBhaW50VGltaW5nOnRydWUsUGVyZm9ybWFuY2VSZXNvdXJjZVRpbWluZzp0cnVlLFBlcmZvcm1h
-bmNlU2VydmVyVGltaW5nOnRydWUsUGVyZm9ybWFuY2VUaW1pbmc6dHJ1ZSxQZXJtaXNzaW9uczp0cnVl
-LFBob3RvQ2FwYWJpbGl0aWVzOnRydWUsUG9zaXRpb25FcnJvcjp0cnVlLFByZXNlbnRhdGlvbjp0cnVl
-LFByZXNlbnRhdGlvblJlY2VpdmVyOnRydWUsUHVibGljS2V5Q3JlZGVudGlhbDp0cnVlLFB1c2hNYW5h
-Z2VyOnRydWUsUHVzaE1lc3NhZ2VEYXRhOnRydWUsUHVzaFN1YnNjcmlwdGlvbjp0cnVlLFB1c2hTdWJz
-Y3JpcHRpb25PcHRpb25zOnRydWUsUmFuZ2U6dHJ1ZSxSZWxhdGVkQXBwbGljYXRpb246dHJ1ZSxSZXBv
-cnRCb2R5OnRydWUsUmVwb3J0aW5nT2JzZXJ2ZXI6dHJ1ZSxSZXNpemVPYnNlcnZlcjp0cnVlLFJlc2l6
-ZU9ic2VydmVyRW50cnk6dHJ1ZSxSVENDZXJ0aWZpY2F0ZTp0cnVlLFJUQ0ljZUNhbmRpZGF0ZTp0cnVl
-LG1velJUQ0ljZUNhbmRpZGF0ZTp0cnVlLFJUQ0xlZ2FjeVN0YXRzUmVwb3J0OnRydWUsUlRDUnRwQ29u
-dHJpYnV0aW5nU291cmNlOnRydWUsUlRDUnRwUmVjZWl2ZXI6dHJ1ZSxSVENSdHBTZW5kZXI6dHJ1ZSxS
-VENTZXNzaW9uRGVzY3JpcHRpb246dHJ1ZSxtb3pSVENTZXNzaW9uRGVzY3JpcHRpb246dHJ1ZSxSVENT
-dGF0c1Jlc3BvbnNlOnRydWUsU2NyZWVuOnRydWUsU2Nyb2xsU3RhdGU6dHJ1ZSxTY3JvbGxUaW1lbGlu
-ZTp0cnVlLFNlbGVjdGlvbjp0cnVlLFNoYXJlZEFycmF5QnVmZmVyOnRydWUsU3BlZWNoUmVjb2duaXRp
-b25BbHRlcm5hdGl2ZTp0cnVlLFNwZWVjaFN5bnRoZXNpc1ZvaWNlOnRydWUsU3RhdGljUmFuZ2U6dHJ1
-ZSxTdG9yYWdlTWFuYWdlcjp0cnVlLFN0eWxlTWVkaWE6dHJ1ZSxTdHlsZVByb3BlcnR5TWFwOnRydWUs
-U3R5bGVQcm9wZXJ0eU1hcFJlYWRvbmx5OnRydWUsU3luY01hbmFnZXI6dHJ1ZSxUYXNrQXR0cmlidXRp
-b25UaW1pbmc6dHJ1ZSxUZXh0RGV0ZWN0b3I6dHJ1ZSxUZXh0TWV0cmljczp0cnVlLFRyYWNrRGVmYXVs
-dDp0cnVlLFRyZWVXYWxrZXI6dHJ1ZSxUcnVzdGVkSFRNTDp0cnVlLFRydXN0ZWRTY3JpcHRVUkw6dHJ1
-ZSxUcnVzdGVkVVJMOnRydWUsVW5kZXJseWluZ1NvdXJjZUJhc2U6dHJ1ZSxVUkxTZWFyY2hQYXJhbXM6
-dHJ1ZSxWUkNvb3JkaW5hdGVTeXN0ZW06dHJ1ZSxWUkRpc3BsYXlDYXBhYmlsaXRpZXM6dHJ1ZSxWUkV5
-ZVBhcmFtZXRlcnM6dHJ1ZSxWUkZyYW1lRGF0YTp0cnVlLFZSRnJhbWVPZlJlZmVyZW5jZTp0cnVlLFZS
-UG9zZTp0cnVlLFZSU3RhZ2VCb3VuZHM6dHJ1ZSxWUlN0YWdlQm91bmRzUG9pbnQ6dHJ1ZSxWUlN0YWdl
-UGFyYW1ldGVyczp0cnVlLFZhbGlkaXR5U3RhdGU6dHJ1ZSxWaWRlb1BsYXliYWNrUXVhbGl0eTp0cnVl
-LFZpZGVvVHJhY2s6dHJ1ZSxWVFRSZWdpb246dHJ1ZSxXaW5kb3dDbGllbnQ6dHJ1ZSxXb3JrbGV0QW5p
-bWF0aW9uOnRydWUsV29ya2xldEdsb2JhbFNjb3BlOnRydWUsWFBhdGhFdmFsdWF0b3I6dHJ1ZSxYUGF0
-aEV4cHJlc3Npb246dHJ1ZSxYUGF0aE5TUmVzb2x2ZXI6dHJ1ZSxYUGF0aFJlc3VsdDp0cnVlLFhNTFNl
-cmlhbGl6ZXI6dHJ1ZSxYU0xUUHJvY2Vzc29yOnRydWUsQmx1ZXRvb3RoOnRydWUsQmx1ZXRvb3RoQ2hh
-cmFjdGVyaXN0aWNQcm9wZXJ0aWVzOnRydWUsQmx1ZXRvb3RoUmVtb3RlR0FUVFNlcnZlcjp0cnVlLEJs
-dWV0b290aFJlbW90ZUdBVFRTZXJ2aWNlOnRydWUsQmx1ZXRvb3RoVVVJRDp0cnVlLEJ1ZGdldFNlcnZp
-Y2U6dHJ1ZSxDYWNoZTp0cnVlLERPTUZpbGVTeXN0ZW1TeW5jOnRydWUsRGlyZWN0b3J5RW50cnlTeW5j
-OnRydWUsRGlyZWN0b3J5UmVhZGVyU3luYzp0cnVlLEVudHJ5U3luYzp0cnVlLEZpbGVFbnRyeVN5bmM6
-dHJ1ZSxGaWxlUmVhZGVyU3luYzp0cnVlLEZpbGVXcml0ZXJTeW5jOnRydWUsSFRNTEFsbENvbGxlY3Rp
-b246dHJ1ZSxNb2pvOnRydWUsTW9qb0hhbmRsZTp0cnVlLE1vam9XYXRjaGVyOnRydWUsTkZDOnRydWUs
-UGFnZVBvcHVwQ29udHJvbGxlcjp0cnVlLFJlcG9ydDp0cnVlLFJlcXVlc3Q6dHJ1ZSxSZXNwb25zZTp0
-cnVlLFN1YnRsZUNyeXB0bzp0cnVlLFVTQkFsdGVybmF0ZUludGVyZmFjZTp0cnVlLFVTQkNvbmZpZ3Vy
-YXRpb246dHJ1ZSxVU0JEZXZpY2U6dHJ1ZSxVU0JFbmRwb2ludDp0cnVlLFVTQkluVHJhbnNmZXJSZXN1
-bHQ6dHJ1ZSxVU0JJbnRlcmZhY2U6dHJ1ZSxVU0JJc29jaHJvbm91c0luVHJhbnNmZXJQYWNrZXQ6dHJ1
-ZSxVU0JJc29jaHJvbm91c0luVHJhbnNmZXJSZXN1bHQ6dHJ1ZSxVU0JJc29jaHJvbm91c091dFRyYW5z
-ZmVyUGFja2V0OnRydWUsVVNCSXNvY2hyb25vdXNPdXRUcmFuc2ZlclJlc3VsdDp0cnVlLFVTQk91dFRy
-YW5zZmVyUmVzdWx0OnRydWUsV29ya2VyTG9jYXRpb246dHJ1ZSxXb3JrZXJOYXZpZ2F0b3I6dHJ1ZSxX
-b3JrbGV0OnRydWUsSURCRmFjdG9yeTp0cnVlLElEQkluZGV4OnRydWUsSURCT2JqZWN0U3RvcmU6dHJ1
-ZSxJREJPYnNlcnZlcjp0cnVlLElEQk9ic2VydmVyQ2hhbmdlczp0cnVlLFNWR0FuaW1hdGVkQW5nbGU6
-dHJ1ZSxTVkdBbmltYXRlZEJvb2xlYW46dHJ1ZSxTVkdBbmltYXRlZEVudW1lcmF0aW9uOnRydWUsU1ZH
-QW5pbWF0ZWRJbnRlZ2VyOnRydWUsU1ZHQW5pbWF0ZWRMZW5ndGg6dHJ1ZSxTVkdBbmltYXRlZExlbmd0
-aExpc3Q6dHJ1ZSxTVkdBbmltYXRlZE51bWJlcjp0cnVlLFNWR0FuaW1hdGVkTnVtYmVyTGlzdDp0cnVl
-LFNWR0FuaW1hdGVkUHJlc2VydmVBc3BlY3RSYXRpbzp0cnVlLFNWR0FuaW1hdGVkUmVjdDp0cnVlLFNW
-R0FuaW1hdGVkU3RyaW5nOnRydWUsU1ZHQW5pbWF0ZWRUcmFuc2Zvcm1MaXN0OnRydWUsU1ZHTWF0cml4
-OnRydWUsU1ZHUG9pbnQ6dHJ1ZSxTVkdQcmVzZXJ2ZUFzcGVjdFJhdGlvOnRydWUsU1ZHUmVjdDp0cnVl
-LFNWR1VuaXRUeXBlczp0cnVlLEF1ZGlvTGlzdGVuZXI6dHJ1ZSxBdWRpb1RyYWNrOnRydWUsQXVkaW9X
-b3JrbGV0R2xvYmFsU2NvcGU6dHJ1ZSxBdWRpb1dvcmtsZXRQcm9jZXNzb3I6dHJ1ZSxQZXJpb2RpY1dh
-dmU6dHJ1ZSxXZWJHTEFjdGl2ZUluZm86dHJ1ZSxBTkdMRUluc3RhbmNlZEFycmF5czp0cnVlLEFOR0xF
-X2luc3RhbmNlZF9hcnJheXM6dHJ1ZSxXZWJHTEJ1ZmZlcjp0cnVlLFdlYkdMQ2FudmFzOnRydWUsV2Vi
-R0xDb2xvckJ1ZmZlckZsb2F0OnRydWUsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUFTVEM6dHJ1ZSxXZWJH
-TENvbXByZXNzZWRUZXh0dXJlQVRDOnRydWUsV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX2F0Yzp0cnVl
-LFdlYkdMQ29tcHJlc3NlZFRleHR1cmVFVEMxOnRydWUsV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX2V0
-YzE6dHJ1ZSxXZWJHTENvbXByZXNzZWRUZXh0dXJlRVRDOnRydWUsV2ViR0xDb21wcmVzc2VkVGV4dHVy
-ZVBWUlRDOnRydWUsV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX3B2cnRjOnRydWUsV2ViR0xDb21wcmVz
-c2VkVGV4dHVyZVMzVEM6dHJ1ZSxXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0Yzp0cnVlLFdlYkdM
-Q29tcHJlc3NlZFRleHR1cmVTM1RDc1JHQjp0cnVlLFdlYkdMRGVidWdSZW5kZXJlckluZm86dHJ1ZSxX
-RUJHTF9kZWJ1Z19yZW5kZXJlcl9pbmZvOnRydWUsV2ViR0xEZWJ1Z1NoYWRlcnM6dHJ1ZSxXRUJHTF9k
-ZWJ1Z19zaGFkZXJzOnRydWUsV2ViR0xEZXB0aFRleHR1cmU6dHJ1ZSxXRUJHTF9kZXB0aF90ZXh0dXJl
-OnRydWUsV2ViR0xEcmF3QnVmZmVyczp0cnVlLFdFQkdMX2RyYXdfYnVmZmVyczp0cnVlLEVYVHNSR0I6
-dHJ1ZSxFWFRfc1JHQjp0cnVlLEVYVEJsZW5kTWluTWF4OnRydWUsRVhUX2JsZW5kX21pbm1heDp0cnVl
-LEVYVENvbG9yQnVmZmVyRmxvYXQ6dHJ1ZSxFWFRDb2xvckJ1ZmZlckhhbGZGbG9hdDp0cnVlLEVYVERp
-c2pvaW50VGltZXJRdWVyeTp0cnVlLEVYVERpc2pvaW50VGltZXJRdWVyeVdlYkdMMjp0cnVlLEVYVEZy
-YWdEZXB0aDp0cnVlLEVYVF9mcmFnX2RlcHRoOnRydWUsRVhUU2hhZGVyVGV4dHVyZUxPRDp0cnVlLEVY
-VF9zaGFkZXJfdGV4dHVyZV9sb2Q6dHJ1ZSxFWFRUZXh0dXJlRmlsdGVyQW5pc290cm9waWM6dHJ1ZSxF
-WFRfdGV4dHVyZV9maWx0ZXJfYW5pc290cm9waWM6dHJ1ZSxXZWJHTEZyYW1lYnVmZmVyOnRydWUsV2Vi
-R0xHZXRCdWZmZXJTdWJEYXRhQXN5bmM6dHJ1ZSxXZWJHTExvc2VDb250ZXh0OnRydWUsV2ViR0xFeHRl
-bnNpb25Mb3NlQ29udGV4dDp0cnVlLFdFQkdMX2xvc2VfY29udGV4dDp0cnVlLE9FU0VsZW1lbnRJbmRl
-eFVpbnQ6dHJ1ZSxPRVNfZWxlbWVudF9pbmRleF91aW50OnRydWUsT0VTU3RhbmRhcmREZXJpdmF0aXZl
-czp0cnVlLE9FU19zdGFuZGFyZF9kZXJpdmF0aXZlczp0cnVlLE9FU1RleHR1cmVGbG9hdDp0cnVlLE9F
-U190ZXh0dXJlX2Zsb2F0OnRydWUsT0VTVGV4dHVyZUZsb2F0TGluZWFyOnRydWUsT0VTX3RleHR1cmVf
-ZmxvYXRfbGluZWFyOnRydWUsT0VTVGV4dHVyZUhhbGZGbG9hdDp0cnVlLE9FU190ZXh0dXJlX2hhbGZf
-ZmxvYXQ6dHJ1ZSxPRVNUZXh0dXJlSGFsZkZsb2F0TGluZWFyOnRydWUsT0VTX3RleHR1cmVfaGFsZl9m
-bG9hdF9saW5lYXI6dHJ1ZSxPRVNWZXJ0ZXhBcnJheU9iamVjdDp0cnVlLE9FU192ZXJ0ZXhfYXJyYXlf
-b2JqZWN0OnRydWUsV2ViR0xQcm9ncmFtOnRydWUsV2ViR0xRdWVyeTp0cnVlLFdlYkdMUmVuZGVyYnVm
-ZmVyOnRydWUsV2ViR0xSZW5kZXJpbmdDb250ZXh0OnRydWUsV2ViR0wyUmVuZGVyaW5nQ29udGV4dDp0
-cnVlLFdlYkdMU2FtcGxlcjp0cnVlLFdlYkdMU2hhZGVyOnRydWUsV2ViR0xTaGFkZXJQcmVjaXNpb25G
-b3JtYXQ6dHJ1ZSxXZWJHTFN5bmM6dHJ1ZSxXZWJHTFRleHR1cmU6dHJ1ZSxXZWJHTFRpbWVyUXVlcnlF
-WFQ6dHJ1ZSxXZWJHTFRyYW5zZm9ybUZlZWRiYWNrOnRydWUsV2ViR0xVbmlmb3JtTG9jYXRpb246dHJ1
-ZSxXZWJHTFZlcnRleEFycmF5T2JqZWN0OnRydWUsV2ViR0xWZXJ0ZXhBcnJheU9iamVjdE9FUzp0cnVl
-LFdlYkdMOnRydWUsV2ViR0wyUmVuZGVyaW5nQ29udGV4dEJhc2U6dHJ1ZSxEYXRhYmFzZTp0cnVlLFNR
-TEVycm9yOnRydWUsU1FMUmVzdWx0U2V0OnRydWUsU1FMVHJhbnNhY3Rpb246dHJ1ZSxBcnJheUJ1ZmZl
-cjp0cnVlLERhdGFWaWV3OnRydWUsQXJyYXlCdWZmZXJWaWV3OmZhbHNlLEZsb2F0MzJBcnJheTp0cnVl
-LEZsb2F0NjRBcnJheTp0cnVlLEludDE2QXJyYXk6dHJ1ZSxJbnQzMkFycmF5OnRydWUsSW50OEFycmF5
-OnRydWUsVWludDE2QXJyYXk6dHJ1ZSxVaW50MzJBcnJheTp0cnVlLFVpbnQ4Q2xhbXBlZEFycmF5OnRy
-dWUsQ2FudmFzUGl4ZWxBcnJheTp0cnVlLFVpbnQ4QXJyYXk6ZmFsc2UsSFRNTEF1ZGlvRWxlbWVudDp0
-cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1ZSxIVE1MQ2FudmFzRWxlbWVudDp0cnVlLEhUTUxDb250ZW50RWxl
-bWVudDp0cnVlLEhUTUxETGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MRGF0YUxpc3RFbGVtZW50OnRydWUsSFRN
-TERldGFpbHNFbGVtZW50OnRydWUsSFRNTERpYWxvZ0VsZW1lbnQ6dHJ1ZSxIVE1MRGl2RWxlbWVudDp0
-cnVlLEhUTUxFbWJlZEVsZW1lbnQ6dHJ1ZSxIVE1MRmllbGRTZXRFbGVtZW50OnRydWUsSFRNTEhSRWxl
-bWVudDp0cnVlLEhUTUxIZWFkRWxlbWVudDp0cnVlLEhUTUxIZWFkaW5nRWxlbWVudDp0cnVlLEhUTUxI
-dG1sRWxlbWVudDp0cnVlLEhUTUxJRnJhbWVFbGVtZW50OnRydWUsSFRNTEltYWdlRWxlbWVudDp0cnVl
-LEhUTUxMYWJlbEVsZW1lbnQ6dHJ1ZSxIVE1MTGVnZW5kRWxlbWVudDp0cnVlLEhUTUxMaW5rRWxlbWVu
-dDp0cnVlLEhUTUxNYXBFbGVtZW50OnRydWUsSFRNTE1lZGlhRWxlbWVudDp0cnVlLEhUTUxNZW51RWxl
-bWVudDp0cnVlLEhUTUxNZXRhRWxlbWVudDp0cnVlLEhUTUxNb2RFbGVtZW50OnRydWUsSFRNTE9MaXN0
-RWxlbWVudDp0cnVlLEhUTUxPYmplY3RFbGVtZW50OnRydWUsSFRNTE9wdEdyb3VwRWxlbWVudDp0cnVl
-LEhUTUxQaWN0dXJlRWxlbWVudDp0cnVlLEhUTUxQcmVFbGVtZW50OnRydWUsSFRNTFF1b3RlRWxlbWVu
-dDp0cnVlLEhUTUxTY3JpcHRFbGVtZW50OnRydWUsSFRNTFNoYWRvd0VsZW1lbnQ6dHJ1ZSxIVE1MU2xv
-dEVsZW1lbnQ6dHJ1ZSxIVE1MU291cmNlRWxlbWVudDp0cnVlLEhUTUxTcGFuRWxlbWVudDp0cnVlLEhU
-TUxTdHlsZUVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNl
-bGxFbGVtZW50OnRydWUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OnRydWUsSFRNTFRhYmxlSGVhZGVy
-Q2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDb2xFbGVtZW50OnRydWUsSFRNTFRpbWVFbGVtZW50OnRy
-dWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0VsZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RFbGVt
-ZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRydWUsSFRNTFZpZGVvRWxlbWVudDp0cnVlLEhUTUxE
-aXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50OnRydWUsSFRNTEZyYW1lRWxlbWVudDp0
-cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFycXVlZUVsZW1lbnQ6dHJ1ZSxIVE1MRWxl
-bWVudDpmYWxzZSxBY2Nlc3NpYmxlTm9kZUxpc3Q6dHJ1ZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhU
-TUxBcmVhRWxlbWVudDp0cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsQmx1ZXRvb3Ro
-UmVtb3RlR0FUVERlc2NyaXB0b3I6dHJ1ZSxIVE1MQm9keUVsZW1lbnQ6dHJ1ZSxIVE1MQnV0dG9uRWxl
-bWVudDp0cnVlLENEQVRBU2VjdGlvbjp0cnVlLENoYXJhY3RlckRhdGE6dHJ1ZSxDb21tZW50OnRydWUs
-UHJvY2Vzc2luZ0luc3RydWN0aW9uOnRydWUsVGV4dDp0cnVlLENTU0tleXdvcmRWYWx1ZTp0cnVlLENT
-U051bWVyaWNWYWx1ZTpmYWxzZSxDU1NQZXJzcGVjdGl2ZTp0cnVlLENTU0NoYXJzZXRSdWxlOnRydWUs
-Q1NTQ29uZGl0aW9uUnVsZTp0cnVlLENTU0ZvbnRGYWNlUnVsZTp0cnVlLENTU0dyb3VwaW5nUnVsZTp0
-cnVlLENTU0ltcG9ydFJ1bGU6dHJ1ZSxDU1NLZXlmcmFtZVJ1bGU6dHJ1ZSxNb3pDU1NLZXlmcmFtZVJ1
-bGU6dHJ1ZSxXZWJLaXRDU1NLZXlmcmFtZVJ1bGU6dHJ1ZSxDU1NLZXlmcmFtZXNSdWxlOnRydWUsTW96
-Q1NTS2V5ZnJhbWVzUnVsZTp0cnVlLFdlYktpdENTU0tleWZyYW1lc1J1bGU6dHJ1ZSxDU1NNZWRpYVJ1
-bGU6dHJ1ZSxDU1NOYW1lc3BhY2VSdWxlOnRydWUsQ1NTUGFnZVJ1bGU6dHJ1ZSxDU1NSdWxlOnRydWUs
-Q1NTU3R5bGVSdWxlOnRydWUsQ1NTU3VwcG9ydHNSdWxlOnRydWUsQ1NTVmlld3BvcnRSdWxlOnRydWUs
-Q1NTU3R5bGVEZWNsYXJhdGlvbjp0cnVlLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOnRydWUsQ1NTMlByb3Bl
-cnRpZXM6dHJ1ZSxDU1NJbWFnZVZhbHVlOnRydWUsQ1NTUG9zaXRpb25WYWx1ZTp0cnVlLENTU1Jlc291
-cmNlVmFsdWU6dHJ1ZSxDU1NVUkxJbWFnZVZhbHVlOnRydWUsQ1NTU3R5bGVWYWx1ZTpmYWxzZSxDU1NN
-YXRyaXhDb21wb25lbnQ6dHJ1ZSxDU1NSb3RhdGlvbjp0cnVlLENTU1NjYWxlOnRydWUsQ1NTU2tldzp0
-cnVlLENTU1RyYW5zbGF0aW9uOnRydWUsQ1NTVHJhbnNmb3JtQ29tcG9uZW50OmZhbHNlLENTU1RyYW5z
-Zm9ybVZhbHVlOnRydWUsQ1NTVW5pdFZhbHVlOnRydWUsQ1NTVW5wYXJzZWRWYWx1ZTp0cnVlLEhUTUxE
-YXRhRWxlbWVudDp0cnVlLERhdGFUcmFuc2Zlckl0ZW1MaXN0OnRydWUsWE1MRG9jdW1lbnQ6dHJ1ZSxE
-b2N1bWVudDpmYWxzZSxET01FeGNlcHRpb246dHJ1ZSxDbGllbnRSZWN0TGlzdDp0cnVlLERPTVJlY3RM
-aXN0OnRydWUsRE9NUmVjdFJlYWRPbmx5OmZhbHNlLERPTVN0cmluZ0xpc3Q6dHJ1ZSxET01Ub2tlbkxp
-c3Q6dHJ1ZSxFbGVtZW50OmZhbHNlLEFib3J0UGF5bWVudEV2ZW50OnRydWUsQW5pbWF0aW9uRXZlbnQ6
-dHJ1ZSxBbmltYXRpb25QbGF5YmFja0V2ZW50OnRydWUsQXBwbGljYXRpb25DYWNoZUVycm9yRXZlbnQ6
-dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRXZlbnQ6dHJ1
-ZSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hlZEV2ZW50OnRydWUs
-QmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OnRydWUsQmVmb3JlVW5sb2FkRXZlbnQ6dHJ1ZSxCbG9iRXZl
-bnQ6dHJ1ZSxDYW5NYWtlUGF5bWVudEV2ZW50OnRydWUsQ2xpcGJvYXJkRXZlbnQ6dHJ1ZSxDbG9zZUV2
-ZW50OnRydWUsQ3VzdG9tRXZlbnQ6dHJ1ZSxEZXZpY2VNb3Rpb25FdmVudDp0cnVlLERldmljZU9yaWVu
-dGF0aW9uRXZlbnQ6dHJ1ZSxFcnJvckV2ZW50OnRydWUsRXh0ZW5kYWJsZUV2ZW50OnRydWUsRXh0ZW5k
-YWJsZU1lc3NhZ2VFdmVudDp0cnVlLEZldGNoRXZlbnQ6dHJ1ZSxGb250RmFjZVNldExvYWRFdmVudDp0
-cnVlLEZvcmVpZ25GZXRjaEV2ZW50OnRydWUsR2FtZXBhZEV2ZW50OnRydWUsSGFzaENoYW5nZUV2ZW50
-OnRydWUsSW5zdGFsbEV2ZW50OnRydWUsTWVkaWFFbmNyeXB0ZWRFdmVudDp0cnVlLE1lZGlhS2V5TWVz
-c2FnZUV2ZW50OnRydWUsTWVkaWFRdWVyeUxpc3RFdmVudDp0cnVlLE1lZGlhU3RyZWFtRXZlbnQ6dHJ1
-ZSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6dHJ1ZSxNZXNzYWdlRXZlbnQ6dHJ1ZSxNSURJQ29ubmVjdGlv
-bkV2ZW50OnRydWUsTUlESU1lc3NhZ2VFdmVudDp0cnVlLE11dGF0aW9uRXZlbnQ6dHJ1ZSxOb3RpZmlj
-YXRpb25FdmVudDp0cnVlLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdEV2ZW50
-OnRydWUsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDp0cnVlLFBvcFN0YXRlRXZlbnQ6dHJ1ZSxQcmVz
-ZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9u
-Q2xvc2VFdmVudDp0cnVlLFByb21pc2VSZWplY3Rpb25FdmVudDp0cnVlLFB1c2hFdmVudDp0cnVlLFJU
-Q0RhdGFDaGFubmVsRXZlbnQ6dHJ1ZSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OnRydWUsUlRDUGVlckNv
-bm5lY3Rpb25JY2VFdmVudDp0cnVlLFJUQ1RyYWNrRXZlbnQ6dHJ1ZSxTZWN1cml0eVBvbGljeVZpb2xh
-dGlvbkV2ZW50OnRydWUsU2Vuc29yRXJyb3JFdmVudDp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXJyb3I6
-dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OnRydWUsU3BlZWNoU3ludGhlc2lzRXZlbnQ6dHJ1ZSxT
-eW5jRXZlbnQ6dHJ1ZSxUcmFja0V2ZW50OnRydWUsVHJhbnNpdGlvbkV2ZW50OnRydWUsV2ViS2l0VHJh
-bnNpdGlvbkV2ZW50OnRydWUsVlJEZXZpY2VFdmVudDp0cnVlLFZSRGlzcGxheUV2ZW50OnRydWUsVlJT
-ZXNzaW9uRXZlbnQ6dHJ1ZSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OnRydWUsVVNCQ29ubmVjdGlv
-bkV2ZW50OnRydWUsSURCVmVyc2lvbkNoYW5nZUV2ZW50OnRydWUsQXVkaW9Qcm9jZXNzaW5nRXZlbnQ6
-dHJ1ZSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6dHJ1ZSxXZWJHTENvbnRleHRFdmVudDp0cnVl
-LEV2ZW50OmZhbHNlLElucHV0RXZlbnQ6ZmFsc2UsQWJzb2x1dGVPcmllbnRhdGlvblNlbnNvcjp0cnVl
-LEFjY2VsZXJvbWV0ZXI6dHJ1ZSxBY2Nlc3NpYmxlTm9kZTp0cnVlLEFtYmllbnRMaWdodFNlbnNvcjp0
-cnVlLEFuaW1hdGlvbjp0cnVlLEFwcGxpY2F0aW9uQ2FjaGU6dHJ1ZSxET01BcHBsaWNhdGlvbkNhY2hl
-OnRydWUsT2ZmbGluZVJlc291cmNlTGlzdDp0cnVlLEJhY2tncm91bmRGZXRjaFJlZ2lzdHJhdGlvbjp0
-cnVlLEJhdHRlcnlNYW5hZ2VyOnRydWUsQnJvYWRjYXN0Q2hhbm5lbDp0cnVlLENhbnZhc0NhcHR1cmVN
-ZWRpYVN0cmVhbVRyYWNrOnRydWUsRXZlbnRTb3VyY2U6dHJ1ZSxGaWxlUmVhZGVyOnRydWUsRm9udEZh
-Y2VTZXQ6dHJ1ZSxHeXJvc2NvcGU6dHJ1ZSxMaW5lYXJBY2NlbGVyYXRpb25TZW5zb3I6dHJ1ZSxNYWdu
-ZXRvbWV0ZXI6dHJ1ZSxNZWRpYURldmljZXM6dHJ1ZSxNZWRpYUtleVNlc3Npb246dHJ1ZSxNZWRpYVF1
-ZXJ5TGlzdDp0cnVlLE1lZGlhUmVjb3JkZXI6dHJ1ZSxNZWRpYVNvdXJjZTp0cnVlLE1lZGlhU3RyZWFt
-OnRydWUsTWVkaWFTdHJlYW1UcmFjazp0cnVlLE1JRElBY2Nlc3M6dHJ1ZSxNSURJSW5wdXQ6dHJ1ZSxN
-SURJT3V0cHV0OnRydWUsTUlESVBvcnQ6dHJ1ZSxOZXR3b3JrSW5mb3JtYXRpb246dHJ1ZSxOb3RpZmlj
-YXRpb246dHJ1ZSxPZmZzY3JlZW5DYW52YXM6dHJ1ZSxPcmllbnRhdGlvblNlbnNvcjp0cnVlLFBheW1l
-bnRSZXF1ZXN0OnRydWUsUGVyZm9ybWFuY2U6dHJ1ZSxQZXJtaXNzaW9uU3RhdHVzOnRydWUsUHJlc2Vu
-dGF0aW9uQ29ubmVjdGlvbjp0cnVlLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25MaXN0OnRydWUsUHJlc2Vu
-dGF0aW9uUmVxdWVzdDp0cnVlLFJlbGF0aXZlT3JpZW50YXRpb25TZW5zb3I6dHJ1ZSxSZW1vdGVQbGF5
-YmFjazp0cnVlLFJUQ0RhdGFDaGFubmVsOnRydWUsRGF0YUNoYW5uZWw6dHJ1ZSxSVENEVE1GU2VuZGVy
-OnRydWUsUlRDUGVlckNvbm5lY3Rpb246dHJ1ZSx3ZWJraXRSVENQZWVyQ29ubmVjdGlvbjp0cnVlLG1v
-elJUQ1BlZXJDb25uZWN0aW9uOnRydWUsU2NyZWVuT3JpZW50YXRpb246dHJ1ZSxTZW5zb3I6dHJ1ZSxT
-ZXJ2aWNlV29ya2VyOnRydWUsU2VydmljZVdvcmtlckNvbnRhaW5lcjp0cnVlLFNlcnZpY2VXb3JrZXJS
-ZWdpc3RyYXRpb246dHJ1ZSxTaGFyZWRXb3JrZXI6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbjp0cnVlLFNw
-ZWVjaFN5bnRoZXNpczp0cnVlLFNwZWVjaFN5bnRoZXNpc1V0dGVyYW5jZTp0cnVlLFZSOnRydWUsVlJE
-ZXZpY2U6dHJ1ZSxWUkRpc3BsYXk6dHJ1ZSxWUlNlc3Npb246dHJ1ZSxWaXN1YWxWaWV3cG9ydDp0cnVl
-LFdlYlNvY2tldDp0cnVlLFdvcmtlcjp0cnVlLFdvcmtlclBlcmZvcm1hbmNlOnRydWUsQmx1ZXRvb3Ro
-RGV2aWNlOnRydWUsQmx1ZXRvb3RoUmVtb3RlR0FUVENoYXJhY3RlcmlzdGljOnRydWUsQ2xpcGJvYXJk
-OnRydWUsTW9qb0ludGVyZmFjZUludGVyY2VwdG9yOnRydWUsVVNCOnRydWUsSURCRGF0YWJhc2U6dHJ1
-ZSxJREJPcGVuREJSZXF1ZXN0OnRydWUsSURCVmVyc2lvbkNoYW5nZVJlcXVlc3Q6dHJ1ZSxJREJSZXF1
-ZXN0OnRydWUsSURCVHJhbnNhY3Rpb246dHJ1ZSxBbmFseXNlck5vZGU6dHJ1ZSxSZWFsdGltZUFuYWx5
-c2VyTm9kZTp0cnVlLEF1ZGlvQnVmZmVyU291cmNlTm9kZTp0cnVlLEF1ZGlvRGVzdGluYXRpb25Ob2Rl
-OnRydWUsQXVkaW9Ob2RlOnRydWUsQXVkaW9TY2hlZHVsZWRTb3VyY2VOb2RlOnRydWUsQXVkaW9Xb3Jr
-bGV0Tm9kZTp0cnVlLEJpcXVhZEZpbHRlck5vZGU6dHJ1ZSxDaGFubmVsTWVyZ2VyTm9kZTp0cnVlLEF1
-ZGlvQ2hhbm5lbE1lcmdlcjp0cnVlLENoYW5uZWxTcGxpdHRlck5vZGU6dHJ1ZSxBdWRpb0NoYW5uZWxT
-cGxpdHRlcjp0cnVlLENvbnN0YW50U291cmNlTm9kZTp0cnVlLENvbnZvbHZlck5vZGU6dHJ1ZSxEZWxh
-eU5vZGU6dHJ1ZSxEeW5hbWljc0NvbXByZXNzb3JOb2RlOnRydWUsR2Fpbk5vZGU6dHJ1ZSxBdWRpb0dh
-aW5Ob2RlOnRydWUsSUlSRmlsdGVyTm9kZTp0cnVlLE1lZGlhRWxlbWVudEF1ZGlvU291cmNlTm9kZTp0
-cnVlLE1lZGlhU3RyZWFtQXVkaW9EZXN0aW5hdGlvbk5vZGU6dHJ1ZSxNZWRpYVN0cmVhbUF1ZGlvU291
-cmNlTm9kZTp0cnVlLE9zY2lsbGF0b3JOb2RlOnRydWUsT3NjaWxsYXRvcjp0cnVlLFBhbm5lck5vZGU6
-dHJ1ZSxBdWRpb1Bhbm5lck5vZGU6dHJ1ZSx3ZWJraXRBdWRpb1Bhbm5lck5vZGU6dHJ1ZSxTY3JpcHRQ
-cm9jZXNzb3JOb2RlOnRydWUsSmF2YVNjcmlwdEF1ZGlvTm9kZTp0cnVlLFN0ZXJlb1Bhbm5lck5vZGU6
-dHJ1ZSxXYXZlU2hhcGVyTm9kZTp0cnVlLEV2ZW50VGFyZ2V0OmZhbHNlLEZpbGU6dHJ1ZSxGaWxlTGlz
-dDp0cnVlLEZpbGVXcml0ZXI6dHJ1ZSxIVE1MRm9ybUVsZW1lbnQ6dHJ1ZSxHYW1lcGFkOnRydWUsR2Ft
-ZXBhZEJ1dHRvbjp0cnVlLEhpc3Rvcnk6dHJ1ZSxIVE1MQ29sbGVjdGlvbjp0cnVlLEhUTUxGb3JtQ29u
-dHJvbHNDb2xsZWN0aW9uOnRydWUsSFRNTE9wdGlvbnNDb2xsZWN0aW9uOnRydWUsSFRNTERvY3VtZW50
-OnRydWUsWE1MSHR0cFJlcXVlc3Q6dHJ1ZSxYTUxIdHRwUmVxdWVzdFVwbG9hZDp0cnVlLFhNTEh0dHBS
-ZXF1ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1hZ2VEYXRhOnRydWUsSFRNTElucHV0RWxlbWVudDp0cnVl
-LEtleWJvYXJkRXZlbnQ6dHJ1ZSxIVE1MTElFbGVtZW50OnRydWUsTG9jYXRpb246dHJ1ZSxNZWRpYUxp
-c3Q6dHJ1ZSxNZXNzYWdlUG9ydDp0cnVlLEhUTUxNZXRlckVsZW1lbnQ6dHJ1ZSxNSURJSW5wdXRNYXA6
-dHJ1ZSxNSURJT3V0cHV0TWFwOnRydWUsTWltZVR5cGU6dHJ1ZSxNaW1lVHlwZUFycmF5OnRydWUsTW91
-c2VFdmVudDp0cnVlLERyYWdFdmVudDp0cnVlLFBvaW50ZXJFdmVudDp0cnVlLFdoZWVsRXZlbnQ6dHJ1
-ZSxEb2N1bWVudEZyYWdtZW50OnRydWUsU2hhZG93Um9vdDp0cnVlLERvY3VtZW50VHlwZTp0cnVlLE5v
-ZGU6ZmFsc2UsTm9kZUxpc3Q6dHJ1ZSxSYWRpb05vZGVMaXN0OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6
-dHJ1ZSxIVE1MT3V0cHV0RWxlbWVudDp0cnVlLEhUTUxQYXJhZ3JhcGhFbGVtZW50OnRydWUsSFRNTFBh
-cmFtRWxlbWVudDp0cnVlLFBsdWdpbjp0cnVlLFBsdWdpbkFycmF5OnRydWUsUHJlc2VudGF0aW9uQXZh
-aWxhYmlsaXR5OnRydWUsSFRNTFByb2dyZXNzRWxlbWVudDp0cnVlLFByb2dyZXNzRXZlbnQ6dHJ1ZSxS
-ZXNvdXJjZVByb2dyZXNzRXZlbnQ6dHJ1ZSxSVENTdGF0c1JlcG9ydDp0cnVlLEhUTUxTZWxlY3RFbGVt
-ZW50OnRydWUsU291cmNlQnVmZmVyOnRydWUsU291cmNlQnVmZmVyTGlzdDp0cnVlLFNwZWVjaEdyYW1t
-YXI6dHJ1ZSxTcGVlY2hHcmFtbWFyTGlzdDp0cnVlLFNwZWVjaFJlY29nbml0aW9uUmVzdWx0OnRydWUs
-U3RvcmFnZTp0cnVlLFN0b3JhZ2VFdmVudDp0cnVlLENTU1N0eWxlU2hlZXQ6dHJ1ZSxTdHlsZVNoZWV0
-OnRydWUsSFRNTFRhYmxlRWxlbWVudDp0cnVlLEhUTUxUYWJsZVJvd0VsZW1lbnQ6dHJ1ZSxIVE1MVGFi
-bGVTZWN0aW9uRWxlbWVudDp0cnVlLEhUTUxUZW1wbGF0ZUVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFF
-bGVtZW50OnRydWUsVGV4dFRyYWNrOnRydWUsVGV4dFRyYWNrQ3VlOnRydWUsVlRUQ3VlOnRydWUsVGV4
-dFRyYWNrQ3VlTGlzdDp0cnVlLFRleHRUcmFja0xpc3Q6dHJ1ZSxUaW1lUmFuZ2VzOnRydWUsVG91Y2g6
-dHJ1ZSxUb3VjaExpc3Q6dHJ1ZSxUcmFja0RlZmF1bHRMaXN0OnRydWUsQ29tcG9zaXRpb25FdmVudDp0
-cnVlLEZvY3VzRXZlbnQ6dHJ1ZSxUZXh0RXZlbnQ6dHJ1ZSxUb3VjaEV2ZW50OnRydWUsVUlFdmVudDpm
-YWxzZSxVUkw6dHJ1ZSxWaWRlb1RyYWNrTGlzdDp0cnVlLFdpbmRvdzp0cnVlLERPTVdpbmRvdzp0cnVl
-LERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2VydmljZVdvcmtlckdsb2JhbFNjb3BlOnRy
-dWUsU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxXb3JrZXJHbG9iYWxTY29wZTp0cnVlLEF0dHI6
-dHJ1ZSxDU1NSdWxlTGlzdDp0cnVlLENsaWVudFJlY3Q6dHJ1ZSxET01SZWN0OnRydWUsR2FtZXBhZExp
-c3Q6dHJ1ZSxOYW1lZE5vZGVNYXA6dHJ1ZSxNb3pOYW1lZEF0dHJNYXA6dHJ1ZSxTcGVlY2hSZWNvZ25p
-dGlvblJlc3VsdExpc3Q6dHJ1ZSxTdHlsZVNoZWV0TGlzdDp0cnVlLElEQkN1cnNvcjpmYWxzZSxJREJD
-dXJzb3JXaXRoVmFsdWU6dHJ1ZSxJREJLZXlSYW5nZTp0cnVlLElEQk9ic2VydmF0aW9uOnRydWUsU1ZH
-QW5nbGU6dHJ1ZSxTVkdMZW5ndGg6dHJ1ZSxTVkdMZW5ndGhMaXN0OnRydWUsU1ZHTnVtYmVyOnRydWUs
-U1ZHTnVtYmVyTGlzdDp0cnVlLFNWR1BvaW50TGlzdDp0cnVlLFNWR1NjcmlwdEVsZW1lbnQ6dHJ1ZSxT
-VkdTdHJpbmdMaXN0OnRydWUsU1ZHQUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlRWxlbWVudDp0cnVlLFNW
-R0FuaW1hdGVNb3Rpb25FbGVtZW50OnRydWUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6dHJ1ZSxT
-VkdBbmltYXRpb25FbGVtZW50OnRydWUsU1ZHQ2lyY2xlRWxlbWVudDp0cnVlLFNWR0NsaXBQYXRoRWxl
-bWVudDp0cnVlLFNWR0RlZnNFbGVtZW50OnRydWUsU1ZHRGVzY0VsZW1lbnQ6dHJ1ZSxTVkdEaXNjYXJk
-RWxlbWVudDp0cnVlLFNWR0VsbGlwc2VFbGVtZW50OnRydWUsU1ZHRkVCbGVuZEVsZW1lbnQ6dHJ1ZSxT
-VkdGRUNvbG9yTWF0cml4RWxlbWVudDp0cnVlLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50OnRy
-dWUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OnRydWUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6dHJ1
-ZSxTVkdGRURpZmZ1c2VMaWdodGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRURpc3BsYWNlbWVudE1hcEVsZW1l
-bnQ6dHJ1ZSxTVkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRUZsb29kRWxlbWVudDp0cnVl
-LFNWR0ZFRnVuY0FFbGVtZW50OnRydWUsU1ZHRkVGdW5jQkVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNHRWxl
-bWVudDp0cnVlLFNWR0ZFRnVuY1JFbGVtZW50OnRydWUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50OnRy
-dWUsU1ZHRkVJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VO
-b2RlRWxlbWVudDp0cnVlLFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6dHJ1ZSxTVkdGRU9mZnNldEVsZW1l
-bnQ6dHJ1ZSxTVkdGRVBvaW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5nRWxl
-bWVudDp0cnVlLFNWR0ZFU3BvdExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFVGlsZUVsZW1lbnQ6dHJ1ZSxT
-VkdGRVR1cmJ1bGVuY2VFbGVtZW50OnRydWUsU1ZHRmlsdGVyRWxlbWVudDp0cnVlLFNWR0ZvcmVpZ25P
-YmplY3RFbGVtZW50OnRydWUsU1ZHR0VsZW1lbnQ6dHJ1ZSxTVkdHZW9tZXRyeUVsZW1lbnQ6dHJ1ZSxT
-VkdHcmFwaGljc0VsZW1lbnQ6dHJ1ZSxTVkdJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5lRWxlbWVudDp0
-cnVlLFNWR0xpbmVhckdyYWRpZW50RWxlbWVudDp0cnVlLFNWR01hcmtlckVsZW1lbnQ6dHJ1ZSxTVkdN
-YXNrRWxlbWVudDp0cnVlLFNWR01ldGFkYXRhRWxlbWVudDp0cnVlLFNWR1BhdGhFbGVtZW50OnRydWUs
-U1ZHUGF0dGVybkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5Z29uRWxlbWVudDp0cnVlLFNWR1BvbHlsaW5lRWxl
-bWVudDp0cnVlLFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDp0cnVlLFNWR1JlY3RFbGVtZW50OnRydWUs
-U1ZHU2V0RWxlbWVudDp0cnVlLFNWR1N0b3BFbGVtZW50OnRydWUsU1ZHU3R5bGVFbGVtZW50OnRydWUs
-U1ZHU1ZHRWxlbWVudDp0cnVlLFNWR1N3aXRjaEVsZW1lbnQ6dHJ1ZSxTVkdTeW1ib2xFbGVtZW50OnRy
-dWUsU1ZHVFNwYW5FbGVtZW50OnRydWUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OnRydWUsU1ZHVGV4dEVs
-ZW1lbnQ6dHJ1ZSxTVkdUZXh0UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UG9zaXRpb25pbmdFbGVtZW50
-OnRydWUsU1ZHVGl0bGVFbGVtZW50OnRydWUsU1ZHVXNlRWxlbWVudDp0cnVlLFNWR1ZpZXdFbGVtZW50
-OnRydWUsU1ZHR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlvbkVs
-ZW1lbnQ6dHJ1ZSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OnRydWUsU1ZHTVBhdGhFbGVtZW50OnRydWUs
-U1ZHRWxlbWVudDpmYWxzZSxTVkdUcmFuc2Zvcm06dHJ1ZSxTVkdUcmFuc2Zvcm1MaXN0OnRydWUsQXVk
-aW9CdWZmZXI6dHJ1ZSxBdWRpb1BhcmFtOnRydWUsQXVkaW9QYXJhbU1hcDp0cnVlLEF1ZGlvVHJhY2tM
-aXN0OnRydWUsQXVkaW9Db250ZXh0OnRydWUsd2Via2l0QXVkaW9Db250ZXh0OnRydWUsQmFzZUF1ZGlv
-Q29udGV4dDpmYWxzZSxPZmZsaW5lQXVkaW9Db250ZXh0OnRydWUsU1FMUmVzdWx0U2V0Um93TGlzdDp0
-cnVlfSkKSC5iMC4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlJHLiRuYXRp
-dmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguVlAuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9
-IkFycmF5QnVmZmVyVmlldyIKSC5EZy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3
-IgpILldCLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguWkcuJG5hdGl2ZVN1
-cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5QZy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJy
-YXlCdWZmZXJWaWV3IgpXLm9ILiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJFdmVudFRhcmdldCIKVy5DRS4k
-bmF0aXZlU3VwZXJjbGFzc1RhZz0iRXZlbnRUYXJnZXQiClcuUVYuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9
-IkV2ZW50VGFyZ2V0IgpXLkF3LiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJFdmVudFRhcmdldCJ9KSgpCmNv
-bnZlcnRBbGxUb0Zhc3RPYmplY3QodykKY29udmVydFRvRmFzdE9iamVjdCgkKTsoZnVuY3Rpb24oYSl7
-aWYodHlwZW9mIGRvY3VtZW50PT09InVuZGVmaW5lZCIpe2EobnVsbCkKcmV0dXJufWlmKHR5cGVvZiBk
-b2N1bWVudC5jdXJyZW50U2NyaXB0IT0ndW5kZWZpbmVkJyl7YShkb2N1bWVudC5jdXJyZW50U2NyaXB0
-KQpyZXR1cm59dmFyIHQ9ZG9jdW1lbnQuc2NyaXB0cwpmdW5jdGlvbiBvbkxvYWQoYil7Zm9yKHZhciBy
-PTA7cjx0Lmxlbmd0aDsrK3IpdFtyXS5yZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIixvbkxvYWQsZmFs
-c2UpCmEoYi50YXJnZXQpfWZvcih2YXIgcz0wO3M8dC5sZW5ndGg7KytzKXRbc10uYWRkRXZlbnRMaXN0
-ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKX0pKGZ1bmN0aW9uKGEpe3YuY3VycmVudFNjcmlwdD1hCmlm
-KHR5cGVvZiBkYXJ0TWFpblJ1bm5lcj09PSJmdW5jdGlvbiIpZGFydE1haW5SdW5uZXIoTC5EZSxbXSkK
-ZWxzZSBMLkRlKFtdKX0pfSkoKQovLyMgc291cmNlTWFwcGluZ1VSTD1taWdyYXRpb24uanMubWFwCg==
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucShhLGIpfSwKJGliUToxLAokaWNYOjEsCiRpek06MX0K
+UC5tby5wcm90b3R5cGU9e30KUC5LZy5wcm90b3R5cGU9e30KVS5kMi5wcm90b3R5cGU9e30KVS5TZS5w
+cm90b3R5cGU9e30KVS5NbC5wcm90b3R5cGU9e30KVS55RC5wcm90b3R5cGU9ewpnUHU6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuYn19ClUud2IucHJvdG90eXBlPXt9CkIuajgucHJvdG90eXBlPXt9CkIucXAu
+cHJvdG90eXBlPXt9ClQubVEucHJvdG90eXBlPXt9CkwuZS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscSxwLG8sbgp1LkIuYihhKQp0PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZQpzPUwu
+RzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnI9TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikKTC5HZSgp
+CmlmKHQhPT0iLyImJnQhPT1KLlQwKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENv
+bnRlbnQpKUwuRzcodCxzLHIsITAsbmV3IEwuVlcodCxzLHIpKQpxPWRvY3VtZW50CnA9Si5xRihxLnF1
+ZXJ5U2VsZWN0b3IoIi5hcHBseS1taWdyYXRpb24iKSkKbz1wLiR0aQpuPW8uQygifigxKSIpLmIobmV3
+IEwub1ooKSkKdS5NLmIobnVsbCkKVy5KRShwLmEscC5iLG4sITEsby5kKQpxPUoucUYocS5xdWVyeVNl
+bGVjdG9yKCIucmVydW4tbWlncmF0aW9uIikpCm89cS4kdGkKVy5KRShxLmEscS5iLG8uQygifigxKSIp
+LmIobmV3IEwueTgoKSksITEsby5kKX0sCiRTOjIwfQpMLlZXLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
+KCl7TC5Gcih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzowfQpMLm9aLnByb3RvdHlwZT17CiQxOmZ1
+bmN0aW9uKGEpe3UuVi5iKGEpCmlmKEgub1Qod2luZG93LmNvbmZpcm0oIlRoaXMgd2lsbCBhcHBseSB0
+aGUgY2hhbmdlcyB5b3UndmUgcHJldmlld2VkIHRvIHlvdXIgd29ya2luZyBkaXJlY3RvcnkuIEl0IGlz
+IHJlY29tbWVuZGVkIHlvdSBjb21taXQgYW55IGNoYW5nZXMgeW91IG1hZGUgYmVmb3JlIGRvaW5nIHRo
+aXMuIikpKUwudHkoIi9hcHBseS1taWdyYXRpb24iKS5XNyhuZXcgTC5qcigpLHUuUCkuT0EobmV3IEwu
+cWwoKSl9LAokUzo2fQpMLmpyLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuci5iKGEp
+CnQ9ZG9jdW1lbnQuYm9keQp0LmNsYXNzTGlzdC5yZW1vdmUoInByb3Bvc2VkIikKdC5jbGFzc0xpc3Qu
+YWRkKCJhcHBsaWVkIil9LAokUzo3fQpMLnFsLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5x
+SigiYXBwbHkgbWlncmF0aW9uIGVycm9yOiAiK0guZChhKSxiKQp3aW5kb3cuYWxlcnQoIkNvdWxkIG5v
+dCBhcHBseSBtaWdyYXRpb24gKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6MX0KTC55
+OC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy54bih1LlYuYihhKSl9LAp4bjpm
+dW5jdGlvbihhKXt2YXIgdD0wLHM9UC5GWCh1LlApLHI9MSxxLHA9W10sbyxuLG0sbAp2YXIgJGFzeW5j
+JCQxPVAubHooZnVuY3Rpb24oYixjKXtpZihiPT09MSl7cT1jCnQ9cn13aGlsZSh0cnVlKXN3aXRjaCh0
+KXtjYXNlIDA6cj0zCmRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgicmVydW5uaW5nIikKdD02CnJl
+dHVybiBQLmpRKEwudHkoIi9yZXJ1bi1taWdyYXRpb24iKSwkYXN5bmMkJDEpCmNhc2UgNjp3aW5kb3cu
+bG9jYXRpb24ucmVsb2FkKCkKcC5wdXNoKDUpCnQ9NApicmVhawpjYXNlIDM6cj0yCmw9cQpvPUguUnUo
+bCkKbj1ILnRzKGwpCkwucUooInJlcnVuIG1pZ3JhdGlvbjogIitILmQobyksbikKd2luZG93LmFsZXJ0
+KCJGYWlsZWQgdG8gcmVydW4gbWlncmF0aW9uOiAiK0guZChvKSsiLiIpCnAucHVzaCg1KQp0PTQKYnJl
+YWsKY2FzZSAyOnA9WzFdCmNhc2UgNDpyPTEKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCJy
+ZXJ1bm5pbmciKQp0PXAucG9wKCkKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2FzZSAx
+OnJldHVybiBQLmYzKHEscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJCQxLHMpfSwKJFM6NDJ9CkwuTC5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKdS5CLmIoYSkKdD13aW5kb3cubG9jYXRp
+b24ucGF0aG5hbWUKcz1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpyPUwuYUsod2luZG93LmxvY2F0
+aW9uLmhyZWYpCmlmKHQubGVuZ3RoPjEpTC5HNyh0LHMsciwhMSxudWxsKQplbHNle0wuQkUodCxuZXcg
+Qi5xcCgiIiwiIiwiIixDLkNNKSwhMCkKTC5CWCgiJm5ic3A7IixudWxsKX19LAokUzoyMH0KTC5XeC5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT0iY29sbGFwc2VkIgp1LlYuYihhKQp0
+PXRoaXMuYQpzPUouUkUodCkKcj10aGlzLmIKaWYoIXMuZ0REKHQpLnRnKDAscSkpe3MuZ0REKHQpLkEo
+MCxxKQpKLmRSKHIpLkEoMCxxKX1lbHNle3MuZ0REKHQpLlJ6KDAscSkKSi5kUihyKS5SeigwLHEpfX0s
+CiRTOjZ9CkwuQU8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1LmguYihhKSks
+cz10LiR0aSxyPXMuQygifigxKSIpLmIobmV3IEwuZE4odGhpcy5hKSkKdS5NLmIobnVsbCkKVy5KRSh0
+LmEsdC5iLHIsITEscy5kKX0sCiRTOjN9CkwuZE4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFy
+IHQKdS5WLmIoYSkKdD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKdC50
+b1N0cmluZwpMLnQyKGEsdGhpcy5hLHQuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcu
+aTcodCkpLlMoInBhdGgiKSkpfSwKJFM6Nn0KTC5Iby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
+YXIgdCxzLHIKdS5oLmIoYSkKdD1KLnFGKGEpCnM9dC4kdGkKcj1zLkMoIn4oMSkiKS5iKG5ldyBMLnh6
+KGEsdGhpcy5hKSkKdS5NLmIobnVsbCkKVy5KRSh0LmEsdC5iLHIsITEscy5kKX0sCiRTOjN9CkwueHou
+cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscz1udWxsCnUuVi5iKGEpCnQ9dGhpcy5hCkwu
+aFgodGhpcy5iLFAuUUEodC5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyh0KSku
+Uygib2Zmc2V0IikpLHMscyksUC5RQSh0LmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBX
+Lmk3KHQpKS5TKCJsaW5lIikpLHMscykpfSwKJFM6Nn0KTC5JQy5wcm90b3R5cGU9ewokMTpmdW5jdGlv
+bihhKXt2YXIgdD1KLnFGKHUuaC5iKGEpKSxzPXQuJHRpCnMuQygifigxKSIpLmIoTC5IMCgpKQp1Lk0u
+YihudWxsKQpXLkpFKHQuYSx0LmIsTC5IMCgpLCExLHMuZCl9LAokUzozfQpMLkwxLnByb3RvdHlwZT17
+CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuci5iKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMClyZXR1cm4g
+YQplbHNlIHRocm93IEguYigiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo0
+NH0KTC5uVC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLmEsdGhpcy5iLHRoaXMu
+Yyl9LAokUzowfQpMLkJaLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7TC5Gcih0aGlzLmEuYSxudWxs
+LG51bGwpfSwKJFM6MH0KTC5HSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LmguYihhKQokLnpC
+KCkudG9TdHJpbmcKdS52LmIoJC5vdygpLnEoMCwiaGxqcyIpKS5WNygiaGlnaGxpZ2h0QmxvY2siLFth
+XSl9LAokUzozfQpMLkRULnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMKdS5yLmIoYSkK
+dD1hLnN0YXR1cwppZih0PT09MjAwKXt0PUMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxudWxsKQpzPUou
+VTYodCkKTC5UMShuZXcgVS5kMihVLmpmKHMucSh0LCJlZGl0cyIpKSxILnkocy5xKHQsImV4cGxhbmF0
+aW9uIikpLEguU2Mocy5xKHQsImxpbmUiKSksSC55KHMucSh0LCJwYXRoIikpLFUuTmQocy5xKHQsInRy
+YWNlcyIpKSkpCkwuRnIodGhpcy5hLHRoaXMuYix0aGlzLmMpCkwueVgoIi5lZGl0LXBhbmVsIC5wYW5l
+bC1jb250ZW50IiwhMSl9ZWxzZSB3aW5kb3cuYWxlcnQoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2Yg
+IitILmQodCkpfSwKJFM6N30KTC5lSC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wucUooImxv
+YWRSZWdpb25FeHBsYW5hdGlvbjogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9h
+ZCAiK0guZCh0aGlzLmEpKyIgKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6MX0KTC55
+dS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcwp1LnIuYihhKQp0PWEuc3Rh
+dHVzCmlmKHQ9PT0yMDApe3M9ci5hCkwuQkUocyxCLllmKHUuYi5iKEMuQ3QucFcoMCxhLnJlc3BvbnNl
+VGV4dCxudWxsKSkpLHIuYikKdD1yLmMKTC5mRyh0LHIuZCkKTC5CWChDLnhCLnRnKHMsIj8iKT9DLnhC
+Lk5qKHMsMCxDLnhCLk9ZKHMsIj8iKSk6cyx0KQp0PXIuZQppZih0IT1udWxsKXQuJDAoKX1lbHNlIHdp
+bmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLnpE
+LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZEZpbGU6ICIrSC5kKGEpLGIpCndp
+bmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIit0aGlzLmErIiAoIitILmQoYSkrIikuIil9LAokQzoi
+JDIiLAokUjoyLAokUzoxfQpMLlRXLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1
+LnIuYihhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDApe3M9Qy5DdC5wVygwLGEucmVzcG9uc2VUZXh0LG51
+bGwpCnI9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLm5hdi10cmVlIikKSi5sNShyLCIiKQpMLnRYKHIs
+TC5tSyhzKSl9ZWxzZSB3aW5kb3cuYWxlcnQoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitILmQo
+dCkpfSwKJFM6N30KTC54ci5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wucUooImxvYWROYXZp
+Z2F0aW9uVHJlZTogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK3RoaXMu
+YSsiICgiK0guZChhKSsiKS4iKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjF9CkwuRUUucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7dmFyIHQscwp1LlYuYihhKQp0PXRoaXMuYQpzPXRoaXMuYgpMLmFmKHdpbmRv
+dy5sb2NhdGlvbi5wYXRobmFtZSx0LHMsITAsbmV3IEwuUUwodCxzKSkKTC5oWCh0aGlzLmMsdCxzKX0s
+CiRTOjZ9CkwuUUwucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHdpbmRvdy5sb2NhdGlvbi5w
+YXRobmFtZSx0aGlzLmEsdGhpcy5iKX0sCiRTOjB9CkwuVlMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
+YSl7dmFyIHQscz0ic2VsZWN0ZWQtZmlsZSIKdS5oLmIoYSkKYS50b1N0cmluZwp0PUouUkUoYSkKaWYo
+YS5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhhKSkuUygibmFtZSIpKT09PXRo
+aXMuYS5hKXQuZ0REKGEpLkEoMCxzKQplbHNlIHQuZ0REKGEpLlJ6KDAscyl9LAokUzozfQpMLlRELnBy
+b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBMLnQyKHUuVi5iKGEpLCEwLG51bGwpfSwKJFM6
+MjF9CkwuWEEucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiEwfSwKaTA6ZnVuY3Rp
+b24oYSl7cmV0dXJuITB9LAokaWtGOjF9CkwuWloucHJvdG90eXBlPXt9CkwuQmMucHJvdG90eXBlPXsK
+dzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ifX0KTS5sSS5wcm90b3R5cGU9ewpXTzpmdW5jdGlvbihh
+LGIpe3ZhciB0LHM9bnVsbApNLllGKCJhYnNvbHV0ZSIsSC5WTShbYixudWxsLG51bGwsbnVsbCxudWxs
+LG51bGwsbnVsbF0sdS5zKSkKdD10aGlzLmEKdD10LllyKGIpPjAmJiF0LmhLKGIpCmlmKHQpcmV0dXJu
+IGIKdD1ELlJYKCkKcmV0dXJuIHRoaXMucTcoMCx0LGIscyxzLHMscyxzLHMpfSwKdE06ZnVuY3Rpb24o
+YSl7dmFyIHQscyxyPVguQ0woYSx0aGlzLmEpCnIuSVYoKQp0PXIuZApzPXQubGVuZ3RoCmlmKHM9PT0w
+KXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZihzPT09MSl7dD1yLmIKcmV0dXJuIHQ9PW51bGw/
+Ii4iOnR9aWYoMD49cylyZXR1cm4gSC5PSCh0LC0xKQp0LnBvcCgpCkMuTm0ubXYoci5lKQpyLklWKCkK
+cmV0dXJuIHIudygwKX0sCnE3OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpKXt2YXIgdD1ILlZNKFti
+LGMsZCxlLGYsZyxoLGldLHUucykKTS5ZRigiam9pbiIsdCkKcmV0dXJuIHRoaXMuSVAobmV3IEguVTUo
+dCx1LmJCLmIobmV3IE0uTWkoKSksdS5jYykpfSwKSVA6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxv
+LG4sbSxsCnUuWC5iKGEpCmZvcih0PWEuJHRpLHM9dC5DKCJhMihjWC5FKSIpLmIobmV3IE0ucTcoKSks
+cj1hLmdreihhKSx0PW5ldyBILlNPKHIscyx0LkMoIlNPPGNYLkU+IikpLHM9dGhpcy5hLHE9ITEscD0h
+MSxvPSIiO3QubSgpOyl7bj1yLmdSKHIpCmlmKHMuaEsobikmJnApe209WC5DTChuLHMpCmw9by5jaGFy
+Q29kZUF0KDApPT0wP286bwpvPUMueEIuTmoobCwwLHMuU3AobCwhMCkpCm0uYj1vCmlmKHMuZHMobykp
+Qy5ObS5ZKG0uZSwwLHMuZ21JKCkpCm89bS53KDApfWVsc2UgaWYocy5ZcihuKT4wKXtwPSFzLmhLKG4p
+Cm89SC5kKG4pfWVsc2V7aWYoIShuLmxlbmd0aD4wJiZzLlVkKG5bMF0pKSlpZihxKW8rPXMuZ21JKCkK
+bys9SC5kKG4pfXE9cy5kcyhuKX1yZXR1cm4gby5jaGFyQ29kZUF0KDApPT0wP286b30sCm81OmZ1bmN0
+aW9uKGEsYil7dmFyIHQKaWYoIXRoaXMueTMoYikpcmV0dXJuIGIKdD1YLkNMKGIsdGhpcy5hKQp0LnJS
+KDApCnJldHVybiB0LncoMCl9LAp5MzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsawph
+LnRvU3RyaW5nCnQ9dGhpcy5hCnM9dC5ZcihhKQppZihzIT09MCl7aWYodD09PSQuS2soKSlmb3Iocj0w
+O3I8czsrK3IpaWYoQy54Qi5XZChhLHIpPT09NDcpcmV0dXJuITAKcT1zCnA9NDd9ZWxzZXtxPTAKcD1u
+dWxsfWZvcihvPW5ldyBILnFqKGEpLmEsbj1vLmxlbmd0aCxyPXEsbT1udWxsO3I8bjsrK3IsbT1wLHA9
+bCl7bD1DLnhCLk8yKG8scikKaWYodC5yNChsKSl7aWYodD09PSQuS2soKSYmbD09PTQ3KXJldHVybiEw
+CmlmKHAhPW51bGwmJnQucjQocCkpcmV0dXJuITAKaWYocD09PTQ2KWs9bT09bnVsbHx8bT09PTQ2fHx0
+LnI0KG0pCmVsc2Ugaz0hMQppZihrKXJldHVybiEwfX1pZihwPT1udWxsKXJldHVybiEwCmlmKHQucjQo
+cCkpcmV0dXJuITAKaWYocD09PTQ2KXQ9bT09bnVsbHx8dC5yNChtKXx8bT09PTQ2CmVsc2UgdD0hMQpp
+Zih0KXJldHVybiEwCnJldHVybiExfSwKSFA6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89dGhp
+cyxuPSdVbmFibGUgdG8gZmluZCBhIHBhdGggdG8gIicKYj1vLldPKDAsYikKdD1vLmEKaWYodC5Zcihi
+KTw9MCYmdC5ZcihhKT4wKXJldHVybiBvLm81KDAsYSkKaWYodC5ZcihhKTw9MHx8dC5oSyhhKSlhPW8u
+V08oMCxhKQppZih0LllyKGEpPD0wJiZ0LllyKGIpPjApdGhyb3cgSC5iKFguSTcobitILmQoYSkrJyIg
+ZnJvbSAiJytILmQoYikrJyIuJykpCnM9WC5DTChiLHQpCnMuclIoMCkKcj1YLkNMKGEsdCkKci5yUigw
+KQpxPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4iKSlyZXR1cm4gci53KDApCnE9cy5iCnA9
+ci5iCmlmKHEhPXApcT1xPT1udWxsfHxwPT1udWxsfHwhdC5OYyhxLHApCmVsc2UgcT0hMQppZihxKXJl
+dHVybiByLncoMCkKd2hpbGUoITApe3E9cy5kCmlmKHEubGVuZ3RoPjApe3A9ci5kCnE9cC5sZW5ndGg+
+MCYmdC5OYyhxWzBdLHBbMF0pfWVsc2UgcT0hMQppZighcSlicmVhawpDLk5tLlc0KHMuZCwwKQpDLk5t
+Llc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0KHIuZSwxKX1xPXMuZAppZihxLmxlbmd0aD4w
+JiZKLlJNKHFbMF0sIi4uIikpdGhyb3cgSC5iKFguSTcobitILmQoYSkrJyIgZnJvbSAiJytILmQoYikr
+JyIuJykpCnE9dS5OCkMuTm0ub0Yoci5kLDAsUC5POChzLmQubGVuZ3RoLCIuLiIscSkpCkMuTm0uWShy
+LmUsMCwiIikKQy5ObS5vRihyLmUsMSxQLk84KHMuZC5sZW5ndGgsdC5nbUkoKSxxKSkKdD1yLmQKcT10
+Lmxlbmd0aAppZihxPT09MClyZXR1cm4iLiIKaWYocT4xJiZKLlJNKEMuTm0uZ3JaKHQpLCIuIikpe3Q9
+ci5kCmlmKDA+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsLTEpCnQucG9wKCkKdD1yLmUKQy5ObS5tdih0
+KQpDLk5tLm12KHQpCkMuTm0uQSh0LCIiKX1yLmI9IiIKci5JVigpCnJldHVybiByLncoMCl9fQpNLk1p
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBILnkoYSkhPW51bGx9LAokUzo5fQpNLnE3
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBILnkoYSkhPT0iIn0sCiRTOjl9Ck0uTm8u
+cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC55KGEpCnJldHVybiBhPT1udWxsPyJudWxsIjonIicr
+YSsnIid9LAokUzo1fQpCLkx1LnByb3RvdHlwZT17CnhaOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5Z
+cihhKQppZihzPjApcmV0dXJuIEoubGQoYSwwLHMpCmlmKHRoaXMuaEsoYSkpe2lmKDA+PWEubGVuZ3Ro
+KXJldHVybiBILk9IKGEsMCkKdD1hWzBdfWVsc2UgdD1udWxsCnJldHVybiB0fSwKTmM6ZnVuY3Rpb24o
+YSxiKXtyZXR1cm4gYT09Yn19ClguV0QucHJvdG90eXBlPXsKSVY6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9
+dGhpcwp3aGlsZSghMCl7dD1yLmQKaWYoISh0Lmxlbmd0aCE9PTAmJkouUk0oQy5ObS5ncloodCksIiIp
+KSlicmVhawp0PXIuZAppZigwPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LC0xKQp0LnBvcCgpCkMuTm0u
+bXYoci5lKX10PXIuZQpzPXQubGVuZ3RoCmlmKHM+MClDLk5tLlkodCxzLTEsIiIpfSwKclI6ZnVuY3Rp
+b24oYSl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzLGw9SC5WTShbXSx1LnMpCmZvcih0PW0uZCxzPXQu
+bGVuZ3RoLHI9MCxxPTA7cTx0Lmxlbmd0aDt0Lmxlbmd0aD09PXN8fCgwLEgubGspKHQpLCsrcSl7cD10
+W3FdCm89Si5pYShwKQppZighKG8uRE4ocCwiLiIpfHxvLkROKHAsIiIpKSlpZihvLkROKHAsIi4uIikp
+aWYobC5sZW5ndGg+MClsLnBvcCgpCmVsc2UgKytyCmVsc2UgQy5ObS5BKGwscCl9aWYobS5iPT1udWxs
+KUMuTm0ub0YobCwwLFAuTzgociwiLi4iLHUuTikpCmlmKGwubGVuZ3RoPT09MCYmbS5iPT1udWxsKUMu
+Tm0uQShsLCIuIikKbj1QLmRIKGwubGVuZ3RoLG5ldyBYLnFSKG0pLCEwLHUuTikKdD1tLmIKdD10IT1u
+dWxsJiZsLmxlbmd0aD4wJiZtLmEuZHModCk/bS5hLmdtSSgpOiIiCkgudDYobikuZC5iKHQpCmlmKCEh
+bi5maXhlZCRsZW5ndGgpSC5WaihQLkw0KCJpbnNlcnQiKSkKbi5zcGxpY2UoMCwwLHQpCm0uc25KKGwp
+Cm0uc1BoKG4pCnQ9bS5iCmlmKHQhPW51bGwmJm0uYT09PSQuS2soKSl7dC50b1N0cmluZwptLmI9SC55
+cyh0LCIvIiwiXFwiKX1tLklWKCl9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9ci5iCnE9
+cSE9bnVsbD9xOiIiCmZvcih0PTA7dDxyLmQubGVuZ3RoOysrdCl7cz1yLmUKaWYodD49cy5sZW5ndGgp
+cmV0dXJuIEguT0gocyx0KQpzPXErSC5kKHNbdF0pCnE9ci5kCmlmKHQ+PXEubGVuZ3RoKXJldHVybiBI
+Lk9IKHEsdCkKcT1zK0guZChxW3RdKX1xKz1ILmQoQy5ObS5nclooci5lKSkKcmV0dXJuIHEuY2hhckNv
+ZGVBdCgwKT09MD9xOnF9LApzbko6ZnVuY3Rpb24oYSl7dGhpcy5kPXUuYS5iKGEpfSwKc1BoOmZ1bmN0
+aW9uKGEpe3RoaXMuZT11LmEuYihhKX19ClgucVIucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuYS5hLmdtSSgpfSwKJFM6NDZ9ClguZHYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXty
+ZXR1cm4iUGF0aEV4Y2VwdGlvbjogIit0aGlzLmF9fQpPLk9PLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuZ29jKHRoaXMpfX0KRS5PRi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXty
+ZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fSwKZHM6ZnVu
+Y3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKcmV0dXJuIHQhPT0wJiZDLnhCLk8yKGEsdC0xKSE9PTQ3fSwK
+U3A6ZnVuY3Rpb24oYSxiKXtpZihhLmxlbmd0aCE9PTAmJkMueEIuV2QoYSwwKT09PTQ3KXJldHVybiAx
+CnJldHVybiAwfSwKWXI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlv
+bihhKXtyZXR1cm4hMX0sCmdvYzpmdW5jdGlvbigpe3JldHVybiJwb3NpeCJ9LApnbUk6ZnVuY3Rpb24o
+KXtyZXR1cm4iLyJ9fQpGLnJ1LnByb3RvdHlwZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRn
+KGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVybiBhPT09NDd9LApkczpmdW5jdGlvbihhKXt2YXIg
+dD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQppZihDLnhCLk8yKGEsdC0xKSE9PTQ3KXJldHVybiEw
+CnJldHVybiBDLnhCLlRjKGEsIjovLyIpJiZ0aGlzLllyKGEpPT09dH0sClNwOmZ1bmN0aW9uKGEsYil7
+dmFyIHQscyxyLHEscD1hLmxlbmd0aAppZihwPT09MClyZXR1cm4gMAppZihDLnhCLldkKGEsMCk9PT00
+NylyZXR1cm4gMQpmb3IodD0wO3Q8cDsrK3Qpe3M9Qy54Qi5XZChhLHQpCmlmKHM9PT00NylyZXR1cm4g
+MAppZihzPT09NTgpe2lmKHQ9PT0wKXJldHVybiAwCnI9Qy54Qi5YVShhLCIvIixDLnhCLlFpKGEsIi8v
+Iix0KzEpP3QrMzp0KQppZihyPD0wKXJldHVybiBwCmlmKCFifHxwPHIrMylyZXR1cm4gcgppZighQy54
+Qi5uQyhhLCJmaWxlOi8vIikpcmV0dXJuIHIKaWYoIUIuWXUoYSxyKzEpKXJldHVybiByCnE9ciszCnJl
+dHVybiBwPT09cT9xOnIrNH19cmV0dXJuIDB9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChh
+LCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aCE9PTAmJkMueEIuV2QoYSwwKT09PTQ3
+fSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuInVybCJ9LApnbUk6ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9fQpM
+LklWLnByb3RvdHlwZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1
+bmN0aW9uKGEpe3JldHVybiBhPT09NDd8fGE9PT05Mn0sCmRzOmZ1bmN0aW9uKGEpe3ZhciB0PWEubGVu
+Z3RoCmlmKHQ9PT0wKXJldHVybiExCnQ9Qy54Qi5PMihhLHQtMSkKcmV0dXJuISh0PT09NDd8fHQ9PT05
+Mil9LApTcDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1hLmxlbmd0aAppZihyPT09MClyZXR1cm4gMAp0
+PUMueEIuV2QoYSwwKQppZih0PT09NDcpcmV0dXJuIDEKaWYodD09PTkyKXtpZihyPDJ8fEMueEIuV2Qo
+YSwxKSE9PTkyKXJldHVybiAxCnM9Qy54Qi5YVShhLCJcXCIsMikKaWYocz4wKXtzPUMueEIuWFUoYSwi
+XFwiLHMrMSkKaWYocz4wKXJldHVybiBzfXJldHVybiByfWlmKHI8MylyZXR1cm4gMAppZighQi5PUyh0
+KSlyZXR1cm4gMAppZihDLnhCLldkKGEsMSkhPT01OClyZXR1cm4gMApyPUMueEIuV2QoYSwyKQppZigh
+KHI9PT00N3x8cj09PTkyKSlyZXR1cm4gMApyZXR1cm4gM30sCllyOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuWXIoYSk9PT0xfSwKT3Q6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdAppZihhPT09YilyZXR1cm4hMAppZihhPT09NDcpcmV0dXJuIGI9PT05Mgpp
+ZihhPT09OTIpcmV0dXJuIGI9PT00NwppZigoYV5iKSE9PTMyKXJldHVybiExCnQ9YXwzMgpyZXR1cm4g
+dD49OTcmJnQ8PTEyMn0sCk5jOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmlmKGE9PWIpcmV0dXJuITAK
+dD1hLmxlbmd0aAppZih0IT09Yi5sZW5ndGgpcmV0dXJuITEKZm9yKHM9Si5yWShiKSxyPTA7cjx0Oysr
+cilpZighdGhpcy5PdChDLnhCLldkKGEscikscy5XZChiLHIpKSlyZXR1cm4hMQpyZXR1cm4hMH0sCmdv
+YzpmdW5jdGlvbigpe3JldHVybiJ3aW5kb3dzIn0sCmdtSTpmdW5jdGlvbigpe3JldHVybiJcXCJ9fTso
+ZnVuY3Rpb24gYWxpYXNlcygpe3ZhciB0PUoudkIucHJvdG90eXBlCnQuVUc9dC53CnQuU2o9dC5lNwp0
+PUouTUYucHJvdG90eXBlCnQudD10LncKdD1QLmNYLnByb3RvdHlwZQp0LkdHPXQuZXYKdD1QLmsucHJv
+dG90eXBlCnQueGI9dC53CnQ9Vy5jdi5wcm90b3R5cGUKdC5EVz10LnI2CnQ9Vy5tNi5wcm90b3R5cGUK
+dC5qRj10LkViCnQ9UC5FNC5wcm90b3R5cGUKdC5Vcj10LnEKdC5lND10Lll9KSgpOyhmdW5jdGlvbiBp
+bnN0YWxsVGVhck9mZnMoKXt2YXIgdD1odW5rSGVscGVycy5fc3RhdGljXzEscz1odW5rSGVscGVycy5f
+c3RhdGljXzAscj1odW5rSGVscGVycy5pbnN0YWxsSW5zdGFuY2VUZWFyT2ZmLHE9aHVua0hlbHBlcnMu
+aW5zdGFsbFN0YXRpY1RlYXJPZmYscD1odW5rSGVscGVycy5faW5zdGFuY2VfMXUKdChQLCJFWCIsIlpW
+IiwxMSkKdChQLCJ5dCIsInFHIiwxMSkKdChQLCJxVyIsIkJ6IiwxMSkKcyhQLCJVSSIsImVOIiwyKQpy
+KFAuUGYucHJvdG90eXBlLCJnWUoiLDAsMSxudWxsLFsiJDIiLCIkMSJdLFsidzAiLCJwbSJdLDIzLDAp
+CnQoUCwiUEgiLCJNdCIsNSkKcShXLCJwUyIsNCxudWxsLFsiJDQiXSxbIlV3Il0sMTksMCkKcShXLCJW
+NCIsNCxudWxsLFsiJDQiXSxbIm5aIl0sMTksMCkKcChQLmRNLnByb3RvdHlwZSwiZ3VNIiwiVkwiLDUp
+CnQoUCwiaUciLCJ3WSIsNCkKdChQLCJ3MCIsIkw3IiwzMikKdChMLCJIMCIsInVtIiwyMSl9KSgpOyhm
+dW5jdGlvbiBpbmhlcml0YW5jZSgpe3ZhciB0PWh1bmtIZWxwZXJzLm1peGluLHM9aHVua0hlbHBlcnMu
+aW5oZXJpdCxyPWh1bmtIZWxwZXJzLmluaGVyaXRNYW55CnMoUC5rLG51bGwpCnIoUC5rLFtILmVvLEou
+dkIsSi5tMSxQLm5ZLFAuY1gsSC5hNyxQLkFuLEguU1UsSC5SZSxILnd2LFAuUG4sSC5XVSxILkxJLEgu
+VHAsSC5mOSxQLlhTLEguYnEsSC5YTyxQLllrLEgudmgsSC5ONixILlZSLEguRUssSC5QYixILnRRLEgu
+U2QsSC5KYyxILkcsUC5XMyxQLmloLFAuRnksUC5HVixQLmI4LFAuUGYsUC5GZSxQLnZzLFAuT00sUC5x
+aCxQLk1PLFAua1QsUC54SSxQLkN3LFAubTAsUC5YdixQLmJuLFAubG0sUC5sRCxQLktQLFAubGYsUC5X
+WSxQLlVrLFAuUncsUC5ieixQLmEyLFAuaVAsUC5GSyxQLms1LFAuS1ksUC5DRCxQLmFFLFAuRUgsUC56
+TSxQLlowLFAuTjMsUC5jOCxQLk9kLFAuaWIsUC5HeixQLnFVLFAuUm4sUC5HRCxQLkRuLFAuUEUsUC5V
+ZixXLmlkLFcuRmssVy5KUSxXLkdtLFcudkQsVy5tNixXLk93LFcuVzksVy5kVyxXLkZiLFcua0YsVy5t
+ayxXLktvLFAuaTYsUC5hSixQLkU0LFAuSU4sUC5uNixVLmQyLFUuU2UsVS5NbCxVLnlELFUud2IsQi5q
+OCxCLnFwLFQubVEsTC5YQSxMLlpaLEwuQmMsTS5sSSxPLk9PLFguV0QsWC5kdl0pCnIoSi52QixbSi55
+RSxKLllFLEouTUYsSi5qZCxKLnFJLEouRHIsSC5XWixILkVULFcuRDAsVy5ZZSxXLkF6LFcuUFUsVy5C
+dyxXLm80LFcubHcsVy5MZSxXLlNiLFcuTmgsVy5KVSxXLklCLFcudmUsVy5uNyxXLlFJLFcuZWEsVy50
+SSxXLkdPLFcuSkMsVy5icixXLlo3LFcuU2csVy51OCxXLno2LFcubEcsVy5xcyxXLkFXLFcuY3MsVy5L
+NyxXLmNsLFcuZlQsVy5iZyxXLlk0LFcuYUQsVy5sOCxXLk9YLFcuV1csVy5VaixXLm16LFcuYTMsVy50
+cixXLmNuLFcuRmosVy5PdixXLllELFcuWFcsVy5YVSxXLnp2LFAuVzIsUC5oRixQLkJWLFAudWosUC54
+MCxQLmZVLFAudVAsUC5qRyxQLkVELFAueFcsUC56WSxQLndqLFAucjIsUC5yTyxQLlUzLFAubW9dKQpy
+KEouTUYsW0ouaUMsSi5rZCxKLmM1XSkKcyhKLlBvLEouamQpCnIoSi5xSSxbSi51cixKLlZBXSkKcyhQ
+LkxVLFAublkpCnIoUC5MVSxbSC5YQyxXLnd6LFcuZTddKQpzKEgucWosSC5YQykKcihQLmNYLFtILmJR
+LEguaTEsSC5VNSxILlhSLFAubVcsSC51bl0pCnIoSC5iUSxbSC5hTCxILmk1LFAueHVdKQpyKEguYUws
+W0gubkgsSC5BOCxQLmk4XSkKcyhILnh5LEguaTEpCnIoUC5BbixbSC5NSCxILlNPXSkKcyhQLlJVLFAu
+UG4pCnMoUC5HaixQLlJVKQpzKEguUEQsUC5HaikKcyhILkxQLEguV1UpCnIoSC5UcCxbSC5DaixILkFt
+LEgubGMsSC5kQyxILndOLEguVlgsUC50aCxQLmhhLFAuVnMsUC5GdCxQLnlILFAuV00sUC5TWCxQLkdz
+LFAuZGEsUC5vUSxQLnBWLFAuVTcsUC52cixQLnJILFAuS0YsUC5aTCxQLlJULFAualosUC5ycSxQLlJX
+LFAuQjUsUC5QSSxQLnBLLFAuaGosUC5WcCxQLk9SLFAucmEsUC55USxQLldGLFAubjEsUC5jUyxQLlZD
+LFAuSlQsUC5lMSxQLk5ZLFAuUlosUC5NRSxQLnk1LFAucTMsUC55SSxQLmM2LFAucWQsVy5DdixXLmJV
+LFcuaEgsVy5GQSxXLnVxLFcuaWksVy53USxXLktTLFcuQTMsVy52TixXLlV2LFcuRWcsVy5FbyxXLldr
+LFcuSUEsVy5mbSxQLmxSLFAuamcsUC5LNSxQLkdFLFAuTjcsUC51USxQLlBDLFAubXQsUC5OeixQLm5w
+LFAuVXQsUC52SyxQLnBVLFAucWYsTC5lLEwuVlcsTC5vWixMLmpyLEwucWwsTC55OCxMLkwsTC5XeCxM
+LkFPLEwuZE4sTC5IbyxMLnh6LEwuSUMsTC5MMSxMLm5ULEwuQlosTC5HSCxMLkRULEwuZUgsTC55dSxM
+LnpELEwuVFcsTC54cixMLkVFLEwuUUwsTC5WUyxMLlRELE0uTWksTS5xNyxNLk5vLFgucVJdKQpyKFAu
+WFMsW0guVzAsSC5heixILnZWLEguRXEsUC5DNixILnU5LFAubixQLnUsUC5tcCxQLnViLFAuZHMsUC5s
+aixQLlVWLFAuY10pCnIoSC5sYyxbSC56eCxILnJUXSkKcyhILmtZLFAuQzYpCnMoUC5pbCxQLllrKQpy
+KFAuaWwsW0guTjUsUC51dyxXLmFULFcuU3ldKQpyKFAubVcsW0guS1csUC5xNF0pCnIoSC5FVCxbSC5k
+ZixILmIwXSkKcihILmIwLFtILlJHLEguV0JdKQpzKEguVlAsSC5SRykKcyhILkRnLEguVlApCnMoSC5a
+RyxILldCKQpzKEguUGcsSC5aRykKcihILlBnLFtILnhqLEguZEUsSC5aQSxILndmLEguUHEsSC5lRSxI
+LlY2XSkKcihILnU5LFtILmh6LEguaU1dKQpzKFAuWmYsUC5QZikKcyhQLkppLFAubTApCnMoUC5iNixQ
+Llh2KQpzKFAuUkssUC5XWSkKcihQLlVrLFtQLkNWLFAuWmksUC5ieV0pCnMoUC53SSxQLmtUKQpyKFAu
+d0ksW1AudkEsUC5NeCxQLkUzLFAuR1ldKQpzKFAudTUsUC5aaSkKcihQLkZLLFtQLkNQLFAuS05dKQpy
+KFAudSxbUC5iSixQLmVZXSkKcyhQLnFlLFAuRG4pCnIoVy5EMCxbVy51SCxXLndKLFcud2EsVy5sSyxX
+LkxyLFcuU1YsVy5vSCxXLkExLFcuTU4sVy5RVixXLnZGLFcuT2ksVy5DbSxQLmZvLFAuVjhdKQpyKFcu
+dUgsW1cuY3YsVy5ueCxXLlFGLFcuQ1FdKQpyKFcuY3YsW1cucUUsUC5kNV0pCnIoVy5xRSxbVy5HaCxX
+LmZZLFcubkIsVy5RUCxXLklGLFcuY3gsVy5oNCxXLkpLLFcud1AsVy5RYixXLlFsLFcuR1gsVy5TTixX
+LkhELFcuS1IsVy5scCxXLlRiLFcuSXYsVy5CVCxXLmZYLFcuRkJdKQpyKFcuQncsW1cuUmQsVy5rUixX
+LkhTLFcuRmhdKQpzKFcuVGYsVy5vNCkKcyhXLm9KLFcuTGUpCnMoVy5WbyxXLmtSKQpzKFcueFgsVy5K
+VSkKcyhXLkZ2LFcueFgpCnMoVy5iRyxXLnZlKQpzKFcuWWwsVy5iRykKcyhXLlQ1LFcuQXopCnMoVy5m
+ZyxXLnRJKQpzKFcuWFYsVy5mZykKcyhXLkhXLFcuWjcpCnMoVy54bixXLkhXKQpzKFcuVmIsVy5RRikK
+cyhXLk83LFcud2EpCnIoVy5lYSxbVy53NixXLmV3LFcuYmtdKQpyKFcudzYsW1cuSEwsVy5Bal0pCnMo
+Vy5TMCxXLmxHKQpzKFcuejIsVy5xcykKcyhXLktCLFcuY3MpCnMoVy5ETSxXLktCKQpzKFcuckIsVy5L
+NykKcyhXLkJILFcuckIpCnMoVy5mNyxXLmZUKQpzKFcuRXYsVy5mNykKcyhXLnA4LFcuYmcpCnMoVy5D
+RSxXLm9IKQpzKFcuTWssVy5DRSkKcyhXLlp4LFcuYUQpCnMoVy5ObixXLlp4KQpzKFcuQXMsVy5PWCkK
+cyhXLmpNLFcuVWopCnMoVy5YMCxXLmpNKQpzKFcuQXcsVy5RVikKcyhXLm5KLFcuQXcpCnMoVy5PMyxX
+LnRyKQpzKFcuY2ksVy5PMykKcyhXLmNPLFcuT3YpCnMoVy5QUixXLmNPKQpzKFcudzQsVy5JQikKcyhX
+LkR4LFcuWUQpCnMoVy5GMixXLkR4KQpzKFcub2EsVy5YVykKcyhXLnJoLFcub2EpCnMoVy5SeSxXLlhV
+KQpzKFcuTE8sVy5SeSkKcyhXLm56LFcuenYpCnMoVy5iMSxXLm56KQpzKFcuaTcsVy5hVCkKcyhQLmRN
+LFAuUkspCnIoUC5kTSxbVy5JNCxQLktlXSkKcyhXLlJPLFAucWgpCnMoVy5ldSxXLlJPKQpzKFcueEMs
+UC5NTykKcyhXLmN0LFcubTYpCnMoUC5CZixQLmk2KQpzKFAuemcsUC5hSikKcyhQLmUzLFAuVzIpCnIo
+UC5FNCxbUC5yNyxQLmNvXSkKcyhQLlR6LFAuY28pCnMoUC50bixQLklOKQpzKFAuR0MsUC5mVSkKcyhQ
+LnE2LFAuR0MpCnMoUC5qUyxQLmpHKQpzKFAuZnosUC5qUykKcyhQLm5kLFAuZDUpCnMoUC5kUyxQLnhX
+KQpzKFAuS3EsUC5kUykKcyhQLk1ZLFAud2opCnMoUC5OQyxQLk1ZKQpzKFAuejgsUC5VMykKcyhQLkdu
+LFAuVjgpCnMoUC5LZyxQLm1vKQpzKFAuRm4sUC5LZykKcyhCLkx1LE8uT08pCnIoQi5MdSxbRS5PRixG
+LnJ1LEwuSVZdKQp0KEguWEMsSC5SZSkKdChILlJHLFAubEQpCnQoSC5WUCxILlNVKQp0KEguV0IsUC5s
+RCkKdChILlpHLEguU1UpCnQoUC5uWSxQLmxEKQp0KFAuV1ksUC5sZikKdChQLlJVLFAuS1ApCnQoVy5M
+ZSxXLmlkKQp0KFcuSlUsUC5sRCkKdChXLnhYLFcuR20pCnQoVy52ZSxQLmxEKQp0KFcuYkcsVy5HbSkK
+dChXLnRJLFAubEQpCnQoVy5mZyxXLkdtKQp0KFcuWjcsUC5sRCkKdChXLkhXLFcuR20pCnQoVy5sRyxQ
+LllrKQp0KFcucXMsUC5ZaykKdChXLmNzLFAubEQpCnQoVy5LQixXLkdtKQp0KFcuSzcsUC5sRCkKdChX
+LnJCLFcuR20pCnQoVy5mVCxQLmxEKQp0KFcuZjcsVy5HbSkKdChXLmJnLFAuWWspCnQoVy5vSCxQLmxE
+KQp0KFcuQ0UsVy5HbSkKdChXLmFELFAubEQpCnQoVy5aeCxXLkdtKQp0KFcuT1gsUC5ZaykKdChXLlVq
+LFAubEQpCnQoVy5qTSxXLkdtKQp0KFcuUVYsUC5sRCkKdChXLkF3LFcuR20pCnQoVy50cixQLmxEKQp0
+KFcuTzMsVy5HbSkKdChXLk92LFAubEQpCnQoVy5jTyxXLkdtKQp0KFcuWUQsUC5sRCkKdChXLkR4LFcu
+R20pCnQoVy5YVyxQLmxEKQp0KFcub2EsVy5HbSkKdChXLlhVLFAubEQpCnQoVy5SeSxXLkdtKQp0KFcu
+enYsUC5sRCkKdChXLm56LFcuR20pCnQoUC5jbyxQLmxEKQp0KFAuZlUsUC5sRCkKdChQLkdDLFcuR20p
+CnQoUC5qRyxQLmxEKQp0KFAualMsVy5HbSkKdChQLnhXLFAubEQpCnQoUC5kUyxXLkdtKQp0KFAud2os
+UC5sRCkKdChQLk1ZLFcuR20pCnQoUC5VMyxQLllrKQp0KFAubW8sUC5sRCkKdChQLktnLFcuR20pfSko
+KQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30sZVQ6e30sdFBWOnt9LHNFQTpb
+XX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntLTjoiaW50IixDUDoiZG91YmxlIixGSzoibnVtIixxVToiU3Ry
+aW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xlZE5hbWVzOnt9LGdldFR5cGVG
+cm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBlczpbImM4KCkiLCJjOChALEAp
+IiwifigpIiwiYzgoY3YpIiwiQChAKSIsInFVKHFVKSIsImM4KEFqKSIsImM4KE83KSIsIn4ocVUsQCki
+LCJhMihxVSkiLCJ+KEApIiwifih+KCkpIiwiYzgocVUscVUpIiwiYzgocVUsQCkiLCJ+KHh1PHFVPiki
+LCJjOChxVSkiLCJ+KHFVLHFVKSIsImEyKGtGKSIsImM4KEApIiwiYTIoY3YscVUscVUsSlEpIiwiYzgo
+ZWEpIiwifihBaikiLCJuNihLTikiLCJ+KGtbR3pdKSIsIlowPHFVLHFVPihaMDxxVSxxVT4scVUpIiwi
+YTIodUgpIiwiYzgoQFtHel0pIiwiYzgoZXcpIiwiQChxVSkiLCJAKGVhKSIsInZzPEA+KEApIiwifihx
+VVtAXSkiLCJrKEApIiwiQChALEApIiwiYTIoeHU8cVU+KSIsIktOKEtOLEtOKSIsInI3KEApIiwiVHo8
+QD4oQCkiLCJFNChAKSIsImM4KH4oKSkiLCJjOChALEd6KSIsIn4odUgsdUgpIiwiYjg8Yzg+KEFqKSIs
+ImM4KEtOLEApIiwiTzcoTzcpIiwiQChALHFVKSIsInFVKEtOKSIsImM4KEdELEApIiwifihxVSxLTiki
+LCJuNihALEApIl0saW50ZXJjZXB0b3JzQnlUYWc6bnVsbCxsZWFmVGFnczpudWxsfQpILnhiKHYudHlw
+ZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3siYzUiOiJNRiIsImlDIjoiTUYiLCJrZCI6Ik1GIiwicngiOiJl
+YSIsImU1IjoiZWEiLCJEWCI6IlY4IiwiYzAiOiJEMCIsImZ5IjoiRDAiLCJjZyI6IkQwIiwiWTAiOiJk
+NSIsInRwIjoiZDUiLCJ2MCI6ImV3IiwiTXIiOiJxRSIsImVMIjoicUUiLCJJMCI6InVIIiwiaHMiOiJ1
+SCIsIlhnIjoiUUYiLCJ5YyI6IkFqIiwiajYiOiJNTiIsInk0IjoidzYiLCJhUCI6IkNtIiwieGMiOiJu
+eCIsImtKIjoibngiLCJqNyI6IndhIiwiUUgiOiJ4biIsIncxIjoiUUkiLCJINiI6Imx3IiwiSEUiOiJX
+VyIsInpVIjoiRGciLCJ5RSI6eyJhMiI6W119LCJZRSI6eyJjOCI6W119LCJNRiI6eyJ2bSI6W10sIkVI
+IjpbXX0sImpkIjp7InpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJQbyI6eyJqZCI6WyIx
+Il0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJtMSI6eyJBbiI6WyIxIl19LCJxSSI6
+eyJDUCI6W10sIkZLIjpbXX0sInVyIjp7IktOIjpbXSwiQ1AiOltdLCJGSyI6W119LCJWQSI6eyJDUCI6
+W10sIkZLIjpbXX0sIkRyIjp7InFVIjpbXSwidlgiOltdfSwicWoiOnsiUmUiOlsiS04iXSwibEQiOlsi
+S04iXSwiek0iOlsiS04iXSwiYlEiOlsiS04iXSwiY1giOlsiS04iXSwibEQuRSI6IktOIiwiUmUuRSI6
+IktOIn0sImJRIjp7ImNYIjpbIjEiXX0sImFMIjp7ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwibkgiOnsi
+YUwiOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXSwiYUwuRSI6IjEiLCJjWC5FIjoiMSJ9LCJhNyI6
+eyJBbiI6WyIxIl19LCJpMSI6eyJjWCI6WyIyIl0sImNYLkUiOiIyIn0sInh5Ijp7ImkxIjpbIjEiLCIy
+Il0sImJRIjpbIjIiXSwiY1giOlsiMiJdLCJjWC5FIjoiMiJ9LCJNSCI6eyJBbiI6WyIyIl19LCJBOCI6
+eyJhTCI6WyIyIl0sImJRIjpbIjIiXSwiY1giOlsiMiJdLCJhTC5FIjoiMiIsImNYLkUiOiIyIn0sIlU1
+Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiU08iOnsiQW4iOlsiMSJdfSwiWEMiOnsiUmUiOlsiMSJd
+LCJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJ3diI6eyJHRCI6W119
+LCJQRCI6eyJHaiI6WyIxIiwiMiJdLCJSVSI6WyIxIiwiMiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIx
+IiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiV1UiOnsiWjAiOlsiMSIsIjIiXX0sIkxQIjp7IldVIjpbIjEi
+LCIyIl0sIlowIjpbIjEiLCIyIl19LCJYUiI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIkxJIjp7InZR
+IjpbXX0sIlcwIjp7IlhTIjpbXX0sImF6Ijp7IlhTIjpbXX0sInZWIjp7IlhTIjpbXX0sIlhPIjp7Ikd6
+IjpbXX0sIlRwIjp7IkVIIjpbXX0sImxjIjp7IkVIIjpbXX0sInp4Ijp7IkVIIjpbXX0sInJUIjp7IkVI
+IjpbXX0sIkVxIjp7IlhTIjpbXX0sImtZIjp7IlhTIjpbXX0sIk41Ijp7IkZvIjpbIjEiLCIyIl0sIllr
+IjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl0sIllrLksiOiIxIiwiWWsuViI6IjIifSwiaTUiOnsiYlEi
+OlsiMSJdLCJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIk42Ijp7IkFuIjpbIjEiXX0sIlZSIjp7IndMIjpb
+XSwidlgiOltdfSwiRUsiOnsiaWIiOltdLCJPZCI6W119LCJLVyI6eyJjWCI6WyJpYiJdLCJjWC5FIjoi
+aWIifSwiUGIiOnsiQW4iOlsiaWIiXX0sInRRIjp7Ik9kIjpbXX0sInVuIjp7ImNYIjpbIk9kIl0sImNY
+LkUiOiJPZCJ9LCJTZCI6eyJBbiI6WyJPZCJdfSwiRVQiOnsiQVMiOltdfSwiZGYiOnsiRVQiOltdLCJX
+eSI6W10sIkFTIjpbXX0sImIwIjp7IlhqIjpbIkAiXSwiRVQiOltdLCJBUyI6W119LCJEZyI6eyJsRCI6
+WyJDUCJdLCJYaiI6WyJAIl0sInpNIjpbIkNQIl0sIkVUIjpbXSwiYlEiOlsiQ1AiXSwiU1UiOlsiQ1Ai
+XSwiQVMiOltdLCJjWCI6WyJDUCJdLCJsRC5FIjoiQ1AifSwiUGciOnsibEQiOlsiS04iXSwiek0iOlsi
+S04iXSwiWGoiOlsiQCJdLCJFVCI6W10sImJRIjpbIktOIl0sIlNVIjpbIktOIl0sIkFTIjpbXSwiY1gi
+OlsiS04iXX0sInhqIjp7ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJi
+USI6WyJLTiJdLCJTVSI6WyJLTiJdLCJBUyI6W10sImNYIjpbIktOIl0sImxELkUiOiJLTiJ9LCJkRSI6
+eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpbXSwiYlEiOlsiS04iXSwiU1Ui
+OlsiS04iXSwiQVMiOltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04ifSwiWkEiOnsibEQiOlsiS04iXSwi
+ek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sImJRIjpbIktOIl0sIlNVIjpbIktOIl0sIkFTIjpb
+XSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sIndmIjp7ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhq
+IjpbIkAiXSwiRVQiOltdLCJiUSI6WyJLTiJdLCJTVSI6WyJLTiJdLCJBUyI6W10sImNYIjpbIktOIl0s
+ImxELkUiOiJLTiJ9LCJQcSI6eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpb
+XSwiYlEiOlsiS04iXSwiU1UiOlsiS04iXSwiQVMiOltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04ifSwi
+ZUUiOnsibEQiOlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sImJRIjpbIktOIl0s
+IlNVIjpbIktOIl0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sIlY2Ijp7Im42IjpbXSwi
+bEQiOlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sImJRIjpbIktOIl0sIlNVIjpb
+IktOIl0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sInU5Ijp7IlhTIjpbXX0sImh6Ijp7
+IlhTIjpbXX0sImlNIjp7IlhTIjpbXX0sIkdWIjp7IkFuIjpbIjEiXX0sInE0Ijp7ImNYIjpbIjEiXSwi
+Y1guRSI6IjEifSwiWmYiOnsiUGYiOlsiMSJdfSwidnMiOnsiYjgiOlsiMSJdfSwiQ3ciOnsiWFMiOltd
+fSwibTAiOnsiSkIiOltdfSwiSmkiOnsiSkIiOltdfSwiYjYiOnsiWHYiOlsiMSJdLCJ4dSI6WyIxIl0s
+ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwibG0iOnsiQW4iOlsiMSJdfSwibVciOnsiY1giOlsiMSJdfSwi
+TFUiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiaWwiOnsiWWsi
+OlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIllrIjp7IlowIjpbIjEiLCIyIl19LCJQbiI6eyJaMCI6
+WyIxIiwiMiJdfSwiR2oiOnsiUlUiOlsiMSIsIjIiXSwiUG4iOlsiMSIsIjIiXSwiS1AiOlsiMSIsIjIi
+XSwiWjAiOlsiMSIsIjIiXX0sIlJLIjp7ImxmIjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIxIl0sImNY
+IjpbIjEiXX0sIlh2Ijp7Inh1IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJ1dyI6eyJZayI6
+WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllrLlYiOiJAIn0sImk4Ijp7ImFM
+IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl0sImFMLkUiOiJxVSIsImNYLkUiOiJxVSJ9LCJD
+ViI6eyJVayI6WyJ6TTxLTj4iLCJxVSJdLCJVay5TIjoiek08S04+In0sInZBIjp7IndJIjpbInpNPEtO
+PiIsInFVIl19LCJaaSI6eyJVayI6WyJxVSIsInpNPEtOPiJdfSwiYnkiOnsiVWsiOlsiayIsInFVIl0s
+IlVrLlMiOiJrIn0sIk14Ijp7IndJIjpbInFVIiwiayJdfSwidTUiOnsiVWsiOlsicVUiLCJ6TTxLTj4i
+XSwiVWsuUyI6InFVIn0sIkUzIjp7IndJIjpbInFVIiwiek08S04+Il19LCJHWSI6eyJ3SSI6WyJ6TTxL
+Tj4iLCJxVSJdfSwiQ1AiOnsiRksiOltdfSwiQzYiOnsiWFMiOltdfSwibiI6eyJYUyI6W119LCJ1Ijp7
+IlhTIjpbXX0sImJKIjp7IlhTIjpbXX0sImVZIjp7IlhTIjpbXX0sIm1wIjp7IlhTIjpbXX0sInViIjp7
+IlhTIjpbXX0sImRzIjp7IlhTIjpbXX0sImxqIjp7IlhTIjpbXX0sIlVWIjp7IlhTIjpbXX0sIms1Ijp7
+IlhTIjpbXX0sIktZIjp7IlhTIjpbXX0sImMiOnsiWFMiOltdfSwiS04iOnsiRksiOltdfSwiek0iOnsi
+YlEiOlsiMSJdLCJjWCI6WyIxIl19LCJpYiI6eyJPZCI6W119LCJ4dSI6eyJiUSI6WyIxIl0sImNYIjpb
+IjEiXX0sInFVIjp7InZYIjpbXX0sIlJuIjp7IkJMIjpbXX0sIkRuIjp7ImlEIjpbXX0sIlVmIjp7ImlE
+IjpbXX0sInFlIjp7ImlEIjpbXX0sInFFIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJHaCI6eyJj
+diI6W10sInVIIjpbXSwiRDAiOltdfSwiZlkiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm5CIjp7
+ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJRUCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiSUYi
+OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm54Ijp7InVIIjpbXSwiRDAiOltdfSwiVm8iOnsia1Ii
+OltdfSwiY3giOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlFGIjp7InVIIjpbXSwiRDAiOltdfSwi
+RnYiOnsiR20iOlsidG48Rks+Il0sImxEIjpbInRuPEZLPiJdLCJYaiI6WyJ0bjxGSz4iXSwiek0iOlsi
+dG48Rks+Il0sImJRIjpbInRuPEZLPiJdLCJjWCI6WyJ0bjxGSz4iXSwiR20uRSI6InRuPEZLPiIsImxE
+LkUiOiJ0bjxGSz4ifSwiSUIiOnsidG4iOlsiRksiXX0sIllsIjp7IkdtIjpbInFVIl0sImxEIjpbInFV
+Il0sInpNIjpbInFVIl0sIlhqIjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl0sIkdtLkUiOiJx
+VSIsImxELkUiOiJxVSJ9LCJ3eiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6
+WyIxIl0sImxELkUiOiIxIn0sImN2Ijp7InVIIjpbXSwiRDAiOltdfSwiVDUiOnsiQXoiOltdfSwiWFYi
+OnsiR20iOlsiVDUiXSwibEQiOlsiVDUiXSwiWGoiOlsiVDUiXSwiek0iOlsiVDUiXSwiYlEiOlsiVDUi
+XSwiY1giOlsiVDUiXSwiR20uRSI6IlQ1IiwibEQuRSI6IlQ1In0sIndKIjp7IkQwIjpbXX0sImg0Ijp7
+ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJ4biI6eyJHbSI6WyJ1SCJdLCJsRCI6WyJ1SCJdLCJ6TSI6
+WyJ1SCJdLCJYaiI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJHbS5FIjoidUgiLCJsRC5F
+IjoidUgifSwiVmIiOnsidUgiOltdLCJEMCI6W119LCJPNyI6eyJEMCI6W119LCJ3YSI6eyJEMCI6W119
+LCJKSyI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiSEwiOnsiZWEiOltdfSwid1AiOnsiY3YiOltd
+LCJ1SCI6W10sIkQwIjpbXX0sImxLIjp7IkQwIjpbXX0sIlFiIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6
+W119LCJTMCI6eyJZayI6WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllrLlYi
+OiJAIn0sInoyIjp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsu
+ViI6IkAifSwiRE0iOnsiR20iOlsiQVciXSwibEQiOlsiQVciXSwiWGoiOlsiQVciXSwiek0iOlsiQVci
+XSwiYlEiOlsiQVciXSwiY1giOlsiQVciXSwiR20uRSI6IkFXIiwibEQuRSI6IkFXIn0sIkFqIjp7ImVh
+IjpbXX0sImU3Ijp7ImxEIjpbInVIIl0sInpNIjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0s
+ImxELkUiOiJ1SCJ9LCJ1SCI6eyJEMCI6W119LCJCSCI6eyJHbSI6WyJ1SCJdLCJsRCI6WyJ1SCJdLCJ6
+TSI6WyJ1SCJdLCJYaiI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJHbS5FIjoidUgiLCJs
+RC5FIjoidUgifSwiUWwiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkdYIjp7ImN2IjpbXSwidUgi
+OltdLCJEMCI6W119LCJTTiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiSEQiOnsiY3YiOltdLCJ1
+SCI6W10sIkQwIjpbXX0sIkV2Ijp7IkdtIjpbImNsIl0sImxEIjpbImNsIl0sInpNIjpbImNsIl0sIlhq
+IjpbImNsIl0sImJRIjpbImNsIl0sImNYIjpbImNsIl0sIkdtLkUiOiJjbCIsImxELkUiOiJjbCJ9LCJM
+ciI6eyJEMCI6W119LCJLUiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZXciOnsiZWEiOltdfSwi
+cDgiOnsiWWsiOlsicVUiLCJAIl0sIlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5WIjoiQCJ9
+LCJscCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiU1YiOnsiRDAiOltdfSwiTWsiOnsiR20iOlsi
+U1YiXSwibEQiOlsiU1YiXSwiek0iOlsiU1YiXSwiWGoiOlsiU1YiXSwiRDAiOltdLCJiUSI6WyJTViJd
+LCJjWCI6WyJTViJdLCJHbS5FIjoiU1YiLCJsRC5FIjoiU1YifSwiTm4iOnsiR20iOlsiWTQiXSwibEQi
+OlsiWTQiXSwiek0iOlsiWTQiXSwiWGoiOlsiWTQiXSwiYlEiOlsiWTQiXSwiY1giOlsiWTQiXSwiR20u
+RSI6Ilk0IiwibEQuRSI6Ilk0In0sIkFzIjp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJd
+LCJZay5LIjoicVUiLCJZay5WIjoicVUifSwiYmsiOnsiZWEiOltdfSwiVGIiOnsiY3YiOltdLCJ1SCI6
+W10sIkQwIjpbXX0sIkl2Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJCVCI6eyJjdiI6W10sInVI
+IjpbXSwiRDAiOltdfSwiZlgiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkZCIjp7ImN2IjpbXSwi
+dUgiOltdLCJEMCI6W119LCJBMSI6eyJEMCI6W119LCJNTiI6eyJEMCI6W119LCJYMCI6eyJHbSI6WyJN
+TiJdLCJsRCI6WyJNTiJdLCJYaiI6WyJNTiJdLCJ6TSI6WyJNTiJdLCJiUSI6WyJNTiJdLCJjWCI6WyJN
+TiJdLCJHbS5FIjoiTU4iLCJsRC5FIjoiTU4ifSwibkoiOnsiR20iOlsiQTEiXSwibEQiOlsiQTEiXSwi
+WGoiOlsiQTEiXSwiek0iOlsiQTEiXSwiRDAiOltdLCJiUSI6WyJBMSJdLCJjWCI6WyJBMSJdLCJHbS5F
+IjoiQTEiLCJsRC5FIjoiQTEifSwiY2kiOnsiR20iOlsiYTMiXSwibEQiOlsiYTMiXSwiek0iOlsiYTMi
+XSwiWGoiOlsiYTMiXSwiYlEiOlsiYTMiXSwiY1giOlsiYTMiXSwiR20uRSI6ImEzIiwibEQuRSI6ImEz
+In0sInc2Ijp7ImVhIjpbXX0sInZGIjp7IkQwIjpbXX0sIk9pIjp7InY2IjpbXSwiRDAiOltdfSwiQ20i
+OnsiRDAiOltdfSwiQ1EiOnsidUgiOltdLCJEMCI6W119LCJQUiI6eyJHbSI6WyJsdyJdLCJsRCI6WyJs
+dyJdLCJ6TSI6WyJsdyJdLCJYaiI6WyJsdyJdLCJiUSI6WyJsdyJdLCJjWCI6WyJsdyJdLCJHbS5FIjoi
+bHciLCJsRC5FIjoibHcifSwidzQiOnsidG4iOlsiRksiXX0sIkYyIjp7IkdtIjpbIkdPIl0sImxEIjpb
+IkdPIl0sIlhqIjpbIkdPIl0sInpNIjpbIkdPIl0sImJRIjpbIkdPIl0sImNYIjpbIkdPIl0sIkdtLkUi
+OiJHTyIsImxELkUiOiJHTyJ9LCJyaCI6eyJHbSI6WyJ1SCJdLCJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJd
+LCJYaiI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJHbS5FIjoidUgiLCJsRC5FIjoidUgi
+fSwiTE8iOnsiR20iOlsibDgiXSwibEQiOlsibDgiXSwiek0iOlsibDgiXSwiWGoiOlsibDgiXSwiYlEi
+OlsibDgiXSwiY1giOlsibDgiXSwiR20uRSI6Imw4IiwibEQuRSI6Imw4In0sImIxIjp7IkdtIjpbIldX
+Il0sImxEIjpbIldXIl0sIlhqIjpbIldXIl0sInpNIjpbIldXIl0sImJRIjpbIldXIl0sImNYIjpbIldX
+Il0sIkdtLkUiOiJXVyIsImxELkUiOiJXVyJ9LCJhVCI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFV
+IiwicVUiXX0sImk3Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUi
+LCJZay5WIjoicVUifSwiU3kiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl0sIllrLksi
+OiJxVSIsIllrLlYiOiJxVSJ9LCJJNCI6eyJsZiI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJiUSI6WyJxVSJd
+LCJjWCI6WyJxVSJdfSwiUk8iOnsicWgiOlsiMSJdfSwiZXUiOnsiUk8iOlsiMSJdLCJxaCI6WyIxIl19
+LCJ4QyI6eyJNTyI6WyIxIl19LCJKUSI6eyJrRiI6W119LCJ2RCI6eyJrRiI6W119LCJtNiI6eyJrRiI6
+W119LCJjdCI6eyJrRiI6W119LCJPdyI6eyJrRiI6W119LCJXOSI6eyJBbiI6WyIxIl19LCJkVyI6eyJ2
+NiI6W10sIkQwIjpbXX0sIm1rIjp7IldRIjpbXX0sIktvIjp7Im9uIjpbXX0sImRNIjp7ImxmIjpbInFV
+Il0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl19LCJyNyI6eyJFNCI6W119LCJUeiI6
+eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJFNCI6W10sImNYIjpbIjEiXSwibEQuRSI6
+IjEifSwicTYiOnsiR20iOlsieDAiXSwibEQiOlsieDAiXSwiek0iOlsieDAiXSwiYlEiOlsieDAiXSwi
+Y1giOlsieDAiXSwiR20uRSI6IngwIiwibEQuRSI6IngwIn0sImZ6Ijp7IkdtIjpbInVQIl0sImxEIjpb
+InVQIl0sInpNIjpbInVQIl0sImJRIjpbInVQIl0sImNYIjpbInVQIl0sIkdtLkUiOiJ1UCIsImxELkUi
+OiJ1UCJ9LCJuZCI6eyJkNSI6W10sImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJLcSI6eyJHbSI6WyJx
+VSJdLCJsRCI6WyJxVSJdLCJ6TSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6WyJxVSJdLCJHbS5FIjoi
+cVUiLCJsRC5FIjoicVUifSwiS2UiOnsibGYiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwi
+Y1giOlsicVUiXX0sImQ1Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJOQyI6eyJHbSI6WyJ6WSJd
+LCJsRCI6WyJ6WSJdLCJ6TSI6WyJ6WSJdLCJiUSI6WyJ6WSJdLCJjWCI6WyJ6WSJdLCJHbS5FIjoielki
+LCJsRC5FIjoielkifSwibjYiOnsiek0iOlsiS04iXSwiYlEiOlsiS04iXSwiQVMiOltdLCJjWCI6WyJL
+TiJdfSwiejgiOnsiWWsiOlsicVUiLCJAIl0sIlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5W
+IjoiQCJ9LCJmbyI6eyJEMCI6W119LCJWOCI6eyJEMCI6W119LCJHbiI6eyJEMCI6W119LCJGbiI6eyJH
+bSI6WyJaMDxALEA+Il0sImxEIjpbIlowPEAsQD4iXSwiek0iOlsiWjA8QCxAPiJdLCJiUSI6WyJaMDxA
+LEA+Il0sImNYIjpbIlowPEAsQD4iXSwiR20uRSI6IlowPEAsQD4iLCJsRC5FIjoiWjA8QCxAPiJ9LCJY
+QSI6eyJrRiI6W119LCJPRiI6eyJMdSI6W119LCJydSI6eyJMdSI6W119LCJJViI6eyJMdSI6W119fScp
+KQpILkZGKHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3siYlEiOjEsIlhDIjoxLCJNTyI6MSwia1Qi
+OjIsIm1XIjoxLCJMVSI6MSwiaWwiOjIsIlJLIjoxLCJuWSI6MSwiV1kiOjEsImNvIjoxLCJJTiI6MX0n
+KSkKdmFyIHU9KGZ1bmN0aW9uIHJ0aWkoKXt2YXIgdD1ILllRCnJldHVybntpOnQoIkdoIiksbjp0KCJD
+dyIpLGNSOnQoIm5CIiksZDp0KCJBeiIpLGs6dCgiUVAiKSxnRjp0KCJQRDxHRCxAPiIpLGc1OnQoImx3
+IiksZ3c6dCgiYlE8QD4iKSxoOnQoImN2IiksYlU6dCgiWFMiKSxCOnQoImVhIiksYVM6dCgiRDAiKSxP
+OnQoIlQ1IiksYlg6dCgiWFYiKSxaOnQoIkVIIiksYzp0KCJiODxAPiIpLGRQOnQoIkdPIikscjp0KCJP
+NyIpLEk6dCgiU2ciKSxvOnQoInZRIiksZWg6dCgiY1g8dUg+IiksWDp0KCJjWDxxVT4iKSxSOnQoImNY
+PEA+IiksZkE6dCgiamQ8U2U+IiksZ2k6dCgiamQ8ajg+IiksZmg6dCgiamQ8Wlo+IiksbTp0KCJqZDxr
+Rj4iKSxzOnQoImpkPHFVPiIpLGhoOnQoImpkPHlEPiIpLGFKOnQoImpkPHdiPiIpLHU6dCgiamQ8QD4i
+KSx0OnQoImpkPEtOPiIpLGVIOnQoInZtIiksZzp0KCJjNSIpLGFVOnQoIlhqPEA+IiksYW06dCgiVHo8
+QD4iKSxlbzp0KCJONTxHRCxAPiIpLHY6dCgiRTQiKSxkejp0KCJoRiIpLGJHOnQoIngwIiksZjQ6dCgi
+ek08ajg+IiksYTp0KCJ6TTxxVT4iKSxqOnQoInpNPEA+IiksTDp0KCJ6TTxLTj4iKSxhXzp0KCJ1OCIp
+LGY6dCgiWjA8cVUscVU+IiksYjp0KCJaMDxxVSxAPiIpLEc6dCgiWjA8QCxAPiIpLGR2OnQoIkE4PHFV
+LHFVPiIpLGRvOnQoIkE4PHFVLEA+IiksYks6dCgibEsiKSxjSTp0KCJBVyIpLFY6dCgiQWoiKSxiWjp0
+KCJXWiIpLGREOnQoIkVUIiksYm06dCgiVjYiKSxBOnQoInVIIiksZTp0KCJrRiIpLFA6dCgiYzgiKSxj
+azp0KCJ1UCIpLEs6dCgiayIpLGhlOnQoImNsIikscDp0KCJldyIpLHE6dCgidG48Rks+IiksZnY6dCgi
+d0wiKSxhdjp0KCJKYyIpLGV3OnQoIm5kIiksQzp0KCJ4dTxxVT4iKSxmWTp0KCJTViIpLGY3OnQoIlk0
+IiksZ2Y6dCgibDgiKSxsOnQoIkd6IiksTjp0KCJxVSIpLGRHOnQoInFVKHFVKSIpLGduOnQoIldXIiks
+Zzc6dCgiZDUiKSxmbzp0KCJHRCIpLGFXOnQoImZYIiksYTA6dCgiQTEiKSxjNzp0KCJNTiIpLGFLOnQo
+ImEzIiksY006dCgielkiKSx3OnQoIkFTIiksZ2M6dCgibjYiKSxhazp0KCJrZCIpLFc6dCgiR2o8cVUs
+cVU+IiksRDp0KCJpRCIpLGNjOnQoIlU1PHFVPiIpLGc0OnQoIk9pIiksY2k6dCgidjYiKSxnMjp0KCJD
+bSIpLGJqOnQoIlpmPE83PiIpLGg5OnQoIkNRIiksYWM6dCgiZTciKSxROnQoImV1PEFqPiIpLFM6dCgi
+d3o8Y3Y+IikseDp0KCJGZTxALEA+IiksYW86dCgidnM8Tzc+IiksXzp0KCJ2czxAPiIpLGZKOnQoInZz
+PEtOPiIpLEU6dCgiSlEiKSxKOnQoImJuIiksY0o6dCgiYTIiKSxhbDp0KCJhMihrKSIpLGJCOnQoImEy
+KHFVKSIpLGJmOnQoImEyKEApIiksejp0KCJAIiksZk86dCgiQCgpIiksRjp0KCJAKGVhKSIpLHk6dCgi
+QChrKSIpLGVwOnQoIkAoayxrKSIpLGFnOnQoIkAoayxHeikiKSxjaDp0KCJAKHh1PHFVPikiKSxkTzp0
+KCJAKHFVKSIpLFk6dCgiQChALEApIiksZWc6dCgiS04iKSxIOnQoIn4iKSxNOnQoIn4oKSIpLGFuOnQo
+In4oZXcpIiksVTp0KCJ+KHFVLHFVKSIpLFQ6dCgifihxVSxAKSIpfX0pKCk7KGZ1bmN0aW9uIGNvbnN0
+YW50cygpe3ZhciB0PWh1bmtIZWxwZXJzLm1ha2VDb25zdExpc3QKQy5SWT1XLlFQLnByb3RvdHlwZQpD
+LkJaPVcuVmIucHJvdG90eXBlCkMuRHQ9Vy5PNy5wcm90b3R5cGUKQy5Paz1KLnZCLnByb3RvdHlwZQpD
+Lk5tPUouamQucHJvdG90eXBlCkMuam49Si51ci5wcm90b3R5cGUKQy5qTj1KLllFLnByb3RvdHlwZQpD
+LkNEPUoucUkucHJvdG90eXBlCkMueEI9Si5Eci5wcm90b3R5cGUKQy5ERz1KLmM1LnByb3RvdHlwZQpD
+LkV4PVcudTgucHJvdG90eXBlCkMudDU9Vy5CSC5wcm90b3R5cGUKQy5MdD1XLlNOLnByb3RvdHlwZQpD
+LlpRPUouaUMucHJvdG90eXBlCkMuSWU9Vy5UYi5wcm90b3R5cGUKQy52Qj1KLmtkLnByb3RvdHlwZQpD
+Lm9sPVcuT2kucHJvdG90eXBlCkMueTg9bmV3IFAudkEoKQpDLmg5PW5ldyBQLkNWKCkKQy5PND1mdW5j
+dGlvbiBnZXRUYWdGYWxsYmFjayhvKSB7CiAgdmFyIHMgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5n
+LmNhbGwobyk7CiAgcmV0dXJuIHMuc3Vic3RyaW5nKDgsIHMubGVuZ3RoIC0gMSk7Cn0KQy5ZcT1mdW5j
+dGlvbigpIHsKICB2YXIgdG9TdHJpbmdGdW5jdGlvbiA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7
+CiAgZnVuY3Rpb24gZ2V0VGFnKG8pIHsKICAgIHZhciBzID0gdG9TdHJpbmdGdW5jdGlvbi5jYWxsKG8p
+OwogICAgcmV0dXJuIHMuc3Vic3RyaW5nKDgsIHMubGVuZ3RoIC0gMSk7CiAgfQogIGZ1bmN0aW9uIGdl
+dFVua25vd25UYWcob2JqZWN0LCB0YWcpIHsKICAgIGlmICgvXkhUTUxbQS1aXS4qRWxlbWVudCQvLnRl
+c3QodGFnKSkgewogICAgICB2YXIgbmFtZSA9IHRvU3RyaW5nRnVuY3Rpb24uY2FsbChvYmplY3QpOwog
+ICAgICBpZiAobmFtZSA9PSAiW29iamVjdCBPYmplY3RdIikgcmV0dXJuIG51bGw7CiAgICAgIHJldHVy
+biAiSFRNTEVsZW1lbnQiOwogICAgfQogIH0KICBmdW5jdGlvbiBnZXRVbmtub3duVGFnR2VuZXJpY0Jy
+b3dzZXIob2JqZWN0LCB0YWcpIHsKICAgIGlmIChzZWxmLkhUTUxFbGVtZW50ICYmIG9iamVjdCBpbnN0
+YW5jZW9mIEhUTUxFbGVtZW50KSByZXR1cm4gIkhUTUxFbGVtZW50IjsKICAgIHJldHVybiBnZXRVbmtu
+b3duVGFnKG9iamVjdCwgdGFnKTsKICB9CiAgZnVuY3Rpb24gcHJvdG90eXBlRm9yVGFnKHRhZykgewog
+ICAgaWYgKHR5cGVvZiB3aW5kb3cgPT0gInVuZGVmaW5lZCIpIHJldHVybiBudWxsOwogICAgaWYgKHR5
+cGVvZiB3aW5kb3dbdGFnXSA9PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICB2YXIgY29uc3Ry
+dWN0b3IgPSB3aW5kb3dbdGFnXTsKICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3IgIT0gImZ1bmN0aW9u
+IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gY29uc3RydWN0b3IucHJvdG90eXBlOwogIH0KICBmdW5j
+dGlvbiBkaXNjcmltaW5hdG9yKHRhZykgeyByZXR1cm4gbnVsbDsgfQogIHZhciBpc0Jyb3dzZXIgPSB0
+eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiOwogIHJldHVybiB7CiAgICBnZXRUYWc6IGdldFRhZywK
+ICAgIGdldFVua25vd25UYWc6IGlzQnJvd3NlciA/IGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlciA6
+IGdldFVua25vd25UYWcsCiAgICBwcm90b3R5cGVGb3JUYWc6IHByb3RvdHlwZUZvclRhZywKICAgIGRp
+c2NyaW1pbmF0b3I6IGRpc2NyaW1pbmF0b3IgfTsKfQpDLndiPWZ1bmN0aW9uKGdldFRhZ0ZhbGxiYWNr
+KSB7CiAgcmV0dXJuIGZ1bmN0aW9uKGhvb2tzKSB7CiAgICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPSAi
+b2JqZWN0IikgcmV0dXJuIGhvb2tzOwogICAgdmFyIHVhID0gbmF2aWdhdG9yLnVzZXJBZ2VudDsKICAg
+IGlmICh1YS5pbmRleE9mKCJEdW1wUmVuZGVyVHJlZSIpID49IDApIHJldHVybiBob29rczsKICAgIGlm
+ICh1YS5pbmRleE9mKCJDaHJvbWUiKSA+PSAwKSB7CiAgICAgIGZ1bmN0aW9uIGNvbmZpcm0ocCkgewog
+ICAgICAgIHJldHVybiB0eXBlb2Ygd2luZG93ID09ICJvYmplY3QiICYmIHdpbmRvd1twXSAmJiB3aW5k
+b3dbcF0ubmFtZSA9PSBwOwogICAgICB9CiAgICAgIGlmIChjb25maXJtKCJXaW5kb3ciKSAmJiBjb25m
+aXJtKCJIVE1MRWxlbWVudCIpKSByZXR1cm4gaG9va3M7CiAgICB9CiAgICBob29rcy5nZXRUYWcgPSBn
+ZXRUYWdGYWxsYmFjazsKICB9Owp9CkMuS1U9ZnVuY3Rpb24oaG9va3MpIHsKICBpZiAodHlwZW9mIGRh
+cnRFeHBlcmltZW50YWxGaXh1cEdldFRhZyAhPSAiZnVuY3Rpb24iKSByZXR1cm4gaG9va3M7CiAgaG9v
+a3MuZ2V0VGFnID0gZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0VGFnKGhvb2tzLmdldFRhZyk7Cn0KQy5m
+UT1mdW5jdGlvbihob29rcykgewogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHByb3Rv
+dHlwZUZvclRhZyA9IGhvb2tzLnByb3RvdHlwZUZvclRhZzsKICBmdW5jdGlvbiBnZXRUYWdGaXhlZChv
+KSB7CiAgICB2YXIgdGFnID0gZ2V0VGFnKG8pOwogICAgaWYgKHRhZyA9PSAiRG9jdW1lbnQiKSB7CiAg
+ICAgIGlmICghIW8ueG1sVmVyc2lvbikgcmV0dXJuICIhRG9jdW1lbnQiOwogICAgICByZXR1cm4gIiFI
+VE1MRG9jdW1lbnQiOwogICAgfQogICAgcmV0dXJuIHRhZzsKICB9CiAgZnVuY3Rpb24gcHJvdG90eXBl
+Rm9yVGFnRml4ZWQodGFnKSB7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHJldHVybiBudWxsOwog
+ICAgcmV0dXJuIHByb3RvdHlwZUZvclRhZyh0YWcpOwogIH0KICBob29rcy5nZXRUYWcgPSBnZXRUYWdG
+aXhlZDsKICBob29rcy5wcm90b3R5cGVGb3JUYWcgPSBwcm90b3R5cGVGb3JUYWdGaXhlZDsKfQpDLmRr
+PWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIHVzZXJBZ2VudCA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9i
+amVjdCIgPyBuYXZpZ2F0b3IudXNlckFnZW50IDogIiI7CiAgaWYgKHVzZXJBZ2VudC5pbmRleE9mKCJG
+aXJlZm94IikgPT0gLTEpIHJldHVybiBob29rczsKICB2YXIgZ2V0VGFnID0gaG9va3MuZ2V0VGFnOwog
+IHZhciBxdWlja01hcCA9IHsKICAgICJCZWZvcmVVbmxvYWRFdmVudCI6ICJFdmVudCIsCiAgICAiRGF0
+YVRyYW5zZmVyIjogIkNsaXBib2FyZCIsCiAgICAiR2VvR2VvbG9jYXRpb24iOiAiR2VvbG9jYXRpb24i
+LAogICAgIkxvY2F0aW9uIjogIiFMb2NhdGlvbiIsCiAgICAiV29ya2VyTWVzc2FnZUV2ZW50IjogIk1l
+c3NhZ2VFdmVudCIsCiAgICAiWE1MRG9jdW1lbnQiOiAiIURvY3VtZW50In07CiAgZnVuY3Rpb24gZ2V0
+VGFnRmlyZWZveChvKSB7CiAgICB2YXIgdGFnID0gZ2V0VGFnKG8pOwogICAgcmV0dXJuIHF1aWNrTWFw
+W3RhZ10gfHwgdGFnOwogIH0KICBob29rcy5nZXRUYWcgPSBnZXRUYWdGaXJlZm94Owp9CkMueGk9ZnVu
+Y3Rpb24oaG9va3MpIHsKICB2YXIgdXNlckFnZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0
+IiA/IG5hdmlnYXRvci51c2VyQWdlbnQgOiAiIjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIlRyaWRl
+bnQvIikgPT0gLTEpIHJldHVybiBob29rczsKICB2YXIgZ2V0VGFnID0gaG9va3MuZ2V0VGFnOwogIHZh
+ciBxdWlja01hcCA9IHsKICAgICJCZWZvcmVVbmxvYWRFdmVudCI6ICJFdmVudCIsCiAgICAiRGF0YVRy
+YW5zZmVyIjogIkNsaXBib2FyZCIsCiAgICAiSFRNTERERWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAg
+ICAiSFRNTERURWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiSFRNTFBocmFzZUVsZW1lbnQiOiAi
+SFRNTEVsZW1lbnQiLAogICAgIlBvc2l0aW9uIjogIkdlb3Bvc2l0aW9uIgogIH07CiAgZnVuY3Rpb24g
+Z2V0VGFnSUUobykgewogICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAgIHZhciBuZXdUYWcgPSBxdWlj
+a01hcFt0YWddOwogICAgaWYgKG5ld1RhZykgcmV0dXJuIG5ld1RhZzsKICAgIGlmICh0YWcgPT0gIk9i
+amVjdCIpIHsKICAgICAgaWYgKHdpbmRvdy5EYXRhVmlldyAmJiAobyBpbnN0YW5jZW9mIHdpbmRvdy5E
+YXRhVmlldykpIHJldHVybiAiRGF0YVZpZXciOwogICAgfQogICAgcmV0dXJuIHRhZzsKICB9CiAgZnVu
+Y3Rpb24gcHJvdG90eXBlRm9yVGFnSUUodGFnKSB7CiAgICB2YXIgY29uc3RydWN0b3IgPSB3aW5kb3db
+dGFnXTsKICAgIGlmIChjb25zdHJ1Y3RvciA9PSBudWxsKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBj
+b25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0lFOwogIGhvb2tz
+LnByb3RvdHlwZUZvclRhZyA9IHByb3RvdHlwZUZvclRhZ0lFOwp9CkMuaTc9ZnVuY3Rpb24oaG9va3Mp
+IHsgcmV0dXJuIGhvb2tzOyB9CgpDLkN0PW5ldyBQLmJ5KCkKQy5FcT1uZXcgUC5rNSgpCkMueE09bmV3
+IFAudTUoKQpDLlFrPW5ldyBQLkUzKCkKQy5OVT1uZXcgUC5KaSgpCkMuQTM9bmV3IFAuTXgobnVsbCkK
+Qy5HYj1ILlZNKHQoWzEyNywyMDQ3LDY1NTM1LDExMTQxMTFdKSx1LnQpCkMuYWs9SC5WTSh0KFswLDAs
+MzI3NzYsMzM3OTIsMSwxMDI0MCwwLDBdKSx1LnQpCkMuY209SC5WTSh0KFsiKjo6Y2xhc3MiLCIqOjpk
+aXIiLCIqOjpkcmFnZ2FibGUiLCIqOjpoaWRkZW4iLCIqOjppZCIsIio6OmluZXJ0IiwiKjo6aXRlbXBy
+b3AiLCIqOjppdGVtcmVmIiwiKjo6aXRlbXNjb3BlIiwiKjo6bGFuZyIsIio6OnNwZWxsY2hlY2siLCIq
+Ojp0aXRsZSIsIio6OnRyYW5zbGF0ZSIsIkE6OmFjY2Vzc2tleSIsIkE6OmNvb3JkcyIsIkE6OmhyZWZs
+YW5nIiwiQTo6bmFtZSIsIkE6OnNoYXBlIiwiQTo6dGFiaW5kZXgiLCJBOjp0YXJnZXQiLCJBOjp0eXBl
+IiwiQVJFQTo6YWNjZXNza2V5IiwiQVJFQTo6YWx0IiwiQVJFQTo6Y29vcmRzIiwiQVJFQTo6bm9ocmVm
+IiwiQVJFQTo6c2hhcGUiLCJBUkVBOjp0YWJpbmRleCIsIkFSRUE6OnRhcmdldCIsIkFVRElPOjpjb250
+cm9scyIsIkFVRElPOjpsb29wIiwiQVVESU86Om1lZGlhZ3JvdXAiLCJBVURJTzo6bXV0ZWQiLCJBVURJ
+Tzo6cHJlbG9hZCIsIkJETzo6ZGlyIiwiQk9EWTo6YWxpbmsiLCJCT0RZOjpiZ2NvbG9yIiwiQk9EWTo6
+bGluayIsIkJPRFk6OnRleHQiLCJCT0RZOjp2bGluayIsIkJSOjpjbGVhciIsIkJVVFRPTjo6YWNjZXNz
+a2V5IiwiQlVUVE9OOjpkaXNhYmxlZCIsIkJVVFRPTjo6bmFtZSIsIkJVVFRPTjo6dGFiaW5kZXgiLCJC
+VVRUT046OnR5cGUiLCJCVVRUT046OnZhbHVlIiwiQ0FOVkFTOjpoZWlnaHQiLCJDQU5WQVM6OndpZHRo
+IiwiQ0FQVElPTjo6YWxpZ24iLCJDT0w6OmFsaWduIiwiQ09MOjpjaGFyIiwiQ09MOjpjaGFyb2ZmIiwi
+Q09MOjpzcGFuIiwiQ09MOjp2YWxpZ24iLCJDT0w6OndpZHRoIiwiQ09MR1JPVVA6OmFsaWduIiwiQ09M
+R1JPVVA6OmNoYXIiLCJDT0xHUk9VUDo6Y2hhcm9mZiIsIkNPTEdST1VQOjpzcGFuIiwiQ09MR1JPVVA6
+OnZhbGlnbiIsIkNPTEdST1VQOjp3aWR0aCIsIkNPTU1BTkQ6OmNoZWNrZWQiLCJDT01NQU5EOjpjb21t
+YW5kIiwiQ09NTUFORDo6ZGlzYWJsZWQiLCJDT01NQU5EOjpsYWJlbCIsIkNPTU1BTkQ6OnJhZGlvZ3Jv
+dXAiLCJDT01NQU5EOjp0eXBlIiwiREFUQTo6dmFsdWUiLCJERUw6OmRhdGV0aW1lIiwiREVUQUlMUzo6
+b3BlbiIsIkRJUjo6Y29tcGFjdCIsIkRJVjo6YWxpZ24iLCJETDo6Y29tcGFjdCIsIkZJRUxEU0VUOjpk
+aXNhYmxlZCIsIkZPTlQ6OmNvbG9yIiwiRk9OVDo6ZmFjZSIsIkZPTlQ6OnNpemUiLCJGT1JNOjphY2Nl
+cHQiLCJGT1JNOjphdXRvY29tcGxldGUiLCJGT1JNOjplbmN0eXBlIiwiRk9STTo6bWV0aG9kIiwiRk9S
+TTo6bmFtZSIsIkZPUk06Om5vdmFsaWRhdGUiLCJGT1JNOjp0YXJnZXQiLCJGUkFNRTo6bmFtZSIsIkgx
+OjphbGlnbiIsIkgyOjphbGlnbiIsIkgzOjphbGlnbiIsIkg0OjphbGlnbiIsIkg1OjphbGlnbiIsIkg2
+OjphbGlnbiIsIkhSOjphbGlnbiIsIkhSOjpub3NoYWRlIiwiSFI6OnNpemUiLCJIUjo6d2lkdGgiLCJI
+VE1MOjp2ZXJzaW9uIiwiSUZSQU1FOjphbGlnbiIsIklGUkFNRTo6ZnJhbWVib3JkZXIiLCJJRlJBTUU6
+OmhlaWdodCIsIklGUkFNRTo6bWFyZ2luaGVpZ2h0IiwiSUZSQU1FOjptYXJnaW53aWR0aCIsIklGUkFN
+RTo6d2lkdGgiLCJJTUc6OmFsaWduIiwiSU1HOjphbHQiLCJJTUc6OmJvcmRlciIsIklNRzo6aGVpZ2h0
+IiwiSU1HOjpoc3BhY2UiLCJJTUc6OmlzbWFwIiwiSU1HOjpuYW1lIiwiSU1HOjp1c2VtYXAiLCJJTUc6
+OnZzcGFjZSIsIklNRzo6d2lkdGgiLCJJTlBVVDo6YWNjZXB0IiwiSU5QVVQ6OmFjY2Vzc2tleSIsIklO
+UFVUOjphbGlnbiIsIklOUFVUOjphbHQiLCJJTlBVVDo6YXV0b2NvbXBsZXRlIiwiSU5QVVQ6OmF1dG9m
+b2N1cyIsIklOUFVUOjpjaGVja2VkIiwiSU5QVVQ6OmRpc2FibGVkIiwiSU5QVVQ6OmlucHV0bW9kZSIs
+IklOUFVUOjppc21hcCIsIklOUFVUOjpsaXN0IiwiSU5QVVQ6Om1heCIsIklOUFVUOjptYXhsZW5ndGgi
+LCJJTlBVVDo6bWluIiwiSU5QVVQ6Om11bHRpcGxlIiwiSU5QVVQ6Om5hbWUiLCJJTlBVVDo6cGxhY2Vo
+b2xkZXIiLCJJTlBVVDo6cmVhZG9ubHkiLCJJTlBVVDo6cmVxdWlyZWQiLCJJTlBVVDo6c2l6ZSIsIklO
+UFVUOjpzdGVwIiwiSU5QVVQ6OnRhYmluZGV4IiwiSU5QVVQ6OnR5cGUiLCJJTlBVVDo6dXNlbWFwIiwi
+SU5QVVQ6OnZhbHVlIiwiSU5TOjpkYXRldGltZSIsIktFWUdFTjo6ZGlzYWJsZWQiLCJLRVlHRU46Omtl
+eXR5cGUiLCJLRVlHRU46Om5hbWUiLCJMQUJFTDo6YWNjZXNza2V5IiwiTEFCRUw6OmZvciIsIkxFR0VO
+RDo6YWNjZXNza2V5IiwiTEVHRU5EOjphbGlnbiIsIkxJOjp0eXBlIiwiTEk6OnZhbHVlIiwiTElOSzo6
+c2l6ZXMiLCJNQVA6Om5hbWUiLCJNRU5VOjpjb21wYWN0IiwiTUVOVTo6bGFiZWwiLCJNRU5VOjp0eXBl
+IiwiTUVURVI6OmhpZ2giLCJNRVRFUjo6bG93IiwiTUVURVI6Om1heCIsIk1FVEVSOjptaW4iLCJNRVRF
+Ujo6dmFsdWUiLCJPQkpFQ1Q6OnR5cGVtdXN0bWF0Y2giLCJPTDo6Y29tcGFjdCIsIk9MOjpyZXZlcnNl
+ZCIsIk9MOjpzdGFydCIsIk9MOjp0eXBlIiwiT1BUR1JPVVA6OmRpc2FibGVkIiwiT1BUR1JPVVA6Omxh
+YmVsIiwiT1BUSU9OOjpkaXNhYmxlZCIsIk9QVElPTjo6bGFiZWwiLCJPUFRJT046OnNlbGVjdGVkIiwi
+T1BUSU9OOjp2YWx1ZSIsIk9VVFBVVDo6Zm9yIiwiT1VUUFVUOjpuYW1lIiwiUDo6YWxpZ24iLCJQUkU6
+OndpZHRoIiwiUFJPR1JFU1M6Om1heCIsIlBST0dSRVNTOjptaW4iLCJQUk9HUkVTUzo6dmFsdWUiLCJT
+RUxFQ1Q6OmF1dG9jb21wbGV0ZSIsIlNFTEVDVDo6ZGlzYWJsZWQiLCJTRUxFQ1Q6Om11bHRpcGxlIiwi
+U0VMRUNUOjpuYW1lIiwiU0VMRUNUOjpyZXF1aXJlZCIsIlNFTEVDVDo6c2l6ZSIsIlNFTEVDVDo6dGFi
+aW5kZXgiLCJTT1VSQ0U6OnR5cGUiLCJUQUJMRTo6YWxpZ24iLCJUQUJMRTo6Ymdjb2xvciIsIlRBQkxF
+Ojpib3JkZXIiLCJUQUJMRTo6Y2VsbHBhZGRpbmciLCJUQUJMRTo6Y2VsbHNwYWNpbmciLCJUQUJMRTo6
+ZnJhbWUiLCJUQUJMRTo6cnVsZXMiLCJUQUJMRTo6c3VtbWFyeSIsIlRBQkxFOjp3aWR0aCIsIlRCT0RZ
+OjphbGlnbiIsIlRCT0RZOjpjaGFyIiwiVEJPRFk6OmNoYXJvZmYiLCJUQk9EWTo6dmFsaWduIiwiVEQ6
+OmFiYnIiLCJURDo6YWxpZ24iLCJURDo6YXhpcyIsIlREOjpiZ2NvbG9yIiwiVEQ6OmNoYXIiLCJURDo6
+Y2hhcm9mZiIsIlREOjpjb2xzcGFuIiwiVEQ6OmhlYWRlcnMiLCJURDo6aGVpZ2h0IiwiVEQ6Om5vd3Jh
+cCIsIlREOjpyb3dzcGFuIiwiVEQ6OnNjb3BlIiwiVEQ6OnZhbGlnbiIsIlREOjp3aWR0aCIsIlRFWFRB
+UkVBOjphY2Nlc3NrZXkiLCJURVhUQVJFQTo6YXV0b2NvbXBsZXRlIiwiVEVYVEFSRUE6OmNvbHMiLCJU
+RVhUQVJFQTo6ZGlzYWJsZWQiLCJURVhUQVJFQTo6aW5wdXRtb2RlIiwiVEVYVEFSRUE6Om5hbWUiLCJU
+RVhUQVJFQTo6cGxhY2Vob2xkZXIiLCJURVhUQVJFQTo6cmVhZG9ubHkiLCJURVhUQVJFQTo6cmVxdWly
+ZWQiLCJURVhUQVJFQTo6cm93cyIsIlRFWFRBUkVBOjp0YWJpbmRleCIsIlRFWFRBUkVBOjp3cmFwIiwi
+VEZPT1Q6OmFsaWduIiwiVEZPT1Q6OmNoYXIiLCJURk9PVDo6Y2hhcm9mZiIsIlRGT09UOjp2YWxpZ24i
+LCJUSDo6YWJiciIsIlRIOjphbGlnbiIsIlRIOjpheGlzIiwiVEg6OmJnY29sb3IiLCJUSDo6Y2hhciIs
+IlRIOjpjaGFyb2ZmIiwiVEg6OmNvbHNwYW4iLCJUSDo6aGVhZGVycyIsIlRIOjpoZWlnaHQiLCJUSDo6
+bm93cmFwIiwiVEg6OnJvd3NwYW4iLCJUSDo6c2NvcGUiLCJUSDo6dmFsaWduIiwiVEg6OndpZHRoIiwi
+VEhFQUQ6OmFsaWduIiwiVEhFQUQ6OmNoYXIiLCJUSEVBRDo6Y2hhcm9mZiIsIlRIRUFEOjp2YWxpZ24i
+LCJUUjo6YWxpZ24iLCJUUjo6Ymdjb2xvciIsIlRSOjpjaGFyIiwiVFI6OmNoYXJvZmYiLCJUUjo6dmFs
+aWduIiwiVFJBQ0s6OmRlZmF1bHQiLCJUUkFDSzo6a2luZCIsIlRSQUNLOjpsYWJlbCIsIlRSQUNLOjpz
+cmNsYW5nIiwiVUw6OmNvbXBhY3QiLCJVTDo6dHlwZSIsIlZJREVPOjpjb250cm9scyIsIlZJREVPOjpo
+ZWlnaHQiLCJWSURFTzo6bG9vcCIsIlZJREVPOjptZWRpYWdyb3VwIiwiVklERU86Om11dGVkIiwiVklE
+RU86OnByZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdS5zKQpDLlZDPUguVk0odChbMCwwLDY1NDkwLDQ1
+MDU1LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLm1LPUguVk0odChbMCwwLDI2NjI0LDEw
+MjMsNjU1MzQsMjA0Nyw2NTUzNCwyMDQ3XSksdS50KQpDLlNxPUguVk0odChbIkhFQUQiLCJBUkVBIiwi
+QkFTRSIsIkJBU0VGT05UIiwiQlIiLCJDT0wiLCJDT0xHUk9VUCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFN
+RVNFVCIsIkhSIiwiSU1BR0UiLCJJTUciLCJJTlBVVCIsIklTSU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBB
+UkFNIiwiU09VUkNFIiwiU1RZTEUiLCJUSVRMRSIsIldCUiJdKSx1LnMpCkMueEQ9SC5WTSh0KFtdKSx1
+LnMpCkMuZG49SC5WTSh0KFtdKSx1LnUpCkMudG89SC5WTSh0KFswLDAsMzI3MjIsMTIyODcsNjU1MzQs
+MzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQpCkMuRjM9SC5WTSh0KFswLDAsMjQ1NzYsMTAyMyw2NTUzNCwz
+NDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5lYT1ILlZNKHQoWzAsMCwzMjc1NCwxMTI2Myw2NTUzNCwz
+NDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5aSj1ILlZNKHQoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNSwz
+NDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5XZD1ILlZNKHQoWzAsMCw2NTQ5MCwxMjI4Nyw2NTUzNSwz
+NDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5ReD1ILlZNKHQoWyJiaW5kIiwiaWYiLCJyZWYiLCJyZXBl
+YXQiLCJzeW50YXgiXSksdS5zKQpDLkJJPUguVk0odChbIkE6OmhyZWYiLCJBUkVBOjpocmVmIiwiQkxP
+Q0tRVU9URTo6Y2l0ZSIsIkJPRFk6OmJhY2tncm91bmQiLCJDT01NQU5EOjppY29uIiwiREVMOjpjaXRl
+IiwiRk9STTo6YWN0aW9uIiwiSU1HOjpzcmMiLCJJTlBVVDo6c3JjIiwiSU5TOjpjaXRlIiwiUTo6Y2l0
+ZSIsIlZJREVPOjpwb3N0ZXIiXSksdS5zKQpDLkNNPW5ldyBILkxQKDAse30sQy54RCxILllRKCJMUDxx
+VSx6TTxqOD4+IikpCkMuV089bmV3IEguTFAoMCx7fSxDLnhELEguWVEoIkxQPHFVLHFVPiIpKQpDLmhV
+PUguVk0odChbXSksSC5ZUSgiamQ8R0Q+IikpCkMuRHg9bmV3IEguTFAoMCx7fSxDLmhVLEguWVEoIkxQ
+PEdELEA+IikpCkMuWTI9bmV3IEwuQmMoIk5hdmlnYXRpb25UcmVlTm9kZVR5cGUuZGlyZWN0b3J5IikK
+Qy5yZj1uZXcgTC5CYygiTmF2aWdhdGlvblRyZWVOb2RlVHlwZS5maWxlIikKQy5UZT1uZXcgSC53digi
+Y2FsbCIpCkMud1E9bmV3IFAuRnkobnVsbCwyKX0pKCk7KGZ1bmN0aW9uIHN0YXRpY0ZpZWxkcygpeyQu
+eWo9MAokLm1KPW51bGwKJC5QND1udWxsCiQuTkY9bnVsbAokLlRYPW51bGwKJC54Nz1udWxsCiQubnc9
+bnVsbAokLnZ2PW51bGwKJC5Cdj1udWxsCiQuUzY9bnVsbAokLms4PW51bGwKJC5tZz1udWxsCiQuVUQ9
+ITEKJC5YMz1DLk5VCiQueGc9W10KJC54bz1udWxsCiQuQk89bnVsbAokLmx0PW51bGwKJC5FVT1udWxs
+CiQub3I9UC5GbCh1Lk4sdS5aKQokLkk2PW51bGwKJC5GZj1udWxsfSkoKTsoZnVuY3Rpb24gbGF6eUlu
+aXRpYWxpemVycygpe3ZhciB0PWh1bmtIZWxwZXJzLmxhenkKdCgkLCJmYSIsInciLGZ1bmN0aW9uKCl7
+cmV0dXJuIEguWWcoIl8kZGFydF9kYXJ0Q2xvc3VyZSIpfSkKdCgkLCJZMiIsIlVOIixmdW5jdGlvbigp
+e3JldHVybiBILllnKCJfJGRhcnRfanMiKX0pCnQoJCwiVTIiLCJTbiIsZnVuY3Rpb24oKXtyZXR1cm4g
+SC5jTShILlM3KHsKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9fSkpfSkKdCgk
+LCJ4cSIsImxxIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcoeyRtZXRob2QkOm51bGwsCnRvU3Ry
+aW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnQoJCwiUjEiLCJOOSIsZnVuY3Rp
+b24oKXtyZXR1cm4gSC5jTShILlM3KG51bGwpKX0pCnQoJCwiZk4iLCJpSSIsZnVuY3Rpb24oKXtyZXR1
+cm4gSC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7bnVs
+bC4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0p
+CnQoJCwicWkiLCJLZiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHZvaWQgMCkpfSkKdCgkLCJy
+WiIsIlpoIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNFeHBy
+JD0nJGFyZ3VtZW50cyQnCnRyeXsodm9pZCAwKS4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNo
+KHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwia3EiLCJyTiIsZnVuY3Rpb24oKXtyZXR1cm4g
+SC5jTShILk1qKG51bGwpKX0pCnQoJCwidHQiLCJjMyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5j
+dGlvbigpe3RyeXtudWxsLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQo
+JCwiZHQiLCJISyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1qKHZvaWQgMCkpfSkKdCgkLCJBNyIs
+InIxIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dHJ5eyh2b2lkIDApLiRtZXRob2Qk
+fWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwiV2MiLCJ1dCIsZnVuY3Rpb24oKXty
+ZXR1cm4gUC5PaigpfSkKdCgkLCJraCIsInJmIixmdW5jdGlvbigpe3JldHVybiBQLldJKCl9KQp0KCQs
+ImJ0IiwiVjciLGZ1bmN0aW9uKCl7cmV0dXJuIEguRFEoSC5YRihILlZNKFstMiwtMiwtMiwtMiwtMiwt
+MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
+MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMSwtMiwtMiwtMiwtMiwtMiw2MiwtMiw2
+MiwtMiw2Myw1Miw1Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2MSwtMiwtMiwtMiwtMSwtMiwtMiwtMiww
+LDEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIz
+LDI0LDI1LC0yLC0yLC0yLC0yLDYzLC0yLDI2LDI3LDI4LDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3
+LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLC0yLC0yLC0yLC0yLC0yXSx1
+LnQpKSl9KQp0KCQsIk01IiwiT3giLGZ1bmN0aW9uKCl7cmV0dXJuIHR5cGVvZiBwcm9jZXNzIT0idW5k
+ZWZpbmVkIiYmT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHByb2Nlc3MpPT0iW29iamVjdCBw
+cm9jZXNzXSImJnByb2Nlc3MucGxhdGZvcm09PSJ3aW4zMiJ9KQp0KCQsIm1mIiwiejQiLGZ1bmN0aW9u
+KCl7cmV0dXJuIFAubnUoIl5bXFwtXFwuMC05QS1aX2Eten5dKiQiKX0pCnQoJCwiSkciLCJ2WiIsZnVu
+Y3Rpb24oKXtyZXR1cm4gUC51eCgpfSkKdCgkLCJTQyIsIkFOIixmdW5jdGlvbigpe3JldHVybiBQLnRN
+KFsiQSIsIkFCQlIiLCJBQ1JPTllNIiwiQUREUkVTUyIsIkFSRUEiLCJBUlRJQ0xFIiwiQVNJREUiLCJB
+VURJTyIsIkIiLCJCREkiLCJCRE8iLCJCSUciLCJCTE9DS1FVT1RFIiwiQlIiLCJCVVRUT04iLCJDQU5W
+QVMiLCJDQVBUSU9OIiwiQ0VOVEVSIiwiQ0lURSIsIkNPREUiLCJDT0wiLCJDT0xHUk9VUCIsIkNPTU1B
+TkQiLCJEQVRBIiwiREFUQUxJU1QiLCJERCIsIkRFTCIsIkRFVEFJTFMiLCJERk4iLCJESVIiLCJESVYi
+LCJETCIsIkRUIiwiRU0iLCJGSUVMRFNFVCIsIkZJR0NBUFRJT04iLCJGSUdVUkUiLCJGT05UIiwiRk9P
+VEVSIiwiRk9STSIsIkgxIiwiSDIiLCJIMyIsIkg0IiwiSDUiLCJINiIsIkhFQURFUiIsIkhHUk9VUCIs
+IkhSIiwiSSIsIklGUkFNRSIsIklNRyIsIklOUFVUIiwiSU5TIiwiS0JEIiwiTEFCRUwiLCJMRUdFTkQi
+LCJMSSIsIk1BUCIsIk1BUksiLCJNRU5VIiwiTUVURVIiLCJOQVYiLCJOT0JSIiwiT0wiLCJPUFRHUk9V
+UCIsIk9QVElPTiIsIk9VVFBVVCIsIlAiLCJQUkUiLCJQUk9HUkVTUyIsIlEiLCJTIiwiU0FNUCIsIlNF
+Q1RJT04iLCJTRUxFQ1QiLCJTTUFMTCIsIlNPVVJDRSIsIlNQQU4iLCJTVFJJS0UiLCJTVFJPTkciLCJT
+VUIiLCJTVU1NQVJZIiwiU1VQIiwiVEFCTEUiLCJUQk9EWSIsIlREIiwiVEVYVEFSRUEiLCJURk9PVCIs
+IlRIIiwiVEhFQUQiLCJUSU1FIiwiVFIiLCJUUkFDSyIsIlRUIiwiVSIsIlVMIiwiVkFSIiwiVklERU8i
+LCJXQlIiXSx1Lk4pfSkKdCgkLCJWUSIsImhHIixmdW5jdGlvbigpe3JldHVybiBQLm51KCJeXFxTKyQi
+KX0pCnQoJCwid08iLCJvdyIsZnVuY3Rpb24oKXtyZXR1cm4gdS52LmIoUC5ORChzZWxmKSl9KQp0KCQs
+Imt0IiwiUjgiLGZ1bmN0aW9uKCl7cmV0dXJuIEguWWcoIl8kZGFydF9kYXJ0T2JqZWN0Iil9KQp0KCQs
+IkxGIiwia0kiLGZ1bmN0aW9uKCl7cmV0dXJuIGZ1bmN0aW9uIERhcnRPYmplY3QoYSl7dGhpcy5vPWF9
+fSkKdCgkLCJxdCIsInpCIixmdW5jdGlvbigpe3JldHVybiBuZXcgVC5tUSgpfSkKdCgkLCJPbCIsIlVF
+IixmdW5jdGlvbigpe3JldHVybiBQLmhLKEMub2wuZ21XKFcueDMoKSkuaHJlZikuZ2hZKCkucSgwLCJh
+dXRoVG9rZW4iKX0pCnQoJCwiaFQiLCJ5UCIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2Vs
+ZWN0b3IoIi5lZGl0LWxpc3QgLnBhbmVsLWNvbnRlbnQiKX0pCnQoJCwiVzYiLCJoTCIsZnVuY3Rpb24o
+KXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIi5lZGl0LXBhbmVsIC5wYW5lbC1jb250ZW50Iil9
+KQp0KCQsIlRSIiwiRFciLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJmb290
+ZXIiKX0pCnQoJCwiRVkiLCJmaSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3Io
+ImhlYWRlciIpfSkKdCgkLCJhZCIsIkQ5IixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxl
+Y3RvcigiI3VuaXQtbmFtZSIpfSkKdCgkLCJtcSIsIktHIixmdW5jdGlvbigpe3JldHVybiBuZXcgTC5Y
+QSgpfSkKdCgkLCJtTSIsIm5VIixmdW5jdGlvbigpe3JldHVybiBuZXcgTS5sSSgkLkhrKCkpfSkKdCgk
+LCJlOSIsImJEIixmdW5jdGlvbigpe3JldHVybiBuZXcgRS5PRihQLm51KCIvIiksUC5udSgiW14vXSQi
+KSxQLm51KCJeLyIpKX0pCnQoJCwiWUsiLCJLayIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuSVYoUC5u
+dSgiWy9cXFxcXSIpLFAubnUoIlteL1xcXFxdJCIpLFAubnUoIl4oXFxcXFxcXFxbXlxcXFxdK1xcXFxb
+XlxcXFwvXSt8W2EtekEtWl06Wy9cXFxcXSkiKSxQLm51KCJeWy9cXFxcXSg/IVsvXFxcXF0pIikpfSkK
+dCgkLCJhQyIsIkViIixmdW5jdGlvbigpe3JldHVybiBuZXcgRi5ydShQLm51KCIvIiksUC5udSgiKF5b
+YS16QS1aXVstKy5hLXpBLVpcXGRdKjovL3xbXi9dKSQiKSxQLm51KCJbYS16QS1aXVstKy5hLXpBLVpc
+XGRdKjovL1teL10qIiksUC5udSgiXi8iKSl9KQp0KCQsImxzIiwiSGsiLGZ1bmN0aW9uKCl7cmV0dXJu
+IE8uUmgoKX0pfSkoKTsoZnVuY3Rpb24gbmF0aXZlU3VwcG9ydCgpeyFmdW5jdGlvbigpe3ZhciB0PWZ1
+bmN0aW9uKGEpe3ZhciBuPXt9Cm5bYV09MQpyZXR1cm4gT2JqZWN0LmtleXMoaHVua0hlbHBlcnMuY29u
+dmVydFRvRmFzdE9iamVjdChuKSlbMF19CnYuZ2V0SXNvbGF0ZVRhZz1mdW5jdGlvbihhKXtyZXR1cm4g
+dCgiX19fZGFydF8iK2Erdi5pc29sYXRlVGFnKX0KdmFyIHM9Il9fX2RhcnRfaXNvbGF0ZV90YWdzXyIK
+dmFyIHI9T2JqZWN0W3NdfHwoT2JqZWN0W3NdPU9iamVjdC5jcmVhdGUobnVsbCkpCnZhciBxPSJfWnhZ
+eFgiCmZvcih2YXIgcD0wOztwKyspe3ZhciBvPXQocSsiXyIrcCsiXyIpCmlmKCEobyBpbiByKSl7cltv
+XT0xCnYuaXNvbGF0ZVRhZz1vCmJyZWFrfX12LmRpc3BhdGNoUHJvcGVydHlOYW1lPXYuZ2V0SXNvbGF0
+ZVRhZygiZGlzcGF0Y2hfcmVjb3JkIil9KCkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVJbnRlcmNlcHRv
+cnNCeVRhZyh7QW5pbWF0aW9uRWZmZWN0UmVhZE9ubHk6Si52QixBbmltYXRpb25FZmZlY3RUaW1pbmc6
+Si52QixBbmltYXRpb25FZmZlY3RUaW1pbmdSZWFkT25seTpKLnZCLEFuaW1hdGlvblRpbWVsaW5lOkou
+dkIsQW5pbWF0aW9uV29ya2xldEdsb2JhbFNjb3BlOkoudkIsQXV0aGVudGljYXRvckFzc2VydGlvblJl
+c3BvbnNlOkoudkIsQXV0aGVudGljYXRvckF0dGVzdGF0aW9uUmVzcG9uc2U6Si52QixBdXRoZW50aWNh
+dG9yUmVzcG9uc2U6Si52QixCYWNrZ3JvdW5kRmV0Y2hGZXRjaDpKLnZCLEJhY2tncm91bmRGZXRjaE1h
+bmFnZXI6Si52QixCYWNrZ3JvdW5kRmV0Y2hTZXR0bGVkRmV0Y2g6Si52QixCYXJQcm9wOkoudkIsQmFy
+Y29kZURldGVjdG9yOkoudkIsQm9keTpKLnZCLEJ1ZGdldFN0YXRlOkoudkIsQ2FjaGVTdG9yYWdlOkou
+dkIsQ2FudmFzR3JhZGllbnQ6Si52QixDYW52YXNQYXR0ZXJuOkoudkIsQ2FudmFzUmVuZGVyaW5nQ29u
+dGV4dDJEOkoudkIsQ2xpZW50OkoudkIsQ2xpZW50czpKLnZCLENvb2tpZVN0b3JlOkoudkIsQ29vcmRp
+bmF0ZXM6Si52QixDcmVkZW50aWFsOkoudkIsQ3JlZGVudGlhbFVzZXJEYXRhOkoudkIsQ3JlZGVudGlh
+bHNDb250YWluZXI6Si52QixDcnlwdG86Si52QixDcnlwdG9LZXk6Si52QixDU1M6Si52QixDU1NWYXJp
+YWJsZVJlZmVyZW5jZVZhbHVlOkoudkIsQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5OkoudkIsRGF0YVRyYW5z
+ZmVyOkoudkIsRGF0YVRyYW5zZmVySXRlbTpKLnZCLERlcHJlY2F0ZWRTdG9yYWdlSW5mbzpKLnZCLERl
+cHJlY2F0ZWRTdG9yYWdlUXVvdGE6Si52QixEZXByZWNhdGlvblJlcG9ydDpKLnZCLERldGVjdGVkQmFy
+Y29kZTpKLnZCLERldGVjdGVkRmFjZTpKLnZCLERldGVjdGVkVGV4dDpKLnZCLERldmljZUFjY2VsZXJh
+dGlvbjpKLnZCLERldmljZVJvdGF0aW9uUmF0ZTpKLnZCLERpcmVjdG9yeVJlYWRlcjpKLnZCLERvY3Vt
+ZW50T3JTaGFkb3dSb290OkoudkIsRG9jdW1lbnRUaW1lbGluZTpKLnZCLERPTUVycm9yOkoudkIsRE9N
+SW1wbGVtZW50YXRpb246Si52QixJdGVyYXRvcjpKLnZCLERPTU1hdHJpeDpKLnZCLERPTU1hdHJpeFJl
+YWRPbmx5OkoudkIsRE9NUGFyc2VyOkoudkIsRE9NUG9pbnQ6Si52QixET01Qb2ludFJlYWRPbmx5Okou
+dkIsRE9NUXVhZDpKLnZCLERPTVN0cmluZ01hcDpKLnZCLEV4dGVybmFsOkoudkIsRmFjZURldGVjdG9y
+OkoudkIsRmVkZXJhdGVkQ3JlZGVudGlhbDpKLnZCLERPTUZpbGVTeXN0ZW06Si52QixGb250RmFjZTpK
+LnZCLEZvbnRGYWNlU291cmNlOkoudkIsRm9ybURhdGE6Si52QixHYW1lcGFkUG9zZTpKLnZCLEdlb2xv
+Y2F0aW9uOkoudkIsUG9zaXRpb246Si52QixIZWFkZXJzOkoudkIsSFRNTEh5cGVybGlua0VsZW1lbnRV
+dGlsczpKLnZCLElkbGVEZWFkbGluZTpKLnZCLEltYWdlQml0bWFwOkoudkIsSW1hZ2VCaXRtYXBSZW5k
+ZXJpbmdDb250ZXh0OkoudkIsSW1hZ2VDYXB0dXJlOkoudkIsSW5wdXREZXZpY2VDYXBhYmlsaXRpZXM6
+Si52QixJbnRlcnNlY3Rpb25PYnNlcnZlcjpKLnZCLEludGVyc2VjdGlvbk9ic2VydmVyRW50cnk6Si52
+QixJbnRlcnZlbnRpb25SZXBvcnQ6Si52QixLZXlmcmFtZUVmZmVjdDpKLnZCLEtleWZyYW1lRWZmZWN0
+UmVhZE9ubHk6Si52QixNZWRpYUNhcGFiaWxpdGllczpKLnZCLE1lZGlhQ2FwYWJpbGl0aWVzSW5mbzpK
+LnZCLE1lZGlhRGV2aWNlSW5mbzpKLnZCLE1lZGlhRXJyb3I6Si52QixNZWRpYUtleVN0YXR1c01hcDpK
+LnZCLE1lZGlhS2V5U3lzdGVtQWNjZXNzOkoudkIsTWVkaWFLZXlzOkoudkIsTWVkaWFLZXlzUG9saWN5
+OkoudkIsTWVkaWFNZXRhZGF0YTpKLnZCLE1lZGlhU2Vzc2lvbjpKLnZCLE1lZGlhU2V0dGluZ3NSYW5n
+ZTpKLnZCLE1lbW9yeUluZm86Si52QixNZXNzYWdlQ2hhbm5lbDpKLnZCLE1ldGFkYXRhOkoudkIsTXV0
+YXRpb25PYnNlcnZlcjpKLnZCLFdlYktpdE11dGF0aW9uT2JzZXJ2ZXI6Si52QixNdXRhdGlvblJlY29y
+ZDpKLnZCLE5hdmlnYXRpb25QcmVsb2FkTWFuYWdlcjpKLnZCLE5hdmlnYXRvcjpKLnZCLE5hdmlnYXRv
+ckF1dG9tYXRpb25JbmZvcm1hdGlvbjpKLnZCLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTpKLnZC
+LE5hdmlnYXRvckNvb2tpZXM6Si52QixOYXZpZ2F0b3JVc2VyTWVkaWFFcnJvcjpKLnZCLE5vZGVGaWx0
+ZXI6Si52QixOb2RlSXRlcmF0b3I6Si52QixOb25Eb2N1bWVudFR5cGVDaGlsZE5vZGU6Si52QixOb25F
+bGVtZW50UGFyZW50Tm9kZTpKLnZCLE5vbmNlZEVsZW1lbnQ6Si52QixPZmZzY3JlZW5DYW52YXNSZW5k
+ZXJpbmdDb250ZXh0MkQ6Si52QixPdmVyY29uc3RyYWluZWRFcnJvcjpKLnZCLFBhaW50UmVuZGVyaW5n
+Q29udGV4dDJEOkoudkIsUGFpbnRTaXplOkoudkIsUGFpbnRXb3JrbGV0R2xvYmFsU2NvcGU6Si52QixQ
+YXNzd29yZENyZWRlbnRpYWw6Si52QixQYXRoMkQ6Si52QixQYXltZW50QWRkcmVzczpKLnZCLFBheW1l
+bnRJbnN0cnVtZW50czpKLnZCLFBheW1lbnRNYW5hZ2VyOkoudkIsUGF5bWVudFJlc3BvbnNlOkoudkIs
+UGVyZm9ybWFuY2VFbnRyeTpKLnZCLFBlcmZvcm1hbmNlTG9uZ1Rhc2tUaW1pbmc6Si52QixQZXJmb3Jt
+YW5jZU1hcms6Si52QixQZXJmb3JtYW5jZU1lYXN1cmU6Si52QixQZXJmb3JtYW5jZU5hdmlnYXRpb246
+Si52QixQZXJmb3JtYW5jZU5hdmlnYXRpb25UaW1pbmc6Si52QixQZXJmb3JtYW5jZU9ic2VydmVyOkou
+dkIsUGVyZm9ybWFuY2VPYnNlcnZlckVudHJ5TGlzdDpKLnZCLFBlcmZvcm1hbmNlUGFpbnRUaW1pbmc6
+Si52QixQZXJmb3JtYW5jZVJlc291cmNlVGltaW5nOkoudkIsUGVyZm9ybWFuY2VTZXJ2ZXJUaW1pbmc6
+Si52QixQZXJmb3JtYW5jZVRpbWluZzpKLnZCLFBlcm1pc3Npb25zOkoudkIsUGhvdG9DYXBhYmlsaXRp
+ZXM6Si52QixQb3NpdGlvbkVycm9yOkoudkIsUHJlc2VudGF0aW9uOkoudkIsUHJlc2VudGF0aW9uUmVj
+ZWl2ZXI6Si52QixQdWJsaWNLZXlDcmVkZW50aWFsOkoudkIsUHVzaE1hbmFnZXI6Si52QixQdXNoTWVz
+c2FnZURhdGE6Si52QixQdXNoU3Vic2NyaXB0aW9uOkoudkIsUHVzaFN1YnNjcmlwdGlvbk9wdGlvbnM6
+Si52QixSYW5nZTpKLnZCLFJlbGF0ZWRBcHBsaWNhdGlvbjpKLnZCLFJlcG9ydEJvZHk6Si52QixSZXBv
+cnRpbmdPYnNlcnZlcjpKLnZCLFJlc2l6ZU9ic2VydmVyOkoudkIsUmVzaXplT2JzZXJ2ZXJFbnRyeTpK
+LnZCLFJUQ0NlcnRpZmljYXRlOkoudkIsUlRDSWNlQ2FuZGlkYXRlOkoudkIsbW96UlRDSWNlQ2FuZGlk
+YXRlOkoudkIsUlRDTGVnYWN5U3RhdHNSZXBvcnQ6Si52QixSVENSdHBDb250cmlidXRpbmdTb3VyY2U6
+Si52QixSVENSdHBSZWNlaXZlcjpKLnZCLFJUQ1J0cFNlbmRlcjpKLnZCLFJUQ1Nlc3Npb25EZXNjcmlw
+dGlvbjpKLnZCLG1velJUQ1Nlc3Npb25EZXNjcmlwdGlvbjpKLnZCLFJUQ1N0YXRzUmVzcG9uc2U6Si52
+QixTY3JlZW46Si52QixTY3JvbGxTdGF0ZTpKLnZCLFNjcm9sbFRpbWVsaW5lOkoudkIsU2VsZWN0aW9u
+OkoudkIsU2hhcmVkQXJyYXlCdWZmZXI6Si52QixTcGVlY2hSZWNvZ25pdGlvbkFsdGVybmF0aXZlOkou
+dkIsU3BlZWNoU3ludGhlc2lzVm9pY2U6Si52QixTdGF0aWNSYW5nZTpKLnZCLFN0b3JhZ2VNYW5hZ2Vy
+OkoudkIsU3R5bGVNZWRpYTpKLnZCLFN0eWxlUHJvcGVydHlNYXA6Si52QixTdHlsZVByb3BlcnR5TWFw
+UmVhZG9ubHk6Si52QixTeW5jTWFuYWdlcjpKLnZCLFRhc2tBdHRyaWJ1dGlvblRpbWluZzpKLnZCLFRl
+eHREZXRlY3RvcjpKLnZCLFRleHRNZXRyaWNzOkoudkIsVHJhY2tEZWZhdWx0OkoudkIsVHJlZVdhbGtl
+cjpKLnZCLFRydXN0ZWRIVE1MOkoudkIsVHJ1c3RlZFNjcmlwdFVSTDpKLnZCLFRydXN0ZWRVUkw6Si52
+QixVbmRlcmx5aW5nU291cmNlQmFzZTpKLnZCLFVSTFNlYXJjaFBhcmFtczpKLnZCLFZSQ29vcmRpbmF0
+ZVN5c3RlbTpKLnZCLFZSRGlzcGxheUNhcGFiaWxpdGllczpKLnZCLFZSRXllUGFyYW1ldGVyczpKLnZC
+LFZSRnJhbWVEYXRhOkoudkIsVlJGcmFtZU9mUmVmZXJlbmNlOkoudkIsVlJQb3NlOkoudkIsVlJTdGFn
+ZUJvdW5kczpKLnZCLFZSU3RhZ2VCb3VuZHNQb2ludDpKLnZCLFZSU3RhZ2VQYXJhbWV0ZXJzOkoudkIs
+VmFsaWRpdHlTdGF0ZTpKLnZCLFZpZGVvUGxheWJhY2tRdWFsaXR5OkoudkIsVmlkZW9UcmFjazpKLnZC
+LFZUVFJlZ2lvbjpKLnZCLFdpbmRvd0NsaWVudDpKLnZCLFdvcmtsZXRBbmltYXRpb246Si52QixXb3Jr
+bGV0R2xvYmFsU2NvcGU6Si52QixYUGF0aEV2YWx1YXRvcjpKLnZCLFhQYXRoRXhwcmVzc2lvbjpKLnZC
+LFhQYXRoTlNSZXNvbHZlcjpKLnZCLFhQYXRoUmVzdWx0OkoudkIsWE1MU2VyaWFsaXplcjpKLnZCLFhT
+TFRQcm9jZXNzb3I6Si52QixCbHVldG9vdGg6Si52QixCbHVldG9vdGhDaGFyYWN0ZXJpc3RpY1Byb3Bl
+cnRpZXM6Si52QixCbHVldG9vdGhSZW1vdGVHQVRUU2VydmVyOkoudkIsQmx1ZXRvb3RoUmVtb3RlR0FU
+VFNlcnZpY2U6Si52QixCbHVldG9vdGhVVUlEOkoudkIsQnVkZ2V0U2VydmljZTpKLnZCLENhY2hlOkou
+dkIsRE9NRmlsZVN5c3RlbVN5bmM6Si52QixEaXJlY3RvcnlFbnRyeVN5bmM6Si52QixEaXJlY3RvcnlS
+ZWFkZXJTeW5jOkoudkIsRW50cnlTeW5jOkoudkIsRmlsZUVudHJ5U3luYzpKLnZCLEZpbGVSZWFkZXJT
+eW5jOkoudkIsRmlsZVdyaXRlclN5bmM6Si52QixIVE1MQWxsQ29sbGVjdGlvbjpKLnZCLE1vam86Si52
+QixNb2pvSGFuZGxlOkoudkIsTW9qb1dhdGNoZXI6Si52QixORkM6Si52QixQYWdlUG9wdXBDb250cm9s
+bGVyOkoudkIsUmVwb3J0OkoudkIsUmVxdWVzdDpKLnZCLFJlc3BvbnNlOkoudkIsU3VidGxlQ3J5cHRv
+OkoudkIsVVNCQWx0ZXJuYXRlSW50ZXJmYWNlOkoudkIsVVNCQ29uZmlndXJhdGlvbjpKLnZCLFVTQkRl
+dmljZTpKLnZCLFVTQkVuZHBvaW50OkoudkIsVVNCSW5UcmFuc2ZlclJlc3VsdDpKLnZCLFVTQkludGVy
+ZmFjZTpKLnZCLFVTQklzb2Nocm9ub3VzSW5UcmFuc2ZlclBhY2tldDpKLnZCLFVTQklzb2Nocm9ub3Vz
+SW5UcmFuc2ZlclJlc3VsdDpKLnZCLFVTQklzb2Nocm9ub3VzT3V0VHJhbnNmZXJQYWNrZXQ6Si52QixV
+U0JJc29jaHJvbm91c091dFRyYW5zZmVyUmVzdWx0OkoudkIsVVNCT3V0VHJhbnNmZXJSZXN1bHQ6Si52
+QixXb3JrZXJMb2NhdGlvbjpKLnZCLFdvcmtlck5hdmlnYXRvcjpKLnZCLFdvcmtsZXQ6Si52QixJREJG
+YWN0b3J5OkoudkIsSURCSW5kZXg6Si52QixJREJPYmplY3RTdG9yZTpKLnZCLElEQk9ic2VydmVyOkou
+dkIsSURCT2JzZXJ2ZXJDaGFuZ2VzOkoudkIsU1ZHQW5pbWF0ZWRBbmdsZTpKLnZCLFNWR0FuaW1hdGVk
+Qm9vbGVhbjpKLnZCLFNWR0FuaW1hdGVkRW51bWVyYXRpb246Si52QixTVkdBbmltYXRlZEludGVnZXI6
+Si52QixTVkdBbmltYXRlZExlbmd0aDpKLnZCLFNWR0FuaW1hdGVkTGVuZ3RoTGlzdDpKLnZCLFNWR0Fu
+aW1hdGVkTnVtYmVyOkoudkIsU1ZHQW5pbWF0ZWROdW1iZXJMaXN0OkoudkIsU1ZHQW5pbWF0ZWRQcmVz
+ZXJ2ZUFzcGVjdFJhdGlvOkoudkIsU1ZHQW5pbWF0ZWRSZWN0OkoudkIsU1ZHQW5pbWF0ZWRTdHJpbmc6
+Si52QixTVkdBbmltYXRlZFRyYW5zZm9ybUxpc3Q6Si52QixTVkdNYXRyaXg6Si52QixTVkdQb2ludDpK
+LnZCLFNWR1ByZXNlcnZlQXNwZWN0UmF0aW86Si52QixTVkdSZWN0OkoudkIsU1ZHVW5pdFR5cGVzOkou
+dkIsQXVkaW9MaXN0ZW5lcjpKLnZCLEF1ZGlvVHJhY2s6Si52QixBdWRpb1dvcmtsZXRHbG9iYWxTY29w
+ZTpKLnZCLEF1ZGlvV29ya2xldFByb2Nlc3NvcjpKLnZCLFBlcmlvZGljV2F2ZTpKLnZCLFdlYkdMQWN0
+aXZlSW5mbzpKLnZCLEFOR0xFSW5zdGFuY2VkQXJyYXlzOkoudkIsQU5HTEVfaW5zdGFuY2VkX2FycmF5
+czpKLnZCLFdlYkdMQnVmZmVyOkoudkIsV2ViR0xDYW52YXM6Si52QixXZWJHTENvbG9yQnVmZmVyRmxv
+YXQ6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlQVNUQzpKLnZCLFdlYkdMQ29tcHJlc3NlZFRleHR1
+cmVBVEM6Si52QixXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfYXRjOkoudkIsV2ViR0xDb21wcmVzc2Vk
+VGV4dHVyZUVUQzE6Si52QixXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfZXRjMTpKLnZCLFdlYkdMQ29t
+cHJlc3NlZFRleHR1cmVFVEM6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlUFZSVEM6Si52QixXRUJH
+TF9jb21wcmVzc2VkX3RleHR1cmVfcHZydGM6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlUzNUQzpK
+LnZCLFdFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9zM3RjOkoudkIsV2ViR0xDb21wcmVzc2VkVGV4dHVy
+ZVMzVENzUkdCOkoudkIsV2ViR0xEZWJ1Z1JlbmRlcmVySW5mbzpKLnZCLFdFQkdMX2RlYnVnX3JlbmRl
+cmVyX2luZm86Si52QixXZWJHTERlYnVnU2hhZGVyczpKLnZCLFdFQkdMX2RlYnVnX3NoYWRlcnM6Si52
+QixXZWJHTERlcHRoVGV4dHVyZTpKLnZCLFdFQkdMX2RlcHRoX3RleHR1cmU6Si52QixXZWJHTERyYXdC
+dWZmZXJzOkoudkIsV0VCR0xfZHJhd19idWZmZXJzOkoudkIsRVhUc1JHQjpKLnZCLEVYVF9zUkdCOkou
+dkIsRVhUQmxlbmRNaW5NYXg6Si52QixFWFRfYmxlbmRfbWlubWF4OkoudkIsRVhUQ29sb3JCdWZmZXJG
+bG9hdDpKLnZCLEVYVENvbG9yQnVmZmVySGFsZkZsb2F0OkoudkIsRVhURGlzam9pbnRUaW1lclF1ZXJ5
+OkoudkIsRVhURGlzam9pbnRUaW1lclF1ZXJ5V2ViR0wyOkoudkIsRVhURnJhZ0RlcHRoOkoudkIsRVhU
+X2ZyYWdfZGVwdGg6Si52QixFWFRTaGFkZXJUZXh0dXJlTE9EOkoudkIsRVhUX3NoYWRlcl90ZXh0dXJl
+X2xvZDpKLnZCLEVYVFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYzpKLnZCLEVYVF90ZXh0dXJlX2ZpbHRl
+cl9hbmlzb3Ryb3BpYzpKLnZCLFdlYkdMRnJhbWVidWZmZXI6Si52QixXZWJHTEdldEJ1ZmZlclN1YkRh
+dGFBc3luYzpKLnZCLFdlYkdMTG9zZUNvbnRleHQ6Si52QixXZWJHTEV4dGVuc2lvbkxvc2VDb250ZXh0
+OkoudkIsV0VCR0xfbG9zZV9jb250ZXh0OkoudkIsT0VTRWxlbWVudEluZGV4VWludDpKLnZCLE9FU19l
+bGVtZW50X2luZGV4X3VpbnQ6Si52QixPRVNTdGFuZGFyZERlcml2YXRpdmVzOkoudkIsT0VTX3N0YW5k
+YXJkX2Rlcml2YXRpdmVzOkoudkIsT0VTVGV4dHVyZUZsb2F0OkoudkIsT0VTX3RleHR1cmVfZmxvYXQ6
+Si52QixPRVNUZXh0dXJlRmxvYXRMaW5lYXI6Si52QixPRVNfdGV4dHVyZV9mbG9hdF9saW5lYXI6Si52
+QixPRVNUZXh0dXJlSGFsZkZsb2F0OkoudkIsT0VTX3RleHR1cmVfaGFsZl9mbG9hdDpKLnZCLE9FU1Rl
+eHR1cmVIYWxmRmxvYXRMaW5lYXI6Si52QixPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0X2xpbmVhcjpKLnZC
+LE9FU1ZlcnRleEFycmF5T2JqZWN0OkoudkIsT0VTX3ZlcnRleF9hcnJheV9vYmplY3Q6Si52QixXZWJH
+TFByb2dyYW06Si52QixXZWJHTFF1ZXJ5OkoudkIsV2ViR0xSZW5kZXJidWZmZXI6Si52QixXZWJHTFJl
+bmRlcmluZ0NvbnRleHQ6Si52QixXZWJHTDJSZW5kZXJpbmdDb250ZXh0OkoudkIsV2ViR0xTYW1wbGVy
+OkoudkIsV2ViR0xTaGFkZXI6Si52QixXZWJHTFNoYWRlclByZWNpc2lvbkZvcm1hdDpKLnZCLFdlYkdM
+U3luYzpKLnZCLFdlYkdMVGV4dHVyZTpKLnZCLFdlYkdMVGltZXJRdWVyeUVYVDpKLnZCLFdlYkdMVHJh
+bnNmb3JtRmVlZGJhY2s6Si52QixXZWJHTFVuaWZvcm1Mb2NhdGlvbjpKLnZCLFdlYkdMVmVydGV4QXJy
+YXlPYmplY3Q6Si52QixXZWJHTFZlcnRleEFycmF5T2JqZWN0T0VTOkoudkIsV2ViR0w6Si52QixXZWJH
+TDJSZW5kZXJpbmdDb250ZXh0QmFzZTpKLnZCLERhdGFiYXNlOkoudkIsU1FMRXJyb3I6Si52QixTUUxS
+ZXN1bHRTZXQ6Si52QixTUUxUcmFuc2FjdGlvbjpKLnZCLEFycmF5QnVmZmVyOkguV1osQXJyYXlCdWZm
+ZXJWaWV3OkguRVQsRGF0YVZpZXc6SC5kZixGbG9hdDMyQXJyYXk6SC5EZyxGbG9hdDY0QXJyYXk6SC5E
+ZyxJbnQxNkFycmF5OkgueGosSW50MzJBcnJheTpILmRFLEludDhBcnJheTpILlpBLFVpbnQxNkFycmF5
+Okgud2YsVWludDMyQXJyYXk6SC5QcSxVaW50OENsYW1wZWRBcnJheTpILmVFLENhbnZhc1BpeGVsQXJy
+YXk6SC5lRSxVaW50OEFycmF5OkguVjYsSFRNTEF1ZGlvRWxlbWVudDpXLnFFLEhUTUxCUkVsZW1lbnQ6
+Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhUTUxDb250ZW50RWxlbWVudDpXLnFFLEhUTUxETGlz
+dEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUxpc3RFbGVtZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50Olcu
+cUUsSFRNTERpYWxvZ0VsZW1lbnQ6Vy5xRSxIVE1MRGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1l
+bnQ6Vy5xRSxIVE1MRmllbGRTZXRFbGVtZW50OlcucUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFk
+RWxlbWVudDpXLnFFLEhUTUxIZWFkaW5nRWxlbWVudDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhU
+TUxJRnJhbWVFbGVtZW50OlcucUUsSFRNTEltYWdlRWxlbWVudDpXLnFFLEhUTUxMYWJlbEVsZW1lbnQ6
+Vy5xRSxIVE1MTGVnZW5kRWxlbWVudDpXLnFFLEhUTUxMaW5rRWxlbWVudDpXLnFFLEhUTUxNYXBFbGVt
+ZW50OlcucUUsSFRNTE1lZGlhRWxlbWVudDpXLnFFLEhUTUxNZW51RWxlbWVudDpXLnFFLEhUTUxNZXRh
+RWxlbWVudDpXLnFFLEhUTUxNb2RFbGVtZW50OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxP
+YmplY3RFbGVtZW50OlcucUUsSFRNTE9wdEdyb3VwRWxlbWVudDpXLnFFLEhUTUxQaWN0dXJlRWxlbWVu
+dDpXLnFFLEhUTUxQcmVFbGVtZW50OlcucUUsSFRNTFF1b3RlRWxlbWVudDpXLnFFLEhUTUxTY3JpcHRF
+bGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxIVE1MU2xvdEVsZW1lbnQ6Vy5xRSxIVE1M
+U291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVudDpXLnFFLEhUTUxTdHlsZUVsZW1lbnQ6Vy5x
+RSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNlbGxFbGVtZW50OlcucUUsSFRN
+TFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlSGVhZGVyQ2VsbEVsZW1lbnQ6Vy5xRSxI
+VE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRpbWVFbGVtZW50OlcucUUsSFRNTFRpdGxlRWxlbWVu
+dDpXLnFFLEhUTUxUcmFja0VsZW1lbnQ6Vy5xRSxIVE1MVUxpc3RFbGVtZW50OlcucUUsSFRNTFVua25v
+d25FbGVtZW50OlcucUUsSFRNTFZpZGVvRWxlbWVudDpXLnFFLEhUTUxEaXJlY3RvcnlFbGVtZW50Olcu
+cUUsSFRNTEZvbnRFbGVtZW50OlcucUUsSFRNTEZyYW1lRWxlbWVudDpXLnFFLEhUTUxGcmFtZVNldEVs
+ZW1lbnQ6Vy5xRSxIVE1MTWFycXVlZUVsZW1lbnQ6Vy5xRSxIVE1MRWxlbWVudDpXLnFFLEFjY2Vzc2li
+bGVOb2RlTGlzdDpXLlllLEhUTUxBbmNob3JFbGVtZW50OlcuR2gsSFRNTEFyZWFFbGVtZW50OlcuZlks
+SFRNTEJhc2VFbGVtZW50OlcubkIsQmxvYjpXLkF6LEJsdWV0b290aFJlbW90ZUdBVFREZXNjcmlwdG9y
+OlcuUFUsSFRNTEJvZHlFbGVtZW50OlcuUVAsSFRNTEJ1dHRvbkVsZW1lbnQ6Vy5JRixDREFUQVNlY3Rp
+b246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29tbWVudDpXLm54LFByb2Nlc3NpbmdJbnN0cnVjdGlv
+bjpXLm54LFRleHQ6Vy5ueCxDU1NLZXl3b3JkVmFsdWU6Vy5SZCxDU1NOdW1lcmljVmFsdWU6Vy5rUixD
+U1NQZXJzcGVjdGl2ZTpXLlRmLENTU0NoYXJzZXRSdWxlOlcubHcsQ1NTQ29uZGl0aW9uUnVsZTpXLmx3
+LENTU0ZvbnRGYWNlUnVsZTpXLmx3LENTU0dyb3VwaW5nUnVsZTpXLmx3LENTU0ltcG9ydFJ1bGU6Vy5s
+dyxDU1NLZXlmcmFtZVJ1bGU6Vy5sdyxNb3pDU1NLZXlmcmFtZVJ1bGU6Vy5sdyxXZWJLaXRDU1NLZXlm
+cmFtZVJ1bGU6Vy5sdyxDU1NLZXlmcmFtZXNSdWxlOlcubHcsTW96Q1NTS2V5ZnJhbWVzUnVsZTpXLmx3
+LFdlYktpdENTU0tleWZyYW1lc1J1bGU6Vy5sdyxDU1NNZWRpYVJ1bGU6Vy5sdyxDU1NOYW1lc3BhY2VS
+dWxlOlcubHcsQ1NTUGFnZVJ1bGU6Vy5sdyxDU1NSdWxlOlcubHcsQ1NTU3R5bGVSdWxlOlcubHcsQ1NT
+U3VwcG9ydHNSdWxlOlcubHcsQ1NTVmlld3BvcnRSdWxlOlcubHcsQ1NTU3R5bGVEZWNsYXJhdGlvbjpX
+Lm9KLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOlcub0osQ1NTMlByb3BlcnRpZXM6Vy5vSixDU1NJbWFnZVZh
+bHVlOlcuQncsQ1NTUG9zaXRpb25WYWx1ZTpXLkJ3LENTU1Jlc291cmNlVmFsdWU6Vy5CdyxDU1NVUkxJ
+bWFnZVZhbHVlOlcuQncsQ1NTU3R5bGVWYWx1ZTpXLkJ3LENTU01hdHJpeENvbXBvbmVudDpXLm80LENT
+U1JvdGF0aW9uOlcubzQsQ1NTU2NhbGU6Vy5vNCxDU1NTa2V3OlcubzQsQ1NTVHJhbnNsYXRpb246Vy5v
+NCxDU1NUcmFuc2Zvcm1Db21wb25lbnQ6Vy5vNCxDU1NUcmFuc2Zvcm1WYWx1ZTpXLkhTLENTU1VuaXRW
+YWx1ZTpXLlZvLENTU1VucGFyc2VkVmFsdWU6Vy5GaCxIVE1MRGF0YUVsZW1lbnQ6Vy5jeCxEYXRhVHJh
+bnNmZXJJdGVtTGlzdDpXLlNiLFhNTERvY3VtZW50OlcuUUYsRG9jdW1lbnQ6Vy5RRixET01FeGNlcHRp
+b246Vy5OaCxDbGllbnRSZWN0TGlzdDpXLkZ2LERPTVJlY3RMaXN0OlcuRnYsRE9NUmVjdFJlYWRPbmx5
+OlcuSUIsRE9NU3RyaW5nTGlzdDpXLllsLERPTVRva2VuTGlzdDpXLm43LEVsZW1lbnQ6Vy5jdixEaXJl
+Y3RvcnlFbnRyeTpXLlFJLEVudHJ5OlcuUUksRmlsZUVudHJ5OlcuUUksQWJvcnRQYXltZW50RXZlbnQ6
+Vy5lYSxBbmltYXRpb25FdmVudDpXLmVhLEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6Vy5lYSxBcHBsaWNh
+dGlvbkNhY2hlRXJyb3JFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6Vy5lYSxCYWNr
+Z3JvdW5kRmV0Y2hFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDpXLmVhLEJhY2tncm91
+bmRGZXRjaGVkRXZlbnQ6Vy5lYSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZlbnQ6Vy5lYSxCZWZvcmVVbmxv
+YWRFdmVudDpXLmVhLEJsb2JFdmVudDpXLmVhLENhbk1ha2VQYXltZW50RXZlbnQ6Vy5lYSxDbGlwYm9h
+cmRFdmVudDpXLmVhLENsb3NlRXZlbnQ6Vy5lYSxDdXN0b21FdmVudDpXLmVhLERldmljZU1vdGlvbkV2
+ZW50OlcuZWEsRGV2aWNlT3JpZW50YXRpb25FdmVudDpXLmVhLEVycm9yRXZlbnQ6Vy5lYSxFeHRlbmRh
+YmxlRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OlcuZWEsRmV0Y2hFdmVudDpXLmVhLEZv
+bnRGYWNlU2V0TG9hZEV2ZW50OlcuZWEsRm9yZWlnbkZldGNoRXZlbnQ6Vy5lYSxHYW1lcGFkRXZlbnQ6
+Vy5lYSxIYXNoQ2hhbmdlRXZlbnQ6Vy5lYSxJbnN0YWxsRXZlbnQ6Vy5lYSxNZWRpYUVuY3J5cHRlZEV2
+ZW50OlcuZWEsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6Vy5lYSxNZWRpYVF1ZXJ5TGlzdEV2ZW50OlcuZWEs
+TWVkaWFTdHJlYW1FdmVudDpXLmVhLE1lZGlhU3RyZWFtVHJhY2tFdmVudDpXLmVhLE1lc3NhZ2VFdmVu
+dDpXLmVhLE1JRElDb25uZWN0aW9uRXZlbnQ6Vy5lYSxNSURJTWVzc2FnZUV2ZW50OlcuZWEsTXV0YXRp
+b25FdmVudDpXLmVhLE5vdGlmaWNhdGlvbkV2ZW50OlcuZWEsUGFnZVRyYW5zaXRpb25FdmVudDpXLmVh
+LFBheW1lbnRSZXF1ZXN0RXZlbnQ6Vy5lYSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OlcuZWEsUG9w
+U3RhdGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDpXLmVhLFBy
+ZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OlcuZWEsUHJvbWlzZVJlamVjdGlvbkV2ZW50Olcu
+ZWEsUHVzaEV2ZW50OlcuZWEsUlRDRGF0YUNoYW5uZWxFdmVudDpXLmVhLFJUQ0RUTUZUb25lQ2hhbmdl
+RXZlbnQ6Vy5lYSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OlcuZWEsUlRDVHJhY2tFdmVudDpXLmVh
+LFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6Vy5lYSxTZW5zb3JFcnJvckV2ZW50OlcuZWEsU3Bl
+ZWNoUmVjb2duaXRpb25FcnJvcjpXLmVhLFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6Vy5lYSxTcGVlY2hT
+eW50aGVzaXNFdmVudDpXLmVhLFN5bmNFdmVudDpXLmVhLFRyYWNrRXZlbnQ6Vy5lYSxUcmFuc2l0aW9u
+RXZlbnQ6Vy5lYSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxWUkRldmljZUV2ZW50OlcuZWEsVlJE
+aXNwbGF5RXZlbnQ6Vy5lYSxWUlNlc3Npb25FdmVudDpXLmVhLE1vam9JbnRlcmZhY2VSZXF1ZXN0RXZl
+bnQ6Vy5lYSxVU0JDb25uZWN0aW9uRXZlbnQ6Vy5lYSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6Vy5lYSxB
+dWRpb1Byb2Nlc3NpbmdFdmVudDpXLmVhLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDpXLmVhLFdl
+YkdMQ29udGV4dEV2ZW50OlcuZWEsRXZlbnQ6Vy5lYSxJbnB1dEV2ZW50OlcuZWEsQWJzb2x1dGVPcmll
+bnRhdGlvblNlbnNvcjpXLkQwLEFjY2VsZXJvbWV0ZXI6Vy5EMCxBY2Nlc3NpYmxlTm9kZTpXLkQwLEFt
+YmllbnRMaWdodFNlbnNvcjpXLkQwLEFuaW1hdGlvbjpXLkQwLEFwcGxpY2F0aW9uQ2FjaGU6Vy5EMCxE
+T01BcHBsaWNhdGlvbkNhY2hlOlcuRDAsT2ZmbGluZVJlc291cmNlTGlzdDpXLkQwLEJhY2tncm91bmRG
+ZXRjaFJlZ2lzdHJhdGlvbjpXLkQwLEJhdHRlcnlNYW5hZ2VyOlcuRDAsQnJvYWRjYXN0Q2hhbm5lbDpX
+LkQwLENhbnZhc0NhcHR1cmVNZWRpYVN0cmVhbVRyYWNrOlcuRDAsRXZlbnRTb3VyY2U6Vy5EMCxGaWxl
+UmVhZGVyOlcuRDAsRm9udEZhY2VTZXQ6Vy5EMCxHeXJvc2NvcGU6Vy5EMCxMaW5lYXJBY2NlbGVyYXRp
+b25TZW5zb3I6Vy5EMCxNYWduZXRvbWV0ZXI6Vy5EMCxNZWRpYURldmljZXM6Vy5EMCxNZWRpYUtleVNl
+c3Npb246Vy5EMCxNZWRpYVF1ZXJ5TGlzdDpXLkQwLE1lZGlhUmVjb3JkZXI6Vy5EMCxNZWRpYVNvdXJj
+ZTpXLkQwLE1lZGlhU3RyZWFtOlcuRDAsTWVkaWFTdHJlYW1UcmFjazpXLkQwLE1JRElBY2Nlc3M6Vy5E
+MCxNSURJSW5wdXQ6Vy5EMCxNSURJT3V0cHV0OlcuRDAsTUlESVBvcnQ6Vy5EMCxOZXR3b3JrSW5mb3Jt
+YXRpb246Vy5EMCxOb3RpZmljYXRpb246Vy5EMCxPZmZzY3JlZW5DYW52YXM6Vy5EMCxPcmllbnRhdGlv
+blNlbnNvcjpXLkQwLFBheW1lbnRSZXF1ZXN0OlcuRDAsUGVyZm9ybWFuY2U6Vy5EMCxQZXJtaXNzaW9u
+U3RhdHVzOlcuRDAsUHJlc2VudGF0aW9uQ29ubmVjdGlvbjpXLkQwLFByZXNlbnRhdGlvbkNvbm5lY3Rp
+b25MaXN0OlcuRDAsUHJlc2VudGF0aW9uUmVxdWVzdDpXLkQwLFJlbGF0aXZlT3JpZW50YXRpb25TZW5z
+b3I6Vy5EMCxSZW1vdGVQbGF5YmFjazpXLkQwLFJUQ0RhdGFDaGFubmVsOlcuRDAsRGF0YUNoYW5uZWw6
+Vy5EMCxSVENEVE1GU2VuZGVyOlcuRDAsUlRDUGVlckNvbm5lY3Rpb246Vy5EMCx3ZWJraXRSVENQZWVy
+Q29ubmVjdGlvbjpXLkQwLG1velJUQ1BlZXJDb25uZWN0aW9uOlcuRDAsU2NyZWVuT3JpZW50YXRpb246
+Vy5EMCxTZW5zb3I6Vy5EMCxTZXJ2aWNlV29ya2VyOlcuRDAsU2VydmljZVdvcmtlckNvbnRhaW5lcjpX
+LkQwLFNlcnZpY2VXb3JrZXJSZWdpc3RyYXRpb246Vy5EMCxTaGFyZWRXb3JrZXI6Vy5EMCxTcGVlY2hS
+ZWNvZ25pdGlvbjpXLkQwLFNwZWVjaFN5bnRoZXNpczpXLkQwLFNwZWVjaFN5bnRoZXNpc1V0dGVyYW5j
+ZTpXLkQwLFZSOlcuRDAsVlJEZXZpY2U6Vy5EMCxWUkRpc3BsYXk6Vy5EMCxWUlNlc3Npb246Vy5EMCxW
+aXN1YWxWaWV3cG9ydDpXLkQwLFdlYlNvY2tldDpXLkQwLFdvcmtlcjpXLkQwLFdvcmtlclBlcmZvcm1h
+bmNlOlcuRDAsQmx1ZXRvb3RoRGV2aWNlOlcuRDAsQmx1ZXRvb3RoUmVtb3RlR0FUVENoYXJhY3Rlcmlz
+dGljOlcuRDAsQ2xpcGJvYXJkOlcuRDAsTW9qb0ludGVyZmFjZUludGVyY2VwdG9yOlcuRDAsVVNCOlcu
+RDAsSURCRGF0YWJhc2U6Vy5EMCxJREJPcGVuREJSZXF1ZXN0OlcuRDAsSURCVmVyc2lvbkNoYW5nZVJl
+cXVlc3Q6Vy5EMCxJREJSZXF1ZXN0OlcuRDAsSURCVHJhbnNhY3Rpb246Vy5EMCxBbmFseXNlck5vZGU6
+Vy5EMCxSZWFsdGltZUFuYWx5c2VyTm9kZTpXLkQwLEF1ZGlvQnVmZmVyU291cmNlTm9kZTpXLkQwLEF1
+ZGlvRGVzdGluYXRpb25Ob2RlOlcuRDAsQXVkaW9Ob2RlOlcuRDAsQXVkaW9TY2hlZHVsZWRTb3VyY2VO
+b2RlOlcuRDAsQXVkaW9Xb3JrbGV0Tm9kZTpXLkQwLEJpcXVhZEZpbHRlck5vZGU6Vy5EMCxDaGFubmVs
+TWVyZ2VyTm9kZTpXLkQwLEF1ZGlvQ2hhbm5lbE1lcmdlcjpXLkQwLENoYW5uZWxTcGxpdHRlck5vZGU6
+Vy5EMCxBdWRpb0NoYW5uZWxTcGxpdHRlcjpXLkQwLENvbnN0YW50U291cmNlTm9kZTpXLkQwLENvbnZv
+bHZlck5vZGU6Vy5EMCxEZWxheU5vZGU6Vy5EMCxEeW5hbWljc0NvbXByZXNzb3JOb2RlOlcuRDAsR2Fp
+bk5vZGU6Vy5EMCxBdWRpb0dhaW5Ob2RlOlcuRDAsSUlSRmlsdGVyTm9kZTpXLkQwLE1lZGlhRWxlbWVu
+dEF1ZGlvU291cmNlTm9kZTpXLkQwLE1lZGlhU3RyZWFtQXVkaW9EZXN0aW5hdGlvbk5vZGU6Vy5EMCxN
+ZWRpYVN0cmVhbUF1ZGlvU291cmNlTm9kZTpXLkQwLE9zY2lsbGF0b3JOb2RlOlcuRDAsT3NjaWxsYXRv
+cjpXLkQwLFBhbm5lck5vZGU6Vy5EMCxBdWRpb1Bhbm5lck5vZGU6Vy5EMCx3ZWJraXRBdWRpb1Bhbm5l
+ck5vZGU6Vy5EMCxTY3JpcHRQcm9jZXNzb3JOb2RlOlcuRDAsSmF2YVNjcmlwdEF1ZGlvTm9kZTpXLkQw
+LFN0ZXJlb1Bhbm5lck5vZGU6Vy5EMCxXYXZlU2hhcGVyTm9kZTpXLkQwLEV2ZW50VGFyZ2V0OlcuRDAs
+RmlsZTpXLlQ1LEZpbGVMaXN0OlcuWFYsRmlsZVdyaXRlcjpXLndKLEhUTUxGb3JtRWxlbWVudDpXLmg0
+LEdhbWVwYWQ6Vy5HTyxHYW1lcGFkQnV0dG9uOlcuSkMsSGlzdG9yeTpXLmJyLEhUTUxDb2xsZWN0aW9u
+OlcueG4sSFRNTEZvcm1Db250cm9sc0NvbGxlY3Rpb246Vy54bixIVE1MT3B0aW9uc0NvbGxlY3Rpb246
+Vy54bixIVE1MRG9jdW1lbnQ6Vy5WYixYTUxIdHRwUmVxdWVzdDpXLk83LFhNTEh0dHBSZXF1ZXN0VXBs
+b2FkOlcud2EsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpXLndhLEltYWdlRGF0YTpXLlNnLEhUTUxJ
+bnB1dEVsZW1lbnQ6Vy5KSyxLZXlib2FyZEV2ZW50OlcuSEwsSFRNTExJRWxlbWVudDpXLndQLExvY2F0
+aW9uOlcudTgsTWVkaWFMaXN0OlcuejYsTWVzc2FnZVBvcnQ6Vy5sSyxIVE1MTWV0ZXJFbGVtZW50Olcu
+UWIsTUlESUlucHV0TWFwOlcuUzAsTUlESU91dHB1dE1hcDpXLnoyLE1pbWVUeXBlOlcuQVcsTWltZVR5
+cGVBcnJheTpXLkRNLE1vdXNlRXZlbnQ6Vy5BaixEcmFnRXZlbnQ6Vy5BaixQb2ludGVyRXZlbnQ6Vy5B
+aixXaGVlbEV2ZW50OlcuQWosRG9jdW1lbnRGcmFnbWVudDpXLnVILFNoYWRvd1Jvb3Q6Vy51SCxEb2N1
+bWVudFR5cGU6Vy51SCxOb2RlOlcudUgsTm9kZUxpc3Q6Vy5CSCxSYWRpb05vZGVMaXN0OlcuQkgsSFRN
+TE9wdGlvbkVsZW1lbnQ6Vy5RbCxIVE1MT3V0cHV0RWxlbWVudDpXLkdYLEhUTUxQYXJhZ3JhcGhFbGVt
+ZW50OlcuU04sSFRNTFBhcmFtRWxlbWVudDpXLkhELFBsdWdpbjpXLmNsLFBsdWdpbkFycmF5OlcuRXYs
+UHJlc2VudGF0aW9uQXZhaWxhYmlsaXR5OlcuTHIsSFRNTFByb2dyZXNzRWxlbWVudDpXLktSLFByb2dy
+ZXNzRXZlbnQ6Vy5ldyxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6Vy5ldyxSVENTdGF0c1JlcG9ydDpXLnA4
+LEhUTUxTZWxlY3RFbGVtZW50OlcubHAsU291cmNlQnVmZmVyOlcuU1YsU291cmNlQnVmZmVyTGlzdDpX
+Lk1rLFNwZWVjaEdyYW1tYXI6Vy5ZNCxTcGVlY2hHcmFtbWFyTGlzdDpXLk5uLFNwZWVjaFJlY29nbml0
+aW9uUmVzdWx0OlcubDgsU3RvcmFnZTpXLkFzLFN0b3JhZ2VFdmVudDpXLmJrLENTU1N0eWxlU2hlZXQ6
+Vy5XVyxTdHlsZVNoZWV0OlcuV1csSFRNTFRhYmxlRWxlbWVudDpXLlRiLEhUTUxUYWJsZVJvd0VsZW1l
+bnQ6Vy5JdixIVE1MVGFibGVTZWN0aW9uRWxlbWVudDpXLkJULEhUTUxUZW1wbGF0ZUVsZW1lbnQ6Vy5m
+WCxIVE1MVGV4dEFyZWFFbGVtZW50OlcuRkIsVGV4dFRyYWNrOlcuQTEsVGV4dFRyYWNrQ3VlOlcuTU4s
+VlRUQ3VlOlcuTU4sVGV4dFRyYWNrQ3VlTGlzdDpXLlgwLFRleHRUcmFja0xpc3Q6Vy5uSixUaW1lUmFu
+Z2VzOlcubXosVG91Y2g6Vy5hMyxUb3VjaExpc3Q6Vy5jaSxUcmFja0RlZmF1bHRMaXN0OlcuY24sQ29t
+cG9zaXRpb25FdmVudDpXLnc2LEZvY3VzRXZlbnQ6Vy53NixUZXh0RXZlbnQ6Vy53NixUb3VjaEV2ZW50
+OlcudzYsVUlFdmVudDpXLnc2LFVSTDpXLkZqLFZpZGVvVHJhY2tMaXN0OlcudkYsV2luZG93OlcuT2ks
+RE9NV2luZG93OlcuT2ksRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxTZXJ2aWNlV29ya2Vy
+R2xvYmFsU2NvcGU6Vy5DbSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFdvcmtlckdsb2JhbFNj
+b3BlOlcuQ20sQXR0cjpXLkNRLENTU1J1bGVMaXN0OlcuUFIsQ2xpZW50UmVjdDpXLnc0LERPTVJlY3Q6
+Vy53NCxHYW1lcGFkTGlzdDpXLkYyLE5hbWVkTm9kZU1hcDpXLnJoLE1vek5hbWVkQXR0ck1hcDpXLnJo
+LFNwZWVjaFJlY29nbml0aW9uUmVzdWx0TGlzdDpXLkxPLFN0eWxlU2hlZXRMaXN0OlcuYjEsSURCQ3Vy
+c29yOlAuVzIsSURCQ3Vyc29yV2l0aFZhbHVlOlAuZTMsSURCS2V5UmFuZ2U6UC5oRixJREJPYnNlcnZh
+dGlvbjpQLkJWLFNWR0FuZ2xlOlAudWosU1ZHTGVuZ3RoOlAueDAsU1ZHTGVuZ3RoTGlzdDpQLnE2LFNW
+R051bWJlcjpQLnVQLFNWR051bWJlckxpc3Q6UC5meixTVkdQb2ludExpc3Q6UC5FRCxTVkdTY3JpcHRF
+bGVtZW50OlAubmQsU1ZHU3RyaW5nTGlzdDpQLktxLFNWR0FFbGVtZW50OlAuZDUsU1ZHQW5pbWF0ZUVs
+ZW1lbnQ6UC5kNSxTVkdBbmltYXRlTW90aW9uRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVUcmFuc2Zvcm1F
+bGVtZW50OlAuZDUsU1ZHQW5pbWF0aW9uRWxlbWVudDpQLmQ1LFNWR0NpcmNsZUVsZW1lbnQ6UC5kNSxT
+VkdDbGlwUGF0aEVsZW1lbnQ6UC5kNSxTVkdEZWZzRWxlbWVudDpQLmQ1LFNWR0Rlc2NFbGVtZW50OlAu
+ZDUsU1ZHRGlzY2FyZEVsZW1lbnQ6UC5kNSxTVkdFbGxpcHNlRWxlbWVudDpQLmQ1LFNWR0ZFQmxlbmRF
+bGVtZW50OlAuZDUsU1ZHRkVDb2xvck1hdHJpeEVsZW1lbnQ6UC5kNSxTVkdGRUNvbXBvbmVudFRyYW5z
+ZmVyRWxlbWVudDpQLmQ1LFNWR0ZFQ29tcG9zaXRlRWxlbWVudDpQLmQ1LFNWR0ZFQ29udm9sdmVNYXRy
+aXhFbGVtZW50OlAuZDUsU1ZHRkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OlAuZDUsU1ZHRkVEaXNwbGFj
+ZW1lbnRNYXBFbGVtZW50OlAuZDUsU1ZHRkVEaXN0YW50TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVGbG9v
+ZEVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNBRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0JFbGVtZW50OlAuZDUs
+U1ZHRkVGdW5jR0VsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNSRWxlbWVudDpQLmQ1LFNWR0ZFR2F1c3NpYW5C
+bHVyRWxlbWVudDpQLmQ1LFNWR0ZFSW1hZ2VFbGVtZW50OlAuZDUsU1ZHRkVNZXJnZUVsZW1lbnQ6UC5k
+NSxTVkdGRU1lcmdlTm9kZUVsZW1lbnQ6UC5kNSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OlAuZDUsU1ZH
+RkVPZmZzZXRFbGVtZW50OlAuZDUsU1ZHRkVQb2ludExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFU3BlY3Vs
+YXJMaWdodGluZ0VsZW1lbnQ6UC5kNSxTVkdGRVNwb3RMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRVRpbGVF
+bGVtZW50OlAuZDUsU1ZHRkVUdXJidWxlbmNlRWxlbWVudDpQLmQ1LFNWR0ZpbHRlckVsZW1lbnQ6UC5k
+NSxTVkdGb3JlaWduT2JqZWN0RWxlbWVudDpQLmQ1LFNWR0dFbGVtZW50OlAuZDUsU1ZHR2VvbWV0cnlF
+bGVtZW50OlAuZDUsU1ZHR3JhcGhpY3NFbGVtZW50OlAuZDUsU1ZHSW1hZ2VFbGVtZW50OlAuZDUsU1ZH
+TGluZUVsZW1lbnQ6UC5kNSxTVkdMaW5lYXJHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdNYXJrZXJFbGVt
+ZW50OlAuZDUsU1ZHTWFza0VsZW1lbnQ6UC5kNSxTVkdNZXRhZGF0YUVsZW1lbnQ6UC5kNSxTVkdQYXRo
+RWxlbWVudDpQLmQ1LFNWR1BhdHRlcm5FbGVtZW50OlAuZDUsU1ZHUG9seWdvbkVsZW1lbnQ6UC5kNSxT
+VkdQb2x5bGluZUVsZW1lbnQ6UC5kNSxTVkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdSZWN0
+RWxlbWVudDpQLmQ1LFNWR1NldEVsZW1lbnQ6UC5kNSxTVkdTdG9wRWxlbWVudDpQLmQ1LFNWR1N0eWxl
+RWxlbWVudDpQLmQ1LFNWR1NWR0VsZW1lbnQ6UC5kNSxTVkdTd2l0Y2hFbGVtZW50OlAuZDUsU1ZHU3lt
+Ym9sRWxlbWVudDpQLmQ1LFNWR1RTcGFuRWxlbWVudDpQLmQ1LFNWR1RleHRDb250ZW50RWxlbWVudDpQ
+LmQ1LFNWR1RleHRFbGVtZW50OlAuZDUsU1ZHVGV4dFBhdGhFbGVtZW50OlAuZDUsU1ZHVGV4dFBvc2l0
+aW9uaW5nRWxlbWVudDpQLmQ1LFNWR1RpdGxlRWxlbWVudDpQLmQ1LFNWR1VzZUVsZW1lbnQ6UC5kNSxT
+VkdWaWV3RWxlbWVudDpQLmQ1LFNWR0dyYWRpZW50RWxlbWVudDpQLmQ1LFNWR0NvbXBvbmVudFRyYW5z
+ZmVyRnVuY3Rpb25FbGVtZW50OlAuZDUsU1ZHRkVEcm9wU2hhZG93RWxlbWVudDpQLmQ1LFNWR01QYXRo
+RWxlbWVudDpQLmQ1LFNWR0VsZW1lbnQ6UC5kNSxTVkdUcmFuc2Zvcm06UC56WSxTVkdUcmFuc2Zvcm1M
+aXN0OlAuTkMsQXVkaW9CdWZmZXI6UC5yMixBdWRpb1BhcmFtOlAuck8sQXVkaW9QYXJhbU1hcDpQLno4
+LEF1ZGlvVHJhY2tMaXN0OlAuZm8sQXVkaW9Db250ZXh0OlAuVjgsd2Via2l0QXVkaW9Db250ZXh0OlAu
+VjgsQmFzZUF1ZGlvQ29udGV4dDpQLlY4LE9mZmxpbmVBdWRpb0NvbnRleHQ6UC5HbixTUUxSZXN1bHRT
+ZXRSb3dMaXN0OlAuRm59KQpodW5rSGVscGVycy5zZXRPclVwZGF0ZUxlYWZUYWdzKHtBbmltYXRpb25F
+ZmZlY3RSZWFkT25seTp0cnVlLEFuaW1hdGlvbkVmZmVjdFRpbWluZzp0cnVlLEFuaW1hdGlvbkVmZmVj
+dFRpbWluZ1JlYWRPbmx5OnRydWUsQW5pbWF0aW9uVGltZWxpbmU6dHJ1ZSxBbmltYXRpb25Xb3JrbGV0
+R2xvYmFsU2NvcGU6dHJ1ZSxBdXRoZW50aWNhdG9yQXNzZXJ0aW9uUmVzcG9uc2U6dHJ1ZSxBdXRoZW50
+aWNhdG9yQXR0ZXN0YXRpb25SZXNwb25zZTp0cnVlLEF1dGhlbnRpY2F0b3JSZXNwb25zZTp0cnVlLEJh
+Y2tncm91bmRGZXRjaEZldGNoOnRydWUsQmFja2dyb3VuZEZldGNoTWFuYWdlcjp0cnVlLEJhY2tncm91
+bmRGZXRjaFNldHRsZWRGZXRjaDp0cnVlLEJhclByb3A6dHJ1ZSxCYXJjb2RlRGV0ZWN0b3I6dHJ1ZSxC
+b2R5OnRydWUsQnVkZ2V0U3RhdGU6dHJ1ZSxDYWNoZVN0b3JhZ2U6dHJ1ZSxDYW52YXNHcmFkaWVudDp0
+cnVlLENhbnZhc1BhdHRlcm46dHJ1ZSxDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ6dHJ1ZSxDbGllbnQ6
+dHJ1ZSxDbGllbnRzOnRydWUsQ29va2llU3RvcmU6dHJ1ZSxDb29yZGluYXRlczp0cnVlLENyZWRlbnRp
+YWw6dHJ1ZSxDcmVkZW50aWFsVXNlckRhdGE6dHJ1ZSxDcmVkZW50aWFsc0NvbnRhaW5lcjp0cnVlLENy
+eXB0bzp0cnVlLENyeXB0b0tleTp0cnVlLENTUzp0cnVlLENTU1ZhcmlhYmxlUmVmZXJlbmNlVmFsdWU6
+dHJ1ZSxDdXN0b21FbGVtZW50UmVnaXN0cnk6dHJ1ZSxEYXRhVHJhbnNmZXI6dHJ1ZSxEYXRhVHJhbnNm
+ZXJJdGVtOnRydWUsRGVwcmVjYXRlZFN0b3JhZ2VJbmZvOnRydWUsRGVwcmVjYXRlZFN0b3JhZ2VRdW90
+YTp0cnVlLERlcHJlY2F0aW9uUmVwb3J0OnRydWUsRGV0ZWN0ZWRCYXJjb2RlOnRydWUsRGV0ZWN0ZWRG
+YWNlOnRydWUsRGV0ZWN0ZWRUZXh0OnRydWUsRGV2aWNlQWNjZWxlcmF0aW9uOnRydWUsRGV2aWNlUm90
+YXRpb25SYXRlOnRydWUsRGlyZWN0b3J5UmVhZGVyOnRydWUsRG9jdW1lbnRPclNoYWRvd1Jvb3Q6dHJ1
+ZSxEb2N1bWVudFRpbWVsaW5lOnRydWUsRE9NRXJyb3I6dHJ1ZSxET01JbXBsZW1lbnRhdGlvbjp0cnVl
+LEl0ZXJhdG9yOnRydWUsRE9NTWF0cml4OnRydWUsRE9NTWF0cml4UmVhZE9ubHk6dHJ1ZSxET01QYXJz
+ZXI6dHJ1ZSxET01Qb2ludDp0cnVlLERPTVBvaW50UmVhZE9ubHk6dHJ1ZSxET01RdWFkOnRydWUsRE9N
+U3RyaW5nTWFwOnRydWUsRXh0ZXJuYWw6dHJ1ZSxGYWNlRGV0ZWN0b3I6dHJ1ZSxGZWRlcmF0ZWRDcmVk
+ZW50aWFsOnRydWUsRE9NRmlsZVN5c3RlbTp0cnVlLEZvbnRGYWNlOnRydWUsRm9udEZhY2VTb3VyY2U6
+dHJ1ZSxGb3JtRGF0YTp0cnVlLEdhbWVwYWRQb3NlOnRydWUsR2VvbG9jYXRpb246dHJ1ZSxQb3NpdGlv
+bjp0cnVlLEhlYWRlcnM6dHJ1ZSxIVE1MSHlwZXJsaW5rRWxlbWVudFV0aWxzOnRydWUsSWRsZURlYWRs
+aW5lOnRydWUsSW1hZ2VCaXRtYXA6dHJ1ZSxJbWFnZUJpdG1hcFJlbmRlcmluZ0NvbnRleHQ6dHJ1ZSxJ
+bWFnZUNhcHR1cmU6dHJ1ZSxJbnB1dERldmljZUNhcGFiaWxpdGllczp0cnVlLEludGVyc2VjdGlvbk9i
+c2VydmVyOnRydWUsSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeTp0cnVlLEludGVydmVudGlvblJlcG9y
+dDp0cnVlLEtleWZyYW1lRWZmZWN0OnRydWUsS2V5ZnJhbWVFZmZlY3RSZWFkT25seTp0cnVlLE1lZGlh
+Q2FwYWJpbGl0aWVzOnRydWUsTWVkaWFDYXBhYmlsaXRpZXNJbmZvOnRydWUsTWVkaWFEZXZpY2VJbmZv
+OnRydWUsTWVkaWFFcnJvcjp0cnVlLE1lZGlhS2V5U3RhdHVzTWFwOnRydWUsTWVkaWFLZXlTeXN0ZW1B
+Y2Nlc3M6dHJ1ZSxNZWRpYUtleXM6dHJ1ZSxNZWRpYUtleXNQb2xpY3k6dHJ1ZSxNZWRpYU1ldGFkYXRh
+OnRydWUsTWVkaWFTZXNzaW9uOnRydWUsTWVkaWFTZXR0aW5nc1JhbmdlOnRydWUsTWVtb3J5SW5mbzp0
+cnVlLE1lc3NhZ2VDaGFubmVsOnRydWUsTWV0YWRhdGE6dHJ1ZSxNdXRhdGlvbk9ic2VydmVyOnRydWUs
+V2ViS2l0TXV0YXRpb25PYnNlcnZlcjp0cnVlLE11dGF0aW9uUmVjb3JkOnRydWUsTmF2aWdhdGlvblBy
+ZWxvYWRNYW5hZ2VyOnRydWUsTmF2aWdhdG9yOnRydWUsTmF2aWdhdG9yQXV0b21hdGlvbkluZm9ybWF0
+aW9uOnRydWUsTmF2aWdhdG9yQ29uY3VycmVudEhhcmR3YXJlOnRydWUsTmF2aWdhdG9yQ29va2llczp0
+cnVlLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOnRydWUsTm9kZUZpbHRlcjp0cnVlLE5vZGVJdGVyYXRv
+cjp0cnVlLE5vbkRvY3VtZW50VHlwZUNoaWxkTm9kZTp0cnVlLE5vbkVsZW1lbnRQYXJlbnROb2RlOnRy
+dWUsTm9uY2VkRWxlbWVudDp0cnVlLE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDp0cnVl
+LE92ZXJjb25zdHJhaW5lZEVycm9yOnRydWUsUGFpbnRSZW5kZXJpbmdDb250ZXh0MkQ6dHJ1ZSxQYWlu
+dFNpemU6dHJ1ZSxQYWludFdvcmtsZXRHbG9iYWxTY29wZTp0cnVlLFBhc3N3b3JkQ3JlZGVudGlhbDp0
+cnVlLFBhdGgyRDp0cnVlLFBheW1lbnRBZGRyZXNzOnRydWUsUGF5bWVudEluc3RydW1lbnRzOnRydWUs
+UGF5bWVudE1hbmFnZXI6dHJ1ZSxQYXltZW50UmVzcG9uc2U6dHJ1ZSxQZXJmb3JtYW5jZUVudHJ5OnRy
+dWUsUGVyZm9ybWFuY2VMb25nVGFza1RpbWluZzp0cnVlLFBlcmZvcm1hbmNlTWFyazp0cnVlLFBlcmZv
+cm1hbmNlTWVhc3VyZTp0cnVlLFBlcmZvcm1hbmNlTmF2aWdhdGlvbjp0cnVlLFBlcmZvcm1hbmNlTmF2
+aWdhdGlvblRpbWluZzp0cnVlLFBlcmZvcm1hbmNlT2JzZXJ2ZXI6dHJ1ZSxQZXJmb3JtYW5jZU9ic2Vy
+dmVyRW50cnlMaXN0OnRydWUsUGVyZm9ybWFuY2VQYWludFRpbWluZzp0cnVlLFBlcmZvcm1hbmNlUmVz
+b3VyY2VUaW1pbmc6dHJ1ZSxQZXJmb3JtYW5jZVNlcnZlclRpbWluZzp0cnVlLFBlcmZvcm1hbmNlVGlt
+aW5nOnRydWUsUGVybWlzc2lvbnM6dHJ1ZSxQaG90b0NhcGFiaWxpdGllczp0cnVlLFBvc2l0aW9uRXJy
+b3I6dHJ1ZSxQcmVzZW50YXRpb246dHJ1ZSxQcmVzZW50YXRpb25SZWNlaXZlcjp0cnVlLFB1YmxpY0tl
+eUNyZWRlbnRpYWw6dHJ1ZSxQdXNoTWFuYWdlcjp0cnVlLFB1c2hNZXNzYWdlRGF0YTp0cnVlLFB1c2hT
+dWJzY3JpcHRpb246dHJ1ZSxQdXNoU3Vic2NyaXB0aW9uT3B0aW9uczp0cnVlLFJhbmdlOnRydWUsUmVs
+YXRlZEFwcGxpY2F0aW9uOnRydWUsUmVwb3J0Qm9keTp0cnVlLFJlcG9ydGluZ09ic2VydmVyOnRydWUs
+UmVzaXplT2JzZXJ2ZXI6dHJ1ZSxSZXNpemVPYnNlcnZlckVudHJ5OnRydWUsUlRDQ2VydGlmaWNhdGU6
+dHJ1ZSxSVENJY2VDYW5kaWRhdGU6dHJ1ZSxtb3pSVENJY2VDYW5kaWRhdGU6dHJ1ZSxSVENMZWdhY3lT
+dGF0c1JlcG9ydDp0cnVlLFJUQ1J0cENvbnRyaWJ1dGluZ1NvdXJjZTp0cnVlLFJUQ1J0cFJlY2VpdmVy
+OnRydWUsUlRDUnRwU2VuZGVyOnRydWUsUlRDU2Vzc2lvbkRlc2NyaXB0aW9uOnRydWUsbW96UlRDU2Vz
+c2lvbkRlc2NyaXB0aW9uOnRydWUsUlRDU3RhdHNSZXNwb25zZTp0cnVlLFNjcmVlbjp0cnVlLFNjcm9s
+bFN0YXRlOnRydWUsU2Nyb2xsVGltZWxpbmU6dHJ1ZSxTZWxlY3Rpb246dHJ1ZSxTaGFyZWRBcnJheUJ1
+ZmZlcjp0cnVlLFNwZWVjaFJlY29nbml0aW9uQWx0ZXJuYXRpdmU6dHJ1ZSxTcGVlY2hTeW50aGVzaXNW
+b2ljZTp0cnVlLFN0YXRpY1JhbmdlOnRydWUsU3RvcmFnZU1hbmFnZXI6dHJ1ZSxTdHlsZU1lZGlhOnRy
+dWUsU3R5bGVQcm9wZXJ0eU1hcDp0cnVlLFN0eWxlUHJvcGVydHlNYXBSZWFkb25seTp0cnVlLFN5bmNN
+YW5hZ2VyOnRydWUsVGFza0F0dHJpYnV0aW9uVGltaW5nOnRydWUsVGV4dERldGVjdG9yOnRydWUsVGV4
+dE1ldHJpY3M6dHJ1ZSxUcmFja0RlZmF1bHQ6dHJ1ZSxUcmVlV2Fsa2VyOnRydWUsVHJ1c3RlZEhUTUw6
+dHJ1ZSxUcnVzdGVkU2NyaXB0VVJMOnRydWUsVHJ1c3RlZFVSTDp0cnVlLFVuZGVybHlpbmdTb3VyY2VC
+YXNlOnRydWUsVVJMU2VhcmNoUGFyYW1zOnRydWUsVlJDb29yZGluYXRlU3lzdGVtOnRydWUsVlJEaXNw
+bGF5Q2FwYWJpbGl0aWVzOnRydWUsVlJFeWVQYXJhbWV0ZXJzOnRydWUsVlJGcmFtZURhdGE6dHJ1ZSxW
+UkZyYW1lT2ZSZWZlcmVuY2U6dHJ1ZSxWUlBvc2U6dHJ1ZSxWUlN0YWdlQm91bmRzOnRydWUsVlJTdGFn
+ZUJvdW5kc1BvaW50OnRydWUsVlJTdGFnZVBhcmFtZXRlcnM6dHJ1ZSxWYWxpZGl0eVN0YXRlOnRydWUs
+VmlkZW9QbGF5YmFja1F1YWxpdHk6dHJ1ZSxWaWRlb1RyYWNrOnRydWUsVlRUUmVnaW9uOnRydWUsV2lu
+ZG93Q2xpZW50OnRydWUsV29ya2xldEFuaW1hdGlvbjp0cnVlLFdvcmtsZXRHbG9iYWxTY29wZTp0cnVl
+LFhQYXRoRXZhbHVhdG9yOnRydWUsWFBhdGhFeHByZXNzaW9uOnRydWUsWFBhdGhOU1Jlc29sdmVyOnRy
+dWUsWFBhdGhSZXN1bHQ6dHJ1ZSxYTUxTZXJpYWxpemVyOnRydWUsWFNMVFByb2Nlc3Nvcjp0cnVlLEJs
+dWV0b290aDp0cnVlLEJsdWV0b290aENoYXJhY3RlcmlzdGljUHJvcGVydGllczp0cnVlLEJsdWV0b290
+aFJlbW90ZUdBVFRTZXJ2ZXI6dHJ1ZSxCbHVldG9vdGhSZW1vdGVHQVRUU2VydmljZTp0cnVlLEJsdWV0
+b290aFVVSUQ6dHJ1ZSxCdWRnZXRTZXJ2aWNlOnRydWUsQ2FjaGU6dHJ1ZSxET01GaWxlU3lzdGVtU3lu
+Yzp0cnVlLERpcmVjdG9yeUVudHJ5U3luYzp0cnVlLERpcmVjdG9yeVJlYWRlclN5bmM6dHJ1ZSxFbnRy
+eVN5bmM6dHJ1ZSxGaWxlRW50cnlTeW5jOnRydWUsRmlsZVJlYWRlclN5bmM6dHJ1ZSxGaWxlV3JpdGVy
+U3luYzp0cnVlLEhUTUxBbGxDb2xsZWN0aW9uOnRydWUsTW9qbzp0cnVlLE1vam9IYW5kbGU6dHJ1ZSxN
+b2pvV2F0Y2hlcjp0cnVlLE5GQzp0cnVlLFBhZ2VQb3B1cENvbnRyb2xsZXI6dHJ1ZSxSZXBvcnQ6dHJ1
+ZSxSZXF1ZXN0OnRydWUsUmVzcG9uc2U6dHJ1ZSxTdWJ0bGVDcnlwdG86dHJ1ZSxVU0JBbHRlcm5hdGVJ
+bnRlcmZhY2U6dHJ1ZSxVU0JDb25maWd1cmF0aW9uOnRydWUsVVNCRGV2aWNlOnRydWUsVVNCRW5kcG9p
+bnQ6dHJ1ZSxVU0JJblRyYW5zZmVyUmVzdWx0OnRydWUsVVNCSW50ZXJmYWNlOnRydWUsVVNCSXNvY2hy
+b25vdXNJblRyYW5zZmVyUGFja2V0OnRydWUsVVNCSXNvY2hyb25vdXNJblRyYW5zZmVyUmVzdWx0OnRy
+dWUsVVNCSXNvY2hyb25vdXNPdXRUcmFuc2ZlclBhY2tldDp0cnVlLFVTQklzb2Nocm9ub3VzT3V0VHJh
+bnNmZXJSZXN1bHQ6dHJ1ZSxVU0JPdXRUcmFuc2ZlclJlc3VsdDp0cnVlLFdvcmtlckxvY2F0aW9uOnRy
+dWUsV29ya2VyTmF2aWdhdG9yOnRydWUsV29ya2xldDp0cnVlLElEQkZhY3Rvcnk6dHJ1ZSxJREJJbmRl
+eDp0cnVlLElEQk9iamVjdFN0b3JlOnRydWUsSURCT2JzZXJ2ZXI6dHJ1ZSxJREJPYnNlcnZlckNoYW5n
+ZXM6dHJ1ZSxTVkdBbmltYXRlZEFuZ2xlOnRydWUsU1ZHQW5pbWF0ZWRCb29sZWFuOnRydWUsU1ZHQW5p
+bWF0ZWRFbnVtZXJhdGlvbjp0cnVlLFNWR0FuaW1hdGVkSW50ZWdlcjp0cnVlLFNWR0FuaW1hdGVkTGVu
+Z3RoOnRydWUsU1ZHQW5pbWF0ZWRMZW5ndGhMaXN0OnRydWUsU1ZHQW5pbWF0ZWROdW1iZXI6dHJ1ZSxT
+VkdBbmltYXRlZE51bWJlckxpc3Q6dHJ1ZSxTVkdBbmltYXRlZFByZXNlcnZlQXNwZWN0UmF0aW86dHJ1
+ZSxTVkdBbmltYXRlZFJlY3Q6dHJ1ZSxTVkdBbmltYXRlZFN0cmluZzp0cnVlLFNWR0FuaW1hdGVkVHJh
+bnNmb3JtTGlzdDp0cnVlLFNWR01hdHJpeDp0cnVlLFNWR1BvaW50OnRydWUsU1ZHUHJlc2VydmVBc3Bl
+Y3RSYXRpbzp0cnVlLFNWR1JlY3Q6dHJ1ZSxTVkdVbml0VHlwZXM6dHJ1ZSxBdWRpb0xpc3RlbmVyOnRy
+dWUsQXVkaW9UcmFjazp0cnVlLEF1ZGlvV29ya2xldEdsb2JhbFNjb3BlOnRydWUsQXVkaW9Xb3JrbGV0
+UHJvY2Vzc29yOnRydWUsUGVyaW9kaWNXYXZlOnRydWUsV2ViR0xBY3RpdmVJbmZvOnRydWUsQU5HTEVJ
+bnN0YW5jZWRBcnJheXM6dHJ1ZSxBTkdMRV9pbnN0YW5jZWRfYXJyYXlzOnRydWUsV2ViR0xCdWZmZXI6
+dHJ1ZSxXZWJHTENhbnZhczp0cnVlLFdlYkdMQ29sb3JCdWZmZXJGbG9hdDp0cnVlLFdlYkdMQ29tcHJl
+c3NlZFRleHR1cmVBU1RDOnRydWUsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUFUQzp0cnVlLFdFQkdMX2Nv
+bXByZXNzZWRfdGV4dHVyZV9hdGM6dHJ1ZSxXZWJHTENvbXByZXNzZWRUZXh0dXJlRVRDMTp0cnVlLFdF
+QkdMX2NvbXByZXNzZWRfdGV4dHVyZV9ldGMxOnRydWUsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUVUQzp0
+cnVlLFdlYkdMQ29tcHJlc3NlZFRleHR1cmVQVlJUQzp0cnVlLFdFQkdMX2NvbXByZXNzZWRfdGV4dHVy
+ZV9wdnJ0Yzp0cnVlLFdlYkdMQ29tcHJlc3NlZFRleHR1cmVTM1RDOnRydWUsV0VCR0xfY29tcHJlc3Nl
+ZF90ZXh0dXJlX3MzdGM6dHJ1ZSxXZWJHTENvbXByZXNzZWRUZXh0dXJlUzNUQ3NSR0I6dHJ1ZSxXZWJH
+TERlYnVnUmVuZGVyZXJJbmZvOnRydWUsV0VCR0xfZGVidWdfcmVuZGVyZXJfaW5mbzp0cnVlLFdlYkdM
+RGVidWdTaGFkZXJzOnRydWUsV0VCR0xfZGVidWdfc2hhZGVyczp0cnVlLFdlYkdMRGVwdGhUZXh0dXJl
+OnRydWUsV0VCR0xfZGVwdGhfdGV4dHVyZTp0cnVlLFdlYkdMRHJhd0J1ZmZlcnM6dHJ1ZSxXRUJHTF9k
+cmF3X2J1ZmZlcnM6dHJ1ZSxFWFRzUkdCOnRydWUsRVhUX3NSR0I6dHJ1ZSxFWFRCbGVuZE1pbk1heDp0
+cnVlLEVYVF9ibGVuZF9taW5tYXg6dHJ1ZSxFWFRDb2xvckJ1ZmZlckZsb2F0OnRydWUsRVhUQ29sb3JC
+dWZmZXJIYWxmRmxvYXQ6dHJ1ZSxFWFREaXNqb2ludFRpbWVyUXVlcnk6dHJ1ZSxFWFREaXNqb2ludFRp
+bWVyUXVlcnlXZWJHTDI6dHJ1ZSxFWFRGcmFnRGVwdGg6dHJ1ZSxFWFRfZnJhZ19kZXB0aDp0cnVlLEVY
+VFNoYWRlclRleHR1cmVMT0Q6dHJ1ZSxFWFRfc2hhZGVyX3RleHR1cmVfbG9kOnRydWUsRVhUVGV4dHVy
+ZUZpbHRlckFuaXNvdHJvcGljOnRydWUsRVhUX3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljOnRydWUs
+V2ViR0xGcmFtZWJ1ZmZlcjp0cnVlLFdlYkdMR2V0QnVmZmVyU3ViRGF0YUFzeW5jOnRydWUsV2ViR0xM
+b3NlQ29udGV4dDp0cnVlLFdlYkdMRXh0ZW5zaW9uTG9zZUNvbnRleHQ6dHJ1ZSxXRUJHTF9sb3NlX2Nv
+bnRleHQ6dHJ1ZSxPRVNFbGVtZW50SW5kZXhVaW50OnRydWUsT0VTX2VsZW1lbnRfaW5kZXhfdWludDp0
+cnVlLE9FU1N0YW5kYXJkRGVyaXZhdGl2ZXM6dHJ1ZSxPRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXM6dHJ1
+ZSxPRVNUZXh0dXJlRmxvYXQ6dHJ1ZSxPRVNfdGV4dHVyZV9mbG9hdDp0cnVlLE9FU1RleHR1cmVGbG9h
+dExpbmVhcjp0cnVlLE9FU190ZXh0dXJlX2Zsb2F0X2xpbmVhcjp0cnVlLE9FU1RleHR1cmVIYWxmRmxv
+YXQ6dHJ1ZSxPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0OnRydWUsT0VTVGV4dHVyZUhhbGZGbG9hdExpbmVh
+cjp0cnVlLE9FU190ZXh0dXJlX2hhbGZfZmxvYXRfbGluZWFyOnRydWUsT0VTVmVydGV4QXJyYXlPYmpl
+Y3Q6dHJ1ZSxPRVNfdmVydGV4X2FycmF5X29iamVjdDp0cnVlLFdlYkdMUHJvZ3JhbTp0cnVlLFdlYkdM
+UXVlcnk6dHJ1ZSxXZWJHTFJlbmRlcmJ1ZmZlcjp0cnVlLFdlYkdMUmVuZGVyaW5nQ29udGV4dDp0cnVl
+LFdlYkdMMlJlbmRlcmluZ0NvbnRleHQ6dHJ1ZSxXZWJHTFNhbXBsZXI6dHJ1ZSxXZWJHTFNoYWRlcjp0
+cnVlLFdlYkdMU2hhZGVyUHJlY2lzaW9uRm9ybWF0OnRydWUsV2ViR0xTeW5jOnRydWUsV2ViR0xUZXh0
+dXJlOnRydWUsV2ViR0xUaW1lclF1ZXJ5RVhUOnRydWUsV2ViR0xUcmFuc2Zvcm1GZWVkYmFjazp0cnVl
+LFdlYkdMVW5pZm9ybUxvY2F0aW9uOnRydWUsV2ViR0xWZXJ0ZXhBcnJheU9iamVjdDp0cnVlLFdlYkdM
+VmVydGV4QXJyYXlPYmplY3RPRVM6dHJ1ZSxXZWJHTDp0cnVlLFdlYkdMMlJlbmRlcmluZ0NvbnRleHRC
+YXNlOnRydWUsRGF0YWJhc2U6dHJ1ZSxTUUxFcnJvcjp0cnVlLFNRTFJlc3VsdFNldDp0cnVlLFNRTFRy
+YW5zYWN0aW9uOnRydWUsQXJyYXlCdWZmZXI6dHJ1ZSxBcnJheUJ1ZmZlclZpZXc6ZmFsc2UsRGF0YVZp
+ZXc6dHJ1ZSxGbG9hdDMyQXJyYXk6dHJ1ZSxGbG9hdDY0QXJyYXk6dHJ1ZSxJbnQxNkFycmF5OnRydWUs
+SW50MzJBcnJheTp0cnVlLEludDhBcnJheTp0cnVlLFVpbnQxNkFycmF5OnRydWUsVWludDMyQXJyYXk6
+dHJ1ZSxVaW50OENsYW1wZWRBcnJheTp0cnVlLENhbnZhc1BpeGVsQXJyYXk6dHJ1ZSxVaW50OEFycmF5
+OmZhbHNlLEhUTUxBdWRpb0VsZW1lbnQ6dHJ1ZSxIVE1MQlJFbGVtZW50OnRydWUsSFRNTENhbnZhc0Vs
+ZW1lbnQ6dHJ1ZSxIVE1MQ29udGVudEVsZW1lbnQ6dHJ1ZSxIVE1MRExpc3RFbGVtZW50OnRydWUsSFRN
+TERhdGFMaXN0RWxlbWVudDp0cnVlLEhUTUxEZXRhaWxzRWxlbWVudDp0cnVlLEhUTUxEaWFsb2dFbGVt
+ZW50OnRydWUsSFRNTERpdkVsZW1lbnQ6dHJ1ZSxIVE1MRW1iZWRFbGVtZW50OnRydWUsSFRNTEZpZWxk
+U2V0RWxlbWVudDp0cnVlLEhUTUxIUkVsZW1lbnQ6dHJ1ZSxIVE1MSGVhZEVsZW1lbnQ6dHJ1ZSxIVE1M
+SGVhZGluZ0VsZW1lbnQ6dHJ1ZSxIVE1MSHRtbEVsZW1lbnQ6dHJ1ZSxIVE1MSUZyYW1lRWxlbWVudDp0
+cnVlLEhUTUxJbWFnZUVsZW1lbnQ6dHJ1ZSxIVE1MTGFiZWxFbGVtZW50OnRydWUsSFRNTExlZ2VuZEVs
+ZW1lbnQ6dHJ1ZSxIVE1MTGlua0VsZW1lbnQ6dHJ1ZSxIVE1MTWFwRWxlbWVudDp0cnVlLEhUTUxNZWRp
+YUVsZW1lbnQ6dHJ1ZSxIVE1MTWVudUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0YUVsZW1lbnQ6dHJ1ZSxIVE1M
+TW9kRWxlbWVudDp0cnVlLEhUTUxPTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MT2JqZWN0RWxlbWVudDp0cnVl
+LEhUTUxPcHRHcm91cEVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1lbnQ6dHJ1ZSxIVE1MUHJlRWxl
+bWVudDp0cnVlLEhUTUxRdW90ZUVsZW1lbnQ6dHJ1ZSxIVE1MU2NyaXB0RWxlbWVudDp0cnVlLEhUTUxT
+aGFkb3dFbGVtZW50OnRydWUsSFRNTFNsb3RFbGVtZW50OnRydWUsSFRNTFNvdXJjZUVsZW1lbnQ6dHJ1
+ZSxIVE1MU3BhbkVsZW1lbnQ6dHJ1ZSxIVE1MU3R5bGVFbGVtZW50OnRydWUsSFRNTFRhYmxlQ2FwdGlv
+bkVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZURhdGFDZWxsRWxl
+bWVudDp0cnVlLEhUTUxUYWJsZUhlYWRlckNlbGxFbGVtZW50OnRydWUsSFRNTFRhYmxlQ29sRWxlbWVu
+dDp0cnVlLEhUTUxUaW1lRWxlbWVudDp0cnVlLEhUTUxUaXRsZUVsZW1lbnQ6dHJ1ZSxIVE1MVHJhY2tF
+bGVtZW50OnRydWUsSFRNTFVMaXN0RWxlbWVudDp0cnVlLEhUTUxVbmtub3duRWxlbWVudDp0cnVlLEhU
+TUxWaWRlb0VsZW1lbnQ6dHJ1ZSxIVE1MRGlyZWN0b3J5RWxlbWVudDp0cnVlLEhUTUxGb250RWxlbWVu
+dDp0cnVlLEhUTUxGcmFtZUVsZW1lbnQ6dHJ1ZSxIVE1MRnJhbWVTZXRFbGVtZW50OnRydWUsSFRNTE1h
+cnF1ZWVFbGVtZW50OnRydWUsSFRNTEVsZW1lbnQ6ZmFsc2UsQWNjZXNzaWJsZU5vZGVMaXN0OnRydWUs
+SFRNTEFuY2hvckVsZW1lbnQ6dHJ1ZSxIVE1MQXJlYUVsZW1lbnQ6dHJ1ZSxIVE1MQmFzZUVsZW1lbnQ6
+dHJ1ZSxCbG9iOmZhbHNlLEJsdWV0b290aFJlbW90ZUdBVFREZXNjcmlwdG9yOnRydWUsSFRNTEJvZHlF
+bGVtZW50OnRydWUsSFRNTEJ1dHRvbkVsZW1lbnQ6dHJ1ZSxDREFUQVNlY3Rpb246dHJ1ZSxDaGFyYWN0
+ZXJEYXRhOnRydWUsQ29tbWVudDp0cnVlLFByb2Nlc3NpbmdJbnN0cnVjdGlvbjp0cnVlLFRleHQ6dHJ1
+ZSxDU1NLZXl3b3JkVmFsdWU6dHJ1ZSxDU1NOdW1lcmljVmFsdWU6ZmFsc2UsQ1NTUGVyc3BlY3RpdmU6
+dHJ1ZSxDU1NDaGFyc2V0UnVsZTp0cnVlLENTU0NvbmRpdGlvblJ1bGU6dHJ1ZSxDU1NGb250RmFjZVJ1
+bGU6dHJ1ZSxDU1NHcm91cGluZ1J1bGU6dHJ1ZSxDU1NJbXBvcnRSdWxlOnRydWUsQ1NTS2V5ZnJhbWVS
+dWxlOnRydWUsTW96Q1NTS2V5ZnJhbWVSdWxlOnRydWUsV2ViS2l0Q1NTS2V5ZnJhbWVSdWxlOnRydWUs
+Q1NTS2V5ZnJhbWVzUnVsZTp0cnVlLE1vekNTU0tleWZyYW1lc1J1bGU6dHJ1ZSxXZWJLaXRDU1NLZXlm
+cmFtZXNSdWxlOnRydWUsQ1NTTWVkaWFSdWxlOnRydWUsQ1NTTmFtZXNwYWNlUnVsZTp0cnVlLENTU1Bh
+Z2VSdWxlOnRydWUsQ1NTUnVsZTp0cnVlLENTU1N0eWxlUnVsZTp0cnVlLENTU1N1cHBvcnRzUnVsZTp0
+cnVlLENTU1ZpZXdwb3J0UnVsZTp0cnVlLENTU1N0eWxlRGVjbGFyYXRpb246dHJ1ZSxNU1N0eWxlQ1NT
+UHJvcGVydGllczp0cnVlLENTUzJQcm9wZXJ0aWVzOnRydWUsQ1NTSW1hZ2VWYWx1ZTp0cnVlLENTU1Bv
+c2l0aW9uVmFsdWU6dHJ1ZSxDU1NSZXNvdXJjZVZhbHVlOnRydWUsQ1NTVVJMSW1hZ2VWYWx1ZTp0cnVl
+LENTU1N0eWxlVmFsdWU6ZmFsc2UsQ1NTTWF0cml4Q29tcG9uZW50OnRydWUsQ1NTUm90YXRpb246dHJ1
+ZSxDU1NTY2FsZTp0cnVlLENTU1NrZXc6dHJ1ZSxDU1NUcmFuc2xhdGlvbjp0cnVlLENTU1RyYW5zZm9y
+bUNvbXBvbmVudDpmYWxzZSxDU1NUcmFuc2Zvcm1WYWx1ZTp0cnVlLENTU1VuaXRWYWx1ZTp0cnVlLENT
+U1VucGFyc2VkVmFsdWU6dHJ1ZSxIVE1MRGF0YUVsZW1lbnQ6dHJ1ZSxEYXRhVHJhbnNmZXJJdGVtTGlz
+dDp0cnVlLFhNTERvY3VtZW50OnRydWUsRG9jdW1lbnQ6ZmFsc2UsRE9NRXhjZXB0aW9uOnRydWUsQ2xp
+ZW50UmVjdExpc3Q6dHJ1ZSxET01SZWN0TGlzdDp0cnVlLERPTVJlY3RSZWFkT25seTpmYWxzZSxET01T
+dHJpbmdMaXN0OnRydWUsRE9NVG9rZW5MaXN0OnRydWUsRWxlbWVudDpmYWxzZSxEaXJlY3RvcnlFbnRy
+eTp0cnVlLEVudHJ5OnRydWUsRmlsZUVudHJ5OnRydWUsQWJvcnRQYXltZW50RXZlbnQ6dHJ1ZSxBbmlt
+YXRpb25FdmVudDp0cnVlLEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6dHJ1ZSxBcHBsaWNhdGlvbkNhY2hl
+RXJyb3JFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0
+Y2hFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaGVk
+RXZlbnQ6dHJ1ZSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZlbnQ6dHJ1ZSxCZWZvcmVVbmxvYWRFdmVudDp0
+cnVlLEJsb2JFdmVudDp0cnVlLENhbk1ha2VQYXltZW50RXZlbnQ6dHJ1ZSxDbGlwYm9hcmRFdmVudDp0
+cnVlLENsb3NlRXZlbnQ6dHJ1ZSxDdXN0b21FdmVudDp0cnVlLERldmljZU1vdGlvbkV2ZW50OnRydWUs
+RGV2aWNlT3JpZW50YXRpb25FdmVudDp0cnVlLEVycm9yRXZlbnQ6dHJ1ZSxFeHRlbmRhYmxlRXZlbnQ6
+dHJ1ZSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OnRydWUsRmV0Y2hFdmVudDp0cnVlLEZvbnRGYWNlU2V0
+TG9hZEV2ZW50OnRydWUsRm9yZWlnbkZldGNoRXZlbnQ6dHJ1ZSxHYW1lcGFkRXZlbnQ6dHJ1ZSxIYXNo
+Q2hhbmdlRXZlbnQ6dHJ1ZSxJbnN0YWxsRXZlbnQ6dHJ1ZSxNZWRpYUVuY3J5cHRlZEV2ZW50OnRydWUs
+TWVkaWFLZXlNZXNzYWdlRXZlbnQ6dHJ1ZSxNZWRpYVF1ZXJ5TGlzdEV2ZW50OnRydWUsTWVkaWFTdHJl
+YW1FdmVudDp0cnVlLE1lZGlhU3RyZWFtVHJhY2tFdmVudDp0cnVlLE1lc3NhZ2VFdmVudDp0cnVlLE1J
+RElDb25uZWN0aW9uRXZlbnQ6dHJ1ZSxNSURJTWVzc2FnZUV2ZW50OnRydWUsTXV0YXRpb25FdmVudDp0
+cnVlLE5vdGlmaWNhdGlvbkV2ZW50OnRydWUsUGFnZVRyYW5zaXRpb25FdmVudDp0cnVlLFBheW1lbnRS
+ZXF1ZXN0RXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OnRydWUsUG9wU3RhdGVFdmVu
+dDp0cnVlLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDp0cnVlLFByZXNlbnRhdGlv
+bkNvbm5lY3Rpb25DbG9zZUV2ZW50OnRydWUsUHJvbWlzZVJlamVjdGlvbkV2ZW50OnRydWUsUHVzaEV2
+ZW50OnRydWUsUlRDRGF0YUNoYW5uZWxFdmVudDp0cnVlLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6dHJ1
+ZSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OnRydWUsUlRDVHJhY2tFdmVudDp0cnVlLFNlY3VyaXR5
+UG9saWN5VmlvbGF0aW9uRXZlbnQ6dHJ1ZSxTZW5zb3JFcnJvckV2ZW50OnRydWUsU3BlZWNoUmVjb2du
+aXRpb25FcnJvcjp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6dHJ1ZSxTcGVlY2hTeW50aGVzaXNF
+dmVudDp0cnVlLFN5bmNFdmVudDp0cnVlLFRyYWNrRXZlbnQ6dHJ1ZSxUcmFuc2l0aW9uRXZlbnQ6dHJ1
+ZSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxWUkRldmljZUV2ZW50OnRydWUsVlJEaXNwbGF5RXZl
+bnQ6dHJ1ZSxWUlNlc3Npb25FdmVudDp0cnVlLE1vam9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6dHJ1ZSxV
+U0JDb25uZWN0aW9uRXZlbnQ6dHJ1ZSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6dHJ1ZSxBdWRpb1Byb2Nl
+c3NpbmdFdmVudDp0cnVlLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDp0cnVlLFdlYkdMQ29udGV4
+dEV2ZW50OnRydWUsRXZlbnQ6ZmFsc2UsSW5wdXRFdmVudDpmYWxzZSxBYnNvbHV0ZU9yaWVudGF0aW9u
+U2Vuc29yOnRydWUsQWNjZWxlcm9tZXRlcjp0cnVlLEFjY2Vzc2libGVOb2RlOnRydWUsQW1iaWVudExp
+Z2h0U2Vuc29yOnRydWUsQW5pbWF0aW9uOnRydWUsQXBwbGljYXRpb25DYWNoZTp0cnVlLERPTUFwcGxp
+Y2F0aW9uQ2FjaGU6dHJ1ZSxPZmZsaW5lUmVzb3VyY2VMaXN0OnRydWUsQmFja2dyb3VuZEZldGNoUmVn
+aXN0cmF0aW9uOnRydWUsQmF0dGVyeU1hbmFnZXI6dHJ1ZSxCcm9hZGNhc3RDaGFubmVsOnRydWUsQ2Fu
+dmFzQ2FwdHVyZU1lZGlhU3RyZWFtVHJhY2s6dHJ1ZSxFdmVudFNvdXJjZTp0cnVlLEZpbGVSZWFkZXI6
+dHJ1ZSxGb250RmFjZVNldDp0cnVlLEd5cm9zY29wZTp0cnVlLExpbmVhckFjY2VsZXJhdGlvblNlbnNv
+cjp0cnVlLE1hZ25ldG9tZXRlcjp0cnVlLE1lZGlhRGV2aWNlczp0cnVlLE1lZGlhS2V5U2Vzc2lvbjp0
+cnVlLE1lZGlhUXVlcnlMaXN0OnRydWUsTWVkaWFSZWNvcmRlcjp0cnVlLE1lZGlhU291cmNlOnRydWUs
+TWVkaWFTdHJlYW06dHJ1ZSxNZWRpYVN0cmVhbVRyYWNrOnRydWUsTUlESUFjY2Vzczp0cnVlLE1JRElJ
+bnB1dDp0cnVlLE1JRElPdXRwdXQ6dHJ1ZSxNSURJUG9ydDp0cnVlLE5ldHdvcmtJbmZvcm1hdGlvbjp0
+cnVlLE5vdGlmaWNhdGlvbjp0cnVlLE9mZnNjcmVlbkNhbnZhczp0cnVlLE9yaWVudGF0aW9uU2Vuc29y
+OnRydWUsUGF5bWVudFJlcXVlc3Q6dHJ1ZSxQZXJmb3JtYW5jZTp0cnVlLFBlcm1pc3Npb25TdGF0dXM6
+dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uOnRydWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkxpc3Q6
+dHJ1ZSxQcmVzZW50YXRpb25SZXF1ZXN0OnRydWUsUmVsYXRpdmVPcmllbnRhdGlvblNlbnNvcjp0cnVl
+LFJlbW90ZVBsYXliYWNrOnRydWUsUlRDRGF0YUNoYW5uZWw6dHJ1ZSxEYXRhQ2hhbm5lbDp0cnVlLFJU
+Q0RUTUZTZW5kZXI6dHJ1ZSxSVENQZWVyQ29ubmVjdGlvbjp0cnVlLHdlYmtpdFJUQ1BlZXJDb25uZWN0
+aW9uOnRydWUsbW96UlRDUGVlckNvbm5lY3Rpb246dHJ1ZSxTY3JlZW5PcmllbnRhdGlvbjp0cnVlLFNl
+bnNvcjp0cnVlLFNlcnZpY2VXb3JrZXI6dHJ1ZSxTZXJ2aWNlV29ya2VyQ29udGFpbmVyOnRydWUsU2Vy
+dmljZVdvcmtlclJlZ2lzdHJhdGlvbjp0cnVlLFNoYXJlZFdvcmtlcjp0cnVlLFNwZWVjaFJlY29nbml0
+aW9uOnRydWUsU3BlZWNoU3ludGhlc2lzOnRydWUsU3BlZWNoU3ludGhlc2lzVXR0ZXJhbmNlOnRydWUs
+VlI6dHJ1ZSxWUkRldmljZTp0cnVlLFZSRGlzcGxheTp0cnVlLFZSU2Vzc2lvbjp0cnVlLFZpc3VhbFZp
+ZXdwb3J0OnRydWUsV2ViU29ja2V0OnRydWUsV29ya2VyOnRydWUsV29ya2VyUGVyZm9ybWFuY2U6dHJ1
+ZSxCbHVldG9vdGhEZXZpY2U6dHJ1ZSxCbHVldG9vdGhSZW1vdGVHQVRUQ2hhcmFjdGVyaXN0aWM6dHJ1
+ZSxDbGlwYm9hcmQ6dHJ1ZSxNb2pvSW50ZXJmYWNlSW50ZXJjZXB0b3I6dHJ1ZSxVU0I6dHJ1ZSxJREJE
+YXRhYmFzZTp0cnVlLElEQk9wZW5EQlJlcXVlc3Q6dHJ1ZSxJREJWZXJzaW9uQ2hhbmdlUmVxdWVzdDp0
+cnVlLElEQlJlcXVlc3Q6dHJ1ZSxJREJUcmFuc2FjdGlvbjp0cnVlLEFuYWx5c2VyTm9kZTp0cnVlLFJl
+YWx0aW1lQW5hbHlzZXJOb2RlOnRydWUsQXVkaW9CdWZmZXJTb3VyY2VOb2RlOnRydWUsQXVkaW9EZXN0
+aW5hdGlvbk5vZGU6dHJ1ZSxBdWRpb05vZGU6dHJ1ZSxBdWRpb1NjaGVkdWxlZFNvdXJjZU5vZGU6dHJ1
+ZSxBdWRpb1dvcmtsZXROb2RlOnRydWUsQmlxdWFkRmlsdGVyTm9kZTp0cnVlLENoYW5uZWxNZXJnZXJO
+b2RlOnRydWUsQXVkaW9DaGFubmVsTWVyZ2VyOnRydWUsQ2hhbm5lbFNwbGl0dGVyTm9kZTp0cnVlLEF1
+ZGlvQ2hhbm5lbFNwbGl0dGVyOnRydWUsQ29uc3RhbnRTb3VyY2VOb2RlOnRydWUsQ29udm9sdmVyTm9k
+ZTp0cnVlLERlbGF5Tm9kZTp0cnVlLER5bmFtaWNzQ29tcHJlc3Nvck5vZGU6dHJ1ZSxHYWluTm9kZTp0
+cnVlLEF1ZGlvR2Fpbk5vZGU6dHJ1ZSxJSVJGaWx0ZXJOb2RlOnRydWUsTWVkaWFFbGVtZW50QXVkaW9T
+b3VyY2VOb2RlOnRydWUsTWVkaWFTdHJlYW1BdWRpb0Rlc3RpbmF0aW9uTm9kZTp0cnVlLE1lZGlhU3Ry
+ZWFtQXVkaW9Tb3VyY2VOb2RlOnRydWUsT3NjaWxsYXRvck5vZGU6dHJ1ZSxPc2NpbGxhdG9yOnRydWUs
+UGFubmVyTm9kZTp0cnVlLEF1ZGlvUGFubmVyTm9kZTp0cnVlLHdlYmtpdEF1ZGlvUGFubmVyTm9kZTp0
+cnVlLFNjcmlwdFByb2Nlc3Nvck5vZGU6dHJ1ZSxKYXZhU2NyaXB0QXVkaW9Ob2RlOnRydWUsU3RlcmVv
+UGFubmVyTm9kZTp0cnVlLFdhdmVTaGFwZXJOb2RlOnRydWUsRXZlbnRUYXJnZXQ6ZmFsc2UsRmlsZTp0
+cnVlLEZpbGVMaXN0OnRydWUsRmlsZVdyaXRlcjp0cnVlLEhUTUxGb3JtRWxlbWVudDp0cnVlLEdhbWVw
+YWQ6dHJ1ZSxHYW1lcGFkQnV0dG9uOnRydWUsSGlzdG9yeTp0cnVlLEhUTUxDb2xsZWN0aW9uOnRydWUs
+SFRNTEZvcm1Db250cm9sc0NvbGxlY3Rpb246dHJ1ZSxIVE1MT3B0aW9uc0NvbGxlY3Rpb246dHJ1ZSxI
+VE1MRG9jdW1lbnQ6dHJ1ZSxYTUxIdHRwUmVxdWVzdDp0cnVlLFhNTEh0dHBSZXF1ZXN0VXBsb2FkOnRy
+dWUsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpmYWxzZSxJbWFnZURhdGE6dHJ1ZSxIVE1MSW5wdXRF
+bGVtZW50OnRydWUsS2V5Ym9hcmRFdmVudDp0cnVlLEhUTUxMSUVsZW1lbnQ6dHJ1ZSxMb2NhdGlvbjp0
+cnVlLE1lZGlhTGlzdDp0cnVlLE1lc3NhZ2VQb3J0OnRydWUsSFRNTE1ldGVyRWxlbWVudDp0cnVlLE1J
+RElJbnB1dE1hcDp0cnVlLE1JRElPdXRwdXRNYXA6dHJ1ZSxNaW1lVHlwZTp0cnVlLE1pbWVUeXBlQXJy
+YXk6dHJ1ZSxNb3VzZUV2ZW50OnRydWUsRHJhZ0V2ZW50OnRydWUsUG9pbnRlckV2ZW50OnRydWUsV2hl
+ZWxFdmVudDp0cnVlLERvY3VtZW50RnJhZ21lbnQ6dHJ1ZSxTaGFkb3dSb290OnRydWUsRG9jdW1lbnRU
+eXBlOnRydWUsTm9kZTpmYWxzZSxOb2RlTGlzdDp0cnVlLFJhZGlvTm9kZUxpc3Q6dHJ1ZSxIVE1MT3B0
+aW9uRWxlbWVudDp0cnVlLEhUTUxPdXRwdXRFbGVtZW50OnRydWUsSFRNTFBhcmFncmFwaEVsZW1lbnQ6
+dHJ1ZSxIVE1MUGFyYW1FbGVtZW50OnRydWUsUGx1Z2luOnRydWUsUGx1Z2luQXJyYXk6dHJ1ZSxQcmVz
+ZW50YXRpb25BdmFpbGFiaWxpdHk6dHJ1ZSxIVE1MUHJvZ3Jlc3NFbGVtZW50OnRydWUsUHJvZ3Jlc3NF
+dmVudDp0cnVlLFJlc291cmNlUHJvZ3Jlc3NFdmVudDp0cnVlLFJUQ1N0YXRzUmVwb3J0OnRydWUsSFRN
+TFNlbGVjdEVsZW1lbnQ6dHJ1ZSxTb3VyY2VCdWZmZXI6dHJ1ZSxTb3VyY2VCdWZmZXJMaXN0OnRydWUs
+U3BlZWNoR3JhbW1hcjp0cnVlLFNwZWVjaEdyYW1tYXJMaXN0OnRydWUsU3BlZWNoUmVjb2duaXRpb25S
+ZXN1bHQ6dHJ1ZSxTdG9yYWdlOnRydWUsU3RvcmFnZUV2ZW50OnRydWUsQ1NTU3R5bGVTaGVldDp0cnVl
+LFN0eWxlU2hlZXQ6dHJ1ZSxIVE1MVGFibGVFbGVtZW50OnRydWUsSFRNTFRhYmxlUm93RWxlbWVudDp0
+cnVlLEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OnRydWUsSFRNTFRlbXBsYXRlRWxlbWVudDp0cnVlLEhU
+TUxUZXh0QXJlYUVsZW1lbnQ6dHJ1ZSxUZXh0VHJhY2s6dHJ1ZSxUZXh0VHJhY2tDdWU6dHJ1ZSxWVFRD
+dWU6dHJ1ZSxUZXh0VHJhY2tDdWVMaXN0OnRydWUsVGV4dFRyYWNrTGlzdDp0cnVlLFRpbWVSYW5nZXM6
+dHJ1ZSxUb3VjaDp0cnVlLFRvdWNoTGlzdDp0cnVlLFRyYWNrRGVmYXVsdExpc3Q6dHJ1ZSxDb21wb3Np
+dGlvbkV2ZW50OnRydWUsRm9jdXNFdmVudDp0cnVlLFRleHRFdmVudDp0cnVlLFRvdWNoRXZlbnQ6dHJ1
+ZSxVSUV2ZW50OmZhbHNlLFVSTDp0cnVlLFZpZGVvVHJhY2tMaXN0OnRydWUsV2luZG93OnRydWUsRE9N
+V2luZG93OnRydWUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxTZXJ2aWNlV29ya2VyR2xv
+YmFsU2NvcGU6dHJ1ZSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTp0cnVlLFdvcmtlckdsb2JhbFNjb3Bl
+OnRydWUsQXR0cjp0cnVlLENTU1J1bGVMaXN0OnRydWUsQ2xpZW50UmVjdDp0cnVlLERPTVJlY3Q6dHJ1
+ZSxHYW1lcGFkTGlzdDp0cnVlLE5hbWVkTm9kZU1hcDp0cnVlLE1vek5hbWVkQXR0ck1hcDp0cnVlLFNw
+ZWVjaFJlY29nbml0aW9uUmVzdWx0TGlzdDp0cnVlLFN0eWxlU2hlZXRMaXN0OnRydWUsSURCQ3Vyc29y
+OmZhbHNlLElEQkN1cnNvcldpdGhWYWx1ZTp0cnVlLElEQktleVJhbmdlOnRydWUsSURCT2JzZXJ2YXRp
+b246dHJ1ZSxTVkdBbmdsZTp0cnVlLFNWR0xlbmd0aDp0cnVlLFNWR0xlbmd0aExpc3Q6dHJ1ZSxTVkdO
+dW1iZXI6dHJ1ZSxTVkdOdW1iZXJMaXN0OnRydWUsU1ZHUG9pbnRMaXN0OnRydWUsU1ZHU2NyaXB0RWxl
+bWVudDp0cnVlLFNWR1N0cmluZ0xpc3Q6dHJ1ZSxTVkdBRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVFbGVt
+ZW50OnRydWUsU1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlVHJhbnNmb3JtRWxl
+bWVudDp0cnVlLFNWR0FuaW1hdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdDaXJjbGVFbGVtZW50OnRydWUsU1ZH
+Q2xpcFBhdGhFbGVtZW50OnRydWUsU1ZHRGVmc0VsZW1lbnQ6dHJ1ZSxTVkdEZXNjRWxlbWVudDp0cnVl
+LFNWR0Rpc2NhcmRFbGVtZW50OnRydWUsU1ZHRWxsaXBzZUVsZW1lbnQ6dHJ1ZSxTVkdGRUJsZW5kRWxl
+bWVudDp0cnVlLFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OnRydWUsU1ZHRkVDb21wb25lbnRUcmFuc2Zl
+ckVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbnZvbHZlTWF0cml4
+RWxlbWVudDp0cnVlLFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDp0cnVlLFNWR0ZFRGlzcGxhY2Vt
+ZW50TWFwRWxlbWVudDp0cnVlLFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFRmxvb2RF
+bGVtZW50OnRydWUsU1ZHRkVGdW5jQUVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNCRWxlbWVudDp0cnVlLFNW
+R0ZFRnVuY0dFbGVtZW50OnRydWUsU1ZHRkVGdW5jUkVsZW1lbnQ6dHJ1ZSxTVkdGRUdhdXNzaWFuQmx1
+ckVsZW1lbnQ6dHJ1ZSxTVkdGRUltYWdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VFbGVtZW50OnRydWUs
+U1ZHRkVNZXJnZU5vZGVFbGVtZW50OnRydWUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDp0cnVlLFNWR0ZF
+T2Zmc2V0RWxlbWVudDp0cnVlLFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVNwZWN1bGFy
+TGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVUaWxlRWxl
+bWVudDp0cnVlLFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6dHJ1ZSxTVkdGaWx0ZXJFbGVtZW50OnRydWUs
+U1ZHRm9yZWlnbk9iamVjdEVsZW1lbnQ6dHJ1ZSxTVkdHRWxlbWVudDp0cnVlLFNWR0dlb21ldHJ5RWxl
+bWVudDp0cnVlLFNWR0dyYXBoaWNzRWxlbWVudDp0cnVlLFNWR0ltYWdlRWxlbWVudDp0cnVlLFNWR0xp
+bmVFbGVtZW50OnRydWUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHTWFya2VyRWxlbWVu
+dDp0cnVlLFNWR01hc2tFbGVtZW50OnRydWUsU1ZHTWV0YWRhdGFFbGVtZW50OnRydWUsU1ZHUGF0aEVs
+ZW1lbnQ6dHJ1ZSxTVkdQYXR0ZXJuRWxlbWVudDp0cnVlLFNWR1BvbHlnb25FbGVtZW50OnRydWUsU1ZH
+UG9seWxpbmVFbGVtZW50OnRydWUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHUmVjdEVs
+ZW1lbnQ6dHJ1ZSxTVkdTZXRFbGVtZW50OnRydWUsU1ZHU3RvcEVsZW1lbnQ6dHJ1ZSxTVkdTdHlsZUVs
+ZW1lbnQ6dHJ1ZSxTVkdTVkdFbGVtZW50OnRydWUsU1ZHU3dpdGNoRWxlbWVudDp0cnVlLFNWR1N5bWJv
+bEVsZW1lbnQ6dHJ1ZSxTVkdUU3BhbkVsZW1lbnQ6dHJ1ZSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6dHJ1
+ZSxTVkdUZXh0RWxlbWVudDp0cnVlLFNWR1RleHRQYXRoRWxlbWVudDp0cnVlLFNWR1RleHRQb3NpdGlv
+bmluZ0VsZW1lbnQ6dHJ1ZSxTVkdUaXRsZUVsZW1lbnQ6dHJ1ZSxTVkdVc2VFbGVtZW50OnRydWUsU1ZH
+Vmlld0VsZW1lbnQ6dHJ1ZSxTVkdHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdDb21wb25lbnRUcmFuc2Zl
+ckZ1bmN0aW9uRWxlbWVudDp0cnVlLFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6dHJ1ZSxTVkdNUGF0aEVs
+ZW1lbnQ6dHJ1ZSxTVkdFbGVtZW50OmZhbHNlLFNWR1RyYW5zZm9ybTp0cnVlLFNWR1RyYW5zZm9ybUxp
+c3Q6dHJ1ZSxBdWRpb0J1ZmZlcjp0cnVlLEF1ZGlvUGFyYW06dHJ1ZSxBdWRpb1BhcmFtTWFwOnRydWUs
+QXVkaW9UcmFja0xpc3Q6dHJ1ZSxBdWRpb0NvbnRleHQ6dHJ1ZSx3ZWJraXRBdWRpb0NvbnRleHQ6dHJ1
+ZSxCYXNlQXVkaW9Db250ZXh0OmZhbHNlLE9mZmxpbmVBdWRpb0NvbnRleHQ6dHJ1ZSxTUUxSZXN1bHRT
+ZXRSb3dMaXN0OnRydWV9KQpILmIwLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXci
+CkguUkcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5WUC4kbmF0aXZlU3Vw
+ZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILkRnLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJh
+eUJ1ZmZlclZpZXciCkguV0IuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5a
+Ry4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlBnLiRuYXRpdmVTdXBlcmNs
+YXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciClcub0guJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkV2ZW50VGFy
+Z2V0IgpXLkNFLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJFdmVudFRhcmdldCIKVy5RVi4kbmF0aXZlU3Vw
+ZXJjbGFzc1RhZz0iRXZlbnRUYXJnZXQiClcuQXcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkV2ZW50VGFy
+Z2V0In0pKCkKY29udmVydEFsbFRvRmFzdE9iamVjdCh3KQpjb252ZXJ0VG9GYXN0T2JqZWN0KCQpOyhm
+dW5jdGlvbihhKXtpZih0eXBlb2YgZG9jdW1lbnQ9PT0idW5kZWZpbmVkIil7YShudWxsKQpyZXR1cm59
+aWYodHlwZW9mIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQhPSd1bmRlZmluZWQnKXthKGRvY3VtZW50LmN1
+cnJlbnRTY3JpcHQpCnJldHVybn12YXIgdD1kb2N1bWVudC5zY3JpcHRzCmZ1bmN0aW9uIG9uTG9hZChi
+KXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoOysrcil0W3JdLnJlbW92ZUV2ZW50TGlzdGVuZXIoImxvYWQi
+LG9uTG9hZCxmYWxzZSkKYShiLnRhcmdldCl9Zm9yKHZhciBzPTA7czx0Lmxlbmd0aDsrK3MpdFtzXS5h
+ZGRFdmVudExpc3RlbmVyKCJsb2FkIixvbkxvYWQsZmFsc2UpfSkoZnVuY3Rpb24oYSl7di5jdXJyZW50
+U2NyaXB0PWEKaWYodHlwZW9mIGRhcnRNYWluUnVubmVyPT09ImZ1bmN0aW9uIilkYXJ0TWFpblJ1bm5l
+cihMLkRlLFtdKQplbHNlIEwuRGUoW10pfSl9KSgpCi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1pZ3JhdGlv
+bi5qcy5tYXAK
''';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index 4b12674..3af7d6f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -99,7 +99,7 @@
Either2<Command, CodeAction> _createAssistAction(Assist assist) {
return Either2<Command, CodeAction>.t2(CodeAction(
assist.change.message,
- CodeActionKind.Refactor,
+ toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
const [],
createWorkspaceEdit(server, assist.change.edits),
null,
@@ -114,7 +114,7 @@
Fix fix, Diagnostic diagnostic) {
return Either2<Command, CodeAction>.t2(CodeAction(
fix.change.message,
- CodeActionKind.QuickFix,
+ toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
[diagnostic],
createWorkspaceEdit(server, fix.change.edits),
null,
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index ab35b3f..00efe02 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -605,6 +605,20 @@
lsp.ClosingLabel(
toRange(lineInfo, label.offset, label.length), label.label);
+CodeActionKind toCodeActionKind(String id, lsp.CodeActionKind fallback) {
+ if (id == null) {
+ return fallback;
+ }
+ // Dart fixes and assists start with "dart.assist." and "dart.fix." but in LSP
+ // we want to use the predefined prefixes for CodeActions.
+ final newId = id
+ .replaceAll('dart.assist', CodeActionKind.Refactor.toString())
+ .replaceAll('dart.fix', CodeActionKind.QuickFix.toString())
+ .replaceAll('analysisOptions.assist', CodeActionKind.Refactor.toString())
+ .replaceAll('analysisOptions.fix', CodeActionKind.QuickFix.toString());
+ return CodeActionKind(newId);
+}
+
lsp.CompletionItem toCompletionItem(
lsp.TextDocumentClientCapabilitiesCompletion completionCapabilities,
HashSet<lsp.CompletionItemKind> supportedCompletionItemKinds,
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 88ab0fd..0ed0c88 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -40,7 +40,9 @@
final codeActions = await getCodeActions(mainFileUri.toString(),
range: rangeFromMarkers(content));
final assist = findEditAction(
- codeActions, CodeActionKind.Refactor, "Add explicit 'show' combinator");
+ codeActions,
+ CodeActionKind('refactor.add.showCombinator'),
+ "Add explicit 'show' combinator");
// Ensure the edit came back, and using documentChanges.
expect(assist, isNotNull);
@@ -77,7 +79,9 @@
final codeActions = await getCodeActions(mainFileUri.toString(),
range: rangeFromMarkers(content));
final assistAction = findEditAction(
- codeActions, CodeActionKind.Refactor, "Add explicit 'show' combinator");
+ codeActions,
+ CodeActionKind('refactor.add.showCombinator'),
+ "Add explicit 'show' combinator");
// Ensure the edit came back, and using changes.
expect(assistAction, isNotNull);
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index fa93a77..f2485a1 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -40,8 +40,8 @@
final codeActions = await getCodeActions(mainFileUri.toString(),
range: rangeFromMarkers(content));
- final fixAction = findEditAction(
- codeActions, CodeActionKind.QuickFix, 'Remove unused import');
+ final fixAction = findEditAction(codeActions,
+ CodeActionKind('quickfix.remove.unusedImport'), 'Remove unused import');
// Ensure the edit came back, and using documentChanges.
expect(fixAction, isNotNull);
@@ -78,8 +78,8 @@
final codeActions = await getCodeActions(mainFileUri.toString(),
range: rangeFromMarkers(content));
- final fixAction = findEditAction(
- codeActions, CodeActionKind.QuickFix, 'Remove unused import');
+ final fixAction = findEditAction(codeActions,
+ CodeActionKind('quickfix.remove.unusedImport'), 'Remove unused import');
// Ensure the edit came back, and using changes.
expect(fixAction, isNotNull);
diff --git a/pkg/analysis_server/test/src/cider/cider_service.dart b/pkg/analysis_server/test/src/cider/cider_service.dart
new file mode 100644
index 0000000..e2c8bb1
--- /dev/null
+++ b/pkg/analysis_server/test/src/cider/cider_service.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
+import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/micro/resolve_file.dart';
+import 'package:analyzer/src/test_utilities/mock_sdk.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:crypto/crypto.dart';
+import 'package:linter/src/rules.dart';
+
+class CiderServiceTest with ResourceProviderMixin {
+ static final String _testPath = '/workspace/dart/test/lib/test.dart';
+
+ final ByteStore byteStore = MemoryByteStore();
+
+ final StringBuffer logBuffer = StringBuffer();
+ PerformanceLog logger;
+ MockSdk sdk;
+
+ FileResolver fileResolver;
+
+ String get testPath => _testPath;
+
+ /// Create a new [FileResolver] into [fileResolver].
+ ///
+ /// We do this the first time, and to test reusing results from [byteStore].
+ void createFileResolver() {
+ var workspace = BazelWorkspace.find(
+ resourceProvider,
+ convertPath(_testPath),
+ );
+
+ fileResolver = FileResolver(
+ logger,
+ resourceProvider,
+ byteStore,
+ workspace.createSourceFactory(sdk, null),
+ (String path) => _getDigest(path),
+ null,
+ workspace: workspace,
+ );
+ fileResolver.testView = FileResolverTestView();
+ }
+
+ void setUp() {
+ registerLintRules();
+
+ logger = PerformanceLog(logBuffer);
+ sdk = MockSdk(resourceProvider: resourceProvider);
+
+ newFile('/workspace/WORKSPACE', content: '');
+ createFileResolver();
+ }
+
+ String _getDigest(String path) {
+ try {
+ var content = resourceProvider.getFile(path).readAsStringSync();
+ var contentBytes = utf8.encode(content);
+ return md5.convert(contentBytes).toString();
+ } catch (_) {
+ return '';
+ }
+ }
+}
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
new file mode 100644
index 0000000..1d14888
--- /dev/null
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -0,0 +1,234 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/cider/completion.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart'
+ show CompletionSuggestion, ElementKind;
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'cider_service.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(CiderCompletionComputerTest);
+ });
+}
+
+@reflectiveTest
+class CiderCompletionComputerTest extends CiderServiceTest {
+ final CiderCompletionCache _completionCache = CiderCompletionCache();
+
+ CiderCompletionResult _completionResult;
+ List<CompletionSuggestion> _suggestions;
+
+ @override
+ void setUp() {
+ super.setUp();
+ }
+
+ Future<void> test_compute() async {
+ var context = _updateFile(r'''
+class A {}
+
+int a = 0;
+
+main(int b) {
+ int c = 0;
+ ^
+}
+''');
+
+ // ignore: deprecated_member_use_from_same_package
+ _suggestions = await _newComputer().compute(
+ testPath,
+ context.offset,
+ );
+
+ _assertHasCompletion(text: 'a');
+ _assertHasCompletion(text: 'b');
+ _assertHasCompletion(text: 'c');
+ _assertHasClass(text: 'A');
+ _assertHasClass(text: 'String');
+
+ _assertNoClass(text: 'Random');
+ }
+
+ Future<void> test_compute2() async {
+ await _compute2(r'''
+class A {}
+
+int a = 0;
+
+main(int b) {
+ int c = 0;
+ ^
+}
+''');
+
+ _assertHasCompletion(text: 'a');
+ _assertHasCompletion(text: 'b');
+ _assertHasCompletion(text: 'c');
+ _assertHasClass(text: 'A');
+ _assertHasClass(text: 'String');
+
+ _assertNoClass(text: 'Random');
+ }
+
+ Future<void> test_compute2_updateImportedLibrary() async {
+ var corePath = convertPath('/sdk/lib/core/core.dart');
+
+ var aPath = convertPath('/workspace/dart/test/lib/a.dart');
+ newFile(aPath, content: r'''
+class A {}
+''');
+
+ var content = r'''
+import 'a.dart';
+^
+''';
+
+ _createFileResolver();
+ await _compute2(content);
+ _assertComputedImportedLibraries([corePath, aPath]);
+ _assertHasClass(text: 'A');
+
+ // Repeat the query, still has 'A'.
+ _createFileResolver();
+ await _compute2(content);
+ _assertComputedImportedLibraries([]);
+ _assertHasClass(text: 'A');
+
+ // Update the imported library, has 'B', but not 'A'.
+ newFile(aPath, content: r'''
+class B {}
+''');
+ _createFileResolver();
+ await _compute2(content);
+ _assertComputedImportedLibraries([aPath]);
+ _assertHasClass(text: 'B');
+ _assertNoClass(text: 'A');
+ }
+
+ Future<void> test_compute2_updateImports() async {
+ var corePath = convertPath('/sdk/lib/core/core.dart');
+
+ var aPath = convertPath('/workspace/dart/test/lib/a.dart');
+ newFile(aPath, content: r'''
+class A {}
+''');
+
+ _createFileResolver();
+ await _compute2(r'''
+var a = ^;
+''');
+ _assertComputedImportedLibraries([corePath]);
+ _assertHasClass(text: 'String');
+
+ // Repeat the query, still has 'A'.
+ _createFileResolver();
+ await _compute2(r'''
+import 'a.dart';
+var a = ^;
+''');
+ _assertComputedImportedLibraries([aPath]);
+ _assertHasClass(text: 'A');
+ _assertHasClass(text: 'String');
+ }
+
+ void _assertComputedImportedLibraries(List<String> expected) {
+ expected = expected.map(convertPath).toList();
+ expect(
+ _completionResult.computedImportedLibraries,
+ unorderedEquals(expected),
+ );
+ }
+
+ void _assertHasClass({@required String text}) {
+ var matching = _matchingCompletions(
+ text: text,
+ elementKind: ElementKind.CLASS,
+ );
+ expect(matching, hasLength(1), reason: 'Expected exactly one completion');
+ }
+
+ void _assertHasCompletion({@required String text}) {
+ var matching = _matchingCompletions(text: text);
+ expect(matching, hasLength(1), reason: 'Expected exactly one completion');
+ }
+
+ void _assertNoClass({@required String text}) {
+ var matching = _matchingCompletions(
+ text: text,
+ elementKind: ElementKind.CLASS,
+ );
+ expect(matching, isEmpty, reason: 'Expected zero completions');
+ }
+
+ Future _compute2(String content) async {
+ var context = _updateFile(content);
+
+ _completionResult = await _newComputer().compute2(
+ path: testPath,
+ line: context.line,
+ character: context.character,
+ );
+ _suggestions = _completionResult.suggestions;
+ }
+
+ /// TODO(scheglov) Implement incremental updating
+ void _createFileResolver() {
+ createFileResolver();
+ }
+
+ List<CompletionSuggestion> _matchingCompletions({
+ @required String text,
+ ElementKind elementKind,
+ }) {
+ return _suggestions.where((e) {
+ if (e.completion != text) {
+ return false;
+ }
+
+ if (elementKind != null && e.element.kind != elementKind) {
+ return false;
+ }
+
+ return true;
+ }).toList();
+ }
+
+ CiderCompletionComputer _newComputer() {
+ return CiderCompletionComputer(logger, _completionCache, fileResolver);
+ }
+
+ _CompletionContext _updateFile(String content) {
+ newFile(testPath, content: content);
+
+ var offset = content.indexOf('^');
+ expect(offset, isPositive, reason: 'Expected to find ^');
+ expect(content.indexOf('^', offset + 1), -1, reason: 'Expected only one ^');
+
+ var lineInfo = LineInfo.fromContent(content);
+ var location = lineInfo.getLocation(offset);
+
+ return _CompletionContext(
+ content,
+ offset,
+ location.lineNumber - 1,
+ location.columnNumber - 1,
+ );
+ }
+}
+
+class _CompletionContext {
+ final String content;
+ final int offset;
+ final int line;
+ final int character;
+
+ _CompletionContext(this.content, this.offset, this.line, this.character);
+}
diff --git a/pkg/analysis_server/test/src/cider/test_all.dart b/pkg/analysis_server/test/src/cider/test_all.dart
new file mode 100644
index 0000000..dfae1ef
--- /dev/null
+++ b/pkg/analysis_server/test/src/cider/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'completion_test.dart' as completion;
+
+void main() {
+ defineReflectiveSuite(() {
+ completion.main();
+ });
+}
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index 06f77f0..0dc0d54 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -280,7 +280,26 @@
replacement: ''));
}
- Future<void> test_conditionFalseInStrongMode() async {
+ Future<void> test_conditionFalseInStrongMode_expression() async {
+ var unit = await buildInfoForSingleTestFile(
+ 'int f(String s) => s == null ? 0 : s.length;',
+ migratedContent:
+ 'int f(String s) => s == null /* == false */ ? 0 : s.length;',
+ warnOnWeakCode: true);
+ var insertedComment = '/* == false */';
+ var insertedCommentOffset = unit.content.indexOf(insertedComment);
+ var region = unit.regions
+ .where((region) => region.offset == insertedCommentOffset)
+ .single;
+ assertRegion(
+ region: region,
+ length: insertedComment.length,
+ explanation: 'Condition will always be false in strong checking mode',
+ kind: NullabilityFixKind.conditionFalseInStrongMode,
+ edits: isEmpty);
+ }
+
+ Future<void> test_conditionFalseInStrongMode_if() async {
var unit = await buildInfoForSingleTestFile('''
int f(String s) {
if (s == null) {
@@ -311,7 +330,26 @@
edits: isEmpty);
}
- Future<void> test_conditionTrueInStrongMode() async {
+ Future<void> test_conditionTrueInStrongMode_expression() async {
+ var unit = await buildInfoForSingleTestFile(
+ 'int f(String s) => s != null ? s.length : 0;',
+ migratedContent:
+ 'int f(String s) => s != null /* == true */ ? s.length : 0;',
+ warnOnWeakCode: true);
+ var insertedComment = '/* == true */';
+ var insertedCommentOffset = unit.content.indexOf(insertedComment);
+ var region = unit.regions
+ .where((region) => region.offset == insertedCommentOffset)
+ .single;
+ assertRegion(
+ region: region,
+ length: insertedComment.length,
+ explanation: 'Condition will always be true in strong checking mode',
+ kind: NullabilityFixKind.conditionTrueInStrongMode,
+ edits: isEmpty);
+ }
+
+ Future<void> test_conditionTrueInStrongMode_if() async {
var unit = await buildInfoForSingleTestFile('''
int f(String s) {
if (s != null) {
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart
index 2f1638e..1681ecc 100644
--- a/pkg/analysis_server/test/src/test_all.dart
+++ b/pkg/analysis_server/test/src/test_all.dart
@@ -4,6 +4,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'cider/test_all.dart' as cider;
import 'computer/test_all.dart' as computer;
import 'domain_abstract_test.dart' as domain_abstract;
import 'domains/test_all.dart' as domains;
@@ -17,6 +18,7 @@
void main() {
defineReflectiveSuite(() {
+ cider.main();
computer.main();
domain_abstract.main();
domains.main();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index fd5f01c..818e0b0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -231,8 +231,10 @@
AnalysisErrorListener errorListener = _getErrorListener(file);
ErrorReporter errorReporter = _getErrorReporter(file);
- unit.accept(DeadCodeVerifier(errorReporter, unit.featureSet,
- typeSystem: _typeSystem));
+ if (!_libraryElement.isNonNullableByDefault) {
+ unit.accept(DeadCodeVerifier(errorReporter, unit.featureSet,
+ typeSystem: _typeSystem));
+ }
// Dart2js analysis.
if (_analysisOptions.dart2jsHint) {
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index d599435..6f4e1f1 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -150,7 +150,15 @@
isNonNullableByDefault: isNonNullableByDefault,
);
- implemented = superInterface.implemented;
+ if (isNonNullableByDefault) {
+ implemented = superInterface.implemented;
+ } else {
+ implemented = {};
+ for (var entry in superInterface.implemented.entries) {
+ implemented[entry.key] = Member.legacy(entry.value);
+ }
+ }
+
superImplemented.add(implemented);
} else {
implemented = {};
@@ -182,13 +190,17 @@
var currentList = namedCandidates[name];
if (currentList == null) {
- namedCandidates[name] = [candidate];
+ namedCandidates[name] = [
+ isNonNullableByDefault ? candidate : Member.legacy(candidate),
+ ];
continue;
}
var current = currentList.single;
if (candidate.enclosingElement == mixinElement) {
- namedCandidates[name] = [candidate];
+ namedCandidates[name] = [
+ isNonNullableByDefault ? candidate : Member.legacy(candidate),
+ ];
if (current.kind != candidate.kind) {
var currentIsGetter = current.kind == ElementKind.GETTER;
mixinConflicts.add(
@@ -215,23 +227,19 @@
doTopMerge: true,
);
for (var entry in map.entries) {
- namedCandidates[entry.key] = [entry.value];
+ namedCandidates[entry.key] = [
+ isNonNullableByDefault
+ ? entry.value
+ : Member.legacy(entry.value),
+ ];
}
}
mixinsConflicts.add(mixinConflicts);
implemented = <Name, ExecutableElement>{}..addAll(implemented);
- implemented.addEntries(
- interfaceObj.implemented.entries.where((entry) {
- var executable = entry.value;
- if (executable.isAbstract) {
- return false;
- }
- var class_ = executable.enclosingElement;
- return class_ is ClassElement && !class_.isDartCoreObject;
- }),
- );
+ _addMixinMembers(implemented, interfaceObj,
+ isNonNullableByDefault: isNonNullableByDefault);
superImplemented.add(implemented);
}
@@ -307,6 +315,30 @@
return interface;
}
+ void _addMixinMembers(
+ Map<Name, ExecutableElement> implemented,
+ Interface mixin, {
+ @required bool isNonNullableByDefault,
+ }) {
+ for (var entry in mixin.implemented.entries) {
+ var executable = entry.value;
+ if (executable.isAbstract) {
+ continue;
+ }
+
+ var class_ = executable.enclosingElement;
+ if (class_ is ClassElement && class_.isDartCoreObject) {
+ continue;
+ }
+
+ if (!isNonNullableByDefault) {
+ executable = Member.legacy(executable);
+ }
+
+ implemented[entry.key] = executable;
+ }
+ }
+
/// Return the member with the given [name].
///
/// If [concrete] is `true`, the the concrete implementation is returned,
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index eda8b3d..23be79f 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -388,29 +388,13 @@
}
class FunctionMember extends ExecutableMember implements FunctionElement {
- factory FunctionMember(
- FunctionElement declaration,
- MapSubstitution substitution,
- bool isLegacy,
- ) {
- var freshTypeParameters = _SubstitutedTypeParameters(
- declaration.typeParameters,
- substitution,
- );
- return FunctionMember._(
- declaration,
- freshTypeParameters.substitution,
- isLegacy,
- freshTypeParameters.elements,
- );
- }
-
- FunctionMember._(
- FunctionElement declaration,
- MapSubstitution substitution,
- bool isLegacy,
- List<TypeParameterElement> typeParameters,
- ) : super(declaration, substitution, isLegacy, typeParameters);
+ FunctionMember(FunctionElement declaration, bool isLegacy)
+ : super(
+ declaration,
+ Substitution.empty,
+ isLegacy,
+ declaration.typeParameters,
+ );
@override
FunctionElement get declaration => super.declaration;
@@ -658,15 +642,8 @@
} else if (element is FunctionElement) {
if (!element.library.isNonNullableByDefault) {
return element;
- } else if (element is Member) {
- var member = element as Member;
- return FunctionMember(
- member._declaration,
- member._substitution,
- true,
- );
} else {
- return FunctionMember(element, Substitution.empty, true);
+ return FunctionMember(element.declaration, true);
}
} else if (element is MethodElement) {
if (!element.library.isNonNullableByDefault) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index a0db802..d36cdf0 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -276,11 +276,12 @@
if (_flowAnalysis != null) {
flow?.logicalBinaryOp_rightBegin(left, isAnd: true);
- _flowAnalysis.checkUnreachableNode(right);
+ _resolver.checkUnreachableNode(right);
right.accept(_resolver);
right = node.rightOperand;
+ _resolver.nullSafetyDeadCodeVerifier?.flowEnd(right);
flow?.logicalBinaryOp_end(node, right, isAnd: true);
} else {
_promoteManager.visitBinaryExpression_and_rhs(
@@ -302,7 +303,7 @@
void _resolveLogicalOr(BinaryExpressionImpl node) {
var left = node.leftOperand;
- Expression right = node.rightOperand;
+ var right = node.rightOperand;
var flow = _flowAnalysis?.flow;
InferenceContext.setType(left, _typeProvider.boolType);
@@ -313,11 +314,12 @@
left = node.leftOperand;
flow?.logicalBinaryOp_rightBegin(left, isAnd: false);
- _flowAnalysis?.checkUnreachableNode(right);
+ _resolver.checkUnreachableNode(right);
right.accept(_resolver);
right = node.rightOperand;
+ _resolver.nullSafetyDeadCodeVerifier?.flowEnd(right);
flow?.logicalBinaryOp_end(node, right, isAnd: false);
_checkNonBoolOperand(left, '||');
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index e5a22d0..c85c898 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -218,6 +218,14 @@
return false;
}
+ void labeledStatement_enter(LabeledStatement node) {
+ flow.labeledStatement_begin(node);
+ }
+
+ void labeledStatement_exit(LabeledStatement node) {
+ flow.labeledStatement_end();
+ }
+
void topLevelDeclaration_enter(
Declaration node, FormalParameterList parameters, FunctionBody body) {
assert(node != null);
@@ -272,26 +280,28 @@
/// not specify a label), so the default enclosing target is returned.
static Statement getLabelTarget(AstNode node, LabelElement element) {
for (; node != null; node = node.parent) {
- if (node is DoStatement ||
- node is ForStatement ||
- node is SwitchStatement ||
- node is WhileStatement) {
- if (element == null) {
+ if (element == null) {
+ if (node is DoStatement ||
+ node is ForStatement ||
+ node is SwitchStatement ||
+ node is WhileStatement) {
return node;
}
- var parent = node.parent;
- if (parent is LabeledStatement) {
- for (var nodeLabel in parent.labels) {
- if (identical(nodeLabel.label.staticElement, element)) {
+ } else {
+ if (node is LabeledStatement) {
+ if (_hasLabel(node.labels, element)) {
+ var statement = node.statement;
+ if (statement is Block ||
+ statement is IfStatement ||
+ statement is TryStatement) {
return node;
}
+ return statement;
}
}
- }
- if (element != null && node is SwitchStatement) {
- for (var member in node.members) {
- for (var nodeLabel in member.labels) {
- if (identical(nodeLabel.label.staticElement, element)) {
+ if (node is SwitchStatement) {
+ for (var member in node.members) {
+ if (_hasLabel(member.labels, element)) {
return node;
}
}
@@ -300,6 +310,15 @@
}
return null;
}
+
+ static bool _hasLabel(List<Label> labels, LabelElement element) {
+ for (var nodeLabel in labels) {
+ if (identical(nodeLabel.label.staticElement, element)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/// Override of [FlowAnalysisHelper] that invokes methods of
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index 030a398..7844f5b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -34,7 +34,7 @@
}
void resolveStatement(ForStatementImpl node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ _resolver.checkUnreachableNode(node);
var forLoopParts = node.forLoopParts;
if (forLoopParts is ForParts) {
@@ -63,7 +63,9 @@
: null;
if (iteratedType != null) {
- return iteratedType.typeArguments.single;
+ var elementType = iteratedType.typeArguments.single;
+ elementType = _resolver.toLegacyTypeIfOptOut(elementType);
+ return elementType;
} else {
return null;
}
diff --git a/pkg/analyzer/lib/src/error/correct_override.dart b/pkg/analyzer/lib/src/error/correct_override.dart
index e513da0..7d67e40 100644
--- a/pkg/analyzer/lib/src/error/correct_override.dart
+++ b/pkg/analyzer/lib/src/error/correct_override.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
@@ -16,16 +17,12 @@
import 'package:meta/meta.dart';
class CorrectOverrideHelper {
- final LibraryElement _library;
+ final LibraryElementImpl _library;
final TypeSystemImpl _typeSystem;
final ExecutableElement _thisMember;
FunctionType _thisTypeForSubtype;
- bool _hasCovariant = false;
- Substitution _thisSubstitution;
- Substitution _superSubstitution;
-
CorrectOverrideHelper({
@required LibraryElement library,
@required ExecutableElement thisMember,
@@ -42,50 +39,7 @@
superMember = _library.toLegacyElementIfOptOut(superMember);
var superType = superMember.type;
- if (!_typeSystem.isSubtypeOf2(_thisTypeForSubtype, superType)) {
- return false;
- }
-
- // If no covariant parameters, then the subtype checking above is enough.
- if (!_hasCovariant) {
- return true;
- }
-
- _initSubstitutions(superType);
-
- var thisParameters = _thisMember.parameters;
- for (var i = 0; i < thisParameters.length; i++) {
- var thisParameter = thisParameters[i];
- if (thisParameter.isCovariant) {
- var superParameter = _correspondingParameter(
- superType.parameters,
- thisParameter,
- i,
- );
- if (superParameter != null) {
- var thisParameterType = thisParameter.type;
- var superParameterType = superParameter.type;
-
- if (_thisSubstitution != null) {
- thisParameterType = _thisSubstitution.substituteType(
- thisParameterType,
- );
- superParameterType = _superSubstitution.substituteType(
- superParameterType,
- );
- }
-
- if (!_typeSystem.isSubtypeOf2(
- superParameterType, thisParameterType) &&
- !_typeSystem.isSubtypeOf2(
- thisParameterType, superParameterType)) {
- return false;
- }
- }
- }
- }
-
- return true;
+ return _typeSystem.isSubtypeOf2(_thisTypeForSubtype, superType);
}
/// If [_thisMember] is not a correct override of [superMember], report the
@@ -120,7 +74,6 @@
for (var i = 0; i < parameters.length; i++) {
var parameter = parameters[i];
if (parameter.isCovariant) {
- _hasCovariant = true;
newParameters ??= parameters.toList(growable: false);
newParameters[i] = ParameterElementImpl.synthetic(
parameter.name,
@@ -145,35 +98,138 @@
_thisTypeForSubtype = type;
}
}
+}
- /// We know that [_thisMember] has a covariant parameter, which we need
- /// to check against the corresponding parameters in [superType]. their types
- /// should be compatible. If [_thisMember] (and correspondingly [superType])
- /// has type parameters, we need to convert types of formal parameters in
- /// both to the same type parameters.
- void _initSubstitutions(FunctionType superType) {
- var thisParameters = _thisMember.typeParameters;
- var superParameters = superType.typeFormals;
- if (thisParameters.isEmpty) {
- return;
+class CovariantParametersVerifier {
+ final AnalysisSessionImpl _session;
+ final TypeSystemImpl _typeSystem;
+
+ final ExecutableElement _thisMember;
+
+ CovariantParametersVerifier({
+ @required ExecutableElement thisMember,
+ }) : _session = thisMember.library.session,
+ _typeSystem = thisMember.library.typeSystem,
+ _thisMember = thisMember;
+
+ void verify({
+ @required ErrorReporter errorReporter,
+ @required AstNode errorNode,
+ }) {
+ var superParameters = _superParameters();
+ for (var entry in superParameters.entries) {
+ var parameter = entry.key;
+ for (var superParameter in entry.value) {
+ var thisType = parameter.type;
+ var superType = superParameter.type;
+ if (!_typeSystem.isSubtypeOf2(superType, thisType) &&
+ !_typeSystem.isSubtypeOf2(thisType, superType)) {
+ var superMember = superParameter.member;
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INVALID_OVERRIDE,
+ errorNode,
+ [
+ _thisMember.name,
+ _thisMember.enclosingElement.name,
+ _thisMember.type,
+ superMember.enclosingElement.name,
+ superMember.type,
+ ],
+ );
+ }
+ }
+ }
+ }
+
+ List<_SuperMember> _superMembers() {
+ var classHierarchy = _session.classHierarchy;
+ var classElement = _thisMember.enclosingElement;
+ var interfaces = classHierarchy.implementedInterfaces(classElement);
+
+ var superMembers = <_SuperMember>[];
+ for (var interface in interfaces) {
+ var superMember = _correspondingMember(interface.element, _thisMember);
+ if (superMember != null) {
+ superMembers.add(
+ _SuperMember(interface, superMember),
+ );
+ }
}
- var newParameters = <TypeParameterElement>[];
- var newTypes = <TypeParameterType>[];
- for (var i = 0; i < thisParameters.length; i++) {
- var newParameter = TypeParameterElementImpl.synthetic(
- thisParameters[i].name,
- );
- newParameters.add(newParameter);
+ return superMembers;
+ }
- var newType = newParameter.instantiate(
- nullabilitySuffix: NullabilitySuffix.none,
- );
- newTypes.add(newType);
+ Map<ParameterElement, List<_SuperParameter>> _superParameters() {
+ var result = <ParameterElement, List<_SuperParameter>>{};
+
+ List<_SuperMember> superMembers;
+ var parameters = _thisMember.parameters;
+ for (var i = 0; i < parameters.length; i++) {
+ var parameter = parameters[i];
+ if (parameter.isCovariant) {
+ superMembers ??= _superMembers();
+ for (var superMember in superMembers) {
+ var superParameter = _correspondingParameter(
+ superMember.rawElement.parameters,
+ parameter,
+ i,
+ );
+ if (superParameter != null) {
+ var parameterSuperList = (result[parameter] ??= []);
+ var superType = _superSubstitution(superMember)
+ .substituteType(superParameter.type);
+ parameterSuperList.add(
+ _SuperParameter(superParameter, superType),
+ );
+ }
+ }
+ }
}
- _thisSubstitution = Substitution.fromPairs(thisParameters, newTypes);
- _superSubstitution = Substitution.fromPairs(superParameters, newTypes);
+ return result;
+ }
+
+ /// Return the [Substitution] to convert types of [superMember] to types of
+ /// [_thisMember].
+ Substitution _superSubstitution(_SuperMember superMember) {
+ var result = Substitution.fromInterfaceType(superMember.interface);
+
+ // If the executable has type parameters, ensure that super uses the same.
+ var thisTypeParameters = _thisMember.typeParameters;
+ if (thisTypeParameters.isNotEmpty) {
+ var superTypeParameters = superMember.rawElement.typeParameters;
+ if (thisTypeParameters.length == superTypeParameters.length) {
+ var typeParametersSubstitution = Substitution.fromPairs(
+ superTypeParameters,
+ thisTypeParameters.map((e) {
+ return e.instantiate(
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }).toList(),
+ );
+ result = Substitution.combine(result, typeParametersSubstitution);
+ }
+ }
+
+ return result;
+ }
+
+ /// Return a member from [classElement] that corresponds to the [proto],
+ /// or `null` if no such member exist.
+ static ExecutableElement _correspondingMember(
+ ClassElement classElement,
+ ExecutableElement proto,
+ ) {
+ if (proto is MethodElement) {
+ return classElement.getMethod(proto.displayName);
+ }
+ if (proto is PropertyAccessorElement) {
+ if (proto.isGetter) {
+ return classElement.getGetter(proto.displayName);
+ }
+ return classElement.getSetter(proto.displayName);
+ }
+ return null;
}
/// Return an element of [parameters] that corresponds for the [proto],
@@ -201,3 +257,19 @@
return null;
}
}
+
+class _SuperMember {
+ final InterfaceType interface;
+ final ExecutableElement rawElement;
+
+ _SuperMember(this.interface, this.rawElement);
+}
+
+class _SuperParameter {
+ final ParameterElement element;
+ final DartType type;
+
+ _SuperParameter(this.element, this.type);
+
+ ExecutableElement get member => element.enclosingElement;
+}
diff --git a/pkg/analyzer/lib/src/error/dead_code_verifier.dart b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
index 0edeacd..780f770 100644
--- a/pkg/analyzer/lib/src/error/dead_code_verifier.dart
+++ b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
@@ -10,13 +10,22 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/type_system.dart';
+typedef _CatchClausesVerifierReporter = void Function(
+ CatchClause first,
+ CatchClause last,
+ ErrorCode,
+ List<Object> arguments,
+);
+
/// A visitor that finds dead code and unused labels.
class DeadCodeVerifier extends RecursiveAstVisitor<void> {
/// The error reporter by which errors will be reported.
@@ -265,67 +274,27 @@
void visitTryStatement(TryStatement node) {
node.body?.accept(this);
node.finallyBlock?.accept(this);
- NodeList<CatchClause> catchClauses = node.catchClauses;
- int numOfCatchClauses = catchClauses.length;
- List<DartType> visitedTypes = <DartType>[];
- for (int i = 0; i < numOfCatchClauses; i++) {
- CatchClause catchClause = catchClauses[i];
- if (catchClause.onKeyword != null) {
- // An on-catch clause was found; verify that the exception type is not a
- // subtype of a previous on-catch exception type.
- DartType currentType = catchClause.exceptionType?.type;
- if (currentType != null) {
- if (currentType.isObject) {
- // Found catch clause clause that has Object as an exception type,
- // this is equivalent to having a catch clause that doesn't have an
- // exception type, visit the block, but generate an error on any
- // following catch clauses (and don't visit them).
- catchClause?.accept(this);
- if (i + 1 != numOfCatchClauses) {
- // This catch clause is not the last in the try statement.
- CatchClause nextCatchClause = catchClauses[i + 1];
- CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
- int offset = nextCatchClause.offset;
- int length = lastCatchClause.end - offset;
- _errorReporter.reportErrorForOffset(
- HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length);
- return;
- }
- }
- int length = visitedTypes.length;
- for (int j = 0; j < length; j++) {
- DartType type = visitedTypes[j];
- if (_typeSystem.isSubtypeOf2(currentType, type)) {
- CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
- int offset = catchClause.offset;
- int length = lastCatchClause.end - offset;
- _errorReporter.reportErrorForOffset(
- HintCode.DEAD_CODE_ON_CATCH_SUBTYPE,
- offset,
- length,
- [currentType, type]);
- return;
- }
- }
- visitedTypes.add(currentType);
- }
- catchClause?.accept(this);
- } else {
- // Found catch clause clause that doesn't have an exception type,
- // visit the block, but generate an error on any following catch clauses
- // (and don't visit them).
- catchClause?.accept(this);
- if (i + 1 != numOfCatchClauses) {
- // This catch clause is not the last in the try statement.
- CatchClause nextCatchClause = catchClauses[i + 1];
- CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
- int offset = nextCatchClause.offset;
- int length = lastCatchClause.end - offset;
- _errorReporter.reportErrorForOffset(
- HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length);
- return;
- }
+
+ var verifier = _CatchClausesVerifier(
+ _typeSystem,
+ (first, last, errorCode, arguments) {
+ var offset = first.offset;
+ var length = last.end - offset;
+ _errorReporter.reportErrorForOffset(
+ errorCode,
+ offset,
+ length,
+ arguments,
+ );
+ },
+ node.catchClauses,
+ );
+ for (var catchClause in node.catchClauses) {
+ verifier.nextCatchClause(catchClause);
+ if (verifier._done) {
+ break;
}
+ catchClause.accept(this);
}
}
@@ -472,6 +441,195 @@
}
}
+/// Helper for tracking dead code - [CatchClause]s and unreachable code.
+///
+/// [CatchClause]s are checked separately, as we visit AST we may make some
+/// of them as dead, and record [_deadCatchClauseRanges].
+///
+/// When an unreachable node is found, and [_firstDeadNode] is `null`, we
+/// set [_firstDeadNode], so start a new dead nodes interval. The dead code
+/// interval ends when [flowEnd] is invoked with a node that is the start
+/// node, or contains it. So, we end the the end of the covering control flow.
+class NullSafetyDeadCodeVerifier {
+ final TypeSystemImpl _typeSystem;
+ final ErrorReporter _errorReporter;
+ final FlowAnalysisHelper _flowAnalysis;
+
+ /// The stack of verifiers of (potentially nested) try statements.
+ final List<_CatchClausesVerifier> _catchClausesVerifiers = [];
+
+ /// When a sequence [CatchClause]s is found to be dead, we don't want to
+ /// report additional dead code inside of already dead code.
+ final List<SourceRange> _deadCatchClauseRanges = [];
+
+ /// When this field is `null`, we are in reachable code.
+ /// Once we find the first unreachable node, we store it here.
+ ///
+ /// When this field is not `null`, and we see an unreachable node, this new
+ /// node is ignored, because it continues the same dead code range.
+ AstNode _firstDeadNode;
+
+ NullSafetyDeadCodeVerifier(
+ this._typeSystem,
+ this._errorReporter,
+ this._flowAnalysis,
+ );
+
+ /// The [node] ends a basic block in the control flow. If [_firstDeadNode] is
+ /// not `null`, and is covered by the [node], then we reached the end of
+ /// the current dead code interval.
+ void flowEnd(AstNode node) {
+ if (_firstDeadNode != null) {
+ if (!_containsFirstDeadNode(node)) {
+ return;
+ }
+
+ // We know that [node] is the first dead node, or contains it.
+ // So, technically the code code interval ends at the end of [node].
+ // But we trim it to the last statement for presentation purposes.
+ if (node != _firstDeadNode) {
+ if (node is FunctionDeclaration) {
+ node = (node as FunctionDeclaration).functionExpression.body;
+ }
+ if (node is FunctionExpression) {
+ node = (node as FunctionExpression).body;
+ }
+ if (node is MethodDeclaration) {
+ node = (node as MethodDeclaration).body;
+ }
+ if (node is BlockFunctionBody) {
+ node = (node as BlockFunctionBody).block;
+ }
+ if (node is Block && node.statements.isNotEmpty) {
+ node = (node as Block).statements.last;
+ }
+ if (node is SwitchMember && node.statements.isNotEmpty) {
+ node = (node as SwitchMember).statements.last;
+ }
+ }
+
+ var offset = _firstDeadNode.offset;
+ var length = node.end - offset;
+ _errorReporter.reportErrorForOffset(HintCode.DEAD_CODE, offset, length);
+
+ _firstDeadNode = null;
+ }
+ }
+
+ void tryStatementEnter(TryStatement node) {
+ var verifier = _CatchClausesVerifier(
+ _typeSystem,
+ (first, last, errorCode, arguments) {
+ var offset = first.offset;
+ var length = last.end - offset;
+ _errorReporter.reportErrorForOffset(
+ errorCode,
+ offset,
+ length,
+ arguments,
+ );
+ _deadCatchClauseRanges.add(SourceRange(offset, length));
+ },
+ node.catchClauses,
+ );
+ _catchClausesVerifiers.add(verifier);
+ }
+
+ void tryStatementExit(TryStatement node) {
+ _catchClausesVerifiers.removeLast();
+ }
+
+ void verifyCatchClause(CatchClause node) {
+ var verifier = _catchClausesVerifiers.last;
+ if (verifier._done) return;
+
+ verifier.nextCatchClause(node);
+ }
+
+ void visitNode(AstNode node) {
+ // Comments are visited after bodies of functions.
+ // So, they look unreachable, but this does not make sense.
+ if (node is Comment) return;
+
+ if (_flowAnalysis == null) return;
+ _flowAnalysis.checkUnreachableNode(node);
+
+ var flow = _flowAnalysis.flow;
+ if (flow == null) return;
+
+ if (flow.isReachable) return;
+
+ // If in a dead `CatchClause`, no need to report dead code.
+ for (var range in _deadCatchClauseRanges) {
+ if (range.contains(node.offset)) {
+ return;
+ }
+ }
+
+ if (_firstDeadNode != null) return;
+ _firstDeadNode = node;
+ }
+
+ bool _containsFirstDeadNode(AstNode parent) {
+ for (var node = _firstDeadNode; node != null; node = node.parent) {
+ if (node == parent) return true;
+ }
+ return false;
+ }
+}
+
+class _CatchClausesVerifier {
+ final TypeSystemImpl _typeSystem;
+ final _CatchClausesVerifierReporter _errorReporter;
+ final List<CatchClause> catchClauses;
+
+ bool _done = false;
+ List<DartType> _visitedTypes = <DartType>[];
+
+ _CatchClausesVerifier(
+ this._typeSystem,
+ this._errorReporter,
+ this.catchClauses,
+ );
+
+ void nextCatchClause(CatchClause catchClause) {
+ var currentType = catchClause.exceptionType?.type;
+
+ // Found catch clause that doesn't have an exception type.
+ // Generate an error on any following catch clauses.
+ if (currentType == null || currentType.isDartCoreObject) {
+ if (catchClause != catchClauses.last) {
+ var index = catchClauses.indexOf(catchClause);
+ _errorReporter(
+ catchClauses[index + 1],
+ catchClauses.last,
+ HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH,
+ const [],
+ );
+ _done = true;
+ }
+ return;
+ }
+
+ // An on-catch clause was found; verify that the exception type is not a
+ // subtype of a previous on-catch exception type.
+ for (var type in _visitedTypes) {
+ if (_typeSystem.isSubtypeOf2(currentType, type)) {
+ _errorReporter(
+ catchClause,
+ catchClauses.last,
+ HintCode.DEAD_CODE_ON_CATCH_SUBTYPE,
+ [currentType, type],
+ );
+ _done = true;
+ return;
+ }
+ }
+
+ _visitedTypes.add(currentType);
+ }
+}
+
/// An object used to track the usage of labels within a single label scope.
class _LabelTracker {
/// The tracker for the outer label scope.
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 4596a57..7d6fc78 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -18,6 +18,7 @@
import 'package:analyzer/src/error/getter_setter_types_verifier.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
import 'package:analyzer/src/generated/type_system.dart';
+import 'package:meta/meta.dart';
class InheritanceOverrideVerifier {
static const _missingOverridesKey = 'missingOverrides';
@@ -103,12 +104,7 @@
final TypeName superclass;
final WithClause withClause;
- /// The set of unique supertypes of the current class.
- /// It is used to decide when to add a new element to [allSuperinterfaces].
- final Set<InterfaceType> allSupertypes = <InterfaceType>{};
-
- /// The list of all superinterfaces, collected so far.
- final List<Interface> allSuperinterfaces = [];
+ final List<InterfaceType> directSuperInterfaces = [];
_ClassVerifier({
this.typeSystem,
@@ -126,6 +122,8 @@
}) : libraryUri = library.source.uri,
classElement = classNameNode.staticElement;
+ bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
+
void verify() {
if (_checkDirectSuperTypes()) {
return;
@@ -137,9 +135,16 @@
InterfaceTypeImpl type = classElement.thisType;
- // Add all superinterfaces of the direct supertype.
- if (type.superclass != null) {
- _addSuperinterfaces(type.superclass);
+ // Compute the interface of the class.
+ var interface = inheritance.getInterface(type);
+
+ // Report conflicts between direct superinterfaces of the class.
+ for (var conflict in interface.conflicts) {
+ _reportInconsistentInheritance(classNameNode, conflict);
+ }
+
+ if (classElement.supertype != null) {
+ directSuperInterfaces.add(classElement.supertype);
}
// Each mixin in `class C extends S with M0, M1, M2 {}` is equivalent to:
@@ -153,14 +158,11 @@
var mixinTypes = type.mixins;
for (var i = 0; i < mixinTypes.length; i++) {
var mixinType = mixinTypes[i];
- _checkDeclaredMembers(mixinNodes[i], mixinType);
- _addSuperinterfaces(mixinType);
+ _checkDeclaredMembers(mixinNodes[i], mixinType, mixinIndex: i);
+ directSuperInterfaces.add(mixinType);
}
- // Add all superinterfaces of the direct class interfaces.
- for (var interface in type.interfaces) {
- _addSuperinterfaces(interface);
- }
+ directSuperInterfaces.addAll(classElement.interfaces);
// Check the members if the class itself, against all the previously
// collected superinterfaces of the supertype, mixins, and interfaces.
@@ -178,14 +180,6 @@
}
}
- // Compute the interface of the class.
- var interface = inheritance.getInterface(type);
-
- // Report conflicts between direct superinterfaces of the class.
- for (var conflict in interface.conflicts) {
- _reportInconsistentInheritance(classNameNode, conflict);
- }
-
GetterSetterTypesVerifier(
typeSystem: typeSystem,
errorReporter: reporter,
@@ -246,26 +240,15 @@
}
}
- void _addSuperinterfaces(InterfaceType startingType) {
- var supertypes = <InterfaceType>[];
- ClassElementImpl.collectAllSupertypes(supertypes, startingType, null);
- for (int i = 0; i < supertypes.length; i++) {
- var supertype = supertypes[i];
- if (allSupertypes.add(supertype)) {
- var interface = inheritance.getInterface(supertype);
- allSuperinterfaces.add(interface);
- }
- }
- }
-
/// Check that the given [member] is a valid override of the corresponding
- /// instance members in each of [allSuperinterfaces]. The [libraryUri] is
+ /// instance members in each of [directSuperInterfaces]. The [libraryUri] is
/// the URI of the library containing the [member].
void _checkDeclaredMember(
AstNode node,
Uri libraryUri,
ExecutableElement member, {
List<FormalParameter> methodParameterNodes,
+ int mixinIndex = -1,
}) {
if (member == null) return;
if (member.isStatic) return;
@@ -276,8 +259,12 @@
thisMember: member,
);
- for (var superInterface in allSuperinterfaces) {
- var superMember = superInterface.declared[name];
+ for (var superType in directSuperInterfaces) {
+ var superMember = inheritance.getMember(
+ superType,
+ name,
+ forMixinIndex: mixinIndex,
+ );
if (superMember == null) {
continue;
}
@@ -304,17 +291,25 @@
);
}
}
+
+ if (mixinIndex == -1) {
+ CovariantParametersVerifier(thisMember: member).verify(
+ errorReporter: reporter,
+ errorNode: node,
+ );
+ }
}
/// Check that instance members of [type] are valid overrides of the
/// corresponding instance members in each of [allSuperinterfaces].
- void _checkDeclaredMembers(AstNode node, InterfaceTypeImpl type) {
+ void _checkDeclaredMembers(AstNode node, InterfaceTypeImpl type,
+ {@required int mixinIndex}) {
var libraryUri = type.element.library.source.uri;
for (var method in type.methods) {
- _checkDeclaredMember(node, libraryUri, method);
+ _checkDeclaredMember(node, libraryUri, method, mixinIndex: mixinIndex);
}
for (var accessor in type.accessors) {
- _checkDeclaredMember(node, libraryUri, accessor);
+ _checkDeclaredMember(node, libraryUri, accessor, mixinIndex: mixinIndex);
}
}
@@ -630,8 +625,6 @@
}
}
- bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
-
void _reportInheritedAbstractMembers(List<ExecutableElement> elements) {
if (elements == null) {
return;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 4e7ee60..1dbeab5 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -38,6 +38,7 @@
import 'package:analyzer/src/dart/resolver/yield_statement_resolver.dart';
import 'package:analyzer/src/error/bool_expression_verifier.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/dead_code_verifier.dart';
import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
@@ -222,6 +223,8 @@
PrefixExpressionResolver _prefixExpressionResolver;
YieldStatementResolver _yieldStatementResolver;
+ NullSafetyDeadCodeVerifier nullSafetyDeadCodeVerifier;
+
InvocationInferenceHelper inferenceHelper;
/// The object used to resolve the element associated with the current node.
@@ -388,6 +391,11 @@
this._yieldStatementResolver = YieldStatementResolver(
resolver: this,
);
+ this.nullSafetyDeadCodeVerifier = NullSafetyDeadCodeVerifier(
+ typeSystem,
+ errorReporter,
+ _flowAnalysis,
+ );
this.elementResolver = ElementResolver(this,
reportConstEvaluationErrors: reportConstEvaluationErrors,
migratableAstInfoProvider: _migratableAstInfoProvider);
@@ -431,6 +439,10 @@
bool get _isNonNullableByDefault =>
_featureSet.isEnabled(Feature.non_nullable);
+ void checkUnreachableNode(AstNode node) {
+ nullSafetyDeadCodeVerifier.visitNode(node);
+ }
+
/// Return the static element associated with the given expression whose type
/// can be overridden, or `null` if there is no element whose type can be
/// overridden.
@@ -819,9 +831,10 @@
if (_flowAnalysis != null) {
if (flow != null) {
flow.conditional_thenBegin(condition);
- _flowAnalysis.checkUnreachableNode(thenExpression);
+ checkUnreachableNode(thenExpression);
}
thenExpression.accept(this);
+ nullSafetyDeadCodeVerifier?.flowEnd(thenExpression);
} else {
_promoteManager.visitConditionalExpression_then(
condition,
@@ -837,9 +850,10 @@
if (flow != null) {
flow.conditional_elseBegin(thenExpression);
- _flowAnalysis.checkUnreachableNode(elseExpression);
+ checkUnreachableNode(elseExpression);
elseExpression.accept(this);
flow.conditional_end(node, elseExpression);
+ nullSafetyDeadCodeVerifier?.flowEnd(elseExpression);
} else {
elseExpression.accept(this);
}
@@ -939,7 +953,7 @@
@override
void visitDoStatementInScope(DoStatement node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
var body = node.body;
var condition = node.condition;
@@ -1061,6 +1075,7 @@
@override
void visitForStatementInScope(ForStatement node) {
_forResolver.resolveStatement(node);
+ nullSafetyDeadCodeVerifier?.flowEnd(node.body);
}
@override
@@ -1110,6 +1125,7 @@
} else {
_flowAnalysis.topLevelDeclaration_exit();
}
+ nullSafetyDeadCodeVerifier?.flowEnd(node);
} else {
_promoteManager.exitFunctionBody();
}
@@ -1163,6 +1179,7 @@
errorNode: body,
);
_flowAnalysis.flow?.functionExpression_end();
+ nullSafetyDeadCodeVerifier?.flowEnd(node);
}
} else {
_promoteManager.exitFunctionBody();
@@ -1245,7 +1262,7 @@
@override
void visitIfStatement(IfStatement node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
Expression condition = node.condition;
@@ -1260,6 +1277,7 @@
if (_flowAnalysis != null) {
_flowAnalysis.flow.ifStatement_thenBegin(condition);
visitStatementInScope(thenStatement);
+ nullSafetyDeadCodeVerifier?.flowEnd(thenStatement);
} else {
_promoteManager.visitIfStatement_thenStatement(
condition,
@@ -1274,6 +1292,7 @@
if (elseStatement != null) {
_flowAnalysis?.flow?.ifStatement_elseBegin();
visitStatementInScope(elseStatement);
+ nullSafetyDeadCodeVerifier?.flowEnd(elseStatement);
}
_flowAnalysis?.flow?.ifStatement_end(elseStatement != null);
@@ -1322,11 +1341,18 @@
void visitLabel(Label node) {}
@override
+ void visitLabeledStatement(LabeledStatement node) {
+ _flowAnalysis?.labeledStatement_enter(node);
+ super.visitLabeledStatement(node);
+ _flowAnalysis?.labeledStatement_exit(node);
+ }
+
+ @override
void visitLibraryIdentifier(LibraryIdentifier node) {}
@override
void visitListLiteral(ListLiteral node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
_typedLiteralResolver.resolveListLiteral(node);
}
@@ -1357,6 +1383,7 @@
);
_flowAnalysis.executableDeclaration_exit(node.body, false);
_flowAnalysis.topLevelDeclaration_exit();
+ nullSafetyDeadCodeVerifier?.flowEnd(node);
} else {
_promoteManager.exitFunctionBody();
}
@@ -1421,7 +1448,7 @@
@override
void visitNode(AstNode node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
node.visitChildren(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
@@ -1515,7 +1542,7 @@
@override
void visitSetOrMapLiteral(SetOrMapLiteral node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
_typedLiteralResolver.resolveSetOrMapLiteral(node);
}
@@ -1573,7 +1600,7 @@
@override
void visitSwitchCase(SwitchCase node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
InferenceContext.setType(
node.expression, _enclosingSwitchStatementExpressionType);
@@ -1589,11 +1616,19 @@
);
}
}
+
+ nullSafetyDeadCodeVerifier?.flowEnd(node);
+ }
+
+ @override
+ void visitSwitchDefault(SwitchDefault node) {
+ super.visitSwitchDefault(node);
+ nullSafetyDeadCodeVerifier?.flowEnd(node);
}
@override
void visitSwitchStatementInScope(SwitchStatement node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
var previousExpressionType = _enclosingSwitchStatementExpressionType;
try {
@@ -1639,7 +1674,7 @@
return super.visitTryStatement(node);
}
- _flowAnalysis.checkUnreachableNode(node);
+ checkUnreachableNode(node);
var flow = _flowAnalysis.flow;
var body = node.body;
@@ -1656,18 +1691,23 @@
body.accept(this);
if (catchClauses.isNotEmpty) {
flow.tryCatchStatement_bodyEnd(body);
+ nullSafetyDeadCodeVerifier.tryStatementEnter(node);
var catchLength = catchClauses.length;
for (var i = 0; i < catchLength; ++i) {
var catchClause = catchClauses[i];
+ nullSafetyDeadCodeVerifier.verifyCatchClause(catchClause);
flow.tryCatchStatement_catchBegin(
- catchClause.exceptionParameter?.staticElement,
- catchClause.stackTraceParameter?.staticElement);
+ catchClause.exceptionParameter?.staticElement,
+ catchClause.stackTraceParameter?.staticElement,
+ );
catchClause.accept(this);
flow.tryCatchStatement_catchEnd();
+ nullSafetyDeadCodeVerifier?.flowEnd(catchClause.body);
}
flow.tryCatchStatement_end();
+ nullSafetyDeadCodeVerifier.tryStatementExit(node);
}
if (finallyBlock != null) {
@@ -1721,7 +1761,7 @@
@override
void visitWhileStatement(WhileStatement node) {
- _flowAnalysis?.checkUnreachableNode(node);
+ checkUnreachableNode(node);
// Note: since we don't call the base class, we have to maintain
// _implicitLabelScope ourselves.
@@ -1742,6 +1782,7 @@
_flowAnalysis?.flow?.whileStatement_bodyBegin(node, condition);
visitStatementInScope(body);
_flowAnalysis?.flow?.whileStatement_end();
+ nullSafetyDeadCodeVerifier?.flowEnd(node.body);
}
} finally {
_implicitLabelScope = outerImplicitScope;
@@ -2049,6 +2090,21 @@
migrationResolutionHooks);
@override
+ void visitConditionalExpression(ConditionalExpression node) {
+ var conditionalKnownValue =
+ _migrationResolutionHooks.getConditionalKnownValue(node);
+ if (conditionalKnownValue == null) {
+ super.visitConditionalExpression(node);
+ return;
+ } else {
+ var subexpressionToKeep =
+ conditionalKnownValue ? node.thenExpression : node.elseExpression;
+ subexpressionToKeep.accept(this);
+ typeAnalyzer.recordStaticType(node, subexpressionToKeep.staticType);
+ }
+ }
+
+ @override
void visitIfElement(IfElement node) {
var conditionalKnownValue =
_migrationResolutionHooks.getConditionalKnownValue(node);
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 5ff6329..71e150d 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -174,12 +174,34 @@
}
/**
+ * Record that the static type of the given node is the given type.
+ *
+ * @param expression the node whose type is to be recorded
+ * @param type the static type of the node
+ */
+ void recordStaticType(Expression expression, DartType type) {
+ if (_migrationResolutionHooks != null) {
+ type = _migrationResolutionHooks.modifyExpressionType(
+ expression, type ?? _dynamicType);
+ }
+
+ if (type == null) {
+ expression.staticType = _dynamicType;
+ } else {
+ expression.staticType = type;
+ if (identical(type, NeverTypeImpl.instance)) {
+ _flowAnalysis?.flow?.handleExit();
+ }
+ }
+ }
+
+ /**
* The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
* `String`.</blockquote>
*/
@override
void visitAdjacentStrings(AdjacentStrings node) {
- _recordStaticType(node, _nonNullable(_typeProvider.stringType));
+ recordStaticType(node, _nonNullable(_typeProvider.stringType));
}
/**
@@ -192,7 +214,7 @@
*/
@override
void visitAsExpression(AsExpression node) {
- _recordStaticType(node, _getType(node.type));
+ recordStaticType(node, _getType(node.type));
}
/**
@@ -205,7 +227,7 @@
void visitAwaitExpression(AwaitExpression node) {
DartType resultType = _getStaticType(node.expression);
if (resultType != null) resultType = _typeSystem.flatten(resultType);
- _recordStaticType(node, resultType);
+ recordStaticType(node, resultType);
}
/**
@@ -214,7 +236,7 @@
*/
@override
void visitBooleanLiteral(BooleanLiteral node) {
- _recordStaticType(node, _nonNullable(_typeProvider.boolType));
+ recordStaticType(node, _nonNullable(_typeProvider.boolType));
}
/**
@@ -224,7 +246,7 @@
*/
@override
void visitCascadeExpression(CascadeExpression node) {
- _recordStaticType(node, _getStaticType(node.target));
+ recordStaticType(node, _getStaticType(node.target));
}
/**
@@ -247,7 +269,7 @@
*/
@override
void visitDoubleLiteral(DoubleLiteral node) {
- _recordStaticType(node, _nonNullable(_typeProvider.doubleType));
+ recordStaticType(node, _nonNullable(_typeProvider.doubleType));
}
@override
@@ -270,7 +292,7 @@
functionElement.returnType =
_computeStaticReturnTypeOfFunctionDeclaration(node);
}
- _recordStaticType(function, functionElement.type);
+ recordStaticType(function, functionElement.type);
}
/**
@@ -321,7 +343,7 @@
@override
void visitIndexExpression(IndexExpression node) {
if (identical(node.realTarget.staticType, NeverTypeImpl.instance)) {
- _recordStaticType(node, NeverTypeImpl.instance);
+ recordStaticType(node, NeverTypeImpl.instance);
} else {
DartType type;
if (node.inSetterContext()) {
@@ -335,7 +357,7 @@
type ??= _dynamicType;
- _recordStaticType(node, type);
+ recordStaticType(node, type);
}
_resolver.nullShortingTermination(node);
@@ -353,7 +375,7 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
_inferInstanceCreationExpression(node);
- _recordStaticType(node, node.constructorName.type.type);
+ recordStaticType(node, node.constructorName.type.type);
}
/**
@@ -381,9 +403,9 @@
if (context == null ||
_typeSystem.isAssignableTo2(_typeProvider.intType, context) ||
!_typeSystem.isAssignableTo2(_typeProvider.doubleType, context)) {
- _recordStaticType(node, _nonNullable(_typeProvider.intType));
+ recordStaticType(node, _nonNullable(_typeProvider.intType));
} else {
- _recordStaticType(node, _nonNullable(_typeProvider.doubleType));
+ recordStaticType(node, _nonNullable(_typeProvider.doubleType));
}
}
@@ -395,7 +417,7 @@
*/
@override
void visitIsExpression(IsExpression node) {
- _recordStaticType(node, _nonNullable(_typeProvider.boolType));
+ recordStaticType(node, _nonNullable(_typeProvider.boolType));
}
@override
@@ -406,7 +428,7 @@
@override
void visitNamedExpression(NamedExpression node) {
Expression expression = node.expression;
- _recordStaticType(node, _getStaticType(expression));
+ recordStaticType(node, _getStaticType(expression));
}
/**
@@ -415,13 +437,13 @@
*/
@override
void visitNullLiteral(NullLiteral node) {
- _recordStaticType(node, _typeProvider.nullType);
+ recordStaticType(node, _typeProvider.nullType);
}
@override
void visitParenthesizedExpression(ParenthesizedExpression node) {
Expression expression = node.expression;
- _recordStaticType(node, _getStaticType(expression));
+ recordStaticType(node, _getStaticType(expression));
}
/**
@@ -438,8 +460,8 @@
}
if (identical(node.prefix.staticType, NeverTypeImpl.instance)) {
- _recordStaticType(prefixedIdentifier, NeverTypeImpl.instance);
- _recordStaticType(node, NeverTypeImpl.instance);
+ recordStaticType(prefixedIdentifier, NeverTypeImpl.instance);
+ recordStaticType(node, NeverTypeImpl.instance);
return;
}
@@ -477,8 +499,8 @@
staticType = _inferTearOff(node, node.identifier, staticType);
if (!_inferObjectAccess(node, staticType, prefixedIdentifier)) {
- _recordStaticType(prefixedIdentifier, staticType);
- _recordStaticType(node, staticType);
+ recordStaticType(prefixedIdentifier, staticType);
+ recordStaticType(node, staticType);
}
}
@@ -539,8 +561,8 @@
staticType = _inferTearOff(node, node.propertyName, staticType);
if (!_inferObjectAccess(node, staticType, propertyName)) {
- _recordStaticType(propertyName, staticType);
- _recordStaticType(node, staticType);
+ recordStaticType(propertyName, staticType);
+ recordStaticType(node, staticType);
_resolver.nullShortingTermination(node);
}
}
@@ -551,7 +573,7 @@
*/
@override
void visitRethrowExpression(RethrowExpression node) {
- _recordStaticType(node, _typeProvider.bottomType);
+ recordStaticType(node, _typeProvider.bottomType);
}
/**
@@ -637,7 +659,7 @@
staticType = _dynamicType;
}
staticType = _inferTearOff(node, node, staticType);
- _recordStaticType(node, staticType);
+ recordStaticType(node, staticType);
}
/**
@@ -646,7 +668,7 @@
*/
@override
void visitSimpleStringLiteral(SimpleStringLiteral node) {
- _recordStaticType(node, _nonNullable(_typeProvider.stringType));
+ recordStaticType(node, _nonNullable(_typeProvider.stringType));
}
/**
@@ -655,7 +677,7 @@
*/
@override
void visitStringInterpolation(StringInterpolation node) {
- _recordStaticType(node, _nonNullable(_typeProvider.stringType));
+ recordStaticType(node, _nonNullable(_typeProvider.stringType));
}
@override
@@ -664,15 +686,15 @@
node.thisOrAncestorOfType<ExtensionDeclaration>() != null) {
// TODO(brianwilkerson) Report this error if it hasn't already been
// reported.
- _recordStaticType(node, _dynamicType);
+ recordStaticType(node, _dynamicType);
} else {
- _recordStaticType(node, _resolver.thisType);
+ recordStaticType(node, _resolver.thisType);
}
}
@override
void visitSymbolLiteral(SymbolLiteral node) {
- _recordStaticType(node, _nonNullable(_typeProvider.symbolType));
+ recordStaticType(node, _nonNullable(_typeProvider.symbolType));
}
/**
@@ -684,9 +706,9 @@
if (_resolver.thisType == null) {
// TODO(brianwilkerson) Report this error if it hasn't already been
// reported.
- _recordStaticType(node, _dynamicType);
+ recordStaticType(node, _dynamicType);
} else {
- _recordStaticType(node, _resolver.thisType);
+ recordStaticType(node, _resolver.thisType);
}
}
@@ -696,7 +718,7 @@
*/
@override
void visitThrowExpression(ThrowExpression node) {
- _recordStaticType(node, _typeProvider.bottomType);
+ recordStaticType(node, _typeProvider.bottomType);
}
@override
@@ -739,7 +761,7 @@
staticType = _resolver.toLegacyTypeIfOptOut(staticType);
- _recordStaticType(node, staticType);
+ recordStaticType(node, staticType);
}
/**
@@ -942,7 +964,7 @@
computedType = _computeReturnTypeOfFunction(body, computedType);
functionElement.returnType = computedType;
- _recordStaticType(node, functionElement.type);
+ recordStaticType(node, functionElement.type);
}
/**
@@ -1007,8 +1029,8 @@
nodeType.isDynamic &&
inferredType is InterfaceType &&
_typeProvider.nonSubtypableClasses.contains(inferredType.element)) {
- _recordStaticType(id, inferredType);
- _recordStaticType(node, inferredType);
+ recordStaticType(id, inferredType);
+ recordStaticType(node, inferredType);
return true;
}
return false;
@@ -1075,28 +1097,6 @@
return type;
}
- /**
- * Record that the static type of the given node is the given type.
- *
- * @param expression the node whose type is to be recorded
- * @param type the static type of the node
- */
- void _recordStaticType(Expression expression, DartType type) {
- if (_migrationResolutionHooks != null) {
- type = _migrationResolutionHooks.modifyExpressionType(
- expression, type ?? _dynamicType);
- }
-
- if (type == null) {
- expression.staticType = _dynamicType;
- } else {
- expression.staticType = type;
- if (identical(type, NeverTypeImpl.instance)) {
- _flowAnalysis?.flow?.handleExit();
- }
- }
- }
-
void _setExtensionIdentifierType(Identifier node) {
if (node is SimpleIdentifier && node.inDeclarationContext()) {
return;
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 4380c3d..461f6d3 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -131,10 +131,22 @@
}
CompilationUnit _parse(Source source) {
- return parseString(
+ var result = parseString(
content: source.contents.data,
featureSet: featureSet,
throwIfDiagnostics: false,
- ).unit;
+ );
+
+ if (result.errors.isNotEmpty) {
+ var errorsStr = result.errors.map((e) {
+ var location = result.lineInfo.getLocation(e.offset);
+ return '${source.fullName}:$location - ${e.message}';
+ }).join('\n');
+ throw StateError(
+ 'Unexpected diagnostics:\n$errorsStr',
+ );
+ }
+
+ return result.unit;
}
}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 8571632..71eb4d2 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -1239,7 +1239,7 @@
List<Source> librarySources = sdkLibraries
.map((SdkLibrary library) => mapDartUri(library.shortName))
.toList();
- var featureSet = FeatureSet.fromEnableFlags([]);
+ var featureSet = FeatureSet.fromEnableFlags(['non-nullable']);
return SummaryBuilder(librarySources, context).build(
featureSet: featureSet,
);
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index 0da7a31..e7b9cbae 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -1226,12 +1226,38 @@
int bar(int a) => 0;
}
''');
- _assertGetMember(
+ _assertGetMember2(
className: 'B',
name: 'foo',
expected: 'A.foo: int* Function(int*, int*)*',
);
- _assertGetMember(
+
+ _assertGetMember2(
+ className: 'B',
+ name: 'bar',
+ expected: 'B.bar: int* Function(int*)*',
+ );
+ }
+
+ test_getMember_optOut_mixesOptIn() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ await resolveTestCode('''
+// @dart = 2.6
+import 'a.dart';
+class B with A {
+ int bar(int a) => 0;
+}
+''');
+ _assertGetMember2(
+ className: 'B',
+ name: 'foo',
+ expected: 'A.foo: int* Function(int*, int*)*',
+ );
+ _assertGetMember2(
className: 'B',
name: 'bar',
expected: 'B.bar: int* Function(int*)*',
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
index 4de68fb..7dc6aef 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
@@ -56,10 +56,45 @@
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = FeatureSet.forTesting(
sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+ test_optIn_fromOptOut() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A implements Iterable<int> {
+ Iterator<int> iterator => throw 0;
+}
+''');
+
+ await assertNoErrorsInCode(r'''
+// @dart = 2.7
+import 'a.dart';
+
+main(A a) {
+ for (var v in a) {
+ v;
+ }
+}
+''');
+ }
}
@reflectiveTest
class ForLoopElementTest extends DriverResolutionTest {
+ test_condition_rewrite() async {
+ await assertNoErrorsInCode(r'''
+main(bool Function() b) {
+ <int>[for (; b(); ) 0];
+}
+''');
+
+ assertFunctionExpressionInvocation(
+ findNode.functionExpressionInvocation('b()'),
+ element: null,
+ typeArgumentTypes: [],
+ invokeType: 'bool Function()',
+ type: 'bool',
+ );
+ }
+
test_declaredVariableScope() async {
await assertNoErrorsInCode(r'''
main() {
@@ -77,20 +112,4 @@
findNode.simple('i = 1.1;').staticElement,
);
}
-
- test_condition_rewrite() async {
- await assertNoErrorsInCode(r'''
-main(bool Function() b) {
- <int>[for (; b(); ) 0];
-}
-''');
-
- assertFunctionExpressionInvocation(
- findNode.functionExpressionInvocation('b()'),
- element: null,
- typeArgumentTypes: [],
- invokeType: 'bool Function()',
- type: 'bool',
- );
- }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
index 97ceec7..a79a25e 100644
--- a/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
@@ -124,6 +124,32 @@
@override
bool get typeToStringWithNullability => true;
+ test_functionReference() async {
+ await assertErrorsInCode('''
+// @dart = 2.7
+import 'dart:math';
+
+class A {
+ const A(_);
+}
+
+@A([min])
+main() {}
+''', [
+ error(StrongModeCode.COULD_NOT_INFER, 66, 5),
+ ]);
+
+ var identifier = findNode.simple('min]');
+ assertElement(
+ identifier,
+ elementMatcher(
+ findElement.importFind('dart:math').topFunction('min'),
+ isLegacy: true,
+ ),
+ );
+ assertType(identifier, 'T* Function<T extends num*>(T*, T*)*');
+ }
+
test_implicitCall_tearOff_nullable() async {
await assertErrorsInCode('''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index fbb109e..ae0e08e 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -6,11 +6,13 @@
import 'package:analyzer/src/test_utilities/package_mixin.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../dart/constant/potentially_constant_test.dart';
import '../dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(DeadCodeTest);
+ defineReflectiveTests(DeadCodeWithNullSafetyTest);
});
}
@@ -18,11 +20,12 @@
class DeadCodeTest extends DriverResolutionTest with PackageMixin {
test_afterForEachWithBreakLabel() async {
await assertNoErrorsInCode(r'''
-f() {
+f(List<Object> values) {
named: {
- for (var x in [1]) {
- if (x == null)
+ for (var x in values) {
+ if (x == 42) {
break named;
+ }
}
return;
}
@@ -36,7 +39,7 @@
f() {
named: {
for (int i = 0; i < 7; i++) {
- if (i == null)
+ if (i == 42)
break named;
}
return;
@@ -428,6 +431,13 @@
]);
}
+ test_documentationComment() async {
+ await assertNoErrorsInCode(r'''
+/// text
+int f() => 0;
+''');
+ }
+
test_statementAfterAlwaysThrowsFunction() async {
addMetaPackage();
await assertErrorsInCode(r'''
@@ -639,6 +649,33 @@
]);
}
+ test_statementAfterReturn_function_local() async {
+ await assertErrorsInCode(r'''
+f() {
+ void g() {
+ print(1);
+ return;
+ print(2);
+ }
+ g();
+}''', [
+ error(HintCode.DEAD_CODE, 49, 9),
+ ]);
+ }
+
+ test_statementAfterReturn_functionExpression() async {
+ await assertErrorsInCode(r'''
+f() {
+ () {
+ print(1);
+ return;
+ print(2);
+ };
+}''', [
+ error(HintCode.DEAD_CODE, 43, 9),
+ ]);
+ }
+
test_statementAfterReturn_ifStatement() async {
await assertErrorsInCode(r'''
f(bool b) {
@@ -700,3 +737,34 @@
]);
}
}
+
+@reflectiveTest
+class DeadCodeWithNullSafetyTest extends DeadCodeTest with WithNullSafetyMixin {
+ @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+ @override
+ test_statementAfterAlwaysThrowsFunction() async {
+ return super.test_statementAfterAlwaysThrowsFunction();
+ }
+
+ @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+ @override
+ test_statementAfterAlwaysThrowsMethod() async {
+ return super.test_statementAfterAlwaysThrowsMethod();
+ }
+
+ test_switchStatement_exhaustive() async {
+ await assertErrorsInCode(r'''
+enum Foo { a, b }
+
+int f(Foo foo) {
+ switch (foo) {
+ case Foo.a: return 0;
+ case Foo.b: return 1;
+ }
+ return -1;
+}
+''', [
+ error(HintCode.DEAD_CODE, 111, 10),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart
index 0ff696e..7fe09d4 100644
--- a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart
@@ -71,25 +71,29 @@
sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
test_awaitForIn_never() async {
- await assertNoErrorsInCode('''
+ await assertErrorsInCode('''
f(Never e) async {
await for (var id in e) {
id;
}
}
-''');
+''', [
+ error(HintCode.DEAD_CODE, 32, 26),
+ ]);
// TODO(scheglov) extract for-in resolution and implement
// assertType(findNode.simple('id;'), 'Never');
}
test_forIn_never() async {
- await assertNoErrorsInCode('''
+ await assertErrorsInCode('''
f(Never e) {
for (var id in e) {
id;
}
}
-''');
+''', [
+ error(HintCode.DEAD_CODE, 20, 26),
+ ]);
// TODO(scheglov) extract for-in resolution and implement
// assertType(findNode.simple('id;'), 'Never');
}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index afba36c..662a22b 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -61,7 +61,6 @@
}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 163, 6),
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 163, 6),
]);
}
@@ -124,6 +123,24 @@
''');
}
+ test_method_covariant_3() async {
+ await assertErrorsInCode(r'''
+class A {
+ void foo(num a) {}
+}
+
+class B extends A {
+ void foo(dynamic a) {}
+}
+
+class C extends B {
+ void foo(covariant String a) {}
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3),
+ ]);
+ }
+
test_method_named_fewerNamedParameters() async {
await assertErrorsInCode('''
class A {
@@ -220,7 +237,6 @@
}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
]);
}
@@ -269,7 +285,6 @@
}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 1),
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 1),
]);
}
@@ -408,7 +423,6 @@
}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 129, 1),
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 129, 1),
]);
}
@@ -452,7 +466,6 @@
}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 8),
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 8),
]);
}
@@ -471,7 +484,6 @@
}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 166, 8),
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 166, 8),
]);
}
@@ -539,14 +551,81 @@
''');
}
- test_method_viaLegacy_returnType_notSubtype() async {
+ test_mixedInheritance_1() async {
newFile('/test/lib/a.dart', content: r'''
-class Nullable {
- int? foo() => 0;
+class B {
+ List<int Function(int)> get a => [];
+ set a(List<int Function(int)> _) {}
+ int Function(int) m(int Function(int) x) => x;
}
-class NonNullable {
- int foo() => 0;
+class Bq {
+ List<int? Function(int?)> get a => [];
+ set a(List<int? Function(int?)> _) {}
+ int? Function(int?) m(int? Function(int?) x) => x;
+}
+''');
+
+ newFile('/test/lib/b.dart', content: r'''
+// @dart = 2.7
+import 'a.dart';
+
+class C with B {}
+''');
+
+ await assertNoErrorsInCode(r'''
+import 'a.dart';
+import 'b.dart';
+
+class D extends C implements Bq {}
+''');
+ }
+
+ test_mixedInheritance_2() async {
+ newFile('/test/lib/a.dart', content: r'''
+class B {
+ List<int Function(int)> get a => [];
+ set a(List<int Function(int)> _) {}
+ int Function(int) m(int Function(int) x) => x;
+}
+
+class Bq {
+ List<int? Function(int?)> get a => [];
+ set a(List<int? Function(int?)> _) {}
+ int? Function(int?) m(int? Function(int?) x) => x;
+}
+''');
+
+ newFile('/test/lib/b.dart', content: r'''
+// @dart = 2.7
+import 'a.dart';
+
+class C extends B with Bq {}
+''');
+
+ await assertNoErrorsInCode(r'''
+import 'b.dart';
+
+class D extends C {
+ List<int Function(int)> get a => [];
+ set a(List<int Function(int)> _) {}
+ int Function(int) m(int Function(int) x) => x;
+}
+''');
+ }
+
+ test_viaLegacy_class() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A1 {
+ int m() => 0;
+ int get g => 0;
+ set s(int? _) {}
+}
+
+class A2 {
+ int? m() => 0;
+ int? get g => 0;
+ set s(int _) {}
}
''');
@@ -554,19 +633,58 @@
// @dart=2.6
import 'a.dart';
-class A extends Nullable implements NonNullable {}
+class L extends A2 implements A1 {}
''');
- await assertErrorsInCode('''
+ await assertNoErrorsInCode('''
+import 'a.dart';
import 'b.dart';
-class B extends A {}
+class X1 extends L implements A1 {}
+class X2 extends L implements A2 {}
-class C extends A {
- int? foo() => 0;
+class Y extends L {
+ int? get g => 0;
+ int? m() => 0;
+ set s(int _) {}
}
-''', [
- error(CompileTimeErrorCode.INVALID_OVERRIDE, 70, 3),
- ]);
+''');
+ }
+
+ test_viaLegacy_mixin() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A1 {
+ int m() => 0;
+ int get g => 0;
+ set s(int? _) {}
+}
+
+mixin A2 {
+ int? m() => 0;
+ int? get g => 0;
+ set s(int _) {}
+}
+''');
+
+ newFile('/test/lib/b.dart', content: r'''
+// @dart=2.6
+import 'a.dart';
+
+class L extends Object with A2 implements A1 {}
+''');
+
+ await assertNoErrorsInCode('''
+import 'a.dart';
+import 'b.dart';
+
+class X1 extends L implements A1 {}
+class X2 extends L implements A2 {}
+
+class Y extends L {
+ int? get g => 0;
+ int? m() => 0;
+ set s(int _) {}
+}
+''');
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
index 50e9132..480726c 100644
--- a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
@@ -812,7 +812,7 @@
}
test_if_condition_notTrue() async {
- await assertNoErrorsInCode(r'''
+ await assertErrorsInCode(r'''
void f() {
int v;
if (!true) {
@@ -822,7 +822,9 @@
}
v;
}
-''');
+''', [
+ error(HintCode.DEAD_CODE, 33, 25),
+ ]);
}
test_if_condition_true() async {
@@ -1325,7 +1327,7 @@
}
test_while_true_break_if() async {
- await assertNoErrorsInCode(r'''
+ await assertErrorsInCode(r'''
void f(bool b) {
int v;
while (true) {
@@ -1340,7 +1342,9 @@
}
v;
}
-''');
+''', [
+ error(HintCode.DEAD_CODE, 131, 2),
+ ]);
}
test_while_true_break_if2() async {
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 9e628cc..3c4b65e 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -35,6 +35,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 28, 6),
]);
assertBinaryExpression(
@@ -53,6 +54,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 27, 8),
]);
assertBinaryExpression(
@@ -141,6 +143,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 25, 3),
]);
assertIndexExpression(
@@ -158,6 +161,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 25, 12),
]);
assertIndexExpression(
@@ -177,6 +181,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 25, 11),
]);
assertIndexExpression(
@@ -263,6 +268,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 28, 8),
]);
assertMethodInvocation(
@@ -283,6 +289,7 @@
}
''', [
error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+ error(HintCode.DEAD_CODE, 33, 8),
]);
assertMethodInvocation(
@@ -410,11 +417,13 @@
}
test_propertyAccess_never_readWrite() async {
- await assertNoErrorsInCode(r'''
+ await assertErrorsInCode(r'''
void main(Never x) {
x.foo += 0;
}
-''');
+''', [
+ error(HintCode.DEAD_CODE, 32, 2),
+ ]);
assertSimpleIdentifier(
findNode.simple('foo'),
@@ -444,11 +453,13 @@
}
test_propertyAccess_never_write() async {
- await assertNoErrorsInCode(r'''
+ await assertErrorsInCode(r'''
void main(Never x) {
x.foo = 0;
}
-''');
+''', [
+ error(HintCode.DEAD_CODE, 31, 2),
+ ]);
assertSimpleIdentifier(
findNode.simple('foo'),
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 0162d95..edbcf0e 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2649,7 +2649,6 @@
''');
}
- @failingTest
test_invalidOverrides_doubleOverride() async {
await checkFile('''
class A {}
@@ -2669,7 +2668,6 @@
''');
}
- @failingTest
test_invalidOverrides_doubleOverride2() async {
await checkFile('''
class A {}
@@ -3632,7 +3630,6 @@
''');
}
- @failingTest
test_noDuplicateReports_typeOverridesSomeMethodInMultipleInterfaces() async {
await checkFile('''
class A {}
@@ -4315,12 +4312,7 @@
}
class T1 extends Base {
- // we consider the base class incomplete because it is
- // abstract, so we report the error here too.
- // TODO(sigmund): consider tracking overrides in a fine-grain
- // manner, then this and the double-overrides would not be
- // reported.
- /*error:INVALID_OVERRIDE*/m(B a) {}
+ m(B a) {}
}
''');
}
@@ -4339,7 +4331,7 @@
}
class T1 extends Base {
- /*error:INVALID_OVERRIDE*/m(B a) {}
+ m(B a) {}
}
''');
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index bd8c171..a10948d 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1494,7 +1494,8 @@
newParameter = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
targetElement, newParameter, type);
} else {
- newParameter = _typeBuilder.trustTypeOfParameter(newParameter, type);
+ newParameter = _typeBuilder.trustTypeOfParameter(
+ targetElement, newParameter, type);
}
localsHandler.directLocals[local] = newParameter;
@@ -6335,7 +6336,8 @@
DartType type = localsMap.getLocalType(_elementMap, parameter);
HInstruction checkedOrTrusted;
if (trusted) {
- checkedOrTrusted = _typeBuilder.trustTypeOfParameter(argument, type);
+ checkedOrTrusted =
+ _typeBuilder.trustTypeOfParameter(function, argument, type);
} else {
checkedOrTrusted = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
function, argument, type);
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index f7269a3..de1d2a5 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -102,8 +102,17 @@
return checkInstruction;
}
- HInstruction trustTypeOfParameter(HInstruction original, DartType type) {
+ HInstruction trustTypeOfParameter(
+ MemberEntity memberContext, HInstruction original, DartType type) {
if (type == null) return original;
+
+ /// Dart semantics check against null outside the method definition,
+ /// however dart2js moves the null check to the callee for performance
+ /// reasons. As a result the body cannot trust or check that the type is not
+ /// nullable.
+ if (builder.options.useNullSafety && memberContext.name == '==') {
+ type = _closedWorld.dartTypes.nullableType(type);
+ }
HInstruction trusted = _trustType(original, type);
if (trusted == original) return original;
if (trusted is HTypeKnown && trusted.isRedundant(builder.closedWorld)) {
@@ -119,6 +128,14 @@
HInstruction checkedOrTrusted = original;
CheckPolicy parameterCheckPolicy = builder.closedWorld.annotationsData
.getParameterCheckPolicy(memberContext);
+
+ /// Dart semantics check against null outside the method definition,
+ /// however dart2js moves the null check to the callee for performance
+ /// reasons. As a result the body cannot trust or check that the type is not
+ /// nullable.
+ if (builder.options.useNullSafety && memberContext.name == '==') {
+ type = _closedWorld.dartTypes.nullableType(type);
+ }
if (parameterCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, type);
} else if (parameterCheckPolicy.isEmitted) {
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 0b34601..62180a8 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -24,6 +24,8 @@
argParser.addFlag('verbose',
abbr: 'v', negatable: false, help: 'Show verbose output.');
+ argParser.addFlag('version',
+ negatable: false, help: 'Print the Dart SDK version.');
addCommand(AnalyzeCommand(verbose: verbose));
addCommand(CreateCommand(verbose: verbose));
@@ -35,6 +37,10 @@
}
@override
+ String get invocation =>
+ 'dart [<vm-flags>] <command|dart-file> [<arguments>]';
+
+ @override
Future<int> runCommand(ArgResults results) async {
isVerbose = results['verbose'];
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index c38e3f9..b18b6e5 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -47,7 +47,8 @@
expect(result.exitCode, 0);
expect(result.stderr, isEmpty);
expect(result.stdout, contains(DartdevRunner.dartdevDescription));
- expect(result.stdout, contains('Usage: dart <command> [arguments]'));
+ expect(result.stdout,
+ contains('Usage: dart [<vm-flags>] <command|dart-file> [<arguments>]'));
expect(result.stdout, contains('Global options:'));
expect(result.stdout, contains('Available commands:'));
expect(result.stdout, contains('analyze '));
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 0ffeb41..602303d 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -8,7 +8,7 @@
show DiagnosticMessageHandler;
import 'package:kernel/default_language_version.dart' as kernel
- show defaultLanguageVersionMajor, defaultLanguageVersionMinor;
+ show defaultLanguageVersion;
import 'package:kernel/target/targets.dart' show Target;
@@ -229,9 +229,9 @@
/// The current sdk version string, e.g. "2.6.0-edge.sha1hash".
/// For instance used for language versioning (specifying the maximum
/// version).
- String currentSdkVersion = "${kernel.defaultLanguageVersionMajor}"
+ String currentSdkVersion = "${kernel.defaultLanguageVersion.major}"
"."
- "${kernel.defaultLanguageVersionMinor}";
+ "${kernel.defaultLanguageVersion.minor}";
bool equivalent(CompilerOptions other,
{bool ignoreOnDiagnostic: true,
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index cb97bf9..d5094b8 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -7,6 +7,8 @@
// Instead modify 'tools/experimental_features.yaml' and run
// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
+import 'package:kernel/kernel.dart' show Version;
+
enum ExperimentalFlag {
constantUpdate2018,
controlFlowCollections,
@@ -19,24 +21,15 @@
variance,
}
-const int enableConstantUpdate2018MajorVersion = 2;
-const int enableConstantUpdate2018MinorVersion = 4;
-const int enableControlFlowCollectionsMajorVersion = 2;
-const int enableControlFlowCollectionsMinorVersion = 2;
-const int enableExtensionMethodsMajorVersion = 2;
-const int enableExtensionMethodsMinorVersion = 6;
-const int enableNonNullableMajorVersion = 2;
-const int enableNonNullableMinorVersion = 9;
-const int enableNonfunctionTypeAliasesMajorVersion = 2;
-const int enableNonfunctionTypeAliasesMinorVersion = 9;
-const int enableSetLiteralsMajorVersion = 2;
-const int enableSetLiteralsMinorVersion = 2;
-const int enableSpreadCollectionsMajorVersion = 2;
-const int enableSpreadCollectionsMinorVersion = 2;
-const int enableTripleShiftMajorVersion = 2;
-const int enableTripleShiftMinorVersion = 9;
-const int enableVarianceMajorVersion = 2;
-const int enableVarianceMinorVersion = 9;
+const Version enableConstantUpdate2018Version = const Version(2, 4);
+const Version enableControlFlowCollectionsVersion = const Version(2, 2);
+const Version enableExtensionMethodsVersion = const Version(2, 6);
+const Version enableNonNullableVersion = const Version(2, 9);
+const Version enableNonfunctionTypeAliasesVersion = const Version(2, 9);
+const Version enableSetLiteralsVersion = const Version(2, 2);
+const Version enableSpreadCollectionsVersion = const Version(2, 2);
+const Version enableTripleShiftVersion = const Version(2, 9);
+const Version enableVarianceVersion = const Version(2, 9);
ExperimentalFlag parseExperimentalFlag(String flag) {
switch (flag) {
diff --git a/pkg/front_end/lib/src/api_prototype/language_version.dart b/pkg/front_end/lib/src/api_prototype/language_version.dart
index 4b566d6..af123e5 100644
--- a/pkg/front_end/lib/src/api_prototype/language_version.dart
+++ b/pkg/front_end/lib/src/api_prototype/language_version.dart
@@ -7,6 +7,9 @@
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
show LanguageVersionToken, Scanner, ScannerConfiguration, scan;
+import 'package:kernel/ast.dart' show Version;
+export 'package:kernel/ast.dart' show Version;
+
import 'package:package_config/package_config.dart'
show InvalidLanguageVersion, Package;
@@ -27,8 +30,7 @@
/// specifies a language version that's too high).
///
/// The language version returned is valid though.
-Future<LanguageVersionForUri> languageVersionForUri(
- Uri uri, CompilerOptions options) async {
+Future<Version> languageVersionForUri(Uri uri, CompilerOptions options) async {
return await CompilerContext.runWithOptions(
new ProcessedOptions(options: options, inputs: [uri]), (context) async {
// Get largest valid version / default version.
@@ -96,7 +98,7 @@
}
if (major != null && minor != null) {
// The file decided. Return result.
- return new LanguageVersionForUri(major, minor);
+ return new Version(major, minor);
}
// Check package.
@@ -113,18 +115,10 @@
}
if (major != null && minor != null) {
// The package decided. Return result.
- return new LanguageVersionForUri(major, minor);
+ return new Version(major, minor);
}
// Return default.
- return new LanguageVersionForUri(
- currentSdkVersionMajor, currentSdkVersionMinor);
+ return new Version(currentSdkVersionMajor, currentSdkVersionMinor);
});
}
-
-class LanguageVersionForUri {
- final int major;
- final int minor;
-
- LanguageVersionForUri(this.major, this.minor);
-}
diff --git a/pkg/front_end/lib/src/base/command_line_options.dart b/pkg/front_end/lib/src/base/command_line_options.dart
index c5bfc09..7ac70b7 100644
--- a/pkg/front_end/lib/src/base/command_line_options.dart
+++ b/pkg/front_end/lib/src/base/command_line_options.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// TODO(johnniwinther): Move all option strings here.
class Flags {
// TODO(johnniwinther): What is the right name for this?
static const String nnbdStrongMode = "--nnbd-strong";
@@ -13,4 +12,26 @@
"--force-no-explicit-getter-calls";
static const String target = "--target";
+
+ static const String linkDependencies = "--link-dependencies";
+
+ static const String bytecode = "--bytecode";
+ static const String compileSdk = "--compile-sdk";
+ static const String dumpIr = "--dump-ir";
+ static const String enableExperiment = "--enable-experiment";
+ static const String excludeSource = "--exclude-source";
+ static const String omitPlatform = "--omit-platform";
+ static const String fatal = "--fatal";
+ static const String fatalSkip = "--fatal-skip";
+ static const String help = "--help";
+ static const String librariesJson = "--libraries-json";
+ static const String noDefines = "--no-defines";
+ static const String output = "--output";
+ static const String packages = "--packages";
+ static const String platform = "--platform";
+ static const String sdk = "--sdk";
+ static const String singleRootBase = "--single-root-base";
+ static const String singleRootScheme = "--single-root-scheme";
+ static const String verbose = "--verbose";
+ static const String verify = "--verify";
}
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index e176173..224ecbc 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -6,7 +6,7 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show Library, Nullability;
+import 'package:kernel/ast.dart' show Library, Nullability, Version;
import '../combinator.dart' show Combinator;
@@ -53,7 +53,7 @@
bool mayImplementRestrictedTypes;
- /// Set the language version to a specific non-null major and minor version.
+ /// Set the language version to a specific non-null [version].
///
/// If the language version has previously been explicitly set set (i.e. with
/// [explicit] set to true), any subsequent call (explicit or not) should be
@@ -67,7 +67,7 @@
///
/// [offset] and [length] refers to the offset and length of the source code
/// specifying the language version.
- void setLanguageVersion(int major, int minor,
+ void setLanguageVersion(Version version,
{int offset: 0, int length, bool explicit});
bool get isPart;
@@ -222,6 +222,9 @@
/// Set the language version to a specific non-null major and minor version.
///
+ /// If [version] is null (and no other version has been explicitly set) a
+ /// problem is issued.
+ ///
/// If the language version has previously been explicitly set set (i.e. with
/// [explicit] set to true), any subsequent call (explicit or not) should be
/// ignored.
@@ -235,7 +238,7 @@
/// [offset] and [length] refers to the offset and length of the source code
/// specifying the language version.
@override
- void setLanguageVersion(int major, int minor,
+ void setLanguageVersion(Version version,
{int offset: 0, int length, bool explicit});
@override
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 818480a..e9a2f1d 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -26,7 +26,8 @@
StaticGet,
StringConstant,
StringLiteral,
- Typedef;
+ Typedef,
+ Version;
import '../builder/builder.dart';
import '../builder/class_builder.dart';
@@ -137,7 +138,7 @@
bool get isNonNullableByDefault => library.isNonNullableByDefault;
@override
- void setLanguageVersion(int major, int minor,
+ void setLanguageVersion(Version version,
{int offset: 0, int length, bool explicit}) {}
Uri get importUri => library.importUri;
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index db832ad..20acc5d 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -1597,9 +1597,7 @@
scope: libraryBuilder.scope.createNestedScope("expression"),
nameOrigin: libraryBuilder.library,
);
- debugLibrary.setLanguageVersion(
- libraryBuilder.library.languageVersionMajor,
- libraryBuilder.library.languageVersionMinor);
+ debugLibrary.setLanguageVersion(libraryBuilder.library.languageVersion);
if (libraryBuilder is DillLibraryBuilder) {
for (LibraryDependency dependency
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index e16103f..34c3490 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5,13 +5,9 @@
import 'dart:core' hide MapEntry;
import 'package:_fe_analyzer_shared/src/util/link.dart';
-
import 'package:kernel/ast.dart';
-
import 'package:kernel/src/future_or.dart';
-
import 'package:kernel/type_algebra.dart' show Substitution;
-
import 'package:kernel/type_environment.dart';
import '../../base/instrumentation.dart'
@@ -19,24 +15,15 @@
InstrumentationValueForMember,
InstrumentationValueForType,
InstrumentationValueForTypeArgs;
-
import '../fasta_codes.dart';
-
import '../names.dart';
-
import '../problems.dart' show unhandled;
-
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
import '../type_inference/type_inference_engine.dart';
import '../type_inference/type_inferrer.dart';
-
import '../type_inference/type_schema.dart' show UnknownType;
-
import '../type_inference/type_schema_elimination.dart' show greatestClosure;
-
import 'body_builder.dart' show combineStatements;
-
import 'collections.dart'
show
ForElement,
@@ -48,11 +35,8 @@
SpreadElement,
SpreadMapEntry,
convertToElement;
-
import 'implicit_type_argument.dart' show ImplicitTypeArgument;
-
import 'internal_ast.dart';
-
import 'late_lowering.dart' as late_lowering;
class InferenceVisitor
@@ -1247,7 +1231,19 @@
@override
StatementInferenceResult visitLabeledStatement(LabeledStatement node) {
+ bool isSimpleBody = node.body is Block ||
+ node.body is IfStatement ||
+ node.body is TryStatement;
+ if (isSimpleBody) {
+ inferrer.flowAnalysis.labeledStatement_begin(node);
+ }
+
StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+
+ if (isSimpleBody) {
+ inferrer.flowAnalysis.labeledStatement_end();
+ }
+
if (bodyResult.hasChanged) {
node.body = bodyResult.statement..parent = node;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index cd6a3a7..ee062fb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -76,8 +76,7 @@
Library realLibrary = procedure.enclosingLibrary;
Library fakeLibrary = new Library(new Uri(scheme: 'evaluate', path: 'source'))
- ..setLanguageVersion(
- realLibrary.languageVersionMajor, realLibrary.languageVersionMinor)
+ ..setLanguageVersion(realLibrary.languageVersion)
..isNonNullableByDefault = realLibrary.isNonNullableByDefault
..nonNullableByDefaultCompiledMode =
realLibrary.nonNullableByDefaultCompiledMode;
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index 0ab9f32..a7de26a 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -10,7 +10,7 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show Class, DartType, Library;
+import 'package:kernel/ast.dart' show Class, DartType, Library, Version;
import 'package:package_config/package_config.dart';
import 'scope.dart';
@@ -145,17 +145,14 @@
target.uriTranslator.packages.packageOf(fileUri);
}
bool hasPackageSpecifiedLanguageVersion = false;
- int packageSpecifiedLanguageVersionMajor;
- int packageSpecifiedLanguageVersionMinor;
+ Version version;
if (packageForLanguageVersion != null &&
packageForLanguageVersion.languageVersion != null) {
hasPackageSpecifiedLanguageVersion = true;
if (packageForLanguageVersion.languageVersion
is! InvalidLanguageVersion) {
- packageSpecifiedLanguageVersionMajor =
- packageForLanguageVersion.languageVersion.major;
- packageSpecifiedLanguageVersionMinor =
- packageForLanguageVersion.languageVersion.minor;
+ version = new Version(packageForLanguageVersion.languageVersion.major,
+ packageForLanguageVersion.languageVersion.minor);
}
}
LibraryBuilder library = target.createLibraryBuilder(
@@ -166,9 +163,7 @@
}
if (hasPackageSpecifiedLanguageVersion) {
- library.setLanguageVersion(packageSpecifiedLanguageVersionMajor,
- packageSpecifiedLanguageVersionMinor,
- explicit: false);
+ library.setLanguageVersion(version, explicit: false);
}
if (uri.scheme == "dart" && uri.path == "core") {
coreLibrary = library;
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index bb050e3..2ce9496 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -49,11 +49,9 @@
TypeParameterType,
Typedef,
VariableDeclaration,
+ Version,
VoidType;
-import 'package:kernel/default_language_version.dart' as kernel
- show defaultLanguageVersionMajor, defaultLanguageVersionMinor;
-
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
@@ -169,7 +167,7 @@
import 'source_loader.dart' show SourceLoader;
import '../../api_prototype/experimental_flags.dart'
- show enableNonNullableMajorVersion, enableNonNullableMinorVersion;
+ show enableNonNullableVersion;
class SourceLibraryBuilder extends LibraryBuilderImpl {
static const String MALFORMED_URI_SCHEME = "org-dartlang-malformed-uri";
@@ -272,7 +270,7 @@
List<FieldBuilder> _implicitlyTypedFields;
- LanguageVersion _languageVersion = const ImplicitLanguageVersion();
+ LanguageVersion _languageVersion;
bool postponedProblemsIssued = false;
List<PostponedProblem> postponedProblems;
@@ -312,7 +310,8 @@
this.library,
this._nameOrigin,
this.referencesFrom)
- : currentTypeParameterScopeBuilder = libraryDeclaration,
+ : _languageVersion = new ImplicitLanguageVersion(library.languageVersion),
+ currentTypeParameterScopeBuilder = libraryDeclaration,
referencesFromIndexed =
referencesFrom == null ? null : new IndexedLibrary(referencesFrom),
super(
@@ -362,8 +361,7 @@
reference: referenceIsPartOwner == true
? null
: referencesFrom?.reference)
- ..setLanguageVersion(loader.target.currentSdkVersionMajor,
- loader.target.currentSdkVersionMinor)),
+ ..setLanguageVersion(loader.target.currentSdkVersion)),
nameOrigin,
referencesFrom,
referenceIsPartOwner);
@@ -385,8 +383,7 @@
@override
bool get isNonNullableByDefault =>
loader.target.enableNonNullable &&
- languageVersion.major >= enableNonNullableMajorVersion &&
- languageVersion.minor >= enableNonNullableMinorVersion &&
+ languageVersion.version >= enableNonNullableVersion &&
!isOptOutTest(library.importUri);
bool isOptOutTest(Uri uri) {
@@ -416,56 +413,42 @@
LanguageVersion get languageVersion => _languageVersion;
@override
- void setLanguageVersion(int major, int minor,
+ void setLanguageVersion(Version version,
{int offset: 0, int length: noLength, bool explicit: false}) {
if (languageVersion.isExplicit) return;
- if (major == null || minor == null) {
+ if (version == null) {
addPostponedProblem(
messageLanguageVersionInvalidInDotPackages, offset, length, fileUri);
if (_languageVersion is ImplicitLanguageVersion) {
_languageVersion = new InvalidLanguageVersion(
- fileUri,
- offset,
- length,
- explicit,
- loader.target.currentSdkVersionMajor,
- loader.target.currentSdkVersionMinor);
- library.setLanguageVersion(
- _languageVersion.major, _languageVersion.minor);
+ fileUri, offset, length, explicit, loader.target.currentSdkVersion);
+ library.setLanguageVersion(_languageVersion.version);
}
return;
}
// If trying to set a language version that is higher than the current sdk
// version it's an error.
- if (major > loader.target.currentSdkVersionMajor ||
- (major == loader.target.currentSdkVersionMajor &&
- minor > loader.target.currentSdkVersionMinor)) {
+ if (version > loader.target.currentSdkVersion) {
addPostponedProblem(
templateLanguageVersionTooHigh.withArguments(
- loader.target.currentSdkVersionMajor,
- loader.target.currentSdkVersionMinor),
+ loader.target.currentSdkVersion.major,
+ loader.target.currentSdkVersion.minor),
offset,
length,
fileUri);
if (_languageVersion is ImplicitLanguageVersion) {
_languageVersion = new InvalidLanguageVersion(
- fileUri,
- offset,
- length,
- explicit,
- loader.target.currentSdkVersionMajor,
- loader.target.currentSdkVersionMinor);
- library.setLanguageVersion(
- _languageVersion.major, _languageVersion.minor);
+ fileUri, offset, length, explicit, loader.target.currentSdkVersion);
+ library.setLanguageVersion(_languageVersion.version);
}
return;
}
_languageVersion =
- new LanguageVersion(major, minor, fileUri, offset, length, explicit);
- library.setLanguageVersion(major, minor);
+ new LanguageVersion(version, fileUri, offset, length, explicit);
+ library.setLanguageVersion(version);
}
ConstructorReferenceBuilder addConstructorReference(Object name,
@@ -3743,31 +3726,28 @@
}
class LanguageVersion {
- final int major;
- final int minor;
+ final Version version;
final Uri fileUri;
final int charOffset;
final int charCount;
final bool isExplicit;
- LanguageVersion(this.major, this.minor, this.fileUri, this.charOffset,
- this.charCount, this.isExplicit);
+ LanguageVersion(this.version, this.fileUri, this.charOffset, this.charCount,
+ this.isExplicit);
bool get valid => true;
- int get hashCode =>
- major.hashCode * 13 + minor.hashCode * 17 + isExplicit.hashCode * 19;
+ int get hashCode => version.hashCode * 13 + isExplicit.hashCode * 19;
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is LanguageVersion &&
- major == other.major &&
- minor == other.minor &&
+ version == other.version &&
isExplicit == other.isExplicit;
}
String toString() {
- return 'LanguageVersion(major=$major,minor=$minor,isExplicit=$isExplicit,'
+ return 'LanguageVersion(version=$version,isExplicit=$isExplicit,'
'fileUri=$fileUri,charOffset=$charOffset,charCount=$charCount)';
}
}
@@ -3777,11 +3757,10 @@
final int charOffset;
final int charCount;
final bool isExplicit;
- final int major;
- final int minor;
+ final Version version;
InvalidLanguageVersion(this.fileUri, this.charOffset, this.charCount,
- this.isExplicit, this.major, this.minor);
+ this.isExplicit, this.version);
@override
bool get valid => false;
@@ -3800,13 +3779,10 @@
}
class ImplicitLanguageVersion implements LanguageVersion {
- const ImplicitLanguageVersion();
-
@override
- int get major => kernel.defaultLanguageVersionMajor;
+ final Version version;
- @override
- int get minor => kernel.defaultLanguageVersionMinor;
+ ImplicitLanguageVersion(this.version);
@override
bool get valid => true;
@@ -3823,6 +3799,13 @@
@override
bool get isExplicit => false;
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ return other is ImplicitLanguageVersion && version == other.version;
+ }
+
@override
- String toString() => 'ImplicitLanguageVersion()';
+ String toString() {
+ return 'ImplicitLanguageVersion(version=$version)';
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 5d6a44d..ad7173c 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -42,7 +42,8 @@
ProcedureKind,
Reference,
Supertype,
- TreeNode;
+ TreeNode,
+ Version;
import 'package:kernel/class_hierarchy.dart'
show ClassHierarchy, HandleAmbiguousSupertypes;
@@ -258,7 +259,7 @@
enableNonNullable: library.isNonNullableByDefault),
languageVersionChanged:
(Scanner scanner, LanguageVersionToken version) {
- library.setLanguageVersion(version.major, version.minor,
+ library.setLanguageVersion(new Version(version.major, version.minor),
offset: version.offset, length: version.length, explicit: true);
scanner.configuration = new ScannerConfiguration(
enableTripleShift: target.enableTripleShift,
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 00c4bef..26400d6 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -6,7 +6,7 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show Library, Source;
+import 'package:kernel/ast.dart' show Library, Source, Version;
import 'package:kernel/target/targets.dart' as backend show Target;
@@ -169,36 +169,30 @@
return rewriteSeverity(severity, message.code, fileUri);
}
- String get currentSdkVersion {
+ String get currentSdkVersionString {
return CompilerContext.current.options.currentSdkVersion;
}
- int _currentSdkVersionMajor;
- int _currentSdkVersionMinor;
- int get currentSdkVersionMajor {
- if (_currentSdkVersionMajor != null) return _currentSdkVersionMajor;
+ Version _currentSdkVersion;
+ Version get currentSdkVersion {
+ if (_currentSdkVersion != null) return _currentSdkVersion;
_parseCurrentSdkVersion();
- return _currentSdkVersionMajor;
- }
-
- int get currentSdkVersionMinor {
- if (_currentSdkVersionMinor != null) return _currentSdkVersionMinor;
- _parseCurrentSdkVersion();
- return _currentSdkVersionMinor;
+ return _currentSdkVersion;
}
void _parseCurrentSdkVersion() {
bool good = false;
- if (currentSdkVersion != null) {
- List<String> dotSeparatedParts = currentSdkVersion.split(".");
+ if (currentSdkVersionString != null) {
+ List<String> dotSeparatedParts = currentSdkVersionString.split(".");
if (dotSeparatedParts.length >= 2) {
- _currentSdkVersionMajor = int.tryParse(dotSeparatedParts[0]);
- _currentSdkVersionMinor = int.tryParse(dotSeparatedParts[1]);
+ _currentSdkVersion = new Version(int.tryParse(dotSeparatedParts[0]),
+ int.tryParse(dotSeparatedParts[1]));
good = true;
}
}
if (!good) {
- throw new StateError("Unparsable sdk version given: $currentSdkVersion");
+ throw new StateError(
+ "Unparsable sdk version given: $currentSdkVersionString");
}
}
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 7b38839..81c2a65 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1613,9 +1613,6 @@
Location of the SDK sources for use when compiling additional platform
libraries.
- --supermixin
- Ignored for now.
-
--single-root-scheme=String
--single-root-base=<dir>
Specify a custom URI scheme and a location on disk where such URIs are
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart
new file mode 100644
index 0000000..5d74600
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart
Binary files differ
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect
new file mode 100644
index 0000000..cbfa036
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect
Binary files differ
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect
new file mode 100644
index 0000000..95a1a29
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect
@@ -0,0 +1,2729 @@
+parseUnit(EncodingErrorToken())
+ skipErrorTokens(EncodingErrorToken())
+ listener: beginCompilationUnit(/)
+ syntheticPreviousToken(/)
+ parseTopLevelDeclarationImpl(AsciiControlCharacterToken(0), Instance of 'DirectiveContext')
+ parseMetadataStar(AsciiControlCharacterToken(0))
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(AsciiControlCharacterToken(0))
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(/)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(C)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(C)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(/)
+ listener: beginTopLevelMember(C)
+ parseFields(/, null, null, null, null, null, /, Instance of 'SimpleType', o, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(C, typeReference)
+ listener: handleNoTypeArguments(o)
+ listener: handleType(C, null)
+ ensureIdentifier(C, topLevelVariableDeclaration)
+ listener: handleIdentifier(o, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(o, o, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(p)
+ ensureSemicolon(o)
+ reportRecoverableError(o, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], o, o)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, C, ;)
+ listener: endTopLevelDeclaration(p)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(p)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(p)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', y, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(p, typeReference)
+ listener: handleNoTypeArguments(y)
+ listener: handleType(p, null)
+ ensureIdentifier(p, topLevelVariableDeclaration)
+ listener: handleIdentifier(y, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(y, y, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(r)
+ ensureSemicolon(y)
+ reportRecoverableError(y, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], y, y)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, p, ;)
+ listener: endTopLevelDeclaration(r)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(r)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(r)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', i, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(r, typeReference)
+ listener: handleNoTypeArguments(i)
+ listener: handleType(r, null)
+ ensureIdentifier(r, topLevelVariableDeclaration)
+ listener: handleIdentifier(i, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(i, i, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(g)
+ ensureSemicolon(i)
+ reportRecoverableError(i, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], i, i)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, r, ;)
+ listener: endTopLevelDeclaration(g)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(g)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(g)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', h, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(g, typeReference)
+ listener: handleNoTypeArguments(h)
+ listener: handleType(g, null)
+ ensureIdentifier(g, topLevelVariableDeclaration)
+ listener: handleIdentifier(h, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(h, h, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(t)
+ ensureSemicolon(h)
+ reportRecoverableError(h, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], h, h)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, g, ;)
+ listener: endTopLevelDeclaration(t)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(t)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(t)
+ parseTopLevelMethod(;, null, ;, Instance of 'NoType', null, t)
+ listener: beginTopLevelMethod(;, null)
+ listener: handleNoType(;)
+ ensureIdentifier(;, topLevelFunctionDeclaration)
+ listener: handleIdentifier(t, topLevelFunctionDeclaration)
+ parseMethodTypeVar(t)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters(t, t, false, MemberKind.TopLevelMethod)
+ parseFormalParameters(t, MemberKind.TopLevelMethod)
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+ parseMetadataStar(()
+ listener: beginMetadataStar(c)
+ listener: endMetadataStar(0)
+ listener: beginFormalParameter(c, MemberKind.TopLevelMethod, null, null, null)
+ listener: handleNoType(()
+ ensureIdentifier((, formalParameterDeclaration)
+ listener: handleIdentifier(c, formalParameterDeclaration)
+ listener: handleFormalParameterWithoutValue())
+ listener: endFormalParameter(null, null, c, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+ reportRecoverableError(2, Message[ExpectedFunctionBody, Expected a function body, but got '2'., null, {token: 2}])
+ listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '2'., null, {token: 2}], 2, 2)
+ insertBlock())
+ rewriter()
+ rewriter()
+ listener: handleInvalidFunctionBody({)
+ listener: endTopLevelMethod(t, null, })
+ listener: endTopLevelDeclaration(2)
+ parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+ parseMetadataStar(})
+ listener: beginMetadataStar(2)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(2)
+ parseInvalidTopLevelDeclaration(})
+ reportRecoverableErrorWithToken(2, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '2'., null, {token: 2}], 2, 2)
+ listener: handleInvalidTopLevelDeclaration(2)
+ listener: endTopLevelDeclaration(0)
+ parseTopLevelDeclarationImpl(2, Instance of 'DirectiveContext')
+ parseMetadataStar(2)
+ listener: beginMetadataStar(0)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(0)
+ parseInvalidTopLevelDeclaration(2)
+ reportRecoverableErrorWithToken(0, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '0'., null, {token: 0}], 0, 0)
+ listener: handleInvalidTopLevelDeclaration(0)
+ listener: endTopLevelDeclaration(2)
+ parseTopLevelDeclarationImpl(0, Instance of 'DirectiveContext')
+ parseMetadataStar(0)
+ listener: beginMetadataStar(2)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(2)
+ parseInvalidTopLevelDeclaration(0)
+ reportRecoverableErrorWithToken(2, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '2'., null, {token: 2}], 2, 2)
+ listener: handleInvalidTopLevelDeclaration(2)
+ listener: endTopLevelDeclaration(0)
+ parseTopLevelDeclarationImpl(2, Instance of 'DirectiveContext')
+ parseMetadataStar(2)
+ listener: beginMetadataStar(0)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(0)
+ parseInvalidTopLevelDeclaration(2)
+ reportRecoverableErrorWithToken(0, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '0'., null, {token: 0}], 0, 0)
+ listener: handleInvalidTopLevelDeclaration(0)
+ listener: endTopLevelDeclaration(,)
+ parseTopLevelDeclarationImpl(0, Instance of 'DirectiveContext')
+ parseMetadataStar(0)
+ listener: beginMetadataStar(,)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(,)
+ parseInvalidTopLevelDeclaration(0)
+ reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ','., null, {token: ,}], ,, ,)
+ listener: handleInvalidTopLevelDeclaration(,)
+ listener: endTopLevelDeclaration(t)
+ parseTopLevelDeclarationImpl(,, Instance of 'DirectiveContext')
+ parseMetadataStar(,)
+ listener: beginMetadataStar(t)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(,)
+ listener: beginTopLevelMember(t)
+ parseFields(,, null, null, null, null, null, ,, Instance of 'SimpleType', h, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(t, typeReference)
+ listener: handleNoTypeArguments(h)
+ listener: handleType(t, null)
+ ensureIdentifier(t, topLevelVariableDeclaration)
+ listener: handleIdentifier(h, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(h, h, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(h)
+ reportRecoverableError(h, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], h, h)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, t, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', D, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(D)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(D, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(D, D, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(a)
+ ensureSemicolon(D)
+ reportRecoverableError(D, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], D, D)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(a)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(a)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(a)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', r, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(a, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(a, null)
+ ensureIdentifier(a, topLevelVariableDeclaration)
+ listener: handleIdentifier(r, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(r, r, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(t)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, a, ;)
+ listener: endTopLevelDeclaration(t)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(t)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(t)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', p, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(t, typeReference)
+ listener: handleNoTypeArguments(p)
+ listener: handleType(t, null)
+ ensureIdentifier(t, topLevelVariableDeclaration)
+ listener: handleIdentifier(p, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(p, p, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(r)
+ ensureSemicolon(p)
+ reportRecoverableError(p, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], p, p)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, t, ;)
+ listener: endTopLevelDeclaration(r)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(r)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(r)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', o, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(r, typeReference)
+ listener: handleNoTypeArguments(o)
+ listener: handleType(r, null)
+ ensureIdentifier(r, topLevelVariableDeclaration)
+ listener: handleIdentifier(o, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(o, o, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(j)
+ ensureSemicolon(o)
+ reportRecoverableError(o, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], o, o)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, r, ;)
+ listener: endTopLevelDeclaration(j)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(j)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(j)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(j, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(j, null)
+ ensureIdentifier(j, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(c)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, j, ;)
+ listener: endTopLevelDeclaration(c)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(c)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(c)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(c, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(c, null)
+ ensureIdentifier(c, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(a)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, c, ;)
+ listener: endTopLevelDeclaration(a)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(a)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(a)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', u, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(a, typeReference)
+ listener: handleNoTypeArguments(u)
+ listener: handleType(a, null)
+ ensureIdentifier(a, topLevelVariableDeclaration)
+ listener: handleIdentifier(u, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(u, u, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(t)
+ ensureSemicolon(u)
+ reportRecoverableError(u, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], u, u)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, a, ;)
+ listener: endTopLevelDeclaration(t)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(t)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(t)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', h, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(t, typeReference)
+ listener: handleNoTypeArguments(h)
+ listener: handleType(t, null)
+ ensureIdentifier(t, topLevelVariableDeclaration)
+ listener: handleIdentifier(h, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(h, h, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(o)
+ ensureSemicolon(h)
+ reportRecoverableError(h, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], h, h)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, t, ;)
+ listener: endTopLevelDeclaration(o)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(o)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(o)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', r, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(o, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(o, null)
+ ensureIdentifier(o, topLevelVariableDeclaration)
+ listener: handleIdentifier(r, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(r, r, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, o, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'PrefixedType', l, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, prefixedTypeReference)
+ listener: handleIdentifier(P, typeReferenceContinuation)
+ listener: handleQualified(.)
+ listener: handleNoTypeArguments(l)
+ listener: handleType(s, null)
+ ensureIdentifier(P, topLevelVariableDeclaration)
+ listener: handleIdentifier(l, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(l, l, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(l)
+ reportRecoverableError(l, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], l, l)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', a, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(a)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(a, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(a, a, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(a)
+ reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(h)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(h)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(h)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(h)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(h, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(h, null)
+ ensureIdentifier(h, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(A)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, h, ;)
+ listener: endTopLevelDeclaration(A)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(A)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(A)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', U, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(A, typeReference)
+ listener: handleNoTypeArguments(U)
+ listener: handleType(A, null)
+ ensureIdentifier(A, topLevelVariableDeclaration)
+ listener: handleIdentifier(U, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(U, U, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(T)
+ ensureSemicolon(U)
+ reportRecoverableError(U, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], U, U)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, A, ;)
+ listener: endTopLevelDeclaration(T)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(T)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(T)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', H, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(T, typeReference)
+ listener: handleNoTypeArguments(H)
+ listener: handleType(T, null)
+ ensureIdentifier(T, topLevelVariableDeclaration)
+ listener: handleIdentifier(H, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(H, H, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(O)
+ ensureSemicolon(H)
+ reportRecoverableError(H, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], H, H)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, T, ;)
+ listener: endTopLevelDeclaration(O)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(O)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(O)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', R, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(O, typeReference)
+ listener: handleNoTypeArguments(R)
+ listener: handleType(O, null)
+ ensureIdentifier(O, topLevelVariableDeclaration)
+ listener: handleIdentifier(R, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(R, R, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(S)
+ ensureSemicolon(R)
+ reportRecoverableError(R, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], R, R)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, O, ;)
+ listener: endTopLevelDeclaration(S)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(S)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(S)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', f, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(S, typeReference)
+ listener: handleNoTypeArguments(f)
+ listener: handleType(S, null)
+ ensureIdentifier(S, topLevelVariableDeclaration)
+ listener: handleIdentifier(f, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(f, f, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(f)
+ reportRecoverableError(f, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], f, f)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, S, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', l, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(l)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelVariableDeclaration)
+ listener: handleIdentifier(l, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(l, l, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(l)
+ reportRecoverableError(l, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], l, l)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, i, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'NoType', e, DeclarationKind.TopLevel, null)
+ reportRecoverableError(e, MissingConstFinalVarOrType)
+ listener: handleRecoverableError(MissingConstFinalVarOrType, e, e)
+ listener: handleNoType(;)
+ ensureIdentifier(;, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(/)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(;)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(/)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(f)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(f)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(/)
+ listener: beginTopLevelMember(f)
+ parseFields(/, null, null, null, null, null, /, Instance of 'SimpleType', o, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(f, typeReference)
+ listener: handleNoTypeArguments(o)
+ listener: handleType(f, null)
+ ensureIdentifier(f, topLevelVariableDeclaration)
+ listener: handleIdentifier(o, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(o, o, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(r)
+ ensureSemicolon(o)
+ reportRecoverableError(o, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], o, o)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, f, ;)
+ listener: endTopLevelDeclaration(r)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(r)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(r)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', d, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(r, typeReference)
+ listener: handleNoTypeArguments(d)
+ listener: handleType(r, null)
+ ensureIdentifier(r, topLevelVariableDeclaration)
+ listener: handleIdentifier(d, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(d, d, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(d)
+ reportRecoverableError(d, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], d, d)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, r, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(a)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(a)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(a)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(a)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', i, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(a, typeReference)
+ listener: handleNoTypeArguments(i)
+ listener: handleType(a, null)
+ ensureIdentifier(a, topLevelVariableDeclaration)
+ listener: handleIdentifier(i, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(i, i, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(l)
+ ensureSemicolon(i)
+ reportRecoverableError(i, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], i, i)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, a, ;)
+ listener: endTopLevelDeclaration(l)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(l)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(l)
+ parseTopLevelMethod(;, null, ;, Instance of 'SimpleType', null, s)
+ listener: beginTopLevelMethod(;, null)
+ listener: handleIdentifier(l, typeReference)
+ listener: handleNoTypeArguments(s)
+ listener: handleType(l, null)
+ ensureIdentifier(l, topLevelFunctionDeclaration)
+ listener: handleIdentifier(s, topLevelFunctionDeclaration)
+ parseMethodTypeVar(s)
+ listener: handleNoTypeVariables(.)
+ parseGetterOrFormalParameters(s, s, false, MemberKind.TopLevelMethod)
+ missingParameterMessage(MemberKind.TopLevelMethod)
+ reportRecoverableError(s, MissingFunctionParameters)
+ listener: handleRecoverableError(MissingFunctionParameters, s, s)
+ rewriter()
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+ reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
+ listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+ insertBlock())
+ rewriter()
+ rewriter()
+ listener: handleInvalidFunctionBody({)
+ listener: endTopLevelMethod(l, null, })
+ listener: endTopLevelDeclaration(.)
+ parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+ parseMetadataStar(})
+ listener: beginMetadataStar(.)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(.)
+ parseInvalidTopLevelDeclaration(})
+ reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+ listener: handleInvalidTopLevelDeclaration(.)
+ listener: endTopLevelDeclaration(A)
+ parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
+ parseMetadataStar(.)
+ listener: beginMetadataStar(A)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(.)
+ listener: beginTopLevelMember(A)
+ parseFields(., null, null, null, null, null, ., Instance of 'SimpleType', l, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(A, typeReference)
+ listener: handleNoTypeArguments(l)
+ listener: handleType(A, null)
+ ensureIdentifier(A, topLevelVariableDeclaration)
+ listener: handleIdentifier(l, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(l, l, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(l)
+ ensureSemicolon(l)
+ reportRecoverableError(l, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], l, l)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, A, ;)
+ listener: endTopLevelDeclaration(l)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(l)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(l)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', r, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(l, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(l, null)
+ ensureIdentifier(l, topLevelVariableDeclaration)
+ listener: handleIdentifier(r, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(r, r, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, l, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', g, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(g)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelVariableDeclaration)
+ listener: handleIdentifier(g, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(g, g, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(h)
+ ensureSemicolon(g)
+ reportRecoverableError(g, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], g, g)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, i, ;)
+ listener: endTopLevelDeclaration(h)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(h)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(h)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(h, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(h, null)
+ ensureIdentifier(h, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, h, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', r, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(r, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(r, r, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', s, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(s)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(s, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(s, s, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(s)
+ reportRecoverableError(s, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], s, s)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', r, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(r, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(r, r, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(v)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(v)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(v)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(v)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(v, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(v, null)
+ ensureIdentifier(v, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(d)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, v, ;)
+ listener: endTopLevelDeclaration(d)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(d)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(d)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'PrefixedType', s, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(d, prefixedTypeReference)
+ listener: handleIdentifier(U, typeReferenceContinuation)
+ listener: handleQualified(.)
+ listener: handleNoTypeArguments(s)
+ listener: handleType(d, null)
+ ensureIdentifier(U, topLevelVariableDeclaration)
+ listener: handleIdentifier(s, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(s, s, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(s)
+ reportRecoverableError(s, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], s, s)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, d, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', o, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(o)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(o, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(o, o, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(f)
+ ensureSemicolon(o)
+ reportRecoverableError(o, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], o, o)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(f)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(f)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(f)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(f, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(f, null)
+ ensureIdentifier(f, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(h)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, f, ;)
+ listener: endTopLevelDeclaration(h)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(h)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(h)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', i, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(h, typeReference)
+ listener: handleNoTypeArguments(i)
+ listener: handleType(h, null)
+ ensureIdentifier(h, topLevelVariableDeclaration)
+ listener: handleIdentifier(i, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(i, i, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(i)
+ reportRecoverableError(i, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], i, i)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, h, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', s, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(s)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(s, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(s, s, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(o)
+ ensureSemicolon(s)
+ reportRecoverableError(s, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], s, s)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(o)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(o)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(o)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', u, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(o, typeReference)
+ listener: handleNoTypeArguments(u)
+ listener: handleType(o, null)
+ ensureIdentifier(o, topLevelVariableDeclaration)
+ listener: handleIdentifier(u, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(u, u, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(r)
+ ensureSemicolon(u)
+ reportRecoverableError(u, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], u, u)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, o, ;)
+ listener: endTopLevelDeclaration(r)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(r)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(r)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', c, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(r, typeReference)
+ listener: handleNoTypeArguments(c)
+ listener: handleType(r, null)
+ ensureIdentifier(r, topLevelVariableDeclaration)
+ listener: handleIdentifier(c, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(c, c, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(c)
+ reportRecoverableError(c, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], c, c)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, r, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', c, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(c)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(c, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(c, c, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(o)
+ ensureSemicolon(c)
+ reportRecoverableError(c, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], c, c)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(o)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(o)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(o)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', d, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(o, typeReference)
+ listener: handleNoTypeArguments(d)
+ listener: handleType(o, null)
+ ensureIdentifier(o, topLevelVariableDeclaration)
+ listener: handleIdentifier(d, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(d, d, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(d)
+ reportRecoverableError(d, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], d, d)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, o, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', i, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(i)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(i, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(i, i, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(i)
+ reportRecoverableError(i, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], i, i)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', g, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(g)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(g, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(g, g, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(o)
+ ensureSemicolon(g)
+ reportRecoverableError(g, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], g, g)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(o)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(o)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(o)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', v, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(o, typeReference)
+ listener: handleNoTypeArguments(v)
+ listener: handleType(o, null)
+ ensureIdentifier(o, topLevelVariableDeclaration)
+ listener: handleIdentifier(v, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(v, v, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(v)
+ reportRecoverableError(v, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], v, v)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, o, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', r, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(r, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(r, r, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(n)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(n)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(n)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(n)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(n, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(n, null)
+ ensureIdentifier(n, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(d)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, n, ;)
+ listener: endTopLevelDeclaration(d)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(d)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(d)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', b, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(d, typeReference)
+ listener: handleNoTypeArguments(b)
+ listener: handleType(d, null)
+ ensureIdentifier(d, topLevelVariableDeclaration)
+ listener: handleIdentifier(b, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(b, b, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(y)
+ ensureSemicolon(b)
+ reportRecoverableError(b, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], b, b)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, d, ;)
+ listener: endTopLevelDeclaration(y)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(y)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(y)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', a, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(y, typeReference)
+ listener: handleNoTypeArguments(a)
+ listener: handleType(y, null)
+ ensureIdentifier(y, topLevelVariableDeclaration)
+ listener: handleIdentifier(a, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(a, a, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(/)
+ ensureSemicolon(a)
+ reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, y, ;)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(;)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(/)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(B)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(B)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(/)
+ listener: beginTopLevelMember(B)
+ parseFields(/, null, null, null, null, null, /, Instance of 'SimpleType', S, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(B, typeReference)
+ listener: handleNoTypeArguments(S)
+ listener: handleType(B, null)
+ ensureIdentifier(B, topLevelVariableDeclaration)
+ listener: handleIdentifier(S, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(S, S, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(D)
+ ensureSemicolon(S)
+ reportRecoverableError(S, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], S, S)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, B, ;)
+ listener: endTopLevelDeclaration(D)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(D)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(D)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'NoType', D, DeclarationKind.TopLevel, null)
+ reportRecoverableError(D, MissingConstFinalVarOrType)
+ listener: handleRecoverableError(MissingConstFinalVarOrType, D, D)
+ listener: handleNoType(;)
+ ensureIdentifier(;, topLevelVariableDeclaration)
+ listener: handleIdentifier(D, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(D, D, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(-)
+ ensureSemicolon(D)
+ reportRecoverableError(D, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], D, D)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, D, ;)
+ listener: endTopLevelDeclaration(-)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(-)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(-)
+ parseInvalidTopLevelDeclaration(;)
+ reportRecoverableErrorWithToken(-, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '-'., null, {token: -}], -, -)
+ listener: handleInvalidTopLevelDeclaration(-)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(-, Instance of 'DirectiveContext')
+ parseMetadataStar(-)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(-)
+ listener: beginTopLevelMember(s)
+ parseFields(-, null, null, null, null, null, -, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(y)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(y)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(y)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(y)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', l, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(y, typeReference)
+ listener: handleNoTypeArguments(l)
+ listener: handleType(y, null)
+ ensureIdentifier(y, topLevelVariableDeclaration)
+ listener: handleIdentifier(l, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(l, l, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(l)
+ reportRecoverableError(l, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], l, l)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, y, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', l, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(l)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(l, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(l, l, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(l)
+ reportRecoverableError(l, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], l, l)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', c, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(c)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelVariableDeclaration)
+ listener: handleIdentifier(c, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(c, c, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(c)
+ reportRecoverableError(c, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], c, c)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, i, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', n, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(n)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(n, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(n, n, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(n)
+ reportRecoverableError(n, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], n, n)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(t)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(t)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(t)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(t)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', h, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(t, typeReference)
+ listener: handleNoTypeArguments(h)
+ listener: handleType(t, null)
+ ensureIdentifier(t, topLevelVariableDeclaration)
+ listener: handleIdentifier(h, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(h, h, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(a)
+ ensureSemicolon(h)
+ reportRecoverableError(h, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], h, h)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, t, ;)
+ listener: endTopLevelDeclaration(a)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(a)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(a)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', t, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(a, typeReference)
+ listener: handleNoTypeArguments(t)
+ listener: handleType(a, null)
+ ensureIdentifier(a, topLevelVariableDeclaration)
+ listener: handleIdentifier(t, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(t, t, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(c)
+ ensureSemicolon(t)
+ reportRecoverableError(t, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], t, t)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, a, ;)
+ listener: endTopLevelDeclaration(c)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(c)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(c)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', a, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(c, typeReference)
+ listener: handleNoTypeArguments(a)
+ listener: handleType(c, null)
+ ensureIdentifier(c, topLevelVariableDeclaration)
+ listener: handleIdentifier(a, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(a, a, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(n)
+ ensureSemicolon(a)
+ reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, c, ;)
+ listener: endTopLevelDeclaration(n)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(n)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(n)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', b, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(n, typeReference)
+ listener: handleNoTypeArguments(b)
+ listener: handleType(n, null)
+ ensureIdentifier(n, topLevelVariableDeclaration)
+ listener: handleIdentifier(b, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(b, b, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(b)
+ reportRecoverableError(b, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], b, b)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, n, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', f, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(f)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(f, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(f, f, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(o)
+ ensureSemicolon(f)
+ reportRecoverableError(f, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], f, f)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(o)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(o)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(o)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', u, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(o, typeReference)
+ listener: handleNoTypeArguments(u)
+ listener: handleType(o, null)
+ ensureIdentifier(o, topLevelVariableDeclaration)
+ listener: handleIdentifier(u, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(u, u, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(n)
+ ensureSemicolon(u)
+ reportRecoverableError(u, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], u, u)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, o, ;)
+ listener: endTopLevelDeclaration(n)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(n)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(n)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', d, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(n, typeReference)
+ listener: handleNoTypeArguments(d)
+ listener: handleType(n, null)
+ ensureIdentifier(n, topLevelVariableDeclaration)
+ listener: handleIdentifier(d, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(d, d, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(d)
+ reportRecoverableError(d, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], d, d)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, n, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', n, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(n)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelVariableDeclaration)
+ listener: handleIdentifier(n, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(n, n, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(t)
+ ensureSemicolon(n)
+ reportRecoverableError(n, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], n, n)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, i, ;)
+ listener: endTopLevelDeclaration(t)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(t)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(t)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', h, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(t, typeReference)
+ listener: handleNoTypeArguments(h)
+ listener: handleType(t, null)
+ ensureIdentifier(t, topLevelVariableDeclaration)
+ listener: handleIdentifier(h, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(h, h, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(e)
+ ensureSemicolon(h)
+ reportRecoverableError(h, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], h, h)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, t, ;)
+ listener: endTopLevelDeclaration(e)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(e)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(e)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', L, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(e, typeReference)
+ listener: handleNoTypeArguments(L)
+ listener: handleType(e, null)
+ ensureIdentifier(e, topLevelVariableDeclaration)
+ listener: handleIdentifier(L, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(L, L, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(I)
+ ensureSemicolon(L)
+ reportRecoverableError(L, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], L, L)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, e, ;)
+ listener: endTopLevelDeclaration(I)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(I)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(I)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', C, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(I, typeReference)
+ listener: handleNoTypeArguments(C)
+ listener: handleType(I, null)
+ ensureIdentifier(I, topLevelVariableDeclaration)
+ listener: handleIdentifier(C, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(C, C, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(E)
+ ensureSemicolon(C)
+ reportRecoverableError(C, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], C, C)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, I, ;)
+ listener: endTopLevelDeclaration(E)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(E)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(E)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', N, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(E, typeReference)
+ listener: handleNoTypeArguments(N)
+ listener: handleType(E, null)
+ ensureIdentifier(E, topLevelVariableDeclaration)
+ listener: handleIdentifier(N, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(N, N, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(S)
+ ensureSemicolon(N)
+ reportRecoverableError(N, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], N, N)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, E, ;)
+ listener: endTopLevelDeclaration(S)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(S)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(S)
+ parseTopLevelMethod(;, null, ;, Instance of 'SimpleType', null, E)
+ listener: beginTopLevelMethod(;, null)
+ listener: handleIdentifier(S, typeReference)
+ listener: handleNoTypeArguments(E)
+ listener: handleType(S, null)
+ ensureIdentifier(S, topLevelFunctionDeclaration)
+ listener: handleIdentifier(E, topLevelFunctionDeclaration)
+ parseMethodTypeVar(E)
+ listener: handleNoTypeVariables(.)
+ parseGetterOrFormalParameters(E, E, false, MemberKind.TopLevelMethod)
+ missingParameterMessage(MemberKind.TopLevelMethod)
+ reportRecoverableError(E, MissingFunctionParameters)
+ listener: handleRecoverableError(MissingFunctionParameters, E, E)
+ rewriter()
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+ reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
+ listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+ insertBlock())
+ rewriter()
+ rewriter()
+ listener: handleInvalidFunctionBody({)
+ listener: endTopLevelMethod(S, null, })
+ listener: endTopLevelDeclaration(.)
+ parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+ parseMetadataStar(})
+ listener: beginMetadataStar(.)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(.)
+ parseInvalidTopLevelDeclaration(})
+ reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+ listener: handleInvalidTopLevelDeclaration(.)
+ listener: endTopLevelDeclaration(m)
+ parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
+ parseMetadataStar(.)
+ listener: beginMetadataStar(m)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(.)
+ listener: beginTopLevelMember(m)
+ parseFields(., null, null, null, null, null, ., Instance of 'SimpleType', d, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(m, typeReference)
+ listener: handleNoTypeArguments(d)
+ listener: handleType(m, null)
+ ensureIdentifier(m, topLevelVariableDeclaration)
+ listener: handleIdentifier(d, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(d, d, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(f)
+ ensureSemicolon(d)
+ reportRecoverableError(d, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], d, d)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, m, ;)
+ listener: endTopLevelDeclaration(f)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(f)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(f)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', i, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(f, typeReference)
+ listener: handleNoTypeArguments(i)
+ listener: handleType(f, null)
+ ensureIdentifier(f, topLevelVariableDeclaration)
+ listener: handleIdentifier(i, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(i, i, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(l)
+ ensureSemicolon(i)
+ reportRecoverableError(i, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], i, i)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, f, ;)
+ listener: endTopLevelDeclaration(l)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(l)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(l)
+ parseTopLevelMethod(;, null, ;, Instance of 'SimpleType', null, e)
+ listener: beginTopLevelMethod(;, null)
+ listener: handleIdentifier(l, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(l, null)
+ ensureIdentifier(l, topLevelFunctionDeclaration)
+ listener: handleIdentifier(e, topLevelFunctionDeclaration)
+ parseMethodTypeVar(e)
+ listener: handleNoTypeVariables(.)
+ parseGetterOrFormalParameters(e, e, false, MemberKind.TopLevelMethod)
+ missingParameterMessage(MemberKind.TopLevelMethod)
+ reportRecoverableError(e, MissingFunctionParameters)
+ listener: handleRecoverableError(MissingFunctionParameters, e, e)
+ rewriter()
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+ reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
+ listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+ insertBlock())
+ rewriter()
+ rewriter()
+ listener: handleInvalidFunctionBody({)
+ listener: endTopLevelMethod(l, null, })
+ listener: endTopLevelDeclaration(.)
+ parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+ parseMetadataStar(})
+ listener: beginMetadataStar(.)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(.)
+ parseInvalidTopLevelDeclaration(})
+ reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+ listener: handleInvalidTopLevelDeclaration(.)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
+ parseMetadataStar(.)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(.)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(/)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(/)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(/)
+ parseInvalidTopLevelDeclaration(/)
+ reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+ listener: handleInvalidTopLevelDeclaration(/)
+ listener: endTopLevelDeclaration(T)
+ parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
+ parseMetadataStar(/)
+ listener: beginMetadataStar(T)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(/)
+ listener: beginTopLevelMember(T)
+ parseFields(/, null, null, null, null, null, /, Instance of 'SimpleType', h, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(T, typeReference)
+ listener: handleNoTypeArguments(h)
+ listener: handleType(T, null)
+ ensureIdentifier(T, topLevelVariableDeclaration)
+ listener: handleIdentifier(h, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(h, h, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(h)
+ reportRecoverableError(h, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], h, h)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, T, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', s, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(s)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelVariableDeclaration)
+ listener: handleIdentifier(s, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(s, s, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(f)
+ ensureSemicolon(s)
+ reportRecoverableError(s, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], s, s)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, i, ;)
+ listener: endTopLevelDeclaration(f)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(f)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(f)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', i, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(f, typeReference)
+ listener: handleNoTypeArguments(i)
+ listener: handleType(f, null)
+ ensureIdentifier(f, topLevelVariableDeclaration)
+ listener: handleIdentifier(i, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(i, i, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(l)
+ ensureSemicolon(i)
+ reportRecoverableError(i, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], i, i)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, f, ;)
+ listener: endTopLevelDeclaration(l)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(l)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(l)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(l, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(l, null)
+ ensureIdentifier(l, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, l, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', s, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(s)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelVariableDeclaration)
+ listener: handleIdentifier(s, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(s, s, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(s)
+ reportRecoverableError(s, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], s, s)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, i, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', a, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(a)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(a, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(a, a, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(v)
+ ensureSemicolon(a)
+ reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(v)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(v)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(v)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', e, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(v, typeReference)
+ listener: handleNoTypeArguments(e)
+ listener: handleType(v, null)
+ ensureIdentifier(v, topLevelVariableDeclaration)
+ listener: handleIdentifier(e, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(e, e, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(d)
+ ensureSemicolon(e)
+ reportRecoverableError(e, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], e, e)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, v, ;)
+ listener: endTopLevelDeclaration(d)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(d)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(d)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', a, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(d, typeReference)
+ listener: handleNoTypeArguments(a)
+ listener: handleType(d, null)
+ ensureIdentifier(d, topLevelVariableDeclaration)
+ listener: handleIdentifier(a, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(a, a, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(s)
+ ensureSemicolon(a)
+ reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, d, ;)
+ listener: endTopLevelDeclaration(s)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(s)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(s)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', U, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(s, typeReference)
+ listener: handleNoTypeArguments(U)
+ listener: handleType(s, null)
+ ensureIdentifier(s, topLevelVariableDeclaration)
+ listener: handleIdentifier(U, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(U, U, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(T)
+ ensureSemicolon(U)
+ reportRecoverableError(U, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], U, U)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, s, ;)
+ listener: endTopLevelDeclaration(T)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(T)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(T)
+ parseFields(;, null, null, null, null, null, ;, Instance of 'SimpleType', F, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(T, typeReference)
+ listener: handleNoTypeArguments(F)
+ listener: handleType(T, null)
+ ensureIdentifier(T, topLevelVariableDeclaration)
+ listener: handleIdentifier(F, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(F, F, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(-)
+ ensureSemicolon(F)
+ reportRecoverableError(F, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], F, F)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, T, ;)
+ listener: endTopLevelDeclaration(-)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(-)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(-)
+ parseInvalidTopLevelDeclaration(;)
+ reportRecoverableErrorWithToken(-, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '-'., null, {token: -}], -, -)
+ listener: handleInvalidTopLevelDeclaration(-)
+ listener: endTopLevelDeclaration(1)
+ parseTopLevelDeclarationImpl(-, Instance of 'DirectiveContext')
+ parseMetadataStar(-)
+ listener: beginMetadataStar(1)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(1)
+ parseInvalidTopLevelDeclaration(-)
+ reportRecoverableErrorWithToken(1, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '1'., null, {token: 1}], 1, 1)
+ listener: handleInvalidTopLevelDeclaration(1)
+ listener: endTopLevelDeclaration(6)
+ parseTopLevelDeclarationImpl(1, Instance of 'DirectiveContext')
+ parseMetadataStar(1)
+ listener: beginMetadataStar(6)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(6)
+ parseInvalidTopLevelDeclaration(1)
+ reportRecoverableErrorWithToken(6, Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '6'., null, {token: 6}], 6, 6)
+ listener: handleInvalidTopLevelDeclaration(6)
+ listener: endTopLevelDeclaration(L)
+ parseTopLevelDeclarationImpl(6, Instance of 'DirectiveContext')
+ parseMetadataStar(6)
+ listener: beginMetadataStar(L)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(6)
+ listener: beginTopLevelMember(L)
+ parseTopLevelMethod(6, null, 6, Instance of 'SimpleType', null, E)
+ listener: beginTopLevelMethod(6, null)
+ listener: handleIdentifier(L, typeReference)
+ listener: handleNoTypeArguments(E)
+ listener: handleType(L, null)
+ ensureIdentifier(L, topLevelFunctionDeclaration)
+ listener: handleIdentifier(E, topLevelFunctionDeclaration)
+ parseMethodTypeVar(E)
+ listener: handleNoTypeVariables(.)
+ parseGetterOrFormalParameters(E, E, false, MemberKind.TopLevelMethod)
+ missingParameterMessage(MemberKind.TopLevelMethod)
+ reportRecoverableError(E, MissingFunctionParameters)
+ listener: handleRecoverableError(MissingFunctionParameters, E, E)
+ rewriter()
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+ reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
+ listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+ insertBlock())
+ rewriter()
+ rewriter()
+ listener: handleInvalidFunctionBody({)
+ listener: endTopLevelMethod(L, null, })
+ listener: endTopLevelDeclaration(.)
+ parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+ parseMetadataStar(})
+ listener: beginMetadataStar(.)
+ listener: endMetadataStar(0)
+ listener: beginTopLevelMember(.)
+ parseInvalidTopLevelDeclaration(})
+ reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
+ listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+ listener: handleInvalidTopLevelDeclaration(.)
+ listener: endTopLevelDeclaration(m)
+ parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
+ parseMetadataStar(.)
+ listener: beginMetadataStar(m)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(.)
+ listener: beginTopLevelMember(m)
+ parseFields(., null, null, null, null, null, ., Instance of 'SimpleType', a, DeclarationKind.TopLevel, null)
+ listener: handleIdentifier(m, typeReference)
+ listener: handleNoTypeArguments(a)
+ listener: handleType(m, null)
+ ensureIdentifier(m, topLevelVariableDeclaration)
+ listener: handleIdentifier(a, topLevelVariableDeclaration)
+ parseFieldInitializerOpt(a, a, null, null, DeclarationKind.TopLevel, null)
+ listener: handleNoFieldInitializer(i)
+ ensureSemicolon(a)
+ reportRecoverableError(a, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], a, a)
+ rewriter()
+ listener: endTopLevelFields(null, null, null, null, 1, m, ;)
+ listener: endTopLevelDeclaration(i)
+ parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+ parseMetadataStar(;)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(;)
+ listener: beginTopLevelMember(i)
+ parseTopLevelMethod(;, null, ;, Instance of 'SimpleType', null, n)
+ listener: beginTopLevelMethod(;, null)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(n)
+ listener: handleType(i, null)
+ ensureIdentifier(i, topLevelFunctionDeclaration)
+ listener: handleIdentifier(n, topLevelFunctionDeclaration)
+ parseMethodTypeVar(n)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters(n, n, false, MemberKind.TopLevelMethod)
+ parseFormalParameters(n, MemberKind.TopLevelMethod)
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, p)
+ parseStatement({)
+ parseStatementX({)
+ parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+ looksLikeLocalFunction(r)
+ listener: beginMetadataStar(p)
+ listener: endMetadataStar(0)
+ listener: handleIdentifier(p, typeReference)
+ listener: handleNoTypeArguments(r)
+ listener: handleType(p, null)
+ listener: beginVariablesDeclaration(r, null, null)
+ parseVariablesDeclarationRest(p, true)
+ parseOptionallyInitializedIdentifier(p)
+ ensureIdentifier(p, localVariableDeclaration)
+ listener: handleIdentifier(r, localVariableDeclaration)
+ listener: beginInitializedIdentifier(r)
+ parseVariableInitializerOpt(r)
+ listener: handleNoVariableInitializer(i)
+ listener: endInitializedIdentifier(r)
+ ensureSemicolon(r)
+ reportRecoverableError(r, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], r, r)
+ rewriter()
+ listener: endVariablesDeclaration(1, ;)
+ notEofOrValue(}, i)
+ parseStatement(;)
+ parseStatementX(;)
+ parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+ looksLikeLocalFunction(n)
+ listener: beginMetadataStar(i)
+ listener: endMetadataStar(0)
+ listener: handleIdentifier(i, typeReference)
+ listener: handleNoTypeArguments(n)
+ listener: handleType(i, null)
+ listener: beginVariablesDeclaration(n, null, null)
+ parseVariablesDeclarationRest(i, true)
+ parseOptionallyInitializedIdentifier(i)
+ ensureIdentifier(i, localVariableDeclaration)
+ listener: handleIdentifier(n, localVariableDeclaration)
+ listener: beginInitializedIdentifier(n)
+ parseVariableInitializerOpt(n)
+ listener: handleNoVariableInitializer(t)
+ listener: endInitializedIdentifier(n)
+ ensureSemicolon(n)
+ reportRecoverableError(n, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], n, n)
+ rewriter()
+ listener: endVariablesDeclaration(1, ;)
+ notEofOrValue(}, t)
+ parseStatement(;)
+ parseStatementX(;)
+ parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+ looksLikeLocalFunction(t)
+ parseExpressionStatement(;)
+ parseExpression(;)
+ parsePrecedenceExpression(;, 1, true)
+ parseUnaryExpression(;, true)
+ parsePrimary(;, expression)
+ parseSendOrFunctionLiteral(;, expression)
+ looksLikeFunctionBody(;)
+ parseSend(;, expression)
+ ensureIdentifier(;, expression)
+ listener: handleIdentifier(t, expression)
+ listener: handleNoTypeArguments(()
+ parseArgumentsOpt(t)
+ parseArguments(t)
+ parseArgumentsRest(()
+ listener: beginArguments(()
+ parseExpression(()
+ parsePrecedenceExpression((, 1, true)
+ parseUnaryExpression((, true)
+ parsePrimary((, expression)
+ parseLiteralString(()
+ parseSingleLiteralString(()
+ listener: beginLiteralString("")
+ listener: endLiteralString(0, H)
+ rewriteAndRecover("", Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(H, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], H, H)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(H, expression)
+ listener: handleNoTypeArguments(e)
+ parseArgumentsOpt(H)
+ listener: handleNoArguments(e)
+ listener: handleSend(H, e)
+ rewriteAndRecover(H, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(e, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], e, e)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(e, expression)
+ listener: handleNoTypeArguments(l)
+ parseArgumentsOpt(e)
+ listener: handleNoArguments(l)
+ listener: handleSend(e, l)
+ rewriteAndRecover(e, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(l, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], l, l)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(l, expression)
+ listener: handleNoTypeArguments(l)
+ parseArgumentsOpt(l)
+ listener: handleNoArguments(l)
+ listener: handleSend(l, l)
+ rewriteAndRecover(l, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(l, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], l, l)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(l, expression)
+ listener: handleNoTypeArguments(o)
+ parseArgumentsOpt(l)
+ listener: handleNoArguments(o)
+ listener: handleSend(l, o)
+ rewriteAndRecover(l, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(o, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], o, o)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(o, expression)
+ listener: handleNoTypeArguments(,)
+ parseArgumentsOpt(o)
+ listener: handleNoArguments(,)
+ listener: handleSend(o, ,)
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(w, expression)
+ listener: handleNoTypeArguments(o)
+ parseArgumentsOpt(w)
+ listener: handleNoArguments(o)
+ listener: handleSend(w, o)
+ rewriteAndRecover(w, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(o, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], o, o)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(o, expression)
+ listener: handleNoTypeArguments(r)
+ parseArgumentsOpt(o)
+ listener: handleNoArguments(r)
+ listener: handleSend(o, r)
+ rewriteAndRecover(o, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(r, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], r, r)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(r, expression)
+ listener: handleNoTypeArguments(l)
+ parseArgumentsOpt(r)
+ listener: handleNoArguments(l)
+ listener: handleSend(r, l)
+ rewriteAndRecover(r, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(l, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], l, l)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(l, expression)
+ listener: handleNoTypeArguments(d)
+ parseArgumentsOpt(l)
+ listener: handleNoArguments(d)
+ listener: handleSend(l, d)
+ rewriteAndRecover(l, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError(d, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], d, d)
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseSendOrFunctionLiteral(,, expression)
+ parseSend(,, expression)
+ ensureIdentifier(,, expression)
+ listener: handleIdentifier(d, expression)
+ listener: handleNoTypeArguments(!)
+ parseArgumentsOpt(d)
+ listener: handleNoArguments(!)
+ listener: handleSend(d, !)
+ listener: handleNonNullAssertExpression(!)
+ rewriteAndRecover(!, Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], ,)
+ reportRecoverableError("", Message[ExpectedButGot, Expected ',' before this., null, {string: ,}])
+ listener: handleRecoverableError(Message[ExpectedButGot, Expected ',' before this., null, {string: ,}], "", "")
+ rewriter()
+ parseExpression(,)
+ parsePrecedenceExpression(,, 1, true)
+ parseUnaryExpression(,, true)
+ parsePrimary(,, expression)
+ parseLiteralString(,)
+ parseSingleLiteralString(,)
+ listener: beginLiteralString("")
+ listener: endLiteralString(0, ))
+ listener: endArguments(12, (, ))
+ listener: handleSend(t, ;)
+ ensureSemicolon())
+ listener: handleExpressionStatement(;)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(3, {, })
+ listener: endTopLevelMethod(i, null, })
+ listener: endTopLevelDeclaration()
+ reportAllErrorTokens(EncodingErrorToken())
+ listener: handleErrorToken(EncodingErrorToken())
+ listener: handleErrorToken(EncodingErrorToken())
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(UnterminatedString("))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(UnterminatedString("))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: handleErrorToken(AsciiControlCharacterToken(0))
+ listener: endCompilationUnit(114, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.parser.expect
new file mode 100644
index 0000000..188f401c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.parser.expect
@@ -0,0 +1,31 @@
+NOTICE: Stream was rewritten by parser!
+
+/ / C o ;p y ;r i ;g h ;t ( c ) {}2 0 2 0 , t h ;e D ;a r ;t p ;r o ;j e ;c t ;a u ;t h ;o r ;s . P l ;e a ;s e ;s e ;e t ;h e ;A U ;T H ;O R ;S f ;i l ;e
+;/ / f o ;r d ;e t ;a i ;l s (){}. A l ;l r ;i g ;h t ;s r ;e s ;e r ;v e ;d . U s ;e o ;f t ;h i ;s s ;o u ;r c ;e c ;o d ;e i ;s g ;o v ;e r ;n e ;d b ;y a
+;/ / B S ;D ;- s t ;y l ;e l ;i c ;e n ;s e ;t h ;a t ;c a ;n b ;e f ;o u ;n d ;i n ;t h ;e L ;I C ;E N ;S E (){}. m d ;f i ;l e (){}.
+
+/ / T h ;i s ;f i ;l e ;i s ;s a ;v e ;d a ;s U ;T F ;- 1 6 L E (){}.
+
+m a ;i n ( ) {
+p r ;i n ;t ( "" ,H ,e ,l ,l ,o , w ,o ,r ,l ,d ! ,"" ) ;
+}
+
+
+[EncodingErrorToken][EncodingErrorToken][AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [UnterminatedString][AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [UnterminatedString][AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]/[SimpleToken] /[SimpleToken] C[StringToken] o[StringToken] ;[SyntheticToken]p[StringToken] y[StringToken] ;[SyntheticToken]r[StringToken] i[StringToken] ;[SyntheticToken]g[StringToken] h[StringToken] ;[SyntheticToken]t[StringToken] ([BeginToken] c[StringToken] )[SimpleToken] {[SyntheticBeginToken]}[SyntheticToken]2[StringToken] 0[StringToken] 2[StringToken] 0[StringToken] ,[SimpleToken] t[StringToken] h[StringToken] ;[SyntheticToken]e[StringToken] D[StringToken] ;[SyntheticToken]a[StringToken] r[StringToken] ;[SyntheticToken]t[StringToken] p[StringToken] ;[SyntheticToken]r[StringToken] o[StringToken] ;[SyntheticToken]j[StringToken] e[StringToken] ;[SyntheticToken]c[StringToken] t[StringToken] ;[SyntheticToken]a[StringToken] u[StringToken] ;[SyntheticToken]t[StringToken] h[StringToken] ;[SyntheticToken]o[StringToken] r[StringToken] ;[SyntheticToken]s[StringToken] .[SimpleToken] P[StringToken] l[StringToken] ;[SyntheticToken]e[StringToken] a[StringToken] ;[SyntheticToken]s[StringToken] e[StringToken] ;[SyntheticToken]s[StringToken] e[StringToken] ;[SyntheticToken]e[StringToken] t[StringToken] ;[SyntheticToken]h[StringToken] e[StringToken] ;[SyntheticToken]A[StringToken] U[StringToken] ;[SyntheticToken]T[StringToken] H[StringToken] ;[SyntheticToken]O[StringToken] R[StringToken] ;[SyntheticToken]S[StringToken] f[StringToken] ;[SyntheticToken]i[StringToken] l[StringToken] ;[SyntheticToken]e[StringToken]
+;[SyntheticToken]/[SimpleToken] /[SimpleToken] f[StringToken] o[StringToken] ;[SyntheticToken]r[StringToken] d[StringToken] ;[SyntheticToken]e[StringToken] t[StringToken] ;[SyntheticToken]a[StringToken] i[StringToken] ;[SyntheticToken]l[StringToken] s[StringToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken].[SimpleToken] A[StringToken] l[StringToken] ;[SyntheticToken]l[StringToken] r[StringToken] ;[SyntheticToken]i[StringToken] g[StringToken] ;[SyntheticToken]h[StringToken] t[StringToken] ;[SyntheticToken]s[StringToken] r[StringToken] ;[SyntheticToken]e[StringToken] s[StringToken] ;[SyntheticToken]e[StringToken] r[StringToken] ;[SyntheticToken]v[StringToken] e[StringToken] ;[SyntheticToken]d[StringToken] .[SimpleToken] U[StringToken] s[StringToken] ;[SyntheticToken]e[StringToken] o[StringToken] ;[SyntheticToken]f[StringToken] t[StringToken] ;[SyntheticToken]h[StringToken] i[StringToken] ;[SyntheticToken]s[StringToken] s[StringToken] ;[SyntheticToken]o[StringToken] u[StringToken] ;[SyntheticToken]r[StringToken] c[StringToken] ;[SyntheticToken]e[StringToken] c[StringToken] ;[SyntheticToken]o[StringToken] d[StringToken] ;[SyntheticToken]e[StringToken] i[StringToken] ;[SyntheticToken]s[StringToken] g[StringToken] ;[SyntheticToken]o[StringToken] v[StringToken] ;[SyntheticToken]e[StringToken] r[StringToken] ;[SyntheticToken]n[StringToken] e[StringToken] ;[SyntheticToken]d[StringToken] b[StringToken] ;[SyntheticToken]y[StringToken] a[StringToken]
+;[SyntheticToken]/[SimpleToken] /[SimpleToken] B[StringToken] S[StringToken] ;[SyntheticToken]D[StringToken] ;[SyntheticToken]-[SimpleToken] s[StringToken] t[StringToken] ;[SyntheticToken]y[StringToken] l[StringToken] ;[SyntheticToken]e[StringToken] l[StringToken] ;[SyntheticToken]i[StringToken] c[StringToken] ;[SyntheticToken]e[StringToken] n[StringToken] ;[SyntheticToken]s[StringToken] e[StringToken] ;[SyntheticToken]t[StringToken] h[StringToken] ;[SyntheticToken]a[StringToken] t[StringToken] ;[SyntheticToken]c[StringToken] a[StringToken] ;[SyntheticToken]n[StringToken] b[StringToken] ;[SyntheticToken]e[StringToken] f[StringToken] ;[SyntheticToken]o[StringToken] u[StringToken] ;[SyntheticToken]n[StringToken] d[StringToken] ;[SyntheticToken]i[StringToken] n[StringToken] ;[SyntheticToken]t[StringToken] h[StringToken] ;[SyntheticToken]e[StringToken] L[StringToken] ;[SyntheticToken]I[StringToken] C[StringToken] ;[SyntheticToken]E[StringToken] N[StringToken] ;[SyntheticToken]S[StringToken] E[StringToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken].[SimpleToken] m[StringToken] d[StringToken] ;[SyntheticToken]f[StringToken] i[StringToken] ;[SyntheticToken]l[StringToken] e[StringToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken].[SimpleToken]
+
+/[SimpleToken] /[SimpleToken] T[StringToken] h[StringToken] ;[SyntheticToken]i[StringToken] s[StringToken] ;[SyntheticToken]f[StringToken] i[StringToken] ;[SyntheticToken]l[StringToken] e[StringToken] ;[SyntheticToken]i[StringToken] s[StringToken] ;[SyntheticToken]s[StringToken] a[StringToken] ;[SyntheticToken]v[StringToken] e[StringToken] ;[SyntheticToken]d[StringToken] a[StringToken] ;[SyntheticToken]s[StringToken] U[StringToken] ;[SyntheticToken]T[StringToken] F[StringToken] ;[SyntheticToken]-[SimpleToken] 1[StringToken] 6[StringToken] L[StringToken] E[StringToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken].[SimpleToken]
+
+m[StringToken] a[StringToken] ;[SyntheticToken]i[StringToken] n[StringToken] ([BeginToken] )[SimpleToken] {[BeginToken]
+p[StringToken] r[StringToken] ;[SyntheticToken]i[StringToken] n[StringToken] ;[SyntheticToken]t[StringToken] ([BeginToken] ""[SyntheticStringToken] ,[SyntheticToken]H[StringToken] ,[SyntheticToken]e[StringToken] ,[SyntheticToken]l[StringToken] ,[SyntheticToken]l[StringToken] ,[SyntheticToken]o[StringToken] ,[SimpleToken] w[StringToken] ,[SyntheticToken]o[StringToken] ,[SyntheticToken]r[StringToken] ,[SyntheticToken]l[StringToken] ,[SyntheticToken]d[StringToken] ![SimpleToken] ,[SyntheticToken]""[SyntheticStringToken] )[SimpleToken] ;[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.scanner.expect
new file mode 100644
index 0000000..669e1c9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.scanner.expect
@@ -0,0 +1,29 @@
+/ / C o p y r i g h t ( c ) 2 0 2 0 , t h e D a r t p r o j e c t a u t h o r s . P l e a s e s e e t h e A U T H O R S f i l e
+/ / f o r d e t a i l s . A l l r i g h t s r e s e r v e d . U s e o f t h i s s o u r c e c o d e i s g o v e r n e d b y a
+/ / B S D - s t y l e l i c e n s e t h a t c a n b e f o u n d i n t h e L I C E N S E . m d f i l e .
+
+/ / T h i s f i l e i s s a v e d a s U T F - 1 6 L E .
+
+m a i n ( ) {
+p r i n t ( "" H e l l o , w o r l d ! "" ) ;
+}
+
+
+[EncodingErrorToken][EncodingErrorToken][AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [UnterminatedString][AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [UnterminatedString][AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]
+[AsciiControlCharacterToken] [AsciiControlCharacterToken] [AsciiControlCharacterToken]/[SimpleToken] /[SimpleToken] C[StringToken] o[StringToken] p[StringToken] y[StringToken] r[StringToken] i[StringToken] g[StringToken] h[StringToken] t[StringToken] ([BeginToken] c[StringToken] )[SimpleToken] 2[StringToken] 0[StringToken] 2[StringToken] 0[StringToken] ,[SimpleToken] t[StringToken] h[StringToken] e[StringToken] D[StringToken] a[StringToken] r[StringToken] t[StringToken] p[StringToken] r[StringToken] o[StringToken] j[StringToken] e[StringToken] c[StringToken] t[StringToken] a[StringToken] u[StringToken] t[StringToken] h[StringToken] o[StringToken] r[StringToken] s[StringToken] .[SimpleToken] P[StringToken] l[StringToken] e[StringToken] a[StringToken] s[StringToken] e[StringToken] s[StringToken] e[StringToken] e[StringToken] t[StringToken] h[StringToken] e[StringToken] A[StringToken] U[StringToken] T[StringToken] H[StringToken] O[StringToken] R[StringToken] S[StringToken] f[StringToken] i[StringToken] l[StringToken] e[StringToken]
+/[SimpleToken] /[SimpleToken] f[StringToken] o[StringToken] r[StringToken] d[StringToken] e[StringToken] t[StringToken] a[StringToken] i[StringToken] l[StringToken] s[StringToken] .[SimpleToken] A[StringToken] l[StringToken] l[StringToken] r[StringToken] i[StringToken] g[StringToken] h[StringToken] t[StringToken] s[StringToken] r[StringToken] e[StringToken] s[StringToken] e[StringToken] r[StringToken] v[StringToken] e[StringToken] d[StringToken] .[SimpleToken] U[StringToken] s[StringToken] e[StringToken] o[StringToken] f[StringToken] t[StringToken] h[StringToken] i[StringToken] s[StringToken] s[StringToken] o[StringToken] u[StringToken] r[StringToken] c[StringToken] e[StringToken] c[StringToken] o[StringToken] d[StringToken] e[StringToken] i[StringToken] s[StringToken] g[StringToken] o[StringToken] v[StringToken] e[StringToken] r[StringToken] n[StringToken] e[StringToken] d[StringToken] b[StringToken] y[StringToken] a[StringToken]
+/[SimpleToken] /[SimpleToken] B[StringToken] S[StringToken] D[StringToken] -[SimpleToken] s[StringToken] t[StringToken] y[StringToken] l[StringToken] e[StringToken] l[StringToken] i[StringToken] c[StringToken] e[StringToken] n[StringToken] s[StringToken] e[StringToken] t[StringToken] h[StringToken] a[StringToken] t[StringToken] c[StringToken] a[StringToken] n[StringToken] b[StringToken] e[StringToken] f[StringToken] o[StringToken] u[StringToken] n[StringToken] d[StringToken] i[StringToken] n[StringToken] t[StringToken] h[StringToken] e[StringToken] L[StringToken] I[StringToken] C[StringToken] E[StringToken] N[StringToken] S[StringToken] E[StringToken] .[SimpleToken] m[StringToken] d[StringToken] f[StringToken] i[StringToken] l[StringToken] e[StringToken] .[SimpleToken]
+
+/[SimpleToken] /[SimpleToken] T[StringToken] h[StringToken] i[StringToken] s[StringToken] f[StringToken] i[StringToken] l[StringToken] e[StringToken] i[StringToken] s[StringToken] s[StringToken] a[StringToken] v[StringToken] e[StringToken] d[StringToken] a[StringToken] s[StringToken] U[StringToken] T[StringToken] F[StringToken] -[SimpleToken] 1[StringToken] 6[StringToken] L[StringToken] E[StringToken] .[SimpleToken]
+
+m[StringToken] a[StringToken] i[StringToken] n[StringToken] ([BeginToken] )[SimpleToken] {[BeginToken]
+p[StringToken] r[StringToken] i[StringToken] n[StringToken] t[StringToken] ([BeginToken] ""[SyntheticStringToken] H[StringToken] e[StringToken] l[StringToken] l[StringToken] o[StringToken] ,[SimpleToken] w[StringToken] o[StringToken] r[StringToken] l[StringToken] d[StringToken] ![SimpleToken] ""[SyntheticStringToken] )[SimpleToken] ;[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/test/fasta/bootstrap_test.dart b/pkg/front_end/test/fasta/bootstrap_test.dart
index f4755f4..39effb5 100644
--- a/pkg/front_end/test/fasta/bootstrap_test.dart
+++ b/pkg/front_end/test/fasta/bootstrap_test.dart
@@ -8,6 +8,8 @@
import 'package:async_helper/async_helper.dart' show asyncEnd, asyncStart;
+import 'package:front_end/src/base/command_line_options.dart';
+
import 'package:testing/testing.dart' show StdioProcess;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
@@ -50,9 +52,9 @@
dartVm.toFilePath(),
<String>[
compiler.toFilePath(),
- "--compile-sdk=sdk/",
- "--output=${output.toFilePath()}",
- "--verify",
+ "${Flags.compileSdk}=sdk/",
+ "${Flags.output}=${output.toFilePath()}",
+ Flags.verify,
input.toFilePath(),
],
suppressOutput: false);
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index de177ef..65b8127 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -183,7 +183,7 @@
final Set<Uri> content;
final bool nnbdAgnosticMode;
Component component;
- String errors;
+ List<Iterable<String>> errors;
LinkDependenciesOptions(this.content, {this.nnbdAgnosticMode})
: assert(content != null),
@@ -201,8 +201,8 @@
final bool weak;
final Map<Component, KernelTarget> componentToTarget =
<Component, KernelTarget>{};
- final Map<Component, StringBuffer> componentToDiagnostics =
- <Component, StringBuffer>{};
+ final Map<Component, List<Iterable<String>>> componentToDiagnostics =
+ <Component, List<Iterable<String>>>{};
final Uri platformBinaries;
final Map<Uri, UriTranslator> _uriTranslators = {};
final Map<Uri, TestOptions> _testOptions = {};
@@ -251,11 +251,13 @@
if (!ignoreExpectations) {
steps.add(new MatchExpectation(
fullCompile ? "$fullPrefix.expect" : "$outlinePrefix.expect",
- serializeFirst: false));
+ serializeFirst: false,
+ isLastMatchStep: updateExpectations));
if (!updateExpectations) {
steps.add(new MatchExpectation(
fullCompile ? "$fullPrefix.expect" : "$outlinePrefix.expect",
- serializeFirst: true));
+ serializeFirst: true,
+ isLastMatchStep: true));
}
}
steps.add(const TypeCheck());
@@ -270,13 +272,15 @@
fullCompile
? "$fullPrefix.transformed.expect"
: "$outlinePrefix.transformed.expect",
- serializeFirst: false));
+ serializeFirst: false,
+ isLastMatchStep: updateExpectations));
if (!updateExpectations) {
steps.add(new MatchExpectation(
fullCompile
? "$fullPrefix.transformed.expect"
: "$outlinePrefix.transformed.expect",
- serializeFirst: true));
+ serializeFirst: true,
+ isLastMatchStep: true));
}
}
steps.add(const EnsureNoErrors());
@@ -589,7 +593,7 @@
Future<Result<ComponentResult>> run(
TestDescription description, FastaContext context) async {
- StringBuffer errors = new StringBuffer();
+ List<Iterable<String>> errors = <Iterable<String>>[];
Uri librariesSpecificationUri =
context.computeLibrariesSpecificationUri(description);
@@ -606,10 +610,7 @@
ProcessedOptions createProcessedOptions(NnbdMode nnbdMode) {
CompilerOptions compilerOptions = new CompilerOptions()
..onDiagnostic = (DiagnosticMessage message) {
- if (errors.isNotEmpty) {
- errors.write("\n\n");
- }
- errors.writeAll(message.plainTextFormatted, "\n");
+ errors.add(message.plainTextFormatted);
}
..environmentDefines = {}
..experimentalFlags = experimentalFlags
@@ -639,7 +640,7 @@
KernelTarget sourceTarget = await outlineInitialization(context,
description, testOptions, linkDependenciesOptions.content.toList());
if (linkDependenciesOptions.errors != null) {
- errors.write(linkDependenciesOptions.errors);
+ errors.addAll(linkDependenciesOptions.errors);
}
Component p = await sourceTarget.buildOutlines();
if (fullCompile) {
@@ -654,7 +655,7 @@
}
p.libraries.clear();
p.libraries.addAll(keepLibraries);
- linkDependenciesOptions.errors = errors.toString();
+ linkDependenciesOptions.errors = errors.toList();
errors.clear();
});
}
@@ -844,10 +845,14 @@
Future<Result<ComponentResult>> run(
ComponentResult result, FastaContext context) async {
- StringBuffer buffer = context.componentToDiagnostics[result.component];
- return buffer.isEmpty
+ List<Iterable<String>> errors =
+ context.componentToDiagnostics[result.component];
+ return errors.isEmpty
? pass(result)
- : fail(result, """Unexpected errors:\n$buffer""");
+ : fail(
+ result,
+ "Unexpected errors:\n"
+ "${errors.map((error) => error.join('\n')).join('\n\n')}");
}
}
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index fca5c65..08631e7 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -20,7 +20,7 @@
onFailure,
runTestFor;
-import 'package:kernel/ast.dart' show Component, Library;
+import 'package:kernel/ast.dart' show Component, Library, Version;
main(List<String> args) async {
// Fix default/max major and minor version so we can test it.
@@ -76,19 +76,16 @@
Future<void> inspectComponent(Component component) async {
for (Library library in component.libraries) {
if (library.importUri.scheme == "dart") continue;
- lv.LanguageVersionForUri lvFile =
+ Version lvFile =
await lv.languageVersionForUri(library.fileUri, stashedOptions);
- lv.LanguageVersionForUri lvImportUri =
+ Version lvImportUri =
await lv.languageVersionForUri(library.importUri, stashedOptions);
- if ((lvFile.major != lvImportUri.major ||
- lvFile.major != library.languageVersionMajor) ||
- (lvFile.minor != lvImportUri.minor ||
- lvFile.minor != library.languageVersionMinor)) {
+ if ((lvFile != lvImportUri || lvFile != library.languageVersion)) {
throw """
Language version disagreement:
-Library: ${library.languageVersionMajor}.${library.languageVersionMinor}
-Language version API (file URI): ${lvFile.major}.${lvFile.minor}
-Language version API (import URI): ${lvImportUri.major}.${lvImportUri.minor}
+Library: ${library.languageVersion}
+Language version API (file URI): ${lvFile}
+Language version API (import URI): ${lvImportUri}
""";
}
}
@@ -123,9 +120,8 @@
@override
String computeLibraryValue(Id id, Library library) {
- return "languageVersion="
- "${library.languageVersionMajor}"
+ return "languageVersion=${library.languageVersion.major}"
"."
- "${library.languageVersionMinor}";
+ "${library.languageVersion.minor}";
}
}
diff --git a/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart b/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart
index 171e212..3e20772 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart
@@ -6,8 +6,7 @@
import 'package:front_end/src/api_prototype/compiler_options.dart';
-import 'package:kernel/default_language_version.dart' as kernel
- show defaultLanguageVersionMajor, defaultLanguageVersionMinor;
+import 'package:kernel/ast.dart' as kernel show Version, defaultLanguageVersion;
import '../utils/io_utils.dart';
@@ -36,14 +35,12 @@
List<String> dotSeparatedParts = versionString.split(".");
int major = int.tryParse(dotSeparatedParts[0]);
int minor = int.tryParse(dotSeparatedParts[1]);
+ kernel.Version version = new kernel.Version(major, minor);
- if (kernel.defaultLanguageVersionMajor != major ||
- kernel.defaultLanguageVersionMinor != minor) {
+ if (kernel.defaultLanguageVersion != version) {
throw "Kernel defaults "
- "${kernel.defaultLanguageVersionMajor}"
- "."
- "${kernel.defaultLanguageVersionMinor}"
- " does not match output from make_version.py ($major.$minor)";
+ "${kernel.defaultLanguageVersion}"
+ " does not match output from make_version.py ($version)";
} else {
print("Kernel version matches.");
}
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index db3e01e..c0e36d4 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -6,6 +6,7 @@
src/api_prototype/constant_evaluator/Exports: Fail
src/api_prototype/front_end/Exports: Fail
src/api_prototype/incremental_kernel_generator/Exports: Fail
+src/api_prototype/language_version/Exports: Fail
src/api_unstable/bazel_worker/ImportsTwice: Fail
src/fasta/fasta_codes/Exports: Fail
src/fasta/incremental_compiler/ImportsTwice: Fail
diff --git a/pkg/front_end/test/old_dill_suite.dart b/pkg/front_end/test/old_dill_suite.dart
index 7e70850..c48c30b 100644
--- a/pkg/front_end/test/old_dill_suite.dart
+++ b/pkg/front_end/test/old_dill_suite.dart
@@ -8,6 +8,8 @@
import 'package:kernel/binary/tag.dart' show Tag;
+import 'package:front_end/src/base/command_line_options.dart';
+
import 'package:testing/testing.dart'
show ChainContext, Result, Step, TestDescription, Chain, runMe;
@@ -73,11 +75,11 @@
[
fastaCompile.toFilePath(),
"sdkroot:/pkg/compiler/bin/dart2js.dart",
- "-o",
+ "${Flags.output}",
output.toFilePath(),
- "--target=vm",
- "--single-root-base=${Uri.base.toFilePath()}",
- "--single-root-scheme=sdkroot",
+ "${Flags.target}=vm",
+ "${Flags.singleRootBase}=${Uri.base.toFilePath()}",
+ "${Flags.singleRootScheme}=sdkroot",
],
workingDirectory: Uri.base.toFilePath());
if (result.exitCode != 0) {
diff --git a/pkg/front_end/test/parser_suite.dart b/pkg/front_end/test/parser_suite.dart
index ce28c25..4824e2e 100644
--- a/pkg/front_end/test/parser_suite.dart
+++ b/pkg/front_end/test/parser_suite.dart
@@ -242,40 +242,59 @@
{bool addTypes: false}) {
StringBuffer sb = new StringBuffer();
Token token = firstToken;
- bool printed = false;
- int endOfLast = -1;
- int lineStartsIteratorLine = 1;
- Iterator<int> lineStartsIterator = lineStarts.iterator;
- lineStartsIterator.moveNext();
- lineStartsIterator.moveNext();
- lineStartsIteratorLine++;
- while (token != null) {
- int prevLine = lineStartsIteratorLine;
- while (token.offset >= lineStartsIterator.current &&
- lineStartsIterator.moveNext()) {
- lineStartsIteratorLine++;
- }
- if (printed &&
- (token.offset > endOfLast || prevLine < lineStartsIteratorLine)) {
- if (prevLine < lineStartsIteratorLine) {
- for (int i = prevLine; i < lineStartsIteratorLine; i++) {
- sb.write("\n");
- }
- } else {
- sb.write(" ");
+
+ Token process(Token token, bool errorTokens) {
+ bool printed = false;
+ int endOfLast = -1;
+ int lineStartsIteratorLine = 1;
+ Iterator<int> lineStartsIterator = lineStarts.iterator;
+ lineStartsIterator.moveNext();
+ lineStartsIterator.moveNext();
+ lineStartsIteratorLine++;
+
+ while (token != null) {
+ if (errorTokens && token is! ErrorToken) return token;
+ if (!errorTokens && token is ErrorToken) {
+ if (token == token.next) break;
+ token = token.next;
+ continue;
}
+
+ int prevLine = lineStartsIteratorLine;
+ while (token.offset >= lineStartsIterator.current &&
+ lineStartsIterator.moveNext()) {
+ lineStartsIteratorLine++;
+ }
+ if (printed &&
+ (token.offset > endOfLast || prevLine < lineStartsIteratorLine)) {
+ if (prevLine < lineStartsIteratorLine) {
+ for (int i = prevLine; i < lineStartsIteratorLine; i++) {
+ sb.write("\n");
+ }
+ } else {
+ sb.write(" ");
+ }
+ }
+ if (token is! ErrorToken) {
+ sb.write(token.lexeme);
+ }
+ if (addTypes) {
+ sb.write("[${token.runtimeType}]");
+ }
+ printed = true;
+ endOfLast = token.end;
+ if (token == token.next) break;
+ token = token.next;
}
- if (token is! ErrorToken) {
- sb.write(token.lexeme);
- }
- if (addTypes) {
- sb.write("[${token.runtimeType}]");
- }
- printed = true;
- endOfLast = token.end;
- if (token == token.next) break;
- token = token.next;
+
+ return token;
}
+
+ if (addTypes) {
+ token = process(token, true);
+ }
+ token = process(token, false);
+
return sb;
}
}
diff --git a/pkg/front_end/test/static_types/data/for_in.dart b/pkg/front_end/test/static_types/data/for_in.dart
index 8ae7137..93dcd4f 100644
--- a/pkg/front_end/test/static_types/data/for_in.dart
+++ b/pkg/front_end/test/static_types/data/for_in.dart
@@ -29,7 +29,8 @@
for (var e in
/*cfe.List<int>*/
/*cfe:nnbd.List<int!>!*/ list) {
- /*int*/
+ /*cfe.int*/
+ /*cfe:nnbd.int!*/
e;
}
}
@@ -72,7 +73,8 @@
/*cfe.Stream<int>*/
/*cfe:nnbd.Stream<int!>!*/
stream) {
- /*int*/
+ /*cfe.int*/
+ /*cfe:nnbd.int!*/
e;
}
}
diff --git a/pkg/front_end/test/utils/kernel_chain.dart b/pkg/front_end/test/utils/kernel_chain.dart
index 1f77cd2..a9d27a9 100644
--- a/pkg/front_end/test/utils/kernel_chain.dart
+++ b/pkg/front_end/test/utils/kernel_chain.dart
@@ -31,7 +31,8 @@
import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
-import 'package:front_end/src/fasta/messages.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/messages.dart'
+ show DiagnosticMessageFromJson, LocatedMessage;
import 'package:kernel/ast.dart' show Component, Library;
@@ -222,12 +223,15 @@
extends Step<ComponentResult, ComponentResult, MatchContext> {
final String suffix;
final bool serializeFirst;
+ final bool isLastMatchStep;
/// Check if a textual representation of the component matches the expectation
/// located at [suffix]. If [serializeFirst] is true, the input component will
/// be serialized, deserialized, and the textual representation of that is
/// compared. It is still the original component that is returned though.
- const MatchExpectation(this.suffix, {this.serializeFirst: false});
+ const MatchExpectation(this.suffix,
+ {this.serializeFirst: false, this.isLastMatchStep})
+ : assert(isLastMatchStep != null);
String get name => "match expectations";
@@ -259,16 +263,58 @@
component.adoptChildren();
}
- StringBuffer messages =
- (context as dynamic).componentToDiagnostics[component];
Uri uri =
component.uriToSource.keys.firstWhere((uri) => uri?.scheme == "file");
Iterable<Library> libraries =
componentToText.libraries.where(result.isUserLibrary);
Uri base = uri.resolve(".");
Uri dartBase = Uri.base;
+
StringBuffer buffer = new StringBuffer();
- messages.clear();
+
+ List<Iterable<String>> errors =
+ (context as dynamic).componentToDiagnostics[component];
+ Set<String> reportedErrors = <String>{};
+ for (Iterable<String> message in errors) {
+ reportedErrors.add(message.join('\n'));
+ }
+ Set<String> problemsAsJson = <String>{};
+ void addProblemsAsJson(List<String> problems) {
+ if (problems != null) {
+ for (String jsonString in problems) {
+ DiagnosticMessage message =
+ new DiagnosticMessageFromJson.fromJson(jsonString);
+ problemsAsJson.add(message.plainTextFormatted.join('\n'));
+ }
+ }
+ }
+
+ addProblemsAsJson(componentToText.problemsAsJson);
+ libraries.forEach((Library library) {
+ addProblemsAsJson(library.problemsAsJson);
+ });
+
+ bool hasProblemsOutsideComponent = false;
+ for (String reportedError in reportedErrors) {
+ if (!problemsAsJson.contains(reportedError)) {
+ if (!hasProblemsOutsideComponent) {
+ buffer.writeln('//');
+ buffer.writeln('// Problems outside component:');
+ }
+ buffer.writeln('//');
+ buffer.writeln('// ${reportedError.split('\n').join('\n// ')}');
+ hasProblemsOutsideComponent = true;
+ }
+ }
+ if (hasProblemsOutsideComponent) {
+ buffer.writeln('//');
+ }
+ if (isLastMatchStep) {
+ // Clear errors only in the last match step. This is needed to verify
+ // problems reported outside the component in both the serialized and
+ // non-serialized step.
+ errors.clear();
+ }
Printer printer = new Printer(buffer)
..writeProblemsAsJson(
"Problems in component", componentToText.problemsAsJson);
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.outline.expect b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.outline.expect
index f23adfb..f702343 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.outline.expect
@@ -1,3 +1,10 @@
+//
+// Problems outside component:
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart:9:8: Error: Not found: 'dart:_foreign_helper'
+// import 'dart:_foreign_helper' show JS; // error
+// ^
+//
library test;
//
// Problems in library:
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.strong.expect
index 7b69eef..e9116be 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart.strong.expect
@@ -1,3 +1,10 @@
+//
+// Problems outside component:
+//
+// pkg/front_end/testcases/inference/generic_methods_infer_js_builtin.dart:9:8: Error: Not found: 'dart:_foreign_helper'
+// import 'dart:_foreign_helper' show JS; // error
+// ^
+//
library test;
//
// Problems in library:
diff --git a/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.outline.expect b/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.outline.expect
index d2b8d3d..b80948b 100644
--- a/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.outline.expect
@@ -1,3 +1,10 @@
+//
+// Problems outside component:
+//
+// pkg/front_end/testcases/rasta/unsupported_platform_library.dart:5:8: Error: Not found: 'dart:html'
+// import 'dart:html';
+// ^
+//
library;
import self as self;
diff --git a/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.strong.expect b/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.strong.expect
index 22b2878..7651a58 100644
--- a/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unsupported_platform_library.dart.strong.expect
@@ -1,3 +1,10 @@
+//
+// Problems outside component:
+//
+// pkg/front_end/testcases/rasta/unsupported_platform_library.dart:5:8: Error: Not found: 'dart:html'
+// import 'dart:html';
+// ^
+//
library;
import self as self;
diff --git a/pkg/front_end/testcases/regress/utf_16_le_content.crash_dart b/pkg/front_end/testcases/regress/utf_16_le_content.crash_dart
new file mode 100644
index 0000000..3c1884f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/utf_16_le_content.crash_dart
Binary files differ
diff --git a/pkg/front_end/testcases/regress/utf_16_le_content.crash_dart.outline.expect b/pkg/front_end/testcases/regress/utf_16_le_content.crash_dart.outline.expect
new file mode 100644
index 0000000..13bf5cc
--- /dev/null
+++ b/pkg/front_end/testcases/regress/utf_16_le_content.crash_dart.outline.expect
Binary files differ
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index d6a567e..486fea6 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -236,6 +236,7 @@
regress/issue_39035.crash: RuntimeError
regress/issue_39091_1: RuntimeError
regress/issue_39091_2: RuntimeError
+regress/utf_16_le_content.crash: Crash
runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 64d249d..bf8a83c 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,14 +6,10 @@
# the round trip for Kernel textual serialization where the initial binary
# Kernel files are produced by compiling Dart code via Fasta.
-agnostic/identical: TextSerializationFailure
-agnostic/map: TextSerializationFailure
-agnostic/set: TextSerializationFailure
expression/eval: TextSerializationFailure # Was: Pass
expression/main: TextSerializationFailure # Was: Pass
extensions/ambiguous: TextSerializationFailure
extensions/annotations: TextSerializationFailure
-extensions/builtin_identifiers: TextSerializationFailure
extensions/call_methods: TypeCheckError
extensions/check_bounds: TextSerializationFailure
extensions/compounds: TextSerializationFailure
@@ -28,7 +24,6 @@
extensions/explicit_extension_access: TextSerializationFailure
extensions/explicit_extension_inference: TextSerializationFailure
extensions/explicit_generic_extension_access: TextSerializationFailure
-extensions/explicit_invalid_access: TextSerializationFailure
extensions/explicit_this: TextSerializationFailure
extensions/export_twice: TextSerializationFailure
extensions/extension_call: TextSerializationFailure
@@ -50,9 +45,7 @@
extensions/instance_tearoff: TextSerializationFailure
extensions/internal_resolution: TextSerializationFailure
extensions/invalid_explicit_access: TextSerializationFailure
-extensions/invalid_explicit_static_access: TextSerializationFailure
extensions/issue38600: TextSerializationFailure
-extensions/issue38713: TextSerializationFailure
extensions/issue38745: TextSerializationFailure
extensions/issue38750: TextSerializationFailure
extensions/issue38755: TextSerializationFailure
@@ -80,20 +73,14 @@
extensions/use_this: TextSerializationFailure
general/DeltaBlue: TextSerializationFailure # Was: Pass
general/abstract_members: TypeCheckError
-general/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
general/accessors: TextSerializationFailure # Was: RuntimeError
general/all_variances: TextSerializationFailure
-general/ambiguous_exports: TextSerializationFailure # Was: RuntimeError # Expected, this file exports two main methods.
+general/ambiguous_exports: RuntimeError
general/annotation_on_enum_values: TextSerializationFailure # Was: Pass
-general/annotation_top: TextSerializationFailure # Was: Pass
-general/annotation_typedef_formals: TextSerializationFailure # Was: Pass
-general/annotation_typedef_formals_resolution: TextSerializationFailure # Was: Pass
-general/annotation_variable_declaration: TextSerializationFailure # Was: Pass
general/argument: TextSerializationFailure # Was: Pass
general/arithmetic: TextSerializationFailure # Was: Pass
general/arrow_function: TextSerializationFailure # Was: Pass
general/assign_to_initializing_formal: TextSerializationFailure
-general/async_function: TextSerializationFailure # Was: Pass
general/async_nested: TextSerializationFailure # Was: Pass
general/await_complex: TextSerializationFailure
general/await_in_cascade: TextSerializationFailure
@@ -105,7 +92,7 @@
general/bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
general/bug21938: TypeCheckError
general/bug30695: TypeCheckError
-general/bug31124: TextSerializationFailure # Was: RuntimeError # Test has no main method (and we shouldn't add one).
+general/bug31124: RuntimeError
general/bug32414a: TextSerializationFailure # Was: Pass
general/bug32414b: TextSerializationFailure # Was: Pass
general/bug32426: TextSerializationFailure # Was: Pass
@@ -121,82 +108,62 @@
general/call: TypeCheckError
general/candidate_found: TypeCheckError
general/cascade: TextSerializationFailure # Was: RuntimeError
-general/casts: TextSerializationFailure # Was: Pass
-general/check_deferred_allocation: TextSerializationFailure # Was: Pass
general/check_deferred_as_check: TextSerializationFailure # Was: Pass
-general/check_deferred_before_args2: TextSerializationFailure # Was: Pass
-general/check_deferred_before_args: TextSerializationFailure # Was: Pass
-general/check_deferred_before_call: TextSerializationFailure # Was: Pass
-general/check_deferred_before_write: TextSerializationFailure # Was: Pass
general/check_deferred_is_check: TextSerializationFailure # Was: Pass
-general/check_deferred_read: TextSerializationFailure # Was: Pass
-general/check_deferred_read_static_field: TextSerializationFailure # Was: Pass
-general/check_deferred_read_type: TextSerializationFailure # Was: Pass
-general/check_deferred_static_method_call: TextSerializationFailure # Was: Pass
-general/check_deferred_type_declaration: TextSerializationFailure # Was: Pass
general/circularity-via-initializing-formal: TextSerializationFailure # Was: Pass
general/classes: TextSerializationFailure # Was: Pass
general/clone_function_type: TextSerializationFailure # Was: Pass
general/closure: TextSerializationFailure # Was: Pass
-general/co19_language_metadata_syntax_t04: TextSerializationFailure # Was: Pass
general/complex_class_hierarchy: TextSerializationFailure
general/compound_binary_implicit_as: TextSerializationFailure
-general/const_redirect_to_nonconst: TextSerializationFailure
general/constant_truncate: TextSerializationFailure
general/constructor_const_inference: TextSerializationFailure # Was: Pass
-general/constructor_cycle: TextSerializationFailure # Was: Pass
general/constructor_function_types: TextSerializationFailure # Was: Pass
general/constructor_initializer_invalid: TextSerializationFailure # Was: RuntimeError # Fails execution after recovery
-general/continue_inference_after_error: TextSerializationFailure # Was: Pass
general/continue_inference_after_error_lib: TextSerializationFailure # Was: Pass
general/control_flow_collection: TextSerializationFailure
general/control_flow_collection_inference: TextSerializationFailure
general/covariant_equals: TextSerializationFailure
general/covariant_generic: TextSerializationFailure # Was: RuntimeError
general/covariant_parameter_in_superclass_of_mixin_application: TextSerializationFailure
-general/cycles: TextSerializationFailure # Was: Pass
general/default_values: TextSerializationFailure # Was: Pass
general/deferred_lib: TextSerializationFailure # Was: Pass
-general/deferred_type_annotation: TextSerializationFailure # Was: Pass
general/demote_closure_types: TextSerializationFailure
-general/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
general/duplicated_bad_prefix_lib1: TextSerializationFailure # Was: Pass
general/duplicated_bad_prefix_lib2: TextSerializationFailure # Was: Pass
general/duplicated_declarations: TypeCheckError
general/duplicated_declarations_lib: TextSerializationFailure # Was: Pass
general/duplicated_declarations_part: TextSerializationFailure # Was: Pass
-general/duplicated_field_initializer: TextSerializationFailure # Was: RuntimeError
-general/duplicated_named_args_3: TextSerializationFailure # Was: Pass
+general/duplicated_field_initializer: RuntimeError
general/error_locations/error_location_01: TextSerializationFailure
general/error_locations/error_location_02: TextSerializationFailure
general/error_locations/error_location_03: TextSerializationFailure
general/error_locations/error_location_04: TextSerializationFailure
-general/error_locations/error_location_05: TextSerializationFailure
-general/error_locations/error_location_06: TextSerializationFailure
-general/error_recovery/await_not_in_async: TextSerializationFailure
-general/error_recovery/constructor_recovery_bad_name_general.crash: TextSerializationFailure
-general/error_recovery/constructor_recovery_bad_name_get.crash: TextSerializationFailure
-general/error_recovery/constructor_recovery_bad_name_return_type.crash: TextSerializationFailure
-general/error_recovery/constructor_recovery_bad_name_set.crash: TextSerializationFailure
-general/error_recovery/constructor_recovery_get: TextSerializationFailure
-general/error_recovery/constructor_recovery_ok: TextSerializationFailure
-general/error_recovery/constructor_recovery_operator.crash: TextSerializationFailure
-general/error_recovery/constructor_recovery_return_type: TextSerializationFailure
-general/error_recovery/constructor_recovery_set: TextSerializationFailure
-general/error_recovery/empty_await_for: TextSerializationFailure
-general/error_recovery/empty_for: TextSerializationFailure
+general/error_locations/error_location_05: RuntimeError
+general/error_locations/error_location_06: RuntimeError
+general/error_recovery/await_not_in_async: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_general.crash: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_get.crash: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_return_type.crash: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_set.crash: RuntimeError
+general/error_recovery/constructor_recovery_get: RuntimeError
+general/error_recovery/constructor_recovery_ok: RuntimeError
+general/error_recovery/constructor_recovery_operator.crash: RuntimeError
+general/error_recovery/constructor_recovery_return_type: RuntimeError
+general/error_recovery/constructor_recovery_set: RuntimeError
+general/error_recovery/empty_await_for: RuntimeError
+general/error_recovery/empty_for: RuntimeError
general/error_recovery/issue_38415.crash: RuntimeError
general/error_recovery/issue_38415.crash: TextSerializationFailure
general/error_recovery/issue_39024.crash: RuntimeError
-general/error_recovery/issue_39026.crash: TextSerializationFailure
-general/error_recovery/issue_39026_prime.crash: TextSerializationFailure
-general/error_recovery/issue_39033.crash: TextSerializationFailure
+general/error_recovery/issue_39026.crash: RuntimeError
+general/error_recovery/issue_39026_prime.crash: RuntimeError
+general/error_recovery/issue_39033.crash: RuntimeError
general/error_recovery/issue_39058.crash: RuntimeError
general/error_recovery/issue_39058_prime.crash: RuntimeError
-general/error_recovery/issue_39060: TextSerializationFailure
general/error_recovery/issue_39202.crash: RuntimeError
general/error_recovery/issue_39202.crash: TextSerializationFailure
-general/error_recovery/issue_39230.crash: TextSerializationFailure
+general/error_recovery/issue_39230.crash: RuntimeError
general/error_recovery/issue_39958_01: RuntimeError
general/error_recovery/issue_39958_01: TextSerializationFailure
general/error_recovery/issue_39958_02: RuntimeError
@@ -205,13 +172,12 @@
general/error_recovery/issue_39958_03: TextSerializationFailure
general/error_recovery/issue_39958_04: RuntimeError
general/error_recovery/issue_39958_04: TextSerializationFailure
-general/error_recovery/yield_not_in_generator: TextSerializationFailure
+general/error_recovery/yield_not_in_generator: RuntimeError
general/escape: TextSerializationFailure # Was: Pass
-general/export_test: TextSerializationFailure # Was: Pass
general/expressions: TextSerializationFailure # Was: RuntimeError
general/extend_with_type_variable: TextSerializationFailure
general/external: TextSerializationFailure # Was: Pass
-general/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
+general/external_import: RuntimeError
general/fallthrough: TextSerializationFailure
general/ffi_sample: TextSerializationFailure
general/fibonacci: TextSerializationFailure # Was: Pass
@@ -221,57 +187,38 @@
general/function_in_field: TextSerializationFailure # Was: Pass
general/function_type_assignments: TextSerializationFailure # Was: Pass
general/function_type_is_check: TextSerializationFailure # Was: Pass
-general/function_type_recovery: TextSerializationFailure # Was: Pass
general/functions: TextSerializationFailure # Was: Pass
-general/future_or_test: TextSerializationFailure # Was: Pass
general/generic_function_type_in_message: TextSerializationFailure
general/getter_call: TextSerializationFailure
-general/having_part_with_part_and_annotation: TextSerializationFailure
-general/having_part_with_parts_and_annotation: TextSerializationFailure
general/if_null_in_cascade: TextSerializationFailure
general/if_null_in_list_literal: TextSerializationFailure
general/if_null_in_set_literal: TextSerializationFailure
-general/ignore_function: TextSerializationFailure
general/illegal_named_function_expression: TextSerializationFailure # Was: Pass
general/illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
-general/implicit_const_with_static_fields: TextSerializationFailure # Was: Pass
general/implicit_new: TextSerializationFailure # Was: Pass
general/implicit_scope_test: TextSerializationFailure # Was: Pass
-general/implicit_this: TextSerializationFailure # Was: Pass
-general/import_conflicting_getters: TextSerializationFailure
-general/import_conflicting_setters: TextSerializationFailure
-general/import_conflicting_type_member: TextSerializationFailure
-general/import_conflicting_types: TextSerializationFailure
-general/incomplete_field_formal_parameter: TextSerializationFailure # Was: RuntimeError
+general/incomplete_field_formal_parameter: RuntimeError
general/infer_field_from_multiple: TypeCheckError
-general/infer_field_type: TextSerializationFailure
general/infer_fixed_generic_return_type: TextSerializationFailure
general/infer_map_literal_with_closure: TextSerializationFailure
-general/inherit_function: TextSerializationFailure
-general/interface_conflict: TextSerializationFailure
general/interface_contravariant_from_class: TextSerializationFailure
general/interface_covariantImpl_from_class: TextSerializationFailure
general/interface_covariantInterface_from_class: TextSerializationFailure
general/invalid_assignment: TextSerializationFailure # Was: Pass
general/invalid_cast: TextSerializationFailure # Was: Pass
-general/invalid_operator2: TextSerializationFailure
general/invalid_operator: TypeCheckError
-general/invalid_type: TextSerializationFailure
-general/invocations: TextSerializationFailure # Was: RuntimeError
-general/issue129167943: TextSerializationFailure
-general/issue34515: TextSerializationFailure
+general/invocations: RuntimeError
general/issue34899: TextSerializationFailure
general/issue35875: TextSerializationFailure
general/issue37027: TextSerializationFailure
general/issue37381: TextSerializationFailure
-general/issue37776: TextSerializationFailure
+general/issue37776: RuntimeError
general/issue38812: TextSerializationFailure
-general/issue38938: TextSerializationFailure
+general/issue38938: RuntimeError
general/issue38943: TextSerializationFailure
general/issue38944: TextSerializationFailure
-general/issue38961: TextSerializationFailure
+general/issue38961: RuntimeError
general/issue39344: TextSerializationFailure
-general/issue39421: TextSerializationFailure
general/issue39817: TextSerializationFailure
general/issue40242: TextSerializationFailure
general/issue40428: TextSerializationFailure
@@ -280,27 +227,20 @@
general/issue41070: TextSerializationFailure
general/issue41210a: TypeCheckError
general/issue41210b/issue41210: TypeCheckError
-general/literals: TextSerializationFailure # Was: Pass
general/local_generic_function: TextSerializationFailure # Was: Pass
general/long_chain_of_typedefs: TextSerializationFailure
-general/magic_const: TextSerializationFailure # Was: Pass
general/many_errors: TextSerializationFailure
general/metadata_enum: TextSerializationFailure # Was: Pass
-general/metadata_named_mixin_application: TextSerializationFailure # Was: Pass
general/micro: TextSerializationFailure # Was: RuntimeError
-general/missing_constructor: TextSerializationFailure # Was: Pass
general/missing_toplevel: TextSerializationFailure
general/mixin: TextSerializationFailure # Was: Pass
general/mixin_application_inferred_parameter_type: TextSerializationFailure
general/mixin_application_override: ExpectationFileMismatch
general/mixin_application_override: TypeCheckError
-general/mixin_conflicts: TextSerializationFailure
general/mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
general/mixin_covariant: TextSerializationFailure
general/mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
-general/mixin_interface_conflict: TextSerializationFailure
general/mixin_super_repeated: TextSerializationFailure # Was: Pass
-general/mixin_with_static_member: TextSerializationFailure
general/named_function_scope: TextSerializationFailure # Was: Pass
general/named_parameters: TextSerializationFailure # Was: Pass
general/native_as_name: TextSerializationFailure # Was: Pass
@@ -327,16 +267,8 @@
general/override_check_generic_method_f_bounded: TextSerializationFailure # Was: Pass
general/override_check_two_substitutions: TextSerializationFailure # Was: Pass
general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
-general/override_inference_for_getters_and_setters: TextSerializationFailure
-general/override_inference_for_setters: TextSerializationFailure
-general/override_inference_named_parameters_ordering: TextSerializationFailure
general/override_setter_with_field: TypeCheckError
general/part_as_entry_point_lib: TextSerializationFailure # Was: Pass
-general/part_not_part_of: TextSerializationFailure
-general/part_not_part_of_same_named_library: TextSerializationFailure
-general/part_part_of_different_unnamed_library: TextSerializationFailure
-general/part_part_of_differently_named_library: TextSerializationFailure
-general/prefer_baseclass: TextSerializationFailure # Was: Pass
general/private_method_tearoff: TextSerializationFailure # Was: Pass
general/private_method_tearoff_lib: TextSerializationFailure # Was: Pass
general/promoted_access: TextSerializationFailure
@@ -346,12 +278,8 @@
general/qualified: TextSerializationFailure # Was: Pass
general/qualified_lib: TextSerializationFailure # Was: Pass
general/qualified_part: TextSerializationFailure # Was: Pass
-general/redirecting_constructor: TextSerializationFailure # Was: Pass
general/redirecting_factory: TextSerializationFailure # Was: Pass
-general/redirecting_factory_chain_test: TextSerializationFailure # Was: Pass
general/redirecting_factory_const_inference: TextSerializationFailure # Was: Pass
-general/redirecting_factory_metadata: TextSerializationFailure # Was: Pass
-general/redirecting_factory_simple_test: TextSerializationFailure # Was: Pass
general/redirecting_factory_typeargs_test: TextSerializationFailure # Was: Pass
general/redirecting_factory_typeparam_test: TextSerializationFailure # Was: Pass
general/redirecting_factory_typeparambounds_test: TextSerializationFailure # Was: Pass
@@ -362,20 +290,16 @@
general/redirection_type_arguments: TextSerializationFailure # Was: Pass
general/reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
general/return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
-general/sdk_diagnostic: TextSerializationFailure
general/spread_collection: TextSerializationFailure # Should be fixed as part of implementing spread collection support
general/spread_collection_inference: TextSerializationFailure # Should be fixed as part of implementing spread collection support
general/statements: Crash
-general/static_setter: TextSerializationFailure # Was: Pass
general/store_load: TextSerializationFailure # Was: Pass
-general/stringliteral: TextSerializationFailure # Was: Pass
general/super_call: TextSerializationFailure # Was: Pass
general/super_nsm: TextSerializationFailure # Was: Pass
general/this_field_call: TextSerializationFailure
general/three_typedefs_loop: TextSerializationFailure
general/top_level_accessors: TextSerializationFailure # Was: Pass
general/top_level_accessors_part: TextSerializationFailure # Was: Pass
-general/type_literal_as_metadata: TextSerializationFailure
general/type_of_null: TextSerializationFailure
general/type_parameter_type_named_int: TextSerializationFailure
general/type_parameter_usage_in_static_method_in_class: TextSerializationFailure
@@ -384,7 +308,6 @@
general/type_variable_bound_access: TypeCheckError
general/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
general/type_variable_uses: TextSerializationFailure # Was: Pass
-general/typedef: TextSerializationFailure # Was: Pass
general/undefined: TextSerializationFailure # Was: Pass
general/undefined_getter_in_compound_assignment: TextSerializationFailure # Was: Pass
general/uninitialized_fields: TextSerializationFailure # Was: Pass
@@ -393,27 +316,19 @@
general/var_as_type_name: TextSerializationFailure # Was: Pass
general/vm_type_ops: TextSerializationFailure
general/void_methods: TextSerializationFailure
-general/warn_unresolved_sends: TextSerializationFailure
general/well_boundness_checks_in_outline: TextSerializationFailure
-general/with_dependencies/abstract_members_from_dill/main: TextSerializationFailure
general/with_dependencies/extension_from_dill/extension_from_dill: TextSerializationFailure
general/with_dependencies/variance_from_dill/variance_from_dill: TextSerializationFailure
general_nnbd_opt_out/DeltaBlue: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/abstract_members: TypeCheckError
-general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
general_nnbd_opt_out/accessors: TextSerializationFailure # Was: RuntimeError
general_nnbd_opt_out/all_variances: TextSerializationFailure
-general_nnbd_opt_out/ambiguous_exports: TextSerializationFailure # Was: RuntimeError # Expected, this file exports two main methods.
+general_nnbd_opt_out/ambiguous_exports: RuntimeError
general_nnbd_opt_out/annotation_on_enum_values: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/annotation_top: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/annotation_typedef_formals: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/annotation_typedef_formals_resolution: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/annotation_variable_declaration: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/argument: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/arithmetic: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/arrow_function: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/assign_to_initializing_formal: TextSerializationFailure
-general_nnbd_opt_out/async_function: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/async_nested: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/await_complex: TextSerializationFailure
general_nnbd_opt_out/await_in_cascade: TextSerializationFailure
@@ -425,7 +340,7 @@
general_nnbd_opt_out/bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/bug21938: TypeCheckError
general_nnbd_opt_out/bug30695: TypeCheckError
-general_nnbd_opt_out/bug31124: TextSerializationFailure # Was: RuntimeError # Test has no main method (and we shouldn't add one).
+general_nnbd_opt_out/bug31124: RuntimeError
general_nnbd_opt_out/bug32414a: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/bug32414b: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/bug32426: TextSerializationFailure # Was: Pass
@@ -441,62 +356,42 @@
general_nnbd_opt_out/call: TypeCheckError
general_nnbd_opt_out/candidate_found: TypeCheckError
general_nnbd_opt_out/cascade: TextSerializationFailure # Was: RuntimeError
-general_nnbd_opt_out/casts: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_allocation: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/check_deferred_as_check: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_before_args2: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_before_args: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_before_call: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_before_write: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/check_deferred_is_check: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_read: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_read_static_field: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_read_type: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_static_method_call: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_type_declaration: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/circularity-via-initializing-formal: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/classes: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/clone_function_type: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/closure: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/co19_language_metadata_syntax_t04: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/complex_class_hierarchy: TextSerializationFailure
general_nnbd_opt_out/compound_binary_implicit_as: TextSerializationFailure
-general_nnbd_opt_out/const_redirect_to_nonconst: TextSerializationFailure
general_nnbd_opt_out/constructor_const_inference: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/constructor_cycle: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/constructor_function_types: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/constructor_initializer_invalid: TextSerializationFailure # Was: RuntimeError # Fails execution after recovery
-general_nnbd_opt_out/continue_inference_after_error: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/continue_inference_after_error_lib: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/control_flow_collection: TextSerializationFailure
general_nnbd_opt_out/control_flow_collection_inference: TextSerializationFailure
general_nnbd_opt_out/covariant_equals: TextSerializationFailure
general_nnbd_opt_out/covariant_generic: TextSerializationFailure # Was: RuntimeError
general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application: TextSerializationFailure
-general_nnbd_opt_out/cycles: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/default_values: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/deferred_lib: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/deferred_type_annotation: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/duplicated_bad_prefix_lib1: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/duplicated_bad_prefix_lib2: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/duplicated_declarations: TypeCheckError
general_nnbd_opt_out/duplicated_declarations_lib: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/duplicated_declarations_part: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/duplicated_field_initializer: TextSerializationFailure # Was: RuntimeError
-general_nnbd_opt_out/duplicated_named_args_3: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/duplicated_field_initializer: RuntimeError
general_nnbd_opt_out/error_locations/error_location_01: TextSerializationFailure
general_nnbd_opt_out/error_locations/error_location_02: TextSerializationFailure
general_nnbd_opt_out/error_locations/error_location_03: TextSerializationFailure
general_nnbd_opt_out/error_locations/error_location_04: TextSerializationFailure
-general_nnbd_opt_out/error_locations/error_location_05: TextSerializationFailure
-general_nnbd_opt_out/error_locations/error_location_06: TextSerializationFailure
+general_nnbd_opt_out/error_locations/error_location_05: RuntimeError
+general_nnbd_opt_out/error_locations/error_location_06: RuntimeError
general_nnbd_opt_out/escape: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/export_test: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/expressions: TextSerializationFailure # Was: RuntimeError
general_nnbd_opt_out/extend_with_type_variable: TextSerializationFailure
general_nnbd_opt_out/external: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
+general_nnbd_opt_out/external_import: RuntimeError
general_nnbd_opt_out/fallthrough: TextSerializationFailure
general_nnbd_opt_out/ffi_sample: TextSerializationFailure
general_nnbd_opt_out/fibonacci: TextSerializationFailure # Was: Pass
@@ -506,68 +401,47 @@
general_nnbd_opt_out/function_in_field: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/function_type_assignments: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/function_type_is_check: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/function_type_recovery: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/functions: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/future_or_test: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/generic_function_type_in_message: TextSerializationFailure
-general_nnbd_opt_out/having_part_with_part_and_annotation: TextSerializationFailure
-general_nnbd_opt_out/having_part_with_parts_and_annotation: TextSerializationFailure
general_nnbd_opt_out/if_null_in_cascade: TextSerializationFailure
general_nnbd_opt_out/if_null_in_list_literal: TextSerializationFailure
general_nnbd_opt_out/if_null_in_set_literal: TextSerializationFailure
-general_nnbd_opt_out/ignore_function: TextSerializationFailure
general_nnbd_opt_out/illegal_named_function_expression: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/implicit_const_with_static_fields: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/implicit_new: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/implicit_scope_test: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/implicit_this: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/import_conflicting_getters: TextSerializationFailure
-general_nnbd_opt_out/import_conflicting_setters: TextSerializationFailure
-general_nnbd_opt_out/import_conflicting_type_member: TextSerializationFailure
-general_nnbd_opt_out/import_conflicting_types: TextSerializationFailure
-general_nnbd_opt_out/incomplete_field_formal_parameter: TextSerializationFailure # Was: RuntimeError
+general_nnbd_opt_out/incomplete_field_formal_parameter: RuntimeError
general_nnbd_opt_out/interface_contravariant_from_class: TextSerializationFailure
general_nnbd_opt_out/interface_covariantImpl_from_class: TextSerializationFailure
general_nnbd_opt_out/interface_covariantInterface_from_class: TextSerializationFailure
general_nnbd_opt_out/invalid_assignment: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/invalid_cast: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/invalid_type: TextSerializationFailure
-general_nnbd_opt_out/invocations: TextSerializationFailure # Was: RuntimeError
-general_nnbd_opt_out/issue129167943: TextSerializationFailure
-general_nnbd_opt_out/issue34515: TextSerializationFailure
+general_nnbd_opt_out/invocations: RuntimeError
general_nnbd_opt_out/issue34899: TextSerializationFailure
general_nnbd_opt_out/issue35875: TextSerializationFailure
general_nnbd_opt_out/issue37027: TextSerializationFailure
general_nnbd_opt_out/issue37381: TextSerializationFailure
-general_nnbd_opt_out/issue37776: TextSerializationFailure
+general_nnbd_opt_out/issue37776: RuntimeError
general_nnbd_opt_out/issue38812: TextSerializationFailure
-general_nnbd_opt_out/issue38938: TextSerializationFailure
+general_nnbd_opt_out/issue38938: RuntimeError
general_nnbd_opt_out/issue38943: TextSerializationFailure
general_nnbd_opt_out/issue38944: TextSerializationFailure
-general_nnbd_opt_out/issue38961: TextSerializationFailure
+general_nnbd_opt_out/issue38961: RuntimeError
general_nnbd_opt_out/issue39344: TextSerializationFailure
-general_nnbd_opt_out/issue39421: TextSerializationFailure
general_nnbd_opt_out/issue39817: TextSerializationFailure
-general_nnbd_opt_out/literals: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/local_generic_function: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/long_chain_of_typedefs: TextSerializationFailure
-general_nnbd_opt_out/magic_const: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/many_errors: TextSerializationFailure
general_nnbd_opt_out/metadata_enum: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/metadata_named_mixin_application: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/micro: TextSerializationFailure # Was: RuntimeError
-general_nnbd_opt_out/missing_constructor: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/missing_toplevel: TextSerializationFailure
general_nnbd_opt_out/mixin: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/mixin_application_inferred_parameter_type: TextSerializationFailure
general_nnbd_opt_out/mixin_application_override: ExpectationFileMismatch
general_nnbd_opt_out/mixin_application_override: TypeCheckError
-general_nnbd_opt_out/mixin_conflicts: TextSerializationFailure
general_nnbd_opt_out/mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/mixin_super_repeated: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/mixin_with_static_member: TextSerializationFailure
general_nnbd_opt_out/named_function_scope: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/named_parameters: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/native_as_name: TextSerializationFailure # Was: Pass
@@ -594,15 +468,8 @@
general_nnbd_opt_out/override_check_generic_method_f_bounded: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/override_check_two_substitutions: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
-general_nnbd_opt_out/override_inference_for_setters: TextSerializationFailure
-general_nnbd_opt_out/override_inference_named_parameters_ordering: TextSerializationFailure
general_nnbd_opt_out/override_setter_with_field: TypeCheckError
general_nnbd_opt_out/part_as_entry_point_lib: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/part_not_part_of: TextSerializationFailure
-general_nnbd_opt_out/part_not_part_of_same_named_library: TextSerializationFailure
-general_nnbd_opt_out/part_part_of_different_unnamed_library: TextSerializationFailure
-general_nnbd_opt_out/part_part_of_differently_named_library: TextSerializationFailure
-general_nnbd_opt_out/prefer_baseclass: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/private_method_tearoff: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/private_method_tearoff_lib: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/promoted_access: TextSerializationFailure
@@ -611,12 +478,8 @@
general_nnbd_opt_out/qualified: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/qualified_lib: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/qualified_part: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/redirecting_constructor: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/redirecting_factory: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/redirecting_factory_chain_test: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/redirecting_factory_const_inference: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/redirecting_factory_metadata: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/redirecting_factory_simple_test: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/redirecting_factory_typeargs_test: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/redirecting_factory_typeparam_test: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/redirecting_factory_typeparambounds_test: TextSerializationFailure # Was: Pass
@@ -627,26 +490,21 @@
general_nnbd_opt_out/redirection_type_arguments: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
general_nnbd_opt_out/return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/sdk_diagnostic: TextSerializationFailure
general_nnbd_opt_out/spread_collection: TextSerializationFailure # Should be fixed as part of implementing spread collection support
general_nnbd_opt_out/spread_collection_inference: TextSerializationFailure # Should be fixed as part of implementing spread collection support
general_nnbd_opt_out/statements: Crash
-general_nnbd_opt_out/static_setter: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/store_load: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/stringliteral: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/super_call: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/super_nsm: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/three_typedefs_loop: TextSerializationFailure
general_nnbd_opt_out/top_level_accessors: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/top_level_accessors_part: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/type_literal_as_metadata: TextSerializationFailure
general_nnbd_opt_out/type_of_null: TextSerializationFailure
general_nnbd_opt_out/type_parameter_type_named_int: TextSerializationFailure
general_nnbd_opt_out/type_variable_as_super: TextSerializationFailure # Was: RuntimeError
general_nnbd_opt_out/type_variable_bound_access: TypeCheckError
general_nnbd_opt_out/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
general_nnbd_opt_out/type_variable_uses: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/typedef: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/undefined: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/undefined_getter_in_compound_assignment: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/uninitialized_fields: TextSerializationFailure # Was: Pass
@@ -654,7 +512,6 @@
general_nnbd_opt_out/unused_methods: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/var_as_type_name: TextSerializationFailure # Was: Pass
general_nnbd_opt_out/void_methods: TextSerializationFailure
-general_nnbd_opt_out/warn_unresolved_sends: TextSerializationFailure
implicit_getter_calls/getter_call: TextSerializationFailure
implicit_getter_calls/this_field_call: TextSerializationFailure
inference/abstract_class_instantiation: TextSerializationFailure
@@ -662,9 +519,6 @@
inference/assert_initializer: TextSerializationFailure # Was: Pass
inference/assign_local: TextSerializationFailure # Was: Pass
inference/async_await: TextSerializationFailure # Was: Pass
-inference/async_closure_return_type_flatten: TextSerializationFailure # Was: Pass
-inference/async_closure_return_type_future: TextSerializationFailure # Was: Pass
-inference/async_closure_return_type_future_or: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_async_all_returns_are_futures: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_async_all_returns_are_values: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_async_mix_of_values_and_futures: TextSerializationFailure # Was: Pass
@@ -672,7 +526,6 @@
inference/block_bodied_lambdas_basic: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_basic_void: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference: TextSerializationFailure # Was: Pass
-inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_infer_bottom_async: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_infer_bottom_async_star: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_infer_bottom_sync: TextSerializationFailure # Was: Pass
@@ -683,7 +536,6 @@
inference/block_bodied_lambdas_returns: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_sync_star: TextSerializationFailure # Was: Pass
inference/block_bodied_lambdas_void_context: TextSerializationFailure # Was: Pass
-inference/bottom_in_closure: TextSerializationFailure # Was: Pass
inference/bug30251: TextSerializationFailure # Was: Pass
inference/bug30620: TextSerializationFailure # Was: Pass
inference/bug30620_b: TextSerializationFailure # Was: Pass
@@ -695,17 +547,9 @@
inference/bug31436: TextSerializationFailure # Was: Pass
inference/bug32291: TextSerializationFailure # Was: Pass
inference/bug33324: TextSerializationFailure # Was: Pass
-inference/call_corner_cases: TextSerializationFailure # Was: Pass
inference/callable_generic_class: TextSerializationFailure # Was: Pass
-inference/circular_method_inference: TextSerializationFailure # Was: Pass
-inference/closure_param_null_to_object: TextSerializationFailure # Was: Pass
-inference/coerce_bottom_and_null_types: TextSerializationFailure # Was: Pass
inference/complex_predecrement: TextSerializationFailure # Was: Pass
-inference/conditional_lub: TextSerializationFailure # Was: Pass
inference/conditional_upwards_inference: TextSerializationFailure # Was: Pass
-inference/conflicting_fields: TextSerializationFailure
-inference/conflicts_can_happen2: TextSerializationFailure
-inference/conflicts_can_happen: TextSerializationFailure
inference/constructors_downwards_with_constraint: TextSerializationFailure # Was: Pass
inference/constructors_infer_from_arguments: TextSerializationFailure # Was: Pass
inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
@@ -723,47 +567,31 @@
inference/constructors_reverse_type_parameters: TextSerializationFailure # Was: Pass
inference/constructors_too_many_positional_arguments: TextSerializationFailure
inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
-inference/dont_infer_field_type_when_initializer_is_null: TextSerializationFailure # Was: Pass
inference/dont_infer_type_on_dynamic: TextSerializationFailure # Was: Pass
inference/dont_infer_type_when_initializer_is_null: TextSerializationFailure # Was: Pass
inference/downward_inference_fixes_no_upwards_errors: TextSerializationFailure # Was: Pass
inference/downward_inference_miscellaneous: TextSerializationFailure # Was: Pass
-inference/downwards_context_from_inferred_field_type: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_class_members: TextSerializationFailure # Was: Pass
inference/downwards_inference_annotations_for_loop_variable: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_locals: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_locals_referring_to_locals: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_parameter: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_parameter_local: TextSerializationFailure # Was: Pass
inference/downwards_inference_annotations_type_variable: TextSerializationFailure
-inference/downwards_inference_annotations_type_variable_local: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_typedef: TextSerializationFailure # Was: Pass
-inference/downwards_inference_assignment_statements: TextSerializationFailure # Was: Pass
inference/downwards_inference_async_await: TextSerializationFailure # Was: Pass
inference/downwards_inference_for_each: TextSerializationFailure # Was: Pass
inference/downwards_inference_initializing_formal_default_formal: TextSerializationFailure # Was: Pass
inference/downwards_inference_inside_top_level: TextSerializationFailure # Was: Pass
inference/downwards_inference_inside_top_level_2: TextSerializationFailure # Was: Pass
-inference/downwards_inference_on_constructor_arguments_infer_downwards: TextSerializationFailure # Was: Pass
-inference/downwards_inference_on_function_arguments_infer_downwards: TextSerializationFailure # Was: Pass
inference/downwards_inference_on_function_expressions: TextSerializationFailure # Was: Pass
inference/downwards_inference_on_function_of_t_using_the_t: TextSerializationFailure
inference/downwards_inference_on_generic_constructor_arguments_empty_list: TextSerializationFailure # Was: Pass
inference/downwards_inference_on_generic_constructor_arguments_infer_downwards: TextSerializationFailure # Was: Pass
inference/downwards_inference_on_generic_function_expressions: TextSerializationFailure # Was: Pass
inference/downwards_inference_on_instance_creations_infer_downwards: TextSerializationFailure # Was: Pass
-inference/downwards_inference_on_list_literals_infer_downwards: TextSerializationFailure # Was: RuntimeError
+inference/downwards_inference_on_list_literals_infer_downwards: RuntimeError
inference/downwards_inference_on_list_literals_infer_if_value_types_match_context: TextSerializationFailure # Was: Pass
-inference/downwards_inference_on_map_literals: TextSerializationFailure # Was: Pass
inference/downwards_inference_yield_yield_star: TextSerializationFailure # Was: Pass
inference/dynamic_methods: TextSerializationFailure # Was: Pass
inference/field_initializer_context_explicit: TextSerializationFailure # Was: Pass
inference/field_initializer_context_implicit: TextSerializationFailure # Was: Pass
inference/field_initializer_context_this: TextSerializationFailure # Was: Pass
inference/field_initializer_parameter: TextSerializationFailure # Was: Pass
-inference/field_refers_to_static_getter: TextSerializationFailure # Was: Pass
-inference/field_refers_to_top_level_getter: TextSerializationFailure # Was: Pass
inference/for_each_downcast_iterable: TextSerializationFailure # Was: Pass
inference/for_in_loop_promotion: TextSerializationFailure # Was: Pass
inference/for_loop_empty_condition: TextSerializationFailure # Was: Pass
@@ -798,7 +626,6 @@
inference/future_union_downwards_generic_method_with_future_return: TextSerializationFailure # Was: Pass
inference/future_union_downwards_generic_method_with_generic_return: TextSerializationFailure # Was: Pass
inference/future_union_upwards_generic_methods: TextSerializationFailure # Was: Pass
-inference/generator_closure: TextSerializationFailure # Was: Pass
inference/generic_functions_return_typedef: TextSerializationFailure
inference/generic_methods_basic_downward_inference: TextSerializationFailure # Was: Pass
inference/generic_methods_correctly_recognize_generic_upper_bound: TypeCheckError
@@ -818,10 +645,6 @@
inference/generic_methods_nested_generic_instantiation: TextSerializationFailure # Was: Pass
inference/generic_methods_uses_greatest_lower_bound: TextSerializationFailure # Was: Pass
inference/greatest_closure_multiple_params: TextSerializationFailure # Was: Pass
-inference/inconsistent_overrides: TextSerializationFailure
-inference/index_assign_operator_return_type: TextSerializationFailure # Was: Pass
-inference/index_assign_operator_return_type_2: TextSerializationFailure # Was: Pass
-inference/infer_accessor_from_later_inferred_field: TextSerializationFailure # Was: Pass
inference/infer_assign_to_implicit_this: TextSerializationFailure # Was: Pass
inference/infer_assign_to_implicit_this_upwards: TextSerializationFailure # Was: Pass
inference/infer_assign_to_index_full: TextSerializationFailure # Was: Pass
@@ -835,87 +658,39 @@
inference/infer_assign_to_property_super: TextSerializationFailure # Was: Pass
inference/infer_assign_to_property_super_upwards: TextSerializationFailure # Was: Pass
inference/infer_assign_to_property_upwards: TextSerializationFailure # Was: Pass
-inference/infer_assign_to_ref: TextSerializationFailure # Was: Pass
inference/infer_assign_to_static: TextSerializationFailure # Was: Pass
inference/infer_assign_to_static_upwards: TextSerializationFailure # Was: Pass
-inference/infer_binary_custom: TextSerializationFailure # Was: Pass
-inference/infer_binary_double_double: TextSerializationFailure # Was: Pass
-inference/infer_binary_double_int: TextSerializationFailure # Was: Pass
-inference/infer_binary_int_double: TextSerializationFailure # Was: Pass
-inference/infer_binary_int_int: TextSerializationFailure # Was: Pass
-inference/infer_conditional: TextSerializationFailure # Was: Pass
-inference/infer_consts_transitively_2: TextSerializationFailure # Was: Pass
-inference/infer_consts_transitively_2_a: TextSerializationFailure # Was: Pass
-inference/infer_consts_transitively_2_b: TextSerializationFailure # Was: Pass
-inference/infer_consts_transitively_b: TextSerializationFailure # Was: Pass
-inference/infer_correctly_on_multiple_variables_declared_together: TextSerializationFailure # Was: Pass
-inference/infer_field_from_later_inferred_field: TextSerializationFailure # Was: Pass
-inference/infer_field_from_later_inferred_getter: TextSerializationFailure # Was: Pass
-inference/infer_field_from_later_inferred_setter: TextSerializationFailure # Was: Pass
-inference/infer_field_override_multiple: TextSerializationFailure
-inference/infer_field_override_of_override: TextSerializationFailure # Was: Pass
inference/infer_field_override_with_substitution: TextSerializationFailure # Was: Pass
-inference/infer_field_overrides_getter: TextSerializationFailure # Was: Pass
-inference/infer_field_overrides_setter: TextSerializationFailure # Was: Pass
-inference/infer_field_static: TextSerializationFailure # Was: Pass
inference/infer_final_field_getter_and_setter: TextSerializationFailure # Was: Pass
inference/infer_final_field_getter_only: TextSerializationFailure # Was: Pass
inference/infer_final_field_setter_only: TextSerializationFailure # Was: Pass
inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TextSerializationFailure
-inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: TextSerializationFailure # Was: Pass
-inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: TextSerializationFailure # Was: Pass
inference/infer_from_variables_in_cycle_libs_when_flag_is_on2: TextSerializationFailure # Was: Pass
inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a: TextSerializationFailure # Was: Pass
inference/infer_from_variables_in_cycle_libs_when_flag_is_on: TextSerializationFailure # Was: Pass
inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag2: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag2_a: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag_a: TextSerializationFailure # Was: Pass
inference/infer_generic_field_types: TextSerializationFailure
inference/infer_generic_method_type_named: TextSerializationFailure # Was: Pass
inference/infer_generic_method_type_positional2: TextSerializationFailure # Was: Pass
inference/infer_generic_method_type_positional: TextSerializationFailure # Was: Pass
inference/infer_generic_method_type_required: TextSerializationFailure # Was: Pass
-inference/infer_getter_cross_to_setter: TextSerializationFailure # Was: Pass
-inference/infer_getter_from_later_inferred_getter: TextSerializationFailure # Was: Pass
inference/infer_list_literal_nested_in_map_literal: TextSerializationFailure # Was: Pass
inference/infer_local_function_referenced_before_declaration: TextSerializationFailure # Was: Pass
inference/infer_local_function_return_type: TextSerializationFailure # Was: Pass
inference/infer_method_function_typed: TextSerializationFailure # Was: Pass
inference/infer_method_missing_params: ExpectationFileMismatch
inference/infer_method_missing_params: TypeCheckError
-inference/infer_parameter_type_setter_from_field: TextSerializationFailure # Was: Pass
-inference/infer_parameter_type_setter_from_setter: TextSerializationFailure # Was: Pass
-inference/infer_prefix_expression: TextSerializationFailure # Was: Pass
-inference/infer_prefix_expression_custom: TextSerializationFailure # Was: Pass
inference/infer_rethrow: TextSerializationFailure # Was: Pass
inference/infer_return_of_statement_lambda: TextSerializationFailure # Was: Pass
-inference/infer_return_type_for_static_setter: TextSerializationFailure # Was: Pass
-inference/infer_setter_cross_to_getter: TextSerializationFailure # Was: Pass
-inference/infer_setter_from_later_inferred_setter: TextSerializationFailure # Was: Pass
inference/infer_setter_function_typed: TextSerializationFailure # Was: Pass
-inference/infer_setter_return_type_only: TextSerializationFailure # Was: Pass
inference/infer_statics_transitively2: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively3: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively3_a: TextSerializationFailure # Was: Pass
inference/infer_statics_transitively: TextSerializationFailure # Was: Pass
inference/infer_statics_transitively_2_a: TextSerializationFailure # Was: Pass
inference/infer_statics_transitively_a: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively_b: TextSerializationFailure # Was: Pass
-inference/infer_statics_with_method_invocations: TextSerializationFailure # Was: Pass
-inference/infer_statics_with_method_invocations_a: TextSerializationFailure # Was: Pass
-inference/infer_throw: TextSerializationFailure # Was: Pass
inference/infer_throw_downwards: TextSerializationFailure # Was: Pass
-inference/infer_type_on_overridden_fields2: TextSerializationFailure # Was: Pass
-inference/infer_type_on_overridden_fields4: TextSerializationFailure # Was: Pass
-inference/infer_type_on_var2: TextSerializationFailure # Was: Pass
-inference/infer_type_on_var: TextSerializationFailure # Was: Pass
inference/infer_type_on_var_from_field: TextSerializationFailure # Was: Pass
inference/infer_type_on_var_from_top_level: TextSerializationFailure # Was: Pass
-inference/infer_type_regardless_of_declaration_order_or_cycles: TextSerializationFailure # Was: RuntimeError
-inference/infer_type_regardless_of_declaration_order_or_cycles_b: TextSerializationFailure # Was: Pass
-inference/infer_typed_map_literal: TextSerializationFailure # Was: Pass
+inference/infer_type_regardless_of_declaration_order_or_cycles: RuntimeError
inference/infer_types_on_generic_instantiations_3: TextSerializationFailure # Was: Pass
inference/infer_types_on_generic_instantiations_4: TextSerializationFailure # Was: RuntimeError
inference/infer_types_on_generic_instantiations_5: TextSerializationFailure # Was: Pass
@@ -925,38 +700,15 @@
inference/infer_types_on_loop_indices_for_each_loop: TextSerializationFailure # Was: Pass
inference/infer_types_on_loop_indices_for_each_loop_async: TextSerializationFailure # Was: Pass
inference/infer_types_on_loop_indices_for_loop_with_inference: TextSerializationFailure # Was: Pass
-inference/infer_use_of_void_local: TextSerializationFailure # Was: Pass
inference/inferred_initializing_formal_checks_default_value: TextSerializationFailure # Was: Pass
-inference/inferred_nonstatic_field_depends_on_static_field_complex: TextSerializationFailure # Was: Pass
-inference/inferred_nonstatic_field_depends_on_top_level_var_simple: TextSerializationFailure # Was: Pass
-inference/inferred_type_block_closure_no_args_no_return: TextSerializationFailure # Was: Pass
-inference/inferred_type_block_closure_no_args_no_return_void_context: TextSerializationFailure # Was: Pass
inference/inferred_type_cascade: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_binary_op: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_binary_op_via_interface: TextSerializationFailure # Was: Pass
inference/inferred_type_custom_index_op: TextSerializationFailure # Was: Pass
inference/inferred_type_custom_index_op_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_unary_op: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_unary_op_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_extract_method_tear_off: TextSerializationFailure # Was: Pass
-inference/inferred_type_extract_method_tear_off_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_from_top_level_executable_tear_off: TextSerializationFailure # Was: Pass
-inference/inferred_type_invoke_method: TextSerializationFailure # Was: Pass
-inference/inferred_type_invoke_method_via_interface: TextSerializationFailure # Was: Pass
inference/inferred_type_is_enum: TextSerializationFailure # Was: Pass
inference/inferred_type_is_enum_values: TextSerializationFailure # Was: Pass
-inference/inferred_type_is_typedef: TextSerializationFailure # Was: Pass
inference/inferred_type_is_typedef_parameterized: TextSerializationFailure # Was: Pass
-inference/inferred_type_uses_synthetic_function_type: TextSerializationFailure # Was: Pass
-inference/inferred_type_uses_synthetic_function_type_function_typed_param: TextSerializationFailure # Was: Pass
-inference/inferred_type_uses_synthetic_function_type_named_param: TextSerializationFailure # Was: Pass
-inference/inferred_type_uses_synthetic_function_type_positional_param: TextSerializationFailure # Was: Pass
-inference/inferred_type_uses_synthetic_function_type_required_param: TextSerializationFailure # Was: Pass
inference/inferred_type_via_closure_multiple_levels_of_nesting: TextSerializationFailure # Was: Pass
inference/inferred_type_via_closure_type_depends_on_args: TextSerializationFailure # Was: Pass
-inference/inferred_type_via_closure_type_independent_of_args_field: TextSerializationFailure # Was: Pass
-inference/inferred_type_via_closure_type_independent_of_args_top_level: TextSerializationFailure # Was: Pass
-inference/inheritance_does_not_imply_circularity: TextSerializationFailure # Was: Pass
inference/instance_creation_downwards: TextSerializationFailure # Was: Pass
inference/instantiate_tearoff: TextSerializationFailure # Was: Pass
inference/instantiate_tearoff_after_contravariance_check: TextSerializationFailure # Was: Pass
@@ -970,14 +722,11 @@
inference/instantiate_to_bounds_invoke_constructor_no_bound: TextSerializationFailure # Was: Pass
inference/instantiate_to_bounds_invoke_constructor_type_args_exact: TextSerializationFailure # Was: Pass
inference/instantiate_to_bounds_not_generic: TextSerializationFailure # Was: Pass
-inference/int_upwards_local: TextSerializationFailure # Was: Pass
inference/lambda_does_not_have_propagated_type_hint: TextSerializationFailure # Was: Pass
inference/lambda_return_type: TextSerializationFailure # Was: Pass
inference/lambda_void_context: TextSerializationFailure # Was: Pass
-inference/list_literal_typed: TextSerializationFailure # Was: Pass
inference/list_literals: TextSerializationFailure # Was: Pass
inference/list_literals_can_infer_null_bottom: TextSerializationFailure # Was: Pass
-inference/list_literals_top_level: TextSerializationFailure # Was: Pass
inference/local_constructor_from_arguments: TextSerializationFailure # Was: Pass
inference/local_reference_upwards_local: TextSerializationFailure # Was: Pass
inference/local_return_and_yield: TextSerializationFailure # Was: Pass
@@ -1002,7 +751,6 @@
inference/mixin_inference_unification_2: TypeCheckError
inference/no_error_when_declared_type_is_num_and_assigned_null: TextSerializationFailure # Was: Pass
inference/non_const_invocation: TextSerializationFailure # Was: Pass
-inference/non_inferrable_getter_setter: TextSerializationFailure # Was: Pass
inference/null_aware_method_invocation: TextSerializationFailure # Was: Pass
inference/null_aware_property_get: TextSerializationFailure # Was: Pass
inference/null_coalescing_operator: TextSerializationFailure # Was: Pass
@@ -1012,7 +760,6 @@
inference/override_equals: TextSerializationFailure # Was: RuntimeError
inference/override_inference_depends_on_field_inference: TextSerializationFailure
inference/override_inference_with_type_parameters: TextSerializationFailure
-inference/parameter_defaults_downwards: TextSerializationFailure # Was: Pass
inference/parameter_defaults_upwards: TextSerializationFailure # Was: Pass
inference/promote_bounds: TextSerializationFailure # Was: Pass
inference/promote_from_logical_rhs: TextSerializationFailure # Was: Pass
@@ -1022,39 +769,23 @@
inference/propagate_inference_transitively2: TextSerializationFailure # Was: Pass
inference/propagate_inference_transitively: TextSerializationFailure # Was: Pass
inference/propagate_variable_get: TextSerializationFailure # Was: Pass
-inference/property_get_toplevel: TextSerializationFailure # Was: Pass
inference/property_set: TextSerializationFailure # Was: Pass
inference/property_set_bad_setter: TextSerializationFailure # Was: Pass
inference/recursive_generic_function: TextSerializationFailure # Was: Pass
-inference/reference_to_typedef: TextSerializationFailure # Was: Pass
inference/refine_binary_expression_type_type_parameter_t_double: TextSerializationFailure # Was: Pass
inference/refine_binary_expression_type_type_parameter_t_int: TextSerializationFailure # Was: Pass
inference/refine_binary_expression_type_type_parameter_t_t: TextSerializationFailure # Was: Pass
-inference/setter_return_type: TextSerializationFailure # Was: Pass
-inference/simple_literal_bool: TextSerializationFailure # Was: Pass
-inference/simple_literal_double: TextSerializationFailure # Was: Pass
-inference/simple_literal_int: TextSerializationFailure # Was: Pass
-inference/simple_literal_null: TextSerializationFailure
-inference/static_method_tear_off: TextSerializationFailure # Was: Pass
inference/string_literal: TextSerializationFailure # Was: Pass
-inference/subexpressions_of_explicitly_typed_fields: TextSerializationFailure # Was: Pass
inference/super_index_set: TextSerializationFailure # Was: Pass
inference/super_index_set_substitution: TextSerializationFailure # Was: Pass
inference/super_initializer: TextSerializationFailure # Was: Pass
inference/super_initializer_substitution: TextSerializationFailure # Was: Pass
-inference/super_method_invocation: TextSerializationFailure # Was: Pass
inference/super_method_invocation_substitution: TextSerializationFailure # Was: Pass
-inference/super_property_get: TextSerializationFailure # Was: Pass
-inference/super_property_get_invoke_function_typed: TextSerializationFailure # Was: Pass
-inference/super_property_get_invoke_implicit_call: TextSerializationFailure # Was: Pass
inference/super_property_get_substitution: TextSerializationFailure # Was: Pass
-inference/super_property_get_tearoff: TextSerializationFailure # Was: Pass
inference/super_property_set_substitution: TextSerializationFailure # Was: Pass
inference/switch_continue: TextSerializationFailure # Was: Pass
-inference/symbol_literal: TextSerializationFailure # Was: Pass
inference/this_reference: TextSerializationFailure # Was: Pass
inference/top_level_return_and_yield: TextSerializationFailure # Was: Pass
-inference/toplevel_inference_toplevel_var: TextSerializationFailure # Was: Pass
inference/try_catch: TextSerializationFailure # Was: Pass
inference/try_catch_finally: TextSerializationFailure # Was: Pass
inference/try_catch_promotion: TextSerializationFailure # Was: Pass
@@ -1067,11 +798,9 @@
inference/type_promotion_stopped_by_assignment_in_scope: TextSerializationFailure # Was: Pass
inference/type_promotion_stopped_by_mutation_in_a_closure: TextSerializationFailure # Was: Pass
inference/unresolved_super: TextSerializationFailure
-inference/unsafe_block_closure_inference_closure_call: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_constructor_call_explicit_dynamic_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_constructor_call_explicit_type_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_constructor_call_implicit_type_param: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_constructor_call_no_type_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: TextSerializationFailure
inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: TextSerializationFailure
@@ -1080,27 +809,15 @@
inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: TextSerializationFailure
inference/unsafe_block_closure_inference_function_call_implicit_type_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_function_call_no_type_param: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_in_list_dynamic: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_in_list_typed: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_in_list_untyped: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_in_map_dynamic: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_in_map_typed: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_in_map_untyped: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_method_call_explicit_type_param: TextSerializationFailure # Was: Pass
inference/unsafe_block_closure_inference_method_call_implicit_type_param: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_method_call_no_type_param: TextSerializationFailure # Was: Pass
inference/void_return_type_subtypes_dynamic: TextSerializationFailure # Was: Pass
inference_new/const_invocation: TextSerializationFailure # Was: Pass
inference_new/dependency_only_if_generic_method: TextSerializationFailure # Was: Pass
-inference_new/dependency_only_if_overloaded: TextSerializationFailure # Was: Pass
-inference_new/dependency_only_if_overloaded: TypeCheckError
inference_new/do_loop: TextSerializationFailure # Was: Pass
inference_new/downwards_inference_inside_top_level: TextSerializationFailure # Was: Pass
inference_new/downwards_inference_inside_top_level_2: TextSerializationFailure # Was: Pass
-inference_new/field_inference_circularity: TextSerializationFailure # Was: Pass
inference_new/for_each_identifier_downwards: TextSerializationFailure # Was: Pass
inference_new/for_each_invalid_iterable: TextSerializationFailure # Was: Pass
inference_new/for_each_outer_var_type: TextSerializationFailure # Was: Pass
@@ -1125,39 +842,24 @@
inference_new/infer_assign_to_property_super: TextSerializationFailure # Was: Pass
inference_new/infer_assign_to_property_super_upwards: TextSerializationFailure # Was: Pass
inference_new/infer_assign_to_property_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_ref: TextSerializationFailure # Was: Pass
inference_new/infer_assign_to_static: TextSerializationFailure # Was: Pass
inference_new/infer_assign_to_static_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_field_getter_setter_mismatch: TextSerializationFailure
-inference_new/infer_field_override_accessors: TextSerializationFailure
-inference_new/infer_field_override_getter_overrides_setter: TextSerializationFailure
-inference_new/infer_field_override_setter_overrides_getter: TextSerializationFailure # Was: Pass
inference_new/infer_instance_accessor_ref: TextSerializationFailure # Was: Pass
inference_new/infer_instance_field_ref: TextSerializationFailure # Was: Pass
-inference_new/infer_instance_field_ref_circular: TextSerializationFailure # Was: Pass
inference_new/infer_logical: TextSerializationFailure # Was: Pass
-inference_new/infer_use_of_void: TextSerializationFailure # Was: Pass
inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
-inference_new/list_literals_can_infer_null_top_level: TextSerializationFailure # Was: Pass
-inference_new/map_literals_can_infer_null_top_level: TextSerializationFailure # Was: Pass
inference_new/multiple_interface_inheritance: TextSerializationFailure # Was: Pass
inference_new/null_aware_property_get: TextSerializationFailure
inference_new/property_assign_combiner: TextSerializationFailure # Was: Pass
-inference_new/property_get_toplevel: TextSerializationFailure # Was: Pass
inference_new/static_assign_combiner: TextSerializationFailure # Was: Pass
-inference_new/strongly_connected_component: TextSerializationFailure # Was: Pass
-inference_new/strongly_connected_component: TypeCheckError
inference_new/super_index_get: TextSerializationFailure # Was: Pass
inference_new/super_index_get_substitution: TextSerializationFailure # Was: Pass
inference_new/switch: TextSerializationFailure # Was: Pass
-inference_new/top_level_field_depends_on_multiple_inheritance: ExpectationFileMismatch
-inference_new/top_level_field_depends_on_multiple_inheritance: TextSerializationFailure # Was: Pass
inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: TextSerializationFailure # Was: Pass
inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: TextSerializationFailure # Was: Pass
inference_new/void_return_type_subtypes_dynamic: TextSerializationFailure # Was: Pass
inference_new/while_loop: TextSerializationFailure # Was: Pass
instantiate_to_bound/all_steps: TextSerializationFailure # Was: Pass
-instantiate_to_bound/body_generic_classes_from_dill: TextSerializationFailure # Was: Pass
instantiate_to_bound/body_literal_list: TextSerializationFailure # Was: Pass
instantiate_to_bound/body_literal_list_with_generic_argument: TextSerializationFailure # Was: Pass
instantiate_to_bound/body_literal_map: TextSerializationFailure # Was: Pass
@@ -1178,7 +880,6 @@
instantiate_to_bound/covariant_mutual_dependence_in_literals: TextSerializationFailure # Was: Pass
instantiate_to_bound/dependence: TextSerializationFailure # Was: Pass
instantiate_to_bound/dependence_in_literals: TextSerializationFailure # Was: Pass
-instantiate_to_bound/generic_classes_from_dill: TextSerializationFailure # Was: Pass
instantiate_to_bound/inference_constrained_by_bound: TextSerializationFailure # Was: Pass
instantiate_to_bound/inference_defaults_to_bound: TextSerializationFailure # Was: Pass
instantiate_to_bound/inference_gives_input: TextSerializationFailure # Was: Pass
@@ -1236,7 +937,6 @@
late_lowering/issue40373b: TextSerializationFailure
late_lowering/issue40601: TextSerializationFailure
late_lowering/issue40805: TextSerializationFailure
-late_lowering/issue41436/issue41436: TextSerializationFailure
late_lowering/issue41436b: TextSerializationFailure
late_lowering/issue41436c/issue41436c: TextSerializationFailure
late_lowering/late_field_inference: TextSerializationFailure
@@ -1271,30 +971,23 @@
nnbd/constant_null_is: TextSerializationFailure
nnbd/constants: TextSerializationFailure
nnbd/covariant_equals: TextSerializationFailure
-nnbd/covariant_nnbd_top_merge: TextSerializationFailure
nnbd/definite_assignment_and_completion: TextSerializationFailure
nnbd/definitely_assigned: TextSerializationFailure
nnbd/definitely_unassigned: TextSerializationFailure
nnbd/definitely_unassigned_late_local_variables: TextSerializationFailure
nnbd/demote_closure_types: TextSerializationFailure
-nnbd/export_from_opt_out: TextSerializationFailure
-nnbd/forbidden_supers: TextSerializationFailure
nnbd/forin: TextSerializationFailure
-nnbd/from_agnostic/from_agnostic: TextSerializationFailure
nnbd/function_types: TextSerializationFailure
nnbd/future_or_variables: TextSerializationFailure
-nnbd/generic_override: TextSerializationFailure
nnbd/infer_constraints_from_opt_in: TextSerializationFailure
nnbd/infer_from_late_variable: TextSerializationFailure
nnbd/infer_from_opt_in: TextSerializationFailure
nnbd/infer_from_opt_out: TextSerializationFailure
nnbd/infer_if_null: TextSerializationFailure
nnbd/infer_in_legacy_from_opted_in: TextSerializationFailure
-nnbd/infer_method_types: TextSerializationFailure
nnbd/inheritance_from_opt_in: TypeCheckError
nnbd/inheritance_from_opt_out: TextSerializationFailure
nnbd/intersection_types: TextSerializationFailure
-nnbd/issue39659: TextSerializationFailure
nnbd/issue39822: TextSerializationFailure
nnbd/issue40093: TextSerializationFailure
nnbd/issue40134: TextSerializationFailure
@@ -1310,12 +1003,8 @@
nnbd/issue41210a/issue41210: TextSerializationFailure
nnbd/issue41210b: TextSerializationFailure
nnbd/issue41273: TextSerializationFailure
-nnbd/issue41496: TextSerializationFailure
-nnbd/issue41496b: TextSerializationFailure
nnbd/issue41498: TextSerializationFailure
nnbd/issue41498b: TextSerializationFailure
-nnbd/issue41499: TextSerializationFailure
-nnbd/issue41499b: TextSerializationFailure
nnbd/issue_39286: TextSerializationFailure
nnbd/issue_39286_2: TextSerializationFailure
nnbd/late: TextSerializationFailure
@@ -1324,7 +1013,6 @@
nnbd/list_constructor: TextSerializationFailure
nnbd/literal_from_opt_in: TextSerializationFailure
nnbd/load_library: TextSerializationFailure
-nnbd/member_inheritance_from_opt_in: TextSerializationFailure
nnbd/member_inheritance_from_opt_out: TextSerializationFailure
nnbd/messages_with_types_opt_in: TypeCheckError
nnbd/messages_with_types_opt_out: TypeCheckError
@@ -1336,13 +1024,10 @@
nnbd/never_bound: TextSerializationFailure
nnbd/never_opt_out: TypeCheckError
nnbd/never_receiver: TextSerializationFailure
-nnbd/nnbd_opt_out_language_version: TextSerializationFailure
-nnbd/nnbd_opt_out_language_version_try_to_trick: TextSerializationFailure
nnbd/no_null_shorting: TextSerializationFailure
nnbd/no_null_shorting_explicit_extension: TextSerializationFailure
nnbd/no_null_shorting_extension: TextSerializationFailure
nnbd/non_nullable_field_initialization: TextSerializationFailure
-nnbd/non_nullable_optional: TextSerializationFailure
nnbd/not_definitely_unassigned_late_local_variables: TextSerializationFailure
nnbd/nsm_from_opt_in: TextSerializationFailure
nnbd/null_access: TextSerializationFailure
@@ -1362,20 +1047,13 @@
nnbd/nullable_rhs_of_typedef: TextSerializationFailure
nnbd/opt_out: TextSerializationFailure
nnbd/override_checks: TextSerializationFailure
-nnbd/platform_definite_assignment/main: TextSerializationFailure
-nnbd/platform_nonnullable_fields/main: TextSerializationFailure
-nnbd/platform_optional_parameters/main: TextSerializationFailure
nnbd/potentially_constant_type_as: TextSerializationFailure
nnbd/potentially_constant_type_is: TextSerializationFailure
nnbd/potentially_non_nullable_field: TextSerializationFailure
nnbd/regress_null_aware: TextSerializationFailure
-nnbd/required: TextSerializationFailure
-nnbd/required_name_override: TextSerializationFailure
-nnbd/required_named_parameter: TextSerializationFailure
nnbd/return_late: TextSerializationFailure
nnbd/return_null: TextSerializationFailure
nnbd/shorting_stop: TextSerializationFailure
-nnbd/simple_never: TextSerializationFailure
nnbd/sink_hierarchy: TextSerializationFailure
nnbd/strictly_non_nullable_warnings: TextSerializationFailure
nnbd/substitution_in_inference: TextSerializationFailure
@@ -1388,143 +1066,98 @@
no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in: TextSerializationFailure # Was: Pass
no_such_method_forwarders/abstract_accessors_from_field_one_defined: TextSerializationFailure # Was: Pass
no_such_method_forwarders/abstract_accessors_from_field_with_substitution: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/abstract_interface_nsm_inherited: TextSerializationFailure # Was: Pass
no_such_method_forwarders/abstract_override_abstract_different_type: TextSerializationFailure
no_such_method_forwarders/abstract_override_with_different_signature: TextSerializationFailure
-no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application: TextSerializationFailure # Was: Pass
no_such_method_forwarders/default_argument_values: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/duplicated_abstract_method: TextSerializationFailure # Was: Pass
no_such_method_forwarders/forwarder_propagation: TextSerializationFailure
-no_such_method_forwarders/forwarders_not_assumed_from_mixin: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/interface_with_concrete: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/interface_with_nsm: TextSerializationFailure # Was: Pass
no_such_method_forwarders/multiple_abstract_setters: TextSerializationFailure
-no_such_method_forwarders/no_forwarders_for_abstract_classes: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/no_forwarders_for_abstract_classes_chain: TextSerializationFailure # Was: Pass
no_such_method_forwarders/nsm_inherited: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/nsm_mixed_in: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/private: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/private_module: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/private_same: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/same: TextSerializationFailure # Was: Pass
no_such_method_forwarders/setter_not_shadowed_by_method: TextSerializationFailure # Was: Pass
no_such_method_forwarders/subst_on_forwarder: TextSerializationFailure # Was: Pass
-nonfunction_type_aliases/issue41501: TextSerializationFailure
-rasta/abstract_constructor: TextSerializationFailure # Was: RuntimeError
-rasta/bad_constructor_redirection: TextSerializationFailure # Was: RuntimeError
-rasta/bad_continue: TextSerializationFailure # Was: RuntimeError
-rasta/bad_default_constructor: TextSerializationFailure
-rasta/bad_explicit_super_constructor: TextSerializationFailure # Was: RuntimeError
-rasta/bad_implicit_super_constructor: TextSerializationFailure # Was: RuntimeError
+rasta/abstract_constructor: RuntimeError
+rasta/bad_constructor_redirection: RuntimeError
+rasta/bad_continue: RuntimeError
+rasta/bad_default_constructor: RuntimeError
+rasta/bad_explicit_super_constructor: RuntimeError
+rasta/bad_implicit_super_constructor: RuntimeError
rasta/bad_interpolation: RuntimeError
rasta/bad_interpolation: TextSerializationFailure # Was: RuntimeError
-rasta/bad_redirection: TextSerializationFailure # Was: RuntimeError
-rasta/bad_setter_initializer: TextSerializationFailure # Was: RuntimeError
-rasta/breaking_bad: TextSerializationFailure # Was: RuntimeError
+rasta/bad_redirection: RuntimeError
+rasta/bad_setter_initializer: RuntimeError
+rasta/breaking_bad: RuntimeError
rasta/cascades: TextSerializationFailure # Was: Pass
-rasta/class_hierarchy: TextSerializationFailure # Was: RuntimeError
-rasta/class_member: TextSerializationFailure # Was: RuntimeError
-rasta/constant_get_and_invoke: TextSerializationFailure # Was: RuntimeError
+rasta/class_hierarchy: RuntimeError
+rasta/class_member: RuntimeError
+rasta/constant_get_and_invoke: RuntimeError
rasta/deferred_lib: TextSerializationFailure # Was: Pass
-rasta/deferred_load: TextSerializationFailure # Was: Pass
-rasta/duplicated_mixin: TextSerializationFailure # Was: RuntimeError # Expected, this file has no main method.
+rasta/duplicated_mixin: RuntimeError
rasta/enum: TextSerializationFailure # Was: Pass
rasta/export: RuntimeError
rasta/export: TextSerializationFailure # Was: RuntimeError # Expected, this file has no main method.
-rasta/external_factory_redirection: TextSerializationFailure # Was: Pass
rasta/foo: RuntimeError
rasta/foo: TextSerializationFailure # Was: RuntimeError # Expected, this file has no main method.
rasta/for_loop: TextSerializationFailure # Was: Pass
rasta/generic_factory: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000001: TextSerializationFailure # Was: RuntimeError
+rasta/issue_000001: RuntimeError
rasta/issue_000002: TextSerializationFailure # Was: Pass
rasta/issue_000004: TextSerializationFailure # Was: Pass
-rasta/issue_000006: TextSerializationFailure # Was: Pass
-rasta/issue_000007: TextSerializationFailure # Was: Pass
rasta/issue_000008: TextSerializationFailure # Was: Pass
-rasta/issue_000011: TextSerializationFailure # Was: Pass
-rasta/issue_000012: TextSerializationFailure # Was: Pass
-rasta/issue_000025: TextSerializationFailure # Was: Pass
-rasta/issue_000026: TextSerializationFailure # Was: Pass
rasta/issue_000031: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000032: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000034: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000035: TextSerializationFailure # Was: Pass
-rasta/issue_000035a: TextSerializationFailure # Was: Pass
+rasta/issue_000032: RuntimeError
+rasta/issue_000034: RuntimeError
rasta/issue_000036: RuntimeError
rasta/issue_000036: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000039: TextSerializationFailure
-rasta/issue_000041: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000042: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000043: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000044: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000046: TextSerializationFailure # Was: RuntimeError
+rasta/issue_000039: RuntimeError
+rasta/issue_000041: RuntimeError
+rasta/issue_000042: RuntimeError
+rasta/issue_000043: RuntimeError
+rasta/issue_000044: RuntimeError
+rasta/issue_000046: RuntimeError
rasta/issue_000048: TextSerializationFailure # Was: Pass
rasta/issue_000052: TextSerializationFailure # Was: Pass
-rasta/issue_000053: TextSerializationFailure # Was: Pass
rasta/issue_000067: TextSerializationFailure # Was: Pass
rasta/issue_000068: TextSerializationFailure # Was: Pass
rasta/issue_000069: TextSerializationFailure # Was: Pass
rasta/issue_000070: TextSerializationFailure # Was: Pass
rasta/issue_000080: TextSerializationFailure # Was: Pass
rasta/issue_000081: TextSerializationFailure # Was: RuntimeError
-rasta/malformed_const_constructor: TextSerializationFailure # Was: RuntimeError
+rasta/malformed_const_constructor: RuntimeError
rasta/malformed_function: RuntimeError
rasta/malformed_function: TextSerializationFailure # Was: RuntimeError
-rasta/malformed_function_type: TextSerializationFailure # Was: Pass
-rasta/mandatory_parameter_initializer: TextSerializationFailure
rasta/mixin_library: TypeCheckError
-rasta/native_is_illegal: TextSerializationFailure # Was: RuntimeError
+rasta/native_is_illegal: RuntimeError
rasta/parser_error: TextSerializationFailure # Was: RuntimeError
-rasta/previsit_deferred: TextSerializationFailure # Was: Pass
rasta/static: TextSerializationFailure # Was: RuntimeError
rasta/super: TypeCheckError
rasta/super_initializer: TextSerializationFailure # Was: RuntimeError
rasta/super_mixin: TypeCheckError
rasta/super_operator: TypeCheckError
-rasta/supports_reflection: TextSerializationFailure # Was: Pass
rasta/switch_execution_case_t02: TextSerializationFailure # Was: Pass
-rasta/switch_fall_through: TextSerializationFailure # Was: Pass
rasta/this_invoke: TextSerializationFailure # Was: Pass
-rasta/try_label: TextSerializationFailure
rasta/type_literals: TextSerializationFailure
rasta/type_with_parse_error: TextSerializationFailure # Was: Pass
rasta/typedef: RuntimeError
rasta/typedef: TextSerializationFailure
rasta/unresolved: RuntimeError
rasta/unresolved: TextSerializationFailure # Was: RuntimeError
-rasta/unresolved_constructor: TextSerializationFailure # Was: RuntimeError
+rasta/unresolved_constructor: RuntimeError
rasta/unresolved_for_in: TextSerializationFailure # Was: RuntimeError
rasta/unresolved_recovery: TypeCheckError
regress/issue_29937: TextSerializationFailure # Was: Pass
-regress/issue_29940: TextSerializationFailure # Was: Pass
-regress/issue_29941: TextSerializationFailure # Was: Pass
regress/issue_29942: TextSerializationFailure # Was: Pass
-regress/issue_29944: TextSerializationFailure # Was: Pass
-regress/issue_29945: TextSerializationFailure
regress/issue_29976: RuntimeError
regress/issue_29976: TextSerializationFailure # Was: RuntimeError # Tests runtime behavior of error recovery.
regress/issue_29978: TextSerializationFailure # Was: Pass
regress/issue_29979: TextSerializationFailure # Was: Pass
-regress/issue_29980: TextSerializationFailure
regress/issue_29981: TextSerializationFailure # Was: Pass
regress/issue_29982: TextSerializationFailure # Was: RuntimeError # Tests runtime behavior of error recovery.
-regress/issue_29983: TextSerializationFailure # Was: Pass
-regress/issue_29984: TextSerializationFailure # Was: Pass
-regress/issue_29986: TextSerializationFailure
regress/issue_30834: TextSerializationFailure # Was: Pass
-regress/issue_30836: TextSerializationFailure # Was: RuntimeError # Issue 30836.
+regress/issue_30836: RuntimeError
regress/issue_30838: TextSerializationFailure # Was: Pass
-regress/issue_30981: TextSerializationFailure # Was: Pass
-regress/issue_31155: TextSerializationFailure # Was: Pass
-regress/issue_31171: TextSerializationFailure # Was: Pass
regress/issue_31181: TextSerializationFailure # Was: Pass
-regress/issue_31183: TextSerializationFailure # Was: Pass
regress/issue_31184: TextSerializationFailure # Was: Pass
regress/issue_31185: TextSerializationFailure # Was: Pass
regress/issue_31190: TextSerializationFailure # Was: Pass
-regress/issue_31192: TextSerializationFailure # Was: Pass
-regress/issue_31198: TextSerializationFailure # Was: Pass
regress/issue_31213: TextSerializationFailure # Was: Pass
regress/issue_31299: TypeCheckError
regress/issue_31766: TextSerializationFailure # Was: Pass
@@ -1538,31 +1171,24 @@
regress/issue_33452: TextSerializationFailure # Was: RuntimeError # Test has an intentional error
regress/issue_33672: TextSerializationFailure # Was: Pass
regress/issue_34225: TextSerializationFailure # Was: RuntimeError
-regress/issue_34291: TextSerializationFailure # Was: Pass
regress/issue_34291_lib: TextSerializationFailure # Was: Pass
regress/issue_34403: TextSerializationFailure # Was: Pass
regress/issue_34403_lib: TextSerializationFailure # Was: Pass
regress/issue_34498: TextSerializationFailure # Was: Pass
regress/issue_34498_lib: TextSerializationFailure # Was: Pass
-regress/issue_34563: TextSerializationFailure # Was: RuntimeError # Test execution after recovery
-regress/issue_34610: TextSerializationFailure # Was: Pass
+regress/issue_34563: RuntimeError
regress/issue_34614: TextSerializationFailure # Was: Pass
-regress/issue_34850: TextSerializationFailure # Was: Pass
-regress/issue_35151: TextSerializationFailure # Was: Pass
regress/issue_35177: TextSerializationFailure # Was: RuntimeError
-regress/issue_35213: TextSerializationFailure # Was: Pass
-regress/issue_35220: TextSerializationFailure
-regress/issue_35258: TextSerializationFailure # Was: RuntimeError # Expected
-regress/issue_35259: TextSerializationFailure # Was: RuntimeError # Expected
-regress/issue_35260: TextSerializationFailure # Was: RuntimeError # Expected
+regress/issue_35258: RuntimeError
+regress/issue_35259: RuntimeError
+regress/issue_35260: RuntimeError
regress/issue_35266: TextSerializationFailure # Was: RuntimeError # Expected
regress/issue_35900: TextSerializationFailure
-regress/issue_36400: TextSerializationFailure
-regress/issue_36647: TextSerializationFailure
-regress/issue_36647_2: TextSerializationFailure
-regress/issue_36669: TextSerializationFailure
-regress/issue_36793: TextSerializationFailure
-regress/issue_37285: TextSerializationFailure
+regress/issue_36400: RuntimeError
+regress/issue_36647: RuntimeError
+regress/issue_36647_2: RuntimeError
+regress/issue_36669: RuntimeError
+regress/issue_37285: RuntimeError
regress/issue_37681: TextSerializationFailure
regress/issue_39035.crash: RuntimeError
regress/issue_39035.crash: TextSerializationFailure
@@ -1573,6 +1199,7 @@
regress/issue_39682: TextSerializationFailure
regress/issue_41265.crash: TextSerializationFailure
runtime_checks/call_kinds: TextSerializationFailure # Was: Pass
+regress/utf_16_le_content.crash: Crash
runtime_checks/call_kinds_get: TextSerializationFailure # Was: Pass
runtime_checks/call_kinds_set: TextSerializationFailure # Was: Pass
runtime_checks/call_method_implicit_tear_off: TextSerializationFailure # Was: Pass
@@ -1594,10 +1221,6 @@
runtime_checks/covariant_generic_parameter_in_interface_super_mixin: TextSerializationFailure # Was: Pass
runtime_checks/covariant_generic_parameter_tear_off: TextSerializationFailure # Was: Pass
runtime_checks/covariant_keyword: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_field: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_field_inherited_by_setter: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_setter: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_setter_inherited_by_field: TextSerializationFailure # Was: Pass
runtime_checks/covariant_setter: TextSerializationFailure # Was: Pass
runtime_checks/dynamic_invocation: TextSerializationFailure # Was: Pass
runtime_checks/dynamic_invocation_generic: TextSerializationFailure # Was: Pass
@@ -1630,7 +1253,6 @@
runtime_checks_new/field_forwarding_stub_explicit_covariant: TextSerializationFailure # Was: Pass
runtime_checks_new/for_in_call_kinds: TextSerializationFailure # Was: Pass
runtime_checks_new/generic_covariance_based_on_inference: TextSerializationFailure # Was: Pass
-runtime_checks_new/implicit_downcast_field: TextSerializationFailure # Was: Pass
runtime_checks_new/mixin_forwarding_stub_field: ExpectationFileMismatch
runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError
@@ -1643,13 +1265,10 @@
runtime_checks_new/stub_from_interface_covariantImpl_from_super: TextSerializationFailure # Was: Pass
runtime_checks_new/stub_from_interface_covariantInterface_from_class: TextSerializationFailure # Was: Pass
runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializationFailure # Was: Pass
-runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
top_level_variance_test: TextSerializationFailure
-triple_shift/invalid_operator: TextSerializationFailure
unified_collections/mixed_entries: TextSerializationFailure
unified_collections/string_concatenation: TextSerializationFailure
variance/class_type_parameter_modifier: TextSerializationFailure
variance/generic_covariance_sound_variance: TextSerializationFailure
-variance/mixin_type_parameter_modifier: TextSerializationFailure
variance/unconstrained_inference: TextSerializationFailure
diff --git a/pkg/front_end/tool/_fasta/additional_targets_test.dart b/pkg/front_end/tool/_fasta/additional_targets_test.dart
index 041a363..daffd49 100644
--- a/pkg/front_end/tool/_fasta/additional_targets_test.dart
+++ b/pkg/front_end/tool/_fasta/additional_targets_test.dart
@@ -6,6 +6,8 @@
import 'package:kernel/target/targets.dart' show targets;
+import 'package:front_end/src/base/command_line_options.dart';
+
import 'package:front_end/src/fasta/fasta_codes.dart'
show MessageCode, messageFastaUsageLong;
@@ -13,7 +15,8 @@
main() {
installAdditionalTargets();
- String expected = " --target=${(targets.keys.toList()..sort()).join('|')}";
+ String expected =
+ " ${Flags.target}=${(targets.keys.toList()..sort()).join('|')}";
MessageCode code = messageFastaUsageLong;
if (!code.message.contains(expected)) {
throw "Error: ${code.name} in pkg/front_end/messages.yaml doesn't contain"
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 392a4d3..811f854 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -44,7 +44,7 @@
messageFastaUsageShort,
templateUnspecified;
-import 'package:front_end/src/fasta/problems.dart' show DebugAbort, unhandled;
+import 'package:front_end/src/fasta/problems.dart' show DebugAbort;
import 'package:front_end/src/fasta/resolve_input_uri.dart'
show resolveInputUri;
@@ -104,8 +104,8 @@
/// All other options require an option value, either on the form `--option
/// value` or `--option=value`.
static ParsedArguments parse(
- List<String> arguments, Map<String, dynamic> specification) {
- specification ??= const <String, dynamic>{};
+ List<String> arguments, Map<String, ValueSpecification> specification) {
+ specification ??= const <String, ValueSpecification>{};
ParsedArguments result = new ParsedArguments();
int index = arguments.indexOf("--");
Iterable<String> nonOptions = const <String>[];
@@ -128,26 +128,21 @@
argument = argument.substring(0, index);
}
}
- var valueSpecification = specification[argument];
+ ValueSpecification valueSpecification = specification[argument];
if (valueSpecification == null) {
throw new CommandLineProblem.deprecated(
"Unknown option '$argument'.");
}
String canonicalArgument = argument;
- if (valueSpecification is String &&
- valueSpecification != "," &&
- valueSpecification != "<define>") {
- canonicalArgument = valueSpecification;
- valueSpecification = specification[valueSpecification];
+ if (valueSpecification.alias != null) {
+ canonicalArgument = valueSpecification.alias;
+ valueSpecification = specification[valueSpecification.alias];
}
- if (valueSpecification == true || valueSpecification == false) {
- valueSpecification = bool;
+ if (valueSpecification == null) {
+ throw new CommandLineProblem.deprecated(
+ "Unknown option alias '$canonicalArgument'.");
}
- if (valueSpecification is! String && valueSpecification is! Type) {
- throw new CommandLineProblem.deprecated("Unrecognized type of value "
- "specification: ${valueSpecification.runtimeType}.");
- }
- final bool requiresValue = valueSpecification != bool;
+ final bool requiresValue = valueSpecification.requiresValue;
if (requiresValue && value == null) {
if (!iterator.moveNext()) {
throw new CommandLineProblem(
@@ -155,84 +150,15 @@
}
value = iterator.current;
}
- switch ("$valueSpecification") {
- case ",":
- result.options
- .putIfAbsent(argument, () => <String>[])
- .addAll(value.split(","));
- break;
-
- case "<define>":
- int index = value.indexOf('=');
- String name;
- String expression;
- if (index != -1) {
- name = value.substring(0, index);
- expression = value.substring(index + 1);
- } else {
- name = value;
- expression = value;
- }
- result.defines[name] = expression;
- break;
-
- case "int":
- case "bool":
- case "String":
- case "Uri":
- if (result.options.containsKey(canonicalArgument)) {
- return throw new CommandLineProblem.deprecated(
- "Multiple values for '$argument': "
- "'${result.options[canonicalArgument]}' and '$value'.");
- }
- var parsedValue;
- if (valueSpecification == int) {
- parsedValue = int.tryParse(value);
- if (parsedValue == null) {
- return throw new CommandLineProblem.deprecated(
- "Value for '$argument', '$value', isn't an int.");
- }
- } else if (valueSpecification == bool) {
- if (value == null || value == "true" || value == "yes") {
- parsedValue = true;
- } else if (value == "false" || value == "no") {
- parsedValue = false;
- } else {
- return throw new CommandLineProblem.deprecated(
- "Value for '$argument' is '$value', "
- "but expected one of: 'true', 'false', 'yes', or 'no'.");
- }
- } else if (valueSpecification == Uri) {
- // TODO(ahe): resolve Uris lazily, so that schemes provided by
- // other flags can be used for parsed command-line arguments too.
- parsedValue = resolveInputUri(value);
- } else if (valueSpecification == String) {
- parsedValue = value;
- } else if (valueSpecification is String) {
- return throw new CommandLineProblem.deprecated(
- "Unrecognized value specification: "
- "'$valueSpecification', try using a type literal instead.");
- } else {
- // All possible cases should have been handled above.
- return unhandled("${valueSpecification.runtimeType}",
- "CommandLine.parse", -1, null);
- }
- result.options[canonicalArgument] = parsedValue;
- break;
-
- default:
- return throw new CommandLineProblem.deprecated(
- "Unrecognized value specification: '$valueSpecification'.");
- }
+ valueSpecification.processValue(
+ result, canonicalArgument, argument, value);
} else {
result.arguments.add(argument);
}
}
- specification.forEach((String key, value) {
- if (value == bool) {
- result.options[key] ??= false;
- } else if (value is bool) {
- result.options[key] ??= value;
+ specification.forEach((String key, ValueSpecification value) {
+ if (value.defaultValue != null) {
+ result.options[key] ??= value.defaultValue;
}
});
result.arguments.addAll(nonOptions);
@@ -243,76 +169,72 @@
// Before adding new options here, you must:
// * Document the option.
// * Get an explicit approval from the front-end team.
-const Map<String, dynamic> optionSpecification = const <String, dynamic>{
- "--bytecode": false,
- "--compile-sdk": Uri,
- "--dump-ir": false,
- "--enable-experiment": ",",
- "--exclude-source": false,
- "--omit-platform": false,
- "--fatal": ",",
- "--fatal-skip": String,
- Flags.forceLateLowering: false,
- Flags.forceNoExplicitGetterCalls: false,
- "--help": false,
- // TODO(johnniwinther): Remove legacy option flags. Legacy mode is no longer
- // supported.
- "--legacy": "--legacy-mode",
- "--legacy-mode": false,
- "--libraries-json": Uri,
- "--no-defines": false,
- "--output": Uri,
- "--packages": Uri,
- "--platform": Uri,
- "--sdk": Uri,
- "--single-root-base": Uri,
- "--single-root-scheme": String,
- Flags.nnbdStrongMode: false,
- Flags.nnbdAgnosticMode: false,
- "--supermixin": true,
- Flags.target: String,
- "--enable-asserts": false,
- "--verbose": false,
- "--verify": false,
- "-D": "<define>",
- "-h": "--help",
- "-o": "--output",
- "-t": "--target",
- "-v": "--verbose",
- "/?": "--help",
- "/h": "--help",
+const Map<String, ValueSpecification> optionSpecification =
+ const <String, ValueSpecification>{
+ Flags.bytecode: const BoolValue(false),
+ Flags.compileSdk: const UriValue(),
+ Flags.dumpIr: const BoolValue(false),
+ Flags.enableExperiment: const StringListValue(),
+ Flags.excludeSource: const BoolValue(false),
+ Flags.omitPlatform: const BoolValue(false),
+ Flags.fatal: const StringListValue(),
+ Flags.fatalSkip: const StringValue(),
+ Flags.forceLateLowering: const BoolValue(false),
+ Flags.forceNoExplicitGetterCalls: const BoolValue(false),
+ Flags.help: const BoolValue(false),
+ Flags.librariesJson: const UriValue(),
+ Flags.noDefines: const BoolValue(false),
+ Flags.output: const UriValue(),
+ Flags.packages: const UriValue(),
+ Flags.platform: const UriValue(),
+ Flags.sdk: const UriValue(),
+ Flags.singleRootBase: const UriValue(),
+ Flags.singleRootScheme: const StringValue(),
+ Flags.nnbdStrongMode: const BoolValue(false),
+ Flags.nnbdAgnosticMode: const BoolValue(false),
+ Flags.target: const StringValue(),
+ Flags.verbose: const BoolValue(false),
+ Flags.verify: const BoolValue(false),
+ Flags.linkDependencies: const UriListValue(),
+ "-D": const DefineValue(),
+ "-h": const AliasValue(Flags.help),
+ "--out": const AliasValue(Flags.output),
+ "-o": const AliasValue(Flags.output),
+ "-t": const AliasValue(Flags.target),
+ "-v": const AliasValue(Flags.verbose),
+ "/?": const AliasValue(Flags.help),
+ "/h": const AliasValue(Flags.help),
};
void throwCommandLineProblem(String message) {
throw new CommandLineProblem.deprecated(message);
}
-ProcessedOptions analyzeCommandLine(
- String programName,
- ParsedArguments parsedArguments,
- bool areRestArgumentsInputs,
- bool verbose) {
+ProcessedOptions analyzeCommandLine(String programName,
+ ParsedArguments parsedArguments, bool areRestArgumentsInputs) {
final Map<String, dynamic> options = parsedArguments.options;
final List<String> arguments = parsedArguments.arguments;
- final bool help = options["--help"];
+ final bool help = options[Flags.help];
+
+ final bool verbose = options[Flags.verbose];
if (help) {
print(computeUsage(programName, verbose).message);
exit(0);
}
- if (options.containsKey("--compile-sdk") &&
- options.containsKey("--platform")) {
+ if (options.containsKey(Flags.compileSdk) &&
+ options.containsKey(Flags.platform)) {
return throw new CommandLineProblem.deprecated(
- "Can't specify both '--compile-sdk' and '--platform'.");
+ "Can't specify both '${Flags.compileSdk}' and '${Flags.platform}'.");
}
- final String targetName = options["--target"] ?? "vm";
+ final String targetName = options[Flags.target] ?? "vm";
Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags(
- parseExperimentalArguments(options["--enable-experiment"]),
+ parseExperimentalArguments(options[Flags.enableExperiment]),
onError: throwCommandLineProblem,
onWarning: print);
@@ -331,33 +253,33 @@
"Valid targets are:\n ${targets.keys.join("\n ")}");
}
- final bool noDefines = options["--no-defines"];
+ final bool noDefines = options[Flags.noDefines];
- final bool verify = options["--verify"];
+ final bool verify = options[Flags.verify];
- final bool dumpIr = options["--dump-ir"];
+ final bool dumpIr = options[Flags.dumpIr];
- final bool excludeSource = options["--exclude-source"];
+ final bool excludeSource = options[Flags.excludeSource];
- final bool omitPlatform = options["--omit-platform"];
+ final bool omitPlatform = options[Flags.omitPlatform];
- final Uri packages = options["--packages"];
+ final Uri packages = options[Flags.packages];
final Set<String> fatal =
- new Set<String>.from(options["--fatal"] ?? <String>[]);
+ new Set<String>.from(options[Flags.fatal] ?? <String>[]);
final bool errorsAreFatal = fatal.contains("errors");
final bool warningsAreFatal = fatal.contains("warnings");
- final int fatalSkip = int.tryParse(options["--fatal-skip"] ?? "0") ?? -1;
+ final int fatalSkip = int.tryParse(options[Flags.fatalSkip] ?? "0") ?? -1;
- final bool bytecode = options["--bytecode"];
+ final bool bytecode = options[Flags.bytecode];
- final bool compileSdk = options.containsKey("--compile-sdk");
+ final bool compileSdk = options.containsKey(Flags.compileSdk);
- final String singleRootScheme = options["--single-root-scheme"];
- final Uri singleRootBase = options["--single-root-base"];
+ final String singleRootScheme = options[Flags.singleRootScheme];
+ final Uri singleRootBase = options[Flags.singleRootBase];
final bool nnbdStrongMode = options[Flags.nnbdStrongMode];
@@ -367,6 +289,8 @@
? NnbdMode.Agnostic
: (nnbdStrongMode ? NnbdMode.Strong : NnbdMode.Weak);
+ final List<Uri> linkDependencies = options[Flags.linkDependencies] ?? [];
+
if (nnbdStrongMode && nnbdAgnosticMode) {
return throw new CommandLineProblem.deprecated(
"Can't specify both '${Flags.nnbdStrongMode}' and "
@@ -386,6 +310,24 @@
});
}
+ CompilerOptions compilerOptions = new CompilerOptions()
+ ..compileSdk = compileSdk
+ ..fileSystem = fileSystem
+ ..packagesFileUri = packages
+ ..target = target
+ ..throwOnErrorsForDebugging = errorsAreFatal
+ ..throwOnWarningsForDebugging = warningsAreFatal
+ ..skipForDebugging = fatalSkip
+ ..embedSourceText = !excludeSource
+ ..debugDump = dumpIr
+ ..omitPlatform = omitPlatform
+ ..verbose = verbose
+ ..verify = verify
+ ..experimentalFlags = experimentalFlags
+ ..environmentDefines = noDefines ? null : parsedArguments.defines
+ ..nnbdMode = nnbdMode
+ ..additionalDills = linkDependencies;
+
if (programName == "compile_platform") {
if (arguments.length != 5) {
return throw new CommandLineProblem.deprecated(
@@ -393,33 +335,19 @@
}
if (compileSdk) {
return throw new CommandLineProblem.deprecated(
- "Cannot specify '--compile-sdk' option to compile_platform.");
+ "Cannot specify '${Flags.compileSdk}' option to compile_platform.");
}
- if (options.containsKey("--output")) {
+ if (options.containsKey(Flags.output)) {
return throw new CommandLineProblem.deprecated(
- "Cannot specify '--output' option to compile_platform.");
+ "Cannot specify '${Flags.output}' option to compile_platform.");
}
return new ProcessedOptions(
- options: new CompilerOptions()
- ..sdkSummary = options["--platform"]
+ options: compilerOptions
+ ..sdkSummary = options[Flags.platform]
..librariesSpecificationUri = resolveInputUri(arguments[1])
..setExitCodeOnProblem = true
- ..fileSystem = fileSystem
- ..packagesFileUri = packages
- ..target = target
- ..throwOnErrorsForDebugging = errorsAreFatal
- ..throwOnWarningsForDebugging = warningsAreFatal
- ..skipForDebugging = fatalSkip
- ..embedSourceText = !excludeSource
- ..debugDump = dumpIr
- ..omitPlatform = omitPlatform
- ..verbose = verbose
- ..verify = verify
- ..bytecode = bytecode
- ..experimentalFlags = experimentalFlags
- ..environmentDefines = noDefines ? null : parsedArguments.defines
- ..nnbdMode = nnbdMode,
+ ..bytecode = bytecode,
inputs: <Uri>[Uri.parse(arguments[0])],
output: resolveInputUri(arguments[3]));
} else if (arguments.isEmpty) {
@@ -428,9 +356,11 @@
final Uri defaultOutput = resolveInputUri("${arguments.first}.dill");
- final Uri output = options["-o"] ?? options["--output"] ?? defaultOutput;
+ final Uri output = options[Flags.output] ?? defaultOutput;
- final Uri sdk = options["--sdk"] ?? options["--compile-sdk"];
+ final Uri sdk = options[Flags.sdk] ?? options[Flags.compileSdk];
+
+ final Uri librariesJson = options[Flags.librariesJson];
String computePlatformDillName() {
switch (target.name) {
@@ -447,38 +377,21 @@
case 'none':
return "vm_platform_strong.dill";
default:
- throwCommandLineProblem(
- 'Target "${target.name}" requires an explicit --platform option.');
+ throwCommandLineProblem("Target '${target.name}' requires an explicit "
+ "'${Flags.platform}' option.");
}
return null;
}
final Uri platform = compileSdk
? null
- : (options["--platform"] ??
+ : (options[Flags.platform] ??
computePlatformBinariesLocation(forceBuildDir: true)
.resolve(computePlatformDillName()));
-
- CompilerOptions compilerOptions = new CompilerOptions()
- ..compileSdk = compileSdk
- ..fileSystem = fileSystem
+ compilerOptions
..sdkRoot = sdk
..sdkSummary = platform
- ..packagesFileUri = packages
- ..target = target
- ..throwOnErrorsForDebugging = errorsAreFatal
- ..throwOnWarningsForDebugging = warningsAreFatal
- ..skipForDebugging = fatalSkip
- ..embedSourceText = !excludeSource
- ..debugDump = dumpIr
- ..omitPlatform = omitPlatform
- ..verbose = verbose
- ..verify = verify
- ..experimentalFlags = experimentalFlags
- ..environmentDefines = noDefines ? null : parsedArguments.defines
- ..nnbdMode = nnbdMode;
-
- // TODO(ahe): What about chase dependencies?
+ ..librariesSpecificationUri = librariesJson;
List<Uri> inputs = <Uri>[];
if (areRestArgumentsInputs) {
@@ -495,21 +408,13 @@
List<String> arguments,
bool areRestArgumentsInputs,
Future<T> f(CompilerContext context, List<String> restArguments)) {
- bool verbose = false;
- for (String argument in arguments) {
- if (argument == "--") break;
- if (argument == "-v" || argument == "--verbose") {
- verbose = true;
- break;
- }
- }
ParsedArguments parsedArguments;
ProcessedOptions options;
CommandLineProblem problem;
try {
parsedArguments = ParsedArguments.parse(arguments, optionSpecification);
options = analyzeCommandLine(
- programName, parsedArguments, areRestArgumentsInputs, verbose);
+ programName, parsedArguments, areRestArgumentsInputs);
} on CommandLineProblem catch (e) {
options = new ProcessedOptions();
problem = e;
@@ -517,7 +422,7 @@
return CompilerContext.runWithOptions<T>(options, (c) {
if (problem != null) {
- print(computeUsage(programName, verbose).message);
+ print(computeUsage(programName, options.verbose).message);
print(c.formatWithoutLocation(problem.message, Severity.error));
exit(1);
}
@@ -580,3 +485,148 @@
}
return failingValue;
}
+
+abstract class ValueSpecification {
+ const ValueSpecification();
+
+ String get alias => null;
+
+ dynamic get defaultValue => null;
+
+ bool get requiresValue => true;
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value);
+}
+
+class AliasValue extends ValueSpecification {
+ final String alias;
+
+ const AliasValue(this.alias);
+
+ bool get requiresValue =>
+ throw new UnsupportedError("AliasValue.requiresValue");
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ throw new UnsupportedError("AliasValue.processValue");
+ }
+}
+
+class UriValue extends ValueSpecification {
+ const UriValue();
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ if (result.options.containsKey(canonicalArgument)) {
+ throw new CommandLineProblem.deprecated(
+ "Multiple values for '$argument': "
+ "'${result.options[canonicalArgument]}' and '$value'.");
+ }
+ // TODO(ahe): resolve Uris lazily, so that schemes provided by
+ // other flags can be used for parsed command-line arguments too.
+ result.options[canonicalArgument] = resolveInputUri(value);
+ }
+}
+
+class StringValue extends ValueSpecification {
+ const StringValue();
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ if (result.options.containsKey(canonicalArgument)) {
+ throw new CommandLineProblem.deprecated(
+ "Multiple values for '$argument': "
+ "'${result.options[canonicalArgument]}' and '$value'.");
+ }
+ result.options[canonicalArgument] = value;
+ }
+}
+
+class BoolValue extends ValueSpecification {
+ final bool defaultValue;
+
+ const BoolValue(this.defaultValue);
+
+ bool get requiresValue => false;
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ if (result.options.containsKey(canonicalArgument)) {
+ throw new CommandLineProblem.deprecated(
+ "Multiple values for '$argument': "
+ "'${result.options[canonicalArgument]}' and '$value'.");
+ }
+ bool parsedValue;
+ if (value == null || value == "true" || value == "yes") {
+ parsedValue = true;
+ } else if (value == "false" || value == "no") {
+ parsedValue = false;
+ } else {
+ throw new CommandLineProblem.deprecated(
+ "Value for '$argument' is '$value', "
+ "but expected one of: 'true', 'false', 'yes', or 'no'.");
+ }
+ result.options[canonicalArgument] = parsedValue;
+ }
+}
+
+class IntValue extends ValueSpecification {
+ const IntValue();
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ if (result.options.containsKey(canonicalArgument)) {
+ throw new CommandLineProblem.deprecated(
+ "Multiple values for '$argument': "
+ "'${result.options[canonicalArgument]}' and '$value'.");
+ }
+ int parsedValue = int.tryParse(value);
+ if (parsedValue == null) {
+ throw new CommandLineProblem.deprecated(
+ "Value for '$argument', '$value', isn't an int.");
+ }
+ result.options[canonicalArgument] = parsedValue;
+ }
+}
+
+class DefineValue extends ValueSpecification {
+ const DefineValue();
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ int index = value.indexOf('=');
+ String name;
+ String expression;
+ if (index != -1) {
+ name = value.substring(0, index);
+ expression = value.substring(index + 1);
+ } else {
+ name = value;
+ expression = value;
+ }
+ result.defines[name] = expression;
+ }
+}
+
+class StringListValue extends ValueSpecification {
+ const StringListValue();
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ result.options
+ .putIfAbsent(canonicalArgument, () => <String>[])
+ .addAll(value.split(","));
+ }
+}
+
+class UriListValue extends ValueSpecification {
+ const UriListValue();
+
+ void processValue(ParsedArguments result, String canonicalArgument,
+ String argument, String value) {
+ result.options
+ .putIfAbsent(canonicalArgument, () => <Uri>[])
+ .addAll(value.split(",").map(resolveInputUri));
+ }
+}
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 9276ee9..1ef0065 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -186,7 +186,7 @@
options.sdkSummaryComponent = platformComponent;
}
CompileTask task = new CompileTask(c, ticker);
- await task.compile(omitPlatform: true);
+ await task.compile(omitPlatform: true, supportAdditionalDills: false);
CanonicalName root = platformComponent.root;
for (Library library in platformComponent.libraries) {
library.parent = platformComponent;
@@ -220,7 +220,7 @@
}
CompileTask task =
new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
- return await task.buildOutline(c.options.output);
+ return await task.buildOutline(output: c.options.output);
});
});
}
@@ -292,15 +292,31 @@
return dFile;
}
- Future<KernelTarget> buildOutline([Uri output]) async {
+ Future<KernelTarget> buildOutline(
+ {Uri output, bool supportAdditionalDills: true}) async {
UriTranslator uriTranslator = await c.options.getUriTranslator();
ticker.logMs("Read packages file");
DillTarget dillTarget = createDillTarget(uriTranslator);
KernelTarget kernelTarget = createKernelTarget(dillTarget, uriTranslator);
- Uri platform = c.options.sdkSummary;
- if (platform != null) {
- _appendDillForUri(dillTarget, platform);
+
+ if (supportAdditionalDills) {
+ Component sdkSummary = await c.options.loadSdkSummary(null);
+ if (sdkSummary != null) {
+ dillTarget.loader.appendLibraries(sdkSummary);
+ }
+
+ CanonicalName nameRoot = sdkSummary?.root ?? new CanonicalName.root();
+ for (Component additionalDill
+ in await c.options.loadAdditionalDills(nameRoot)) {
+ dillTarget.loader.appendLibraries(additionalDill);
+ }
+ } else {
+ Uri platform = c.options.sdkSummary;
+ if (platform != null) {
+ _appendDillForUri(dillTarget, platform);
+ }
}
+
kernelTarget.setEntryPoints(c.options.inputs);
await dillTarget.buildOutlines();
var outline = await kernelTarget.buildOutlines();
@@ -314,8 +330,10 @@
return kernelTarget;
}
- Future<Uri> compile({bool omitPlatform: false}) async {
- KernelTarget kernelTarget = await buildOutline();
+ Future<Uri> compile(
+ {bool omitPlatform: false, bool supportAdditionalDills: true}) async {
+ KernelTarget kernelTarget =
+ await buildOutline(supportAdditionalDills: supportAdditionalDills);
Uri uri = c.options.output;
Component component =
await kernelTarget.buildComponent(verify: c.options.verify);
@@ -347,10 +365,11 @@
/// Load the [Component] from the given [uri] and append its libraries
/// to the [dillTarget].
-void _appendDillForUri(DillTarget dillTarget, Uri uri) {
+Component _appendDillForUri(DillTarget dillTarget, Uri uri) {
var bytes = new File.fromUri(uri).readAsBytesSync();
var platformComponent = loadComponentFromBytes(bytes);
dillTarget.loader.appendLibraries(platformComponent, byteCount: bytes.length);
+ return platformComponent;
}
Future<void> compilePlatform(List<String> arguments) async {
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
index 9d8b634..5b1356b 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
@@ -59,8 +59,9 @@
// Instead modify 'tools/experimental_features.yaml' and run
// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
- int defaultLanguageVersionMajor = $currentVersionMajor;
- int defaultLanguageVersionMinor = $currentVersionMinor;
+import "ast.dart";
+
+Version defaultLanguageVersion = const Version($currentVersionMajor, $currentVersionMinor);
''');
return new DartFormatter().format("$sb");
@@ -91,6 +92,8 @@
//
// Instead modify 'tools/experimental_features.yaml' and run
// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
+
+import 'package:kernel/kernel.dart' show Version;
''');
Map<dynamic, dynamic> features = yaml['features'];
@@ -122,12 +125,9 @@
major = int.parse(split[0]);
minor = int.parse(split[1]);
}
- sb.writeln(' const int enable'
+ sb.writeln(' const Version enable'
'${keyToIdentifier(key, upperCaseFirst: true)}'
- 'MajorVersion = $major;');
- sb.writeln(' const int enable'
- '${keyToIdentifier(key, upperCaseFirst: true)}'
- 'MinorVersion = $minor;');
+ 'Version = const Version($major, $minor);');
}
sb.write('''
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 8ee02d2..1437c1d 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -73,7 +73,8 @@
import 'canonical_name.dart' show CanonicalName;
export 'canonical_name.dart' show CanonicalName;
-import 'default_language_version.dart';
+import 'default_language_version.dart' show defaultLanguageVersion;
+export 'default_language_version.dart' show defaultLanguageVersion;
import 'transformations/flags.dart';
import 'text/ast_to_text.dart' as astToText;
@@ -353,18 +354,14 @@
/// The URI of the source file this library was loaded from.
Uri fileUri;
- int _languageVersionMajor;
- int _languageVersionMinor;
- int get languageVersionMajor =>
- _languageVersionMajor ?? defaultLanguageVersionMajor;
- int get languageVersionMinor =>
- _languageVersionMinor ?? defaultLanguageVersionMinor;
- void setLanguageVersion(int languageVersionMajor, int languageVersionMinor) {
- if (languageVersionMajor == null || languageVersionMinor == null) {
+ Version _languageVersion;
+ Version get languageVersion => _languageVersion ?? defaultLanguageVersion;
+
+ void setLanguageVersion(Version languageVersion) {
+ if (languageVersion == null) {
throw new StateError("Trying to set language version 'null'");
}
- _languageVersionMajor = languageVersionMajor;
- _languageVersionMinor = languageVersionMinor;
+ _languageVersion = languageVersion;
}
static const int SyntheticFlag = 1 << 1;
@@ -9109,3 +9106,65 @@
}
return result;
}
+
+class Version extends Object {
+ final int major;
+ final int minor;
+
+ const Version(this.major, this.minor)
+ : assert(major != null),
+ assert(minor != null);
+
+ bool operator <(Version other) {
+ if (major < other.major) return true;
+ if (major > other.major) return false;
+
+ // Major is the same.
+ if (minor < other.minor) return true;
+ return false;
+ }
+
+ bool operator <=(Version other) {
+ if (major < other.major) return true;
+ if (major > other.major) return false;
+
+ // Major is the same.
+ if (minor <= other.minor) return true;
+ return false;
+ }
+
+ bool operator >(Version other) {
+ if (major > other.major) return true;
+ if (major < other.major) return false;
+
+ // Major is the same.
+ if (minor > other.minor) return true;
+ return false;
+ }
+
+ bool operator >=(Version other) {
+ if (major > other.major) return true;
+ if (major < other.major) return false;
+
+ // Major is the same.
+ if (minor >= other.minor) return true;
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ return major.hashCode * 13 + minor.hashCode * 17;
+ }
+
+ @override
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! Version) return false;
+ return major == other.major && minor == other.minor;
+ }
+
+ @override
+ String toString() {
+ return "Version(major=$major, minor=$minor)";
+ }
+}
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 941c5d5..73b41c5 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -926,7 +926,8 @@
List<String> problemsAsJson = readListOfStrings();
library.flags = flags;
- library.setLanguageVersion(languageVersionMajor, languageVersionMinor);
+ library.setLanguageVersion(
+ new Version(languageVersionMajor, languageVersionMinor));
library.name = name;
library.fileUri = fileUri;
library.problemsAsJson = problemsAsJson;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index c6f6104..93546be 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -955,8 +955,8 @@
libraryOffsets.add(getBufferOffset());
writeByte(node.flags);
- writeUInt30(node.languageVersionMajor);
- writeUInt30(node.languageVersionMinor);
+ writeUInt30(node.languageVersion.major);
+ writeUInt30(node.languageVersion.minor);
writeNonNullCanonicalNameReference(getCanonicalNameOfLibrary(node));
writeStringReference(node.name ?? '');
diff --git a/pkg/kernel/lib/default_language_version.dart b/pkg/kernel/lib/default_language_version.dart
index b5c8df5..4aa2488 100644
--- a/pkg/kernel/lib/default_language_version.dart
+++ b/pkg/kernel/lib/default_language_version.dart
@@ -7,5 +7,6 @@
// Instead modify 'tools/experimental_features.yaml' and run
// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
-int defaultLanguageVersionMajor = 2;
-int defaultLanguageVersionMinor = 9;
+import "ast.dart";
+
+Version defaultLanguageVersion = const Version(2, 9);
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index ead78e9..3f31c54 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -16,8 +16,6 @@
initializeSerializers,
statementSerializer;
-import '../visitor.dart' show Visitor;
-
const Uri noUri = null;
const int noOffset = -1;
@@ -56,7 +54,29 @@
: super(uri, offset);
}
-class TextSerializationVerifier implements Visitor<void> {
+class VerificationStatus {
+ final Node node;
+ int childrenCount = 0;
+ final List<Node> supportedChildren = [];
+
+ VerificationStatus(this.node);
+
+ bool isFullySupported(TextSerializationVerifier verifier) {
+ return verifier.isSupported(node) &&
+ childrenCount == supportedChildren.length;
+ }
+
+ void addChild(Node child, bool isSupported) {
+ ++childrenCount;
+ if (isSupported) supportedChildren.add(child);
+ }
+}
+
+class TextSerializationVerifier extends RecursiveVisitor<void> {
+ static const bool showStackTrace = bool.fromEnvironment(
+ "text_serialization.showStackTrace",
+ defaultValue: false);
+
/// List of errors produced during round trips on the visited nodes.
final List<TextSerializationVerificationFailure> failures =
<TextSerializationVerificationFailure>[];
@@ -67,15 +87,63 @@
int lastSeenOffset = noOffset;
- static const bool showStackTrace = bool.fromEnvironment(
- "text_serialization.showStackTrace",
- defaultValue: false);
+ List<VerificationStatus> _statusStack = [];
TextSerializationVerifier({CanonicalName root})
: root = root ?? new CanonicalName.root() {
initializeSerializers();
}
+ bool get isRoot => _statusStack.isEmpty;
+
+ VerificationStatus get currentStatus => _statusStack.last;
+
+ void pushStatus(VerificationStatus status) {
+ _statusStack.add(status);
+ }
+
+ VerificationStatus popStatus() {
+ return _statusStack.removeLast();
+ }
+
+ void verify(Node node) {}
+
+ void defaultNode(Node node) {
+ enterNode(node);
+ node.visitChildren(this);
+ bool isFullySupported = exitNode(node);
+ if (isFullySupported) {
+ if (node is DartType) {
+ makeRoundTrip<DartType>(node, dartTypeSerializer);
+ } else if (node is Expression) {
+ makeRoundTrip<Expression>(node, expressionSerializer);
+ } else if (node is Statement) {
+ makeRoundTrip<Statement>(node, statementSerializer);
+ } else {
+ throw new StateError(
+ "Don't know how to make a round trip for a supported node '${node.runtimeType}'");
+ }
+ }
+ }
+
+ void enterNode(node) {
+ storeLastSeenUriAndOffset(node);
+ pushStatus(new VerificationStatus(node));
+ }
+
+ bool exitNode(node) {
+ if (!identical(node, currentStatus.node)) {
+ throw new StateError("Trying to remove node '${node}' from the stack, "
+ "while another node '${currentStatus.node}' is on the top of it.");
+ }
+ VerificationStatus status = popStatus();
+ bool isFullySupported = status.isFullySupported(this);
+ if (!isRoot) {
+ currentStatus.addChild(node, isFullySupported);
+ }
+ return isFullySupported;
+ }
+
void storeLastSeenUriAndOffset(Node node) {
if (node is TreeNode) {
Location location = node.location;
@@ -125,951 +193,77 @@
return buffer.toString();
}
- void makeExpressionRoundTrip(Expression node) {
- Uri uri = noUri;
- int offset = noOffset;
- Location location = node.location;
- if (location != null) {
- uri = location.file;
- offset = node.fileOffset;
- }
-
- String initial = writeNode(node, expressionSerializer, uri, offset);
+ void makeRoundTrip<T extends Node>(T node, TextSerializer<T> serializer) {
+ String initial = writeNode(node, serializer, lastSeenUri, lastSeenOffset);
// Do the round trip.
- Expression deserialized =
- readNode(initial, expressionSerializer, uri, offset);
+ T deserialized = readNode(initial, serializer, lastSeenUri, lastSeenOffset);
+
// The error is reported elsewhere for the case of null.
if (deserialized == null) return;
String serialized =
- writeNode(deserialized, expressionSerializer, uri, offset);
+ writeNode(deserialized, serializer, lastSeenUri, lastSeenOffset);
if (initial != serialized) {
- failures.add(new TextRoundTripFailure(initial, serialized, uri, offset));
+ failures.add(new TextRoundTripFailure(
+ initial, serialized, lastSeenUri, lastSeenOffset));
}
}
- void makeDartTypeRoundTrip(DartType node) {
- Uri uri = lastSeenUri;
- int offset = lastSeenOffset;
+ bool isDartTypeSupported(DartType node) =>
+ node is InvalidType ||
+ node is DynamicType ||
+ node is VoidType ||
+ node is BottomType ||
+ node is FunctionType ||
+ node is TypeParameterType;
- String initial = writeNode(node, dartTypeSerializer, uri, offset);
+ bool isExpressionSupported(Expression node) =>
+ node is StringLiteral ||
+ node is SymbolLiteral ||
+ node is IntLiteral ||
+ node is DoubleLiteral ||
+ node is BoolLiteral ||
+ node is NullLiteral ||
+ node is ListLiteral ||
+ node is SetLiteral ||
+ node is MapLiteral ||
+ node is TypeLiteral ||
+ node is InvalidExpression ||
+ node is Not ||
+ node is LogicalExpression ||
+ node is StringConcatenation ||
+ node is ThisExpression ||
+ node is Rethrow ||
+ node is Throw ||
+ node is AwaitExpression ||
+ node is ConditionalExpression ||
+ node is IsExpression ||
+ node is AsExpression ||
+ node is Let ||
+ node is PropertyGet ||
+ node is PropertySet ||
+ node is SuperPropertyGet ||
+ node is SuperPropertySet ||
+ node is MethodInvocation ||
+ node is SuperMethodInvocation ||
+ node is VariableGet ||
+ node is VariableSet ||
+ node is StaticGet ||
+ node is StaticSet ||
+ node is DirectPropertyGet ||
+ node is DirectPropertySet ||
+ node is StaticInvocation ||
+ node is DirectMethodInvocation ||
+ node is ConstructorInvocation ||
+ node is FunctionExpression;
- // Do the round trip.
- DartType deserialized = readNode(initial, dartTypeSerializer, uri, offset);
- // The error is reported elsewhere for the case of null.
- if (deserialized == null) return;
+ bool isStatementSupported(Statement node) =>
+ node is ExpressionStatement || node is ReturnStatement;
- String serialized =
- writeNode(deserialized, dartTypeSerializer, uri, offset);
-
- if (initial != serialized) {
- failures.add(new TextRoundTripFailure(initial, serialized, uri, offset));
- }
- }
-
- void makeStatementRoundTrip(Statement node) {
- Uri uri = noUri;
- int offset = noOffset;
- Location location = node.location;
- if (location != null) {
- uri = location.file;
- offset = node.fileOffset;
- }
-
- String initial = writeNode(node, statementSerializer, uri, offset);
-
- // Do the round trip.
- Statement deserialized =
- readNode(initial, statementSerializer, uri, offset);
- // The error is reported elsewhere for the case of null.
- if (deserialized == null) return;
-
- String serialized =
- writeNode(deserialized, statementSerializer, uri, offset);
-
- if (initial != serialized) {
- failures.add(new TextRoundTripFailure(initial, serialized, uri, offset));
- }
- }
-
- @override
- void defaultExpression(Expression node) {
- throw new UnsupportedError("defaultExpression");
- }
-
- @override
- void defaultMemberReference(Member node) {
- throw new UnsupportedError("defaultMemberReference");
- }
-
- @override
- void defaultConstantReference(Constant node) {
- throw new UnsupportedError("defaultConstantReference");
- }
-
- @override
- void defaultConstant(Constant node) {
- throw new UnsupportedError("defaultConstant");
- }
-
- @override
- void defaultDartType(DartType node) {
- throw new UnsupportedError("defaultDartType");
- }
-
- @override
- void defaultTreeNode(TreeNode node) {
- throw new UnsupportedError("defaultTreeNode");
- }
-
- @override
- void defaultNode(Node node) {
- throw new UnsupportedError("defaultNode");
- }
-
- @override
- void defaultInitializer(Initializer node) {
- throw new UnsupportedError("defaultInitializer");
- }
-
- @override
- void defaultMember(Member node) {
- throw new UnsupportedError("defaultMember");
- }
-
- @override
- void defaultStatement(Statement node) {
- throw new UnsupportedError("defaultStatement");
- }
-
- @override
- void defaultBasicLiteral(BasicLiteral node) {
- throw new UnsupportedError("defaultBasicLiteral");
- }
-
- @override
- void visitNamedType(NamedType node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSupertype(Supertype node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitName(Name node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitRedirectingFactoryConstructorReference(
- RedirectingFactoryConstructor node) {}
-
- @override
- void visitProcedureReference(Procedure node) {}
-
- @override
- void visitConstructorReference(Constructor node) {}
-
- @override
- void visitFieldReference(Field node) {}
-
- @override
- void visitTypeLiteralConstantReference(TypeLiteralConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitTearOffConstantReference(TearOffConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitPartialInstantiationConstantReference(
- PartialInstantiationConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitInstanceConstantReference(InstanceConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitListConstantReference(ListConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSetConstantReference(SetConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitMapConstantReference(MapConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSymbolConstantReference(SymbolConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitStringConstantReference(StringConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitDoubleConstantReference(DoubleConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitIntConstantReference(IntConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitBoolConstantReference(BoolConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitNullConstantReference(NullConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitUnevaluatedConstantReference(UnevaluatedConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitTypedefReference(Typedef node) {}
-
- @override
- void visitClassReference(Class node) {}
-
- @override
- void visitTypeLiteralConstant(TypeLiteralConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitTearOffConstant(TearOffConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitPartialInstantiationConstant(PartialInstantiationConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitInstanceConstant(InstanceConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitListConstant(ListConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSetConstant(SetConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitMapConstant(MapConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitInstanceCreation(InstanceCreation node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitFileUriExpression(FileUriExpression node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSymbolConstant(SymbolConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitStringConstant(StringConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitDoubleConstant(DoubleConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitIntConstant(IntConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitBoolConstant(BoolConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitNullConstant(NullConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitUnevaluatedConstant(UnevaluatedConstant node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitTypedefType(TypedefType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitTypeParameterType(TypeParameterType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitFunctionType(FunctionType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitInterfaceType(InterfaceType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitBottomType(BottomType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitNeverType(NeverType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitVoidType(VoidType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitDynamicType(DynamicType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitInvalidType(InvalidType node) {
- storeLastSeenUriAndOffset(node);
- makeDartTypeRoundTrip(node);
- }
-
- @override
- void visitComponent(Component node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitMapEntry(MapEntry node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitCatch(Catch node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSwitchCase(SwitchCase node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitNamedExpression(NamedExpression node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitArguments(Arguments node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitFunctionNode(FunctionNode node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitTypeParameter(TypeParameter node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitTypedef(Typedef node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitLibraryPart(LibraryPart node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitCombinator(Combinator node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitLibraryDependency(LibraryDependency node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitLibrary(Library node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitAssertInitializer(AssertInitializer node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitLocalInitializer(LocalInitializer node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitRedirectingInitializer(RedirectingInitializer node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitSuperInitializer(SuperInitializer node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitFieldInitializer(FieldInitializer node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitInvalidInitializer(InvalidInitializer node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitClass(Class node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitExtension(Extension node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitField(Field node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitProcedure(Procedure node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitConstructor(Constructor node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitFunctionDeclaration(FunctionDeclaration node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitVariableDeclaration(VariableDeclaration node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitYieldStatement(YieldStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitTryFinally(TryFinally node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitTryCatch(TryCatch node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitReturnStatement(ReturnStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitIfStatement(IfStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitContinueSwitchStatement(ContinueSwitchStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitSwitchStatement(SwitchStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitForInStatement(ForInStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitForStatement(ForStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitDoStatement(DoStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitWhileStatement(WhileStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitBreakStatement(BreakStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitLabeledStatement(LabeledStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitAssertStatement(AssertStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitEmptyStatement(EmptyStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitAssertBlock(AssertBlock node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitBlock(Block node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
-
- @override
- void visitExpressionStatement(ExpressionStatement node) {
- storeLastSeenUriAndOffset(node);
- makeStatementRoundTrip(node);
- }
-
- @override
- void visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitLoadLibrary(LoadLibrary node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitInstantiation(Instantiation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitLet(Let node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitBlockExpression(BlockExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitNullLiteral(NullLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitBoolLiteral(BoolLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitDoubleLiteral(DoubleLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitIntLiteral(IntLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitStringLiteral(StringLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitConstantExpression(ConstantExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitFunctionExpression(FunctionExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitAwaitExpression(AwaitExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitMapLiteral(MapLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitSetLiteral(SetLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitListLiteral(ListLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitThrow(Throw node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitRethrow(Rethrow node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitThisExpression(ThisExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitTypeLiteral(TypeLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitSymbolLiteral(SymbolLiteral node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitAsExpression(AsExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitIsExpression(IsExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitStringConcatenation(StringConcatenation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitListConcatenation(ListConcatenation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitSetConcatenation(SetConcatenation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitMapConcatenation(MapConcatenation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitConditionalExpression(ConditionalExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitLogicalExpression(LogicalExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitNot(Not node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitNullCheck(NullCheck node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitConstructorInvocation(ConstructorInvocation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitStaticInvocation(StaticInvocation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitSuperMethodInvocation(SuperMethodInvocation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitDirectMethodInvocation(DirectMethodInvocation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitMethodInvocation(MethodInvocation node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitStaticSet(StaticSet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitStaticGet(StaticGet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitSuperPropertySet(SuperPropertySet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitSuperPropertyGet(SuperPropertyGet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitDirectPropertySet(DirectPropertySet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitDirectPropertyGet(DirectPropertyGet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitPropertySet(PropertySet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitPropertyGet(PropertyGet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitVariableSet(VariableSet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitVariableGet(VariableGet node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
-
- @override
- void visitInvalidExpression(InvalidExpression node) {
- storeLastSeenUriAndOffset(node);
- makeExpressionRoundTrip(node);
- }
+ bool isSupported(Node node) =>
+ node is DartType && isDartTypeSupported(node) ||
+ node is Expression && isExpressionSupported(node) ||
+ node is Statement && isStatementSupported(node);
}
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 2ead984..06b285b 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -223,6 +223,8 @@
alreadyMigratedType,
alwaysNullableType,
compoundAssignment,
+ // See [DummyOrigin].
+ dummy,
dynamicAssignment,
enumValue,
expressionChecks,
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 711a751..8e2da63 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -4,11 +4,11 @@
import 'dart:convert';
-import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/src/nullability_migration_impl.dart';
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index f2e5b91..96f2cf9 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -363,8 +363,10 @@
var rightOperand = node.rightOperand;
if (operatorType == TokenType.EQ_EQ || operatorType == TokenType.BANG_EQ) {
var leftType = _dispatch(leftOperand);
+ _graph.connectDummy(leftType.node, DummyOrigin(source, node));
_flowAnalysis.equalityOp_rightBegin(leftOperand);
var rightType = _dispatch(rightOperand);
+ _graph.connectDummy(rightType.node, DummyOrigin(source, node));
bool notEqual = operatorType == TokenType.BANG_EQ;
_flowAnalysis.equalityOp_end(node, rightOperand, notEqual: notEqual);
@@ -567,21 +569,52 @@
@override
DecoratedType visitConditionalExpression(ConditionalExpression node) {
_checkExpressionNotNull(node.condition);
+ NullabilityNode trueGuard;
+ NullabilityNode falseGuard;
+ if (identical(_conditionInfo?.condition, node.condition)) {
+ trueGuard = _conditionInfo.trueGuard;
+ falseGuard = _conditionInfo.falseGuard;
+ _variables.recordConditionalDiscard(source, node,
+ ConditionalDiscard(trueGuard, falseGuard, _conditionInfo.isPure));
+ }
DecoratedType thenType;
DecoratedType elseType;
- // TODO(paulberry): guard anything inside the true and false branches.
- // See https://github.com/dart-lang/sdk/issues/41551.
-
// Post-dominators diverge as we branch in the conditional.
// Note: we don't have to create a scope for each branch because they can't
// define variables.
_postDominatedLocals.doScoped(action: () {
_flowAnalysis.conditional_thenBegin(node.condition);
- thenType = _dispatch(node.thenExpression);
+ if (trueGuard != null) {
+ _guards.add(trueGuard);
+ }
+ try {
+ thenType = _dispatch(node.thenExpression);
+ if (trueGuard != null) {
+ thenType = thenType
+ .withNode(_nullabilityNodeForGLB(node, thenType.node, trueGuard));
+ }
+ } finally {
+ if (trueGuard != null) {
+ _guards.removeLast();
+ }
+ }
_flowAnalysis.conditional_elseBegin(node.thenExpression);
- elseType = _dispatch(node.elseExpression);
+ if (falseGuard != null) {
+ _guards.add(falseGuard);
+ }
+ try {
+ elseType = _dispatch(node.elseExpression);
+ if (falseGuard != null) {
+ elseType = elseType.withNode(
+ _nullabilityNodeForGLB(node, elseType.node, falseGuard));
+ }
+ } finally {
+ if (falseGuard != null) {
+ _guards.removeLast();
+ }
+ }
_flowAnalysis.conditional_end(node, node.elseExpression);
});
@@ -679,6 +712,13 @@
return null;
}
+ @override
+ DecoratedType visitExpressionStatement(ExpressionStatement node) {
+ var decoratedType = _dispatch(node.expression);
+ _graph.connectDummy(decoratedType.node, DummyOrigin(source, node));
+ return decoratedType;
+ }
+
DecoratedType visitExtensionDeclaration(ExtensionDeclaration node) {
visitClassOrMixinOrExtensionDeclaration(node);
_dispatch(node.extendedType);
@@ -1496,14 +1536,16 @@
_flowAnalysis.switchStatement_expressionEnd(node);
var hasDefault = false;
for (var member in node.members) {
- var hasLabel = member.labels.isNotEmpty;
- _flowAnalysis.switchStatement_beginCase(hasLabel, node);
- if (member is SwitchCase) {
- _dispatch(member.expression);
- } else {
- hasDefault = true;
- }
- _dispatchList(member.statements);
+ _postDominatedLocals.doScoped(action: () {
+ var hasLabel = member.labels.isNotEmpty;
+ _flowAnalysis.switchStatement_beginCase(hasLabel, node);
+ if (member is SwitchCase) {
+ _dispatch(member.expression);
+ } else {
+ hasDefault = true;
+ }
+ _dispatchList(member.statements);
+ });
}
_flowAnalysis.switchStatement_end(hasDefault);
return null;
@@ -2344,7 +2386,11 @@
if (parts is ForPartsWithDeclarations) {
_dispatch(parts.variables);
} else if (parts is ForPartsWithExpression) {
- _dispatch(parts.initialization);
+ var initializationType = _dispatch(parts.initialization);
+ if (initializationType != null) {
+ _graph.connectDummy(
+ initializationType.node, DummyOrigin(source, parts));
+ }
}
_flowAnalysis.for_conditionBegin(node);
if (parts.condition != null) {
@@ -2394,7 +2440,10 @@
if (parts is ForParts) {
_flowAnalysis.for_updaterBegin();
- _dispatchList(parts.updaters);
+ for (var updater in parts.updaters ?? <Expression>[]) {
+ var updaterType = _dispatch(updater);
+ _graph.connectDummy(updaterType.node, DummyOrigin(source, updater));
+ }
_flowAnalysis.for_end();
} else {
_flowAnalysis.forEach_end();
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index e71c1b4..aaa8f5d 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -472,6 +472,18 @@
EdgeOriginKind get kind => EdgeOriginKind.optionalFormalParameter;
}
+/// Edge origin resulting from the use of an element which does not affect the
+/// nullability graph in other ways.
+class DummyOrigin extends EdgeOrigin {
+ DummyOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ String get description => 'dummy';
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.dummy;
+}
+
/// Edge origin resulting from an inheritance relationship between two method
/// parameters.
class ParameterInheritanceOrigin extends EdgeOrigin {
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 8389313..6e4f5aa 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -273,11 +273,11 @@
{AtomicEditInfo info, bool isInformative = false}) {
var end = innerPlan.end;
return surround(innerPlan, suffix: [
- AtomicEdit.insert(' '),
+ AtomicEdit.insert(' ', isInformative: isInformative),
AtomicEdit.insert(comment, info: info, isInformative: isInformative),
if (!_isJustBefore(end, const [')', ']', '}', ';']) &&
!_isJustBeforeWhitespace(end))
- AtomicEdit.insert(' ')
+ AtomicEdit.insert(' ', isInformative: isInformative)
]);
}
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 0873973..7c37739 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -320,7 +320,6 @@
AstNode conditionNode, AstNode thenNode, AstNode elseNode) {
if (conditionValue == null) return null;
if (aggregator._warnOnWeakCode) {
- List<EditPlan> innerPlans = [];
var conditionPlan = aggregator.innerPlanForNode(conditionNode);
var info = AtomicEditInfo(
conditionValue
@@ -330,12 +329,11 @@
var commentedConditionPlan = aggregator.planner.addCommentPostfix(
conditionPlan, '/* == $conditionValue */',
info: info, isInformative: true);
- innerPlans.add(commentedConditionPlan);
- innerPlans.addAll(aggregator.innerPlansForNode(thenNode));
- if (elseNode != null) {
- innerPlans.addAll(aggregator.innerPlansForNode(elseNode));
- }
- return aggregator.planner.passThrough(node, innerPlans: innerPlans);
+ return aggregator.planner.passThrough(node, innerPlans: [
+ commentedConditionPlan,
+ aggregator.planForNode(thenNode),
+ if (elseNode != null) aggregator.planForNode(elseNode)
+ ]);
}
AstNode nodeToKeep;
NullabilityFixDescription descriptionBefore, descriptionAfter;
@@ -762,6 +760,10 @@
NodeChangeForCompilationUnit();
@override
+ NodeChange visitConditionalExpression(ConditionalExpression node) =>
+ NodeChangeForConditionalExpression();
+
+ @override
NodeChange visitDefaultFormalParameter(DefaultFormalParameter node) =>
NodeChangeForDefaultFormalParameter();
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 35177f7..0bc3fd1 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -101,6 +101,10 @@
/// that type should be.
final Map<ParameterElement, DartType> _addedParameterTypes = {};
+ final bool warnOnWeakCode;
+
+ final NullabilityGraph _graph;
+
factory FixBuilder(
Source source,
DecoratedClassHierarchy decoratedClassHierarchy,
@@ -109,7 +113,9 @@
Variables variables,
LibraryElement definingLibrary,
NullabilityMigrationListener listener,
- CompilationUnit unit) {
+ CompilationUnit unit,
+ bool warnOnWeakCode,
+ NullabilityGraph graph) {
var migrationResolutionHooks = MigrationResolutionHooksImpl();
return FixBuilder._(
decoratedClassHierarchy,
@@ -122,7 +128,9 @@
definingLibrary,
listener,
unit,
- migrationResolutionHooks);
+ migrationResolutionHooks,
+ warnOnWeakCode,
+ graph);
}
FixBuilder._(
@@ -133,7 +141,9 @@
LibraryElement definingLibrary,
this.listener,
this.unit,
- this.migrationResolutionHooks)
+ this.migrationResolutionHooks,
+ this.warnOnWeakCode,
+ this._graph)
: typeProvider = _typeSystem.typeProvider {
migrationResolutionHooks._fixBuilder = this;
// TODO(paulberry): make use of decoratedClassHierarchy
@@ -304,13 +314,27 @@
(_fixBuilder._getChange(node) as NodeChangeForConditional)
..conditionValue = conditionValue
..conditionReason = conditionalDiscard.reason;
- return conditionValue;
+ // If we're just issuing warnings, instruct the resolver to go ahead
+ // and visit both branches of the conditional.
+ return _fixBuilder.warnOnWeakCode ? null : conditionValue;
}
});
@override
- List<ParameterElement> getExecutableParameters(ExecutableElement element) =>
- getExecutableType(element as ElementImplWithFunctionType).parameters;
+ List<ParameterElement> getExecutableParameters(
+ ExecutableElementImpl element) {
+ if (_fixBuilder._graph.isBeingMigrated(element.library.source)) {
+ // The element is part of a library that's being migrated, so its
+ // parameters all have been visited (and thus have their own final
+ // types). So we don't need to do anything.
+ return const ElementTypeProvider().getExecutableParameters(element);
+ } else {
+ // The element is not part of a library that's being migrated, so its
+ // parameters probably haven't been visited; we need to get the parameters
+ // from the final function type.
+ return getExecutableType(element).parameters;
+ }
+ }
@override
DartType getExecutableReturnType(Element element) =>
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index ae087d2..d80b2b4 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -2,12 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
@@ -105,7 +105,9 @@
_variables,
library,
_permissive ? listener : null,
- unit);
+ unit,
+ warnOnWeakCode,
+ _graph);
try {
DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
fixBuilder.visitAll();
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index a7ce41f2..44175cb 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -158,6 +158,9 @@
case _NullabilityEdgeKind.union:
json['kind'] = 'union';
break;
+ case _NullabilityEdgeKind.dummy:
+ json['kind'] = 'dummy';
+ break;
}
if (codeReference != null) json['code'] = codeReference.toJson();
if (description != null) json['description'] = description;
@@ -183,6 +186,9 @@
case _NullabilityEdgeKind.union:
edgeDecorations.add('union');
break;
+ case _NullabilityEdgeKind.dummy:
+ edgeDecorations.add('dummy');
+ break;
}
edgeDecorations.addAll(guards);
var edgeDecoration =
@@ -271,6 +277,11 @@
return _connect(upstreamNodes, destinationNode, kind, origin);
}
+ /// Records that [sourceNode] is immediately upstream from [always], via a
+ /// dummy edge.
+ NullabilityEdge connectDummy(NullabilityNode sourceNode, EdgeOrigin origin) =>
+ _connect([sourceNode], always, _NullabilityEdgeKind.dummy, origin);
+
/// Prints out a representation of the graph nodes. Useful in debugging
/// broken tests.
void debugDump() {
@@ -1238,6 +1249,10 @@
/// Union edge. Indicates that two nodes should have exactly the same
/// nullability.
union,
+
+ /// Dummy edge. Indicates that two edges are connected in a way that should
+ /// not propagate (non-)nullability in either direction.
+ dummy,
}
class _NullabilityNodeImmutable extends NullabilityNode {
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 92b2de1..615a4bb 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -41,7 +41,8 @@
Future<void> _checkMultipleFileChanges(
Map<String, String> input, Map<String, String> expectedOutput,
{Map<String, String> migratedInput = const {},
- bool removeViaComments = false}) async {
+ bool removeViaComments = false,
+ bool warnOnWeakCode = false}) async {
for (var path in migratedInput.keys) {
driver.getFileSync(newFile(path, content: migratedInput[path]).path);
}
@@ -52,7 +53,7 @@
var migration = NullabilityMigration(listener,
permissive: _usePermissiveMode,
removeViaComments: removeViaComments,
- warnOnWeakCode: false);
+ warnOnWeakCode: warnOnWeakCode);
for (var path in input.keys) {
if (!(await session.getFile(path)).isPart) {
for (var unit in (await session.getResolvedLibrary(path)).units) {
@@ -98,11 +99,14 @@
/// be removed in its entirety (the default) or removed by commenting it out.
Future<void> _checkSingleFileChanges(String content, String expected,
{Map<String, String> migratedInput = const {},
- bool removeViaComments = false}) async {
+ bool removeViaComments = false,
+ bool warnOnWeakCode = false}) async {
var sourcePath = convertPath('/home/test/lib/test.dart');
await _checkMultipleFileChanges(
{sourcePath: content}, {sourcePath: expected},
- migratedInput: migratedInput, removeViaComments: removeViaComments);
+ migratedInput: migratedInput,
+ removeViaComments: removeViaComments,
+ warnOnWeakCode: warnOnWeakCode);
}
}
@@ -438,6 +442,53 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_code_inside_switch_does_not_imply_non_null_intent() async {
+ var content = '''
+int f(int i, int j) {
+ switch (i) {
+ case 0:
+ return j + 1;
+ default:
+ return 0;
+ }
+}
+int g(int i, int j) {
+ if (i == 0) {
+ return f(i, j);
+ } else {
+ return 0;
+ }
+}
+main() {
+ g(0, null);
+}
+''';
+ var expected = '''
+int f(int i, int? j) {
+ switch (i) {
+ case 0:
+ return j! + 1;
+ default:
+ return 0;
+ }
+}
+int g(int i, int? j) {
+ if (i == 0) {
+ return f(i, j);
+ } else {
+ return 0;
+ }
+}
+main() {
+ g(0, null);
+}
+''';
+ // Note: prior to the fix for https://github.com/dart-lang/sdk/issues/41407,
+ // we would consider the use of `j` in `f` to establish non-null intent, so
+ // the null check would be erroneously placed in `g`'s call to `f`.
+ await _checkSingleFileChanges(content, expected, warnOnWeakCode: true);
+ }
+
Future<void> test_comment_bang_implies_non_null_intent() async {
var content = '''
void f(int/*!*/ i) {}
@@ -530,7 +581,6 @@
await _checkSingleFileChanges(content, expected);
}
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/41551')
Future<void> test_conditional_expression_guard_subexpression() async {
var content = '''
void f(String s, int x) {
@@ -542,14 +592,19 @@
s == null ? (x = null!) : (x = s.length);
}
''';
- await _checkSingleFileChanges(content, expected);
+ await _checkSingleFileChanges(content, expected, warnOnWeakCode: true);
}
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/41551')
- Future<void> test_conditional_expression_guard_value() async {
+ Future<void> test_conditional_expression_guard_value_ifFalse() async {
+ var content = 'int f(String s) => s != null ? s.length : null;';
+ var expected = 'int f(String s) => s != null ? s.length : null!;';
+ await _checkSingleFileChanges(content, expected, warnOnWeakCode: true);
+ }
+
+ Future<void> test_conditional_expression_guard_value_ifTrue() async {
var content = 'int f(String s) => s == null ? null : s.length;';
var expected = 'int f(String s) => s == null ? null! : s.length;';
- await _checkSingleFileChanges(content, expected);
+ await _checkSingleFileChanges(content, expected, warnOnWeakCode: true);
}
Future<void>
@@ -1919,6 +1974,54 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_field_formal_parameters_do_not_promote() async {
+ var content = '''
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+abstract class D {
+ final A x;
+ D(this.x) {
+ if (x is B) {
+ visitB(x);
+ } else {
+ visitC(x as C);
+ }
+ }
+
+ void visitB(B b);
+
+ void visitC(C c);
+}
+''';
+ var expected = '''
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+abstract class D {
+ final A x;
+ D(this.x) {
+ if (x is B) {
+ visitB(x as B);
+ } else {
+ visitC(x as C);
+ }
+ }
+
+ void visitB(B b);
+
+ void visitC(C c);
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_field_initialized_at_declaration_site() async {
var content = '''
class C {
@@ -5584,6 +5687,28 @@
''';
await _checkSingleFileChanges(content, expected);
}
+
+ Future<void> test_weak_if_visit_weak_subexpression() async {
+ var content = '''
+int f(int x, int/*?*/ y) {
+ if (x == null) {
+ print(y.toDouble());
+ } else {
+ print(y.toDouble());
+ }
+}
+''';
+ var expected = '''
+int f(int x, int? y) {
+ if (x == null) {
+ print(y!.toDouble());
+ } else {
+ print(y!.toDouble());
+ }
+}
+''';
+ await _checkSingleFileChanges(content, expected, warnOnWeakCode: true);
+ }
}
@reflectiveTest
diff --git a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
index 1aff883..46a5782 100644
--- a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
@@ -430,19 +430,19 @@
Future<void> test_conditionalExpression() async {
await analyze('''
-int f(int i) => i == null ? g(i) : h(i);
+int f(int i, int l) => i == null ? g(l) : h(i);
int g(int j) => 1;
int h(int k) => 1;
''');
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
var kNode = decoratedTypeAnnotation('int k').node;
+ var lNode = decoratedTypeAnnotation('int l').node;
// No edge from i to k because i is known to be non-nullable at the site of
// the call to h()
assertNoEdge(iNode, kNode);
- // But there is an edge from i to j
- // TODO(paulberry): there should be a guard on this edge.
- assertEdge(iNode, jNode, hard: false);
+ // But there is an edge from l to j
+ assertEdge(lNode, jNode, hard: false, guards: [iNode]);
}
Future<void> test_conditionalExpression_propagates_promotions() async {
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 8e55074..8babb8a 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -2066,6 +2066,19 @@
assertNullCheck(check_b, assertEdge(nullable_b, never, hard: true));
}
+ Future<void> test_conditionalExpression_false_guard() async {
+ await analyze('int f(int x, int y, int z) => x != null ? null : y = z;');
+ var guard = decoratedTypeAnnotation('int x').node;
+ assertEdge(decoratedTypeAnnotation('int z').node,
+ decoratedTypeAnnotation('int y').node,
+ hard: false, guards: [guard]);
+ var conditionalDiscard =
+ variables.conditionalDiscard(findNode.conditionalExpression('!='));
+ expect(conditionalDiscard, isNotNull);
+ expect(conditionalDiscard.trueGuard, isNull);
+ expect(conditionalDiscard.falseGuard, same(guard));
+ }
+
Future<void> test_conditionalExpression_functionTyped_namedParameter() async {
await analyze('''
void f(bool b, void Function({int p}) x, void Function({int p}) y) {
@@ -2455,6 +2468,19 @@
assertLUB(nullable_conditional, nullable_t, inSet(alwaysPlus));
}
+ Future<void> test_conditionalExpression_true_guard() async {
+ await analyze('int f(int x, int y, int z) => x == null ? y = z : null;');
+ var guard = decoratedTypeAnnotation('int x').node;
+ assertEdge(decoratedTypeAnnotation('int z').node,
+ decoratedTypeAnnotation('int y').node,
+ hard: false, guards: [guard]);
+ var conditionalDiscard =
+ variables.conditionalDiscard(findNode.conditionalExpression('=='));
+ expect(conditionalDiscard, isNotNull);
+ expect(conditionalDiscard.trueGuard, same(guard));
+ expect(conditionalDiscard.falseGuard, isNull);
+ }
+
Future<void> test_conditionalExpression_typeParameter_bound() async {
await analyze('''
num f<T extends num>(bool b, num x, T y) {
@@ -2727,6 +2753,64 @@
assertNoUpstreamNullability(decoratedTypeAnnotation('double').node);
}
+ Future<void> test_dummyNode_fromEqualityComparison_left() async {
+ await analyze('''
+f() {
+ int i;
+ if (i == 7) {}
+}
+''');
+ var nullable_i = decoratedTypeAnnotation('int i').node;
+ assertDummyEdge(nullable_i);
+ }
+
+ Future<void> test_dummyNode_fromEqualityComparison_right() async {
+ await analyze('''
+f() {
+ int i;
+ if (7 == i) {}
+}
+''');
+ var nullable_i = decoratedTypeAnnotation('int i').node;
+ assertDummyEdge(nullable_i);
+ }
+
+ Future<void> test_dummyNode_fromExpressionStatement() async {
+ await analyze('''
+f() {
+ int i;
+ i;
+}
+''');
+ var nullable_i = decoratedTypeAnnotation('int i').node;
+ assertDummyEdge(nullable_i);
+ }
+
+ Future<void> test_dummyNode_fromForLoopUpdaters() async {
+ await analyze('''
+f() {
+ int i;
+ int j;
+ for (;; i, j) {}
+}
+''');
+ var nullable_i = decoratedTypeAnnotation('int i').node;
+ var nullable_j = decoratedTypeAnnotation('int j').node;
+ assertDummyEdge(nullable_i);
+ assertDummyEdge(nullable_j);
+ }
+
+ Future<void> test_dummyNode_fromForLoopVariables() async {
+ await analyze('''
+f() {
+ int i;
+ for (i;;) {}
+}
+''');
+ var nullable_i = decoratedTypeAnnotation('int i').node;
+ assertDummyEdge(nullable_i);
+ }
+
Future<void> test_edgeOrigin_call_from_function() async {
await analyze('''
void f(int i) {}
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 1f9ccfa..b9e52c0 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -274,6 +274,16 @@
'f() => 0 /* zero */ + 1;');
}
+ Future<void> test_addCommentPostfix_informative() async {
+ await analyze('f() => 0.isEven;');
+ checkPlan(
+ planner.addCommentPostfix(
+ planner.passThrough(findNode.integerLiteral('0')), '/* zero */',
+ isInformative: true),
+ 'f() => 0.isEven;',
+ expectedIncludingInformative: 'f() => 0 /* zero */ .isEven;');
+ }
+
Future<void> test_addUnaryPostfix_inner_precedence_add_parens() async {
await analyze('f(x) => -x;');
checkPlan(
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 8b320b7..4a03e5b 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -1038,6 +1038,38 @@
visitSubexpression(findNode.booleanLiteral('true'), 'bool');
}
+ Future<void> test_conditionalExpression_dead_else_remove() async {
+ await analyze('_f(int x, int/*?*/ y) => x != null ? x + 1 : y + 1.0;');
+ var expression = findNode.conditionalExpression('x != null');
+ visitSubexpression(expression, 'int',
+ changes: {expression: isConditionalWithKnownValue(true)});
+ }
+
+ Future<void> test_conditionalExpression_dead_else_warn() async {
+ await analyze('_f(int x, int/*?*/ y) => x != null ? x + 1 : y + 1.0;');
+ var expression = findNode.conditionalExpression('x != null');
+ visitSubexpression(expression, 'num', warnOnWeakCode: true, changes: {
+ expression: isConditionalWithKnownValue(true),
+ findNode.simple('y +'): isNullCheck
+ });
+ }
+
+ Future<void> test_conditionalExpression_dead_then_remove() async {
+ await analyze('_f(int x, int/*?*/ y) => x == null ? y + 1.0 : x + 1;');
+ var expression = findNode.conditionalExpression('x == null');
+ visitSubexpression(expression, 'int',
+ changes: {expression: isConditionalWithKnownValue(false)});
+ }
+
+ Future<void> test_conditionalExpression_dead_then_warn() async {
+ await analyze('_f(int x, int/*?*/ y) => x == null ? y + 1.0 : x + 1;');
+ var expression = findNode.conditionalExpression('x == null');
+ visitSubexpression(expression, 'num', warnOnWeakCode: true, changes: {
+ expression: isConditionalWithKnownValue(false),
+ findNode.simple('y +'): isNullCheck
+ });
+ }
+
Future<void> test_conditionalExpression_flow_as_condition() async {
await analyze('''
_f(bool x, int/*?*/ y) => (x ? y != null : y != null) ? y + 1 : 0;
@@ -1337,7 +1369,7 @@
''');
var ifStatement = findNode.statement('if');
visitStatement(ifStatement,
- changes: {ifStatement: isEliminateDeadIf(true)});
+ changes: {ifStatement: isConditionalWithKnownValue(true)});
}
Future<void> test_ifStatement_dead_then() async {
@@ -1352,7 +1384,7 @@
''');
var ifStatement = findNode.statement('if');
visitStatement(ifStatement,
- changes: {ifStatement: isEliminateDeadIf(false)});
+ changes: {ifStatement: isConditionalWithKnownValue(false)});
}
Future<void> test_ifStatement_flow_promote_in_else() async {
@@ -1513,7 +1545,7 @@
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
visitSubexpression(findNode.listLiteral('['), 'List<int>', changes: {
- findNode.ifElement('null'): isEliminateDeadIf(true),
+ findNode.ifElement('null'): isConditionalWithKnownValue(true),
findNode.simple('y) else'): isNullCheck
});
}
@@ -1524,7 +1556,7 @@
int/*!*/ g(int/*!*/ y) => y;
''');
visitSubexpression(findNode.listLiteral('['), 'List<int>', changes: {
- findNode.ifElement('null'): isEliminateDeadIf(true),
+ findNode.ifElement('null'): isConditionalWithKnownValue(true),
findNode.simple('y)]'): isNullCheck
});
}
@@ -1536,7 +1568,7 @@
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
visitSubexpression(findNode.listLiteral('['), 'List<int>', changes: {
- findNode.ifElement('null'): isEliminateDeadIf(false),
+ findNode.ifElement('null'): isConditionalWithKnownValue(false),
findNode.simple('y)]'): isNullCheck
});
}
@@ -1549,8 +1581,9 @@
_f(int x, int/*?*/ y) => [if (x == null) h(y)];
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
- visitSubexpression(findNode.listLiteral('['), 'List<dynamic>',
- changes: {findNode.ifElement('null'): isEliminateDeadIf(false)});
+ visitSubexpression(findNode.listLiteral('['), 'List<dynamic>', changes: {
+ findNode.ifElement('null'): isConditionalWithKnownValue(false)
+ });
}
Future<void> test_list_make_explicit_type_nullable() async {
@@ -1615,7 +1648,7 @@
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Map<int, int>',
changes: {
- findNode.ifElement('null'): isEliminateDeadIf(true),
+ findNode.ifElement('null'): isConditionalWithKnownValue(true),
findNode.simple('y) else'): isNullCheck
});
}
@@ -1627,7 +1660,7 @@
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Map<int, int>',
changes: {
- findNode.ifElement('null'): isEliminateDeadIf(true),
+ findNode.ifElement('null'): isConditionalWithKnownValue(true),
findNode.simple('y)}'): isNullCheck
});
}
@@ -1640,7 +1673,7 @@
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Map<int, int>',
changes: {
- findNode.ifElement('null'): isEliminateDeadIf(false),
+ findNode.ifElement('null'): isConditionalWithKnownValue(false),
findNode.simple('y)}'): isNullCheck
});
}
@@ -1654,7 +1687,9 @@
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Map<dynamic, dynamic>',
- changes: {findNode.ifElement('null'): isEliminateDeadIf(false)});
+ changes: {
+ findNode.ifElement('null'): isConditionalWithKnownValue(false)
+ });
}
Future<void> test_map_make_explicit_key_type_nullable() async {
@@ -2460,7 +2495,7 @@
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Set<int>', changes: {
- findNode.ifElement('null'): isEliminateDeadIf(true),
+ findNode.ifElement('null'): isConditionalWithKnownValue(true),
findNode.simple('y) else'): isNullCheck
});
}
@@ -2471,7 +2506,7 @@
int/*!*/ g(int/*!*/ y) => y;
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Set<int>', changes: {
- findNode.ifElement('null'): isEliminateDeadIf(true),
+ findNode.ifElement('null'): isConditionalWithKnownValue(true),
findNode.simple('y)}'): isNullCheck
});
}
@@ -2483,7 +2518,7 @@
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Set<int>', changes: {
- findNode.ifElement('null'): isEliminateDeadIf(false),
+ findNode.ifElement('null'): isConditionalWithKnownValue(false),
findNode.simple('y)}'): isNullCheck
});
}
@@ -2497,7 +2532,9 @@
double/*!*/ h(int/*!*/ y) => y.toDouble();
''');
visitSubexpression(findNode.setOrMapLiteral('{'), 'Map<dynamic, dynamic>',
- changes: {findNode.ifElement('null'): isEliminateDeadIf(false)});
+ changes: {
+ findNode.ifElement('null'): isConditionalWithKnownValue(false)
+ });
}
Future<void> test_set_make_explicit_type_nullable() async {
@@ -2832,8 +2869,9 @@
void visitSubexpression(Expression node, String expectedType,
{Map<AstNode, Matcher> changes = const <Expression, Matcher>{},
- Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{}}) {
- var fixBuilder = _createFixBuilder(node);
+ Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{},
+ bool warnOnWeakCode = false}) {
+ var fixBuilder = _createFixBuilder(node, warnOnWeakCode: warnOnWeakCode);
fixBuilder.visitAll();
var type = node.staticType;
expect(type.getDisplayString(withNullability: true), expectedType);
@@ -2871,7 +2909,7 @@
}
}
- FixBuilder _createFixBuilder(AstNode scope) {
+ FixBuilder _createFixBuilder(AstNode scope, {bool warnOnWeakCode = false}) {
var unit = scope.thisOrAncestorOfType<CompilationUnit>();
var definingLibrary = unit.declaredElement.library;
return FixBuilder(
@@ -2882,7 +2920,9 @@
variables,
definingLibrary,
null,
- scope.thisOrAncestorOfType<CompilationUnit>());
+ scope.thisOrAncestorOfType<CompilationUnit>(),
+ warnOnWeakCode,
+ graph);
}
bool _isInScope(AstNode node, AstNode scope) {
@@ -2891,7 +2931,7 @@
null;
}
- static Matcher isEliminateDeadIf(bool knownValue) =>
+ static Matcher isConditionalWithKnownValue(bool knownValue) =>
TypeMatcher<NodeChangeForConditional>()
.having((c) => c.conditionValue, 'conditionValue', knownValue);
}
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index 24433c5..74c2c3f 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -61,9 +61,11 @@
@override
void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo) {
- expect(test.edgeOrigin, isNot(contains(edge)));
- test.edges.add(edge);
- test.edgeOrigin[edge] = originInfo;
+ if (edge.destinationNode != test.always) {
+ expect(test.edgeOrigin, isNot(contains(edge)));
+ test.edges.add(edge);
+ test.edgeOrigin[edge] = originInfo;
+ }
}
@override
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index 3f50cd6..a789b23 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -193,6 +193,9 @@
return {for (var edge in getEdges(anyNode, graph.never)) edge.sourceNode};
}
+ NullabilityEdge assertDummyEdge(Object source) =>
+ assertEdge(source, graph.always, hard: false, checkable: false);
+
/// Asserts that an edge exists with a node matching [source] and a node
/// matching [destination], and with the given [hard]ness and [guards].
///
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 087dfe4..99a1b6a 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -55,7 +55,6 @@
kernel/test/closures_test: Slow, Pass
kernel/testcases/*: Skip # These are not tests but input for tests.
vm/test/frontend_server_test: Slow, Pass
-vm/test/kernel_front_end_test: Skip # Issue http://dartbug.com/41489
vm/test/transformations/type_flow/transformer_test: Slow, Pass
vm/testcases/*: SkipByDesign # These are not tests but input for tests.
diff --git a/pkg/testing/lib/src/analyze.dart b/pkg/testing/lib/src/analyze.dart
index f9a23ee..fd4d17f 100644
--- a/pkg/testing/lib/src/analyze.dart
+++ b/pkg/testing/lib/src/analyze.dart
@@ -137,8 +137,8 @@
return kind == null
? "Malformed output from dartanalyzer:\n$message"
: "${uri.toFilePath()}:$line:$startColumn: "
- "${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n"
- "[$code] $message";
+ "${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n"
+ "[$code] $message";
}
}
@@ -169,10 +169,18 @@
} catch (e) {
topLevel = Uri.base.toFilePath(windows: false);
}
+ if (Platform.isWindows) {
+ // We need lowercase comparison on Windows to match C:/path with c:/path
+ topLevel = topLevel.toLowerCase();
+ }
String toFilePath(Uri uri) {
String path = uri.toFilePath(windows: false);
- return path.startsWith(topLevel) ? path.substring(topLevel.length) : path;
+ return (Platform.isWindows
+ ? path.toLowerCase().startsWith(topLevel)
+ : path.startsWith(topLevel))
+ ? path.substring(topLevel.length)
+ : path;
}
Set<String> filesToAnalyze = new Set<String>();
diff --git a/pkg/vm/lib/metadata/table_selector.dart b/pkg/vm/lib/metadata/table_selector.dart
index 938d5c5..e692529 100644
--- a/pkg/vm/lib/metadata/table_selector.dart
+++ b/pkg/vm/lib/metadata/table_selector.dart
@@ -9,22 +9,32 @@
// Information associated with a selector, used by the dispatch table generator.
class TableSelectorInfo {
static const int kCalledOnNullBit = 1 << 0;
- static const int kCallCountShift = 1;
+ static const int kTornOffBit = 1 << 1;
int callCount;
- bool calledOnNull;
+ int flags;
+
+ bool get calledOnNull => (flags & kCalledOnNullBit) != 0;
+ set calledOnNull(bool value) {
+ flags = value ? (flags | kCalledOnNullBit) : (flags & ~kCalledOnNullBit);
+ }
+
+ bool get tornOff => (flags & kTornOffBit) != 0;
+ set tornOff(bool value) {
+ flags = value ? (flags | kTornOffBit) : (flags & ~kTornOffBit);
+ }
TableSelectorInfo()
: callCount = 0,
- calledOnNull = false;
+ flags = 0;
TableSelectorInfo.readFromBinary(BinarySource source)
: callCount = source.readUInt(),
- calledOnNull = source.readByte() != 0;
+ flags = source.readByte();
void writeToBinary(BinarySink sink) {
sink.writeUInt30(callCount);
- sink.writeByte(calledOnNull ? 1 : 0);
+ sink.writeByte(flags);
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index a2bf551..348f562 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -1363,6 +1363,10 @@
}
}
+ Procedure _cachedUnsafeCast;
+ Procedure get unsafeCast => _cachedUnsafeCast ??= _environment.coreTypes.index
+ .getTopLevelMember('dart:_internal', 'unsafeCast');
+
@override
defaultTreeNode(TreeNode node) =>
throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
@@ -1754,7 +1758,17 @@
passTypeArguments: node.target.isFactory);
final target = node.target;
assertx((target is! Field) && !target.isGetter && !target.isSetter);
- return _makeCall(node, new DirectSelector(target), args);
+ TypeExpr result = _makeCall(node, new DirectSelector(target), args);
+ if (target == unsafeCast) {
+ // Async transformation inserts unsafeCasts to make sure
+ // kernel is correctly typed. Instead of using the result of unsafeCast
+ // (which is an opaque native function), we can use its argument narrowed
+ // by the casted type.
+ final arg = args.values.single;
+ result = _makeNarrow(
+ arg, _typesBuilder.fromStaticType(node.arguments.types.single, true));
+ }
+ return result;
}
@override
diff --git a/pkg/vm/lib/transformations/type_flow/table_selector.dart b/pkg/vm/lib/transformations/type_flow/table_selector.dart
index 2533d48..571f190 100644
--- a/pkg/vm/lib/transformations/type_flow/table_selector.dart
+++ b/pkg/vm/lib/transformations/type_flow/table_selector.dart
@@ -60,16 +60,22 @@
throw "Unexpected member kind '${member.runtimeType}'";
}
- void registerCall(int selectorId, bool calledOnNull) {
- metadata.selectors[selectorId].callCount++;
- metadata.selectors[selectorId].calledOnNull |= calledOnNull;
- }
-
void registerMethodOrSetterCall(Member member, bool calledOnNull) {
- registerCall(methodOrSetterSelectorId(member), calledOnNull);
+ final TableSelectorInfo selector =
+ metadata.selectors[methodOrSetterSelectorId(member)];
+ selector.callCount++;
+ selector.calledOnNull |= calledOnNull;
}
void registerGetterCall(Member member, bool calledOnNull) {
- registerCall(getterSelectorId(member), calledOnNull);
+ final TableSelectorInfo selector =
+ metadata.selectors[getterSelectorId(member)];
+ selector.callCount++;
+ selector.calledOnNull |= calledOnNull;
+ if (member is Procedure && member.kind == ProcedureKind.Method) {
+ final TableSelectorInfo methodSelector =
+ metadata.selectors[methodOrSetterSelectorId(member)];
+ methodSelector.tornOff = true;
+ }
}
}
diff --git a/pkg/vm/test/kernel_front_end_test.dart b/pkg/vm/test/kernel_front_end_test.dart
index ec3e8b0..6aef35e 100644
--- a/pkg/vm/test/kernel_front_end_test.dart
+++ b/pkg/vm/test/kernel_front_end_test.dart
@@ -48,7 +48,7 @@
outputDill(),
'$sdkDir/$mainScript',
]);
- });
+ }, timeout: Timeout.none);
test('compile-multi-root', () async {
await testCompile([
@@ -64,7 +64,7 @@
outputDill(),
'test-filesystem-scheme:///$mainScript',
]);
- });
+ }, timeout: Timeout.none);
test('compile-multi-root-with-package-uri-main', () async {
await testCompile([
@@ -80,7 +80,7 @@
outputDill(),
'$mainScriptPackageUri',
]);
- });
+ }, timeout: Timeout.none);
test('compile-package-split', () async {
await testCompile([
@@ -93,7 +93,7 @@
'--split-output-by-packages',
'$sdkDir/$mainScript',
]);
- });
+ }, timeout: Timeout.none);
test('compile-bytecode', () async {
await testCompile([
@@ -107,7 +107,7 @@
'--drop-ast',
'$sdkDir/$mainScript',
]);
- });
+ }, timeout: Timeout.none);
test('compile-bytecode-package-split', () async {
await testCompile([
@@ -122,5 +122,5 @@
'--split-output-by-packages',
'$sdkDir/$mainScript',
]);
- });
+ }, timeout: Timeout.none);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart
new file mode 100644
index 0000000..9af419c
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+ Future<dynamic> bar(x) async => print(x);
+}
+
+class B {}
+
+dynamic foo() => new A();
+Future<dynamic> baz() async => new B();
+
+main() async {
+ await foo().bar(await baz());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
new file mode 100644
index 0000000..17ce2e4
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
@@ -0,0 +1,103 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method bar(dynamic x) → asy::Future<dynamic>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ (dynamic) →* dynamic :async_op_then;
+ (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print(x);
+ break #L1;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
+ [@vm.direct-call.metadata=_AsyncAwaitCompleter::completeError] [@vm.inferred-type.metadata=!? (skip check)] :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ [@vm.direct-call.metadata=_AsyncAwaitCompleter::start] [@vm.inferred-type.metadata=!? (skip check)] :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+ return [@vm.direct-call.metadata=_AsyncAwaitCompleter::future] [@vm.inferred-type.metadata=dart.async::_Future] :async_completer.{asy::Completer::future};
+ }
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ : super core::Object::•()
+ ;
+}
+static method foo() → dynamic
+ return new self::A::•();
+static method baz() → asy::Future<dynamic>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ (dynamic) →* dynamic :async_op_then;
+ (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = new self::B::•();
+ break #L2;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
+ [@vm.direct-call.metadata=_AsyncAwaitCompleter::completeError] [@vm.inferred-type.metadata=!? (skip check)] :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ [@vm.direct-call.metadata=_AsyncAwaitCompleter::start] [@vm.inferred-type.metadata=!? (skip check)] :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+ return [@vm.direct-call.metadata=_AsyncAwaitCompleter::future] [@vm.inferred-type.metadata=dart.async::_Future] :async_completer.{asy::Completer::future};
+}
+static method main() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ (dynamic) →* dynamic :async_op_then;
+ (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :async_temporary_0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ :async_temporary_0 = [@vm.inferred-type.metadata=#lib::A] self::foo();
+ [yield] let dynamic #t1 = asy::_awaitHelper([@vm.inferred-type.metadata=dart.async::_Future] self::baz(), :async_op_then, :async_op_error, :async_op) in null;
+ [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=A::bar??] [@vm.inferred-type.metadata=dart.async::_Future (receiver not int)] _in::unsafeCast<dynamic>(:async_temporary_0).bar(:result), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
+ [@vm.direct-call.metadata=_AsyncAwaitCompleter::completeError] [@vm.inferred-type.metadata=!? (skip check)] :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ [@vm.direct-call.metadata=_AsyncAwaitCompleter::start] [@vm.inferred-type.metadata=!? (skip check)] :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+ return [@vm.direct-call.metadata=_AsyncAwaitCompleter::future] [@vm.inferred-type.metadata=dart.async::_Future] :async_completer.{asy::Completer::future};
+}
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 8c963c4..8394deb 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -161,7 +161,12 @@
MutexLocker ml(&mutex_);
// Do not ask for POLLERR and POLLHUP explicitly as they are
// triggered anyway.
- uint32_t events = POLLRDHUP;
+ uint32_t events = 0;
+ // Do not subscribe to read closed events when kCloseEvent has already been
+ // sent to the Dart thread.
+ if (close_events_enabled_) {
+ events |= POLLRDHUP;
+ }
if (read_events_enabled_ && ((mask & (1 << kInEvent)) != 0)) {
events |= POLLIN;
}
@@ -253,19 +258,39 @@
return events;
}
+// This function controls the simulation of edge-triggering. It is responsible
+// for removing events from the event mask when they should be supressed, and
+// for supressing future events. Events are unsupressed by their respective
+// operations by the Dart thread on the socket---that is, where the
+// *_events_enabled_ flags are set to true.
intptr_t IOHandle::ToggleEvents(intptr_t event_mask) {
MutexLocker ml(&mutex_);
+ // If write events are disabled, then remove the kOutEvent bit from the
+ // event mask.
if (!write_events_enabled_) {
- LOG_INFO("IOHandle::ToggleEvents: fd = %ld de-asserting write\n", fd_);
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "de-asserting kOutEvent\n",
+ fd_);
event_mask = event_mask & ~(1 << kOutEvent);
}
+ // If the kOutEvent bit is set, then supress future write events until the
+ // Dart thread writes.
if ((event_mask & (1 << kOutEvent)) != 0) {
- LOG_INFO("IOHandle::ToggleEvents: fd = %ld asserting write and disabling\n",
- fd_);
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "asserting kOutEvent and disabling\n",
+ fd_);
write_events_enabled_ = false;
}
+
+ // If read events are disabled, then remove the kInEvent bit from the event
+ // mask.
if (!read_events_enabled_) {
- LOG_INFO("IOHandle::ToggleEvents: fd=%ld de-asserting read\n", fd_);
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "de-asserting kInEvent\n",
+ fd_);
event_mask = event_mask & ~(1 << kInEvent);
}
// We may get In events without available bytes, so we must make sure there
@@ -283,11 +308,43 @@
//
// As a detail, negative available bytes (errors) are handled specially; see
// IOHandle::AvailableBytes for more information.
- if ((event_mask & (1 << kInEvent)) != 0 &&
- FDUtils::AvailableBytes(fd_) != 0) {
- LOG_INFO("IOHandle::ToggleEvents: fd = %ld asserting read and disabling\n",
- fd_);
- read_events_enabled_ = false;
+ if ((event_mask & (1 << kInEvent)) != 0) {
+ if (FDUtils::AvailableBytes(fd_) != 0) {
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "asserting kInEvent and disabling with bytes available\n",
+ fd_);
+ read_events_enabled_ = false;
+ }
+ // Also supress future read events if we get a kCloseEvent. This is to
+ // account for POLLIN being set by Fuchsia when the socket is read-closed.
+ if ((event_mask & (1 << kCloseEvent)) != 0) {
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "asserting kInEvent and disabling due to a close event\n",
+ fd_);
+ read_events_enabled_ = false;
+ }
+ }
+
+ // If the close events are disabled, then remove the kCloseEvent bit from the
+ // event mask.
+ if (!close_events_enabled_) {
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "de-asserting kCloseEvent\n",
+ fd_);
+ event_mask = event_mask & ~(1 << kCloseEvent);
+ }
+ // If the kCloseEvent bit is set, then supress future close events, they will
+ // be ignored by the Dart thread. See _NativeSocket.multiplex in
+ // socket_patch.dart.
+ if ((event_mask & (1 << kCloseEvent)) != 0) {
+ LOG_INFO(
+ "IOHandle::ToggleEvents: fd = %ld "
+ "asserting kCloseEvent and disabling\n",
+ fd_);
+ close_events_enabled_ = false;
}
return event_mask;
}
diff --git a/runtime/bin/eventhandler_fuchsia.h b/runtime/bin/eventhandler_fuchsia.h
index 07acef97..0011f26 100644
--- a/runtime/bin/eventhandler_fuchsia.h
+++ b/runtime/bin/eventhandler_fuchsia.h
@@ -34,6 +34,7 @@
mutex_(),
write_events_enabled_(true),
read_events_enabled_(true),
+ close_events_enabled_(true),
fd_(fd),
handle_(ZX_HANDLE_INVALID),
wait_key_(0),
@@ -73,6 +74,8 @@
Mutex mutex_;
bool write_events_enabled_;
bool read_events_enabled_;
+ bool close_events_enabled_;
+
// Bytes remaining to be read from the socket. Read events should only be
// re-enabled when this drops to zero.
intptr_t available_bytes_;
diff --git a/runtime/bin/exe_utils.cc b/runtime/bin/exe_utils.cc
index 5361a9e..d9333dc 100644
--- a/runtime/bin/exe_utils.cc
+++ b/runtime/bin/exe_utils.cc
@@ -12,6 +12,17 @@
namespace dart {
namespace bin {
+static bool StartsWithPathSeparator(const char* path,
+ const char* sep,
+ intptr_t sep_length) {
+ return (strncmp(path, sep, sep_length) == 0
+#if defined(HOST_OS_WINDOWS)
+ // TODO(aam): GetExecutableName doesn't work reliably on Windows,
+ || *path == '/'
+#endif
+ );
+}
+
// Returns the directory portion of a given path.
//
// If dir is NULL, the result must be freed by the caller. Otherwise, the
@@ -23,12 +34,7 @@
for (intptr_t i = path_len - 1; i >= 0; --i) {
const char* str = path + i;
- if (strncmp(str, sep, sep_length) == 0
-#if defined(HOST_OS_WINDOWS)
- // TODO(aam): GetExecutableName doesn't work reliably on Windows,
- || *str == '/'
-#endif
- ) {
+ if (StartsWithPathSeparator(str, sep, sep_length)) {
if (dir != nullptr) {
strncpy(dir, path, i);
dir[i] = '\0';
@@ -41,6 +47,24 @@
return nullptr;
}
+// Returns the file portion of a given path. Returned string is either
+// `path` if no path separators are found or `path + separator_loc + sep_length`
+// if a separator is found.
+static const char* GetFileNameFromPath(const char* path) {
+ const char* sep = File::PathSeparator();
+ const intptr_t sep_length = strlen(sep);
+ intptr_t path_len = strlen(path);
+
+ for (intptr_t i = path_len - 1; i >= 0; --i) {
+ const char* str = path + i;
+ if (StartsWithPathSeparator(str, sep, sep_length)) {
+ return str + sep_length;
+ }
+ }
+ // No path separators, assume that path is a file name.
+ return path;
+}
+
Utils::CStringUniquePtr EXEUtils::GetDirectoryPrefixFromExeName() {
const char* name = nullptr;
const int kTargetSize = 4096;
@@ -70,7 +94,8 @@
do {
Directory::SetCurrent(namespc, GetDirectoryFromPath(name, dir_path));
// Resolve the link without creating Dart scope String.
- name = File::LinkTarget(namespc, name, target, kTargetSize);
+ name = File::LinkTarget(namespc, GetFileNameFromPath(name), target,
+ kTargetSize);
if (name == nullptr) {
return Utils::CreateCStringUniquePtr(strdup(""));
}
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 58f1d77..bc51eb1 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -33,14 +33,13 @@
// throw ArgumentExceptions.
static bool IsPointerType(const AbstractType& type) {
- return RawObject::IsFfiPointerClassId(type.type_class_id());
+ return IsFfiPointerClassId(type.type_class_id());
}
static void CheckSized(const AbstractType& type_arg) {
const classid_t type_cid = type_arg.type_class_id();
- if (RawObject::IsFfiNativeTypeTypeClassId(type_cid) ||
- RawObject::IsFfiTypeVoidClassId(type_cid) ||
- RawObject::IsFfiTypeNativeFunctionClassId(type_cid)) {
+ if (IsFfiNativeTypeTypeClassId(type_cid) || IsFfiTypeVoidClassId(type_cid) ||
+ IsFfiTypeNativeFunctionClassId(type_cid)) {
const String& error = String::Handle(String::NewFormatted(
"%s does not have a predefined size (@unsized). "
"Unsized NativeTypes do not support [sizeOf] because their size "
@@ -77,7 +76,7 @@
// You must check [IsConcreteNativeType] and [CheckSized] first to verify that
// this type has a defined size.
static size_t SizeOf(const AbstractType& type, Zone* zone) {
- if (RawObject::IsFfiTypeClassId(type.type_class_id())) {
+ if (IsFfiTypeClassId(type.type_class_id())) {
return compiler::ffi::NativeType::FromAbstractType(type, zone)
.SizeInBytes();
} else {
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index e931966..0f114ee 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -22,7 +22,7 @@
#define RETURN_OR_PROPAGATE(expr) \
RawObject* result = expr; \
- if (RawObject::IsErrorClassId(result->GetClassIdMayBeSmi())) { \
+ if (IsErrorClassId(result->GetClassIdMayBeSmi())) { \
Exceptions::PropagateError(Error::Handle(Error::RawCast(result))); \
} \
return result;
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index a41c8fa..bc22233 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -93,10 +93,10 @@
const intptr_t right_cid = right.GetClassId();
if (left_cid != right_cid) {
- if (RawObject::IsIntegerClassId(left_cid)) {
- return Bool::Get(RawObject::IsIntegerClassId(right_cid)).raw();
- } else if (RawObject::IsStringClassId(right_cid)) {
- return Bool::Get(RawObject::IsStringClassId(right_cid)).raw();
+ if (IsIntegerClassId(left_cid)) {
+ return Bool::Get(IsIntegerClassId(right_cid)).raw();
+ } else if (IsStringClassId(right_cid)) {
+ return Bool::Get(IsStringClassId(right_cid)).raw();
} else {
return Bool::False().raw();
}
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 947ba4f..4b262c6 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -430,7 +430,7 @@
Exceptions::ThrowArgumentError(end_obj);
}
return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
- } else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
+ } else if (IsTypedDataViewClassId(list.GetClassId())) {
const auto& view = TypedDataView::Cast(list);
const intptr_t cid = list.GetClassId();
if (cid != kTypedDataUint16ArrayViewCid) {
diff --git a/runtime/platform/BUILD.gn b/runtime/platform/BUILD.gn
index 9a2905c..012421d 100644
--- a/runtime/platform/BUILD.gn
+++ b/runtime/platform/BUILD.gn
@@ -5,9 +5,22 @@
import("../configs.gni")
import("platform_sources.gni")
+if (is_fuchsia) {
+ import("//build/fuchsia/sdk.gni")
+}
+
library_for_all_configs("libdart_platform") {
target_type = "source_set"
public_configs = [ "../vm:libdart_vm_config" ]
sources = platform_sources
include_dirs = [ ".." ]
+ extra_deps = []
+
+ if (is_fuchsia) {
+ if (using_fuchsia_sdk) {
+ extra_deps += [ "$fuchsia_sdk_root/pkg:sys_cpp" ]
+ } else {
+ extra_deps += [ "//sdk/lib/sys/cpp" ]
+ }
+ }
}
diff --git a/runtime/platform/utils_fuchsia.cc b/runtime/platform/utils_fuchsia.cc
index 04e813a..fd1b082 100644
--- a/runtime/platform/utils_fuchsia.cc
+++ b/runtime/platform/utils_fuchsia.cc
@@ -5,7 +5,11 @@
#include "platform/globals.h"
#if defined(HOST_OS_FUCHSIA)
+#include <memory>
+
+#include "lib/sys/cpp/component_context.h"
#include "platform/utils.h"
+#include "platform/utils_fuchsia.h"
namespace dart {
@@ -33,6 +37,12 @@
return retval;
}
+sys::ComponentContext* ComponentContext() {
+ static std::unique_ptr<sys::ComponentContext> context =
+ sys::ComponentContext::Create();
+ return context.get();
+}
+
} // namespace dart
#endif // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/platform/utils_fuchsia.h b/runtime/platform/utils_fuchsia.h
index 7cb3812..4b2064e 100644
--- a/runtime/platform/utils_fuchsia.h
+++ b/runtime/platform/utils_fuchsia.h
@@ -7,6 +7,13 @@
#include <endian.h>
+namespace sys {
+
+// From Fuchsia SDK.
+class ComponentContext;
+
+} // namespace sys
+
namespace dart {
inline uint16_t Utils::HostToBigEndian16(uint16_t value) {
@@ -40,6 +47,16 @@
return buffer;
}
+// Returns the singleton component context for this process.
+//
+// The returned pointer is never null. The caller must not take ownership of
+// the context.
+//
+// The context is a singleton as it can be meaningfully instantiated only once
+// during the lifetime of the program. If you use this function, you MUST NOT
+// call sys::ComponentContext::Create().
+sys::ComponentContext* ComponentContext();
+
} // namespace dart
#endif // RUNTIME_PLATFORM_UTILS_FUCHSIA_H_
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 3078643..4a79fa7 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -10,6 +10,8 @@
// Note: we assume that all builds of Dart VM use exactly the same class ids
// for these classes.
+#include "platform/assert.h"
+
namespace dart {
#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
@@ -227,6 +229,238 @@
const int kTypedDataCidRemainderView = 1;
const int kTypedDataCidRemainderExternal = 2;
+// Class Id predicates.
+
+bool IsErrorClassId(intptr_t index);
+bool IsNumberClassId(intptr_t index);
+bool IsIntegerClassId(intptr_t index);
+bool IsStringClassId(intptr_t index);
+bool IsOneByteStringClassId(intptr_t index);
+bool IsTwoByteStringClassId(intptr_t index);
+bool IsExternalStringClassId(intptr_t index);
+bool IsBuiltinListClassId(intptr_t index);
+bool IsTypedDataBaseClassId(intptr_t index);
+bool IsTypedDataClassId(intptr_t index);
+bool IsTypedDataViewClassId(intptr_t index);
+bool IsExternalTypedDataClassId(intptr_t index);
+bool IsFfiNativeTypeTypeClassId(intptr_t index);
+bool IsFfiPointerClassId(intptr_t index);
+bool IsFfiTypeClassId(intptr_t index);
+bool IsFfiTypeIntClassId(intptr_t index);
+bool IsFfiTypeDoubleClassId(intptr_t index);
+bool IsFfiTypeVoidClassId(intptr_t index);
+bool IsFfiTypeNativeFunctionClassId(intptr_t index);
+bool IsFfiDynamicLibraryClassId(intptr_t index);
+bool IsFfiClassId(intptr_t index);
+bool IsInternalVMdefinedClassId(intptr_t index);
+bool IsVariableSizeClassId(intptr_t index);
+bool IsImplicitFieldClassId(intptr_t index);
+intptr_t NumberOfTypedDataClasses();
+
+inline bool IsErrorClassId(intptr_t index) {
+ // Make sure this function is updated when new Error types are added.
+ COMPILE_ASSERT(
+ kApiErrorCid == kErrorCid + 1 && kLanguageErrorCid == kErrorCid + 2 &&
+ kUnhandledExceptionCid == kErrorCid + 3 &&
+ kUnwindErrorCid == kErrorCid + 4 && kInstanceCid == kErrorCid + 5);
+ return (index >= kErrorCid && index < kInstanceCid);
+}
+
+inline bool IsNumberClassId(intptr_t index) {
+ // Make sure this function is updated when new Number types are added.
+ COMPILE_ASSERT(kIntegerCid == kNumberCid + 1 && kSmiCid == kNumberCid + 2 &&
+ kMintCid == kNumberCid + 3 && kDoubleCid == kNumberCid + 4);
+ return (index >= kNumberCid && index <= kDoubleCid);
+}
+
+inline bool IsIntegerClassId(intptr_t index) {
+ // Make sure this function is updated when new Integer types are added.
+ COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2);
+ return (index >= kIntegerCid && index <= kMintCid);
+}
+
+inline bool IsStringClassId(intptr_t index) {
+ // Make sure this function is updated when new StringCid types are added.
+ COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
+ kTwoByteStringCid == kStringCid + 2 &&
+ kExternalOneByteStringCid == kStringCid + 3 &&
+ kExternalTwoByteStringCid == kStringCid + 4);
+ return (index >= kStringCid && index <= kExternalTwoByteStringCid);
+}
+
+inline bool IsOneByteStringClassId(intptr_t index) {
+ // Make sure this function is updated when new StringCid types are added.
+ COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
+ kTwoByteStringCid == kStringCid + 2 &&
+ kExternalOneByteStringCid == kStringCid + 3 &&
+ kExternalTwoByteStringCid == kStringCid + 4);
+ return (index == kOneByteStringCid || index == kExternalOneByteStringCid);
+}
+
+inline bool IsTwoByteStringClassId(intptr_t index) {
+ // Make sure this function is updated when new StringCid types are added.
+ COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
+ kTwoByteStringCid == kStringCid + 2 &&
+ kExternalOneByteStringCid == kStringCid + 3 &&
+ kExternalTwoByteStringCid == kStringCid + 4);
+ return (index == kTwoByteStringCid || index == kExternalTwoByteStringCid);
+}
+
+inline bool IsExternalStringClassId(intptr_t index) {
+ // Make sure this function is updated when new StringCid types are added.
+ COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
+ kTwoByteStringCid == kStringCid + 2 &&
+ kExternalOneByteStringCid == kStringCid + 3 &&
+ kExternalTwoByteStringCid == kStringCid + 4);
+ return (index == kExternalOneByteStringCid ||
+ index == kExternalTwoByteStringCid);
+}
+
+inline bool IsBuiltinListClassId(intptr_t index) {
+ // Make sure this function is updated when new builtin List types are added.
+ COMPILE_ASSERT(kImmutableArrayCid == kArrayCid + 1);
+ return ((index >= kArrayCid && index <= kImmutableArrayCid) ||
+ (index == kGrowableObjectArrayCid) || IsTypedDataBaseClassId(index) ||
+ (index == kByteBufferCid));
+}
+
+inline bool IsTypedDataBaseClassId(intptr_t index) {
+ // Make sure this is updated when new TypedData types are added.
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
+ return index >= kTypedDataInt8ArrayCid && index < kByteDataViewCid;
+}
+
+inline bool IsTypedDataClassId(intptr_t index) {
+ // Make sure this is updated when new TypedData types are added.
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
+ return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
+ 3) == kTypedDataCidRemainderInternal;
+}
+
+inline bool IsTypedDataViewClassId(intptr_t index) {
+ // Make sure this is updated when new TypedData types are added.
+ COMPILE_ASSERT(kTypedDataInt8ArrayViewCid + 3 == kTypedDataUint8ArrayViewCid);
+
+ const bool is_byte_data_view = index == kByteDataViewCid;
+ return is_byte_data_view ||
+ (IsTypedDataBaseClassId(index) &&
+ ((index - kTypedDataInt8ArrayCid) % 3) == kTypedDataCidRemainderView);
+}
+
+inline bool IsExternalTypedDataClassId(intptr_t index) {
+ // Make sure this is updated when new TypedData types are added.
+ COMPILE_ASSERT(kExternalTypedDataInt8ArrayCid + 3 ==
+ kExternalTypedDataUint8ArrayCid);
+
+ return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
+ 3) == kTypedDataCidRemainderExternal;
+}
+
+inline bool IsFfiNativeTypeTypeClassId(intptr_t index) {
+ return index == kFfiNativeTypeCid;
+}
+
+inline bool IsFfiTypeClassId(intptr_t index) {
+ // Make sure this is updated when new Ffi types are added.
+ COMPILE_ASSERT(kFfiNativeFunctionCid == kFfiPointerCid + 1 &&
+ kFfiInt8Cid == kFfiPointerCid + 2 &&
+ kFfiInt16Cid == kFfiPointerCid + 3 &&
+ kFfiInt32Cid == kFfiPointerCid + 4 &&
+ kFfiInt64Cid == kFfiPointerCid + 5 &&
+ kFfiUint8Cid == kFfiPointerCid + 6 &&
+ kFfiUint16Cid == kFfiPointerCid + 7 &&
+ kFfiUint32Cid == kFfiPointerCid + 8 &&
+ kFfiUint64Cid == kFfiPointerCid + 9 &&
+ kFfiIntPtrCid == kFfiPointerCid + 10 &&
+ kFfiFloatCid == kFfiPointerCid + 11 &&
+ kFfiDoubleCid == kFfiPointerCid + 12 &&
+ kFfiVoidCid == kFfiPointerCid + 13);
+ return (index >= kFfiPointerCid && index <= kFfiVoidCid);
+}
+
+inline bool IsFfiTypeIntClassId(intptr_t index) {
+ return (index >= kFfiInt8Cid && index <= kFfiIntPtrCid);
+}
+
+inline bool IsFfiTypeDoubleClassId(intptr_t index) {
+ return (index >= kFfiFloatCid && index <= kFfiDoubleCid);
+}
+
+inline bool IsFfiPointerClassId(intptr_t index) {
+ return index == kFfiPointerCid;
+}
+
+inline bool IsFfiTypeVoidClassId(intptr_t index) {
+ return index == kFfiVoidCid;
+}
+
+inline bool IsFfiTypeNativeFunctionClassId(intptr_t index) {
+ return index == kFfiNativeFunctionCid;
+}
+
+inline bool IsFfiClassId(intptr_t index) {
+ return (index >= kFfiPointerCid && index <= kFfiVoidCid);
+}
+
+inline bool IsFfiDynamicLibraryClassId(intptr_t index) {
+ return index == kFfiDynamicLibraryCid;
+}
+
+inline bool IsInternalVMdefinedClassId(intptr_t index) {
+ return ((index < kNumPredefinedCids) && !IsImplicitFieldClassId(index));
+}
+
+inline bool IsVariableSizeClassId(intptr_t index) {
+ return (index == kArrayCid) || (index == kImmutableArrayCid) ||
+ IsOneByteStringClassId(index) || IsTwoByteStringClassId(index) ||
+ IsTypedDataClassId(index) || (index == kContextCid) ||
+ (index == kTypeArgumentsCid) || (index == kInstructionsCid) ||
+ (index == kInstructionsSectionCid) || (index == kObjectPoolCid) ||
+ (index == kPcDescriptorsCid) || (index == kCodeSourceMapCid) ||
+ (index == kCompressedStackMapsCid) ||
+ (index == kLocalVarDescriptorsCid) ||
+ (index == kExceptionHandlersCid) || (index == kCodeCid) ||
+ (index == kContextScopeCid) || (index == kInstanceCid) ||
+ (index == kRegExpCid);
+}
+
+// This is a set of classes that are not Dart classes whose representation
+// is defined by the VM but are used in the VM code by computing the
+// implicit field offsets of the various fields in the dart object.
+inline bool IsImplicitFieldClassId(intptr_t index) {
+ return index == kByteBufferCid;
+}
+
+inline intptr_t NumberOfTypedDataClasses() {
+ // Make sure this is updated when new TypedData types are added.
+
+ // Ensure that each typed data type comes in internal/view/external variants
+ // next to each other.
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 == kTypedDataInt8ArrayViewCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 == kExternalTypedDataInt8ArrayCid);
+
+ // Ensure the order of the typed data members in 3-step.
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 * 3 == kTypedDataUint8ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 * 3 ==
+ kTypedDataUint8ClampedArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 * 3 == kTypedDataInt16ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 4 * 3 == kTypedDataUint16ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 5 * 3 == kTypedDataInt32ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 6 * 3 == kTypedDataUint32ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 7 * 3 == kTypedDataInt64ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 8 * 3 == kTypedDataUint64ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 9 * 3 == kTypedDataFloat32ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 10 * 3 == kTypedDataFloat64ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 11 * 3 ==
+ kTypedDataFloat32x4ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 12 * 3 == kTypedDataInt32x4ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 13 * 3 ==
+ kTypedDataFloat64x2ArrayCid);
+ COMPILE_ASSERT(kTypedDataInt8ArrayCid + 14 * 3 == kByteDataViewCid);
+ COMPILE_ASSERT(kByteBufferCid + 1 == kNullCid);
+ return (kNullCid - kTypedDataInt8ArrayCid);
+}
+
} // namespace dart
#endif // RUNTIME_VM_CLASS_ID_H_
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 338cc0a..74a8677 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -447,7 +447,7 @@
}
bool SharedClassTable::ShouldUpdateSizeForClassId(intptr_t cid) {
- return !RawObject::IsVariableSizeClassId(cid);
+ return !IsVariableSizeClassId(cid);
}
intptr_t SharedClassTable::ClassOffsetFor(intptr_t cid) {
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index b498c29..8eca9ce 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -324,7 +324,7 @@
cls->ptr()->binary_declaration_ = d->Read<uint32_t>();
}
#endif
- if (!RawObject::IsInternalVMdefinedClassId(class_id)) {
+ if (!IsInternalVMdefinedClassId(class_id)) {
cls->ptr()->host_instance_size_in_words_ = d->Read<int32_t>();
cls->ptr()->host_next_field_offset_in_words_ = d->Read<int32_t>();
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -1522,7 +1522,7 @@
s->Push(code->ptr()->pc_descriptors_);
s->Push(code->ptr()->catch_entry_);
s->Push(code->ptr()->compressed_stackmaps_);
- if (!FLAG_dwarf_stack_traces_mode) {
+ if (!FLAG_precompiled_mode || !FLAG_dwarf_stack_traces_mode) {
s->Push(code->ptr()->inlined_id_to_function_);
s->Push(code->ptr()->code_source_map_);
}
@@ -1619,7 +1619,7 @@
WriteField(code, pc_descriptors_);
WriteField(code, catch_entry_);
WriteField(code, compressed_stackmaps_);
- if (FLAG_dwarf_stack_traces_mode) {
+ if (FLAG_precompiled_mode && FLAG_dwarf_stack_traces_mode) {
WriteFieldValue(inlined_id_to_function_, Array::null());
WriteFieldValue(code_source_map_, CodeSourceMap::null());
} else {
@@ -4808,13 +4808,13 @@
Push(isolate()->class_table()->At(cid));
return new (Z) InstanceSerializationCluster(cid);
}
- if (RawObject::IsTypedDataViewClassId(cid)) {
+ if (IsTypedDataViewClassId(cid)) {
return new (Z) TypedDataViewSerializationCluster(cid);
}
- if (RawObject::IsExternalTypedDataClassId(cid)) {
+ if (IsExternalTypedDataClassId(cid)) {
return new (Z) ExternalTypedDataSerializationCluster(cid);
}
- if (RawObject::IsTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid)) {
return new (Z) TypedDataSerializationCluster(cid);
}
@@ -5674,13 +5674,13 @@
if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
return new (Z) InstanceDeserializationCluster(cid);
}
- if (RawObject::IsTypedDataViewClassId(cid)) {
+ if (IsTypedDataViewClassId(cid)) {
return new (Z) TypedDataViewDeserializationCluster(cid);
}
- if (RawObject::IsExternalTypedDataClassId(cid)) {
+ if (IsExternalTypedDataClassId(cid)) {
return new (Z) ExternalTypedDataDeserializationCluster(cid);
}
- if (RawObject::IsTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid)) {
return new (Z) TypedDataDeserializationCluster(cid);
}
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 78e6edd..e881bcd 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -1300,9 +1300,28 @@
}
}
-void AotCallSpecializer::TryReplaceWithDispatchTableCall(
+const Function& AotCallSpecializer::InterfaceTargetForTableDispatch(
InstanceCallBaseInstr* call) {
const Function& interface_target = call->interface_target();
+ if (!interface_target.IsNull()) {
+ return interface_target;
+ }
+
+ // Dynamic call or tearoff.
+ const Function& tearoff_interface_target = call->tearoff_interface_target();
+ if (!tearoff_interface_target.IsNull()) {
+ // Tearoff.
+ return Function::ZoneHandle(
+ Z, tearoff_interface_target.GetMethodExtractor(call->function_name()));
+ }
+
+ // Dynamic call.
+ return Function::null_function();
+}
+
+void AotCallSpecializer::TryReplaceWithDispatchTableCall(
+ InstanceCallBaseInstr* call) {
+ const Function& interface_target = InterfaceTargetForTableDispatch(call);
if (interface_target.IsNull()) {
// Dynamic call.
return;
@@ -1333,7 +1352,7 @@
InsertBefore(call, load_cid, call->env(), FlowGraph::kValue);
auto dispatch_table_call = DispatchTableCallInstr::FromCall(
- Z, call, new (Z) Value(load_cid), selector);
+ Z, call, new (Z) Value(load_cid), interface_target, selector);
call->ReplaceWith(dispatch_table_call, current_iterator());
}
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.h b/runtime/vm/compiler/aot/aot_call_specializer.h
index a14acd2..fd23ebf 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.h
+++ b/runtime/vm/compiler/aot/aot_call_specializer.h
@@ -56,6 +56,7 @@
// If a call can be dispatched through the global dispatch table, replace
// it by a dispatch table call.
void TryReplaceWithDispatchTableCall(InstanceCallBaseInstr* call);
+ const Function& InterfaceTargetForTableDispatch(InstanceCallBaseInstr* call);
// Try to replace a call with a more specialized instruction working on
// integers (e.g. BinaryInt64OpInstr, CheckedSmiComparisonInstr,
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.cc b/runtime/vm/compiler/aot/dispatch_table_generator.cc
index 99a21ed..1b24c52 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.cc
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.cc
@@ -366,7 +366,8 @@
kernel::ProcedureAttributesMetadata metadata;
metadata = kernel::ProcedureAttributesOf(interface_target, Z);
return interface_target.IsGetterFunction() ||
- interface_target.IsImplicitGetterFunction()
+ interface_target.IsImplicitGetterFunction() ||
+ interface_target.IsMethodExtractor()
? metadata.getter_selector_id
: metadata.method_or_setter_selector_id;
}
@@ -381,10 +382,12 @@
return selector;
}
-void SelectorMap::AddSelector(int32_t call_count, bool called_on_null) {
+void SelectorMap::AddSelector(int32_t call_count,
+ bool called_on_null,
+ bool torn_off) {
const int32_t added_sid = selectors_.length();
selectors_.Add(TableSelector(added_sid, call_count, kInvalidSelectorOffset,
- called_on_null));
+ called_on_null, torn_off));
}
void SelectorMap::SetSelectorProperties(int32_t sid,
@@ -421,7 +424,8 @@
RELEASE_ASSERT(metadata != nullptr);
for (intptr_t i = 0; i < metadata->selectors.length(); i++) {
const kernel::TableSelectorInfo* info = &metadata->selectors[i];
- selector_map_.AddSelector(info->call_count, info->called_on_null);
+ selector_map_.AddSelector(info->call_count, info->called_on_null,
+ info->torn_off);
}
}
@@ -562,13 +566,29 @@
const int32_t sid = selector_map_.SelectorId(function);
if (sid != SelectorMap::kInvalidSelectorId) {
- // Make a function handle that survives until the table is built.
- auto& function_handle = Function::ZoneHandle(Z, function.raw());
+ auto MakeIntervals = [&](const Function& function, int32_t sid) {
+ // A function handle that survives until the table is built.
+ auto& function_handle = Function::ZoneHandle(Z, function.raw());
- for (intptr_t i = 0; i < subclasss_cid_ranges.length(); i++) {
- Interval& subclass_cid_range = subclasss_cid_ranges[i];
- selector_rows[sid].DefineSelectorImplementationForInterval(
- cid, depth, subclass_cid_range, &function_handle);
+ for (intptr_t i = 0; i < subclasss_cid_ranges.length(); i++) {
+ Interval& subclass_cid_range = subclasss_cid_ranges[i];
+ selector_rows[sid].DefineSelectorImplementationForInterval(
+ cid, depth, subclass_cid_range, &function_handle);
+ }
+ };
+ MakeIntervals(function, sid);
+
+ if (selector_map_.selectors_[sid].torn_off) {
+ const String& method_name = String::Handle(Z, function.name());
+ const String& getter_name =
+ String::Handle(Z, Field::GetterName(method_name));
+ const Function& tearoff = Function::Handle(
+ Z, function.GetMethodExtractor(getter_name));
+ const int32_t tearoff_sid = selector_map_.SelectorId(tearoff);
+
+ if (tearoff_sid != SelectorMap::kInvalidSelectorId) {
+ MakeIntervals(tearoff, tearoff_sid);
+ }
}
}
}
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.h b/runtime/vm/compiler/aot/dispatch_table_generator.h
index f987606..336e532 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.h
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.h
@@ -25,11 +25,13 @@
TableSelector(int32_t _id,
int32_t _call_count,
int32_t _offset,
- bool _called_on_null)
+ bool _called_on_null,
+ bool _torn_off)
: id(_id),
call_count(_call_count),
offset(_offset),
- called_on_null(_called_on_null) {}
+ called_on_null(_called_on_null),
+ torn_off(_torn_off) {}
bool IsUsed() const { return call_count > 0; }
@@ -42,6 +44,8 @@
int32_t offset;
// Are there any call sites with this selector where the receiver may be null?
bool called_on_null;
+ // Is this method ever torn off, i.e. is its method extractor accessed?
+ bool torn_off;
// Is the selector part of the interface on Null (same as Object)?
bool on_null_interface = false;
// Do any targets of this selector assume that an args descriptor is passed?
@@ -63,7 +67,7 @@
int32_t SelectorId(const Function& interface_target) const;
- void AddSelector(int32_t call_count, bool called_on_null);
+ void AddSelector(int32_t call_count, bool called_on_null, bool torn_off);
void SetSelectorProperties(int32_t sid,
bool on_null_interface,
bool requires_args_descriptor);
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index c9be7d3..1137f5c 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -984,60 +984,14 @@
ASSERT(value.IsInstance());
AddConstObject(Instance::Cast(value));
}
-
- if (field.has_nontrivial_initializer()) {
- if (!field.HasInitializerFunction() ||
- !Function::Handle(Z, field.InitializerFunction()).HasCode()) {
- if (FLAG_trace_precompiler) {
- THR_Print("Precompiling initializer for %s\n", field.ToCString());
- }
- const intptr_t gop_offset =
- FLAG_use_bare_instructions
- ? global_object_pool_builder()->CurrentLength()
- : 0;
- ASSERT(Dart::vm_snapshot_kind() != Snapshot::kFullAOT);
- const Function& initializer =
- Function::Handle(Z, CompileStaticInitializer(field));
- ASSERT(!initializer.IsNull());
- field.SetInitializerFunction(initializer);
- AddCalleesOf(initializer, gop_offset);
- }
- }
- }
-}
-
-RawFunction* Precompiler::CompileStaticInitializer(const Field& field) {
- ASSERT(field.is_static());
- Thread* thread = Thread::Current();
- StackZone stack_zone(thread);
- Zone* zone = stack_zone.GetZone();
- ASSERT(Error::Handle(zone, thread->sticky_error()).IsNull());
-
- const Function& initializer_fun =
- Function::ZoneHandle(zone, field.EnsureInitializerFunction());
- ParsedFunction* parsed_function =
- new (zone) ParsedFunction(thread, initializer_fun);
-
- DartCompilationPipeline pipeline;
- PrecompileParsedFunctionHelper helper(Precompiler::Instance(),
- parsed_function,
- /* optimized = */ true);
- if (!helper.Compile(&pipeline)) {
- Error& error = Error::Handle(zone, thread->sticky_error());
- ASSERT(!error.IsNull());
- Jump(error);
- UNREACHABLE();
}
- if ((FLAG_disassemble || FLAG_disassemble_optimized) &&
- FlowGraphPrinter::ShouldPrint(parsed_function->function())) {
- Code& code = Code::Handle(parsed_function->function().CurrentCode());
- Disassembler::DisassembleCode(parsed_function->function(), code,
- /* optimized = */ true);
+ if (field.has_nontrivial_initializer() &&
+ (field.is_static() || field.is_late())) {
+ const Function& initializer =
+ Function::ZoneHandle(Z, field.EnsureInitializerFunction());
+ AddFunction(initializer);
}
-
- ASSERT(Error::Handle(zone, thread->sticky_error()).IsNull());
- return parsed_function->function().raw();
}
bool Precompiler::MustRetainFunction(const Function& function) {
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 24d8c8c..66c091c 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -199,8 +199,6 @@
Zone* zone,
const Function& function);
- static RawFunction* CompileStaticInitializer(const Field& field);
-
// Returns true if get:runtimeType is not overloaded by any class.
bool get_runtime_type_is_unique() const {
return get_runtime_type_is_unique_;
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 11b1099..66855f9 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -668,7 +668,7 @@
Definition* left_defn = instr->left()->definition();
Definition* right_defn = instr->right()->definition();
- if (RawObject::IsIntegerClassId(instr->operation_cid())) {
+ if (IsIntegerClassId(instr->operation_cid())) {
// Fold x == x, and x != x to true/false for numbers comparisons.
Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 2ad41c6..e249c5e 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1234,8 +1234,10 @@
GrowableArray<Definition*>* env) {
Environment* deopt_env =
Environment::From(zone(), *env, num_direct_parameters_, parsed_function_);
- if (instr->IsClosureCall()) {
- // Trim extra input of ClosureCall instruction.
+ if (instr->IsClosureCall() || instr->IsInitInstanceField()) {
+ // Trim extra inputs of ClosureCall and InitInstanceField instructions.
+ // Inputs of those instructions are not pushed onto the stack at the
+ // point where deoptimization can occur.
deopt_env =
deopt_env->DeepCopy(zone(), deopt_env->Length() - instr->InputCount() +
instr->ArgumentCount());
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index bfc7d5b..04e1142 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -755,16 +755,17 @@
void FlowGraphCompiler::AddNullCheck(TokenPosition token_pos,
const String& name) {
- // If we have DWARF stack traces enabled, the AOT runtime is unable to obtain
- // the pool index at runtime. There is therefore no reason to put the name
- // into the pool in the first place.
+#if defined(DART_PRECOMPILER)
+ // If we are generating an AOT snapshot and have DWARF stack traces enabled,
+ // the AOT runtime is unable to obtain the pool index at runtime. Therefore,
+ // there is no reason to put the name into the pool in the first place.
// TODO(dartbug.com/40605): Move this info to the pc descriptors.
- if (!FLAG_dwarf_stack_traces_mode) {
- const intptr_t name_index =
- assembler()->object_pool_builder().FindObject(name);
- code_source_map_builder_->NoteNullCheck(assembler()->CodeSize(), token_pos,
- name_index);
- }
+ if (FLAG_precompiled_mode && FLAG_dwarf_stack_traces_mode) return;
+#endif
+ const intptr_t name_index =
+ assembler()->object_pool_builder().FindObject(name);
+ code_source_map_builder_->NoteNullCheck(assembler()->CodeSize(), token_pos,
+ name_index);
}
void FlowGraphCompiler::AddPcRelativeCallTarget(const Function& function,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 8b42dc0..91ad3ab 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -965,6 +965,7 @@
friend class CheckStackOverflowSlowPath; // For pending_deoptimization_env_.
friend class CheckedSmiSlowPath; // Same.
friend class CheckedSmiComparisonSlowPath; // Same.
+ friend class InitInstanceFieldInstr; // Same.
// Architecture specific implementation of simple native moves.
void EmitNativeMoveArchitecture(const compiler::ffi::NativeLocation& dst,
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 8b9836a..92ef4dc 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2631,8 +2631,7 @@
}
bool LoadFieldInstr::IsFixedLengthArrayCid(intptr_t cid) {
- if (RawObject::IsTypedDataClassId(cid) ||
- RawObject::IsExternalTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid)) {
return true;
}
@@ -4111,7 +4110,12 @@
__ LoadObject(InitInstanceFieldABI::kFieldReg,
Field::ZoneHandle(field().Original()));
- compiler->GenerateStubCall(token_pos(), StubCode::InitInstanceField(),
+ const auto& stub = Code::ZoneHandle(
+ compiler->isolate()->object_store()->init_instance_field_stub());
+ // Instruction inputs are popped from the stack at this point,
+ // so deoptimization environment has to be adjusted.
+ // This adjustment is done in FlowGraph::AttachEnvironment.
+ compiler->GenerateStubCall(token_pos(), stub,
/*kind=*/RawPcDescriptors::kOther, locs(),
deopt_id());
__ Bind(&no_call);
@@ -4688,6 +4692,7 @@
Zone* zone,
const InstanceCallBaseInstr* call,
Value* cid,
+ const Function& interface_target,
const compiler::TableSelector* selector) {
InputsArray* args = new (zone) InputsArray(zone, call->ArgumentCount() + 1);
for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
@@ -4695,7 +4700,7 @@
}
args->Add(cid);
auto dispatch_table_call = new (zone) DispatchTableCallInstr(
- call->token_pos(), call->interface_target(), selector, args,
+ call->token_pos(), interface_target, selector, args,
call->type_args_len(), call->argument_names());
if (call->has_inlining_id()) {
dispatch_table_call->set_inlining_id(call->inlining_id());
@@ -4858,8 +4863,8 @@
const intptr_t start = targets[i].cid_start;
const intptr_t end = targets[i].cid_end;
for (intptr_t cid = start; cid <= end; cid++) {
- is_string = is_string && RawObject::IsStringClassId(cid);
- is_integer = is_integer && RawObject::IsIntegerClassId(cid);
+ is_string = is_string && IsStringClassId(cid);
+ is_integer = is_integer && IsIntegerClassId(cid);
is_double = is_double && (cid == kDoubleCid);
}
}
@@ -5502,9 +5507,8 @@
}
intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) {
- if (RawObject::IsTypedDataClassId(class_id) ||
- RawObject::IsTypedDataViewClassId(class_id) ||
- RawObject::IsExternalTypedDataClassId(class_id)) {
+ if (IsTypedDataClassId(class_id) || IsTypedDataViewClassId(class_id) ||
+ IsExternalTypedDataClassId(class_id)) {
return compiler::target::TypedDataBase::length_offset();
}
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index a0816ba..de48463 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -3854,7 +3854,8 @@
const Array& argument_names,
const ICData* ic_data,
intptr_t deopt_id,
- const Function& interface_target)
+ const Function& interface_target,
+ const Function& tearoff_interface_target)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
@@ -3864,10 +3865,12 @@
function_name_(function_name),
token_kind_(token_kind),
interface_target_(interface_target),
+ tearoff_interface_target_(tearoff_interface_target),
result_type_(nullptr),
has_unique_selector_(false) {
ASSERT(function_name.IsNotTemporaryScopedHandle());
ASSERT(interface_target.IsNotTemporaryScopedHandle());
+ ASSERT(tearoff_interface_target.IsNotTemporaryScopedHandle());
ASSERT(!arguments->is_empty());
ASSERT(Token::IsBinaryOperator(token_kind) ||
Token::IsEqualityOperator(token_kind) ||
@@ -3890,6 +3893,9 @@
const String& function_name() const { return function_name_; }
Token::Kind token_kind() const { return token_kind_; }
const Function& interface_target() const { return interface_target_; }
+ const Function& tearoff_interface_target() const {
+ return tearoff_interface_target_;
+ }
bool has_unique_selector() const { return has_unique_selector_; }
void set_has_unique_selector(bool b) { has_unique_selector_ = b; }
@@ -3968,6 +3974,7 @@
const String& function_name_;
const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL.
const Function& interface_target_;
+ const Function& tearoff_interface_target_;
CompileType* result_type_; // Inferred result type.
bool has_unique_selector_;
Code::EntryKind entry_kind_ = Code::EntryKind::kNormal;
@@ -3988,7 +3995,8 @@
intptr_t checked_argument_count,
const ZoneGrowableArray<const ICData*>& ic_data_array,
intptr_t deopt_id,
- const Function& interface_target = Function::null_function())
+ const Function& interface_target = Function::null_function(),
+ const Function& tearoff_interface_target = Function::null_function())
: InstanceCallBaseInstr(
token_pos,
function_name,
@@ -3998,7 +4006,8 @@
argument_names,
GetICData(ic_data_array, deopt_id, /*is_static_call=*/false),
deopt_id,
- interface_target),
+ interface_target,
+ tearoff_interface_target),
checked_argument_count_(checked_argument_count) {}
InstanceCallInstr(
@@ -4010,7 +4019,8 @@
const Array& argument_names,
intptr_t checked_argument_count,
intptr_t deopt_id,
- const Function& interface_target = Function::null_function())
+ const Function& interface_target = Function::null_function(),
+ const Function& tearoff_interface_target = Function::null_function())
: InstanceCallBaseInstr(token_pos,
function_name,
token_kind,
@@ -4019,7 +4029,8 @@
argument_names,
/*ic_data=*/nullptr,
deopt_id,
- interface_target),
+ interface_target,
+ tearoff_interface_target),
checked_argument_count_(checked_argument_count) {}
DECLARE_INSTRUCTION(InstanceCall)
@@ -4074,7 +4085,8 @@
auto new_call = new (zone) PolymorphicInstanceCallInstr(
call->token_pos(), call->function_name(), call->token_kind(), args,
call->type_args_len(), call->argument_names(), call->ic_data(),
- call->deopt_id(), call->interface_target(), targets, complete);
+ call->deopt_id(), call->interface_target(),
+ call->tearoff_interface_target(), targets, complete);
if (call->has_inlining_id()) {
new_call->set_inlining_id(call->inlining_id());
}
@@ -4127,6 +4139,7 @@
const ICData* ic_data,
intptr_t deopt_id,
const Function& interface_target,
+ const Function& tearoff_interface_target,
const CallTargets& targets,
bool complete)
: InstanceCallBaseInstr(token_pos,
@@ -4137,7 +4150,8 @@
argument_names,
ic_data,
deopt_id,
- interface_target),
+ interface_target,
+ tearoff_interface_target),
targets_(targets),
complete_(complete) {
ASSERT(targets.length() != 0);
@@ -4180,6 +4194,7 @@
Zone* zone,
const InstanceCallBaseInstr* call,
Value* cid,
+ const Function& interface_target,
const compiler::TableSelector* selector);
DECLARE_INSTRUCTION(DispatchTableCall)
@@ -5424,7 +5439,7 @@
element_count_(element_count),
representation_(kTagged) {
ASSERT(element_count == 1 || element_count == 2 || element_count == 4);
- ASSERT(RawObject::IsStringClassId(class_id));
+ ASSERT(IsStringClassId(class_id));
SetInputAt(0, str);
SetInputAt(1, index);
}
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index abc152e..dc524d3 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -1038,9 +1038,14 @@
SExpList* sexp,
const InstrInfo& info) {
auto& interface_target = Function::ZoneHandle(zone());
+ auto& tearoff_interface_target = Function::ZoneHandle(zone());
if (!ParseDartValue(Retrieve(sexp, "interface_target"), &interface_target)) {
return nullptr;
}
+ if (!ParseDartValue(Retrieve(sexp, "tearoff_interface_target"),
+ &tearoff_interface_target)) {
+ return nullptr;
+ }
auto& function_name = String::ZoneHandle(zone());
// If we have an explicit function_name value, then use that value. Otherwise,
// if we have an non-null interface_target, use its name.
@@ -1048,6 +1053,8 @@
if (!ParseDartValue(name_sexp, &function_name)) return nullptr;
} else if (!interface_target.IsNull()) {
function_name = interface_target.name();
+ } else if (!tearoff_interface_target.IsNull()) {
+ function_name = tearoff_interface_target.name();
}
auto token_kind = Token::Kind::kILLEGAL;
@@ -1071,7 +1078,7 @@
auto const inst = new (zone()) InstanceCallInstr(
info.token_pos, function_name, token_kind, call_info.inputs,
call_info.type_args_len, call_info.argument_names, checked_arg_count,
- info.deopt_id, interface_target);
+ info.deopt_id, interface_target, tearoff_interface_target);
if (call_info.result_type != nullptr) {
inst->SetResultType(zone(), *call_info.result_type);
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index cfab7bb..4a4cb57 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -1227,17 +1227,22 @@
sexp->AddExtra("interface_target", target);
}
+ if (auto const target = s->DartValueToSExp(tearoff_interface_target())) {
+ sexp->AddExtra("tearoff_interface_target", target);
+ }
+
if (HasICData()) {
sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data()));
}
if (function_name().IsNull()) {
- if (!interface_target().IsNull()) {
+ if (!interface_target().IsNull() || !tearoff_interface_target().IsNull()) {
s->AddExtraSymbol(sexp, "function_name", "null");
}
} else {
if (interface_target().IsNull() ||
- function_name().raw() != interface_target().name()) {
+ (function_name().raw() != interface_target().name() &&
+ function_name().raw() != tearoff_interface_target().name())) {
s->AddExtraString(sexp, "function_name", function_name().ToCString());
}
}
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index f689b65..5bec543 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -21,6 +21,8 @@
namespace dart {
+Definition* const FlowGraphBuilderHelper::kPhiSelfReference = nullptr;
+
RawLibrary* LoadTestScript(const char* script,
Dart_NativeEntryResolver resolver,
const char* lib_uri) {
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index 5232aabb..779c4df 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -253,7 +253,7 @@
return flow_graph_.GetConstant(Double::Handle(Double::NewCanonical(value)));
}
- static constexpr Definition* kPhiSelfReference = nullptr;
+ static Definition* const kPhiSelfReference;
PhiInstr* Phi(JoinEntryInstr* join,
std::initializer_list<std::pair<BlockEntryInstr*, Definition*>>
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 1daefa0..b4365f0 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2425,7 +2425,7 @@
// Load from the data from backing store which is a fixed-length array.
*array = elements;
array_cid = kArrayCid;
- } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ } else if (IsExternalTypedDataClassId(array_cid)) {
LoadUntaggedInstr* elements = new (Z)
LoadUntaggedInstr(new (Z) Value(*array),
compiler::target::TypedDataBase::data_field_offset());
@@ -2626,9 +2626,8 @@
// Check if store barrier is needed. Byte arrays don't need a store barrier.
StoreBarrierType needs_store_barrier =
- (RawObject::IsTypedDataClassId(array_cid) ||
- RawObject::IsTypedDataViewClassId(array_cid) ||
- RawObject::IsExternalTypedDataClassId(array_cid))
+ (IsTypedDataClassId(array_cid) || IsTypedDataViewClassId(array_cid) ||
+ IsExternalTypedDataClassId(array_cid))
? kNoStoreBarrier
: kEmitStoreBarrier;
@@ -2893,8 +2892,7 @@
intptr_t array_cid,
Definition** array,
Instruction** cursor) {
- if (array_cid == kDynamicCid ||
- RawObject::IsExternalTypedDataClassId(array_cid)) {
+ if (array_cid == kDynamicCid || IsExternalTypedDataClassId(array_cid)) {
// Internal or External typed data: load untagged.
auto elements = new (Z)
LoadUntaggedInstr(new (Z) Value(*array),
@@ -2903,7 +2901,7 @@
*array = elements;
} else {
// Internal typed data: no action.
- ASSERT(RawObject::IsTypedDataClassId(array_cid));
+ ASSERT(IsTypedDataClassId(array_cid));
}
}
@@ -4191,11 +4189,11 @@
Type& type = Type::ZoneHandle(Z);
if (receiver_cid == kDynamicCid) {
return false;
- } else if (RawObject::IsStringClassId(receiver_cid)) {
+ } else if (IsStringClassId(receiver_cid)) {
type = Type::StringType();
} else if (receiver_cid == kDoubleCid) {
type = Type::Double();
- } else if (RawObject::IsIntegerClassId(receiver_cid)) {
+ } else if (IsIntegerClassId(receiver_cid)) {
type = Type::IntType();
} else if (receiver_cid != kClosureCid) {
const Class& cls = Class::Handle(
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index f81e017..b960558 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2769,7 +2769,7 @@
}
void LoadCodeUnitsInstr::InferRange(RangeAnalysis* analysis, Range* range) {
- ASSERT(RawObject::IsStringClassId(class_id()));
+ ASSERT(IsStringClassId(class_id()));
RangeBoundary zero = RangeBoundary::FromConstant(0);
// Take the number of loaded characters into account when determining the
// range of the result.
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index bab1c7a..b54bc57 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -118,9 +118,8 @@
// Note: should only be called with cids of array-like classes.
const Slot& Slot::GetLengthFieldForArrayCid(intptr_t array_cid) {
- if (RawObject::IsExternalTypedDataClassId(array_cid) ||
- RawObject::IsTypedDataClassId(array_cid) ||
- RawObject::IsTypedDataViewClassId(array_cid)) {
+ if (IsExternalTypedDataClassId(array_cid) || IsTypedDataClassId(array_cid) ||
+ IsTypedDataViewClassId(array_cid)) {
return GetNativeSlot(Kind::kTypedDataBase_length);
}
switch (array_cid) {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 9f1ef36..b739030 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1533,9 +1533,8 @@
// instances of the [implementor_].
if (implementor_.is_finalized()) {
const classid_t cid = implementor_.id();
- if (!RawObject::IsTypedDataClassId(cid) &&
- !RawObject::IsTypedDataViewClassId(cid) &&
- !RawObject::IsExternalTypedDataClassId(cid)) {
+ if (!IsTypedDataClassId(cid) && !IsTypedDataViewClassId(cid) &&
+ !IsExternalTypedDataClassId(cid)) {
return true;
}
}
diff --git a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
index af47f51..91acf20 100644
--- a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
@@ -105,11 +105,6 @@
}
}
}
- } else {
- if (field.is_late()) {
- // LoadLateField uses expression_temp_var.
- needs_expr_temp = true;
- }
}
break;
}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 61f3c73..fbc70d0 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1764,9 +1764,9 @@
intptr_t argument_count,
intptr_t checked_argument_count) {
const intptr_t kTypeArgsLen = 0;
- return flow_graph_builder_->InstanceCall(
- position, name, kind, kTypeArgsLen, argument_count, Array::null_array(),
- checked_argument_count, Function::null_function());
+ return flow_graph_builder_->InstanceCall(position, name, kind, kTypeArgsLen,
+ argument_count, Array::null_array(),
+ checked_argument_count);
}
Fragment StreamingFlowGraphBuilder::InstanceCall(
@@ -1778,14 +1778,15 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const Function& tearoff_interface_target,
const InferredTypeMetadata* result_type,
bool use_unchecked_entry,
const CallSiteAttributesMetadata* call_site_attrs,
bool receiver_is_not_smi) {
return flow_graph_builder_->InstanceCall(
position, name, kind, type_args_len, argument_count, argument_names,
- checked_argument_count, interface_target, result_type,
- use_unchecked_entry, call_site_attrs, receiver_is_not_smi);
+ checked_argument_count, interface_target, tearoff_interface_target,
+ result_type, use_unchecked_entry, call_site_attrs, receiver_is_not_smi);
}
Fragment StreamingFlowGraphBuilder::ThrowException(TokenPosition position) {
@@ -2330,6 +2331,7 @@
const String& getter_name = ReadNameAsGetterName(); // read name.
const Function* interface_target = &Function::null_function();
+ const Function* tearoff_interface_target = &Function::null_function();
const NameIndex itarget_name =
ReadCanonicalNameReference(); // read interface_target_reference.
if (!H.IsRoot(itarget_name) &&
@@ -2338,6 +2340,10 @@
Z,
H.LookupMethodByMember(itarget_name, H.DartGetterName(itarget_name)));
ASSERT(getter_name.raw() == interface_target->name());
+ } else if (!H.IsRoot(itarget_name) && H.IsMethod(itarget_name)) {
+ tearoff_interface_target = &Function::ZoneHandle(
+ Z,
+ H.LookupMethodByMember(itarget_name, H.DartMethodName(itarget_name)));
}
if (direct_call.check_receiver_for_null_) {
@@ -2352,9 +2358,10 @@
} else {
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
- instructions += InstanceCall(
- position, getter_name, Token::kGET, kTypeArgsLen, 1,
- Array::null_array(), kNumArgsChecked, *interface_target, &result_type);
+ instructions +=
+ InstanceCall(position, getter_name, Token::kGET, kTypeArgsLen, 1,
+ Array::null_array(), kNumArgsChecked, *interface_target,
+ *tearoff_interface_target, &result_type);
}
if (direct_call.check_receiver_for_null_) {
@@ -2445,6 +2452,7 @@
instructions += InstanceCall(
position, *mangled_name, Token::kSET, kTypeArgsLen, 2,
Array::null_array(), kNumArgsChecked, *interface_target,
+ Function::null_function(),
/*result_type=*/nullptr,
/*use_unchecked_entry=*/is_unchecked_call, &call_site_attributes);
}
@@ -3030,11 +3038,12 @@
argument_names, ICData::kNoRebind, &result_type,
type_args_len, /*use_unchecked_entry=*/is_unchecked_call);
} else {
- instructions += InstanceCall(
- position, *mangled_name, token_kind, type_args_len, argument_count,
- argument_names, checked_argument_count, *interface_target, &result_type,
- /*use_unchecked_entry=*/is_unchecked_call, &call_site_attributes,
- result_type.ReceiverNotInt());
+ instructions +=
+ InstanceCall(position, *mangled_name, token_kind, type_args_len,
+ argument_count, argument_names, checked_argument_count,
+ *interface_target, Function::null_function(), &result_type,
+ /*use_unchecked_entry=*/is_unchecked_call,
+ &call_site_attributes, result_type.ReceiverNotInt());
}
// Drop temporaries preserving result on the top of the stack.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 4a383ad..3b05a70 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -200,6 +200,7 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const Function& tearoff_interface_target,
const InferredTypeMetadata* result_type = nullptr,
bool use_unchecked_entry = false,
const CallSiteAttributesMetadata* call_site_attrs = nullptr,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 7f0f7a1..ba7804d 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -332,16 +332,17 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const Function& tearoff_interface_target,
const InferredTypeMetadata* result_type,
bool use_unchecked_entry,
const CallSiteAttributesMetadata* call_site_attrs,
bool receiver_is_not_smi) {
const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0);
InputsArray* arguments = GetArguments(total_count);
- InstanceCallInstr* call = new (Z)
- InstanceCallInstr(position, name, kind, arguments, type_args_len,
- argument_names, checked_argument_count, ic_data_array_,
- GetNextDeoptId(), interface_target);
+ InstanceCallInstr* call = new (Z) InstanceCallInstr(
+ position, name, kind, arguments, type_args_len, argument_names,
+ checked_argument_count, ic_data_array_, GetNextDeoptId(),
+ interface_target, tearoff_interface_target);
if ((result_type != NULL) && !result_type->IsTrivial()) {
call->SetResultType(Z, result_type->ToCompileType(Z));
}
@@ -434,60 +435,6 @@
}
}
-Fragment FlowGraphBuilder::LoadLateField(const Field& field,
- LocalVariable* instance) {
- Fragment instructions;
- TargetEntryInstr *is_uninitialized, *is_initialized;
- const TokenPosition position = field.token_pos();
- ASSERT(!field.is_static());
-
- // Check whether the field has been initialized already.
- instructions += LoadLocal(instance);
- instructions += LoadField(field);
-
- LocalVariable* temp = parsed_function_->expression_temp_var();
- instructions += StoreLocal(position, temp);
- instructions += Constant(Object::sentinel());
- instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
-
- JoinEntryInstr* join = BuildJoinEntry();
-
- if (field.has_initializer()) {
- // has_nontrivial_initializer is required for EnsureInitializerFunction. The
- // trivial initializer case is treated as a normal field.
- ASSERT(field.has_nontrivial_initializer());
-
- // If the field isn't initialized, call the initializer and set the field.
- Function& init_function =
- Function::ZoneHandle(Z, field.EnsureInitializerFunction());
- Fragment initialize(is_uninitialized);
- initialize += LoadLocal(instance);
- initialize += StaticCall(position, init_function,
- /* argument_count = */ 1, ICData::kNoRebind);
- initialize += StoreLocal(position, temp);
- initialize += Drop();
- initialize += StoreLateField(field, instance, temp);
- initialize += Goto(join);
- } else {
- // The field has no initializer, so throw a LateInitializationError.
- Fragment initialize(is_uninitialized);
- initialize += ThrowLateInitializationError(
- position, String::ZoneHandle(Z, field.name()));
- initialize += Goto(join);
- }
-
- {
- // Already initialized, so there's nothing to do.
- Fragment already_initialized(is_initialized);
- already_initialized += Goto(join);
- }
-
- // Now that the field has been initialized, load it.
- instructions = Fragment(instructions.entry, join);
- instructions += LoadLocal(temp);
- return instructions;
-}
-
Fragment FlowGraphBuilder::ThrowLateInitializationError(TokenPosition position,
const String& name) {
const Class& klass = Class::ZoneHandle(
@@ -563,7 +510,7 @@
Fragment FlowGraphBuilder::InitInstanceField(const Field& field) {
ASSERT(field.is_instance());
- ASSERT(field.needs_load_guard());
+ ASSERT(field.NeedsInitializationCheckOnLoad());
InitInstanceFieldInstr* init = new (Z)
InitInstanceFieldInstr(Pop(), MayCloneField(field), GetNextDeoptId());
return Fragment(init);
@@ -2019,8 +1966,7 @@
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
body += InstanceCall(TokenPosition::kMinSource, getter_name, Token::kGET,
- kTypeArgsLen, 1, Array::null_array(), kNumArgsChecked,
- Function::null_function());
+ kTypeArgsLen, 1, Array::null_array(), kNumArgsChecked);
}
// Push all arguments onto the stack.
@@ -2040,8 +1986,7 @@
const intptr_t kNumArgsChecked = 1;
body += InstanceCall(TokenPosition::kMinSource, Symbols::Call(),
Token::kILLEGAL, descriptor.TypeArgsLen(),
- descriptor.Count(), argument_names, kNumArgsChecked,
- Function::null_function());
+ descriptor.Count(), argument_names, kNumArgsChecked);
}
body += Return(TokenPosition::kNoSource);
@@ -2301,7 +2246,7 @@
body += InstanceCall(
TokenPosition::kNoSource, Symbols::NoSuchMethod(), Token::kILLEGAL,
/*type_args_len=*/0, /*argument_count=*/2, Array::null_array(),
- /*checked_argument_count=*/1, Function::null_function());
+ /*checked_argument_count=*/1);
}
body += StoreLocal(TokenPosition::kNoSource, result);
body += Drop();
@@ -2616,24 +2561,22 @@
}
body += NullConstant();
} else if (is_method) {
+ ASSERT(!field.needs_load_guard()
+ NOT_IN_PRODUCT(|| I->HasAttemptedReload()));
+ if (field.NeedsInitializationCheckOnLoad()) {
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
+ body += InitInstanceField(field);
+ }
+
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
+ body += LoadField(field);
if (field.needs_load_guard()) {
#if defined(PRODUCT)
UNREACHABLE();
#else
- ASSERT(Isolate::Current()->HasAttemptedReload());
- body += LoadLocal(parsed_function_->ParameterVariable(0));
- body += InitInstanceField(field);
-
- body += LoadLocal(parsed_function_->ParameterVariable(0));
- body += LoadField(field);
body += CheckAssignable(AbstractType::Handle(Z, field.type()),
Symbols::FunctionResult());
#endif
- } else if (field.is_late() && !field.has_trivial_initializer()) {
- body += LoadLateField(field, parsed_function_->ParameterVariable(0));
- } else {
- body += LoadLocal(parsed_function_->ParameterVariable(0));
- body += LoadField(field);
}
} else if (field.is_const()) {
// If the parser needs to know the value of an uninitialized constant field
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 9e798c8..0d0c930 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -124,7 +124,8 @@
intptr_t argument_count,
const Array& argument_names,
intptr_t checked_argument_count,
- const Function& interface_target,
+ const Function& interface_target = Function::null_function(),
+ const Function& tearoff_interface_target = Function::null_function(),
const InferredTypeMetadata* result_type = nullptr,
bool use_unchecked_entry = false,
const CallSiteAttributesMetadata* call_site_attrs = nullptr,
@@ -135,7 +136,6 @@
Fragment ThrowException(TokenPosition position);
Fragment RethrowException(TokenPosition position, int catch_try_index);
Fragment LoadLocal(LocalVariable* variable);
- Fragment LoadLateField(const Field& field, LocalVariable* instance);
Fragment StoreLateField(const Field& field,
LocalVariable* instance,
LocalVariable* setter_value);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index c9aa6d8..7ab661a 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1854,7 +1854,9 @@
void TableSelectorMetadataHelper::ReadTableSelectorInfo(
TableSelectorInfo* info) {
info->call_count = helper_->ReadUInt();
- info->called_on_null = helper_->ReadByte() != 0;
+ uint8_t flags = helper_->ReadByte();
+ info->called_on_null = (flags & kCalledOnNullBit) != 0;
+ info->torn_off = (flags & kTornOffBit) != 0;
}
UnboxingInfoMetadataHelper::UnboxingInfoMetadataHelper(
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 6192f88..5aa3f74 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -1056,6 +1056,7 @@
struct TableSelectorInfo {
int call_count = 0;
bool called_on_null = true;
+ bool torn_off = true;
};
// Collection of table selector information for all selectors in the program.
@@ -1081,8 +1082,8 @@
TableSelectorMetadata* GetTableSelectorMetadata(Zone* zone);
private:
- static const int32_t kCalledOnNullBit = 1 << 0;
- static const int32_t kCallCountShift = 1;
+ static const uint8_t kCalledOnNullBit = 1 << 0;
+ static const uint8_t kTornOffBit = 1 << 1;
void ReadTableSelectorInfo(TableSelectorInfo* info);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index ed32087..4663bd8 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -315,11 +315,6 @@
LocalVariable::kTypeCheckedByCaller);
}
}
- } else {
- if (field.is_late()) {
- // LoadLateField uses expression_temp_var.
- needs_expr_temp_ = true;
- }
}
break;
}
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 994b5c7..3a42c2d 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -187,7 +187,7 @@
index = PrepareIndexedOp(flow_graph, &builder, array, index,
Slot::GetLengthFieldForArrayCid(array_cid));
- if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ if (IsExternalTypedDataClassId(array_cid)) {
array = builder.AddDefinition(new LoadUntaggedInstr(
new Value(array), target::TypedDataBase::data_field_offset()));
}
@@ -367,13 +367,13 @@
UNREACHABLE();
}
- if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ if (IsExternalTypedDataClassId(array_cid)) {
array = builder.AddDefinition(new LoadUntaggedInstr(
new Value(array), target::TypedDataBase::data_field_offset()));
}
// No store barrier.
- ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
- RawObject::IsTypedDataClassId(array_cid));
+ ASSERT(IsExternalTypedDataClassId(array_cid) ||
+ IsTypedDataClassId(array_cid));
builder.AddInstruction(new StoreIndexedInstr(
new Value(array), new Value(index), new Value(value), kNoStoreBarrier,
/*index_unboxed=*/false,
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 4f6221e..3dd8271 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -311,8 +311,8 @@
const word RawObject::kBarrierOverlapShift =
dart::RawObject::kBarrierOverlapShift;
-bool RawObject::IsTypedDataClassId(intptr_t cid) {
- return dart::RawObject::IsTypedDataClassId(cid);
+bool IsTypedDataClassId(intptr_t cid) {
+ return dart::IsTypedDataClassId(cid);
}
const word Class::kNoTypeArguments = dart::Class::kNoTypeArguments;
@@ -402,12 +402,12 @@
}
word Instance::DataOffsetFor(intptr_t cid) {
- if (dart::RawObject::IsExternalTypedDataClassId(cid) ||
- dart::RawObject::IsExternalStringClassId(cid)) {
+ if (dart::IsExternalTypedDataClassId(cid) ||
+ dart::IsExternalStringClassId(cid)) {
// Elements start at offset 0 of the external data.
return 0;
}
- if (dart::RawObject::IsTypedDataClassId(cid)) {
+ if (dart::IsTypedDataClassId(cid)) {
return TypedData::data_offset();
}
switch (cid) {
@@ -425,9 +425,8 @@
}
word Instance::ElementSizeFor(intptr_t cid) {
- if (dart::RawObject::IsExternalTypedDataClassId(cid) ||
- dart::RawObject::IsTypedDataClassId(cid) ||
- dart::RawObject::IsTypedDataViewClassId(cid)) {
+ if (dart::IsExternalTypedDataClassId(cid) || dart::IsTypedDataClassId(cid) ||
+ dart::IsTypedDataViewClassId(cid)) {
return dart::TypedDataBase::ElementSizeInBytes(cid);
}
switch (cid) {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 6d3cf56..82ad6d6 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -222,7 +222,7 @@
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& obj = thread->ObjectHandle();
obj = arguments->NativeArgAt(arg_index);
- if (RawObject::IsStringClassId(obj.GetClassId())) {
+ if (IsStringClassId(obj.GetClassId())) {
ASSERT(thread->api_top_scope() != NULL);
*str = Api::NewHandle(thread, obj.raw());
return true;
@@ -2269,14 +2269,14 @@
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
- return RawObject::IsNumberClassId(Api::ClassId(object));
+ return IsNumberClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsInteger(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
- return RawObject::IsIntegerClassId(Api::ClassId(object));
+ return IsIntegerClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsDouble(Dart_Handle object) {
@@ -2297,26 +2297,26 @@
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
- return RawObject::IsStringClassId(Api::ClassId(object));
+ return IsStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
- return RawObject::IsOneByteStringClassId(Api::ClassId(object));
+ return IsOneByteStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
- return RawObject::IsExternalStringClassId(Api::ClassId(object));
+ return IsExternalStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsList(Dart_Handle object) {
DARTSCOPE(Thread::Current());
- if (RawObject::IsBuiltinListClassId(Api::ClassId(object))) {
+ if (IsBuiltinListClassId(Api::ClassId(object))) {
return true;
}
@@ -2389,9 +2389,8 @@
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
intptr_t cid = Api::ClassId(handle);
- return RawObject::IsTypedDataClassId(cid) ||
- RawObject::IsExternalTypedDataClassId(cid) ||
- RawObject::IsTypedDataViewClassId(cid);
+ return IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid) ||
+ IsTypedDataViewClassId(cid);
}
DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle handle) {
@@ -3446,7 +3445,7 @@
return CopyBytes(external_array, offset, native_array, length);
}
}
- if (RawObject::IsTypedDataViewClassId(obj.GetClassId())) {
+ if (IsTypedDataViewClassId(obj.GetClassId())) {
const auto& view = TypedDataView::Cast(obj);
if (view.ElementSizeInBytes() == 1) {
const intptr_t view_length = Smi::Value(view.length());
@@ -3732,8 +3731,7 @@
API_TIMELINE_DURATION(thread);
TransitionNativeToVM transition(thread);
intptr_t class_id = Api::ClassId(object);
- if (RawObject::IsTypedDataClassId(class_id) ||
- RawObject::IsTypedDataViewClassId(class_id)) {
+ if (IsTypedDataClassId(class_id) || IsTypedDataViewClassId(class_id)) {
return GetType(class_id);
}
return Dart_TypedData_kInvalid;
@@ -3745,10 +3743,10 @@
API_TIMELINE_DURATION(thread);
TransitionNativeToVM transition(thread);
intptr_t class_id = Api::ClassId(object);
- if (RawObject::IsExternalTypedDataClassId(class_id)) {
+ if (IsExternalTypedDataClassId(class_id)) {
return GetType(class_id);
}
- if (RawObject::IsTypedDataViewClassId(class_id)) {
+ if (IsTypedDataViewClassId(class_id)) {
// Check if data object of the view is external.
Zone* zone = thread->zone();
const auto& view_obj = Api::UnwrapTypedDataViewHandle(zone, object);
@@ -4001,9 +3999,8 @@
DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) {
DARTSCOPE(Thread::Current());
intptr_t class_id = Api::ClassId(typed_data);
- if (!RawObject::IsExternalTypedDataClassId(class_id) &&
- !RawObject::IsTypedDataViewClassId(class_id) &&
- !RawObject::IsTypedDataClassId(class_id)) {
+ if (!IsExternalTypedDataClassId(class_id) &&
+ !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, typed_data, 'TypedData');
}
Object& result = Object::Handle(Z);
@@ -4066,9 +4063,8 @@
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
intptr_t class_id = Api::ClassId(object);
- if (!RawObject::IsExternalTypedDataClassId(class_id) &&
- !RawObject::IsTypedDataViewClassId(class_id) &&
- !RawObject::IsTypedDataClassId(class_id)) {
+ if (!IsExternalTypedDataClassId(class_id) &&
+ !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, object, 'TypedData');
}
if (type == NULL) {
@@ -4088,7 +4084,7 @@
bool external = false;
T->IncrementNoSafepointScopeDepth();
START_NO_CALLBACK_SCOPE(T);
- if (RawObject::IsExternalTypedDataClassId(class_id)) {
+ if (IsExternalTypedDataClassId(class_id)) {
const ExternalTypedData& obj =
Api::UnwrapExternalTypedDataHandle(Z, object);
ASSERT(!obj.IsNull());
@@ -4096,14 +4092,14 @@
size_in_bytes = length * ExternalTypedData::ElementSizeInBytes(class_id);
data_tmp = obj.DataAddr(0);
external = true;
- } else if (RawObject::IsTypedDataClassId(class_id)) {
+ } else if (IsTypedDataClassId(class_id)) {
const TypedData& obj = Api::UnwrapTypedDataHandle(Z, object);
ASSERT(!obj.IsNull());
length = obj.Length();
size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
data_tmp = obj.DataAddr(0);
} else {
- ASSERT(RawObject::IsTypedDataViewClassId(class_id));
+ ASSERT(IsTypedDataViewClassId(class_id));
const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
ASSERT(!view_obj.IsNull());
Smi& val = Smi::Handle();
@@ -4151,9 +4147,8 @@
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
intptr_t class_id = Api::ClassId(object);
- if (!RawObject::IsExternalTypedDataClassId(class_id) &&
- !RawObject::IsTypedDataViewClassId(class_id) &&
- !RawObject::IsTypedDataClassId(class_id)) {
+ if (!IsExternalTypedDataClassId(class_id) &&
+ !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, object, 'TypedData');
}
T->DecrementNoSafepointScopeDepth();
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 16c875d..621f88b 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -220,7 +220,7 @@
// Returns true if the handle holds an Error.
static bool IsError(Dart_Handle handle) {
- return RawObject::IsErrorClassId(ClassId(handle));
+ return IsErrorClassId(ClassId(handle));
}
static intptr_t ClassId(Dart_Handle handle) {
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 6ac1947..30e127d 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -324,7 +324,7 @@
}
Dart_CObject* ApiMessageReader::CreateDartCObjectString(RawObject* raw) {
- ASSERT(RawObject::IsOneByteStringClassId(raw->GetClassId()));
+ ASSERT(IsOneByteStringClassId(raw->GetClassId()));
RawOneByteString* raw_str = reinterpret_cast<RawOneByteString*>(raw);
intptr_t len = Smi::Value(raw_str->ptr()->length_);
Dart_CObject* object = AllocateDartCObjectString(len);
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index 90555f5..ce28a4b 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -279,10 +279,10 @@
// If we have external typed data we can simply return, since the backing
// store lives in C-heap and will not move. Otherwise we have to update
// the inner pointer.
- if (RawObject::IsTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid)) {
raw_view->RecomputeDataFieldForInternalTypedData();
} else {
- ASSERT(RawObject::IsExternalTypedDataClassId(cid));
+ ASSERT(IsExternalTypedDataClassId(cid));
}
}
}
@@ -530,7 +530,7 @@
memmove(reinterpret_cast<void*>(new_addr),
reinterpret_cast<void*>(old_addr), size);
- if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
+ if (IsTypedDataClassId(new_obj->GetClassId())) {
reinterpret_cast<RawTypedData*>(new_obj)->RecomputeDataField();
}
}
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 0403d54..1ff35e1 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -212,12 +212,12 @@
return old_space_.DataContains(addr);
}
-void Heap::VisitObjects(ObjectVisitor* visitor) const {
+void Heap::VisitObjects(ObjectVisitor* visitor) {
new_space_.VisitObjects(visitor);
old_space_.VisitObjects(visitor);
}
-void Heap::VisitObjectsNoImagePages(ObjectVisitor* visitor) const {
+void Heap::VisitObjectsNoImagePages(ObjectVisitor* visitor) {
new_space_.VisitObjects(visitor);
old_space_.VisitObjectsNoImagePages(visitor);
}
@@ -318,7 +318,7 @@
isolate_group()->VisitStackPointers(visitor, validate_frames);
}
-void Heap::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
+void Heap::VisitObjectPointers(ObjectPointerVisitor* visitor) {
new_space_.VisitObjectPointers(visitor);
old_space_.VisitObjectPointers(visitor);
}
@@ -335,11 +335,11 @@
return old_space_.FindObject(visitor, HeapPage::kData);
}
-RawObject* Heap::FindNewObject(FindObjectVisitor* visitor) const {
+RawObject* Heap::FindNewObject(FindObjectVisitor* visitor) {
return new_space_.FindObject(visitor);
}
-RawObject* Heap::FindObject(FindObjectVisitor* visitor) const {
+RawObject* Heap::FindObject(FindObjectVisitor* visitor) {
// The visitor must not allocate from the heap.
NoSafepointScope no_safepoint_scope;
RawObject* raw_obj = FindNewObject(visitor);
@@ -702,7 +702,7 @@
void Heap::CollectOnNthAllocation(intptr_t num_allocations) {
// Prevent generated code from using the TLAB fast path on next allocation.
- new_space_.AbandonRemainingTLAB(Thread::Current());
+ new_space_.AbandonRemainingTLABForDebugging(Thread::Current());
gc_on_nth_allocation_ = num_allocations;
}
@@ -735,13 +735,12 @@
gc_on_nth_allocation_ = kNoForcedGarbageCollection;
} else {
// Prevent generated code from using the TLAB fast path on next allocation.
- new_space_.AbandonRemainingTLAB(Thread::Current());
+ new_space_.AbandonRemainingTLABForDebugging(Thread::Current());
}
}
-ObjectSet* Heap::CreateAllocatedObjectSet(
- Zone* zone,
- MarkExpectation mark_expectation) const {
+ObjectSet* Heap::CreateAllocatedObjectSet(Zone* zone,
+ MarkExpectation mark_expectation) {
ObjectSet* allocated_set = new (zone) ObjectSet(zone);
this->AddRegionsToObjectSet(allocated_set);
@@ -768,13 +767,14 @@
return allocated_set;
}
-bool Heap::Verify(MarkExpectation mark_expectation) const {
+bool Heap::Verify(MarkExpectation mark_expectation) {
HeapIterationScope heap_iteration_scope(Thread::Current());
return VerifyGC(mark_expectation);
}
-bool Heap::VerifyGC(MarkExpectation mark_expectation) const {
- StackZone stack_zone(Thread::Current());
+bool Heap::VerifyGC(MarkExpectation mark_expectation) {
+ auto thread = Thread::Current();
+ StackZone stack_zone(thread);
// Change the new space's top_ with the more up-to-date thread's view of top_
new_space_.MakeNewSpaceIterable();
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 34ab784..09f7584 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -116,8 +116,8 @@
// Returns null object if nothing is found.
RawInstructions* FindObjectInCodeSpace(FindObjectVisitor* visitor) const;
RawObject* FindOldObject(FindObjectVisitor* visitor) const;
- RawObject* FindNewObject(FindObjectVisitor* visitor) const;
- RawObject* FindObject(FindObjectVisitor* visitor) const;
+ RawObject* FindNewObject(FindObjectVisitor* visitor);
+ RawObject* FindObject(FindObjectVisitor* visitor);
void NotifyIdle(int64_t deadline);
void NotifyLowMemory();
@@ -173,7 +173,7 @@
static const char* RegionName(Space space);
// Verify that all pointers in the heap point to the heap.
- bool Verify(MarkExpectation mark_expectation = kForbidMarked) const;
+ bool Verify(MarkExpectation mark_expectation = kForbidMarked);
// Print heap sizes.
void PrintSizes() const;
@@ -192,7 +192,7 @@
intptr_t Collections(Space space) const;
ObjectSet* CreateAllocatedObjectSet(Zone* zone,
- MarkExpectation mark_expectation) const;
+ MarkExpectation mark_expectation);
static const char* GCTypeToString(GCType type);
static const char* GCReasonToString(GCReason reason);
@@ -352,17 +352,17 @@
// Visit all pointers. Caller must ensure concurrent sweeper is not running,
// and the visitor must not allocate.
- void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
+ void VisitObjectPointers(ObjectPointerVisitor* visitor);
// Visit all objects, including FreeListElement "objects". Caller must ensure
// concurrent sweeper is not running, and the visitor must not allocate.
- void VisitObjects(ObjectVisitor* visitor) const;
- void VisitObjectsNoImagePages(ObjectVisitor* visitor) const;
+ void VisitObjects(ObjectVisitor* visitor);
+ void VisitObjectsNoImagePages(ObjectVisitor* visitor);
void VisitObjectsImagePages(ObjectVisitor* visitor) const;
// Like Verify, but does not wait for concurrent sweeper, so caller must
// ensure thread-safety.
- bool VerifyGC(MarkExpectation mark_expectation = kForbidMarked) const;
+ bool VerifyGC(MarkExpectation mark_expectation = kForbidMarked);
// Helper functions for garbage collection.
void CollectNewSpaceGarbage(Thread* thread, GCReason reason);
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 1ca8bd9..5c8e620 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -133,7 +133,7 @@
const uword view_header =
*reinterpret_cast<uword*>(RawObject::ToAddr(view));
ASSERT(!IsForwarding(view_header) || view->IsOldObject());
- ASSERT(RawObject::IsTypedDataViewClassId(view->GetClassIdMayBeSmi()));
+ ASSERT(IsTypedDataViewClassId(view->GetClassIdMayBeSmi()));
// Validate that the backing store is not a forwarding word.
RawTypedDataBase* td = view->ptr()->typed_data_;
@@ -146,12 +146,12 @@
// If we have external typed data we can simply return since the backing
// store lives in C-heap and will not move.
- if (RawObject::IsExternalTypedDataClassId(cid)) {
+ if (IsExternalTypedDataClassId(cid)) {
return;
}
// Now we update the inner pointer.
- ASSERT(RawObject::IsTypedDataClassId(cid));
+ ASSERT(IsTypedDataClassId(cid));
view->RecomputeDataFieldForInternalTypedData();
}
@@ -237,8 +237,15 @@
thread_ = nullptr;
}
- uword last_top() { return labs_[producer_index_].top; }
- uword last_end() { return labs_[producer_index_].end; }
+ void DonateTLABs() {
+ MutexLocker ml(&scavenger_->space_lock_);
+ // NOTE: We could make all [labs_] re-usable after a scavenge if we remember
+ // the promotion pointer of each TLAB.
+ const auto& lab = labs_[producer_index_];
+ if (lab.end == scavenger_->top_) {
+ scavenger_->top_ = lab.top;
+ }
+ }
private:
void UpdateStoreBuffer(RawObject** p, RawObject* obj) {
@@ -324,7 +331,7 @@
}
intptr_t cid = RawObject::ClassIdTag::decode(header);
- if (RawObject::IsTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid)) {
reinterpret_cast<RawTypedData*>(new_obj)->RecomputeDataField();
}
@@ -856,7 +863,8 @@
heap_->isolate_group()->ForEachIsolate(
[&](Isolate* isolate) {
Thread* mutator_thread = isolate->mutator_thread();
- ASSERT((mutator_thread == NULL) || (!mutator_thread->HasActiveTLAB()));
+ ASSERT(mutator_thread == nullptr ||
+ mutator_thread->tlab().IsAbandoned());
},
/*at_safepoint=*/true);
@@ -1301,49 +1309,72 @@
}
}
-void Scavenger::MakeNewSpaceIterable() const {
+void Scavenger::MakeNewSpaceIterable() {
ASSERT(Thread::Current()->IsAtSafepoint() ||
(Thread::Current()->task_kind() == Thread::kMarkerTask) ||
(Thread::Current()->task_kind() == Thread::kCompactorTask));
auto isolate_group = heap_->isolate_group();
MonitorLocker ml(isolate_group->threads_lock(), false);
+
+ // Make all scheduled thread's TLABs iterable.
Thread* current = heap_->isolate_group()->thread_registry()->active_list();
while (current != NULL) {
- if (current->HasActiveTLAB()) {
- heap_->new_space()->MakeTLABIterable(current);
+ const TLAB tlab = current->tlab();
+ if (!tlab.IsAbandoned()) {
+ MakeTLABIterable(tlab);
}
current = current->next();
}
+
+ // All unscheduled mutator threads should have already abnadoned their TLABs.
isolate_group->ForEachIsolate(
[&](Isolate* isolate) {
Thread* mutator_thread = isolate->mutator_thread();
if (mutator_thread != NULL) {
- heap_->new_space()->MakeTLABIterable(mutator_thread);
+ if (isolate->scheduled_mutator_thread_ == nullptr) {
+ RELEASE_ASSERT(mutator_thread->tlab().IsAbandoned());
+ }
}
},
/*at_safepoint=*/true);
+
+ for (intptr_t i = 0; i < free_tlabs_.length(); ++i) {
+ MakeTLABIterable(free_tlabs_[i]);
+ }
}
void Scavenger::AbandonTLABsLocked() {
ASSERT(Thread::Current()->IsAtSafepoint());
IsolateGroup* isolate_group = heap_->isolate_group();
MonitorLocker ml(isolate_group->threads_lock(), false);
+
+ // Abandon TLABs of all scheduled threads.
Thread* current = isolate_group->thread_registry()->active_list();
while (current != NULL) {
- AbandonRemainingTLABLocked(current);
+ const TLAB tlab = current->tlab();
+ AddAbandonedInBytesLocked(tlab.RemainingSize());
+ current->set_tlab(TLAB());
current = current->next();
}
+ // All unscheduled mutator threads should have already abandoned their TLAB.
isolate_group->ForEachIsolate(
[&](Isolate* isolate) {
Thread* mutator_thread = isolate->mutator_thread();
if (mutator_thread != NULL) {
- AbandonRemainingTLABLocked(mutator_thread);
+ if (isolate->scheduled_mutator_thread_ == nullptr) {
+ RELEASE_ASSERT(mutator_thread->tlab().IsAbandoned());
+ }
}
},
/*at_safepoint=*/true);
+
+ while (free_tlabs_.length() > 0) {
+ const TLAB tlab = free_tlabs_.RemoveLast();
+ AddAbandonedInBytesLocked(tlab.RemainingSize());
+ }
}
-void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
+void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
ASSERT(Thread::Current()->IsAtSafepoint() ||
(Thread::Current()->task_kind() == Thread::kMarkerTask) ||
(Thread::Current()->task_kind() == Thread::kCompactorTask));
@@ -1355,7 +1386,7 @@
}
}
-void Scavenger::VisitObjects(ObjectVisitor* visitor) const {
+void Scavenger::VisitObjects(ObjectVisitor* visitor) {
ASSERT(Thread::Current()->IsAtSafepoint() ||
(Thread::Current()->task_kind() == Thread::kMarkerTask));
MakeNewSpaceIterable();
@@ -1371,7 +1402,7 @@
set->AddRegion(to_->start(), to_->end());
}
-RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const {
+RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) {
ASSERT(!scavenging_);
MakeNewSpaceIterable();
uword cur = FirstObjectStart();
@@ -1393,7 +1424,13 @@
ASSERT(heap_ != Dart::vm_isolate()->heap());
ASSERT(!scavenging_);
MutexLocker ml(&space_lock_);
- AbandonRemainingTLABLocked(thread);
+
+ // We might need a new TLAB not because the current TLAB is empty but because
+ // we failed to allocate alarge object in new space. So in case the remaining
+ // TLAB is still big enough to be useful we cache it.
+ CacheTLABLocked(thread->tlab());
+ thread->set_tlab(TLAB());
+
uword result = top_;
intptr_t remaining = end_ - top_;
intptr_t size = kTLABSize;
@@ -1403,6 +1440,7 @@
}
ASSERT(Utils::IsAligned(size, kObjectAlignment));
if (size == 0) {
+ thread->set_tlab(TryAcquireCachedTLABLocked());
return;
}
ASSERT(to_->Contains(result));
@@ -1410,35 +1448,26 @@
top_ += size;
ASSERT(to_->Contains(top_) || (top_ == to_->end()));
ASSERT(result < top_);
- thread->set_top(result);
- thread->set_end(top_);
+ thread->set_tlab(TLAB(result, top_));
}
-void Scavenger::MakeTLABIterable(Thread* thread) {
- uword start = thread->top();
- uword end = thread->end();
- ASSERT(end >= start);
- intptr_t size = end - start;
+void Scavenger::MakeTLABIterable(const TLAB& tlab) {
+ ASSERT(tlab.end >= tlab.top);
+ const intptr_t size = tlab.RemainingSize();
ASSERT(Utils::IsAligned(size, kObjectAlignment));
if (size >= kObjectAlignment) {
// ForwardingCorpse(forwarding to default null) will work as filler.
- ForwardingCorpse::AsForwarder(start, size);
- ASSERT(RawObject::FromAddr(start)->HeapSize() == size);
+ ForwardingCorpse::AsForwarder(tlab.top, size);
+ ASSERT(RawObject::FromAddr(tlab.top)->HeapSize() == size);
}
}
-void Scavenger::AbandonRemainingTLAB(Thread* thread) {
- MakeTLABIterable(thread);
- AddAbandonedInBytes(thread->end() - thread->top());
- thread->set_top(0);
- thread->set_end(0);
-}
-
-void Scavenger::AbandonRemainingTLABLocked(Thread* thread) {
- MakeTLABIterable(thread);
- AddAbandonedInBytesLocked(thread->end() - thread->top());
- thread->set_top(0);
- thread->set_end(0);
+void Scavenger::AbandonRemainingTLABForDebugging(Thread* thread) {
+ MutexLocker ml(&space_lock_);
+ const TLAB tlab = thread->tlab();
+ MakeTLABIterable(tlab);
+ AddAbandonedInBytesLocked(tlab.RemainingSize());
+ thread->set_tlab(TLAB());
}
template <bool parallel>
@@ -1484,6 +1513,35 @@
return true;
}
+TLAB Scavenger::TryAcquireCachedTLABLocked() {
+ if (free_tlabs_.length() == 0) {
+ return TLAB();
+ }
+ return free_tlabs_.RemoveLast();
+}
+
+void Scavenger::CacheTLABLocked(TLAB tlab) {
+ // If the memory following this TLAB is the unused new space, we'll merge the
+ // bytes into there.
+ if (tlab.end == top_) {
+ top_ = tlab.top;
+ return;
+ }
+
+ MakeTLABIterable(tlab);
+
+ // If this TLAB is lare enough to be useful in the future, we'll make it
+ // reusable, otherwise we abandon it.
+ const uword size = tlab.RemainingSize();
+ if (size > (50 * KB)) {
+ free_tlabs_.Add(tlab);
+ return;
+ }
+
+ // Else we discard the memory.
+ AddAbandonedInBytesLocked(size);
+}
+
void Scavenger::Scavenge() {
int64_t start = OS::GetCurrentMonotonicMicros();
@@ -1560,13 +1618,8 @@
visitor.ProcessAll();
}
visitor.Finalize();
+ visitor.DonateTLABs();
- // Donate last bit of TLAB.
- uword top = visitor.last_top();
- uword end = visitor.last_end();
- if (end == top_) {
- top_ = top;
- }
return visitor.bytes_promoted();
}
@@ -1600,12 +1653,7 @@
for (intptr_t i = 0; i < num_tasks; i++) {
bytes_promoted += visitors[i]->bytes_promoted();
- // Donate last bit of TLAB.
- uword top = visitors[i]->last_top();
- uword end = visitors[i]->last_end();
- if (end == top_) {
- top_ = top;
- }
+ visitors[i]->DonateTLABs();
delete visitors[i];
}
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 138a1a6..0e23b5d 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -7,10 +7,12 @@
#include "platform/assert.h"
#include "platform/utils.h"
+
#include "vm/dart.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/heap/spaces.h"
+#include "vm/heap/tlab.h"
#include "vm/lockers.h"
#include "vm/raw_object.h"
#include "vm/ring_buffer.h"
@@ -128,7 +130,7 @@
// be part of the surviving objects.
bool Contains(uword addr) const { return to_->Contains(addr); }
- RawObject* FindObject(FindObjectVisitor* visitor) const;
+ RawObject* FindObject(FindObjectVisitor* visitor);
uword TryAllocate(Thread* thread, intptr_t size) {
uword addr = TryAllocateFromTLAB(thread, size);
@@ -138,11 +140,26 @@
TryAllocateNewTLAB(thread);
return TryAllocateFromTLAB(thread, size);
}
- void MakeTLABIterable(Thread* thread);
- void AbandonRemainingTLAB(Thread* thread);
+ void MakeTLABIterable(const TLAB& tlab);
+ void AbandonRemainingTLABForDebugging(Thread* thread);
template <bool parallel>
bool TryAllocateNewTLAB(ScavengerVisitorBase<parallel>* visitor);
+ // When a thread gets scheduled it will try to acquire a TLAB.
+ void TryAcquireCachedTLAB(Thread* thread) {
+ MutexLocker ml(&space_lock_);
+ thread->set_tlab(TryAcquireCachedTLABLocked());
+ }
+ TLAB TryAcquireCachedTLABLocked();
+
+ // When a thread gets unscheduled it will release it's TLAB.
+ void ReleaseAndCacheTLAB(Thread* thread) {
+ MutexLocker ml(&space_lock_);
+ CacheTLABLocked(thread->tlab());
+ thread->set_tlab(TLAB());
+ }
+ void CacheTLABLocked(TLAB tlab);
+
// Collect the garbage in this scavenger.
void Scavenge();
@@ -175,8 +192,8 @@
return usage;
}
- void VisitObjects(ObjectVisitor* visitor) const;
- void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
+ void VisitObjects(ObjectVisitor* visitor);
+ void VisitObjectPointers(ObjectPointerVisitor* visitor);
void AddRegionsToObjectSet(ObjectSet* set) const;
@@ -199,7 +216,7 @@
void AllocateExternal(intptr_t cid, intptr_t size);
void FreeExternal(intptr_t size);
- void MakeNewSpaceIterable() const;
+ void MakeNewSpaceIterable();
int64_t FreeSpaceInWords(Isolate* isolate) const;
void InitGrowthControl() {
@@ -236,23 +253,22 @@
uword TryAllocateFromTLAB(Thread* thread, intptr_t size) {
ASSERT(Utils::IsAligned(size, kObjectAlignment));
ASSERT(heap_ != Dart::vm_isolate()->heap());
- uword top = thread->top();
- uword end = thread->end();
- uword result = top;
- intptr_t remaining = end - top;
+ TLAB tlab = thread->tlab();
+ const intptr_t remaining = tlab.RemainingSize();
if (UNLIKELY(remaining < size)) {
return 0;
}
+
+ const uword result = tlab.top;
ASSERT(to_->Contains(result));
ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
- top += size;
- ASSERT((to_->Contains(top)) || (top == to_->end()));
- thread->set_top(top);
+ const uword new_top = tlab.top + size;
+ ASSERT(to_->Contains(new_top) || new_top == to_->end());
+ thread->set_tlab(tlab.BumpAllocate(size));
return result;
}
void TryAllocateNewTLAB(Thread* thread);
void AddAbandonedInBytesLocked(intptr_t value) { abandoned_ += value; }
- void AbandonRemainingTLABLocked(Thread* thread);
void AbandonTLABsLocked();
uword FirstObjectStart() const {
@@ -286,6 +302,9 @@
uword top_;
uword end_;
+ MallocGrowableArray<TLAB> abandoned_tlabs_;
+ MallocGrowableArray<TLAB> free_tlabs_;
+
SemiSpace* to_;
Heap* heap_;
diff --git a/runtime/vm/heap/tlab.h b/runtime/vm/heap/tlab.h
new file mode 100644
index 0000000..d186831
--- /dev/null
+++ b/runtime/vm/heap/tlab.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_HEAP_TLAB_H_
+#define RUNTIME_VM_HEAP_TLAB_H_
+
+#include "platform/assert.h"
+#include "platform/globals.h"
+
+namespace dart {
+
+struct TLAB {
+ TLAB() : top(0), end(0) {}
+ TLAB(uword top, uword end) : top(top), end(end) {}
+ TLAB(const TLAB& other) : top(other.top), end(other.end) {}
+ TLAB& operator=(const TLAB& other) {
+ top = other.top;
+ end = other.end;
+ return *this;
+ }
+
+ intptr_t RemainingSize() const { return end - top; }
+ bool IsAbandoned() const { return top == 0 && end == 0; }
+
+ TLAB BumpAllocate(intptr_t size) const {
+ ASSERT(RemainingSize() >= size);
+ return TLAB(top + size, end);
+ }
+
+ uword top;
+ uword end;
+};
+
+} // namespace dart
+
+#endif // RUNTIME_VM_HEAP_TLAB_H_
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index bc009ec..21044dc 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -271,17 +271,18 @@
ASSERT(instance_size > 0);
ASSERT(Utils::IsAligned(instance_size, kObjectAlignment));
- const uword start = thread->top();
+ const TLAB tlab = thread->tlab();
#ifndef PRODUCT
auto table = thread->isolate_group()->shared_class_table();
if (UNLIKELY(table->TraceAllocationFor(class_id))) {
return false;
}
#endif
- const intptr_t remaining = thread->end() - start;
+ const intptr_t remaining = tlab.RemainingSize();
if (LIKELY(remaining >= instance_size)) {
- thread->set_top(start + instance_size);
- *result = InitializeHeader(start, class_id, instance_size);
+ const uword old_top = tlab.top;
+ thread->set_tlab(tlab.BumpAllocate(instance_size));
+ *result = InitializeHeader(old_top, class_id, instance_size);
return true;
}
return false;
@@ -646,7 +647,7 @@
}
UNREACHABLE();
}
- if (RawObject::IsErrorClassId(result_cid)) {
+ if (IsErrorClassId(result_cid)) {
// Unwind to entry frame.
fp_ = *FP;
pc_ = SavedCallerPC(fp_);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 46fe80d..6af9e05 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -419,6 +419,8 @@
os_thread->set_thread(thread);
Thread::SetCurrent(thread);
os_thread->EnableThreadInterrupts();
+
+ thread->heap()->new_space()->TryAcquireCachedTLAB(thread);
}
return thread;
}
@@ -427,10 +429,11 @@
Thread* thread,
bool is_mutator,
bool bypass_safepoint) {
+ thread->heap()->new_space()->ReleaseAndCacheTLAB(thread);
+
// Clear since GC will not visit the thread once it is unscheduled. Do this
// under the thread lock to prevent races with the GC visiting thread roots.
if (!is_mutator) {
- thread->heap()->new_space()->AbandonRemainingTLAB(thread);
thread->ClearReusableHandles();
}
@@ -676,7 +679,7 @@
!class_table()->HasValidClassAt(cid)) {
continue;
}
- if ((cid == kTypeArgumentsCid) || RawObject::IsStringClassId(cid)) {
+ if ((cid == kTypeArgumentsCid) || IsStringClassId(cid)) {
// TypeArguments and Symbols have special tables for canonical objects
// that aren't based on address.
continue;
@@ -2397,12 +2400,6 @@
// since we're just going to delete it anyway).
isolate_group->UnregisterIsolate(isolate);
- // Since the death of this isolate is not the death of the heap, we have to
- // leave the new space iterable (e.g. for old space marking) by abanoning the
- // TLAB.
- isolate->group()->heap()->new_space()->AbandonRemainingTLAB(
- Thread::Current());
-
// From this point on the isolate doesn't participate in safepointing
// requests anymore.
Thread::ExitIsolate();
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index 133f8bf..19b5101 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -11,6 +11,7 @@
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/os_thread.h"
+#include "vm/port_set.h"
#include "vm/thread_pool.h"
namespace dart {
@@ -211,6 +212,8 @@
friend class MessageHandlerTestPeer;
friend class MessageHandlerTask;
+ struct PortSetEntry : public PortSet<PortSetEntry>::Entry {};
+
// Called by MessageHandlerTask to process our task queue.
void TaskCallback();
@@ -248,6 +251,8 @@
// thread.
bool oob_message_handling_allowed_;
bool paused_for_messages_;
+ PortSet<PortSetEntry>
+ ports_; // Only accessed by [PortMap], protected by [PortMap]s lock.
intptr_t live_ports_; // The number of open ports, including control ports.
intptr_t paused_; // The number of pause messages received.
#if !defined(PRODUCT)
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 47582a1..ccfc289 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -92,8 +92,7 @@
bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) {
RawObject* retval = arguments->ReturnValue();
- return (retval->IsHeapObject() &&
- RawObject::IsErrorClassId(retval->GetClassId()));
+ return (retval->IsHeapObject() && IsErrorClassId(retval->GetClassId()));
}
void NativeEntry::PropagateErrors(NativeArguments* arguments) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index db8ab2a..373f524 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2546,7 +2546,7 @@
} else {
uword initial_value;
bool needs_init;
- if (RawObject::IsTypedDataBaseClassId(class_id)) {
+ if (IsTypedDataBaseClassId(class_id)) {
initial_value = 0;
// If the size is greater than both kNewAllocatableSize and
// kAllocatablePageSize, the object must have been allocated to a new
@@ -4424,7 +4424,7 @@
}
RawClass* Class::NewTypedDataClass(intptr_t class_id, Isolate* isolate) {
- ASSERT(RawObject::IsTypedDataClassId(class_id));
+ ASSERT(IsTypedDataClassId(class_id));
const intptr_t host_instance_size = TypedData::InstanceSize();
const intptr_t target_instance_size =
compiler::target::RoundedAllocationSize(RTN::TypedData::InstanceSize());
@@ -4442,7 +4442,7 @@
}
RawClass* Class::NewTypedDataViewClass(intptr_t class_id, Isolate* isolate) {
- ASSERT(RawObject::IsTypedDataViewClassId(class_id));
+ ASSERT(IsTypedDataViewClassId(class_id));
const intptr_t host_instance_size = TypedDataView::InstanceSize();
const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
RTN::TypedDataView::InstanceSize());
@@ -4462,7 +4462,7 @@
RawClass* Class::NewExternalTypedDataClass(intptr_t class_id,
Isolate* isolate) {
- ASSERT(RawObject::IsExternalTypedDataClassId(class_id));
+ ASSERT(IsExternalTypedDataClassId(class_id));
const intptr_t host_instance_size = ExternalTypedData::InstanceSize();
const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
RTN::ExternalTypedData::InstanceSize());
@@ -4481,7 +4481,7 @@
}
RawClass* Class::NewPointerClass(intptr_t class_id, Isolate* isolate) {
- ASSERT(RawObject::IsFfiPointerClassId(class_id));
+ ASSERT(IsFfiPointerClassId(class_id));
intptr_t host_instance_size = Pointer::InstanceSize();
intptr_t target_instance_size =
compiler::target::RoundedAllocationSize(RTN::Pointer::InstanceSize());
@@ -7175,7 +7175,7 @@
intptr_t string_specialization_cid,
bool sticky) const {
ASSERT(kind() == RawFunction::kIrregexpFunction);
- ASSERT(RawObject::IsStringClassId(string_specialization_cid));
+ ASSERT(IsStringClassId(string_specialization_cid));
ASSERT(raw_ptr()->data_ == Object::null());
const Array& pair = Array::Handle(Array::New(2, Heap::kOld));
pair.SetAt(0, regexp);
@@ -9126,17 +9126,11 @@
return true;
}
- // Method extractors are always called dynamically (for now).
- // See dartbug.com/40188.
- if (IsMethodExtractor()) {
- return true;
- }
-
// Use the results of TFA to determine whether this function is ever
// called dynamically, i.e. using switchable calls.
kernel::ProcedureAttributesMetadata metadata;
metadata = kernel::ProcedureAttributesOf(*this, zone);
- if (IsGetterFunction() || IsImplicitGetterFunction()) {
+ if (IsGetterFunction() || IsImplicitGetterFunction() || IsMethodExtractor()) {
return metadata.getter_called_dynamically;
} else {
return metadata.method_or_setter_called_dynamically;
@@ -9926,6 +9920,10 @@
return Error::Cast(value).raw();
}
} else {
+ if (is_late() && !has_initializer()) {
+ Exceptions::ThrowLateInitializationError(String::Handle(name()));
+ UNREACHABLE();
+ }
#if defined(DART_PRECOMPILED_RUNTIME)
UNREACHABLE();
#else
@@ -9933,6 +9931,11 @@
#endif
}
ASSERT(value.IsNull() || value.IsInstance());
+ if (is_late() && is_final() &&
+ (instance.GetField(*this) != Object::sentinel().raw())) {
+ Exceptions::ThrowLateInitializationError(String::Handle(name()));
+ UNREACHABLE();
+ }
instance.SetField(*this, value);
return Error::null();
}
@@ -10001,9 +10004,8 @@
}
static intptr_t GetListLengthOffset(intptr_t cid) {
- if (RawObject::IsTypedDataClassId(cid) ||
- RawObject::IsTypedDataViewClassId(cid) ||
- RawObject::IsExternalTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid) || IsTypedDataViewClassId(cid) ||
+ IsExternalTypedDataClassId(cid)) {
return TypedData::length_offset();
} else if (cid == kArrayCid || cid == kImmutableArrayCid) {
return Array::length_offset();
@@ -10034,8 +10036,7 @@
Class::Handle(Isolate::Current()->class_table()->At(guarded_cid()));
const char* class_name = String::Handle(cls.Name()).ToCString();
- if (RawObject::IsBuiltinListClassId(guarded_cid()) && !is_nullable() &&
- is_final()) {
+ if (IsBuiltinListClassId(guarded_cid()) && !is_nullable() && is_final()) {
ASSERT(guarded_list_length() != kUnknownFixedLength);
if (guarded_list_length() == kNoFixedLength) {
return zone->PrintToString("<%s [*]%s>", class_name, exactness);
@@ -18151,9 +18152,8 @@
}
intptr_t Instance::ElementSizeFor(intptr_t cid) {
- if (RawObject::IsExternalTypedDataClassId(cid) ||
- RawObject::IsTypedDataClassId(cid) ||
- RawObject::IsTypedDataViewClassId(cid)) {
+ if (IsExternalTypedDataClassId(cid) || IsTypedDataClassId(cid) ||
+ IsTypedDataViewClassId(cid)) {
return TypedDataBase::ElementSizeInBytes(cid);
}
switch (cid) {
@@ -18175,12 +18175,11 @@
}
intptr_t Instance::DataOffsetFor(intptr_t cid) {
- if (RawObject::IsExternalTypedDataClassId(cid) ||
- RawObject::IsExternalStringClassId(cid)) {
+ if (IsExternalTypedDataClassId(cid) || IsExternalStringClassId(cid)) {
// Elements start at offset 0 of the external data.
return 0;
}
- if (RawObject::IsTypedDataClassId(cid)) {
+ if (IsTypedDataClassId(cid)) {
return TypedData::data_offset();
}
switch (cid) {
@@ -20967,7 +20966,7 @@
uint16_t String::CharAt(intptr_t index) const {
intptr_t class_id = raw()->GetClassId();
- ASSERT(RawObject::IsStringClassId(class_id));
+ ASSERT(IsStringClassId(class_id));
if (class_id == kOneByteStringCid) {
return OneByteString::CharAt(*this, index);
}
@@ -23218,7 +23217,7 @@
}
bool Pointer::IsPointer(const Instance& obj) {
- return RawObject::IsFfiPointerClassId(obj.raw()->GetClassId());
+ return IsFfiPointerClassId(obj.raw()->GetClassId());
}
bool Instance::IsPointer() const {
@@ -23543,16 +23542,11 @@
#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
static void PrintStackTraceFrameBodyFromDSO(ZoneTextBuffer* buffer,
- uword call_addr,
- bool print_virtual_address) {
+ uword call_addr) {
uword dso_base;
char* dso_name;
if (NativeSymbolResolver::LookupSharedObject(call_addr, &dso_base,
&dso_name)) {
- uword dso_offset = call_addr - dso_base;
- if (print_virtual_address) {
- buffer->Printf(" virt %" Pp "", dso_offset);
- }
uword symbol_start;
if (auto const symbol_name =
NativeSymbolResolver::LookupSymbolName(call_addr, &symbol_start)) {
@@ -23662,8 +23656,7 @@
if (function.IsNull()) {
#if defined(DART_PRECOMPILED_RUNTIME)
PrintStackTraceFrameIndex(&buffer, frame_index);
- PrintStackTraceFrameBodyFromDSO(&buffer, pc - 1,
- /*print_virtual_address=*/false);
+ PrintStackTraceFrameBodyFromDSO(&buffer, pc - 1);
frame_index++;
#else
UNREACHABLE();
@@ -23767,8 +23760,7 @@
uword return_addr = start + pc_offset;
uword call_addr = return_addr - 1;
buffer.Printf(" #%02" Pd " abs %" Pp "", frame_index, call_addr);
- PrintStackTraceFrameBodyFromDSO(&buffer, call_addr,
- /*print_virtual_address=*/true);
+ PrintStackTraceFrameBodyFromDSO(&buffer, call_addr);
frame_index++;
}
}
@@ -23801,11 +23793,11 @@
DEFINE_FLAG_HANDLER(DwarfStackTracesHandler,
dwarf_stack_traces,
- "Emit DWARF line number and inlining info in dylib "
- "snapshots and don't symbolize stack traces.");
+ "Omit CodeSourceMaps in precompiled snapshots and don't "
+ "symbolize stack traces in the precompiled runtime.");
const char* StackTrace::ToCString() const {
-#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_PRECOMPILED_RUNTIME)
if (FLAG_dwarf_stack_traces_mode) {
return ToDwarfCString(*this);
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index fad2bef..3b6f97a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3372,7 +3372,7 @@
if (is_native() && kind() == RawFunction::kConstructor) {
// This is a native factory constructor.
const Class& klass = Class::Handle(Owner());
- return RawObject::IsTypedDataViewClassId(klass.id());
+ return IsTypedDataViewClassId(klass.id());
}
return false;
}
@@ -4132,6 +4132,10 @@
bool NeedsSetter() const;
bool NeedsGetter() const;
+ bool NeedsInitializationCheckOnLoad() const {
+ return needs_load_guard() || (is_late() && !has_trivial_initializer());
+ }
+
const char* GuardedPropertiesAsCString() const;
intptr_t UnboxedFieldCid() const { return guarded_cid(); }
@@ -8586,7 +8590,7 @@
}
bool IsExternal() const {
- return RawObject::IsExternalStringClassId(raw()->GetClassId());
+ return IsExternalStringClassId(raw()->GetClassId());
}
void* GetPeer() const;
@@ -9709,16 +9713,16 @@
static TypedDataElementType ElementType(classid_t cid) {
if (cid == kByteDataViewCid) {
return kUint8ArrayElement;
- } else if (RawObject::IsTypedDataClassId(cid)) {
+ } else if (IsTypedDataClassId(cid)) {
const intptr_t index =
(cid - kTypedDataInt8ArrayCid - kTypedDataCidRemainderInternal) / 3;
return static_cast<TypedDataElementType>(index);
- } else if (RawObject::IsTypedDataViewClassId(cid)) {
+ } else if (IsTypedDataViewClassId(cid)) {
const intptr_t index =
(cid - kTypedDataInt8ArrayCid - kTypedDataCidRemainderView) / 3;
return static_cast<TypedDataElementType>(index);
} else {
- ASSERT(RawObject::IsExternalTypedDataClassId(cid));
+ ASSERT(IsExternalTypedDataClassId(cid));
const intptr_t index =
(cid - kTypedDataInt8ArrayCid - kTypedDataCidRemainderExternal) / 3;
return static_cast<TypedDataElementType>(index);
@@ -9809,12 +9813,12 @@
}
static intptr_t MaxElements(intptr_t class_id) {
- ASSERT(RawObject::IsTypedDataClassId(class_id));
+ ASSERT(IsTypedDataClassId(class_id));
return (kSmiMax / ElementSizeInBytes(class_id));
}
static intptr_t MaxNewSpaceElements(intptr_t class_id) {
- ASSERT(RawObject::IsTypedDataClassId(class_id));
+ ASSERT(IsTypedDataClassId(class_id));
return (Heap::kNewAllocatableSize - sizeof(RawTypedData)) /
ElementSizeInBytes(class_id);
}
@@ -9873,7 +9877,7 @@
static bool IsTypedData(const Instance& obj) {
ASSERT(!obj.IsNull());
intptr_t cid = obj.raw()->GetClassId();
- return RawObject::IsTypedDataClassId(cid);
+ return IsTypedDataClassId(cid);
}
protected:
@@ -9942,7 +9946,7 @@
}
static intptr_t MaxElements(intptr_t class_id) {
- ASSERT(RawObject::IsExternalTypedDataClassId(class_id));
+ ASSERT(IsExternalTypedDataClassId(class_id));
return (kSmiMax / ElementSizeInBytes(class_id));
}
@@ -9958,7 +9962,7 @@
static bool IsExternalTypedData(const Instance& obj) {
ASSERT(!obj.IsNull());
intptr_t cid = obj.raw()->GetClassId();
- return RawObject::IsExternalTypedDataClassId(cid);
+ return IsExternalTypedDataClassId(cid);
}
protected:
@@ -10005,9 +10009,8 @@
static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
const auto& data = Instance::Handle(Data(view_obj));
intptr_t cid = data.raw()->GetClassId();
- ASSERT(RawObject::IsTypedDataClassId(cid) ||
- RawObject::IsExternalTypedDataClassId(cid));
- return RawObject::IsExternalTypedDataClassId(cid);
+ ASSERT(IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid));
+ return IsExternalTypedDataClassId(cid);
}
static intptr_t data_offset() {
@@ -10024,8 +10027,7 @@
intptr_t offset_in_bytes,
intptr_t length) {
const classid_t cid = typed_data.GetClassId();
- ASSERT(RawObject::IsTypedDataClassId(cid) ||
- RawObject::IsExternalTypedDataClassId(cid));
+ ASSERT(IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid));
StorePointer(&raw_ptr()->typed_data_, typed_data.raw());
StoreSmi(&raw_ptr()->length_, Smi::New(length));
StoreSmi(&raw_ptr()->offset_in_bytes_, Smi::New(offset_in_bytes));
@@ -10126,7 +10128,7 @@
static bool IsDynamicLibrary(const Instance& obj) {
ASSERT(!obj.IsNull());
intptr_t cid = obj.raw()->GetClassId();
- return RawObject::IsFfiDynamicLibraryClassId(cid);
+ return IsFfiDynamicLibraryClassId(cid);
}
void* GetHandle() const {
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index e568c4a..ff147cb 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -890,11 +890,11 @@
} else if (cid == kObjectPoolCid) {
writer_->WriteUnsigned(kLengthData);
writer_->WriteUnsigned(static_cast<RawObjectPool*>(obj)->ptr()->length_);
- } else if (RawObject::IsTypedDataClassId(cid)) {
+ } else if (IsTypedDataClassId(cid)) {
writer_->WriteUnsigned(kLengthData);
writer_->WriteUnsigned(
Smi::Value(static_cast<RawTypedData*>(obj)->ptr()->length_));
- } else if (RawObject::IsExternalTypedDataClassId(cid)) {
+ } else if (IsExternalTypedDataClassId(cid)) {
writer_->WriteUnsigned(kLengthData);
writer_->WriteUnsigned(
Smi::Value(static_cast<RawExternalTypedData*>(obj)->ptr()->length_));
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index e2381e9..102581e 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -195,6 +195,7 @@
RW(Code, assert_boolean_stub) \
RW(Code, instance_of_stub) \
RW(Code, init_static_field_stub) \
+ RW(Code, init_instance_field_stub) \
RW(Code, call_closure_no_such_method_stub) \
RW(Code, default_tts_stub) \
RW(Code, default_nullable_tts_stub) \
@@ -244,6 +245,7 @@
DO(re_throw_stub, ReThrow) \
DO(assert_boolean_stub, AssertBoolean) \
DO(init_static_field_stub, InitStaticField) \
+ DO(init_instance_field_stub, InitInstanceField) \
DO(instance_of_stub, InstanceOf)
#define ISOLATE_OBJECT_STORE_FIELD_LIST(R_, RW) \
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index 826a8c5..140121d 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -17,58 +17,10 @@
namespace dart {
Mutex* PortMap::mutex_ = NULL;
-PortMap::Entry* PortMap::map_ = NULL;
+PortSet<PortMap::Entry>* PortMap::ports_ = NULL;
MessageHandler* PortMap::deleted_entry_ = reinterpret_cast<MessageHandler*>(1);
-intptr_t PortMap::capacity_ = 0;
-intptr_t PortMap::used_ = 0;
-intptr_t PortMap::deleted_ = 0;
Random* PortMap::prng_ = NULL;
-intptr_t PortMap::FindPort(Dart_Port port) {
- // ILLEGAL_PORT (0) is used as a sentinel value in Entry.port. The loop below
- // could return the index to a deleted port when we are searching for
- // port id ILLEGAL_PORT. Return -1 immediately to indicate the port
- // does not exist.
- if (port == ILLEGAL_PORT) {
- return -1;
- }
- ASSERT(port != ILLEGAL_PORT);
- intptr_t index = port % capacity_;
- intptr_t start_index = index;
- Entry entry = map_[index];
- while (entry.handler != NULL) {
- if (entry.port == port) {
- return index;
- }
- index = (index + 1) % capacity_;
- // Prevent endless loops.
- ASSERT(index != start_index);
- entry = map_[index];
- }
- return -1;
-}
-
-void PortMap::Rehash(intptr_t new_capacity) {
- Entry* new_ports = new Entry[new_capacity];
- memset(new_ports, 0, new_capacity * sizeof(Entry));
-
- for (intptr_t i = 0; i < capacity_; i++) {
- Entry entry = map_[i];
- // Skip free and deleted entries.
- if (entry.port != 0) {
- intptr_t new_index = entry.port % new_capacity;
- while (new_ports[new_index].port != 0) {
- new_index = (new_index + 1) % new_capacity;
- }
- new_ports[new_index] = entry;
- }
- }
- delete[] map_;
- map_ = new_ports;
- capacity_ = new_capacity;
- deleted_ = 0;
-}
-
const char* PortMap::PortStateString(PortState kind) {
switch (kind) {
case kNewPort:
@@ -96,23 +48,34 @@
// an object pointer as a port id never produces a used port id.
const Dart_Port kMask2 = 0x3;
result = (prng_->NextUInt64() & kMask1) | kMask2;
+
+ // The two special marker ports are used for the hashset implementation and
+ // cannot be used as actual ports.
+ if (result == PortSet<Entry>::kFreePort ||
+ result == PortSet<Entry>::kDeletedPort) {
+ continue;
+ }
+
ASSERT(!reinterpret_cast<RawObject*>(result)->IsWellFormed());
- } while (FindPort(result) >= 0);
+ } while (ports_->Contains(result));
ASSERT(result != 0);
- ASSERT(FindPort(result) < 0);
+ ASSERT(!ports_->Contains(result));
return result;
}
void PortMap::SetPortState(Dart_Port port, PortState state) {
MutexLocker ml(mutex_);
- intptr_t index = FindPort(port);
- ASSERT(index >= 0);
- PortState old_state = map_[index].state;
+
+ auto it = ports_->TryLookup(port);
+ ASSERT(it != ports_->end());
+
+ Entry& entry = *it;
+ PortState old_state = entry.state;
ASSERT(old_state == kNewPort);
- map_[index].state = state;
+ entry.state = state;
if (state == kLivePort) {
- map_[index].handler->increment_live_ports();
+ entry.handler->increment_live_ports();
}
if (FLAG_trace_isolates) {
OS::PrintErr(
@@ -120,19 +83,7 @@
"\thandler: %s\n"
"\tport: %" Pd64 "\n",
PortStateString(old_state), PortStateString(state),
- map_[index].handler->name(), port);
- }
-}
-
-void PortMap::MaintainInvariants() {
- intptr_t empty = capacity_ - used_ - deleted_;
- if (used_ > ((capacity_ / 4) * 3)) {
- // Grow the port map.
- Rehash(capacity_ * 2);
- } else if (empty < deleted_) {
- // Rehash without growing the table to flush the deleted slots out of the
- // map.
- Rehash(capacity_);
+ entry.handler->name(), port);
}
}
@@ -143,37 +94,19 @@
handler->CheckAccess();
#endif
+ const Dart_Port port = AllocatePort();
+
+ // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
+ // by the [PortMap::mutex_] we already hold.
+ MessageHandler::PortSetEntry isolate_entry;
+ isolate_entry.port = port;
+ handler->ports_.Insert(isolate_entry);
+
Entry entry;
- entry.port = AllocatePort();
+ entry.port = port;
entry.handler = handler;
entry.state = kNewPort;
-
- // Search for the first unused slot. Make use of the knowledge that here is
- // currently no port with this id in the port map.
- ASSERT(FindPort(entry.port) < 0);
- intptr_t index = entry.port % capacity_;
- Entry cur = map_[index];
- // Stop the search at the first found unused (free or deleted) slot.
- while (cur.port != 0) {
- index = (index + 1) % capacity_;
- cur = map_[index];
- }
-
- // Insert the newly created port at the index.
- ASSERT(index >= 0);
- ASSERT(index < capacity_);
- ASSERT(map_[index].port == 0);
- ASSERT((map_[index].handler == NULL) ||
- (map_[index].handler == deleted_entry_));
- if (map_[index].handler == deleted_entry_) {
- // Consuming a deleted entry.
- deleted_--;
- }
- map_[index] = entry;
-
- // Increment number of used slots and grow if necessary.
- used_++;
- MaintainInvariants();
+ ports_->Insert(entry);
if (FLAG_trace_isolates) {
OS::PrintErr(
@@ -190,31 +123,33 @@
MessageHandler* handler = NULL;
{
MutexLocker ml(mutex_);
- intptr_t index = FindPort(port);
- if (index < 0) {
+ auto it = ports_->TryLookup(port);
+ if (it == ports_->end()) {
return false;
}
- ASSERT(index < capacity_);
- ASSERT(map_[index].port != 0);
- ASSERT(map_[index].handler != deleted_entry_);
- ASSERT(map_[index].handler != NULL);
+ Entry entry = *it;
+ handler = entry.handler;
+ ASSERT(handler != nullptr);
- handler = map_[index].handler;
#if defined(DEBUG)
handler->CheckAccess();
#endif
- // Before releasing the lock mark the slot in the map as deleted. This makes
- // it possible to release the port map lock before flushing all of its
- // pending messages below.
- map_[index].port = 0;
- map_[index].handler = deleted_entry_;
- if (map_[index].state == kLivePort) {
+
+ if (entry.state == kLivePort) {
handler->decrement_live_ports();
}
- used_--;
- deleted_++;
- MaintainInvariants();
+ // Delete the port entry before releasing the lock to avoid holding the lock
+ // while flushing the messages below.
+ it.Delete();
+ ports_->Rebalance();
+
+ // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
+ // by the [PortMap::mutex_] we already hold.
+ auto isolate_it = handler->ports_.TryLookup(port);
+ ASSERT(isolate_it != handler->ports_.end());
+ isolate_it.Delete();
+ handler->ports_.Rebalance();
}
handler->ClosePort(port);
if (!handler->HasLivePorts() && handler->OwnedByPortMap()) {
@@ -227,19 +162,23 @@
void PortMap::ClosePorts(MessageHandler* handler) {
{
MutexLocker ml(mutex_);
- for (intptr_t i = 0; i < capacity_; i++) {
- if (map_[i].handler == handler) {
- // Mark the slot as deleted.
- map_[i].port = 0;
- map_[i].handler = deleted_entry_;
- if (map_[i].state == kLivePort) {
- handler->decrement_live_ports();
- }
- used_--;
- deleted_++;
+ // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
+ // by the [PortMap::mutex_] we already hold.
+ for (auto isolate_it = handler->ports_.begin();
+ isolate_it != handler->ports_.end(); ++isolate_it) {
+ auto it = ports_->TryLookup((*isolate_it).port);
+ ASSERT(it != ports_->end());
+ Entry entry = *it;
+ ASSERT(entry.port == (*isolate_it).port);
+ ASSERT(entry.handler == handler);
+ if (entry.state == kLivePort) {
+ handler->decrement_live_ports();
}
+ it.Delete();
+ isolate_it.Delete();
}
- MaintainInvariants();
+ ASSERT(handler->ports_.IsEmpty());
+ ports_->Rebalance();
}
handler->CloseAllPorts();
}
@@ -247,80 +186,76 @@
bool PortMap::PostMessage(std::unique_ptr<Message> message,
bool before_events) {
MutexLocker ml(mutex_);
- intptr_t index = FindPort(message->dest_port());
- if (index < 0) {
+ auto it = ports_->TryLookup(message->dest_port());
+ if (it == ports_->end()) {
// Ownership of external data remains with the poster.
message->DropFinalizers();
return false;
}
- ASSERT(index >= 0);
- ASSERT(index < capacity_);
- MessageHandler* handler = map_[index].handler;
- ASSERT(map_[index].port != 0);
- ASSERT((handler != NULL) && (handler != deleted_entry_));
+ MessageHandler* handler = (*it).handler;
+ ASSERT(handler != nullptr);
handler->PostMessage(std::move(message), before_events);
return true;
}
bool PortMap::IsLocalPort(Dart_Port id) {
MutexLocker ml(mutex_);
- intptr_t index = FindPort(id);
- if (index < 0) {
+ auto it = ports_->TryLookup(id);
+ if (it == ports_->end()) {
// Port does not exist.
return false;
}
- MessageHandler* handler = map_[index].handler;
+ MessageHandler* handler = (*it).handler;
+ ASSERT(handler != nullptr);
return handler->IsCurrentIsolate();
}
Isolate* PortMap::GetIsolate(Dart_Port id) {
MutexLocker ml(mutex_);
- intptr_t index = FindPort(id);
- if (index < 0) {
+ auto it = ports_->TryLookup(id);
+ if (it == ports_->end()) {
// Port does not exist.
- return NULL;
+ return nullptr;
}
- MessageHandler* handler = map_[index].handler;
+ MessageHandler* handler = (*it).handler;
return handler->isolate();
}
void PortMap::Init() {
+ // TODO(bkonyi): don't keep ports_ after Dart_Cleanup.
if (mutex_ == NULL) {
mutex_ = new Mutex();
}
ASSERT(mutex_ != NULL);
- prng_ = new Random();
-
- static const intptr_t kInitialCapacity = 8;
- // TODO(iposva): Verify whether we want to keep exponentially growing.
- ASSERT(Utils::IsPowerOfTwo(kInitialCapacity));
- if (map_ == NULL) {
- // TODO(bkonyi): don't keep map_ after Dart_Cleanup.
- map_ = new Entry[kInitialCapacity];
- capacity_ = kInitialCapacity;
+ if (prng_ == nullptr) {
+ prng_ = new Random();
}
- memset(map_, 0, capacity_ * sizeof(Entry));
- used_ = 0;
- deleted_ = 0;
+ if (ports_ == nullptr) {
+ ports_ = new PortSet<Entry>();
+ }
}
void PortMap::Cleanup() {
- ASSERT(map_ != NULL);
+ ASSERT(ports_ != nullptr);
ASSERT(prng_ != NULL);
- for (intptr_t i = 0; i < capacity_; ++i) {
- auto handler = map_[i].handler;
- if (handler != NULL && handler != deleted_entry_) {
- ClosePorts(handler);
- delete handler;
+ for (auto it = ports_->begin(); it != ports_->end(); ++it) {
+ const auto& entry = *it;
+ ASSERT(entry.handler != nullptr);
+ if (entry.state == kLivePort) {
+ entry.handler->decrement_live_ports();
}
+ delete entry.handler;
+ it.Delete();
}
+ ports_->Rebalance();
+
delete prng_;
prng_ = NULL;
// TODO(bkonyi): find out why deleting map_ sometimes causes crashes.
- // delete[] map_;
- // map_ = NULL;
+ // delete ports_;
+ // ports_ = nullptr;
}
void PortMap::PrintPortsForMessageHandler(MessageHandler* handler,
@@ -332,13 +267,13 @@
{
JSONArray ports(&jsobj, "ports");
SafepointMutexLocker ml(mutex_);
- for (intptr_t i = 0; i < capacity_; i++) {
- if (map_[i].handler == handler) {
- if (map_[i].state == kLivePort) {
+ for (auto& entry : *ports_) {
+ if (entry.handler == handler) {
+ if (entry.state == kLivePort) {
JSONObject port(&ports);
port.AddProperty("type", "_Port");
- port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", map_[i].port);
- msg_handler = DartLibraryCalls::LookupHandler(map_[i].port);
+ port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", entry.port);
+ msg_handler = DartLibraryCalls::LookupHandler(entry.port);
port.AddProperty("handler", msg_handler);
}
}
@@ -350,11 +285,11 @@
void PortMap::DebugDumpForMessageHandler(MessageHandler* handler) {
SafepointMutexLocker ml(mutex_);
Object& msg_handler = Object::Handle();
- for (intptr_t i = 0; i < capacity_; i++) {
- if (map_[i].handler == handler) {
- if (map_[i].state == kLivePort) {
- OS::PrintErr("Live Port = %" Pd64 "\n", map_[i].port);
- msg_handler = DartLibraryCalls::LookupHandler(map_[i].port);
+ for (auto& entry : *ports_) {
+ if (entry.handler == handler) {
+ if (entry.state == kLivePort) {
+ OS::PrintErr("Live Port = %" Pd64 "\n", entry.port);
+ msg_handler = DartLibraryCalls::LookupHandler(entry.port);
OS::PrintErr("Handler = %s\n", msg_handler.ToCString());
}
}
diff --git a/runtime/vm/port.h b/runtime/vm/port.h
index 155e3832..1d9c88e 100644
--- a/runtime/vm/port.h
+++ b/runtime/vm/port.h
@@ -11,6 +11,7 @@
#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/json_stream.h"
+#include "vm/port_set.h"
#include "vm/random.h"
namespace dart {
@@ -68,15 +69,12 @@
private:
friend class dart::PortMapTestPeer;
- // Mapping between port numbers and handlers.
- //
- // Free entries have id == 0 and handler == NULL. Deleted entries
- // have id == 0 and handler == deleted_entry_.
- typedef struct {
- Dart_Port port;
+ struct Entry : public PortSet<Entry>::Entry {
+ Entry() : handler(nullptr), state(kNewPort) {}
+
MessageHandler* handler;
PortState state;
- } Entry;
+ };
static const char* PortStateString(PortState state);
@@ -86,20 +84,11 @@
static bool IsActivePort(Dart_Port id);
static bool IsLivePort(Dart_Port id);
- static intptr_t FindPort(Dart_Port port);
- static void Rehash(intptr_t new_capacity);
-
- static void MaintainInvariants();
-
// Lock protecting access to the port map.
static Mutex* mutex_;
- // Hashmap of ports.
- static Entry* map_;
+ static PortSet<Entry>* ports_;
static MessageHandler* deleted_entry_;
- static intptr_t capacity_;
- static intptr_t used_;
- static intptr_t deleted_;
static Random* prng_;
};
diff --git a/runtime/vm/port_set.h b/runtime/vm/port_set.h
new file mode 100644
index 0000000..97a2c9a
--- /dev/null
+++ b/runtime/vm/port_set.h
@@ -0,0 +1,235 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_PORT_SET_H_
+#define RUNTIME_VM_PORT_SET_H_
+
+#include "include/dart_api.h"
+
+#include "platform/globals.h"
+#include "platform/utils.h"
+
+namespace dart {
+
+template <typename T /* :public PortSet<T>::Entry */>
+class PortSet {
+ public:
+ static constexpr Dart_Port kFreePort = static_cast<Dart_Port>(0);
+ static constexpr Dart_Port kDeletedPort = static_cast<Dart_Port>(3);
+
+ struct Entry {
+ Entry() : port(kFreePort) {}
+
+ // Free entries have set this to 0.
+ Dart_Port port;
+ };
+
+ class Iterator {
+ public:
+ Iterator(PortSet<T>* ports, intptr_t index) : ports_(ports), index_(index) {
+#if defined(DEBUG)
+ dirty_counter_ = ports_->dirty_counter_;
+#endif
+ }
+
+ DART_FORCE_INLINE T& operator->() const {
+ ASSERT(index_ >= 0 && index_ < ports_->capacity_);
+ DEBUG_ASSERT(!WasModified());
+ return ports_->map_[index_];
+ }
+ DART_FORCE_INLINE T& operator*() const {
+ ASSERT(index_ >= 0 && index_ < ports_->capacity_);
+ DEBUG_ASSERT(!WasModified());
+ return ports_->map_[index_];
+ }
+
+ DART_FORCE_INLINE bool operator==(const Iterator& other) const {
+ DEBUG_ASSERT(!WasModified());
+ return ports_ == other.ports_ && index_ == other.index_;
+ }
+
+ DART_FORCE_INLINE bool operator!=(const Iterator& other) const {
+ DEBUG_ASSERT(!WasModified());
+ return !(*this == other);
+ }
+
+ DART_FORCE_INLINE Iterator& operator++() {
+ DEBUG_ASSERT(!WasModified());
+ index_++;
+ while (index_ < ports_->capacity_) {
+ const Dart_Port port = ports_->map_[index_].port;
+ if (port == kFreePort || port == kDeletedPort) {
+ index_++;
+ continue;
+ } else {
+ break;
+ }
+ }
+ return *this;
+ }
+
+ // The caller must ensure to call [PortSet::Rebalance] once the iterator is
+ // not used anymore.
+ DART_FORCE_INLINE void Delete() {
+ DEBUG_ASSERT(!WasModified());
+ ports_->map_[index_] = T();
+ ports_->map_[index_].port = kDeletedPort;
+ ports_->used_--;
+ ports_->deleted_++;
+ }
+
+ private:
+ friend class PortSet;
+
+#if defined(DEBUG)
+ // Whether the underlying [PortSet] was modified in a way that would render
+ // the iterator unusable.
+ bool WasModified() const {
+ return dirty_counter_ != ports_->dirty_counter_;
+ }
+#endif
+
+ PortSet<T>* ports_;
+ intptr_t index_ = 0;
+#if defined(DEBUG)
+ intptr_t dirty_counter_ = 0;
+#endif
+ };
+
+ PortSet() {
+ static const intptr_t kInitialCapacity = 8;
+ ASSERT(Utils::IsPowerOfTwo(kInitialCapacity));
+ map_ = new T[kInitialCapacity];
+ capacity_ = kInitialCapacity;
+ }
+ ~PortSet() {
+ delete[] map_;
+ map_ = nullptr;
+ }
+
+ bool IsEmpty() const { return used_ == 0; }
+
+ DART_FORCE_INLINE Iterator begin() {
+ for (intptr_t i = 0; i < capacity_; ++i) {
+ auto& entry = map_[i];
+ if (entry.port != kFreePort && entry.port != kDeletedPort) {
+ return Iterator(this, i);
+ }
+ }
+ return end();
+ }
+
+ DART_FORCE_INLINE Iterator end() { return Iterator(this, capacity_); }
+
+ void Insert(const T& entry) {
+ // Search for the first unused slot. Make use of the knowledge that here is
+ // currently no port with this id in the port map.
+ ASSERT(FindIndexOfPort(entry.port) < 0);
+ intptr_t index = entry.port % capacity_;
+ T cur = map_[index];
+
+ // Stop the search at the first found unused (free or deleted) slot.
+ while (cur.port != kFreePort && cur.port != kDeletedPort) {
+ index = (index + 1) % capacity_;
+ cur = map_[index];
+ }
+
+ // Insert the newly created port at the index.
+ ASSERT(map_[index].port == kFreePort || map_[index].port == kDeletedPort);
+ if (map_[index].port == kDeletedPort) {
+ deleted_--;
+ }
+ map_[index] = entry;
+ ASSERT(FindIndexOfPort(entry.port) >= 0);
+
+ // Increment number of used slots and grow if necessary.
+ used_++;
+ MaintainInvariants();
+
+#if defined(DEBUG)
+ dirty_counter_++;
+#endif
+ }
+
+ Iterator TryLookup(Dart_Port port) {
+ const intptr_t index = FindIndexOfPort(port);
+ if (index >= 0) return Iterator(this, index);
+ return Iterator(this, capacity_);
+ }
+
+ bool Contains(Dart_Port port) { return FindIndexOfPort(port) >= 0; }
+
+ // To be called if an iterator was used to delete an entry.
+ void Rebalance() { MaintainInvariants(); }
+
+ private:
+ intptr_t FindIndexOfPort(Dart_Port port) {
+ // ILLEGAL_PORT (0) is used as a sentinel value in Entry.port. The loop
+ // below could return the index to a deleted port when we are searching for
+ // port id ILLEGAL_PORT. Return -1 immediately to indicate the port
+ // does not exist.
+ if (port == ILLEGAL_PORT) {
+ return -1;
+ }
+ ASSERT(port != ILLEGAL_PORT);
+ intptr_t index = port % capacity_;
+ intptr_t start_index = index;
+ T entry = map_[index];
+ while (entry.port != kFreePort) {
+ if (entry.port == port) {
+ return index;
+ }
+ index = (index + 1) % capacity_;
+ // Prevent endless loops.
+ ASSERT(index != start_index);
+ entry = map_[index];
+ }
+ return -1;
+ }
+
+ void MaintainInvariants() {
+ const intptr_t empty = capacity_ - used_ - deleted_;
+ if (used_ > ((capacity_ / 4) * 3)) {
+ // Grow the port map.
+ Rehash(capacity_ * 2);
+ } else if (empty < deleted_) {
+ // Rehash without growing the table to flush the deleted slots out of the
+ // map.
+ Rehash(capacity_);
+ }
+ }
+
+ void Rehash(intptr_t new_capacity) {
+ T* new_ports = new T[new_capacity];
+
+ for (auto entry : *this) {
+ intptr_t new_index = entry.port % new_capacity;
+ while (new_ports[new_index].port != 0) {
+ new_index = (new_index + 1) % new_capacity;
+ }
+ new_ports[new_index] = entry;
+ }
+ delete[] map_;
+ map_ = new_ports;
+ capacity_ = new_capacity;
+ deleted_ = 0;
+
+#if defined(DEBUG)
+ dirty_counter_++;
+#endif
+ }
+
+ T* map_ = nullptr;
+ intptr_t capacity_ = 0;
+ intptr_t used_ = 0;
+ intptr_t deleted_ = 0;
+
+#if defined(DEBUG)
+ intptr_t dirty_counter_ = 0;
+#endif
+};
+
+} // namespace dart
+
+#endif // RUNTIME_VM_PORT_SET_H_
diff --git a/runtime/vm/port_test.cc b/runtime/vm/port_test.cc
index 6526471..2681b3a 100644
--- a/runtime/vm/port_test.cc
+++ b/runtime/vm/port_test.cc
@@ -16,16 +16,17 @@
public:
static bool IsActivePort(Dart_Port port) {
MutexLocker ml(PortMap::mutex_);
- return (PortMap::FindPort(port) >= 0);
+ auto it = PortMap::ports_->TryLookup(port);
+ return it != PortMap::ports_->end();
}
static bool IsLivePort(Dart_Port port) {
MutexLocker ml(PortMap::mutex_);
- intptr_t index = PortMap::FindPort(port);
- if (index < 0) {
+ auto it = PortMap::ports_->TryLookup(port);
+ if (it == PortMap::ports_->end()) {
return false;
}
- return PortMap::map_[index].state == PortMap::kLivePort;
+ return (*it).state == PortMap::kLivePort;
}
};
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 087c701..1080e7d 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -150,7 +150,7 @@
class_fields_ = cls.fields();
for (intptr_t j = 0; j < class_fields_.Length(); j++) {
class_field_ ^= class_fields_.At(j);
- if (class_field_.is_static() && class_field_.HasInitializerFunction()) {
+ if (class_field_.HasInitializerFunction()) {
class_function_ = class_field_.InitializerFunction();
AddToWorklist(class_function_);
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index b3758a2..0b6e0e4 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -573,34 +573,6 @@
return CanonicalBit::decode(value);
}
- // Class Id predicates.
- static bool IsErrorClassId(intptr_t index);
- static bool IsNumberClassId(intptr_t index);
- static bool IsIntegerClassId(intptr_t index);
- static bool IsStringClassId(intptr_t index);
- static bool IsOneByteStringClassId(intptr_t index);
- static bool IsTwoByteStringClassId(intptr_t index);
- static bool IsExternalStringClassId(intptr_t index);
- static bool IsBuiltinListClassId(intptr_t index);
- static bool IsTypedDataBaseClassId(intptr_t index);
- static bool IsTypedDataClassId(intptr_t index);
- static bool IsTypedDataViewClassId(intptr_t index);
- static bool IsExternalTypedDataClassId(intptr_t index);
- static bool IsFfiNativeTypeTypeClassId(intptr_t index);
- static bool IsFfiPointerClassId(intptr_t index);
- static bool IsFfiTypeClassId(intptr_t index);
- static bool IsFfiTypeIntClassId(intptr_t index);
- static bool IsFfiTypeDoubleClassId(intptr_t index);
- static bool IsFfiTypeVoidClassId(intptr_t index);
- static bool IsFfiTypeNativeFunctionClassId(intptr_t index);
- static bool IsFfiDynamicLibraryClassId(intptr_t index);
- static bool IsFfiClassId(intptr_t index);
- static bool IsInternalVMdefinedClassId(intptr_t index);
- static bool IsVariableSizeClassId(intptr_t index);
- static bool IsImplicitFieldClassId(intptr_t index);
-
- static intptr_t NumberOfTypedDataClasses();
-
private:
Tags tags_; // Various object tags (bits).
#if defined(HASH_IN_OBJECT_HEADER)
@@ -2958,214 +2930,6 @@
friend class SnapshotReader;
};
-// Class Id predicates.
-
-inline bool RawObject::IsErrorClassId(intptr_t index) {
- // Make sure this function is updated when new Error types are added.
- COMPILE_ASSERT(
- kApiErrorCid == kErrorCid + 1 && kLanguageErrorCid == kErrorCid + 2 &&
- kUnhandledExceptionCid == kErrorCid + 3 &&
- kUnwindErrorCid == kErrorCid + 4 && kInstanceCid == kErrorCid + 5);
- return (index >= kErrorCid && index < kInstanceCid);
-}
-
-inline bool RawObject::IsNumberClassId(intptr_t index) {
- // Make sure this function is updated when new Number types are added.
- COMPILE_ASSERT(kIntegerCid == kNumberCid + 1 && kSmiCid == kNumberCid + 2 &&
- kMintCid == kNumberCid + 3 && kDoubleCid == kNumberCid + 4);
- return (index >= kNumberCid && index <= kDoubleCid);
-}
-
-inline bool RawObject::IsIntegerClassId(intptr_t index) {
- // Make sure this function is updated when new Integer types are added.
- COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2);
- return (index >= kIntegerCid && index <= kMintCid);
-}
-
-inline bool RawObject::IsStringClassId(intptr_t index) {
- // Make sure this function is updated when new StringCid types are added.
- COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
- kTwoByteStringCid == kStringCid + 2 &&
- kExternalOneByteStringCid == kStringCid + 3 &&
- kExternalTwoByteStringCid == kStringCid + 4);
- return (index >= kStringCid && index <= kExternalTwoByteStringCid);
-}
-
-inline bool RawObject::IsOneByteStringClassId(intptr_t index) {
- // Make sure this function is updated when new StringCid types are added.
- COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
- kTwoByteStringCid == kStringCid + 2 &&
- kExternalOneByteStringCid == kStringCid + 3 &&
- kExternalTwoByteStringCid == kStringCid + 4);
- return (index == kOneByteStringCid || index == kExternalOneByteStringCid);
-}
-
-inline bool RawObject::IsTwoByteStringClassId(intptr_t index) {
- // Make sure this function is updated when new StringCid types are added.
- COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
- kTwoByteStringCid == kStringCid + 2 &&
- kExternalOneByteStringCid == kStringCid + 3 &&
- kExternalTwoByteStringCid == kStringCid + 4);
- return (index == kTwoByteStringCid || index == kExternalTwoByteStringCid);
-}
-
-inline bool RawObject::IsExternalStringClassId(intptr_t index) {
- // Make sure this function is updated when new StringCid types are added.
- COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
- kTwoByteStringCid == kStringCid + 2 &&
- kExternalOneByteStringCid == kStringCid + 3 &&
- kExternalTwoByteStringCid == kStringCid + 4);
- return (index == kExternalOneByteStringCid ||
- index == kExternalTwoByteStringCid);
-}
-
-inline bool RawObject::IsBuiltinListClassId(intptr_t index) {
- // Make sure this function is updated when new builtin List types are added.
- COMPILE_ASSERT(kImmutableArrayCid == kArrayCid + 1);
- return ((index >= kArrayCid && index <= kImmutableArrayCid) ||
- (index == kGrowableObjectArrayCid) || IsTypedDataBaseClassId(index) ||
- (index == kByteBufferCid));
-}
-
-inline bool RawObject::IsTypedDataBaseClassId(intptr_t index) {
- // Make sure this is updated when new TypedData types are added.
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
- return index >= kTypedDataInt8ArrayCid && index < kByteDataViewCid;
-}
-
-inline bool RawObject::IsTypedDataClassId(intptr_t index) {
- // Make sure this is updated when new TypedData types are added.
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
- return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
- 3) == kTypedDataCidRemainderInternal;
-}
-
-inline bool RawObject::IsTypedDataViewClassId(intptr_t index) {
- // Make sure this is updated when new TypedData types are added.
- COMPILE_ASSERT(kTypedDataInt8ArrayViewCid + 3 == kTypedDataUint8ArrayViewCid);
-
- const bool is_byte_data_view = index == kByteDataViewCid;
- return is_byte_data_view ||
- (IsTypedDataBaseClassId(index) &&
- ((index - kTypedDataInt8ArrayCid) % 3) == kTypedDataCidRemainderView);
-}
-
-inline bool RawObject::IsExternalTypedDataClassId(intptr_t index) {
- // Make sure this is updated when new TypedData types are added.
- COMPILE_ASSERT(kExternalTypedDataInt8ArrayCid + 3 ==
- kExternalTypedDataUint8ArrayCid);
-
- return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
- 3) == kTypedDataCidRemainderExternal;
-}
-
-inline bool RawObject::IsFfiNativeTypeTypeClassId(intptr_t index) {
- return index == kFfiNativeTypeCid;
-}
-
-inline bool RawObject::IsFfiTypeClassId(intptr_t index) {
- // Make sure this is updated when new Ffi types are added.
- COMPILE_ASSERT(kFfiNativeFunctionCid == kFfiPointerCid + 1 &&
- kFfiInt8Cid == kFfiPointerCid + 2 &&
- kFfiInt16Cid == kFfiPointerCid + 3 &&
- kFfiInt32Cid == kFfiPointerCid + 4 &&
- kFfiInt64Cid == kFfiPointerCid + 5 &&
- kFfiUint8Cid == kFfiPointerCid + 6 &&
- kFfiUint16Cid == kFfiPointerCid + 7 &&
- kFfiUint32Cid == kFfiPointerCid + 8 &&
- kFfiUint64Cid == kFfiPointerCid + 9 &&
- kFfiIntPtrCid == kFfiPointerCid + 10 &&
- kFfiFloatCid == kFfiPointerCid + 11 &&
- kFfiDoubleCid == kFfiPointerCid + 12 &&
- kFfiVoidCid == kFfiPointerCid + 13);
- return (index >= kFfiPointerCid && index <= kFfiVoidCid);
-}
-
-inline bool RawObject::IsFfiTypeIntClassId(intptr_t index) {
- return (index >= kFfiInt8Cid && index <= kFfiIntPtrCid);
-}
-
-inline bool RawObject::IsFfiTypeDoubleClassId(intptr_t index) {
- return (index >= kFfiFloatCid && index <= kFfiDoubleCid);
-}
-
-inline bool RawObject::IsFfiPointerClassId(intptr_t index) {
- return index == kFfiPointerCid;
-}
-
-inline bool RawObject::IsFfiTypeVoidClassId(intptr_t index) {
- return index == kFfiVoidCid;
-}
-
-inline bool RawObject::IsFfiTypeNativeFunctionClassId(intptr_t index) {
- return index == kFfiNativeFunctionCid;
-}
-
-inline bool RawObject::IsFfiClassId(intptr_t index) {
- return (index >= kFfiPointerCid && index <= kFfiVoidCid);
-}
-
-inline bool RawObject::IsFfiDynamicLibraryClassId(intptr_t index) {
- return index == kFfiDynamicLibraryCid;
-}
-
-inline bool RawObject::IsInternalVMdefinedClassId(intptr_t index) {
- return ((index < kNumPredefinedCids) &&
- !RawObject::IsImplicitFieldClassId(index));
-}
-
-inline bool RawObject::IsVariableSizeClassId(intptr_t index) {
- return (index == kArrayCid) || (index == kImmutableArrayCid) ||
- RawObject::IsOneByteStringClassId(index) ||
- RawObject::IsTwoByteStringClassId(index) ||
- RawObject::IsTypedDataClassId(index) || (index == kContextCid) ||
- (index == kTypeArgumentsCid) || (index == kInstructionsCid) ||
- (index == kInstructionsSectionCid) || (index == kObjectPoolCid) ||
- (index == kPcDescriptorsCid) || (index == kCodeSourceMapCid) ||
- (index == kCompressedStackMapsCid) ||
- (index == kLocalVarDescriptorsCid) ||
- (index == kExceptionHandlersCid) || (index == kCodeCid) ||
- (index == kContextScopeCid) || (index == kInstanceCid) ||
- (index == kRegExpCid);
-}
-
-// This is a set of classes that are not Dart classes whose representation
-// is defined by the VM but are used in the VM code by computing the
-// implicit field offsets of the various fields in the dart object.
-inline bool RawObject::IsImplicitFieldClassId(intptr_t index) {
- return index == kByteBufferCid;
-}
-
-inline intptr_t RawObject::NumberOfTypedDataClasses() {
- // Make sure this is updated when new TypedData types are added.
-
- // Ensure that each typed data type comes in internal/view/external variants
- // next to each other.
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 == kTypedDataInt8ArrayViewCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 == kExternalTypedDataInt8ArrayCid);
-
- // Ensure the order of the typed data members in 3-step.
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 * 3 == kTypedDataUint8ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 * 3 ==
- kTypedDataUint8ClampedArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 * 3 == kTypedDataInt16ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 4 * 3 == kTypedDataUint16ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 5 * 3 == kTypedDataInt32ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 6 * 3 == kTypedDataUint32ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 7 * 3 == kTypedDataInt64ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 8 * 3 == kTypedDataUint64ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 9 * 3 == kTypedDataFloat32ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 10 * 3 == kTypedDataFloat64ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 11 * 3 ==
- kTypedDataFloat32x4ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 12 * 3 == kTypedDataInt32x4ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 13 * 3 ==
- kTypedDataFloat64x2ArrayCid);
- COMPILE_ASSERT(kTypedDataInt8ArrayCid + 14 * 3 == kByteDataViewCid);
- COMPILE_ASSERT(kByteBufferCid + 1 == kNullCid);
- return (kNullCid - kTypedDataInt8ArrayCid);
-}
-
} // namespace dart
#endif // RUNTIME_VM_RAW_OBJECT_H_
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 2c295ef..9183c9a 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -1752,7 +1752,7 @@
intptr_t characters) {
// Bind the pattern as the load receiver.
Value* pattern_val = BindLoadLocal(*string_param_);
- if (RawObject::IsExternalStringClassId(specialization_cid_)) {
+ if (IsExternalStringClassId(specialization_cid_)) {
// The data of an external string is stored through one indirection.
intptr_t external_offset = 0;
if (specialization_cid_ == kExternalOneByteStringCid) {
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 32bab52..ccf5867 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -3289,7 +3289,7 @@
}
RawObject* result = interpreter->Call(function, argdesc, argc, argv, thread);
DEBUG_ASSERT(thread->top_exit_frame_info() == exit_fp);
- if (RawObject::IsErrorClassId(result->GetClassIdMayBeSmi())) {
+ if (IsErrorClassId(result->GetClassIdMayBeSmi())) {
// Must not leak handles in the caller's zone.
HANDLESCOPE(thread);
// Protect the result in a handle before transitioning, which may trigger
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index d966d45..a8dbaee 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -42,10 +42,9 @@
return (class_id == kObjectCid ||
(class_id >= kInstanceCid && class_id <= kUserTagCid) ||
class_id == kArrayCid || class_id == kImmutableArrayCid ||
- RawObject::IsStringClassId(class_id) ||
- RawObject::IsTypedDataClassId(class_id) ||
- RawObject::IsExternalTypedDataClassId(class_id) ||
- RawObject::IsTypedDataViewClassId(class_id) || class_id == kNullCid ||
+ IsStringClassId(class_id) || IsTypedDataClassId(class_id) ||
+ IsExternalTypedDataClassId(class_id) ||
+ IsTypedDataViewClassId(class_id) || class_id == kNullCid ||
class_id == kTransferableTypedDataCid);
}
@@ -62,7 +61,7 @@
// later inline with complete contents.
return class_id >= kNumPredefinedCids || class_id == kArrayCid ||
class_id == kImmutableArrayCid || class_id == kObjectPoolCid ||
- RawObject::IsImplicitFieldClassId(class_id);
+ IsImplicitFieldClassId(class_id);
}
static intptr_t ClassIdFromObjectId(intptr_t object_id) {
@@ -1187,8 +1186,7 @@
RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
intptr_t class_id = cls->ptr()->id_;
ASSERT(class_id == RawObject::ClassIdTag::decode(tags));
- if (class_id >= kNumPredefinedCids ||
- RawObject::IsImplicitFieldClassId(class_id)) {
+ if (class_id >= kNumPredefinedCids || IsImplicitFieldClassId(class_id)) {
WriteInstance(raw, cls, tags, object_id, as_reference);
return;
}
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 420618d..d96d81d 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -68,8 +68,6 @@
write_barrier_mask_(RawObject::kGenerationalBarrierMask),
isolate_(NULL),
dispatch_table_array_(NULL),
- top_(0),
- end_(0),
saved_stack_limit_(0),
stack_overflow_flags_(0),
heap_(NULL),
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index bee44edb..9780e89 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -19,6 +19,7 @@
#include "vm/globals.h"
#include "vm/handles.h"
#include "vm/heap/pointer_block.h"
+#include "vm/heap/tlab.h"
#include "vm/os_thread.h"
#include "vm/random.h"
#include "vm/runtime_entry_list.h"
@@ -502,13 +503,12 @@
Heap* heap() const { return heap_; }
static intptr_t heap_offset() { return OFFSET_OF(Thread, heap_); }
- void set_top(uword value) { top_ = value; }
- void set_end(uword value) { end_ = value; }
+ void set_tlab(TLAB tlab) {
+ top_ = tlab.top;
+ end_ = tlab.end;
+ }
- uword top() { return top_; }
- uword end() { return end_; }
-
- bool HasActiveTLAB() { return end_ > 0; }
+ TLAB tlab() { return TLAB(top_, end_); }
static intptr_t top_offset() { return OFFSET_OF(Thread, top_); }
static intptr_t end_offset() { return OFFSET_OF(Thread, end_); }
@@ -904,8 +904,8 @@
uword write_barrier_mask_;
Isolate* isolate_;
const uword* dispatch_table_array_;
- uword top_;
- uword end_;
+ uword top_ = 0;
+ uword end_ = 0;
// Offsets up to this point can all fit in a byte on X64. All of the above
// fields are very abundantly accessed from code. Thus, keeping them first
// is important for code size (although code size on X64 is not a priority).
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index d3560f0..a919b39 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -220,6 +220,7 @@
"pointer_tagging.h",
"port.cc",
"port.h",
+ "port_set.h",
"proccpuinfo.cc",
"proccpuinfo.h",
"profiler.cc",
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index 8708886..5416d03 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -54,7 +54,7 @@
* integers, the result is a number with only the bits set that are set in
* both `this` and [other]
*
- * Of both operands are negative, the result is negative, otherwise
+ * If both operands are negative, the result is negative, otherwise
* the result is non-negative.
*/
int operator &(int other);
diff --git a/sdk_nnbd/lib/_http/http.dart b/sdk_nnbd/lib/_http/http.dart
index e00ae5e..6db8524 100644
--- a/sdk_nnbd/lib/_http/http.dart
+++ b/sdk_nnbd/lib/_http/http.dart
@@ -1926,8 +1926,7 @@
*
* The default value is `true`.
*/
- bool get persistentConnection;
- void set persistentConnection(bool persistentConnection);
+ bool persistentConnection = true;
/**
* Whether to follow redirects automatically.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index bee1a93..b325083 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -168,7 +168,7 @@
var requiredNamed = type.requiredNamed;
if (namedActuals != null) {
names = getOwnPropertyNames(namedActuals);
- for (var name in names!) {
+ for (var name in names) {
if (!JS<bool>('!', '(#.hasOwnProperty(#) || #.hasOwnProperty(#))', named,
name, requiredNamed, name)) {
return "Dynamic call with unexpected named argument '$name'.";
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index eb34fca..e35aa06 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -2898,7 +2898,7 @@
if (JS_GET_FLAG("VARIANCE")) {
sVariances = _Universe.findTypeParameterVariances(universe, sName);
hasVariances = sVariances != null;
- assert(!hasVariances! || length == _Utils.arrayLength(sVariances));
+ assert(!hasVariances || length == _Utils.arrayLength(sVariances));
}
for (int i = 0; i < length; i++) {
diff --git a/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart
index e2ced70..f602449 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart
@@ -206,7 +206,7 @@
if (end == start) {
return 0;
}
- var result = _nativeReadInto(buffer, start, end! - start);
+ var result = _nativeReadInto(buffer, start, end - start);
if (result is OSError) {
throw new SocketException("readIntoSync failed", osError: result);
}
@@ -297,7 +297,7 @@
return;
}
_BufferAndStart bufferAndStart =
- _ensureFastAndSerializableByteData(buffer, start, end!);
+ _ensureFastAndSerializableByteData(buffer, start, end);
var result = _nativeWrite(bufferAndStart.buffer, bufferAndStart.start,
end - (start - bufferAndStart.start));
if (result is OSError) {
diff --git a/sdk_nnbd/lib/core/int.dart b/sdk_nnbd/lib/core/int.dart
index 42af709..b1203ed 100644
--- a/sdk_nnbd/lib/core/int.dart
+++ b/sdk_nnbd/lib/core/int.dart
@@ -52,7 +52,7 @@
* integers, the result is a number with only the bits set that are set in
* both `this` and [other]
*
- * Of both operands are negative, the result is negative, otherwise
+ * If both operands are negative, the result is negative, otherwise
* the result is non-negative.
*/
int operator &(int other);
diff --git a/sdk_nnbd/lib/io/file_impl.dart b/sdk_nnbd/lib/io/file_impl.dart
index eed5268..ee34b7d 100644
--- a/sdk_nnbd/lib/io/file_impl.dart
+++ b/sdk_nnbd/lib/io/file_impl.dart
@@ -770,7 +770,7 @@
if (end == start) {
return new Future.value(0);
}
- int length = end! - start;
+ int length = end - start;
return _dispatch(_IOService.fileReadInto, [null, length]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "readInto failed", path);
@@ -791,7 +791,7 @@
if (end == start) {
return 0;
}
- var result = _ops.readInto(buffer, start, end!);
+ var result = _ops.readInto(buffer, start, end);
if (result is OSError) {
throw new FileSystemException("readInto failed", path, result);
}
@@ -834,7 +834,7 @@
}
_BufferAndStart result;
try {
- result = _ensureFastAndSerializableByteData(buffer, start, end!);
+ result = _ensureFastAndSerializableByteData(buffer, start, end);
} catch (e) {
return new Future.error(e);
}
@@ -863,7 +863,7 @@
return;
}
_BufferAndStart bufferAndStart =
- _ensureFastAndSerializableByteData(buffer, start, end!);
+ _ensureFastAndSerializableByteData(buffer, start, end);
var result = _ops.writeFrom(bufferAndStart.buffer, bufferAndStart.start,
end - (start - bufferAndStart.start));
if (result is OSError) {
diff --git a/tests/corelib/list_test.dart b/tests/corelib/list_test.dart
index aa18a79..a607a5a 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -22,26 +22,20 @@
testTypedList(new Int32List(4).toList(growable: false));
// Fixed length lists, length 4.
- testFixedLengthList(<T>() => new List<T?>.filled(4, null));
- testFixedLengthList(
- <T>() => new List<T?>.filled(4, null).toList(growable: false));
- testFixedLengthList(<T>() => (<T?>[]..length = 4).toList(growable: false));
- testFixedLengthList(<T>() => (new List<T?>.filled(0, null, growable: true)
- ..length = 4)
- .toList(growable: false));
+ testFixedLengthList(<T>(T t) => List<T>.filled(4, t));
+ testFixedLengthList(<T>(T t) => List<T>.filled(4, t).toList(growable: false));
// ListBase implementation of List.
- testFixedLengthList(<T>() => new MyFixedList(new List<T?>.filled(4, null)));
- testFixedLengthList(<T>() => new MyFixedList<T?>(new List<T?>.filled(4, null))
- .toList(growable: false));
+ testFixedLengthList(<T>(T t) => new MyFixedList(List<T>.filled(4, t)));
+ testFixedLengthList(<T>(T t) =>
+ new MyFixedList<T>(List<T>.filled(4, t)).toList(growable: false));
// Growable lists. Initial length 0.
- testGrowableList(<T>() => <T?>[].toList());
- testGrowableList(<T>() => new List<T?>.filled(0, null).toList());
- testGrowableList(<T>() => new List<T?>.filled(0, null, growable: true));
- testGrowableList(<T>() => []);
- testGrowableList(<T>() => new List.from(const []));
- testGrowableList(<T>() => new MyList([]));
- testGrowableList(<T>() => new MyList<T>([]).toList());
+ testGrowableList(<T>(T t) => <T>[].toList());
+ testGrowableList(<T>(T t) => new List<T>.filled(0, t, growable: true));
+ testGrowableList(<T>(T t) => []);
+ testGrowableList(<T>(T t) => new List.from(const []));
+ testGrowableList(<T>(T t) => new MyList([]));
+ testGrowableList(<T>(T t) => new MyList<T>([]).toList());
testTypedGrowableList(new Uint8List(0).toList());
testTypedGrowableList(new Int8List(0).toList());
@@ -122,7 +116,7 @@
// Empty lists.
testRangeErrors([], "list");
- testRangeErrors(new List.filled(0, null), "fixed-list");
+ testRangeErrors(List.filled(0, null, growable: false), "fixed-list");
testRangeErrors(const [], "const-list");
testRangeErrors(new List.unmodifiable([]), "unmodifiable");
testRangeErrors(new Uint8List(0), "typed-list");
@@ -130,7 +124,7 @@
testRangeErrors([1, 2, 3].sublist(1, 1), "sub-list");
// Non-empty lists.
testRangeErrors([1, 2, 3], "list");
- testRangeErrors(new List.filled(3, null), "fixed-list");
+ testRangeErrors(List.filled(3, null, growable: false), "fixed-list");
testRangeErrors(const [1, 2, 3], "const-list");
testRangeErrors(new List.unmodifiable([1, 2, 3]), "unmodifiable");
testRangeErrors(new Uint8List(3), "typed-list");
@@ -168,7 +162,7 @@
}
// setRange.
- list.setRange(0, 4, [3, 2, 1, 0]);
+ list.setRange(0, 4, <int>[3, 2, 1, 0]);
Expect.listEquals([3, 2, 1, 0], list);
list.setRange(1, 4, list);
@@ -183,9 +177,9 @@
Expect.listEquals([2, 1, 2, 1], list);
// setAll.
- list.setAll(0, [3, 2, 0, 1]);
+ list.setAll(0, <int>[3, 2, 0, 1]);
Expect.listEquals([3, 2, 0, 1], list);
- list.setAll(1, [0, 1]);
+ list.setAll(1, <int>[0, 1]);
Expect.listEquals([3, 0, 1, 1], list);
// fillRange.
@@ -199,22 +193,22 @@
Expect.listEquals([9, 9, 9, 9], list);
// sort.
- list.setRange(0, 4, [3, 2, 1, 0]);
+ list.setRange(0, 4, <int>[3, 2, 1, 0]);
list.sort();
Expect.listEquals([0, 1, 2, 3], list);
- list.setRange(0, 4, [1, 2, 3, 0]);
+ list.setRange(0, 4, <int>[1, 2, 3, 0]);
list.sort();
Expect.listEquals([0, 1, 2, 3], list);
- list.setRange(0, 4, [1, 3, 0, 2]);
+ list.setRange(0, 4, <int>[1, 3, 0, 2]);
list.sort((a, b) => b! - a!); // reverse compare.
Expect.listEquals([3, 2, 1, 0], list);
- list.setRange(0, 4, [1, 2, 3, 0]);
+ list.setRange(0, 4, <int>[1, 2, 3, 0]);
list.sort((a, b) => b! - a!);
Expect.listEquals([3, 2, 1, 0], list);
// Some Iterable methods.
- list.setRange(0, 4, [0, 1, 2, 3]);
+ list.setRange(0, 4, <int>[0, 1, 2, 3]);
// map.
testMap(val) {
return val * 2 + 10;
@@ -304,18 +298,18 @@
Expect.throwsArgumentError(() => list.getRange(-1, 5));
Expect.throwsArgumentError(() => list.getRange(2, 5));
Expect.throwsArgumentError(() => list.getRange(4, 2));
- Expect.throwsArgumentError(() => list.setRange(-1, 2, [1, 2, 3]));
- Expect.throwsArgumentError(() => list.setRange(-1, 5, [1, 2, 3, 4, 5, 6]));
- Expect.throwsArgumentError(() => list.setRange(2, 5, [1, 2, 3]));
- Expect.throwsArgumentError(() => list.setRange(4, 2, [1, 2]));
+ Expect.throwsArgumentError(() => list.setRange(-1, 2, <int>[1, 2, 3]));
+ Expect.throwsArgumentError(() => list.setRange(-1, 5, <int>[1, 2, 3, 4, 5, 6]));
+ Expect.throwsArgumentError(() => list.setRange(2, 5, <int>[1, 2, 3]));
+ Expect.throwsArgumentError(() => list.setRange(4, 2, <int>[1, 2]));
// for setAll, end is implicitly start + values.length.
- Expect.throwsArgumentError(() => list.setAll(-1, []));
- Expect.throwsArgumentError(() => list.setAll(5, []));
- Expect.throwsArgumentError(() => list.setAll(2, [1, 2, 3]));
- Expect.throwsArgumentError(() => list.fillRange(-1, 2));
- Expect.throwsArgumentError(() => list.fillRange(-1, 5));
- Expect.throwsArgumentError(() => list.fillRange(2, 5));
- Expect.throwsArgumentError(() => list.fillRange(4, 2));
+ Expect.throwsArgumentError(() => list.setAll(-1, <int>[]));
+ Expect.throwsArgumentError(() => list.setAll(5, <int>[]));
+ Expect.throwsArgumentError(() => list.setAll(2, <int>[1, 2, 3]));
+ Expect.throwsArgumentError(() => list.fillRange(-1, 2, 1));
+ Expect.throwsArgumentError(() => list.fillRange(-1, 5, 1));
+ Expect.throwsArgumentError(() => list.fillRange(2, 5, 1));
+ Expect.throwsArgumentError(() => list.fillRange(4, 2, 1));
}
void testTypedList(List<int> list) {
@@ -323,51 +317,60 @@
testCannotChangeLength(list);
}
-void testFixedLengthList(List<T?> Function<T>() createList) {
- testLengthInvariantOperations(createList<int>());
- testCannotChangeLength(createList<int>());
- testUntypedListTests(createList());
+void testFixedLengthList(List<T> Function<T>(T t) createList) {
+ testLengthInvariantOperations(createList<int>(-1));
+ testCannotChangeLength(createList<int>(-1));
+ testLengthInvariantOperations(createList<int?>(null));
+ testCannotChangeLength(createList<int?>(null));
+ testUntypedListTests(createList(null));
}
void testCannotChangeLength(List<int?> list) {
- list.setAll(0, [0, 1, 2, 3]);
+ list.setAll(0, <int>[0, 1, 2, 3]);
Expect.throwsUnsupportedError(() => list.add(0));
- Expect.throwsUnsupportedError(() => list.addAll([0]));
+ Expect.throwsUnsupportedError(() => list.addAll(<int>[0]));
Expect.throwsUnsupportedError(() => list.removeLast());
Expect.throwsUnsupportedError(() => list.insert(0, 1));
- Expect.throwsUnsupportedError(() => list.insertAll(0, [1]));
+ Expect.throwsUnsupportedError(() => list.insertAll(0, <int>[1]));
Expect.throwsUnsupportedError(() => list.clear());
Expect.throwsUnsupportedError(() => list.remove(1));
Expect.throwsUnsupportedError(() => list.removeAt(1));
Expect.throwsUnsupportedError(() => list.removeRange(0, 1));
- Expect.throwsUnsupportedError(() => list.replaceRange(0, 1, []));
+ Expect.throwsUnsupportedError(() => list.replaceRange(0, 1, <int>[]));
}
void testTypedGrowableList(List<int> list) {
testLength(0, list);
- // set length.
- list.length = 4;
+ list.addAll([0, 0, 0, 0]);
testLength(4, list);
testTypedLengthInvariantOperations(list);
testGrowableListOperations(list);
+
+ list.length = 2;
+ testLength(2, list);
}
-void testGrowableList(List<T?> Function<T>() createList) {
- List<int?> list = createList<int>();
+void testGrowableList(List<T> Function<T>(T t) createList) {
+ List<int> list = createList<int>(-1);
testLength(0, list);
- list.length = 4;
+ list.addAll([0, 0, 0, 0]);
testLength(4, list);
-
testLengthInvariantOperations(list);
testGrowableListOperations(list);
- List listDynamic = createList();
+ List<int?> listNullable = createList<int?>(null);
+ testLength(0, listNullable);
+ listNullable.length = 4;
+ testLength(4, listNullable);
+ testLengthInvariantOperations(listNullable);
+ testGrowableListOperations(listNullable);
+
+ List listDynamic = createList(null);
testLength(0, listDynamic);
listDynamic.length = 4;
testLength(4, listDynamic);
-
testUntypedListTests(listDynamic);
}
@@ -457,39 +460,39 @@
Expect.listEquals([2], list);
// insertAll
- list.insertAll(0, [1, 2, 3]);
+ list.insertAll(0, <int>[1, 2, 3]);
Expect.listEquals([1, 2, 3, 2], list);
- list.insertAll(2, []);
+ list.insertAll(2, <int>[]);
Expect.listEquals([1, 2, 3, 2], list);
- list.insertAll(4, [7, 9]);
+ list.insertAll(4, <int>[7, 9]);
Expect.listEquals([1, 2, 3, 2, 7, 9], list);
// addAll
list.addAll(list.reversed.toList());
Expect.listEquals([1, 2, 3, 2, 7, 9, 9, 7, 2, 3, 2, 1], list);
- list.addAll([]);
+ list.addAll(<int>[]);
Expect.listEquals([1, 2, 3, 2, 7, 9, 9, 7, 2, 3, 2, 1], list);
// replaceRange
- list.replaceRange(3, 7, [0, 0]);
+ list.replaceRange(3, 7, <int>[0, 0]);
Expect.listEquals([1, 2, 3, 0, 0, 7, 2, 3, 2, 1], list);
- list.replaceRange(2, 3, [5, 5, 5]);
+ list.replaceRange(2, 3, <int>[5, 5, 5]);
Expect.listEquals([1, 2, 5, 5, 5, 0, 0, 7, 2, 3, 2, 1], list);
- list.replaceRange(2, 4, [6, 6]);
+ list.replaceRange(2, 4, <int>[6, 6]);
Expect.listEquals([1, 2, 6, 6, 5, 0, 0, 7, 2, 3, 2, 1], list);
- list.replaceRange(6, 8, []);
+ list.replaceRange(6, 8, <int>[]);
Expect.listEquals([1, 2, 6, 6, 5, 0, 2, 3, 2, 1], list);
// Any operation that doesn't change the length should be safe for iteration.
testSafeConcurrentModification(action()) {
list.length = 4;
- list.setAll(0, [0, 1, 2, 3]);
+ list.setAll(0, <int>[0, 1, 2, 3]);
for (var i in list) {
action();
}
@@ -514,7 +517,7 @@
// Argument errors on bad indices for methods that are only allowed
// on growable lists.
list.length = 4;
- list.setAll(0, [0, 1, 2, 3]);
+ list.setAll(0, <int>[0, 1, 2, 3]);
// Direct indices (0 <= index < length).
Expect.throwsArgumentError(() => list.removeAt(-1));
@@ -522,19 +525,19 @@
// Direct indices including end (0 <= index <= length).
Expect.throwsArgumentError(() => list.insert(-1, 0));
Expect.throwsArgumentError(() => list.insert(5, 0));
- Expect.throwsArgumentError(() => list.insertAll(-1, [0]));
- Expect.throwsArgumentError(() => list.insertAll(5, [0]));
- Expect.throwsArgumentError(() => list.insertAll(-1, [0]));
- Expect.throwsArgumentError(() => list.insertAll(5, [0]));
+ Expect.throwsArgumentError(() => list.insertAll(-1, <int>[0]));
+ Expect.throwsArgumentError(() => list.insertAll(5, <int>[0]));
+ Expect.throwsArgumentError(() => list.insertAll(-1, <int>[0]));
+ Expect.throwsArgumentError(() => list.insertAll(5, <int>[0]));
// Ranges (0 <= start <= end <= length).
Expect.throwsArgumentError(() => list.removeRange(-1, 2));
Expect.throwsArgumentError(() => list.removeRange(2, 5));
Expect.throwsArgumentError(() => list.removeRange(-1, 5));
Expect.throwsArgumentError(() => list.removeRange(4, 2));
- Expect.throwsArgumentError(() => list.replaceRange(-1, 2, [9]));
- Expect.throwsArgumentError(() => list.replaceRange(2, 5, [9]));
- Expect.throwsArgumentError(() => list.replaceRange(-1, 5, [9]));
- Expect.throwsArgumentError(() => list.replaceRange(4, 2, [9]));
+ Expect.throwsArgumentError(() => list.replaceRange(-1, 2, <int>[9]));
+ Expect.throwsArgumentError(() => list.replaceRange(2, 5, <int>[9]));
+ Expect.throwsArgumentError(() => list.replaceRange(-1, 5, <int>[9]));
+ Expect.throwsArgumentError(() => list.replaceRange(4, 2, <int>[9]));
}
class Yes {
@@ -550,6 +553,10 @@
_source.length = length;
}
+ void add(E element) {
+ _source.add(element);
+ }
+
E operator [](int index) => _source[index];
void operator []=(int index, E value) {
_source[index] = value;
@@ -575,7 +582,6 @@
Expect.throws(() => new List<int?>.filled(0, null).add(4));
Expect.throws(() => new List.filled(-2, null)); // Not negative. //# 01: ok
// Not null.
- Expect.throws(() => new List.filled(null, null));
Expect.listEquals([4], <int>[]..add(4));
// Is fixed-length.
Expect.throws(() => new List.filled(0, 42).add(4));
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart
index 3fa4375..bda8280 100644
--- a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart
@@ -299,7 +299,7 @@
// [cfe] unspecified
DiBqOq0().a,
-// ^^^^^^^^^^
+// ^^^^^^^^^^^
// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
// [cfe] unspecified
@@ -309,7 +309,7 @@
// [cfe] unspecified
DiBqOq1().a,
-// ^^^^^^^^^^
+// ^^^^^^^^^^^
// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
// [cfe] unspecified
@@ -319,7 +319,7 @@
// [cfe] unspecified
DiBqOq2().a,
-// ^^^^^^^^^^
+// ^^^^^^^^^^^
// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
// [cfe] unspecified
@@ -329,7 +329,7 @@
// [cfe] unspecified
DiBqOq3().a,
-// ^^^^^^^^^^
+// ^^^^^^^^^^^
// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
// [cfe] unspecified
@@ -339,7 +339,7 @@
// [cfe] unspecified
DiBqOq4().a,
-// ^^^^^^^^^^
+// ^^^^^^^^^^^
// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
// [cfe] unspecified
@@ -349,7 +349,7 @@
// [cfe] unspecified
DiBqOq5().a,
-// ^^^^^^^^^^
+// ^^^^^^^^^^^
// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
// [cfe] unspecified
];
diff --git a/tests/language/void/await_void_error_test.dart b/tests/language/void/await_void_error_test.dart
new file mode 100644
index 0000000..94b902b
--- /dev/null
+++ b/tests/language/void/await_void_error_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that it is an error to await an expression of type `void`.
+
+import "dart:async";
+
+void v;
+List<void> vs = [null];
+FutureOr<void> fov;
+
+void main() async {
+ await print('');
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+
+ await v;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+
+ await vs[0];
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+
+ var v2 = vs[0];
+ await v2;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+
+ // A `FutureOr<void>` can be awaited.
+ await fov;
+}
diff --git a/tests/language_2/void/await_void_test.dart b/tests/language_2/void/await_void_test.dart
new file mode 100644
index 0000000..314e732
--- /dev/null
+++ b/tests/language_2/void/await_void_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that it is not an error to await an expression of type `void`.
+
+import "dart:async";
+
+void v;
+List<void> vs = [null];
+FutureOr<void> fov;
+
+void main() async {
+ await print('');
+ await v;
+ await vs[0];
+ var v2 = vs[0];
+ await v2;
+ await fov;
+}
diff --git a/tests/lib/convert/json_utf8_chunk_test.dart b/tests/lib/convert/json_utf8_chunk_test.dart
index db6a220..c18f330 100644
--- a/tests/lib/convert/json_utf8_chunk_test.dart
+++ b/tests/lib/convert/json_utf8_chunk_test.dart
@@ -148,7 +148,7 @@
// Tests combinations of numbers, strings and keywords.
void testAll() {
var s = r'{"":[true,false,42, -33e-3,null,"\u0080"], "z": 0}';
- bool check(o) {
+ void check(o) {
if (o is Map) {
Expect.equals(2, o.length);
Expect.equals(0, o["z"]);
diff --git a/tests/lib/html/indexeddb_2_test.dart b/tests/lib/html/indexeddb_2_test.dart
index b13c3cf..9c4da2b 100644
--- a/tests/lib/html/indexeddb_2_test.dart
+++ b/tests/lib/html/indexeddb_2_test.dart
@@ -32,7 +32,7 @@
db = await html.window.indexedDB!
.open(dbName, version: version, onUpgradeNeeded: createObjectStore);
- idb.Transaction transaction = db!.transactionList([storeName], 'readwrite');
+ idb.Transaction transaction = db.transactionList([storeName], 'readwrite');
transaction.objectStore(storeName).put(value, key);
db = await transaction.completed;
diff --git a/tests/standalone/io/http_parser_connect_method.dart b/tests/standalone/io/http_parser_connect_method.dart
deleted file mode 100644
index f543bcd..0000000
--- a/tests/standalone/io/http_parser_connect_method.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:async";
-import "dart:io";
-import "package:expect/expect.dart";
-
-test(String header, value) async {
- final connect = "CONNECT";
- var server = await HttpServer.bind("127.0.0.1", 0);
- server.listen((HttpRequest request) {
- Expect.equals(connect, request.method);
- request.response.statusCode = 200;
- request.response.headers.add(header, value);
- request.response.close();
- });
-
- var completer = Completer();
- HttpClient client = HttpClient();
- client
- .open(connect, "127.0.0.1", server.port, "/")
- .then((HttpClientRequest request) {
- return request.close();
- }).then((HttpClientResponse response) {
- Expect.isTrue(response.statusCode == 200);
- Expect.isNull(response.headers[header]);
- client.close();
- server.close();
- completer.complete();
- });
-
- await completer.future;
-}
-
-main() async {
- await test(HttpHeaders.contentLengthHeader, 0);
- await test(HttpHeaders.transferEncodingHeader, 'chunked');
-}
diff --git a/tests/standalone/io/http_parser_connect_method_test.dart b/tests/standalone/io/http_parser_connect_method_test.dart
new file mode 100644
index 0000000..ab02945
--- /dev/null
+++ b/tests/standalone/io/http_parser_connect_method_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<void> test(String header, value) async {
+ final connect = "CONNECT";
+ final server = await HttpServer.bind("127.0.0.1", 0);
+ server.listen((HttpRequest request) {
+ Expect.equals(connect, request.method);
+ request.response.statusCode = 200;
+ request.response.headers.add(header, value);
+ request.response.close();
+ });
+
+ final completer = Completer<void>();
+ HttpClient client = HttpClient();
+ client
+ .open(connect, "127.0.0.1", server.port, "/")
+ .then((HttpClientRequest request) {
+ return request.close();
+ }).then((HttpClientResponse response) {
+ Expect.equals(200, response.statusCode);
+ // Headers except Content-Length and Transfer-Encoding header will be read.
+ if (header == HttpHeaders.contentLengthHeader ||
+ header == HttpHeaders.transferEncodingHeader) {
+ Expect.isNull(response.headers[header]);
+ } else {
+ final list = response.headers[header];
+ Expect.isNotNull(list);
+ Expect.equals(1, list!.length);
+ Expect.equals(value, list[0]);
+ }
+
+ client.close();
+ server.close();
+ completer.complete();
+ });
+
+ await completer.future;
+}
+
+Future<void> runTests() async {
+ await test(HttpHeaders.contentLengthHeader, 0);
+ await test(HttpHeaders.transferEncodingHeader, 'chunked');
+ await test('testHeader', 'testValue');
+}
+
+main() {
+ asyncTest(runTests);
+}
diff --git a/tests/standalone/io/http_parser_header_add_test.dart b/tests/standalone/io/http_parser_header_add_test.dart
new file mode 100644
index 0000000..ebb947b
--- /dev/null
+++ b/tests/standalone/io/http_parser_header_add_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+
+// The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
+final value = 'Bob’s browser';
+
+// When a invalid value is added to http header, test that a FormatException is
+// thrown on an invalid user-agent header.
+Future<void> main() async {
+ final client = HttpClient();
+ client.userAgent = value;
+
+ asyncExpectThrows<FormatException>(() async {
+ try {
+ await client.getUrl(Uri.parse('https://postman-echo.com/get?'));
+ } finally {
+ client.close(force: true);
+ }
+ });
+}
diff --git a/tests/standalone/io/socket_hang_test.dart b/tests/standalone/io/socket_hang_test.dart
index 2231844..810d2a1 100644
--- a/tests/standalone/io/socket_hang_test.dart
+++ b/tests/standalone/io/socket_hang_test.dart
@@ -2,10 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:convert';
-import 'dart:io' as io;
+import 'dart:io';
-void main(List<String> args) async {
+import 'package:expect/expect.dart';
+
+// A regression test for: https://github.com/dart-lang/sdk/issues/40589
+Future<void> main(List<String> args) async {
if (args.length != 0) {
for (int i = 0; i < 100000; i++) {
print('line $i');
@@ -14,11 +16,14 @@
return;
} else {
// Create child process and keeps writing into stdout.
- final p = await io.Process.start(
- io.Platform.executable, [io.Platform.script.toFilePath(), 'child']);
- p.stdout.transform(utf8.decoder).listen((x) => print('stdout: $x'));
- p.stderr.transform(utf8.decoder).listen((x) => print('stderr: $x'));
+ final p = await Process.start(
+ Platform.executable, [Platform.script.toFilePath(), 'child']);
+ p.stdout.drain();
+ p.stderr.drain();
final exitCode = await p.exitCode;
- print('process exited with ${exitCode}');
+ if (exitCode != 0) {
+ Expect.fail('process failed with ${exitCode}');
+ }
+ return;
}
}
diff --git a/tests/standalone_2/io/http_parser_connect_method.dart b/tests/standalone_2/io/http_parser_connect_method.dart
deleted file mode 100644
index f543bcd..0000000
--- a/tests/standalone_2/io/http_parser_connect_method.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:async";
-import "dart:io";
-import "package:expect/expect.dart";
-
-test(String header, value) async {
- final connect = "CONNECT";
- var server = await HttpServer.bind("127.0.0.1", 0);
- server.listen((HttpRequest request) {
- Expect.equals(connect, request.method);
- request.response.statusCode = 200;
- request.response.headers.add(header, value);
- request.response.close();
- });
-
- var completer = Completer();
- HttpClient client = HttpClient();
- client
- .open(connect, "127.0.0.1", server.port, "/")
- .then((HttpClientRequest request) {
- return request.close();
- }).then((HttpClientResponse response) {
- Expect.isTrue(response.statusCode == 200);
- Expect.isNull(response.headers[header]);
- client.close();
- server.close();
- completer.complete();
- });
-
- await completer.future;
-}
-
-main() async {
- await test(HttpHeaders.contentLengthHeader, 0);
- await test(HttpHeaders.transferEncodingHeader, 'chunked');
-}
diff --git a/tests/standalone_2/io/http_parser_connect_method_test.dart b/tests/standalone_2/io/http_parser_connect_method_test.dart
new file mode 100644
index 0000000..d4ecad2
--- /dev/null
+++ b/tests/standalone_2/io/http_parser_connect_method_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<void> test(String header, value) async {
+ final connect = "CONNECT";
+ final server = await HttpServer.bind("127.0.0.1", 0);
+ server.listen((HttpRequest request) {
+ Expect.equals(connect, request.method);
+ request.response.statusCode = 200;
+ request.response.headers.add(header, value);
+ request.response.close();
+ });
+
+ final completer = Completer<void>();
+ HttpClient client = HttpClient();
+ client
+ .open(connect, "127.0.0.1", server.port, "/")
+ .then((HttpClientRequest request) {
+ return request.close();
+ }).then((HttpClientResponse response) {
+ Expect.equals(200, response.statusCode);
+ // Headers except Content-Length and Transfer-Encoding header will be read.
+ if (header == HttpHeaders.contentLengthHeader ||
+ header == HttpHeaders.transferEncodingHeader) {
+ Expect.isNull(response.headers[header]);
+ } else {
+ Expect.isNotNull(response.headers[header]);
+ Expect.equals(1, response.headers[header].length);
+ Expect.equals(value, response.headers[header][0]);
+ }
+
+ client.close();
+ server.close();
+ completer.complete();
+ });
+
+ await completer.future;
+}
+
+Future<void> runTests() async {
+ await test(HttpHeaders.contentLengthHeader, 0);
+ await test(HttpHeaders.transferEncodingHeader, 'chunked');
+ await test('testHeader', 'testValue');
+}
+
+main() {
+ asyncTest(runTests);
+}
diff --git a/tests/standalone_2/io/http_parser_header_add_test.dart b/tests/standalone_2/io/http_parser_header_add_test.dart
new file mode 100644
index 0000000..ebb947b
--- /dev/null
+++ b/tests/standalone_2/io/http_parser_header_add_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+
+// The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
+final value = 'Bob’s browser';
+
+// When a invalid value is added to http header, test that a FormatException is
+// thrown on an invalid user-agent header.
+Future<void> main() async {
+ final client = HttpClient();
+ client.userAgent = value;
+
+ asyncExpectThrows<FormatException>(() async {
+ try {
+ await client.getUrl(Uri.parse('https://postman-echo.com/get?'));
+ } finally {
+ client.close(force: true);
+ }
+ });
+}
diff --git a/tests/standalone_2/io/socket_hang_test.dart b/tests/standalone_2/io/socket_hang_test.dart
index 2231844..810d2a1 100644
--- a/tests/standalone_2/io/socket_hang_test.dart
+++ b/tests/standalone_2/io/socket_hang_test.dart
@@ -2,10 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:convert';
-import 'dart:io' as io;
+import 'dart:io';
-void main(List<String> args) async {
+import 'package:expect/expect.dart';
+
+// A regression test for: https://github.com/dart-lang/sdk/issues/40589
+Future<void> main(List<String> args) async {
if (args.length != 0) {
for (int i = 0; i < 100000; i++) {
print('line $i');
@@ -14,11 +16,14 @@
return;
} else {
// Create child process and keeps writing into stdout.
- final p = await io.Process.start(
- io.Platform.executable, [io.Platform.script.toFilePath(), 'child']);
- p.stdout.transform(utf8.decoder).listen((x) => print('stdout: $x'));
- p.stderr.transform(utf8.decoder).listen((x) => print('stderr: $x'));
+ final p = await Process.start(
+ Platform.executable, [Platform.script.toFilePath(), 'child']);
+ p.stdout.drain();
+ p.stderr.drain();
final exitCode = await p.exitCode;
- print('process exited with ${exitCode}');
+ if (exitCode != 0) {
+ Expect.fail('process failed with ${exitCode}');
+ }
+ return;
}
}
diff --git a/tests/standalone_2/regress_41329_test.dart b/tests/standalone_2/regress_41329_absolute_test.dart
similarity index 81%
rename from tests/standalone_2/regress_41329_test.dart
rename to tests/standalone_2/regress_41329_absolute_test.dart
index 3ac957a..5673b99 100644
--- a/tests/standalone_2/regress_41329_test.dart
+++ b/tests/standalone_2/regress_41329_absolute_test.dart
@@ -5,17 +5,18 @@
import 'dart:io';
import 'package:async_helper/async_helper.dart';
+import 'package:path/path.dart' as p;
import 'package:expect/expect.dart';
Future<void> main() async {
final origDir = Directory.current;
final exePath = Platform.resolvedExecutable;
- var d = Directory.systemTemp.createTempSync('dart_symlink');
+ final d = Directory.systemTemp.createTempSync('dart_symlink');
// Roughly emulate a Brew installation:
// - $BREW/bin/dart -> ../Cellar/dart/2.8.0-dev.20.0/bin/dart
// - $BREW/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
- var a = Directory('${d.path}/usr/local/bin');
+ final a = Directory('${d.path}/usr/local/bin');
a.createSync(recursive: true);
// /usr/local/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
@@ -26,11 +27,10 @@
// /usr/local/bin/dart -> /usr/local/Cellar/dart/2.8.0-dev.20/bin/dart
final link2 = Link('dart')..createSync(linkLocation, recursive: true);
- final path = link2.absolute.path;
-
+ final path = Uri.parse(link2.absolute.path).path;
Directory.current = origDir;
final result = await Process.run('${path}',
- [Platform.script.resolve('regress_41329_helper.dart').toString()]);
+ [p.relative(Platform.script.resolve('regress_41329_helper.dart').path)]);
Expect.equals(result.stdout, '');
Expect.equals(result.stderr, '');
Expect.equals(result.exitCode, 42);
diff --git a/tests/standalone_2/regress_41329_test.dart b/tests/standalone_2/regress_41329_relative_test.dart
similarity index 81%
copy from tests/standalone_2/regress_41329_test.dart
copy to tests/standalone_2/regress_41329_relative_test.dart
index 3ac957a..5673b99 100644
--- a/tests/standalone_2/regress_41329_test.dart
+++ b/tests/standalone_2/regress_41329_relative_test.dart
@@ -5,17 +5,18 @@
import 'dart:io';
import 'package:async_helper/async_helper.dart';
+import 'package:path/path.dart' as p;
import 'package:expect/expect.dart';
Future<void> main() async {
final origDir = Directory.current;
final exePath = Platform.resolvedExecutable;
- var d = Directory.systemTemp.createTempSync('dart_symlink');
+ final d = Directory.systemTemp.createTempSync('dart_symlink');
// Roughly emulate a Brew installation:
// - $BREW/bin/dart -> ../Cellar/dart/2.8.0-dev.20.0/bin/dart
// - $BREW/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
- var a = Directory('${d.path}/usr/local/bin');
+ final a = Directory('${d.path}/usr/local/bin');
a.createSync(recursive: true);
// /usr/local/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
@@ -26,11 +27,10 @@
// /usr/local/bin/dart -> /usr/local/Cellar/dart/2.8.0-dev.20/bin/dart
final link2 = Link('dart')..createSync(linkLocation, recursive: true);
- final path = link2.absolute.path;
-
+ final path = Uri.parse(link2.absolute.path).path;
Directory.current = origDir;
final result = await Process.run('${path}',
- [Platform.script.resolve('regress_41329_helper.dart').toString()]);
+ [p.relative(Platform.script.resolve('regress_41329_helper.dart').path)]);
Expect.equals(result.stdout, '');
Expect.equals(result.stderr, '');
Expect.equals(result.exitCode, 42);
diff --git a/tools/VERSION b/tools/VERSION
index fe4153b..aad0d9f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
MAJOR 2
MINOR 9
PATCH 0
-PRERELEASE 2
+PRERELEASE 3
PRERELEASE_PATCH 0
ABI_VERSION 32
OLDEST_SUPPORTED_ABI_VERSION 32
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index c549bb6..068c5df 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -452,6 +452,18 @@
"use-sdk": true
}
},
+ "unittest-weak-asserts-no-sdk-(linux|mac|win)": {
+ "options": {
+ "compiler": "dartk",
+ "enable-asserts": true,
+ "mode": "release",
+ "runtime": "vm",
+ "timeout": 240,
+ "enable-experiment": [
+ "non-nullable"
+ ]
+ }
+ },
"analyzer-unittest-asserts-(debug|product|release)-(linux|mac|win)": {
"options": {
"compiler": "dartk",
@@ -2700,6 +2712,14 @@
],
"shards": 6,
"fileset": "dart2js_hostasserts_nnbd"
+ },
+ {
+ "name": "dart2js nnbd unit tests",
+ "arguments": [
+ "-nunittest-weak-asserts-no-sdk-linux",
+ "dart2js",
+ "pkg//compiler/"
+ ]
}
]
},