@rljson/io 0.0.61 → 0.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/io.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { hip, hsh } from "@rljson/hash";
2
2
  import { IsReady } from "@rljson/is-ready";
3
- import { copy, equals } from "@rljson/json";
3
+ import { copy, equals, merge } from "@rljson/json";
4
4
  import { iterateTables, throwOnInvalidTableCfg, validateRljsonAgainstTableCfg, iterateTablesSync } from "@rljson/rljson";
5
5
  class IoDbNameMapping {
6
6
  // The primary key column is always named '_hash'
@@ -600,20 +600,6 @@ class IoMem {
600
600
  });
601
601
  }
602
602
  }
603
- const exampleTestSetup = () => {
604
- return {
605
- io: new IoMem(),
606
- beforeAll: async () => {
607
- },
608
- beforeEach: async () => {
609
- },
610
- afterEach: async () => {
611
- },
612
- afterAll: async () => {
613
- }
614
- };
615
- };
616
- const exampleIo = "Checkout @rljson/io-mem for an example implementation";
617
603
  class PeerSocketMock {
618
604
  constructor(_io) {
619
605
  this._io = _io;
@@ -622,6 +608,36 @@ class PeerSocketMock {
622
608
  connected = false;
623
609
  disconnected = true;
624
610
  // ............................................................................
611
+ /**
612
+ * Removes a specific listener for the specified event.
613
+ * @param eventName - The name of the event.
614
+ * @param listener - The callback function to remove.
615
+ * @returns The PeerSocketMock instance for chaining.
616
+ */
617
+ off(eventName, listener) {
618
+ const listeners = this._listenersMap.get(eventName) || [];
619
+ const index = listeners.indexOf(listener);
620
+ if (index !== -1) {
621
+ listeners.splice(index, 1);
622
+ this._listenersMap.set(eventName, listeners);
623
+ }
624
+ return this;
625
+ }
626
+ // ............................................................................
627
+ /**
628
+ * Removes all listeners for the specified event, or all listeners if no event is specified.
629
+ * @param eventName - (Optional) The name of the event.
630
+ * @returns The PeerSocketMock instance for chaining.
631
+ */
632
+ removeAllListeners(eventName) {
633
+ if (eventName) {
634
+ this._listenersMap.delete(eventName);
635
+ } else {
636
+ this._listenersMap.clear();
637
+ }
638
+ return this;
639
+ }
640
+ // ............................................................................
625
641
  /**
626
642
  * Registers an event listener for the specified event.
627
643
  * @param eventName - The name of the event to listen for.
@@ -684,6 +700,741 @@ class PeerSocketMock {
684
700
  return true;
685
701
  }
686
702
  }
703
+ class IoPeer {
704
+ constructor(_socket) {
705
+ this._socket = _socket;
706
+ }
707
+ isOpen = false;
708
+ // ...........................................................................
709
+ /**
710
+ *
711
+ * Initializes the Peer connection.
712
+ * @returns
713
+ */
714
+ async init() {
715
+ this._socket.on("connect", () => {
716
+ this.isOpen = true;
717
+ });
718
+ this._socket.on("disconnect", () => {
719
+ this.isOpen = false;
720
+ });
721
+ this._socket.connect();
722
+ return new Promise((resolve) => {
723
+ if (this._socket.connected) {
724
+ this.isOpen = true;
725
+ resolve();
726
+ } else {
727
+ this._socket.on("connect", () => {
728
+ resolve();
729
+ });
730
+ }
731
+ });
732
+ }
733
+ // ...........................................................................
734
+ /**
735
+ * Closes the Peer connection.
736
+ * @returns
737
+ */
738
+ async close() {
739
+ if (!this._socket.connected) return;
740
+ return new Promise((resolve) => {
741
+ this._socket.on("disconnect", () => {
742
+ resolve();
743
+ });
744
+ this._socket.disconnect();
745
+ });
746
+ }
747
+ // ...........................................................................
748
+ /**
749
+ * Returns a promise that resolves once the Peer connection is ready.
750
+ * @returns
751
+ */
752
+ async isReady() {
753
+ if (!!this._socket && this._socket.connected === true) this.isOpen = true;
754
+ else this.isOpen = false;
755
+ return !!this.isOpen ? Promise.resolve() : Promise.reject();
756
+ }
757
+ // ...........................................................................
758
+ /**
759
+ * Dumps the entire database content.
760
+ * @returns A promise that resolves to the dumped database content.
761
+ */
762
+ async dump() {
763
+ return new Promise((resolve) => {
764
+ this._socket.emit("dump", (data) => {
765
+ resolve(data);
766
+ });
767
+ });
768
+ }
769
+ // ...........................................................................
770
+ /**
771
+ * Dumps a specific table from the database.
772
+ * @param request An object containing the table name to dump.
773
+ * @returns A promise that resolves to the dumped table data.
774
+ */
775
+ dumpTable(request) {
776
+ return new Promise((resolve, reject) => {
777
+ this._socket.emit("dumpTable", request, (data, error) => {
778
+ if (error) reject(error);
779
+ resolve(data);
780
+ });
781
+ });
782
+ }
783
+ // ...........................................................................
784
+ /**
785
+ * Gets the content type of a specific table.
786
+ * @param request An object containing the table name to get the content type for.
787
+ * @returns A promise that resolves to the content type of the specified table.
788
+ */
789
+ contentType(request) {
790
+ return new Promise((resolve, reject) => {
791
+ this._socket.emit(
792
+ "contentType",
793
+ request,
794
+ (data, error) => {
795
+ if (error) reject(error);
796
+ resolve(data);
797
+ }
798
+ );
799
+ });
800
+ }
801
+ // ...........................................................................
802
+ /**
803
+ * Checks if a specific table exists in the database.
804
+ * @param tableKey The key of the table to check for existence.
805
+ * @returns A promise that resolves to true if the table exists, false otherwise.
806
+ */
807
+ tableExists(tableKey) {
808
+ return new Promise((resolve) => {
809
+ this._socket.emit("tableExists", tableKey, (exists) => {
810
+ resolve(exists);
811
+ });
812
+ });
813
+ }
814
+ // ...........................................................................
815
+ /**
816
+ * Creates or extends a table with the given configuration.
817
+ * @param request An object containing the table configuration.
818
+ * @returns A promise that resolves once the table is created or extended.
819
+ */
820
+ createOrExtendTable(request) {
821
+ return new Promise((resolve, reject) => {
822
+ this._socket.emit(
823
+ "createOrExtendTable",
824
+ request,
825
+ (_, error) => {
826
+ if (error) reject(error);
827
+ resolve();
828
+ }
829
+ );
830
+ });
831
+ }
832
+ // ...........................................................................
833
+ /**
834
+ * Retrieves the raw table configurations from the database.
835
+ * @returns A promise that resolves to an array of table configurations.
836
+ */
837
+ rawTableCfgs() {
838
+ return new Promise((resolve) => {
839
+ this._socket.emit("rawTableCfgs", (data) => {
840
+ resolve(data);
841
+ });
842
+ });
843
+ }
844
+ // ...........................................................................
845
+ /**
846
+ * Writes data to the database.
847
+ * @param request An object containing the data to write.
848
+ * @returns A promise that resolves once the data is written.
849
+ */
850
+ write(request) {
851
+ return new Promise((resolve, reject) => {
852
+ this._socket.emit("write", request, (_, error) => {
853
+ if (error) reject(error);
854
+ resolve();
855
+ });
856
+ });
857
+ }
858
+ // ...........................................................................
859
+ /**
860
+ * Reads rows from a specific table that match the given criteria.
861
+ * @param request An object containing the table name and the criteria for selecting rows.
862
+ * @returns A promise that resolves to the selected rows.
863
+ */
864
+ readRows(request) {
865
+ return new Promise((resolve, reject) => {
866
+ this._socket.emit(
867
+ "readRows",
868
+ request,
869
+ (result, error) => {
870
+ if (error) reject(error);
871
+ resolve(result);
872
+ }
873
+ );
874
+ });
875
+ }
876
+ // ...........................................................................
877
+ /**
878
+ * Retrieves the number of rows in a specific table.
879
+ * @param table The name of the table to count rows in.
880
+ * @returns A promise that resolves to the number of rows in the specified table.
881
+ */
882
+ rowCount(table) {
883
+ return new Promise((resolve, reject) => {
884
+ this._socket.emit("rowCount", table, (count, error) => {
885
+ if (error) reject(error);
886
+ resolve(count);
887
+ });
888
+ });
889
+ }
890
+ // ...........................................................................
891
+ static example = async () => {
892
+ const ioMem = await IoMem.example();
893
+ const socket = new PeerSocketMock(ioMem);
894
+ const io = new IoPeer(socket);
895
+ await io.init();
896
+ return io;
897
+ };
898
+ }
899
+ class IoMulti {
900
+ constructor(_ios) {
901
+ this._ios = _ios;
902
+ }
903
+ isOpen = false;
904
+ // ...........................................................................
905
+ /**
906
+ *
907
+ * Initializes all underlying Io instances.
908
+ * @returns
909
+ */
910
+ async init() {
911
+ for (let idx = 0; idx < this._ios.length; idx++) {
912
+ const { io } = this._ios[idx];
913
+ if (io.isOpen === false) {
914
+ throw new Error(
915
+ "All underlying Io instances must be initialized before initializing IoMulti"
916
+ );
917
+ }
918
+ this._ios[idx] = { ...this._ios[idx], id: `io-${idx}` };
919
+ }
920
+ this.isOpen = true;
921
+ return Promise.resolve();
922
+ }
923
+ // ...........................................................................
924
+ /**
925
+ * Closes all underlying Io instances.
926
+ * @returns
927
+ */
928
+ async close() {
929
+ await Promise.all(this._ios.map((ioMultiIo) => ioMultiIo.io.close()));
930
+ this.isOpen = false;
931
+ return Promise.resolve();
932
+ }
933
+ // ...........................................................................
934
+ /**
935
+ * Returns a promise that resolves once all underlying Io instances are ready.
936
+ * @returns
937
+ */
938
+ isReady() {
939
+ return Promise.all(
940
+ this._ios.map((ioMultiIo) => ioMultiIo.io.isReady())
941
+ ).then(() => Promise.resolve());
942
+ }
943
+ // ...........................................................................
944
+ /**
945
+ * Dumps the entire database content by merging dumps from all dumpable underlying Io instances.
946
+ * @returns
947
+ */
948
+ async dump() {
949
+ if (this.dumpables.length === 0) {
950
+ throw new Error("No dumpable Io available");
951
+ }
952
+ const dumps = await Promise.all(
953
+ this.dumpables.map(({ io: dumpable }) => dumpable.dump())
954
+ );
955
+ return merge(...dumps);
956
+ }
957
+ // ...........................................................................
958
+ /**
959
+ * Dumps a specific table by merging dumps from all dumpable underlying Io instances that contain the table.
960
+ * @param request An object containing the table name to dump.
961
+ * @returns A promise that resolves to the dumped table data.
962
+ */
963
+ async dumpTable(request) {
964
+ if (this.dumpables.length === 0) {
965
+ throw new Error("No dumpable Io available");
966
+ }
967
+ const dumps = [];
968
+ for (const { io: dumpable } of this.dumpables) {
969
+ try {
970
+ const dump = await dumpable.dumpTable(request);
971
+ dumps.push(dump);
972
+ } catch {
973
+ continue;
974
+ }
975
+ }
976
+ if (dumps.length === 0) {
977
+ throw new Error(`Table "${request.table}" not found`);
978
+ }
979
+ return merge(...dumps);
980
+ }
981
+ // ...........................................................................
982
+ /**
983
+ * Retrieves the content type of a specific table from the first underlying readable Io instance that contains the table.
984
+ * @param request An object containing the table name.
985
+ * @returns A promise that resolves to the content type of the table.
986
+ */
987
+ async contentType(request) {
988
+ if (this.readables.length === 0) {
989
+ throw new Error("No readable Io available");
990
+ }
991
+ for (const { io: readable } of this.readables) {
992
+ return readable.contentType(request);
993
+ }
994
+ throw new Error(`Table "${request.table}" not found`);
995
+ }
996
+ // ...........................................................................
997
+ /**
998
+ * Checks if a specific table exists in any of the underlying readable Io instances.
999
+ * @param tableKey The key of the table to check.
1000
+ * @returns A promise that resolves to true if the table exists in any readable Io, false otherwise.
1001
+ */
1002
+ async tableExists(tableKey) {
1003
+ if (this.readables.length === 0) {
1004
+ throw new Error("No readable Io available");
1005
+ }
1006
+ for (let i = 0; i < this.readables.length; i++) {
1007
+ const readable = this.readables[i].io;
1008
+ const exists = await readable.tableExists(tableKey);
1009
+ if (exists) {
1010
+ return true;
1011
+ }
1012
+ }
1013
+ return false;
1014
+ }
1015
+ // ...........................................................................
1016
+ /**
1017
+ * Creates or extends a table in all underlying writable Io instances.
1018
+ * @param request An object containing the table configuration.
1019
+ * @returns A promise that resolves once the table has been created or extended in all writable Io instances.
1020
+ */
1021
+ createOrExtendTable(request) {
1022
+ if (this.writables.length === 0) {
1023
+ throw new Error("No writable Io available");
1024
+ }
1025
+ const creations = this.writables.map(
1026
+ ({ io: writable }) => writable.createOrExtendTable(request)
1027
+ );
1028
+ return Promise.all(creations).then(() => Promise.resolve());
1029
+ }
1030
+ // ...........................................................................
1031
+ /**
1032
+ * Retrieves the raw table configurations from the highest priority underlying readable Io instance.
1033
+ * @returns A promise that resolves to an array of table configurations.
1034
+ */
1035
+ async rawTableCfgs() {
1036
+ if (this.readables.length === 0) {
1037
+ throw new Error("No readable Io available");
1038
+ }
1039
+ const rawTableCfgs = /* @__PURE__ */ new Map();
1040
+ for (const { io: readable } of this.readables) {
1041
+ const cfgs = await readable.rawTableCfgs();
1042
+ if (cfgs.length > 0) {
1043
+ for (const tableCfg of cfgs) {
1044
+ if (!rawTableCfgs.has(tableCfg.key)) {
1045
+ rawTableCfgs.set(tableCfg.key, tableCfg);
1046
+ }
1047
+ }
1048
+ }
1049
+ }
1050
+ return Array.from(rawTableCfgs.values());
1051
+ }
1052
+ // ...........................................................................
1053
+ /**
1054
+ * Writes data to all underlying writable Io instances.
1055
+ * @param request - An object containing the data to write.
1056
+ * @returns A promise that resolves once the data has been written to all writable Io instances.
1057
+ */
1058
+ write(request) {
1059
+ if (this.writables.length === 0) {
1060
+ throw new Error("No writable Io available");
1061
+ }
1062
+ const writes = this.writables.map(
1063
+ ({ io: writable }) => writable.write(request)
1064
+ );
1065
+ return Promise.all(writes).then(() => Promise.resolve());
1066
+ }
1067
+ // ...........................................................................
1068
+ /**
1069
+ * Reads rows from a specific table by merging rows from all underlying readable Io instances.
1070
+ * @param request An object containing the table name and where clause.
1071
+ * @returns A promise that resolves to the read rows.
1072
+ */
1073
+ async readRows(request) {
1074
+ if (this.readables.length === 0) {
1075
+ throw new Error("No readable Io available");
1076
+ }
1077
+ let tableExistsAny = false;
1078
+ const rows = /* @__PURE__ */ new Map();
1079
+ let type = void 0;
1080
+ let readFrom = "";
1081
+ const errors = [];
1082
+ for (const readable of this.readables) {
1083
+ let tableRows = [];
1084
+ let tableType;
1085
+ try {
1086
+ const { [request.table]: tableData } = await readable.io.readRows(
1087
+ request
1088
+ );
1089
+ tableRows = tableData._data;
1090
+ tableType = tableData._type;
1091
+ tableExistsAny = true;
1092
+ readFrom = readable.id ?? "";
1093
+ } catch (e) {
1094
+ errors.push(e);
1095
+ continue;
1096
+ }
1097
+ type ??= tableType;
1098
+ if (tableRows.length === 0) {
1099
+ continue;
1100
+ }
1101
+ for (const tableRow of tableRows) {
1102
+ const ref = tableRow._hash;
1103
+ rows.set(ref, tableRow);
1104
+ }
1105
+ break;
1106
+ }
1107
+ if (!tableExistsAny) {
1108
+ if (errors.length === 0) {
1109
+ throw new Error(`Table "${request.table}" not found`);
1110
+ } else {
1111
+ const preciseErrors = errors.filter(
1112
+ (err) => !err.message.includes(`Table "${request.table}" not found`)
1113
+ );
1114
+ if (preciseErrors.length > 0) {
1115
+ throw preciseErrors[0];
1116
+ } else {
1117
+ throw errors[0];
1118
+ }
1119
+ }
1120
+ } else {
1121
+ const rljson = {
1122
+ [request.table]: hip({ _data: Array.from(rows.values()), _type: type })
1123
+ };
1124
+ if (this.writables.length > 0 && rows.size > 0) {
1125
+ for (const writeable of this.writables) {
1126
+ if (writeable.id === readFrom) {
1127
+ continue;
1128
+ }
1129
+ try {
1130
+ await writeable.io.write({
1131
+ data: rljson
1132
+ });
1133
+ } catch {
1134
+ continue;
1135
+ }
1136
+ }
1137
+ }
1138
+ return rljson;
1139
+ }
1140
+ }
1141
+ // ...........................................................................
1142
+ /**
1143
+ * Retrieves the row count of a specific table by aggregating row counts from all dumpable underlying Io instances.
1144
+ * @param table The name of the table.
1145
+ * @returns A promise that resolves to the row count of the table.
1146
+ */
1147
+ async rowCount(table) {
1148
+ if (this.dumpables.length === 0) {
1149
+ throw new Error("No dumpable Io available");
1150
+ }
1151
+ const dumpTable = await this.dumpTable({ table });
1152
+ const tableData = dumpTable[table];
1153
+ if (!tableData) {
1154
+ throw new Error(`Table "${table}" not found`);
1155
+ }
1156
+ return Promise.resolve(tableData._data.length);
1157
+ }
1158
+ // ...........................................................................
1159
+ /**
1160
+ * Gets the list of underlying readable Io instances, sorted by priority.
1161
+ */
1162
+ get readables() {
1163
+ return this._ios.filter((ioMultiIo) => ioMultiIo.read).sort((a, b) => a.priority - b.priority);
1164
+ }
1165
+ // ...........................................................................
1166
+ /**
1167
+ * Gets the list of underlying writable Io instances, sorted by priority.
1168
+ */
1169
+ get writables() {
1170
+ return this._ios.filter((ioMultiIo) => ioMultiIo.write).sort((a, b) => a.priority - b.priority);
1171
+ }
1172
+ // ...........................................................................
1173
+ /**
1174
+ * Gets the list of underlying dumpable Io instances, sorted by priority.
1175
+ */
1176
+ get dumpables() {
1177
+ return this._ios.filter((ioMultiIo) => ioMultiIo.dump).sort((a, b) => a.priority - b.priority);
1178
+ }
1179
+ // ...........................................................................
1180
+ static example = async () => {
1181
+ const ioPeerMem = await IoMem.example();
1182
+ await ioPeerMem.init();
1183
+ const ioPeerSocket = new PeerSocketMock(ioPeerMem);
1184
+ const ioPeer = new IoPeer(ioPeerSocket);
1185
+ await ioPeer.init();
1186
+ const ioMem = await IoMem.example();
1187
+ await ioMem.init();
1188
+ const ios = [
1189
+ { io: ioPeer, priority: 1, read: true, write: false, dump: false },
1190
+ { io: ioMem, priority: 0, read: true, write: true, dump: true }
1191
+ ];
1192
+ const ioMulti = new IoMulti(ios);
1193
+ await ioMulti.init();
1194
+ return ioMulti;
1195
+ };
1196
+ }
1197
+ class IoPeerBridge {
1198
+ constructor(_io, _socket) {
1199
+ this._io = _io;
1200
+ this._socket = _socket;
1201
+ }
1202
+ _eventHandlers = /* @__PURE__ */ new Map();
1203
+ /**
1204
+ * Starts the bridge by setting up connection event handlers and
1205
+ * automatically registering all Io methods.
1206
+ */
1207
+ start() {
1208
+ this._socket.on("connect", () => this._handleConnect());
1209
+ this._socket.on("disconnect", () => this._handleDisconnect());
1210
+ this._registerIoMethods();
1211
+ }
1212
+ /**
1213
+ * Stops the bridge by removing all event handlers.
1214
+ */
1215
+ stop() {
1216
+ this._socket.off("connect", () => this._handleConnect());
1217
+ this._socket.off("disconnect", () => this._handleDisconnect());
1218
+ for (const [eventName, handler] of this._eventHandlers) {
1219
+ this._socket.off(eventName, handler);
1220
+ }
1221
+ this._eventHandlers.clear();
1222
+ }
1223
+ /**
1224
+ * Automatically registers all Io interface methods as socket event handlers.
1225
+ */
1226
+ _registerIoMethods() {
1227
+ const ioMethods = [
1228
+ "init",
1229
+ "isReady",
1230
+ "close",
1231
+ "tableExists",
1232
+ "createOrExtendTable",
1233
+ "write",
1234
+ "readRows",
1235
+ "rowCount",
1236
+ "dumpTable",
1237
+ "dump",
1238
+ "contentType",
1239
+ "rawTableCfgs"
1240
+ ];
1241
+ for (const methodName of ioMethods) {
1242
+ this.registerEvent(methodName);
1243
+ }
1244
+ }
1245
+ /**
1246
+ * Registers a socket event to be translated to an Io method call.
1247
+ *
1248
+ * @param eventName - The socket event name (should match an Io method name)
1249
+ * @param ioMethodName - (Optional) The Io method name if different from eventName
1250
+ */
1251
+ registerEvent(eventName, ioMethodName) {
1252
+ const methodName = ioMethodName || eventName;
1253
+ const handler = (...args) => {
1254
+ const callback = args[args.length - 1];
1255
+ const methodArgs = args.slice(0, -1);
1256
+ const ioMethod = this._io[methodName];
1257
+ if (typeof ioMethod !== "function") {
1258
+ const error = new Error(
1259
+ `Method "${methodName}" not found on Io instance`
1260
+ );
1261
+ if (typeof callback === "function") {
1262
+ callback(null, error);
1263
+ }
1264
+ return;
1265
+ }
1266
+ ioMethod.apply(this._io, methodArgs).then((result) => {
1267
+ if (typeof callback === "function") {
1268
+ callback(result, null);
1269
+ }
1270
+ }).catch((error) => {
1271
+ if (typeof callback === "function") {
1272
+ callback(null, error);
1273
+ }
1274
+ });
1275
+ };
1276
+ this._eventHandlers.set(eventName, handler);
1277
+ this._socket.on(eventName, handler);
1278
+ }
1279
+ /**
1280
+ * Registers multiple socket events at once.
1281
+ *
1282
+ * @param eventNames - Array of event names to register
1283
+ */
1284
+ registerEvents(eventNames) {
1285
+ for (const eventName of eventNames) {
1286
+ this.registerEvent(eventName);
1287
+ }
1288
+ }
1289
+ /**
1290
+ * Unregisters a socket event handler.
1291
+ *
1292
+ * @param eventName - The event name to unregister
1293
+ */
1294
+ unregisterEvent(eventName) {
1295
+ const handler = this._eventHandlers.get(eventName);
1296
+ if (handler) {
1297
+ this._socket.off(eventName, handler);
1298
+ this._eventHandlers.delete(eventName);
1299
+ }
1300
+ }
1301
+ /**
1302
+ * Emits a result back through the socket.
1303
+ *
1304
+ * @param eventName - The event name to emit
1305
+ * @param data - The data to send
1306
+ */
1307
+ emitToSocket(eventName, ...data) {
1308
+ this._socket.emit(eventName, ...data);
1309
+ }
1310
+ /**
1311
+ * Calls an Io method directly and emits the result through the socket.
1312
+ *
1313
+ * @param ioMethodName - The Io method to call
1314
+ * @param socketEventName - The socket event to emit with the result
1315
+ * @param args - Arguments to pass to the Io method
1316
+ */
1317
+ async callIoAndEmit(ioMethodName, socketEventName, ...args) {
1318
+ try {
1319
+ const ioMethod = this._io[ioMethodName];
1320
+ if (typeof ioMethod !== "function") {
1321
+ throw new Error(`Method "${ioMethodName}" not found on Io instance`);
1322
+ }
1323
+ const result = await ioMethod.apply(this._io, args);
1324
+ this._socket.emit(socketEventName, result, null);
1325
+ } catch (error) {
1326
+ this._socket.emit(socketEventName, null, error);
1327
+ }
1328
+ }
1329
+ /* v8 ignore next -- @preserve */
1330
+ _handleConnect() {
1331
+ }
1332
+ /* v8 ignore next -- @preserve */
1333
+ _handleDisconnect() {
1334
+ }
1335
+ /**
1336
+ * Gets the current socket instance.
1337
+ */
1338
+ get socket() {
1339
+ return this._socket;
1340
+ }
1341
+ /**
1342
+ * Gets the current Io instance.
1343
+ */
1344
+ get io() {
1345
+ return this._io;
1346
+ }
1347
+ /**
1348
+ * Returns whether the socket is currently connected.
1349
+ */
1350
+ get isConnected() {
1351
+ return this._socket.connected;
1352
+ }
1353
+ }
1354
+ class IoServer {
1355
+ constructor(_io) {
1356
+ this._io = _io;
1357
+ }
1358
+ _sockets = [];
1359
+ // ...........................................................................
1360
+ /**
1361
+ * Adds a socket to the IoServer instance.
1362
+ * @param socket - The socket to add.
1363
+ */
1364
+ async addSocket(socket) {
1365
+ await this._addTransportLayer(socket);
1366
+ this._sockets.push(socket);
1367
+ }
1368
+ // ...........................................................................
1369
+ /**
1370
+ * Removes a transport layer from the given socket.
1371
+ * @param socket - The socket to remove the transport layer from.
1372
+ */
1373
+ removeSocket(socket) {
1374
+ this._sockets = this._sockets.filter((s) => s !== socket);
1375
+ }
1376
+ // ...........................................................................
1377
+ /**
1378
+ * Adds a transport layer to the given socket.
1379
+ * @param socket - The socket to add the transport layer to.
1380
+ */
1381
+ async _addTransportLayer(socket) {
1382
+ const crud = this._generateTransportLayerCRUD(this._io);
1383
+ for (const [key, fn] of Object.entries(crud)) {
1384
+ socket.on(key, (...args) => {
1385
+ const cb = args[args.length - 1];
1386
+ fn.apply(this, args.slice(0, -1)).then((result) => {
1387
+ cb(result, null);
1388
+ }).catch((err) => {
1389
+ cb(null, err);
1390
+ });
1391
+ });
1392
+ }
1393
+ }
1394
+ // ...........................................................................
1395
+ /**
1396
+ * Creates or extends a table with the given configuration.
1397
+ * @param request - An object containing the table configuration.
1398
+ */
1399
+ async createOrExtendTable(request) {
1400
+ return this._io.createOrExtendTable(request);
1401
+ }
1402
+ // ...........................................................................
1403
+ /**
1404
+ * Generates a transport layer object for the given Io instance.
1405
+ * @param io - The Io instance to generate the transport layer for.
1406
+ * @returns An object containing methods that correspond to the Io interface.
1407
+ */
1408
+ _generateTransportLayerCRUD = (io) => ({
1409
+ init: () => io.init(),
1410
+ close: () => io.close(),
1411
+ isOpen: () => new Promise((resolve) => resolve(io.isOpen)),
1412
+ isReady: () => io.isReady(),
1413
+ dump: () => io.dump(),
1414
+ dumpTable: (request) => io.dumpTable(request),
1415
+ contentType: (request) => io.contentType(request),
1416
+ tableExists: (tableKey) => io.tableExists(tableKey),
1417
+ createOrExtendTable: (request) => this.createOrExtendTable(request),
1418
+ rawTableCfgs: () => io.rawTableCfgs(),
1419
+ write: (request) => io.write(request),
1420
+ readRows: (request) => io.readRows(request),
1421
+ rowCount: (table) => io.rowCount(table)
1422
+ });
1423
+ }
1424
+ const exampleTestSetup = () => {
1425
+ return {
1426
+ io: new IoMem(),
1427
+ beforeAll: async () => {
1428
+ },
1429
+ beforeEach: async () => {
1430
+ },
1431
+ afterEach: async () => {
1432
+ },
1433
+ afterAll: async () => {
1434
+ }
1435
+ };
1436
+ };
1437
+ const exampleIo = "Checkout @rljson/io-mem for an example implementation";
687
1438
  const calcReverseRefs = (rljson) => {
688
1439
  const result = {};
689
1440
  iterateTablesSync(rljson, (childTableKey, table) => {
@@ -940,11 +1691,23 @@ const socketExample = () => ({
940
1691
  /* v8 ignore next -- @preserve */
941
1692
  emit() {
942
1693
  return true;
1694
+ },
1695
+ /* v8 ignore next -- @preserve */
1696
+ off() {
1697
+ return this;
1698
+ },
1699
+ /* v8 ignore next -- @preserve */
1700
+ removeAllListeners() {
1701
+ return this;
943
1702
  }
944
1703
  });
945
1704
  export {
946
1705
  IoDbNameMapping,
947
1706
  IoMem,
1707
+ IoMulti,
1708
+ IoPeer,
1709
+ IoPeerBridge,
1710
+ IoServer,
948
1711
  IoTools,
949
1712
  PeerSocketMock,
950
1713
  SocketMock,
@@ -953,4 +1716,4 @@ export {
953
1716
  exampleTestSetup,
954
1717
  socketExample
955
1718
  };
956
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW8uanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pby1kYi1uYW1lLW1hcHBpbmcudHMiLCIuLi9zcmMvaW8tdG9vbHMudHMiLCIuLi9zcmMvaW8tbWVtLnRzIiwiLi4vc3JjL2lvLXRlc3Qtc2V0dXAudHMiLCIuLi9zcmMvaW8udHMiLCIuLi9zcmMvcGVlci1zb2NrZXQtbW9jay50cyIsIi4uL3NyYy9yZXZlcnNlLXJlZi50cyIsIi4uL3NyYy9zb2NrZXQtbW9jay50cyIsIi4uL3NyYy9zb2NrZXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbmV4cG9ydCBjbGFzcyBJb0RiTmFtZU1hcHBpbmcge1xuICAvLyBUaGUgcHJpbWFyeSBrZXkgY29sdW1uIGlzIGFsd2F5cyBuYW1lZCAnX2hhc2gnXG4gIHB1YmxpYyBwcmltYXJ5S2V5Q29sdW1uOiBzdHJpbmcgPSAnX2hhc2gnO1xuICBwdWJsaWMgZGF0YVNlY3Rpb246IHN0cmluZyA9ICdfZGF0YSc7XG4gIHB1YmxpYyB0eXBlQ29sdW1uOiBzdHJpbmcgPSAndHlwZSc7XG4gIHB1YmxpYyBrZXlDb2x1bW46IHN0cmluZyA9ICdrZXknO1xuXG4gIC8vIE5hbWVzIGZvciB0aGUgbWFpbiB0YWJsZXMgaW4gdGhlIGRhdGFiYXNlXG4gIHB1YmxpYyB0YWJsZU5hbWVzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgIG1haW46ICd0YWJsZUNmZ3MnLFxuICAgIHJldmlzaW9uOiAncmV2aXNpb25zJyxcbiAgfTtcblxuICAvLy8gU3VmZml4IGhhbmRsaW5nIGZvciB0aGUgZGF0YWJhc2VcbiAgcHJpdmF0ZSBfc3VmZml4OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgIGNvbDogJ19jb2wnLFxuICAgIHRibDogJ190YmwnLFxuICAgIHRtcDogJ190bXAnLFxuICB9O1xuXG4gIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gIC8vIGFkZCBhbmQgcmVtb3ZlIHN1ZmZpeGVzIGZvciB1c2UgaW4gU1FMIHN0YXRlbWVudHNcbiAgcHJpdmF0ZSBfYWRkRml4KG5hbWU6IHN0cmluZywgZml4OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuYW1lLmVuZHNXaXRoKGZpeCkgPyBuYW1lIDogbmFtZSArIGZpeDtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUYWJsZVN1ZmZpeChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9hZGRGaXgobmFtZSwgdGhpcy5fc3VmZml4LnRibCk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29sdW1uU3VmZml4KG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZEZpeChuYW1lLCB0aGlzLl9zdWZmaXguY29sKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUbXBTdWZmaXgobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fYWRkRml4KG5hbWUsIHRoaXMuX3N1ZmZpeC50bXApO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVtb3ZlRml4KG5hbWU6IHN0cmluZywgZml4OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuYW1lLmVuZHNXaXRoKGZpeCkgPyBuYW1lLnNsaWNlKDAsIC1maXgubGVuZ3RoKSA6IG5hbWU7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlVGFibGVTdWZmaXgobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fcmVtb3ZlRml4KG5hbWUsIHRoaXMuX3N1ZmZpeC50YmwpO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUNvbHVtblN1ZmZpeChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9yZW1vdmVGaXgobmFtZSwgdGhpcy5fc3VmZml4LmNvbCk7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlVG1wU3VmZml4KG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3JlbW92ZUZpeChuYW1lLCB0aGlzLl9zdWZmaXgudG1wKTtcbiAgfVxufVxuIiwiLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbmltcG9ydCB7IGhpcCB9IGZyb20gJ0BybGpzb24vaGFzaCc7XG5pbXBvcnQge1xuICBpdGVyYXRlVGFibGVzLFxuICBSbGpzb24sXG4gIFRhYmxlQ2ZnLFxuICBUYWJsZUtleSxcbiAgVGFibGVUeXBlLFxuICB0aHJvd09uSW52YWxpZFRhYmxlQ2ZnLFxuICB2YWxpZGF0ZVJsanNvbkFnYWluc3RUYWJsZUNmZyxcbn0gZnJvbSAnQHJsanNvbi9ybGpzb24nO1xuXG5pbXBvcnQgeyBJb01lbSB9IGZyb20gJy4vaW8tbWVtLnRzJztcbmltcG9ydCB7IElvIH0gZnJvbSAnLi9pby50cyc7XG5cbmV4cG9ydCB0eXBlIElvT2JzZXJ2ZXIgPSAoZGF0YTogUmxqc29uKSA9PiB2b2lkO1xuXG4vKipcbiAqIFByb3ZpZGVzIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgSW8gaW50ZXJmYWNlLlxuICovXG5leHBvcnQgY2xhc3MgSW9Ub29scyB7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0gaW8gVGhlIElvIGludGVyZmFjZSB0byB1c2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBpbzogSW8pIHt9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHRhYmxlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHRhYmxlQ2ZncyB0YWJsZS5cbiAgICovXG4gIHN0YXRpYyBnZXQgdGFibGVDZmdzVGFibGVDZmcoKSB7XG4gICAgY29uc3QgdGFibGVDZmcgPSBoaXA8VGFibGVDZmc+KHtcbiAgICAgIF9oYXNoOiAnJyxcbiAgICAgIGtleTogJ3RhYmxlQ2ZncycsXG4gICAgICB0eXBlOiAndGFibGVDZmdzJyxcbiAgICAgIGlzSGVhZDogZmFsc2UsXG4gICAgICBpc1Jvb3Q6IGZhbHNlLFxuICAgICAgaXNTaGFyZWQ6IHRydWUsXG4gICAgICBwcmV2aW91czogJycsXG5cbiAgICAgIGNvbHVtbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGtleTogJ19oYXNoJyxcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnSGFzaCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnUm93IEhhc2gnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAna2V5JyxcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnS2V5JyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdUYWJsZSBLZXknLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAndHlwZScsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1R5cGUnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ0NvbnRlbnQgVHlwZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdpc0hlYWQnLFxuICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnSXMgSGVhZCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnSXMgSGVhZCBUYWJsZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdpc1Jvb3QnLFxuICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnSXMgUm9vdCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnSXMgUm9vdCBUYWJsZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdpc1NoYXJlZCcsXG4gICAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgIHRpdGxlU2hvcnQ6ICdJcyBTaGFyZWQnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ0lzIFNoYXJlZCBUYWJsZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdwcmV2aW91cycsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1ByZXZpb3VzJyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdQcmV2aW91cyBUYWJsZSBDb25maWd1cmF0aW9uIEhhc2gnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAnY29sdW1ucycsXG4gICAgICAgICAgdHlwZTogJ2pzb25BcnJheScsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ0NvbHVtbnMnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ0NvbHVtbiBDb25maWd1cmF0aW9ucycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRhYmxlQ2ZnO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSByZXZpc2lvbnMgdGFibGUuXG4gICAqL1xuICBpbml0UmV2aXNpb25zVGFibGUgPSBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdGFibGVDZmc6IFRhYmxlQ2ZnID0ge1xuICAgICAga2V5OiAncmV2aXNpb25zJyxcbiAgICAgIHR5cGU6ICdyZXZpc2lvbnMnLFxuICAgICAgaXNIZWFkOiB0cnVlLFxuICAgICAgaXNSb290OiB0cnVlLFxuICAgICAgaXNTaGFyZWQ6IGZhbHNlLFxuXG4gICAgICBjb2x1bW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdfaGFzaCcsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ0hhc2gnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ1JvdyBIYXNoJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGtleTogJ3RhYmxlJyxcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnVGFibGUnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ1RhYmxlIEtleScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdwcmVkZWNlc3NvcicsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1ByZWRlY2Vzc29yJyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdQcmVkZWNlc3NvciBSZXZpc2lvbiBIYXNoJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGtleTogJ3N1Y2Nlc3NvcicsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1N1Y2Nlc3NvcicsXG4gICAgICAgICAgdGl0bGVMb25nOiAnU3VjY2Vzc29yIFJldmlzaW9uIEhhc2gnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAndGltZXN0YW1wJyxcbiAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnVGltZXN0YW1wJyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdSZXZpc2lvbiBUaW1lc3RhbXAnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAnaWQnLFxuICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgIHRpdGxlU2hvcnQ6ICdJRCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnUmV2aXNpb24gSUQnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuXG4gICAgYXdhaXQgdGhpcy5pby5jcmVhdGVPckV4dGVuZFRhYmxlKHsgdGFibGVDZmcgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEV4YW1wbGUgb2JqZWN0IGZvciB0ZXN0IHB1cnBvc2VzXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIGlvIHRvb2xzXG4gICAqL1xuICBzdGF0aWMgZXhhbXBsZSA9IGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbyA9IGF3YWl0IElvTWVtLmV4YW1wbGUoKTtcbiAgICBhd2FpdCBpby5pbml0KCk7XG4gICAgYXdhaXQgaW8uaXNSZWFkeSgpO1xuICAgIHJldHVybiBuZXcgSW9Ub29scyhpbyk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFRocm93cyBpZiB0aGUgdGFibGUgZG9lcyBub3QgZXhpc3RcbiAgICovXG4gIGFzeW5jIHRocm93V2hlblRhYmxlRG9lc05vdEV4aXN0KHRhYmxlOiBUYWJsZUtleSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0cyA9IGF3YWl0IHRoaXMuaW8udGFibGVFeGlzdHModGFibGUpO1xuICAgIGlmICghZXhpc3RzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlIFwiJHt0YWJsZX1cIiBub3QgZm91bmRgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhyb3dzIGlmIGFueSBvZiB0aGUgdGFibGVzIGluIHJsanNvbiBkbyBub3QgZXhpc3RcbiAgICogQHBhcmFtIHJsanNvbiAtIFRoZSBSbGpzb24gb2JqZWN0IHRvIGNoZWNrXG4gICAqL1xuICBhc3luYyB0aHJvd1doZW5UYWJsZXNEb05vdEV4aXN0KHJsanNvbjogUmxqc29uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGl0ZXJhdGVUYWJsZXMocmxqc29uLCBhc3luYyAodGFibGVLZXkpID0+IHtcbiAgICAgICAgY29uc3QgZXhpc3RzID0gYXdhaXQgdGhpcy5pby50YWJsZUV4aXN0cyh0YWJsZUtleSk7XG4gICAgICAgIGlmICghZXhpc3RzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYWJsZSBcIiR7dGFibGVLZXl9XCIgbm90IGZvdW5kYCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnN0IG1pc3NpbmdUYWJsZXMgPSAoZSBhcyBBcnJheTxhbnk+KS5tYXAoKGUpID0+IGUudGFibGVLZXkpO1xuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUaGUgZm9sbG93aW5nIHRhYmxlcyBkbyBub3QgZXhpc3Q6ICR7bWlzc2luZ1RhYmxlcy5qb2luKCcsICcpfWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHRhYmxlIGNmZ3Mgb2YgYWxsIHRhYmxlc1xuICAgKiBAcmV0dXJucyBUaGUgdGFibGUgY29uZmlndXJhdGlvbiBvZiBhbGwgdGFibGVzXG4gICAqL1xuICBhc3luYyB0YWJsZUNmZ3MoKTogUHJvbWlzZTxUYWJsZUNmZ1tdPiB7XG4gICAgY29uc3QgdGFibGVzID0gYXdhaXQgdGhpcy5pby5yYXdUYWJsZUNmZ3MoKTtcblxuICAgIC8vIFRha2UgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIGVhY2ggdHlwZSBrZXlcbiAgICBjb25zdCBuZXdlc3RWZXJzaW9uOiBSZWNvcmQ8VGFibGVLZXksIFRhYmxlQ2ZnPiA9IHt9O1xuICAgIGZvciAobGV0IGkgPSB0YWJsZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGNvbnN0IHRhYmxlID0gdGFibGVzW2ldO1xuICAgICAgY29uc3QgZXhpc3RpbmcgPSBuZXdlc3RWZXJzaW9uW3RhYmxlLmtleV07XG4gICAgICBpZiAoIWV4aXN0aW5nIHx8IGV4aXN0aW5nLmNvbHVtbnMubGVuZ3RoIDwgdGFibGUuY29sdW1ucy5sZW5ndGgpIHtcbiAgICAgICAgbmV3ZXN0VmVyc2lvblt0YWJsZS5rZXldID0gdGFibGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU29ydCB0aGUgdGFibGVzIGJ5IGtleVxuICAgIC8qIHY4IGlnbm9yZSBuZXh0IC0tIEBwcmVzZXJ2ZSAqL1xuICAgIGNvbnN0IHJlc3VsdERhdGEgPSBPYmplY3QudmFsdWVzKG5ld2VzdFZlcnNpb24pLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGlmIChhLmtleSA8IGIua2V5KSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGlmIChhLmtleSA+IGIua2V5KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0RGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbGlzdCB3aXRoIGFsbCB0YWJsZSBuYW1lc1xuICAgKi9cbiAgYXN5bmMgYWxsVGFibGVLZXlzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCByZXN1bHQgPSAoYXdhaXQgdGhpcy50YWJsZUNmZ3MoKSkubWFwKChlKSA9PiBlLmtleSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjb25maWd1cmF0aW9uIG9mIGEgZ2l2ZW4gdGFibGVcbiAgICovXG4gIGFzeW5jIHRhYmxlQ2ZnKHRhYmxlOiBUYWJsZUtleSk6IFByb21pc2U8VGFibGVDZmc+IHtcbiAgICBjb25zdCB0YWJsZUNmZyA9IGF3YWl0IHRoaXMudGFibGVDZmdPck51bGwodGFibGUpO1xuICAgIGlmICghdGFibGVDZmcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgXCIke3RhYmxlfVwiIG5vdCBmb3VuZGApO1xuICAgIH1cblxuICAgIHJldHVybiB0YWJsZUNmZyE7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29uZmlndXJhdGlvbiBvZiBhIGdpdmVuIHRhYmxlIG9yIG51bGwgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cbiAgICovXG4gIGFzeW5jIHRhYmxlQ2ZnT3JOdWxsKHRhYmxlOiBUYWJsZUtleSk6IFByb21pc2U8VGFibGVDZmcgfCBudWxsPiB7XG4gICAgY29uc3QgdGFibGVDZmdzID0gYXdhaXQgdGhpcy50YWJsZUNmZ3MoKTtcbiAgICBjb25zdCB0YWJsZUNmZyA9IHRhYmxlQ2Zncy5maW5kKChlKSA9PiBlLmtleSA9PT0gdGFibGUpO1xuICAgIHJldHVybiB0YWJsZUNmZyA/PyBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBsaXN0IG9mIGFsbCBjb2x1bW4gbmFtZXMgb2YgYSBnaXZlbiB0YWJsZVxuICAgKi9cbiAgYXN5bmMgYWxsQ29sdW1uS2V5cyh0YWJsZTogVGFibGVLZXkpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgdGFibGVDZmcgPSBhd2FpdCB0aGlzLnRhYmxlQ2ZnKHRhYmxlKTtcbiAgICBjb25zdCByZXN1bHQgPSB0YWJsZUNmZy5jb2x1bW5zLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4ua2V5KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRocm93cyB3aGVuIGEgY29sdW1uIGRvZXMgbm90IGV4aXN0IGluIGEgZ2l2ZW4gdGFibGVcbiAgICogQHBhcmFtIHRhYmxlIC0gVGhlIHRhYmxlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBjb2x1bW5zIC0gVGhlIGNvbHVtbiB0byBjaGVja1xuICAgKi9cbiAgYXN5bmMgdGhyb3dXaGVuQ29sdW1uRG9lc05vdEV4aXN0KFxuICAgIHRhYmxlOiBUYWJsZUtleSxcbiAgICBjb2x1bW5zOiBzdHJpbmdbXSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdGFibGVDZmcgPSBhd2FpdCB0aGlzLnRhYmxlQ2ZnKHRhYmxlKTtcbiAgICBjb25zdCBjb2x1bW5LZXlzID0gdGFibGVDZmcuY29sdW1ucy5tYXAoKGNvbHVtbikgPT4gY29sdW1uLmtleSk7XG4gICAgY29uc3QgbWlzc2luZ0NvbHVtbnMgPSBjb2x1bW5zLmZpbHRlcihcbiAgICAgIChjb2x1bW4pID0+ICFjb2x1bW5LZXlzLmluY2x1ZGVzKGNvbHVtbiksXG4gICAgKTtcbiAgICBpZiAobWlzc2luZ0NvbHVtbnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIGZvbGxvd2luZyBjb2x1bW5zIGRvIG5vdCBleGlzdCBpbiB0YWJsZSBcIiR7dGFibGV9XCI6ICR7bWlzc2luZ0NvbHVtbnMuam9pbihcbiAgICAgICAgICAnLCAnLFxuICAgICAgICApfS5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhyb3dzIHdoZW4gYSB0YWJsZSB1cGRhdGUgaXMgbm90IGNvbXBhdGlibGUgd2l0aCB0aGUgY3VycmVudCB0YWJsZVxuICAgKiBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgYXN5bmMgdGhyb3dXaGVuVGFibGVJc05vdENvbXBhdGlibGUodXBkYXRlOiBUYWJsZUNmZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHByZWZpeCA9IGBJbnZhbGlkIHVwZGF0ZSBvZiB0YWJsZSBhYmxlIFwiJHt1cGRhdGUua2V5fVwiYDtcblxuICAgIHRocm93T25JbnZhbGlkVGFibGVDZmcodXBkYXRlKTtcblxuICAgIC8vIENoZWNrIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyB0YWJsZVxuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy50YWJsZUNmZ09yTnVsbCh1cGRhdGUua2V5KTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIC8vIEhhdmUgY29sdW1ucyBiZWVuIGRlbGV0ZWQ/XG4gICAgICBpZiAoZXhpc3RpbmcuY29sdW1ucy5sZW5ndGggPiB1cGRhdGUuY29sdW1ucy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgZGVsZXRlZENvbHVtbktleXMgPSBleGlzdGluZy5jb2x1bW5zXG4gICAgICAgICAgLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4ua2V5KVxuICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAoa2V5KSA9PiAhdXBkYXRlLmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiBjb2x1bW4ua2V5ID09PSBrZXkpLFxuICAgICAgICAgICk7XG4gICAgICAgIC8qIHY4IGlnbm9yZSBuZXh0IC0tIEBwcmVzZXJ2ZSAqL1xuICAgICAgICBpZiAoZGVsZXRlZENvbHVtbktleXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IGRlbGV0ZWRDb2x1bW5zID0gZGVsZXRlZENvbHVtbktleXMuam9pbignLCAnKTtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgJHtwcmVmaXh9OiBDb2x1bW5zIG11c3Qgbm90IGJlIGRlbGV0ZWQuIGAgK1xuICAgICAgICAgICAgICBgRGVsZXRlZCBjb2x1bW5zOiAke2RlbGV0ZWRDb2x1bW5zfX1gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSGF2ZSBjb2x1bW4ga2V5cyBjaGFuZ2VkP1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBleGlzdGluZy5jb2x1bW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGJlZm9yZSA9IGV4aXN0aW5nLmNvbHVtbnNbaV0ua2V5O1xuICAgICAgICBjb25zdCBhZnRlciA9IHVwZGF0ZS5jb2x1bW5zW2ldLmtleTtcbiAgICAgICAgaWYgKGJlZm9yZSAhPT0gYWZ0ZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgJHtwcmVmaXh9OiBgICtcbiAgICAgICAgICAgICAgYENvbHVtbiBrZXlzIG11c3Qgbm90IGNoYW5nZSEgYCArXG4gICAgICAgICAgICAgIGBDb2x1bW4gXCIke2JlZm9yZX1cIiB3YXMgcmVuYW1lZCBpbnRvIFwiJHthZnRlcn1cIi5gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSGF2ZSBjb2x1bW4gdHlwZXMgY2hhbmdlZD9cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXhpc3RpbmcuY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBleGlzdGluZy5jb2x1bW5zW2ldLmtleTtcbiAgICAgICAgY29uc3QgYmVmb3JlID0gZXhpc3RpbmcuY29sdW1uc1tpXS50eXBlO1xuICAgICAgICBjb25zdCBhZnRlciA9IHVwZGF0ZS5jb2x1bW5zW2ldLnR5cGU7XG4gICAgICAgIGlmIChiZWZvcmUgIT09IGFmdGVyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYCR7cHJlZml4fTogYCArXG4gICAgICAgICAgICAgIGBDb2x1bW4gdHlwZXMgbXVzdCBub3QgY2hhbmdlISBgICtcbiAgICAgICAgICAgICAgYFR5cGUgb2YgY29sdW1uIFwiJHtjb2x1bW59XCIgd2FzIGNoYW5nZWQgZnJvbSBcIiR7YmVmb3JlfVwiIHRvICR7YWZ0ZXJ9LmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaHJvd3MgaWYgdGhlIGRhdGEgaW4gdGhlIHRhYmxlIGRvIG5vdCBtYXRjaCB0aGUgdGFibGUgY29uZmlndXJhdGlvblxuICAgKi9cbiAgYXN5bmMgdGhyb3dXaGVuVGFibGVEYXRhRG9lc05vdE1hdGNoQ2ZnKGRhdGE6IFJsanNvbikge1xuICAgIGNvbnN0IGVycm9yczogc3RyaW5nW10gPSBbXTtcblxuICAgIGF3YWl0IGl0ZXJhdGVUYWJsZXMoZGF0YSwgYXN5bmMgKHRhYmxlS2V5KSA9PiB7XG4gICAgICBjb25zdCB0YWJsZUNmZyA9IGF3YWl0IHRoaXMudGFibGVDZmcodGFibGVLZXkpO1xuICAgICAgY29uc3QgdGFibGUgPSBkYXRhW3RhYmxlS2V5XTtcblxuICAgICAgLy8gSWdub3JlIHRhYmxlQ2ZncyB0YWJsZVxuICAgICAgLyogdjggaWdub3JlIG5leHQgLS0gQHByZXNlcnZlICovXG4gICAgICBpZiAodGFibGUuX3R5cGUgPT09ICd0YWJsZUNmZ3MnKSByZXR1cm47XG5cbiAgICAgIGVycm9ycy5wdXNoKC4uLnZhbGlkYXRlUmxqc29uQWdhaW5zdFRhYmxlQ2ZnKHRhYmxlLl9kYXRhLCB0YWJsZUNmZykpO1xuICAgIH0pO1xuXG4gICAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUYWJsZSBkYXRhIGRvZXMgbm90IG1hdGNoIHRoZSBjb25maWd1cmF0aW9uLlxcblxcbkVycm9yczpcXG4ke2Vycm9yc1xuICAgICAgICAgIC5tYXAoKGUpID0+IGAtICR7ZX1gKVxuICAgICAgICAgIC5qb2luKCdcXG4nKX1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgdGhlIGRhdGEgb2YgYSB0YWJsZSBieSB0aGUgaGFzaCBhbmQgdXBkYXRlcyB0aGUgdGFibGUgaGFzaCBpbiBwbGFjZVxuICAgKi9cbiAgc29ydFRhYmxlRGF0YUFuZFVwZGF0ZUhhc2godGFibGU6IFRhYmxlVHlwZSk6IHZvaWQge1xuICAgIHRhYmxlLl9kYXRhLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGNvbnN0IGhhc2hBID0gYS5faGFzaCBhcyBzdHJpbmc7XG4gICAgICBjb25zdCBoYXNoQiA9IGIuX2hhc2ggYXMgc3RyaW5nO1xuICAgICAgLyogdjggaWdub3JlIG5leHQgLS0gQHByZXNlcnZlICovXG4gICAgICBpZiAoaGFzaEEgPCBoYXNoQikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICAvKiB2OCBpZ25vcmUgbmV4dCAtLSBAcHJlc2VydmUgKi9cbiAgICAgIGlmIChoYXNoQSA+IGhhc2hCKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICAvKiB2OCBpZ25vcmUgbmV4dCAtLSBAcHJlc2VydmUgKi9cbiAgICAgIHJldHVybiAwO1xuICAgIH0pO1xuXG4gICAgdGFibGUuX2hhc2ggPSAnJztcbiAgICBoaXAodGFibGUsIHtcbiAgICAgIHVwZGF0ZUV4aXN0aW5nSGFzaGVzOiBmYWxzZSxcbiAgICAgIHRocm93T25Xcm9uZ0hhc2hlczogZmFsc2UsXG4gICAgfSk7XG4gIH1cbn1cbiIsIi8vIEBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMjUgUmxqc29uXG4vL1xuLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgdGVybXMgdGhhdCBjYW4gYmVcbi8vIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhpcyBwYWNrYWdlLlxuXG5pbXBvcnQgeyBoaXAsIGhzaCB9IGZyb20gJ0BybGpzb24vaGFzaCc7XG5pbXBvcnQgeyBJc1JlYWR5IH0gZnJvbSAnQHJsanNvbi9pcy1yZWFkeSc7XG5pbXBvcnQgeyBjb3B5LCBlcXVhbHMsIEpzb25WYWx1ZSB9IGZyb20gJ0BybGpzb24vanNvbic7XG5pbXBvcnQge1xuICBDb250ZW50VHlwZSxcbiAgaXRlcmF0ZVRhYmxlc1N5bmMsXG4gIFJsanNvbixcbiAgVGFibGVDZmcsXG4gIFRhYmxlS2V5LFxuICBUYWJsZVR5cGUsXG59IGZyb20gJ0BybGpzb24vcmxqc29uJztcblxuaW1wb3J0IHsgSW9Ub29scyB9IGZyb20gJy4vaW8tdG9vbHMudHMnO1xuaW1wb3J0IHsgSW8gfSBmcm9tICcuL2lvLnRzJztcblxuLyoqXG4gKiBJbi1NZW1vcnkgaW1wbGVtZW50YXRpb24gb2YgdGhlIFJsanNvbiBJbyBpbnRlcmZhY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBJb01lbSBpbXBsZW1lbnRzIElvIHtcbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIENvbnN0cnVjdG9yICYgZXhhbXBsZVxuXG4gIGluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5faXNPcGVuID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5faW5pdCgpO1xuICB9XG5cbiAgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5faXNPcGVuID0gZmFsc2U7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgZ2V0IGlzT3BlbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faXNPcGVuO1xuICB9XG5cbiAgc3RhdGljIGV4YW1wbGUgPSBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgaW8gPSBuZXcgSW9NZW0oKTtcbiAgICBhd2FpdCBpby5pbml0KCk7XG4gICAgcmV0dXJuIGlvO1xuICB9O1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBHZW5lcmFsXG4gIGlzUmVhZHkoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lzUmVhZHkucHJvbWlzZTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBEdW1wXG5cbiAgZHVtcCgpOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIHJldHVybiB0aGlzLl9kdW1wKCk7XG4gIH1cblxuICBhc3luYyBkdW1wVGFibGUocmVxdWVzdDogeyB0YWJsZTogc3RyaW5nIH0pOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIHJldHVybiB0aGlzLl9kdW1wVGFibGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gTWV0YSBEYXRhXG5cbiAgYXN5bmMgY29udGVudFR5cGUocmVxdWVzdDogeyB0YWJsZTogc3RyaW5nIH0pOiBQcm9taXNlPENvbnRlbnRUeXBlPiB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbnRlbnRUeXBlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIFJvd3NcblxuICByZWFkUm93cyhyZXF1ZXN0OiB7XG4gICAgdGFibGU6IHN0cmluZztcbiAgICB3aGVyZTogeyBbY29sdW1uOiBzdHJpbmddOiBKc29uVmFsdWUgfTtcbiAgfSk6IFByb21pc2U8Umxqc29uPiB7XG4gICAgcmV0dXJuIHRoaXMuX3JlYWRSb3dzKHJlcXVlc3QpO1xuICB9XG5cbiAgYXN5bmMgcm93Q291bnQodGFibGU6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgdGFibGVEYXRhID0gdGhpcy5fbWVtW3RhYmxlXSBhcyBUYWJsZVR5cGU7XG4gICAgaWYgKCF0YWJsZURhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgXCIke3RhYmxlfVwiIG5vdCBmb3VuZGApO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRhYmxlRGF0YS5fZGF0YS5sZW5ndGgpO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIFdyaXRlXG5cbiAgd3JpdGUocmVxdWVzdDogeyBkYXRhOiBSbGpzb24gfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl93cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBUYWJsZSBtYW5hZ2VtZW50XG4gIGFzeW5jIHRhYmxlRXhpc3RzKHRhYmxlS2V5OiBUYWJsZUtleSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy5fbWVtW3RhYmxlS2V5XSBhcyBUYWJsZVR5cGU7XG4gICAgcmV0dXJuIHRhYmxlID8gdHJ1ZSA6IGZhbHNlO1xuICB9XG5cbiAgY3JlYXRlT3JFeHRlbmRUYWJsZShyZXF1ZXN0OiB7IHRhYmxlQ2ZnOiBUYWJsZUNmZyB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX2NyZWF0ZU9yRXh0ZW5kVGFibGUocmVxdWVzdCk7XG4gIH1cblxuICBhc3luYyByYXdUYWJsZUNmZ3MoKTogUHJvbWlzZTxUYWJsZUNmZ1tdPiB7XG4gICAgY29uc3QgdGFibGVzID0gdGhpcy5fbWVtLnRhYmxlQ2Zncy5fZGF0YSBhcyBUYWJsZUNmZ1tdO1xuICAgIHJldHVybiB0YWJsZXM7XG4gIH1cblxuICAvLyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXG4gIC8vIFByaXZhdGVcbiAgLy8gIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xuXG4gIHByaXZhdGUgX2lvVG9vbHMhOiBJb1Rvb2xzO1xuXG4gIHByaXZhdGUgX2lzUmVhZHkgPSBuZXcgSXNSZWFkeSgpO1xuICBwcml2YXRlIF9pc09wZW4gPSBmYWxzZTtcblxuICBwcml2YXRlIF9tZW06IFJsanNvbiA9IGhpcCh7fSBhcyBSbGpzb24pO1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIGFzeW5jIF9pbml0KCkge1xuICAgIHRoaXMuX2lvVG9vbHMgPSBuZXcgSW9Ub29scyh0aGlzKTtcbiAgICB0aGlzLl9pbml0VGFibGVDZmdzKCk7XG4gICAgdGhpcy5fdXBkYXRlR2xvYmFsSGFzaCgpO1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMuaW5pdFJldmlzaW9uc1RhYmxlKCk7XG4gICAgaHNoKHRoaXMuX21lbSk7XG5cbiAgICB0aGlzLl9pc1JlYWR5LnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIF9pbml0VGFibGVDZmdzID0gKCkgPT4ge1xuICAgIGNvbnN0IHRhYmxlQ2ZnID0gSW9Ub29scy50YWJsZUNmZ3NUYWJsZUNmZztcblxuICAgIHRoaXMuX21lbS50YWJsZUNmZ3MgPSBoaXAoe1xuICAgICAgX3R5cGU6ICd0YWJsZUNmZ3MnLFxuICAgICAgX2RhdGE6IFt0YWJsZUNmZ10sXG4gICAgICBfdGFibGVDZmc6IHRhYmxlQ2ZnLl9oYXNoIGFzIHN0cmluZyxcbiAgICB9KTtcbiAgfTtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBfdXBkYXRlR2xvYmFsSGFzaCgpIHtcbiAgICAodGhpcy5fbWVtIGFzIGFueSkuX2hhc2ggPSAnJztcbiAgICBoaXAodGhpcy5fbWVtLCB7XG4gICAgICB1cGRhdGVFeGlzdGluZ0hhc2hlczogZmFsc2UsXG4gICAgfSk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBfdXBkYXRlVGFibGVIYXNoKHRhYmxlS2V5OiBUYWJsZUtleSkge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy5fbWVtW3RhYmxlS2V5XSBhcyBUYWJsZVR5cGU7XG4gICAgdGFibGUuX2hhc2ggPSAnJztcbiAgICBoaXAodGFibGUsIHsgdXBkYXRlRXhpc3RpbmdIYXNoZXM6IGZhbHNlIH0pO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIHByaXZhdGUgYXN5bmMgX2NyZWF0ZU9yRXh0ZW5kVGFibGUocmVxdWVzdDoge1xuICAgIHRhYmxlQ2ZnOiBUYWJsZUNmZztcbiAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSB0YWJsZSBjb25maWcgaXMgY29tcGF0aWJsZVxuICAgIC8vIHdpdGggYW4gcG90ZW50aWFsIGV4aXN0aW5nIHRhYmxlXG4gICAgY29uc3QgdGFibGVDZmcgPSByZXF1ZXN0LnRhYmxlQ2ZnO1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVJc05vdENvbXBhdGlibGUodGFibGVDZmcpO1xuXG4gICAgY29uc3QgeyBrZXkgfSA9IHRhYmxlQ2ZnO1xuXG4gICAgLy8gUmVjcmVhdGUgaGFzaGVzIGluIHRoZSBjYXNlIHRoZSBleGlzdGluZyBoYXNoZXMgYXJlIHdyb25nXG4gICAgY29uc3QgbmV3Q29uZmlnID0gaHNoKHRhYmxlQ2ZnKTtcblxuICAgIC8vIEZpbmQgYW4gZXhpc3RpbmcgdGFibGUgY29uZmlnIHdpdGggdGhlIHNhbWUgaGFzaFxuICAgIGNvbnN0IGV4aXN0aW5nQ29uZmlnID0gYXdhaXQgdGhpcy5faW9Ub29scy50YWJsZUNmZ09yTnVsbChrZXkpO1xuXG4gICAgLy8gV3JpdGUgdGhlIG5ldyBjb25maWcgaW50byB0aGUgZGF0YWJhc2VcbiAgICBpZiAoIWV4aXN0aW5nQ29uZmlnKSB7XG4gICAgICB0aGlzLl9jcmVhdGVUYWJsZShuZXdDb25maWcsIGtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2V4dGVuZFRhYmxlKGV4aXN0aW5nQ29uZmlnLCBuZXdDb25maWcpO1xuICAgIH1cbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIF9jcmVhdGVUYWJsZShuZXdDb25maWc6IFRhYmxlQ2ZnLCB0YWJsZUtleTogVGFibGVLZXkpIHtcbiAgICAvLyBXcml0ZSB0aGUgdGFibGUgY29uZmlnIGludG8gdGhlIGRhdGFiYXNlXG4gICAgbmV3Q29uZmlnID0gaHNoKG5ld0NvbmZpZyk7XG4gICAgdGhpcy5fbWVtLnRhYmxlQ2Zncy5fZGF0YS5wdXNoKG5ld0NvbmZpZyk7XG4gICAgdGhpcy5faW9Ub29scy5zb3J0VGFibGVEYXRhQW5kVXBkYXRlSGFzaCh0aGlzLl9tZW0udGFibGVDZmdzKTtcblxuICAgIC8vIENyZWF0ZSBhIHRhYmxlIGFuZCB3cml0ZSBpdCBpbnRvIHRoZSBkYXRhYmFzZVxuICAgIGNvbnN0IHRhYmxlOiBUYWJsZVR5cGUgPSB7XG4gICAgICBfdHlwZTogbmV3Q29uZmlnLnR5cGUsXG4gICAgICBfZGF0YTogW10sXG4gICAgICBfdGFibGVDZmc6IG5ld0NvbmZpZy5faGFzaCBhcyBzdHJpbmcsXG4gICAgfTtcblxuICAgIHRoaXMuX21lbVt0YWJsZUtleV0gPz89IGhpcCh0YWJsZSk7XG5cbiAgICAvLyBVcGRhdGUgaGFzaGVzXG4gICAgdGhpcy5fdXBkYXRlVGFibGVIYXNoKHRhYmxlS2V5KTtcbiAgICB0aGlzLl91cGRhdGVHbG9iYWxIYXNoKCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBfZXh0ZW5kVGFibGUoZXhpc3RpbmdDb25maWc6IFRhYmxlQ2ZnLCBuZXdDb25maWc6IFRhYmxlQ2ZnKSB7XG4gICAgLy8gTm8gY29sdW1ucyBhZGRlZD8gUmV0dXJuLlxuICAgIGlmIChleGlzdGluZ0NvbmZpZy5jb2x1bW5zLmxlbmd0aCA9PT0gbmV3Q29uZmlnLmNvbHVtbnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gV3JpdGUgdGhlIG5ldyB0YWJsZSBjb25maWcgaW50byB0aGUgZGF0YWJhc2VcbiAgICBuZXdDb25maWcgPSBoc2gobmV3Q29uZmlnKTtcbiAgICB0aGlzLl9tZW0udGFibGVDZmdzLl9kYXRhLnB1c2gobmV3Q29uZmlnKTtcbiAgICB0aGlzLl9pb1Rvb2xzLnNvcnRUYWJsZURhdGFBbmRVcGRhdGVIYXNoKHRoaXMuX21lbS50YWJsZUNmZ3MpO1xuXG4gICAgLy8gVXBkYXRlIHRoZSBjb25maWcgb2YgdGhlIGV4aXN0aW5nIHRhYmxlXG4gICAgY29uc3QgdGFibGUgPSB0aGlzLl9tZW1bbmV3Q29uZmlnLmtleV0gYXMgVGFibGVUeXBlO1xuICAgIHRhYmxlLl90YWJsZUNmZyA9IG5ld0NvbmZpZy5faGFzaCBhcyBzdHJpbmc7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGhhc2hlc1xuICAgIHRoaXMuX3VwZGF0ZVRhYmxlSGFzaChuZXdDb25maWcua2V5KTtcbiAgICB0aGlzLl91cGRhdGVHbG9iYWxIYXNoKCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cblxuICBwcml2YXRlIGFzeW5jIF9kdW1wKCk6IFByb21pc2U8Umxqc29uPiB7XG4gICAgcmV0dXJuIGNvcHkodGhpcy5fbWVtKTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIGFzeW5jIF9kdW1wVGFibGUocmVxdWVzdDogeyB0YWJsZTogc3RyaW5nIH0pOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEb2VzTm90RXhpc3QocmVxdWVzdC50YWJsZSk7XG5cbiAgICBjb25zdCB0YWJsZSA9IHRoaXMuX21lbVtyZXF1ZXN0LnRhYmxlXSBhcyBUYWJsZVR5cGU7XG5cbiAgICByZXR1cm4ge1xuICAgICAgW3JlcXVlc3QudGFibGVdOiBjb3B5KHRhYmxlKSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIHByaXZhdGUgYXN5bmMgX2NvbnRlbnRUeXBlKHJlcXVlc3Q6IHsgdGFibGU6IHN0cmluZyB9KTogUHJvbWlzZTxDb250ZW50VHlwZT4ge1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEb2VzTm90RXhpc3QocmVxdWVzdC50YWJsZSk7XG5cbiAgICByZXR1cm4gKHRoaXMuX21lbVtyZXF1ZXN0LnRhYmxlXSBhcyBUYWJsZVR5cGUpLl90eXBlO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIHByaXZhdGUgYXN5bmMgX3dyaXRlKHJlcXVlc3Q6IHsgZGF0YTogUmxqc29uIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhZGRlZERhdGEgPSBoc2gocmVxdWVzdC5kYXRhKTtcbiAgICB0aGlzLl9yZW1vdmVOdWxsVmFsdWVzKGFkZGVkRGF0YSk7XG4gICAgY29uc3QgdGFibGVzID0gT2JqZWN0LmtleXMoYWRkZWREYXRhKTtcbiAgICBoc2goYWRkZWREYXRhKTtcblxuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVzRG9Ob3RFeGlzdChyZXF1ZXN0LmRhdGEpO1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEYXRhRG9lc05vdE1hdGNoQ2ZnKHJlcXVlc3QuZGF0YSk7XG5cbiAgICBmb3IgKGNvbnN0IHRhYmxlIG9mIHRhYmxlcykge1xuICAgICAgaWYgKHRhYmxlLnN0YXJ0c1dpdGgoJ18nKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkVGFibGUgPSB0aGlzLl9tZW1bdGFibGVdIGFzIFRhYmxlVHlwZTtcbiAgICAgIGNvbnN0IG5ld1RhYmxlID0gYWRkZWREYXRhW3RhYmxlXSBhcyBUYWJsZVR5cGU7XG5cbiAgICAgIC8vIFRhYmxlIGV4aXN0cy4gTWVyZ2UgZGF0YVxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIG5ld1RhYmxlLl9kYXRhKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSBpdGVtLl9oYXNoO1xuICAgICAgICBjb25zdCBleGlzdHMgPSBvbGRUYWJsZS5fZGF0YS5maW5kKChpKSA9PiBpLl9oYXNoID09PSBoYXNoKTtcbiAgICAgICAgaWYgKCFleGlzdHMpIHtcbiAgICAgICAgICBvbGRUYWJsZS5fZGF0YS5wdXNoKGl0ZW0gYXMgYW55KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLl9pb1Rvb2xzLnNvcnRUYWJsZURhdGFBbmRVcGRhdGVIYXNoKG9sZFRhYmxlKTtcbiAgICB9XG5cbiAgICAvLyBSZWNhbGMgbWFpbiBoYXNoZXNcbiAgICB0aGlzLl91cGRhdGVHbG9iYWxIYXNoKCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBhc3luYyBfcmVhZFJvd3MocmVxdWVzdDoge1xuICAgIHRhYmxlOiBzdHJpbmc7XG4gICAgd2hlcmU6IHsgW2NvbHVtbjogc3RyaW5nXTogSnNvblZhbHVlIH07XG4gIH0pOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEb2VzTm90RXhpc3QocmVxdWVzdC50YWJsZSk7XG4gICAgYXdhaXQgdGhpcy5faW9Ub29scy50aHJvd1doZW5Db2x1bW5Eb2VzTm90RXhpc3QoXG4gICAgICByZXF1ZXN0LnRhYmxlLFxuICAgICAgT2JqZWN0LmtleXMocmVxdWVzdC53aGVyZSksXG4gICAgKTtcblxuICAgIC8vIFJlYWQgdGFibGUgZnJvbSBkYXRhXG4gICAgY29uc3QgdGFibGUgPSB0aGlzLl9tZW1bcmVxdWVzdC50YWJsZV0gYXMgVGFibGVUeXBlO1xuXG4gICAgLy8gRmlsdGVyIHRhYmxlIGRhdGFcbiAgICBjb25zdCB0YWJsZURhdGFGaWx0ZXJlZCA9IHRhYmxlLl9kYXRhLmZpbHRlcigocm93KSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGNvbHVtbiBpbiByZXF1ZXN0LndoZXJlKSB7XG4gICAgICAgIGNvbnN0IGEgPSByb3dbY29sdW1uXTtcbiAgICAgICAgY29uc3QgYiA9IHJlcXVlc3Qud2hlcmVbY29sdW1uXTtcbiAgICAgICAgaWYgKGIgPT09IG51bGwgJiYgYSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWVxdWFscyhhLCBiKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgYW4gdGFibGVcbiAgICBjb25zdCB0YWJsZUZpbHRlcmVkOiBUYWJsZVR5cGUgPSB7XG4gICAgICBfdHlwZTogdGFibGUuX3R5cGUsXG4gICAgICBfZGF0YTogdGFibGVEYXRhRmlsdGVyZWQsXG4gICAgfTtcblxuICAgIHRoaXMuX2lvVG9vbHMuc29ydFRhYmxlRGF0YUFuZFVwZGF0ZUhhc2godGFibGVGaWx0ZXJlZCk7XG5cbiAgICBjb25zdCByZXN1bHQ6IFJsanNvbiA9IHtcbiAgICAgIFtyZXF1ZXN0LnRhYmxlXTogdGFibGVGaWx0ZXJlZCxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIF9yZW1vdmVOdWxsVmFsdWVzKHJsanNvbjogUmxqc29uKSB7XG4gICAgaXRlcmF0ZVRhYmxlc1N5bmMocmxqc29uLCAodGFibGUpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBybGpzb25bdGFibGVdLl9kYXRhO1xuXG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiBkYXRhKSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHJvdykge1xuICAgICAgICAgIGlmIChyb3dba2V5XSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZGVsZXRlIHJvd1trZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG4iLCIvLyBAbGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDI1IFJsanNvblxuLy9cbi8vIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IHRlcm1zIHRoYXQgY2FuIGJlXG4vLyBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoaXMgcGFja2FnZS5cblxuaW1wb3J0IHsgSW8sIElvTWVtIH0gZnJvbSAnLi9pbmRleC50cyc7XG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4vKipcbiAqIElvIGltcGxlbWVudGF0aW9uIG5lZWQgdG8gaW1wbGVtZW50IHRoaXMgaW50ZXJmYWNlIHRvIGJlIHVzZWQgaW5cbiAqIGNvbmZvcm1hbmNlIHRlc3RzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElvVGVzdFNldHVwIHtcbiAgLyoqIHNldHVwIGJlZm9yZSB0aGUgc2luZ2xlIHNldHVwcyAqL1xuICBiZWZvcmVBbGw6ICgpID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBpbyBpbXBsZW1lbnRhdGlvbi5cbiAgICogQHJldHVybnMgVGhlIGlvIGltcGxlbWVudGF0aW9uLlxuICAgKi9cbiAgYmVmb3JlRWFjaDogKCkgPT4gUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogVGVhcnMgZG93biB0aGUgaW8gaW1wbGVtZW50YXRpb24uXG4gICAqIEByZXR1cm5zIFRoZSBpbyBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIGFmdGVyRWFjaDogKCkgPT4gUHJvbWlzZTx2b2lkPjtcblxuICAvKiogY2xlYW51cCBhZnRlciBhbGwgdGVzdHMgKi9cbiAgYWZ0ZXJBbGw6ICgpID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIFRoZSBpbyBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIGluIHRoZSBjb25mb3JtYW5jZSB0ZXN0cy5cbiAgICovXG4gIGlvOiBJbztcbn1cblxuLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbi8vIEV4YW1wbGUgaW1wbGVtZW50YXRpb24gb2YgdGhlIElvVGVzdFNldHVwIGludGVyZmFjZVxuZXhwb3J0IGNvbnN0IGV4YW1wbGVUZXN0U2V0dXAgPSAoKTogSW9UZXN0U2V0dXAgPT4ge1xuICByZXR1cm4ge1xuICAgIGlvOiBuZXcgSW9NZW0oKSxcbiAgICBiZWZvcmVBbGw6IGFzeW5jICgpID0+IHtcbiAgICAgIC8vIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIGZvciBhbnkgYWRkaXRpb25hbCBzZXR1cCByZXF1aXJlZCBiZWZvcmUgaW5pdC5cbiAgICAgIC8vIEN1cnJlbnRseSwgaXQgZG9lcyBub3RoaW5nLlxuICAgIH0sXG5cbiAgICBiZWZvcmVFYWNoOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBJbml0aWFsaXplIHRoZSBpbyBpbXBsZW1lbnRhdGlvblxuICAgIH0sXG4gICAgYWZ0ZXJFYWNoOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBUZWFyIGRvd24gdGhlIGlvIGltcGxlbWVudGF0aW9uXG4gICAgfSxcblxuICAgIGFmdGVyQWxsOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCBmb3IgYW55IGFkZGl0aW9uYWwgY2xlYW51cCBhZnRlciB0ZWFyRG93bi5cbiAgICB9LFxuICB9O1xufTtcbiIsIi8vIEBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMjUgUmxqc29uXG4vL1xuLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgdGVybXMgdGhhdCBjYW4gYmVcbi8vIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhpcyBwYWNrYWdlLlxuXG5pbXBvcnQgeyBKc29uVmFsdWUgfSBmcm9tICdAcmxqc29uL2pzb24nO1xuaW1wb3J0IHsgQ29udGVudFR5cGUsIFJsanNvbiwgVGFibGVDZmcsIFRhYmxlS2V5IH0gZnJvbSAnQHJsanNvbi9ybGpzb24nO1xuXG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5leHBvcnQgaW50ZXJmYWNlIElvIHtcbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIEdlbmVyYWxcblxuICAvKiogU3RhcnRzIHRoZSBpbml0aWFsaXphdGlvbiAqL1xuICBpbml0KCk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqIENsb3NlcyB0aGUgaW8gKi9cbiAgY2xvc2UoKTogUHJvbWlzZTx2b2lkPjtcblxuICAvKiogUmV0dXJucyB0cnVlIGlmIGlvIGlzIG9wZW5lZCAqL1xuICBpc09wZW46IGJvb2xlYW47XG5cbiAgLyoqIEEgcHJvbWlzZSByZXNvbHZpbmcgb25jZSB0aGUgSW8gaW50ZXJmYWNlIGlzIHJlYWR5XG4gICAqXG4gICAqIPCfkqEgVXNlIEBybGpzb24vaXMtcmVhZHlcbiAgICovXG4gIGlzUmVhZHkoKTogUHJvbWlzZTx2b2lkPjtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gRHVtcFxuXG4gIC8qKiBSZXR1cm5zIHRoZSBjb21wbGV0ZSBkYiBjb250ZW50IGFzIFJsanNvbiAqL1xuICBkdW1wKCk6IFByb21pc2U8Umxqc29uPjtcblxuICAvKiogUmV0dXJucyB0aGUgZHVtcCBvZiBhIGNvbXBsZXRlIHRhYmxlICovXG4gIGR1bXBUYWJsZShyZXF1ZXN0OiB7IHRhYmxlOiBzdHJpbmcgfSk6IFByb21pc2U8Umxqc29uPjtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gTWV0YSBEYXRhXG4gIGNvbnRlbnRUeXBlKHJlcXVlc3Q6IHsgdGFibGU6IHN0cmluZyB9KTogUHJvbWlzZTxDb250ZW50VHlwZT47XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIFRhYmxlc1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHRhYmxlIGV4aXN0c1xuICAgKi9cbiAgdGFibGVFeGlzdHModGFibGVLZXk6IFRhYmxlS2V5KTogUHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHRhYmxlIHdpdGggYSBnaXZlbiBjb25maWcuXG4gICAqIElmIHRoZSB0YWJsZSBhbHJlYWR5IGV4aXN0cywgbmV3IGNvbHVtbnMgYXJlIGFkZGVkIHRvIHRoZSBleGlzdGluZyB0YWJsZS5cbiAgICogSWYgdGhlIHRhYmxlIGRvZXMgbm90IGV4aXN0LCBpdCBpcyBjcmVhdGVkIHdpdGggdGhlIGdpdmVuIGNvbmZpZy5cbiAgICogSWYgdGhlIHRhYmxlIGV4aXN0cyBhbmQgY29sdW1ucyBhcmUgcmVtb3ZlZCwgYW4gZXJyb3IgaXMgdGhyb3duLlxuICAgKiBJZiB0aGUgdGFibGUgZXhpc3RzIGFuZCB0aGUgY29sdW1uIHR5cGUgaXMgY2hhbmdlZCwgYW4gZXJyb3IgaXMgdGhyb3duLlxuICAgKi9cbiAgY3JlYXRlT3JFeHRlbmRUYWJsZShyZXF1ZXN0OiB7IHRhYmxlQ2ZnOiBUYWJsZUNmZyB9KTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIGpzb24gc3RydWN0dXJlIHJldHVybmluZyBjdXJyZW50IHRhYmxlIGNvbmZpZ3VyYXRpb25zXG4gICAqL1xuICByYXdUYWJsZUNmZ3MoKTogUHJvbWlzZTxUYWJsZUNmZ1tdPjtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gV3JpdGVcblxuICAvKiogV3JpdGVzIFJsanNvbiBkYXRhIGludG8gdGhlIGRhdGFiYXNlICovXG4gIHdyaXRlKHJlcXVlc3Q6IHsgZGF0YTogUmxqc29uIH0pOiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBSZWFkIHJvd3NcblxuICAvKiogUXVlcmllcyBhIGxpc3Qgb2Ygcm93cyAqL1xuICByZWFkUm93cyhyZXF1ZXN0OiB7XG4gICAgdGFibGU6IHN0cmluZztcbiAgICB3aGVyZTogeyBbY29sdW1uOiBzdHJpbmddOiBKc29uVmFsdWUgfCBudWxsIH07XG4gIH0pOiBQcm9taXNlPFJsanNvbj47XG5cbiAgLyoqIFJldHVybnMgdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSBnaXZlbiB0YWJsZSAqL1xuICByb3dDb3VudCh0YWJsZTogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+O1xufVxuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuZXhwb3J0IGNvbnN0IGV4YW1wbGVJbyA9XG4gICdDaGVja291dCBAcmxqc29uL2lvLW1lbSBmb3IgYW4gZXhhbXBsZSBpbXBsZW1lbnRhdGlvbic7XG4iLCIvLyBAbGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDI1IFJsanNvblxuLy9cbi8vIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IHRlcm1zIHRoYXQgY2FuIGJlXG4vLyBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoaXMgcGFja2FnZS5cblxuaW1wb3J0IHsgSW8gfSBmcm9tICcuL2lvLnRzJztcbmltcG9ydCB7IFNvY2tldCB9IGZyb20gJy4vc29ja2V0LnRzJztcblxuXG5leHBvcnQgY2xhc3MgUGVlclNvY2tldE1vY2sgaW1wbGVtZW50cyBTb2NrZXQge1xuICBwcml2YXRlIF9saXN0ZW5lcnNNYXA6IE1hcDxzdHJpbmcgfCBzeW1ib2wsIEFycmF5PCguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZD4+ID1cbiAgICBuZXcgTWFwKCk7XG5cbiAgY29ubmVjdGVkOiBib29sZWFuID0gZmFsc2U7XG4gIGRpc2Nvbm5lY3RlZDogYm9vbGVhbiA9IHRydWU7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfaW86IElvKSB7fVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBsaXN0ZW4gZm9yLlxuICAgKiBAcGFyYW0gbGlzdGVuZXIgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gaW52b2tlIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuXG4gICAqIEByZXR1cm5zIFRoZSBQZWVyU29ja2V0TW9jayBpbnN0YW5jZSBmb3IgY2hhaW5pbmcuXG4gICAqL1xuICBvbihldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgbGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHRoaXMge1xuICAgIGlmICghdGhpcy5fbGlzdGVuZXJzTWFwLmhhcyhldmVudE5hbWUpKSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnNNYXAuc2V0KGV2ZW50TmFtZSwgW10pO1xuICAgIH1cbiAgICB0aGlzLl9saXN0ZW5lcnNNYXAuZ2V0KGV2ZW50TmFtZSkhLnB1c2gobGlzdGVuZXIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8qKlxuICAgKiBTaW11bGF0ZXMgYSBjb25uZWN0aW9uIGV2ZW50LlxuICAgKlxuICAgKiBFbWl0cyB0aGUgJ2Nvbm5lY3QnIGV2ZW50IHRvIGFsbCByZWdpc3RlcmVkIGxpc3RlbmVycy5cbiAgICovXG4gIGNvbm5lY3QoKTogdm9pZCB7XG4gICAgdGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuICAgIHRoaXMuZGlzY29ubmVjdGVkID0gZmFsc2U7XG5cbiAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnNNYXAuZ2V0KCdjb25uZWN0JykgfHwgW107XG4gICAgZm9yIChjb25zdCBjYiBvZiBsaXN0ZW5lcnMpIHtcbiAgICAgIGNiKHt9KTtcbiAgICB9XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLyoqXG4gICAqIFNpbXVsYXRlcyBhIGRpc2Nvbm5lY3Rpb24gZXZlbnQuXG4gICAqXG4gICAqIEVtaXRzIHRoZSAnZGlzY29ubmVjdCcgZXZlbnQgdG8gYWxsIHJlZ2lzdGVyZWQgbGlzdGVuZXJzLlxuICAgKi9cbiAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuZGlzY29ubmVjdGVkID0gdHJ1ZTtcblxuICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVyc01hcC5nZXQoJ2Rpc2Nvbm5lY3QnKSB8fCBbXTtcbiAgICBmb3IgKGNvbnN0IGNiIG9mIGxpc3RlbmVycykge1xuICAgICAgY2Ioe30pO1xuICAgIH1cbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLyoqXG4gICAqIEVtaXRzIGFuIGV2ZW50LCBpbnZva2luZyB0aGUgY29ycmVzcG9uZGluZyBtZXRob2Qgb24gdGhlIElvIGluc3RhbmNlLlxuICAgKiBAcGFyYW0gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQuXG4gICAqIEBwYXJhbSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBldmVudCBsaXN0ZW5lci5cbiAgICogQHJldHVybnNcbiAgICovXG4gIGVtaXQoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIC4uLmFyZ3M6IGFueVtdKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZm4gPSAodGhpcy5faW8gYXMgYW55KVtldmVudE5hbWVdIGFzICguLi5hcmdzOiBhbnlbXSkgPT4gUHJvbWlzZTxhbnk+O1xuICAgIGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXZlbnQgJHtldmVudE5hbWUudG9TdHJpbmcoKX0gbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgICBjb25zdCBjYiA9IGFyZ3NbYXJncy5sZW5ndGggLSAxXTtcbiAgICBmbi5hcHBseSh0aGlzLl9pbywgYXJncy5zbGljZSgwLCAtMSkpXG4gICAgICAudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgIGNiKHJlc3VsdCwgbnVsbCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgY2IobnVsbCwgZXJyKTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiIsIi8qIHY4IGlnbm9yZSBmaWxlIC0tIEBwcmVzZXJ2ZSAqL1xuLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbmltcG9ydCB7IEpzb24gfSBmcm9tICdAcmxqc29uL2pzb24nO1xuaW1wb3J0IHtcbiAgQnVmZmV0LFxuICBDYWtlLFxuICBpdGVyYXRlVGFibGVzU3luYyxcbiAgTGF5ZXIsXG4gIFJlZixcbiAgUmxqc29uLFxuICBUYWJsZUtleSxcbn0gZnJvbSAnQHJsanNvbi9ybGpzb24nO1xuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuLyoqXG4gKiBEZXNjcmliZXMgYSByb3cgdGhhdCByZWZlcmVuY2VzIGEgY2hpbGQgdGFibGUgcm93XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGFyZW50UmVmIHtcbiAgLyoqXG4gICAqIFRoZSBwYXJlbnQgdGFibGUgdGhhdCByZWZlcmVuY2VzIHRoZSBjaGlsZCB0YWJsZVxuICAgKi9cbiAgW3BhcmVudFRhYmxlOiBUYWJsZUtleV06IHtcbiAgICAvKipcbiAgICAgKiBUaGUgcGFyZW50IHJvdyB0aGF0IHJlZmVyZW5jZXMgdGhlIGNoaWxkIHJvd1xuICAgICAqL1xuICAgIFtwYXJlbnRSb3c6IFJlZl06IHtcbiAgICAgIC8qKlxuICAgICAgICogRGV0YWlscyBhYm91dCB0aGUgcmVmZXJlbmNlLCBlLmcuIGFuIGFycmF5IGluZGV4IGV0Yy5cbiAgICAgICAqL1xuICAgICAgZGV0YWlscz86IEpzb247XG4gICAgfTtcbiAgfTtcbn1cblxuLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbi8qKlxuICogRGVzY3JpYmVzIHRoZSBwYXJlbnQgdGFibGUgcm93cyByZWZlcmVuY2luZyBhIGNoaWxkIHRhYmxlIHJvd1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFJldmVyc2VSZWZzIHtcbiAgLyoqXG4gICAqIFRoZSBjaGlsZCB0YWJsZSB3ZSBuZWVkIHRoZSByZWZlcmVuY2luZyByb3dzIGZvclxuICAgKi9cbiAgW2NoaWxkVGFibGU6IFRhYmxlS2V5XToge1xuICAgIC8qKlxuICAgICAqIFRoZSByb3cgaGFzaHdlIG5lZWQgdGhlIHJlZmVyZW5jaW5nIHJvd3MgZm9yXG4gICAgICovXG4gICAgW2NoaWxkUm93OiBSZWZdOiBQYXJlbnRSZWY7XG4gIH07XG59XG5cbi8qIHY4IGlnbm9yZSBzdGFydCAqL1xuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSByZXZlcnNlIHJlZmVyZW5jZXMgZm9yIGEgZ2l2ZW4gcmxqc29uIG9iamVjdFxuICovXG5leHBvcnQgY29uc3QgY2FsY1JldmVyc2VSZWZzID0gKHJsanNvbjogUmxqc29uKTogUmV2ZXJzZVJlZnMgPT4ge1xuICBjb25zdCByZXN1bHQ6IFJldmVyc2VSZWZzID0ge307XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBQcmVwYXJlIGRhdGEgc3RydWN0dXJlXG4gIGl0ZXJhdGVUYWJsZXNTeW5jKHJsanNvbiwgKGNoaWxkVGFibGVLZXksIHRhYmxlKSA9PiB7XG4gICAgY29uc3QgY2hpbGRUYWJsZTogeyBbY2hpbGRSb3dIYXNoOiBzdHJpbmddOiBQYXJlbnRSZWYgfSA9IHt9O1xuICAgIHJlc3VsdFtjaGlsZFRhYmxlS2V5XSA9IGNoaWxkVGFibGU7XG4gICAgZm9yIChjb25zdCBjaGlsZFJvdyBvZiB0YWJsZS5fZGF0YSkge1xuICAgICAgY2hpbGRUYWJsZVtjaGlsZFJvdy5faGFzaF0gPSB7fTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gR2VuZXJhdGUgcmV2ZXJzZSByZWZlcmVuY2VzXG4gIGl0ZXJhdGVUYWJsZXNTeW5jKHJsanNvbiwgKHBhcmVudFRhYmxlS2V5LCBwYXJlbnRUYWJsZSkgPT4ge1xuICAgIC8vIEl0ZXJhdGUgYWxsIHJvd3Mgb2YgZWFjaCB0YWJsZVxuICAgIGZvciAoY29uc3QgcGFyZW50VGFibGVSb3cgb2YgcGFyZW50VGFibGUuX2RhdGEpIHtcbiAgICAgIC8vIEZpbmQgb3V0IHdoZSBvdGhlciB0YWJsZXMgJiByb3dzIGFyZSByZWZlcmVuY2VkIGJ5IHRoaXMgcm93XG4gICAgICAvLyBXcml0ZSB0aGVzZSBpbmZvcm1hdGlvbiBpbnR0byByZXN1bHRcbiAgICAgIHN3aXRjaCAocGFyZW50VGFibGUuX3R5cGUpIHtcbiAgICAgICAgY2FzZSAnY29tcG9uZW50cyc6XG4gICAgICAgICAgX3dyaXRlQ29tcG9uZW50UmVmcyhwYXJlbnRUYWJsZUtleSwgcGFyZW50VGFibGVSb3csIHJlc3VsdCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnbGF5ZXJzJzoge1xuICAgICAgICAgIF93cml0ZUxheWVyUmVmcyhwYXJlbnRUYWJsZUtleSwgcGFyZW50VGFibGVSb3csIHJlc3VsdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjYXNlICdzbGljZUlkcyc6IHtcbiAgICAgICAgICAvLyBTbGljZSBpZHMgZG8gbm90IHJlZmVyZW5jZSBvdGhlciB0YWJsZXNcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2Nha2VzJzoge1xuICAgICAgICAgIF93cml0ZUNha2VSZWZzKHBhcmVudFRhYmxlS2V5LCBwYXJlbnRUYWJsZVJvdywgcmVzdWx0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2J1ZmZldHMnOiB7XG4gICAgICAgICAgX3dyaXRlQnVmZmV0UmVmcyhwYXJlbnRUYWJsZUtleSwgcGFyZW50VGFibGVSb3csIHJlc3VsdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG4vKiB2OCBpZ25vcmUgZW5kICovXG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5jb25zdCBfd3JpdGVDb21wb25lbnRSZWZzID0gKFxuICBwYXJlbnRUYWJsZU5hbWU6IFRhYmxlS2V5LFxuICBwYXJlbnRSb3c6IEpzb24sXG4gIHJlc3VsdDogUmV2ZXJzZVJlZnMsXG4pID0+IHtcbiAgY29uc3QgcGFyZW50Um93SGFzaCA9IHBhcmVudFJvdy5faGFzaCBhcyBzdHJpbmc7XG5cbiAgZm9yIChjb25zdCBwYXJlbnRDb2x1bW5OYW1lIGluIHBhcmVudFJvdykge1xuICAgIGlmIChwYXJlbnRDb2x1bW5OYW1lLnN0YXJ0c1dpdGgoJ18nKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJlbnRDb2x1bW5OYW1lLmVuZHNXaXRoKCdSZWYnKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgY2hpbGRUYWJsZU5hbWUgPSBwYXJlbnRDb2x1bW5OYW1lLnNsaWNlKDAsIC0zKTtcbiAgICBjb25zdCBjaGlsZFJvd0hhc2ggPSBwYXJlbnRSb3dbcGFyZW50Q29sdW1uTmFtZV0gYXMgc3RyaW5nO1xuXG4gICAgX3dyaXRlKFxuICAgICAgcmVzdWx0LFxuICAgICAgY2hpbGRUYWJsZU5hbWUsXG4gICAgICBjaGlsZFJvd0hhc2gsXG4gICAgICBwYXJlbnRUYWJsZU5hbWUsXG4gICAgICBwYXJlbnRSb3dIYXNoLFxuICAgICk7XG4gIH1cbn07XG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5jb25zdCBfd3JpdGVMYXllclJlZnMgPSAoXG4gIHBhcmVudFRhYmxlTmFtZTogVGFibGVLZXksXG4gIHBhcmVudFJvdzogTGF5ZXIsXG4gIHJlc3VsdDogUmV2ZXJzZVJlZnMsXG4pID0+IHtcbiAgY29uc3QgY2hpbGRUYWJsZU5hbWUgPSBwYXJlbnRSb3cuY29tcG9uZW50c1RhYmxlO1xuICBjb25zdCBwYXJlbnRSb3dIYXNoID0gcGFyZW50Um93Ll9oYXNoIGFzIHN0cmluZztcblxuICBmb3IgKGNvbnN0IHNsaWNlSWQgaW4gcGFyZW50Um93LmFkZCkge1xuICAgIGlmIChzbGljZUlkLnN0YXJ0c1dpdGgoJ18nKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3Qgc2xpY2VIYXNoID0gcGFyZW50Um93LmFkZFtzbGljZUlkXSBhcyBzdHJpbmc7XG5cbiAgICBfd3JpdGUocmVzdWx0LCBjaGlsZFRhYmxlTmFtZSwgc2xpY2VIYXNoLCBwYXJlbnRUYWJsZU5hbWUsIHBhcmVudFJvd0hhc2gpO1xuICB9XG59O1xuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuY29uc3QgX3dyaXRlQ2FrZVJlZnMgPSAoXG4gIHBhcmVudFRhYmxlTmFtZTogVGFibGVLZXksXG4gIHBhcmVudFJvdzogQ2FrZSxcbiAgcmVzdWx0OiBSZXZlcnNlUmVmcyxcbikgPT4ge1xuICBjb25zdCBwYXJlbnRSb3dIYXNoID0gcGFyZW50Um93Ll9oYXNoIGFzIHN0cmluZztcblxuICBmb3IgKGNvbnN0IGxheWVyIGluIHBhcmVudFJvdy5sYXllcnMpIHtcbiAgICBjb25zdCBjaGlsZFRhYmxlTmFtZSA9IGxheWVyO1xuICAgIGNvbnN0IGNoaWxkUm93SGFzaCA9IHBhcmVudFJvdy5sYXllcnNbbGF5ZXJdIGFzIHN0cmluZztcbiAgICBfd3JpdGUoXG4gICAgICByZXN1bHQsXG4gICAgICBjaGlsZFRhYmxlTmFtZSxcbiAgICAgIGNoaWxkUm93SGFzaCxcbiAgICAgIHBhcmVudFRhYmxlTmFtZSxcbiAgICAgIHBhcmVudFJvd0hhc2gsXG4gICAgKTtcbiAgfVxufTtcblxuLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbmNvbnN0IF93cml0ZUJ1ZmZldFJlZnMgPSAoXG4gIHBhcmVudFRhYmxlTmFtZTogVGFibGVLZXksXG4gIHBhcmVudFJvdzogQnVmZmV0LFxuICByZXN1bHQ6IFJldmVyc2VSZWZzLFxuKSA9PiB7XG4gIGNvbnN0IHBhcmVudFJvd0hhc2ggPSBwYXJlbnRSb3cuX2hhc2ggYXMgc3RyaW5nO1xuXG4gIGZvciAoY29uc3QgaXRlbSBvZiBwYXJlbnRSb3cuaXRlbXMpIHtcbiAgICBjb25zdCBjaGlsZFRhYmxlTmFtZSA9IGl0ZW0udGFibGU7XG4gICAgY29uc3QgY2hpbGRSb3dIYXNoID0gaXRlbS5yZWY7XG4gICAgX3dyaXRlKFxuICAgICAgcmVzdWx0LFxuICAgICAgY2hpbGRUYWJsZU5hbWUsXG4gICAgICBjaGlsZFJvd0hhc2gsXG4gICAgICBwYXJlbnRUYWJsZU5hbWUsXG4gICAgICBwYXJlbnRSb3dIYXNoLFxuICAgICk7XG4gIH1cbn07XG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5jb25zdCBfd3JpdGUgPSAoXG4gIHJlc3VsdDogUmV2ZXJzZVJlZnMsXG4gIGNoaWxkVGFibGVOYW1lOiBzdHJpbmcsXG4gIGNoaWxkUm93SGFzaDogc3RyaW5nLFxuICBwYXJlbnRUYWJsZU5hbWU6IHN0cmluZyxcbiAgcGFyZW50Um93SGFzaDogc3RyaW5nLFxuKSA9PiB7XG4gIGNvbnN0IHJlZmVyZW5jZXNGb3JDaGlsZFRhYmxlID0gKHJlc3VsdFtjaGlsZFRhYmxlTmFtZV0gPz89IHt9KTtcbiAgY29uc3QgcmVmZXJlbmNlc0ZvckNoaWxkVGFibGVSb3cgPSAocmVmZXJlbmNlc0ZvckNoaWxkVGFibGVbY2hpbGRSb3dIYXNoXSA/Pz1cbiAgICB7fSk7XG5cbiAgcmVmZXJlbmNlc0ZvckNoaWxkVGFibGVSb3dbcGFyZW50VGFibGVOYW1lXSA/Pz0ge307XG4gIHJlZmVyZW5jZXNGb3JDaGlsZFRhYmxlUm93W3BhcmVudFRhYmxlTmFtZV1bcGFyZW50Um93SGFzaF0gPz89IHt9O1xufTtcbiIsIi8vIEBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMjUgUmxqc29uXG4vL1xuLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgdGVybXMgdGhhdCBjYW4gYmVcbi8vIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhpcyBwYWNrYWdlLlxuLyogdjggaWdub3JlIGZpbGUgLS0gQHByZXNlcnZlICovXG5pbXBvcnQgeyBTb2NrZXQgfSBmcm9tICcuL3NvY2tldC50cyc7XG5cbmV4cG9ydCBjbGFzcyBTb2NrZXRNb2NrIGltcGxlbWVudHMgU29ja2V0IHtcbiAgcHVibGljIGNvbm5lY3RlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwdWJsaWMgZGlzY29ubmVjdGVkOiBib29sZWFuID0gdHJ1ZTtcblxuICBwcml2YXRlIF9saXN0ZW5lcnM6IE1hcDxzdHJpbmcgfCBzeW1ib2wsIEFycmF5PCguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZD4+ID1cbiAgICBuZXcgTWFwKCk7XG4gIHByaXZhdGUgX29uY2VMaXN0ZW5lcnM6IE1hcDxcbiAgICBzdHJpbmcgfCBzeW1ib2wsXG4gICAgQXJyYXk8KC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkPlxuICA+ID0gbmV3IE1hcCgpO1xuXG4gIGNvbm5lY3QoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbm5lY3RlZCkge1xuICAgICAgdGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5kaXNjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuZW1pdCgnY29ubmVjdCcpO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY29ubmVjdGVkKSB7XG4gICAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5kaXNjb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5lbWl0KCdkaXNjb25uZWN0Jyk7XG4gICAgfVxuICB9XG5cbiAgb24oZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIGxpc3RlbmVyOiAoLi4uYXJnczogYW55W10pID0+IHZvaWQpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuX2xpc3RlbmVycy5oYXMoZXZlbnROYW1lKSkge1xuICAgICAgdGhpcy5fbGlzdGVuZXJzLnNldChldmVudE5hbWUsIFtdKTtcbiAgICB9XG4gICAgdGhpcy5fbGlzdGVuZXJzLmdldChldmVudE5hbWUpIS5wdXNoKGxpc3RlbmVyKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9uY2UoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIGxpc3RlbmVyOiAoLi4uYXJnczogYW55W10pID0+IHZvaWQpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuX29uY2VMaXN0ZW5lcnMuaGFzKGV2ZW50TmFtZSkpIHtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgW10pO1xuICAgIH1cbiAgICB0aGlzLl9vbmNlTGlzdGVuZXJzLmdldChldmVudE5hbWUpIS5wdXNoKGxpc3RlbmVyKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9mZihldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgbGlzdGVuZXI/OiAoLi4uYXJnczogYW55W10pID0+IHZvaWQpOiB0aGlzIHtcbiAgICBpZiAobGlzdGVuZXIpIHtcbiAgICAgIC8vIFJlbW92ZSBzcGVjaWZpYyBsaXN0ZW5lclxuICAgICAgY29uc3QgcmVndWxhckxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVycy5nZXQoZXZlbnROYW1lKTtcbiAgICAgIGlmIChyZWd1bGFyTGlzdGVuZXJzKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gcmVndWxhckxpc3RlbmVycy5pbmRleE9mKGxpc3RlbmVyKTtcbiAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgICByZWd1bGFyTGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgb25jZUxpc3RlbmVycyA9IHRoaXMuX29uY2VMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSk7XG4gICAgICBpZiAob25jZUxpc3RlbmVycykge1xuICAgICAgICBjb25zdCBpbmRleCA9IG9uY2VMaXN0ZW5lcnMuaW5kZXhPZihsaXN0ZW5lcik7XG4gICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgICAgb25jZUxpc3RlbmVycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnRcbiAgICAgIHRoaXMuX2xpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgZW1pdChldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgLi4uYXJnczogYW55W10pOiBib29sZWFuIHtcbiAgICBsZXQgaGFzTGlzdGVuZXJzID0gZmFsc2U7XG5cbiAgICAvLyBFbWl0IHRvIHJlZ3VsYXIgbGlzdGVuZXJzXG4gICAgY29uc3QgcmVndWxhckxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVycy5nZXQoZXZlbnROYW1lKTtcbiAgICBpZiAocmVndWxhckxpc3RlbmVycyAmJiByZWd1bGFyTGlzdGVuZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGhhc0xpc3RlbmVycyA9IHRydWU7XG4gICAgICAvLyBDcmVhdGUgYSBjb3B5IHRvIGF2b2lkIGlzc3VlcyBpZiBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgZHVyaW5nIGVtaXNzaW9uXG4gICAgICBbLi4ucmVndWxhckxpc3RlbmVyc10uZm9yRWFjaCgobGlzdGVuZXIpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsaXN0ZW5lciguLi5hcmdzKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAvLyBJbiBhIHJlYWwgRXZlbnRFbWl0dGVyLCB0aGlzIHdvdWxkIGJlIGhhbmRsZWQgZGlmZmVyZW50bHlcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgYEVycm9yIGluIGxpc3RlbmVyIGZvciBldmVudCAke1N0cmluZyhldmVudE5hbWUpfTpgLFxuICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gRW1pdCB0byBvbmNlIGxpc3RlbmVycyBhbmQgcmVtb3ZlIHRoZW1cbiAgICBjb25zdCBvbmNlTGlzdGVuZXJzID0gdGhpcy5fb25jZUxpc3RlbmVycy5nZXQoZXZlbnROYW1lKTtcbiAgICBpZiAob25jZUxpc3RlbmVycyAmJiBvbmNlTGlzdGVuZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGhhc0xpc3RlbmVycyA9IHRydWU7XG4gICAgICAvLyBDcmVhdGUgYSBjb3B5IGFuZCBjbGVhciB0aGUgb3JpZ2luYWwgYXJyYXlcbiAgICAgIGNvbnN0IGxpc3RlbmVyc1RvQ2FsbCA9IFsuLi5vbmNlTGlzdGVuZXJzXTtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG5cbiAgICAgIGxpc3RlbmVyc1RvQ2FsbC5mb3JFYWNoKChsaXN0ZW5lcikgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGxpc3RlbmVyKC4uLmFyZ3MpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBgRXJyb3IgaW4gb25jZSBsaXN0ZW5lciBmb3IgZXZlbnQgJHtTdHJpbmcoZXZlbnROYW1lKX06YCxcbiAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBoYXNMaXN0ZW5lcnM7XG4gIH1cblxuICByZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnROYW1lPzogc3RyaW5nIHwgc3ltYm9sKTogdGhpcyB7XG4gICAgaWYgKGV2ZW50TmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG4gICAgICB0aGlzLl9vbmNlTGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnMuY2xlYXIoKTtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuY2xlYXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBsaXN0ZW5lckNvdW50KGV2ZW50TmFtZTogc3RyaW5nIHwgc3ltYm9sKTogbnVtYmVyIHtcbiAgICBjb25zdCByZWd1bGFyQ291bnQgPSB0aGlzLl9saXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSk/Lmxlbmd0aCB8fCAwO1xuICAgIGNvbnN0IG9uY2VDb3VudCA9IHRoaXMuX29uY2VMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSk/Lmxlbmd0aCB8fCAwO1xuICAgIHJldHVybiByZWd1bGFyQ291bnQgKyBvbmNlQ291bnQ7XG4gIH1cblxuICBsaXN0ZW5lcnMoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wpOiBBcnJheTwoLi4uYXJnczogYW55W10pID0+IHZvaWQ+IHtcbiAgICBjb25zdCByZWd1bGFyTGlzdGVuZXJzID0gdGhpcy5fbGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IG9uY2VMaXN0ZW5lcnMgPSB0aGlzLl9vbmNlTGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIHJldHVybiBbLi4ucmVndWxhckxpc3RlbmVycywgLi4ub25jZUxpc3RlbmVyc107XG4gIH1cblxuICBldmVudE5hbWVzKCk6IEFycmF5PHN0cmluZyB8IHN5bWJvbD4ge1xuICAgIGNvbnN0IGFsbEV2ZW50cyA9IG5ldyBTZXQoW1xuICAgICAgLi4udGhpcy5fbGlzdGVuZXJzLmtleXMoKSxcbiAgICAgIC4uLnRoaXMuX29uY2VMaXN0ZW5lcnMua2V5cygpLFxuICAgIF0pO1xuICAgIHJldHVybiBBcnJheS5mcm9tKGFsbEV2ZW50cyk7XG4gIH1cblxuICAvLyBUZXN0IGhlbHBlciBtZXRob2RzXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgdGhpcy5kaXNjb25uZWN0ZWQgPSB0cnVlO1xuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gIH1cblxuICBzaW11bGF0ZUVycm9yKGVycm9yOiBFcnJvcik6IHZvaWQge1xuICAgIHRoaXMuZW1pdCgnZXJyb3InLCBlcnJvcik7XG4gIH1cblxuICBzaW11bGF0ZU1lc3NhZ2UobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy5lbWl0KCdtZXNzYWdlJywgbWVzc2FnZSk7XG4gIH1cblxuICAvLyBHZXQgaW50ZXJuYWwgc3RhdGUgZm9yIHRlc3RpbmdcbiAgZ2V0TGlzdGVuZXJzKCk6IE1hcDxzdHJpbmcgfCBzeW1ib2wsIEFycmF5PCguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZD4+IHtcbiAgICByZXR1cm4gbmV3IE1hcCh0aGlzLl9saXN0ZW5lcnMpO1xuICB9XG5cbiAgZ2V0T25jZUxpc3RlbmVycygpOiBNYXA8c3RyaW5nIHwgc3ltYm9sLCBBcnJheTwoLi4uYXJnczogYW55W10pID0+IHZvaWQ+PiB7XG4gICAgcmV0dXJuIG5ldyBNYXAodGhpcy5fb25jZUxpc3RlbmVycyk7XG4gIH1cbn1cblxuLy8gLi4uZXhpc3RpbmcgY29kZS4uLlxuIiwiLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbi8vSW50ZXJmYWNlIGZvciBhIGdlbmVyaWMgU29ja2V0LCBzaW1pbGFyIHRvIE5vZGUuanMgRXZlbnRFbWl0dGVyXG4vL1RoaXMgaXMgYSBzaW1wbGlmaWVkIHZlcnNpb24gYW5kIG1heSBub3QgY292ZXIgYWxsIGZlYXR1cmVzIG9mIGEgZnVsbCBFdmVudEVtaXR0ZXJcbmV4cG9ydCBpbnRlcmZhY2UgU29ja2V0IHtcbiAgY29ubmVjdGVkOiBib29sZWFuO1xuICBkaXNjb25uZWN0ZWQ6IGJvb2xlYW47XG4gIGNvbm5lY3QoKTogdm9pZDtcbiAgZGlzY29ubmVjdCgpOiB2b2lkO1xuICBvbihldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgbGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHRoaXM7XG4gIGVtaXQoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIC4uLmFyZ3M6IGFueVtdKTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IHNvY2tldEV4YW1wbGUgPSAoKTogU29ja2V0ID0+ICh7XG4gIGNvbm5lY3RlZDogZmFsc2UsXG4gIGRpc2Nvbm5lY3RlZDogdHJ1ZSxcbiAgY29ubmVjdCgpIHtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IHRydWU7XG4gICAgdGhpcy5kaXNjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmVtaXQoJ2Nvbm5lY3QnKTtcbiAgfSxcbiAgZGlzY29ubmVjdCgpIHtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuZGlzY29ubmVjdGVkID0gdHJ1ZTtcbiAgICB0aGlzLmVtaXQoJ2Rpc2Nvbm5lY3QnKTtcbiAgfSxcbiAgLyogdjggaWdub3JlIG5leHQgLS0gQHByZXNlcnZlICovXG4gIG9uKCkge1xuICAgIC8vIEltcGxlbWVudGF0aW9uIG9mIGV2ZW50IGxpc3RlbmVyIHJlZ2lzdHJhdGlvblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICAvKiB2OCBpZ25vcmUgbmV4dCAtLSBAcHJlc2VydmUgKi9cbiAgZW1pdCgpIHtcbiAgICAvLyBJbXBsZW1lbnRhdGlvbiBvZiBldmVudCBlbWlzc2lvblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxufSk7XG4iXSwibmFtZXMiOlsiZSJdLCJtYXBwaW5ncyI6Ijs7OztBQU1PLE1BQU0sZ0JBQWdCO0FBQUE7QUFBQSxFQUVwQixtQkFBMkI7QUFBQSxFQUMzQixjQUFzQjtBQUFBLEVBQ3RCLGFBQXFCO0FBQUEsRUFDckIsWUFBb0I7QUFBQTtBQUFBLEVBR3BCLGFBQXdDO0FBQUEsSUFDN0MsTUFBTTtBQUFBLElBQ04sVUFBVTtBQUFBLEVBQUE7QUFBQTtBQUFBLEVBSUosVUFBcUM7QUFBQSxJQUMzQyxLQUFLO0FBQUEsSUFDTCxLQUFLO0FBQUEsSUFDTCxLQUFLO0FBQUEsRUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtDLFFBQVEsTUFBYyxLQUFxQjtBQUNqRCxXQUFPLEtBQUssU0FBUyxHQUFHLElBQUksT0FBTyxPQUFPO0FBQUEsRUFDNUM7QUFBQSxFQUVPLGVBQWUsTUFBc0I7QUFDMUMsV0FBTyxLQUFLLFFBQVEsTUFBTSxLQUFLLFFBQVEsR0FBRztBQUFBLEVBQzVDO0FBQUEsRUFFTyxnQkFBZ0IsTUFBc0I7QUFDM0MsV0FBTyxLQUFLLFFBQVEsTUFBTSxLQUFLLFFBQVEsR0FBRztBQUFBLEVBQzVDO0FBQUEsRUFFTyxhQUFhLE1BQXNCO0FBQ3hDLFdBQU8sS0FBSyxRQUFRLE1BQU0sS0FBSyxRQUFRLEdBQUc7QUFBQSxFQUM1QztBQUFBLEVBRVEsV0FBVyxNQUFjLEtBQXFCO0FBQ3BELFdBQU8sS0FBSyxTQUFTLEdBQUcsSUFBSSxLQUFLLE1BQU0sR0FBRyxDQUFDLElBQUksTUFBTSxJQUFJO0FBQUEsRUFDM0Q7QUFBQSxFQUVPLGtCQUFrQixNQUFzQjtBQUM3QyxXQUFPLEtBQUssV0FBVyxNQUFNLEtBQUssUUFBUSxHQUFHO0FBQUEsRUFDL0M7QUFBQSxFQUVPLG1CQUFtQixNQUFzQjtBQUM5QyxXQUFPLEtBQUssV0FBVyxNQUFNLEtBQUssUUFBUSxHQUFHO0FBQUEsRUFDL0M7QUFBQSxFQUVPLGdCQUFnQixNQUFzQjtBQUMzQyxXQUFPLEtBQUssV0FBVyxNQUFNLEtBQUssUUFBUSxHQUFHO0FBQUEsRUFDL0M7QUFDRjtBQ2xDTyxNQUFNLFFBQVE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS25CLFlBQTRCLElBQVE7QUFBUixTQUFBLEtBQUE7QUFBQSxFQUFTO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLckMsV0FBVyxvQkFBb0I7QUFDN0IsVUFBTSxXQUFXLElBQWM7QUFBQSxNQUM3QixPQUFPO0FBQUEsTUFDUCxLQUFLO0FBQUEsTUFDTCxNQUFNO0FBQUEsTUFDTixRQUFRO0FBQUEsTUFDUixRQUFRO0FBQUEsTUFDUixVQUFVO0FBQUEsTUFDVixVQUFVO0FBQUEsTUFFVixTQUFTO0FBQUEsUUFDUDtBQUFBLFVBQ0UsS0FBSztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sWUFBWTtBQUFBLFVBQ1osV0FBVztBQUFBLFFBQUE7QUFBQSxRQUViO0FBQUEsVUFDRSxLQUFLO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixZQUFZO0FBQUEsVUFDWixXQUFXO0FBQUEsUUFBQTtBQUFBLFFBRWI7QUFBQSxVQUNFLEtBQUs7QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLFlBQVk7QUFBQSxVQUNaLFdBQVc7QUFBQSxRQUFBO0FBQUEsUUFFYjtBQUFBLFVBQ0UsS0FBSztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sWUFBWTtBQUFBLFVBQ1osV0FBVztBQUFBLFFBQUE7QUFBQSxRQUViO0FBQUEsVUFDRSxLQUFLO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixZQUFZO0FBQUEsVUFDWixXQUFXO0FBQUEsUUFBQTtBQUFBLFFBRWI7QUFBQSxVQUNFLEtBQUs7QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLFlBQVk7QUFBQSxVQUNaLFdBQVc7QUFBQSxRQUFBO0FBQUEsUUFFYjtBQUFBLFVBQ0UsS0FBSztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sWUFBWTtBQUFBLFVBQ1osV0FBVztBQUFBLFFBQUE7QUFBQSxRQUViO0FBQUEsVUFDRSxLQUFLO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixZQUFZO0FBQUEsVUFDWixXQUFXO0FBQUEsUUFBQTtBQUFBLE1BQ2I7QUFBQSxJQUNGLENBQ0Q7QUFFRCxXQUFPO0FBQUEsRUFDVDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EscUJBQXFCLFlBQVk7QUFDL0IsVUFBTSxXQUFxQjtBQUFBLE1BQ3pCLEtBQUs7QUFBQSxNQUNMLE1BQU07QUFBQSxNQUNOLFFBQVE7QUFBQSxNQUNSLFFBQVE7QUFBQSxNQUNSLFVBQVU7QUFBQSxNQUVWLFNBQVM7QUFBQSxRQUNQO0FBQUEsVUFDRSxLQUFLO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixZQUFZO0FBQUEsVUFDWixXQUFXO0FBQUEsUUFBQTtBQUFBLFFBRWI7QUFBQSxVQUNFLEtBQUs7QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLFlBQVk7QUFBQSxVQUNaLFdBQVc7QUFBQSxRQUFBO0FBQUEsUUFFYjtBQUFBLFVBQ0UsS0FBSztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sWUFBWTtBQUFBLFVBQ1osV0FBVztBQUFBLFFBQUE7QUFBQSxRQUViO0FBQUEsVUFDRSxLQUFLO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixZQUFZO0FBQUEsVUFDWixXQUFXO0FBQUEsUUFBQTtBQUFBLFFBRWI7QUFBQSxVQUNFLEtBQUs7QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLFlBQVk7QUFBQSxVQUNaLFdBQVc7QUFBQSxRQUFBO0FBQUEsUUFFYjtBQUFBLFVBQ0UsS0FBSztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sWUFBWTtBQUFBLFVBQ1osV0FBVztBQUFBLFFBQUE7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUdGLFVBQU0sS0FBSyxHQUFHLG9CQUFvQixFQUFFLFVBQVU7QUFBQSxFQUNoRDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNQSxPQUFPLFVBQVUsWUFBWTtBQUMzQixVQUFNLEtBQUssTUFBTSxNQUFNLFFBQUE7QUFDdkIsVUFBTSxHQUFHLEtBQUE7QUFDVCxVQUFNLEdBQUcsUUFBQTtBQUNULFdBQU8sSUFBSSxRQUFRLEVBQUU7QUFBQSxFQUN2QjtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsTUFBTSwyQkFBMkIsT0FBZ0M7QUFDL0QsVUFBTSxTQUFTLE1BQU0sS0FBSyxHQUFHLFlBQVksS0FBSztBQUM5QyxRQUFJLENBQUMsUUFBUTtBQUNYLFlBQU0sSUFBSSxNQUFNLFVBQVUsS0FBSyxhQUFhO0FBQUEsSUFDOUM7QUFBQSxFQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU1BLE1BQU0sMEJBQTBCLFFBQStCO0FBQzdELFFBQUk7QUFDRixZQUFNLGNBQWMsUUFBUSxPQUFPLGFBQWE7QUFDOUMsY0FBTSxTQUFTLE1BQU0sS0FBSyxHQUFHLFlBQVksUUFBUTtBQUNqRCxZQUFJLENBQUMsUUFBUTtBQUNYLGdCQUFNLElBQUksTUFBTSxVQUFVLFFBQVEsYUFBYTtBQUFBLFFBQ2pEO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDSCxTQUFTLEdBQUc7QUFDVixZQUFNLGdCQUFpQixFQUFpQixJQUFJLENBQUNBLE9BQU1BLEdBQUUsUUFBUTtBQUU3RCxZQUFNLElBQUk7QUFBQSxRQUNSLHNDQUFzQyxjQUFjLEtBQUssSUFBSSxDQUFDO0FBQUEsTUFBQTtBQUFBLElBRWxFO0FBQUEsRUFDRjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNQSxNQUFNLFlBQWlDO0FBQ3JDLFVBQU0sU0FBUyxNQUFNLEtBQUssR0FBRyxhQUFBO0FBRzdCLFVBQU0sZ0JBQTRDLENBQUE7QUFDbEQsYUFBUyxJQUFJLE9BQU8sU0FBUyxHQUFHLEtBQUssR0FBRyxLQUFLO0FBQzNDLFlBQU0sUUFBUSxPQUFPLENBQUM7QUFDdEIsWUFBTSxXQUFXLGNBQWMsTUFBTSxHQUFHO0FBQ3hDLFVBQUksQ0FBQyxZQUFZLFNBQVMsUUFBUSxTQUFTLE1BQU0sUUFBUSxRQUFRO0FBQy9ELHNCQUFjLE1BQU0sR0FBRyxJQUFJO0FBQUEsTUFDN0I7QUFBQSxJQUNGO0FBSUEsVUFBTSxhQUFhLE9BQU8sT0FBTyxhQUFhLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTTtBQUM3RCxVQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUs7QUFDakIsZUFBTztBQUFBLE1BQ1Q7QUFDQSxVQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUs7QUFDakIsZUFBTztBQUFBLE1BQ1Q7QUFFQSxhQUFPO0FBQUEsSUFDVCxDQUFDO0FBQ0QsV0FBTztBQUFBLEVBQ1Q7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLE1BQU0sZUFBa0M7QUFDdEMsVUFBTSxVQUFVLE1BQU0sS0FBSyxVQUFBLEdBQWEsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHO0FBQ3hELFdBQU87QUFBQSxFQUNUO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxNQUFNLFNBQVMsT0FBb0M7QUFDakQsVUFBTSxXQUFXLE1BQU0sS0FBSyxlQUFlLEtBQUs7QUFDaEQsUUFBSSxDQUFDLFVBQVU7QUFDYixZQUFNLElBQUksTUFBTSxVQUFVLEtBQUssYUFBYTtBQUFBLElBQzlDO0FBRUEsV0FBTztBQUFBLEVBQ1Q7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTUEsTUFBTSxlQUFlLE9BQTJDO0FBQzlELFVBQU0sWUFBWSxNQUFNLEtBQUssVUFBQTtBQUM3QixVQUFNLFdBQVcsVUFBVSxLQUFLLENBQUMsTUFBTSxFQUFFLFFBQVEsS0FBSztBQUN0RCxXQUFPLFlBQVk7QUFBQSxFQUNyQjtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsTUFBTSxjQUFjLE9BQW9DO0FBQ3RELFVBQU0sV0FBVyxNQUFNLEtBQUssU0FBUyxLQUFLO0FBQzFDLFVBQU0sU0FBUyxTQUFTLFFBQVEsSUFBSSxDQUFDLFdBQVcsT0FBTyxHQUFHO0FBQzFELFdBQU87QUFBQSxFQUNUO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsTUFBTSw0QkFDSixPQUNBLFNBQ2U7QUFDZixVQUFNLFdBQVcsTUFBTSxLQUFLLFNBQVMsS0FBSztBQUMxQyxVQUFNLGFBQWEsU0FBUyxRQUFRLElBQUksQ0FBQyxXQUFXLE9BQU8sR0FBRztBQUM5RCxVQUFNLGlCQUFpQixRQUFRO0FBQUEsTUFDN0IsQ0FBQyxXQUFXLENBQUMsV0FBVyxTQUFTLE1BQU07QUFBQSxJQUFBO0FBRXpDLFFBQUksZUFBZSxTQUFTLEdBQUc7QUFDN0IsWUFBTSxJQUFJO0FBQUEsUUFDUixnREFBZ0QsS0FBSyxNQUFNLGVBQWU7QUFBQSxVQUN4RTtBQUFBLFFBQUEsQ0FDRDtBQUFBLE1BQUE7QUFBQSxJQUVMO0FBQUEsRUFDRjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNQSxNQUFNLDhCQUE4QixRQUFpQztBQUNuRSxVQUFNLFNBQVMsaUNBQWlDLE9BQU8sR0FBRztBQUUxRCwyQkFBdUIsTUFBTTtBQUc3QixVQUFNLFdBQVcsTUFBTSxLQUFLLGVBQWUsT0FBTyxHQUFHO0FBQ3JELFFBQUksVUFBVTtBQUVaLFVBQUksU0FBUyxRQUFRLFNBQVMsT0FBTyxRQUFRLFFBQVE7QUFDbkQsY0FBTSxvQkFBb0IsU0FBUyxRQUNoQyxJQUFJLENBQUMsV0FBVyxPQUFPLEdBQUcsRUFDMUI7QUFBQSxVQUNDLENBQUMsUUFBUSxDQUFDLE9BQU8sUUFBUSxLQUFLLENBQUMsV0FBVyxPQUFPLFFBQVEsR0FBRztBQUFBLFFBQUE7QUFHaEUsWUFBSSxrQkFBa0IsU0FBUyxHQUFHO0FBQ2hDLGdCQUFNLGlCQUFpQixrQkFBa0IsS0FBSyxJQUFJO0FBQ2xELGdCQUFNLElBQUk7QUFBQSxZQUNSLEdBQUcsTUFBTSxtREFDYSxjQUFjO0FBQUEsVUFBQTtBQUFBLFFBRXhDO0FBQUEsTUFDRjtBQUdBLGVBQVMsSUFBSSxHQUFHLElBQUksU0FBUyxRQUFRLFFBQVEsS0FBSztBQUNoRCxjQUFNLFNBQVMsU0FBUyxRQUFRLENBQUMsRUFBRTtBQUNuQyxjQUFNLFFBQVEsT0FBTyxRQUFRLENBQUMsRUFBRTtBQUNoQyxZQUFJLFdBQVcsT0FBTztBQUNwQixnQkFBTSxJQUFJO0FBQUEsWUFDUixHQUFHLE1BQU0sMENBRUksTUFBTSx1QkFBdUIsS0FBSztBQUFBLFVBQUE7QUFBQSxRQUVuRDtBQUFBLE1BQ0Y7QUFHQSxlQUFTLElBQUksR0FBRyxJQUFJLFNBQVMsUUFBUSxRQUFRLEtBQUs7QUFDaEQsY0FBTSxTQUFTLFNBQVMsUUFBUSxDQUFDLEVBQUU7QUFDbkMsY0FBTSxTQUFTLFNBQVMsUUFBUSxDQUFDLEVBQUU7QUFDbkMsY0FBTSxRQUFRLE9BQU8sUUFBUSxDQUFDLEVBQUU7QUFDaEMsWUFBSSxXQUFXLE9BQU87QUFDcEIsZ0JBQU0sSUFBSTtBQUFBLFlBQ1IsR0FBRyxNQUFNLG1EQUVZLE1BQU0sdUJBQXVCLE1BQU0sUUFBUSxLQUFLO0FBQUEsVUFBQTtBQUFBLFFBRXpFO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxNQUFNLGtDQUFrQyxNQUFjO0FBQ3BELFVBQU0sU0FBbUIsQ0FBQTtBQUV6QixVQUFNLGNBQWMsTUFBTSxPQUFPLGFBQWE7QUFDNUMsWUFBTSxXQUFXLE1BQU0sS0FBSyxTQUFTLFFBQVE7QUFDN0MsWUFBTSxRQUFRLEtBQUssUUFBUTtBQUkzQixVQUFJLE1BQU0sVUFBVSxZQUFhO0FBRWpDLGFBQU8sS0FBSyxHQUFHLDhCQUE4QixNQUFNLE9BQU8sUUFBUSxDQUFDO0FBQUEsSUFDckUsQ0FBQztBQUVELFFBQUksT0FBTyxTQUFTLEdBQUc7QUFDckIsWUFBTSxJQUFJO0FBQUEsUUFDUjtBQUFBO0FBQUE7QUFBQSxFQUE0RCxPQUN6RCxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxFQUNuQixLQUFLLElBQUksQ0FBQztBQUFBLE1BQUE7QUFBQSxJQUVqQjtBQUFBLEVBQ0Y7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLDJCQUEyQixPQUF3QjtBQUNqRCxVQUFNLE1BQU0sS0FBSyxDQUFDLEdBQUcsTUFBTTtBQUN6QixZQUFNLFFBQVEsRUFBRTtBQUNoQixZQUFNLFFBQVEsRUFBRTtBQUVoQixVQUFJLFFBQVEsT0FBTztBQUNqQixlQUFPO0FBQUEsTUFDVDtBQUVBLFVBQUksUUFBUSxPQUFPO0FBQ2pCLGVBQU87QUFBQSxNQUNUO0FBR0EsYUFBTztBQUFBLElBQ1QsQ0FBQztBQUVELFVBQU0sUUFBUTtBQUNkLFFBQUksT0FBTztBQUFBLE1BQ1Qsc0JBQXNCO0FBQUEsTUFDdEIsb0JBQW9CO0FBQUEsSUFBQSxDQUNyQjtBQUFBLEVBQ0g7QUFDRjtBQ3hYTyxNQUFNLE1BQW9CO0FBQUE7QUFBQTtBQUFBLEVBSS9CLE9BQXNCO0FBQ3BCLFNBQUssVUFBVTtBQUNmLFdBQU8sS0FBSyxNQUFBO0FBQUEsRUFDZDtBQUFBLEVBRUEsUUFBdUI7QUFDckIsU0FBSyxVQUFVO0FBQ2YsV0FBTyxRQUFRLFFBQUE7QUFBQSxFQUNqQjtBQUFBLEVBRUEsSUFBSSxTQUFrQjtBQUNwQixXQUFPLEtBQUs7QUFBQSxFQUNkO0FBQUEsRUFFQSxPQUFPLFVBQVUsWUFBWTtBQUMzQixVQUFNLEtBQUssSUFBSSxNQUFBO0FBQ2YsVUFBTSxHQUFHLEtBQUE7QUFDVCxXQUFPO0FBQUEsRUFDVDtBQUFBO0FBQUE7QUFBQSxFQUlBLFVBQVU7QUFDUixXQUFPLEtBQUssU0FBUztBQUFBLEVBQ3ZCO0FBQUE7QUFBQTtBQUFBLEVBS0EsT0FBd0I7QUFDdEIsV0FBTyxLQUFLLE1BQUE7QUFBQSxFQUNkO0FBQUEsRUFFQSxNQUFNLFVBQVUsU0FBNkM7QUFDM0QsV0FBTyxLQUFLLFdBQVcsT0FBTztBQUFBLEVBQ2hDO0FBQUE7QUFBQTtBQUFBLEVBS0EsTUFBTSxZQUFZLFNBQWtEO0FBQ2xFLFdBQU8sS0FBSyxhQUFhLE9BQU87QUFBQSxFQUNsQztBQUFBO0FBQUE7QUFBQSxFQUtBLFNBQVMsU0FHVztBQUNsQixXQUFPLEtBQUssVUFBVSxPQUFPO0FBQUEsRUFDL0I7QUFBQSxFQUVBLE1BQU0sU0FBUyxPQUFnQztBQUM3QyxVQUFNLFlBQVksS0FBSyxLQUFLLEtBQUs7QUFDakMsUUFBSSxDQUFDLFdBQVc7QUFDZCxZQUFNLElBQUksTUFBTSxVQUFVLEtBQUssYUFBYTtBQUFBLElBQzlDO0FBQ0EsV0FBTyxRQUFRLFFBQVEsVUFBVSxNQUFNLE1BQU07QUFBQSxFQUMvQztBQUFBO0FBQUE7QUFBQSxFQUtBLE1BQU0sU0FBMEM7QUFDOUMsV0FBTyxLQUFLLE9BQU8sT0FBTztBQUFBLEVBQzVCO0FBQUE7QUFBQTtBQUFBLEVBSUEsTUFBTSxZQUFZLFVBQXNDO0FBQ3RELFVBQU0sUUFBUSxLQUFLLEtBQUssUUFBUTtBQUNoQyxXQUFPLFFBQVEsT0FBTztBQUFBLEVBQ3hCO0FBQUEsRUFFQSxvQkFBb0IsU0FBZ0Q7QUFDbEUsV0FBTyxLQUFLLHFCQUFxQixPQUFPO0FBQUEsRUFDMUM7QUFBQSxFQUVBLE1BQU0sZUFBb0M7QUFDeEMsVUFBTSxTQUFTLEtBQUssS0FBSyxVQUFVO0FBQ25DLFdBQU87QUFBQSxFQUNUO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNUTtBQUFBLEVBRUEsV0FBVyxJQUFJLFFBQUE7QUFBQSxFQUNmLFVBQVU7QUFBQSxFQUVWLE9BQWUsSUFBSSxFQUFZO0FBQUE7QUFBQSxFQUd2QyxNQUFjLFFBQVE7QUFDcEIsU0FBSyxXQUFXLElBQUksUUFBUSxJQUFJO0FBQ2hDLFNBQUssZUFBQTtBQUNMLFNBQUssa0JBQUE7QUFDTCxVQUFNLEtBQUssU0FBUyxtQkFBQTtBQUNwQixRQUFJLEtBQUssSUFBSTtBQUViLFNBQUssU0FBUyxRQUFBO0FBQUEsRUFDaEI7QUFBQTtBQUFBLEVBR1EsaUJBQWlCLE1BQU07QUFDN0IsVUFBTSxXQUFXLFFBQVE7QUFFekIsU0FBSyxLQUFLLFlBQVksSUFBSTtBQUFBLE1BQ3hCLE9BQU87QUFBQSxNQUNQLE9BQU8sQ0FBQyxRQUFRO0FBQUEsTUFDaEIsV0FBVyxTQUFTO0FBQUEsSUFBQSxDQUNyQjtBQUFBLEVBQ0g7QUFBQTtBQUFBLEVBR1Esb0JBQW9CO0FBQ3pCLFNBQUssS0FBYSxRQUFRO0FBQzNCLFFBQUksS0FBSyxNQUFNO0FBQUEsTUFDYixzQkFBc0I7QUFBQSxJQUFBLENBQ3ZCO0FBQUEsRUFDSDtBQUFBO0FBQUEsRUFHUSxpQkFBaUIsVUFBb0I7QUFDM0MsVUFBTSxRQUFRLEtBQUssS0FBSyxRQUFRO0FBQ2hDLFVBQU0sUUFBUTtBQUNkLFFBQUksT0FBTyxFQUFFLHNCQUFzQixNQUFBLENBQU87QUFBQSxFQUM1QztBQUFBO0FBQUEsRUFHQSxNQUFjLHFCQUFxQixTQUVqQjtBQUdoQixVQUFNLFdBQVcsUUFBUTtBQUN6QixVQUFNLEtBQUssU0FBUyw4QkFBOEIsUUFBUTtBQUUxRCxVQUFNLEVBQUUsUUFBUTtBQUdoQixVQUFNLFlBQVksSUFBSSxRQUFRO0FBRzlCLFVBQU0saUJBQWlCLE1BQU0sS0FBSyxTQUFTLGVBQWUsR0FBRztBQUc3RCxRQUFJLENBQUMsZ0JBQWdCO0FBQ25CLFdBQUssYUFBYSxXQUFXLEdBQUc7QUFBQSxJQUNsQyxPQUFPO0FBQ0wsV0FBSyxhQUFhLGdCQUFnQixTQUFTO0FBQUEsSUFDN0M7QUFBQSxFQUNGO0FBQUE7QUFBQSxFQUdRLGFBQWEsV0FBcUIsVUFBb0I7QUFFNUQsZ0JBQVksSUFBSSxTQUFTO0FBQ3pCLFNBQUssS0FBSyxVQUFVLE1BQU0sS0FBSyxTQUFTO0FBQ3hDLFNBQUssU0FBUywyQkFBMkIsS0FBSyxLQUFLLFNBQVM7QUFHNUQsVUFBTSxRQUFtQjtBQUFBLE1BQ3ZCLE9BQU8sVUFBVTtBQUFBLE1BQ2pCLE9BQU8sQ0FBQTtBQUFBLE1BQ1AsV0FBVyxVQUFVO0FBQUEsSUFBQTtBQUd2QixTQUFLLEtBQUssUUFBUSxNQUFNLElBQUksS0FBSztBQUdqQyxTQUFLLGlCQUFpQixRQUFRO0FBQzlCLFNBQUssa0JBQUE7QUFBQSxFQUNQO0FBQUE7QUFBQSxFQUdRLGFBQWEsZ0JBQTBCLFdBQXFCO0FBRWxFLFFBQUksZUFBZSxRQUFRLFdBQVcsVUFBVSxRQUFRLFFBQVE7QUFDOUQ7QUFBQSxJQUNGO0FBR0EsZ0JBQVksSUFBSSxTQUFTO0FBQ3pCLFNBQUssS0FBSyxVQUFVLE1BQU0sS0FBSyxTQUFTO0FBQ3hDLFNBQUssU0FBUywyQkFBMkIsS0FBSyxLQUFLLFNBQVM7QUFHNUQsVUFBTSxRQUFRLEtBQUssS0FBSyxVQUFVLEdBQUc7QUFDckMsVUFBTSxZQUFZLFVBQVU7QUFHNUIsU0FBSyxpQkFBaUIsVUFBVSxHQUFHO0FBQ25DLFNBQUssa0JBQUE7QUFBQSxFQUNQO0FBQUE7QUFBQSxFQUlBLE1BQWMsUUFBeUI7QUFDckMsV0FBTyxLQUFLLEtBQUssSUFBSTtBQUFBLEVBQ3ZCO0FBQUE7QUFBQSxFQUdBLE1BQWMsV0FBVyxTQUE2QztBQUNwRSxVQUFNLEtBQUssU0FBUywyQkFBMkIsUUFBUSxLQUFLO0FBRTVELFVBQU0sUUFBUSxLQUFLLEtBQUssUUFBUSxLQUFLO0FBRXJDLFdBQU87QUFBQSxNQUNMLENBQUMsUUFBUSxLQUFLLEdBQUcsS0FBSyxLQUFLO0FBQUEsSUFBQTtBQUFBLEVBRS9CO0FBQUE7QUFBQSxFQUdBLE1BQWMsYUFBYSxTQUFrRDtBQUMzRSxVQUFNLEtBQUssU0FBUywyQkFBMkIsUUFBUSxLQUFLO0FBRTVELFdBQVEsS0FBSyxLQUFLLFFBQVEsS0FBSyxFQUFnQjtBQUFBLEVBQ2pEO0FBQUE7QUFBQSxFQUdBLE1BQWMsT0FBTyxTQUEwQztBQUM3RCxVQUFNLFlBQVksSUFBSSxRQUFRLElBQUk7QUFDbEMsU0FBSyxrQkFBa0IsU0FBUztBQUNoQyxVQUFNLFNBQVMsT0FBTyxLQUFLLFNBQVM7QUFDcEMsUUFBSSxTQUFTO0FBRWIsVUFBTSxLQUFLLFNBQVMsMEJBQTBCLFFBQVEsSUFBSTtBQUMxRCxVQUFNLEtBQUssU0FBUyxrQ0FBa0MsUUFBUSxJQUFJO0FBRWxFLGVBQVcsU0FBUyxRQUFRO0FBQzFCLFVBQUksTUFBTSxXQUFXLEdBQUcsR0FBRztBQUN6QjtBQUFBLE1BQ0Y7QUFFQSxZQUFNLFdBQVcsS0FBSyxLQUFLLEtBQUs7QUFDaEMsWUFBTSxXQUFXLFVBQVUsS0FBSztBQUdoQyxpQkFBVyxRQUFRLFNBQVMsT0FBTztBQUNqQyxjQUFNLE9BQU8sS0FBSztBQUNsQixjQUFNLFNBQVMsU0FBUyxNQUFNLEtBQUssQ0FBQyxNQUFNLEVBQUUsVUFBVSxJQUFJO0FBQzFELFlBQUksQ0FBQyxRQUFRO0FBQ1gsbUJBQVMsTUFBTSxLQUFLLElBQVc7QUFBQSxRQUNqQztBQUFBLE1BQ0Y7QUFFQSxXQUFLLFNBQVMsMkJBQTJCLFFBQVE7QUFBQSxJQUNuRDtBQUdBLFNBQUssa0JBQUE7QUFBQSxFQUNQO0FBQUE7QUFBQSxFQUdBLE1BQWMsVUFBVSxTQUdKO0FBQ2xCLFVBQU0sS0FBSyxTQUFTLDJCQUEyQixRQUFRLEtBQUs7QUFDNUQsVUFBTSxLQUFLLFNBQVM7QUFBQSxNQUNsQixRQUFRO0FBQUEsTUFDUixPQUFPLEtBQUssUUFBUSxLQUFLO0FBQUEsSUFBQTtBQUkzQixVQUFNLFFBQVEsS0FBSyxLQUFLLFFBQVEsS0FBSztBQUdyQyxVQUFNLG9CQUFvQixNQUFNLE1BQU0sT0FBTyxDQUFDLFFBQVE7QUFDcEQsaUJBQVcsVUFBVSxRQUFRLE9BQU87QUFDbEMsY0FBTSxJQUFJLElBQUksTUFBTTtBQUNwQixjQUFNLElBQUksUUFBUSxNQUFNLE1BQU07QUFDOUIsWUFBSSxNQUFNLFFBQVEsTUFBTSxRQUFXO0FBQ2pDLGlCQUFPO0FBQUEsUUFDVDtBQUVBLFlBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxHQUFHO0FBQ2pCLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFDQSxhQUFPO0FBQUEsSUFDVCxDQUFDO0FBR0QsVUFBTSxnQkFBMkI7QUFBQSxNQUMvQixPQUFPLE1BQU07QUFBQSxNQUNiLE9BQU87QUFBQSxJQUFBO0FBR1QsU0FBSyxTQUFTLDJCQUEyQixhQUFhO0FBRXRELFVBQU0sU0FBaUI7QUFBQSxNQUNyQixDQUFDLFFBQVEsS0FBSyxHQUFHO0FBQUEsSUFBQTtBQUduQixXQUFPO0FBQUEsRUFDVDtBQUFBLEVBRUEsa0JBQWtCLFFBQWdCO0FBQ2hDLHNCQUFrQixRQUFRLENBQUMsVUFBVTtBQUNuQyxZQUFNLE9BQU8sT0FBTyxLQUFLLEVBQUU7QUFFM0IsaUJBQVcsT0FBTyxNQUFNO0FBQ3RCLG1CQUFXLE9BQU8sS0FBSztBQUNyQixjQUFJLElBQUksR0FBRyxNQUFNLE1BQU07QUFDckIsbUJBQU8sSUFBSSxHQUFHO0FBQUEsVUFDaEI7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBLElBQ0YsQ0FBQztBQUFBLEVBQ0g7QUFDRjtBQ2hUTyxNQUFNLG1CQUFtQixNQUFtQjtBQUNqRCxTQUFPO0FBQUEsSUFDTCxJQUFJLElBQUksTUFBQTtBQUFBLElBQ1IsV0FBVyxZQUFZO0FBQUEsSUFHdkI7QUFBQSxJQUVBLFlBQVksWUFBWTtBQUFBLElBRXhCO0FBQUEsSUFDQSxXQUFXLFlBQVk7QUFBQSxJQUV2QjtBQUFBLElBRUEsVUFBVSxZQUFZO0FBQUEsSUFFdEI7QUFBQSxFQUFBO0FBRUo7QUMwQk8sTUFBTSxZQUNYO0FDNUVLLE1BQU0sZUFBaUM7QUFBQSxFQU81QyxZQUFvQixLQUFTO0FBQVQsU0FBQSxNQUFBO0FBQUEsRUFBVTtBQUFBLEVBTnRCLG9DQUNGLElBQUE7QUFBQSxFQUVOLFlBQXFCO0FBQUEsRUFDckIsZUFBd0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBV3hCLEdBQUcsV0FBNEIsVUFBMEM7QUFDdkUsUUFBSSxDQUFDLEtBQUssY0FBYyxJQUFJLFNBQVMsR0FBRztBQUN0QyxXQUFLLGNBQWMsSUFBSSxXQUFXLENBQUEsQ0FBRTtBQUFBLElBQ3RDO0FBQ0EsU0FBSyxjQUFjLElBQUksU0FBUyxFQUFHLEtBQUssUUFBUTtBQUNoRCxXQUFPO0FBQUEsRUFDVDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBUUEsVUFBZ0I7QUFDZCxTQUFLLFlBQVk7QUFDakIsU0FBSyxlQUFlO0FBRXBCLFVBQU0sWUFBWSxLQUFLLGNBQWMsSUFBSSxTQUFTLEtBQUssQ0FBQTtBQUN2RCxlQUFXLE1BQU0sV0FBVztBQUMxQixTQUFHLENBQUEsQ0FBRTtBQUFBLElBQ1A7QUFBQSxFQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFRQSxhQUFtQjtBQUNqQixTQUFLLFlBQVk7QUFDakIsU0FBSyxlQUFlO0FBRXBCLFVBQU0sWUFBWSxLQUFLLGNBQWMsSUFBSSxZQUFZLEtBQUssQ0FBQTtBQUMxRCxlQUFXLE1BQU0sV0FBVztBQUMxQixTQUFHLENBQUEsQ0FBRTtBQUFBLElBQ1A7QUFBQSxFQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVNBLEtBQUssY0FBK0IsTUFBc0I7QUFDeEQsVUFBTSxLQUFNLEtBQUssSUFBWSxTQUFTO0FBQ3RDLFFBQUksT0FBTyxPQUFPLFlBQVk7QUFDNUIsWUFBTSxJQUFJLE1BQU0sU0FBUyxVQUFVLFNBQUEsQ0FBVSxnQkFBZ0I7QUFBQSxJQUMvRDtBQUNBLFVBQU0sS0FBSyxLQUFLLEtBQUssU0FBUyxDQUFDO0FBQy9CLE9BQUcsTUFBTSxLQUFLLEtBQUssS0FBSyxNQUFNLEdBQUcsRUFBRSxDQUFDLEVBQ2pDLEtBQUssQ0FBQyxXQUFXO0FBQ2hCLFNBQUcsUUFBUSxJQUFJO0FBQUEsSUFDakIsQ0FBQyxFQUNBLE1BQU0sQ0FBQyxRQUFRO0FBQ2QsU0FBRyxNQUFNLEdBQUc7QUFBQSxJQUNkLENBQUM7QUFFSCxXQUFPO0FBQUEsRUFDVDtBQUNGO0FDNUJPLE1BQU0sa0JBQWtCLENBQUMsV0FBZ0M7QUFDOUQsUUFBTSxTQUFzQixDQUFBO0FBSTVCLG9CQUFrQixRQUFRLENBQUMsZUFBZSxVQUFVO0FBQ2xELFVBQU0sYUFBb0QsQ0FBQTtBQUMxRCxXQUFPLGFBQWEsSUFBSTtBQUN4QixlQUFXLFlBQVksTUFBTSxPQUFPO0FBQ2xDLGlCQUFXLFNBQVMsS0FBSyxJQUFJLENBQUE7QUFBQSxJQUMvQjtBQUFBLEVBQ0YsQ0FBQztBQUlELG9CQUFrQixRQUFRLENBQUMsZ0JBQWdCLGdCQUFnQjtBQUV6RCxlQUFXLGtCQUFrQixZQUFZLE9BQU87QUFHOUMsY0FBUSxZQUFZLE9BQUE7QUFBQSxRQUNsQixLQUFLO0FBQ0gsOEJBQW9CLGdCQUFnQixnQkFBZ0IsTUFBTTtBQUMxRDtBQUFBLFFBRUYsS0FBSyxVQUFVO0FBQ2IsMEJBQWdCLGdCQUFnQixnQkFBZ0IsTUFBTTtBQUN0RDtBQUFBLFFBQ0Y7QUFBQSxRQUVBLEtBQUssWUFBWTtBQUVmO0FBQUEsUUFDRjtBQUFBLFFBRUEsS0FBSyxTQUFTO0FBQ1oseUJBQWUsZ0JBQWdCLGdCQUFnQixNQUFNO0FBQ3JEO0FBQUEsUUFDRjtBQUFBLFFBRUEsS0FBSyxXQUFXO0FBQ2QsMkJBQWlCLGdCQUFnQixnQkFBZ0IsTUFBTTtBQUN2RDtBQUFBLFFBQ0Y7QUFBQSxNQUFBO0FBQUEsSUFFSjtBQUFBLEVBQ0YsQ0FBQztBQUVELFNBQU87QUFDVDtBQUtBLE1BQU0sc0JBQXNCLENBQzFCLGlCQUNBLFdBQ0EsV0FDRztBQUNILFFBQU0sZ0JBQWdCLFVBQVU7QUFFaEMsYUFBVyxvQkFBb0IsV0FBVztBQUN4QyxRQUFJLGlCQUFpQixXQUFXLEdBQUcsR0FBRztBQUNwQztBQUFBLElBQ0Y7QUFFQSxRQUFJLENBQUMsaUJBQWlCLFNBQVMsS0FBSyxHQUFHO0FBQ3JDO0FBQUEsSUFDRjtBQUVBLFVBQU0saUJBQWlCLGlCQUFpQixNQUFNLEdBQUcsRUFBRTtBQUNuRCxVQUFNLGVBQWUsVUFBVSxnQkFBZ0I7QUFFL0M7QUFBQSxNQUNFO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLElBQUE7QUFBQSxFQUVKO0FBQ0Y7QUFHQSxNQUFNLGtCQUFrQixDQUN0QixpQkFDQSxXQUNBLFdBQ0c7QUFDSCxRQUFNLGlCQUFpQixVQUFVO0FBQ2pDLFFBQU0sZ0JBQWdCLFVBQVU7QUFFaEMsYUFBVyxXQUFXLFVBQVUsS0FBSztBQUNuQyxRQUFJLFFBQVEsV0FBVyxHQUFHLEdBQUc7QUFDM0I7QUFBQSxJQUNGO0FBRUEsVUFBTSxZQUFZLFVBQVUsSUFBSSxPQUFPO0FBRXZDLFdBQU8sUUFBUSxnQkFBZ0IsV0FBVyxpQkFBaUIsYUFBYTtBQUFBLEVBQzFFO0FBQ0Y7QUFHQSxNQUFNLGlCQUFpQixDQUNyQixpQkFDQSxXQUNBLFdBQ0c7QUFDSCxRQUFNLGdCQUFnQixVQUFVO0FBRWhDLGFBQVcsU0FBUyxVQUFVLFFBQVE7QUFDcEMsVUFBTSxpQkFBaUI7QUFDdkIsVUFBTSxlQUFlLFVBQVUsT0FBTyxLQUFLO0FBQzNDO0FBQUEsTUFDRTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxJQUFBO0FBQUEsRUFFSjtBQUNGO0FBR0EsTUFBTSxtQkFBbUIsQ0FDdkIsaUJBQ0EsV0FDQSxXQUNHO0FBQ0gsUUFBTSxnQkFBZ0IsVUFBVTtBQUVoQyxhQUFXLFFBQVEsVUFBVSxPQUFPO0FBQ2xDLFVBQU0saUJBQWlCLEtBQUs7QUFDNUIsVUFBTSxlQUFlLEtBQUs7QUFDMUI7QUFBQSxNQUNFO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLElBQUE7QUFBQSxFQUVKO0FBQ0Y7QUFHQSxNQUFNLFNBQVMsQ0FDYixRQUNBLGdCQUNBLGNBQ0EsaUJBQ0Esa0JBQ0c7QUFDSCxRQUFNLDBCQUEyQixPQUFPLGNBQWMsTUFBTSxDQUFBO0FBQzVELFFBQU0sNkJBQThCLHdCQUF3QixZQUFZLE1BQ3RFLENBQUE7QUFFRiw2QkFBMkIsZUFBZSxNQUFNLENBQUE7QUFDaEQsNkJBQTJCLGVBQWUsRUFBRSxhQUFhLE1BQU0sQ0FBQTtBQUNqRTtBQ3BOTyxNQUFNLFdBQTZCO0FBQUEsRUFDakMsWUFBcUI7QUFBQSxFQUNyQixlQUF3QjtBQUFBLEVBRXZCLGlDQUNGLElBQUE7QUFBQSxFQUNFLHFDQUdBLElBQUE7QUFBQSxFQUVSLFVBQWdCO0FBQ2QsUUFBSSxDQUFDLEtBQUssV0FBVztBQUNuQixXQUFLLFlBQVk7QUFDakIsV0FBSyxlQUFlO0FBQ3BCLFdBQUssS0FBSyxTQUFTO0FBQUEsSUFDckI7QUFBQSxFQUNGO0FBQUEsRUFFQSxhQUFtQjtBQUNqQixRQUFJLEtBQUssV0FBVztBQUNsQixXQUFLLFlBQVk7QUFDakIsV0FBSyxlQUFlO0FBQ3BCLFdBQUssS0FBSyxZQUFZO0FBQUEsSUFDeEI7QUFBQSxFQUNGO0FBQUEsRUFFQSxHQUFHLFdBQTRCLFVBQTBDO0FBQ3ZFLFFBQUksQ0FBQyxLQUFLLFdBQVcsSUFBSSxTQUFTLEdBQUc7QUFDbkMsV0FBSyxXQUFXLElBQUksV0FBVyxDQUFBLENBQUU7QUFBQSxJQUNuQztBQUNBLFNBQUssV0FBVyxJQUFJLFNBQVMsRUFBRyxLQUFLLFFBQVE7QUFDN0MsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVBLEtBQUssV0FBNEIsVUFBMEM7QUFDekUsUUFBSSxDQUFDLEtBQUssZUFBZSxJQUFJLFNBQVMsR0FBRztBQUN2QyxXQUFLLGVBQWUsSUFBSSxXQUFXLENBQUEsQ0FBRTtBQUFBLElBQ3ZDO0FBQ0EsU0FBSyxlQUFlLElBQUksU0FBUyxFQUFHLEtBQUssUUFBUTtBQUNqRCxXQUFPO0FBQUEsRUFDVDtBQUFBLEVBRUEsSUFBSSxXQUE0QixVQUEyQztBQUN6RSxRQUFJLFVBQVU7QUFFWixZQUFNLG1CQUFtQixLQUFLLFdBQVcsSUFBSSxTQUFTO0FBQ3RELFVBQUksa0JBQWtCO0FBQ3BCLGNBQU0sUUFBUSxpQkFBaUIsUUFBUSxRQUFRO0FBQy9DLFlBQUksUUFBUSxJQUFJO0FBQ2QsMkJBQWlCLE9BQU8sT0FBTyxDQUFDO0FBQUEsUUFDbEM7QUFBQSxNQUNGO0FBRUEsWUFBTSxnQkFBZ0IsS0FBSyxlQUFlLElBQUksU0FBUztBQUN2RCxVQUFJLGVBQWU7QUFDakIsY0FBTSxRQUFRLGNBQWMsUUFBUSxRQUFRO0FBQzVDLFlBQUksUUFBUSxJQUFJO0FBQ2Qsd0JBQWMsT0FBTyxPQUFPLENBQUM7QUFBQSxRQUMvQjtBQUFBLE1BQ0Y7QUFBQSxJQUNGLE9BQU87QUFFTCxXQUFLLFdBQVcsT0FBTyxTQUFTO0FBQ2hDLFdBQUssZUFBZSxPQUFPLFNBQVM7QUFBQSxJQUN0QztBQUNBLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFQSxLQUFLLGNBQStCLE1BQXNCO0FBQ3hELFFBQUksZUFBZTtBQUduQixVQUFNLG1CQUFtQixLQUFLLFdBQVcsSUFBSSxTQUFTO0FBQ3RELFFBQUksb0JBQW9CLGlCQUFpQixTQUFTLEdBQUc7QUFDbkQscUJBQWU7QUFFZixPQUFDLEdBQUcsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLGFBQWE7QUFDMUMsWUFBSTtBQUNGLG1CQUFTLEdBQUcsSUFBSTtBQUFBLFFBQ2xCLFNBQVMsT0FBTztBQUVkLGtCQUFRO0FBQUEsWUFDTiwrQkFBK0IsT0FBTyxTQUFTLENBQUM7QUFBQSxZQUNoRDtBQUFBLFVBQUE7QUFBQSxRQUVKO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDSDtBQUdBLFVBQU0sZ0JBQWdCLEtBQUssZUFBZSxJQUFJLFNBQVM7QUFDdkQsUUFBSSxpQkFBaUIsY0FBYyxTQUFTLEdBQUc7QUFDN0MscUJBQWU7QUFFZixZQUFNLGtCQUFrQixDQUFDLEdBQUcsYUFBYTtBQUN6QyxXQUFLLGVBQWUsT0FBTyxTQUFTO0FBRXBDLHNCQUFnQixRQUFRLENBQUMsYUFBYTtBQUNwQyxZQUFJO0FBQ0YsbUJBQVMsR0FBRyxJQUFJO0FBQUEsUUFDbEIsU0FBUyxPQUFPO0FBQ2Qsa0JBQVE7QUFBQSxZQUNOLG9DQUFvQyxPQUFPLFNBQVMsQ0FBQztBQUFBLFlBQ3JEO0FBQUEsVUFBQTtBQUFBLFFBRUo7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNIO0FBRUEsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVBLG1CQUFtQixXQUFtQztBQUNwRCxRQUFJLGNBQWMsUUFBVztBQUMzQixXQUFLLFdBQVcsT0FBTyxTQUFTO0FBQ2hDLFdBQUssZUFBZSxPQUFPLFNBQVM7QUFBQSxJQUN0QyxPQUFPO0FBQ0wsV0FBSyxXQUFXLE1BQUE7QUFDaEIsV0FBSyxlQUFlLE1BQUE7QUFBQSxJQUN0QjtBQUNBLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFQSxjQUFjLFdBQW9DO0FBQ2hELFVBQU0sZUFBZSxLQUFLLFdBQVcsSUFBSSxTQUFTLEdBQUcsVUFBVTtBQUMvRCxVQUFNLFlBQVksS0FBSyxlQUFlLElBQUksU0FBUyxHQUFHLFVBQVU7QUFDaEUsV0FBTyxlQUFlO0FBQUEsRUFDeEI7QUFBQSxFQUVBLFVBQVUsV0FBNkQ7QUFDckUsVUFBTSxtQkFBbUIsS0FBSyxXQUFXLElBQUksU0FBUyxLQUFLLENBQUE7QUFDM0QsVUFBTSxnQkFBZ0IsS0FBSyxlQUFlLElBQUksU0FBUyxLQUFLLENBQUE7QUFDNUQsV0FBTyxDQUFDLEdBQUcsa0JBQWtCLEdBQUcsYUFBYTtBQUFBLEVBQy9DO0FBQUEsRUFFQSxhQUFxQztBQUNuQyxVQUFNLGdDQUFnQixJQUFJO0FBQUEsTUFDeEIsR0FBRyxLQUFLLFdBQVcsS0FBQTtBQUFBLE1BQ25CLEdBQUcsS0FBSyxlQUFlLEtBQUE7QUFBQSxJQUFLLENBQzdCO0FBQ0QsV0FBTyxNQUFNLEtBQUssU0FBUztBQUFBLEVBQzdCO0FBQUE7QUFBQSxFQUdBLFFBQWM7QUFDWixTQUFLLFlBQVk7QUFDakIsU0FBSyxlQUFlO0FBQ3BCLFNBQUssbUJBQUE7QUFBQSxFQUNQO0FBQUEsRUFFQSxjQUFjLE9BQW9CO0FBQ2hDLFNBQUssS0FBSyxTQUFTLEtBQUs7QUFBQSxFQUMxQjtBQUFBLEVBRUEsZ0JBQWdCLFNBQW9CO0FBQ2xDLFNBQUssS0FBSyxXQUFXLE9BQU87QUFBQSxFQUM5QjtBQUFBO0FBQUEsRUFHQSxlQUFzRTtBQUNwRSxXQUFPLElBQUksSUFBSSxLQUFLLFVBQVU7QUFBQSxFQUNoQztBQUFBLEVBRUEsbUJBQTBFO0FBQ3hFLFdBQU8sSUFBSSxJQUFJLEtBQUssY0FBYztBQUFBLEVBQ3BDO0FBQ0Y7QUM5Sk8sTUFBTSxnQkFBZ0IsT0FBZTtBQUFBLEVBQzFDLFdBQVc7QUFBQSxFQUNYLGNBQWM7QUFBQSxFQUNkLFVBQVU7QUFDUixTQUFLLFlBQVk7QUFDakIsU0FBSyxlQUFlO0FBQ3BCLFNBQUssS0FBSyxTQUFTO0FBQUEsRUFDckI7QUFBQSxFQUNBLGFBQWE7QUFDWCxTQUFLLFlBQVk7QUFDakIsU0FBSyxlQUFlO0FBQ3BCLFNBQUssS0FBSyxZQUFZO0FBQUEsRUFDeEI7QUFBQTtBQUFBLEVBRUEsS0FBSztBQUVILFdBQU87QUFBQSxFQUNUO0FBQUE7QUFBQSxFQUVBLE9BQU87QUFFTCxXQUFPO0FBQUEsRUFDVDtBQUNGOyJ9
1719
+ //# sourceMappingURL=io.js.map