@gmod/bbi 1.0.27 → 1.0.31

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/bbi.js CHANGED
@@ -1,485 +1,324 @@
1
1
  "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (_) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
8
53
  exports.BBI = void 0;
9
-
10
- var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
-
12
- var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
-
14
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
15
-
16
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
17
-
18
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
19
-
20
- var _binaryParser = require("@gmod/binary-parser");
21
-
22
- var _genericFilehandle = require("generic-filehandle");
23
-
24
- var _rxjs = require("rxjs");
25
-
26
- var _operators = require("rxjs/operators");
27
-
28
- var _blockView = require("./blockView");
29
-
30
- var _util = require("./util");
31
-
32
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
33
-
34
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
35
-
54
+ var binary_parser_1 = require("@gmod/binary-parser");
55
+ var generic_filehandle_1 = require("generic-filehandle");
56
+ var rxjs_1 = require("rxjs");
57
+ var operators_1 = require("rxjs/operators");
58
+ var abortable_promise_cache_1 = __importDefault(require("abortable-promise-cache"));
59
+ var quick_lru_1 = __importDefault(require("quick-lru"));
60
+ var blockView_1 = require("./blockView");
36
61
  var BIG_WIG_MAGIC = -2003829722;
37
62
  var BIG_BED_MAGIC = -2021002517;
38
-
39
- /* A class that provides memoization for abortable calls */
40
- var AbortAwareCache =
41
- /*#__PURE__*/
42
- function () {
43
- function AbortAwareCache() {
44
- (0, _classCallCheck2.default)(this, AbortAwareCache);
45
- (0, _defineProperty2.default)(this, "cache", new Map());
46
- }
47
-
48
- (0, _createClass2.default)(AbortAwareCache, [{
49
- key: "abortableMemoize",
50
-
51
- /*
52
- * Takes a function that has one argument, abortSignal, that returns a promise
53
- * and it works by retrying the function if a previous attempt to initialize the parse cache was aborted
54
- * @param fn - an AbortableCallback
55
- * @return a memoized version of the AbortableCallback using the AbortAwareCache
56
- */
57
- value: function abortableMemoize(fn) {
58
- var cache = this.cache;
59
- return function abortableMemoizeFn(signal) {
60
- if (!cache.has(fn)) {
61
- var fnReturn = fn(signal);
62
- cache.set(fn, fnReturn);
63
-
64
- if (signal) {
65
- fnReturn.catch(function () {
66
- if (signal.aborted) cache.delete(fn);
67
- });
68
- }
69
-
70
- return cache.get(fn);
71
- }
72
-
73
- return cache.get(fn).catch(function (e) {
74
- if (e.code === 'ERR_ABORTED' || e.name === 'AbortError') {
75
- return fn(signal);
76
- }
77
-
78
- throw e;
79
- });
80
- };
81
- }
82
- }]);
83
- return AbortAwareCache;
84
- }();
85
63
  /* get the compiled parsers for different sections of the bigwig file
86
64
  *
87
65
  * @param isBE - is big endian, typically false
88
66
  * @return an object with compiled parsers
89
67
  */
90
-
91
-
92
68
  function getParsers(isBE) {
93
- var le = isBE ? 'big' : 'little';
94
- var headerParser = new _binaryParser.Parser().endianess(le).int32('magic').uint16('version').uint16('numZoomLevels').uint64('chromTreeOffset').uint64('unzoomedDataOffset').uint64('unzoomedIndexOffset').uint16('fieldCount').uint16('definedFieldCount').uint64('asOffset') // autoSql offset, used in bigbed
95
- .uint64('totalSummaryOffset').uint32('uncompressBufSize').uint64('extHeaderOffset') // name index offset, used in bigbed
96
- .array('zoomLevels', {
97
- length: 'numZoomLevels',
98
- type: new _binaryParser.Parser().uint32('reductionLevel').uint32('reserved').uint64('dataOffset').uint64('indexOffset')
99
- });
100
- var totalSummaryParser = new _binaryParser.Parser().endianess(le).uint64('basesCovered').double('scoreMin').double('scoreMax').double('scoreSum').double('scoreSumSquares');
101
- var chromTreeParser = new _binaryParser.Parser().endianess(le).uint32('magic').uint32('blockSize').uint32('keySize').uint32('valSize').uint64('itemCount');
102
- var isLeafNode = new _binaryParser.Parser().endianess(le).uint8('isLeafNode').skip(1).uint16('cnt');
103
- return {
104
- chromTreeParser: chromTreeParser,
105
- totalSummaryParser: totalSummaryParser,
106
- headerParser: headerParser,
107
- isLeafNode: isLeafNode
108
- };
109
- }
110
-
111
- var BBI =
112
- /*#__PURE__*/
113
- function () {
114
- /* fetch and parse header information from a bigwig or bigbed file
115
- * @param abortSignal - abort the operation, can be null
116
- * @return a Header object
117
- */
118
-
119
- /*
120
- * @param filehandle - a filehandle from generic-filehandle or implementing something similar to the node10 fs.promises API
121
- * @param path - a Local file path as a string
122
- * @param url - a URL string
123
- * @param renameRefSeqs - an optional method to rename the internal reference sequences using a mapping function
124
- */
125
- function BBI() {
126
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
127
- (0, _classCallCheck2.default)(this, BBI);
128
- (0, _defineProperty2.default)(this, "bbi", void 0);
129
- (0, _defineProperty2.default)(this, "headerCache", void 0);
130
- (0, _defineProperty2.default)(this, "renameRefSeqs", void 0);
131
- (0, _defineProperty2.default)(this, "getHeader", void 0);
132
- var filehandle = options.filehandle,
133
- renameRefSeqs = options.renameRefSeqs,
134
- path = options.path,
135
- url = options.url;
136
-
137
- this.renameRefSeqs = renameRefSeqs || function (s) {
138
- return s;
69
+ var le = isBE ? 'big' : 'little';
70
+ var headerParser = new binary_parser_1.Parser()
71
+ .endianess(le)
72
+ .int32('magic')
73
+ .uint16('version')
74
+ .uint16('numZoomLevels')
75
+ .uint64('chromTreeOffset')
76
+ .uint64('unzoomedDataOffset')
77
+ .uint64('unzoomedIndexOffset')
78
+ .uint16('fieldCount')
79
+ .uint16('definedFieldCount')
80
+ .uint64('asOffset') // autoSql offset, used in bigbed
81
+ .uint64('totalSummaryOffset')
82
+ .uint32('uncompressBufSize')
83
+ .uint64('extHeaderOffset') // name index offset, used in bigbed
84
+ .array('zoomLevels', {
85
+ length: 'numZoomLevels',
86
+ type: new binary_parser_1.Parser()
87
+ .uint32('reductionLevel')
88
+ .uint32('reserved')
89
+ .uint64('dataOffset')
90
+ .uint64('indexOffset'),
91
+ });
92
+ var totalSummaryParser = new binary_parser_1.Parser()
93
+ .endianess(le)
94
+ .uint64('basesCovered')
95
+ .double('scoreMin')
96
+ .double('scoreMax')
97
+ .double('scoreSum')
98
+ .double('scoreSumSquares');
99
+ var chromTreeParser = new binary_parser_1.Parser()
100
+ .endianess(le)
101
+ .uint32('magic')
102
+ .uint32('blockSize')
103
+ .uint32('keySize')
104
+ .uint32('valSize')
105
+ .uint64('itemCount');
106
+ var isLeafNode = new binary_parser_1.Parser()
107
+ .endianess(le)
108
+ .uint8('isLeafNode')
109
+ .skip(1)
110
+ .uint16('cnt');
111
+ return {
112
+ chromTreeParser: chromTreeParser,
113
+ totalSummaryParser: totalSummaryParser,
114
+ headerParser: headerParser,
115
+ isLeafNode: isLeafNode,
139
116
  };
140
-
141
- this.headerCache = new AbortAwareCache();
142
-
143
- if (filehandle) {
144
- this.bbi = filehandle;
145
- } else if (url) {
146
- this.bbi = new _genericFilehandle.RemoteFile(url);
147
- } else if (path) {
148
- this.bbi = new _genericFilehandle.LocalFile(path);
149
- } else {
150
- throw new Error('no file given');
151
- }
152
-
153
- this.getHeader = this.headerCache.abortableMemoize(this._getHeader.bind(this));
154
- }
155
-
156
- (0, _createClass2.default)(BBI, [{
157
- key: "_getHeader",
158
- value: function () {
159
- var _getHeader2 = (0, _asyncToGenerator2.default)(
160
- /*#__PURE__*/
161
- _regenerator.default.mark(function _callee(abortSignal) {
162
- var header, chroms;
163
- return _regenerator.default.wrap(function _callee$(_context) {
164
- while (1) {
165
- switch (_context.prev = _context.next) {
166
- case 0:
167
- _context.next = 2;
168
- return this._getMainHeader(abortSignal);
169
-
170
- case 2:
171
- header = _context.sent;
172
- _context.next = 5;
173
- return this._readChromTree(header, abortSignal);
174
-
175
- case 5:
176
- chroms = _context.sent;
177
- return _context.abrupt("return", _objectSpread({}, header, {}, chroms));
178
-
179
- case 7:
180
- case "end":
181
- return _context.stop();
182
- }
183
- }
184
- }, _callee, this);
185
- }));
186
-
187
- function _getHeader(_x) {
188
- return _getHeader2.apply(this, arguments);
189
- }
190
-
191
- return _getHeader;
192
- }()
193
- }, {
194
- key: "_getMainHeader",
195
- value: function () {
196
- var _getMainHeader2 = (0, _asyncToGenerator2.default)(
197
- /*#__PURE__*/
198
- _regenerator.default.mark(function _callee2(abortSignal) {
199
- var requestSize,
200
- _ref,
201
- buffer,
202
- isBigEndian,
203
- ret,
204
- header,
205
- tail,
206
- _args2 = arguments;
207
-
208
- return _regenerator.default.wrap(function _callee2$(_context2) {
209
- while (1) {
210
- switch (_context2.prev = _context2.next) {
211
- case 0:
212
- requestSize = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : 2000;
213
- _context2.next = 3;
214
- return this.bbi.read(Buffer.alloc(requestSize), 0, requestSize, 0, {
215
- signal: abortSignal
117
+ }
118
+ var BBI = /** @class */ (function () {
119
+ /*
120
+ * @param filehandle - a filehandle from generic-filehandle or implementing something similar to the node10 fs.promises API
121
+ * @param path - a Local file path as a string
122
+ * @param url - a URL string
123
+ * @param renameRefSeqs - an optional method to rename the internal reference sequences using a mapping function
124
+ */
125
+ function BBI(options) {
126
+ var _this = this;
127
+ if (options === void 0) { options = {}; }
128
+ this.headerCache = new abortable_promise_cache_1.default({
129
+ cache: new quick_lru_1.default({ maxSize: 1 }),
130
+ fill: function (params, signal) { return __awaiter(_this, void 0, void 0, function () {
131
+ return __generator(this, function (_a) {
132
+ return [2 /*return*/, this._getHeader(__assign(__assign({}, params), { signal: signal }))];
216
133
  });
217
-
218
- case 3:
219
- _ref = _context2.sent;
220
- buffer = _ref.buffer;
221
- isBigEndian = this._isBigEndian(buffer);
222
- ret = getParsers(isBigEndian);
223
- header = ret.headerParser.parse(buffer).result;
224
- header.fileType = header.magic === BIG_BED_MAGIC ? 'bigbed' : 'bigwig';
225
-
226
- if (!(header.asOffset > requestSize || header.totalSummaryOffset > requestSize)) {
227
- _context2.next = 11;
228
- break;
229
- }
230
-
231
- return _context2.abrupt("return", this._getMainHeader(abortSignal, requestSize * 2));
232
-
233
- case 11:
234
- if (header.asOffset) {
235
- header.autoSql = buffer.slice(header.asOffset, buffer.indexOf(0, header.asOffset)).toString('utf8');
236
- }
237
-
238
- if (!(header.totalSummaryOffset > requestSize)) {
239
- _context2.next = 14;
240
- break;
241
- }
242
-
243
- return _context2.abrupt("return", this._getMainHeader(abortSignal, requestSize * 2));
244
-
245
- case 14:
246
- if (header.totalSummaryOffset) {
247
- tail = buffer.slice(header.totalSummaryOffset);
248
- header.totalSummary = ret.totalSummaryParser.parse(tail).result;
134
+ }); },
135
+ });
136
+ var filehandle = options.filehandle, renameRefSeqs = options.renameRefSeqs, path = options.path, url = options.url;
137
+ this.renameRefSeqs = renameRefSeqs || (function (s) { return s; });
138
+ if (filehandle) {
139
+ this.bbi = filehandle;
140
+ }
141
+ else if (url) {
142
+ this.bbi = new generic_filehandle_1.RemoteFile(url);
143
+ }
144
+ else if (path) {
145
+ this.bbi = new generic_filehandle_1.LocalFile(path);
146
+ }
147
+ else {
148
+ throw new Error('no file given');
149
+ }
150
+ }
151
+ /* fetch and parse header information from a bigwig or bigbed file
152
+ * @param abortSignal - abort the operation, can be null
153
+ * @return a Header object
154
+ */
155
+ BBI.prototype.getHeader = function (opts) {
156
+ if (opts === void 0) { opts = {}; }
157
+ var options = 'aborted' in opts ? { signal: opts } : opts;
158
+ return this.headerCache.get(JSON.stringify(options), options, options.signal);
159
+ };
160
+ BBI.prototype._getHeader = function (opts) {
161
+ return __awaiter(this, void 0, void 0, function () {
162
+ var header, chroms;
163
+ return __generator(this, function (_a) {
164
+ switch (_a.label) {
165
+ case 0: return [4 /*yield*/, this._getMainHeader(opts)];
166
+ case 1:
167
+ header = _a.sent();
168
+ return [4 /*yield*/, this._readChromTree(header, opts)];
169
+ case 2:
170
+ chroms = _a.sent();
171
+ return [2 /*return*/, __assign(__assign({}, header), chroms)];
249
172
  }
250
-
251
- return _context2.abrupt("return", _objectSpread({}, header, {
252
- isBigEndian: isBigEndian
253
- }));
254
-
255
- case 16:
256
- case "end":
257
- return _context2.stop();
258
- }
259
- }
260
- }, _callee2, this);
261
- }));
262
-
263
- function _getMainHeader(_x2) {
264
- return _getMainHeader2.apply(this, arguments);
265
- }
266
-
267
- return _getMainHeader;
268
- }()
269
- }, {
270
- key: "_isBigEndian",
271
- value: function _isBigEndian(buffer) {
272
- var ret = buffer.readInt32LE(0);
273
-
274
- if (ret === BIG_WIG_MAGIC || ret === BIG_BED_MAGIC) {
275
- return false;
276
- }
277
-
278
- ret = buffer.readInt32BE(0);
279
-
280
- if (ret === BIG_WIG_MAGIC || ret === BIG_BED_MAGIC) {
281
- return true;
282
- }
283
-
284
- throw new Error('not a BigWig/BigBed file');
285
- } // todo: add progress if long running
286
-
287
- }, {
288
- key: "_readChromTree",
289
- value: function () {
290
- var _readChromTree2 = (0, _asyncToGenerator2.default)(
291
- /*#__PURE__*/
292
- _regenerator.default.mark(function _callee4(header, abortSignal) {
293
- var _this = this;
294
-
295
- var isBE, le, refsByNumber, refsByName, chromTreeOffset, unzoomedDataOffset, _ref2, data, p, keySize, leafNodeParser, nonleafNodeParser, rootNodeOffset, bptReadNode;
296
-
297
- return _regenerator.default.wrap(function _callee4$(_context4) {
298
- while (1) {
299
- switch (_context4.prev = _context4.next) {
300
- case 0:
301
- isBE = header.isBigEndian;
302
- le = isBE ? 'big' : 'little';
303
- refsByNumber = [];
304
- refsByName = {};
305
- chromTreeOffset = header.chromTreeOffset;
306
- unzoomedDataOffset = header.unzoomedDataOffset;
307
-
308
- while (unzoomedDataOffset % 4 !== 0) {
309
- unzoomedDataOffset += 1;
173
+ });
174
+ });
175
+ };
176
+ BBI.prototype._getMainHeader = function (opts, requestSize) {
177
+ if (requestSize === void 0) { requestSize = 2000; }
178
+ return __awaiter(this, void 0, void 0, function () {
179
+ var buffer, isBigEndian, ret, header, tail;
180
+ return __generator(this, function (_a) {
181
+ switch (_a.label) {
182
+ case 0: return [4 /*yield*/, this.bbi.read(Buffer.alloc(requestSize), 0, requestSize, 0, opts)];
183
+ case 1:
184
+ buffer = (_a.sent()).buffer;
185
+ isBigEndian = this._isBigEndian(buffer);
186
+ ret = getParsers(isBigEndian);
187
+ header = ret.headerParser.parse(buffer).result;
188
+ header.fileType = header.magic === BIG_BED_MAGIC ? 'bigbed' : 'bigwig';
189
+ if (header.asOffset > requestSize ||
190
+ header.totalSummaryOffset > requestSize) {
191
+ return [2 /*return*/, this._getMainHeader(opts, requestSize * 2)];
192
+ }
193
+ if (header.asOffset) {
194
+ header.autoSql = buffer
195
+ .slice(header.asOffset, buffer.indexOf(0, header.asOffset))
196
+ .toString('utf8');
197
+ }
198
+ if (header.totalSummaryOffset > requestSize) {
199
+ return [2 /*return*/, this._getMainHeader(opts, requestSize * 2)];
200
+ }
201
+ if (header.totalSummaryOffset) {
202
+ tail = buffer.slice(header.totalSummaryOffset);
203
+ header.totalSummary = ret.totalSummaryParser.parse(tail).result;
204
+ }
205
+ return [2 /*return*/, __assign(__assign({}, header), { isBigEndian: isBigEndian })];
310
206
  }
311
-
312
- _context4.next = 9;
313
- return this.bbi.read(Buffer.alloc(unzoomedDataOffset - chromTreeOffset), 0, unzoomedDataOffset - chromTreeOffset, chromTreeOffset, {
314
- signal: abortSignal
315
- });
316
-
317
- case 9:
318
- _ref2 = _context4.sent;
319
- data = _ref2.buffer;
320
- p = getParsers(isBE);
321
- keySize = p.chromTreeParser.parse(data).result.keySize;
322
- leafNodeParser = new _binaryParser.Parser().endianess(le).string('key', {
323
- stripNull: true,
324
- length: keySize
325
- }).uint32('refId').uint32('refSize');
326
- nonleafNodeParser = new _binaryParser.Parser().endianess(le).skip(keySize).uint64('childOffset');
327
- rootNodeOffset = 32;
328
-
329
- bptReadNode =
330
- /*#__PURE__*/
331
- function () {
332
- var _ref3 = (0, _asyncToGenerator2.default)(
333
- /*#__PURE__*/
334
- _regenerator.default.mark(function _callee3(currentOffset) {
335
- var offset, ret, _ret$result, isLeafNode, cnt, n, leafRet, _leafRet$result, _key, refId, refSize, refRec, nextNodes, _n, nonleafRet, childOffset;
336
-
337
- return _regenerator.default.wrap(function _callee3$(_context3) {
338
- while (1) {
339
- switch (_context3.prev = _context3.next) {
340
- case 0:
341
- offset = currentOffset;
342
-
343
- if (!(offset >= data.length)) {
344
- _context3.next = 3;
345
- break;
346
- }
347
-
348
- throw new Error('reading beyond end of buffer');
349
-
350
- case 3:
351
- ret = p.isLeafNode.parse(data.slice(offset));
352
- _ret$result = ret.result, isLeafNode = _ret$result.isLeafNode, cnt = _ret$result.cnt;
353
- offset += ret.offset;
354
- _context3.next = 8;
355
- return (0, _util.abortBreakPoint)(abortSignal);
356
-
357
- case 8:
358
- if (!isLeafNode) {
359
- _context3.next = 12;
360
- break;
361
- }
362
-
363
- for (n = 0; n < cnt; n += 1) {
364
- leafRet = leafNodeParser.parse(data.slice(offset));
365
- offset += leafRet.offset;
366
- _leafRet$result = leafRet.result, _key = _leafRet$result.key, refId = _leafRet$result.refId, refSize = _leafRet$result.refSize;
367
- refRec = {
368
- name: _key,
369
- id: refId,
370
- length: refSize
371
- };
372
- refsByName[_this.renameRefSeqs(_key)] = refId;
373
- refsByNumber[refId] = refRec;
374
- }
375
-
376
- _context3.next = 16;
377
- break;
378
-
379
- case 12:
380
- // parse index node
381
- nextNodes = [];
382
-
383
- for (_n = 0; _n < cnt; _n += 1) {
384
- nonleafRet = nonleafNodeParser.parse(data.slice(offset));
385
- childOffset = nonleafRet.result.childOffset;
386
- offset += nonleafRet.offset;
387
- childOffset -= chromTreeOffset;
388
- nextNodes.push(bptReadNode(childOffset));
389
- }
390
-
391
- _context3.next = 16;
392
- return Promise.all(nextNodes);
393
-
394
- case 16:
395
- case "end":
396
- return _context3.stop();
207
+ });
208
+ });
209
+ };
210
+ BBI.prototype._isBigEndian = function (buffer) {
211
+ var ret = buffer.readInt32LE(0);
212
+ if (ret === BIG_WIG_MAGIC || ret === BIG_BED_MAGIC) {
213
+ return false;
214
+ }
215
+ ret = buffer.readInt32BE(0);
216
+ if (ret === BIG_WIG_MAGIC || ret === BIG_BED_MAGIC) {
217
+ return true;
218
+ }
219
+ throw new Error('not a BigWig/BigBed file');
220
+ };
221
+ // todo: add progress if long running
222
+ BBI.prototype._readChromTree = function (header, opts) {
223
+ return __awaiter(this, void 0, void 0, function () {
224
+ var isBE, le, refsByNumber, refsByName, chromTreeOffset, unzoomedDataOffset, data, p, keySize, leafNodeParser, nonleafNodeParser, rootNodeOffset, bptReadNode;
225
+ var _this = this;
226
+ return __generator(this, function (_a) {
227
+ switch (_a.label) {
228
+ case 0:
229
+ isBE = header.isBigEndian;
230
+ le = isBE ? 'big' : 'little';
231
+ refsByNumber = [];
232
+ refsByName = {};
233
+ chromTreeOffset = header.chromTreeOffset;
234
+ unzoomedDataOffset = header.unzoomedDataOffset;
235
+ while (unzoomedDataOffset % 4 !== 0) {
236
+ unzoomedDataOffset += 1;
397
237
  }
398
- }
399
- }, _callee3);
400
- }));
401
-
402
- return function bptReadNode(_x5) {
403
- return _ref3.apply(this, arguments);
404
- };
405
- }();
406
-
407
- _context4.next = 19;
408
- return bptReadNode(rootNodeOffset);
409
-
410
- case 19:
411
- return _context4.abrupt("return", {
412
- refsByName: refsByName,
413
- refsByNumber: refsByNumber
414
- });
415
-
416
- case 20:
417
- case "end":
418
- return _context4.stop();
419
- }
420
- }
421
- }, _callee4, this);
422
- }));
423
-
424
- function _readChromTree(_x3, _x4) {
425
- return _readChromTree2.apply(this, arguments);
426
- }
427
-
428
- return _readChromTree;
429
- }()
238
+ return [4 /*yield*/, this.bbi.read(Buffer.alloc(unzoomedDataOffset - chromTreeOffset), 0, unzoomedDataOffset - chromTreeOffset, chromTreeOffset, opts)];
239
+ case 1:
240
+ data = (_a.sent()).buffer;
241
+ p = getParsers(isBE);
242
+ keySize = p.chromTreeParser.parse(data).result.keySize;
243
+ leafNodeParser = new binary_parser_1.Parser()
244
+ .endianess(le)
245
+ .string('key', { stripNull: true, length: keySize })
246
+ .uint32('refId')
247
+ .uint32('refSize');
248
+ nonleafNodeParser = new binary_parser_1.Parser()
249
+ .endianess(le)
250
+ .skip(keySize)
251
+ .uint64('childOffset');
252
+ rootNodeOffset = 32;
253
+ bptReadNode = function (currentOffset) { return __awaiter(_this, void 0, void 0, function () {
254
+ var offset, ret, _a, isLeafNode, cnt, n, leafRet, _b, key, refId, refSize, refRec, nextNodes, n, nonleafRet, childOffset;
255
+ return __generator(this, function (_c) {
256
+ switch (_c.label) {
257
+ case 0:
258
+ offset = currentOffset;
259
+ if (offset >= data.length) {
260
+ throw new Error('reading beyond end of buffer');
261
+ }
262
+ ret = p.isLeafNode.parse(data.slice(offset));
263
+ _a = ret.result, isLeafNode = _a.isLeafNode, cnt = _a.cnt;
264
+ offset += ret.offset;
265
+ if (!isLeafNode) return [3 /*break*/, 1];
266
+ for (n = 0; n < cnt; n += 1) {
267
+ leafRet = leafNodeParser.parse(data.slice(offset));
268
+ offset += leafRet.offset;
269
+ _b = leafRet.result, key = _b.key, refId = _b.refId, refSize = _b.refSize;
270
+ refRec = { name: key, id: refId, length: refSize };
271
+ refsByName[this.renameRefSeqs(key)] = refId;
272
+ refsByNumber[refId] = refRec;
273
+ }
274
+ return [3 /*break*/, 3];
275
+ case 1:
276
+ nextNodes = [];
277
+ for (n = 0; n < cnt; n += 1) {
278
+ nonleafRet = nonleafNodeParser.parse(data.slice(offset));
279
+ childOffset = nonleafRet.result.childOffset;
280
+ offset += nonleafRet.offset;
281
+ childOffset -= chromTreeOffset;
282
+ nextNodes.push(bptReadNode(childOffset));
283
+ }
284
+ return [4 /*yield*/, Promise.all(nextNodes)];
285
+ case 2:
286
+ _c.sent();
287
+ _c.label = 3;
288
+ case 3: return [2 /*return*/];
289
+ }
290
+ });
291
+ }); };
292
+ return [4 /*yield*/, bptReadNode(rootNodeOffset)];
293
+ case 2:
294
+ _a.sent();
295
+ return [2 /*return*/, {
296
+ refsByName: refsByName,
297
+ refsByNumber: refsByNumber,
298
+ }];
299
+ }
300
+ });
301
+ });
302
+ };
430
303
  /*
431
304
  * fetches the "unzoomed" view of the bigwig data. this is the default for bigbed
432
305
  * @param abortSignal - a signal to optionally abort this operation
433
306
  */
434
-
435
- }, {
436
- key: "getUnzoomedView",
437
- value: function () {
438
- var _getUnzoomedView = (0, _asyncToGenerator2.default)(
439
- /*#__PURE__*/
440
- _regenerator.default.mark(function _callee5(abortSignal) {
441
- var _ref4, unzoomedIndexOffset, zoomLevels, refsByName, uncompressBufSize, isBigEndian, fileType, nzl, cirLen;
442
-
443
- return _regenerator.default.wrap(function _callee5$(_context5) {
444
- while (1) {
445
- switch (_context5.prev = _context5.next) {
446
- case 0:
447
- _context5.next = 2;
448
- return this.getHeader(abortSignal);
449
-
450
- case 2:
451
- _ref4 = _context5.sent;
452
- unzoomedIndexOffset = _ref4.unzoomedIndexOffset;
453
- zoomLevels = _ref4.zoomLevels;
454
- refsByName = _ref4.refsByName;
455
- uncompressBufSize = _ref4.uncompressBufSize;
456
- isBigEndian = _ref4.isBigEndian;
457
- fileType = _ref4.fileType;
458
- nzl = zoomLevels[0];
459
- cirLen = nzl ? nzl.dataOffset - unzoomedIndexOffset : 4000;
460
- return _context5.abrupt("return", new _blockView.BlockView(this.bbi, refsByName, unzoomedIndexOffset, cirLen, isBigEndian, uncompressBufSize > 0, fileType));
461
-
462
- case 12:
463
- case "end":
464
- return _context5.stop();
465
- }
466
- }
467
- }, _callee5, this);
468
- }));
469
-
470
- function getUnzoomedView(_x6) {
471
- return _getUnzoomedView.apply(this, arguments);
472
- }
473
-
474
- return getUnzoomedView;
475
- }()
476
- /*
477
- * abstract method - get the view for a given scale
478
- */
479
-
480
- }, {
481
- key: "getFeatureStream",
482
-
307
+ BBI.prototype.getUnzoomedView = function (opts) {
308
+ return __awaiter(this, void 0, void 0, function () {
309
+ var _a, unzoomedIndexOffset, zoomLevels, refsByName, uncompressBufSize, isBigEndian, fileType, nzl, cirLen;
310
+ return __generator(this, function (_b) {
311
+ switch (_b.label) {
312
+ case 0: return [4 /*yield*/, this.getHeader(opts)];
313
+ case 1:
314
+ _a = _b.sent(), unzoomedIndexOffset = _a.unzoomedIndexOffset, zoomLevels = _a.zoomLevels, refsByName = _a.refsByName, uncompressBufSize = _a.uncompressBufSize, isBigEndian = _a.isBigEndian, fileType = _a.fileType;
315
+ nzl = zoomLevels[0];
316
+ cirLen = nzl ? nzl.dataOffset - unzoomedIndexOffset : 4000;
317
+ return [2 /*return*/, new blockView_1.BlockView(this.bbi, refsByName, unzoomedIndexOffset, cirLen, isBigEndian, uncompressBufSize > 0, fileType)];
318
+ }
319
+ });
320
+ });
321
+ };
483
322
  /**
484
323
  * Gets features from a BigWig file
485
324
  *
@@ -488,136 +327,65 @@ function () {
488
327
  * @param end - The end of a region
489
328
  * @param opts - An object containing basesPerSpan (e.g. pixels per basepair) or scale used to infer the zoomLevel to use
490
329
  */
491
- value: function () {
492
- var _getFeatureStream = (0, _asyncToGenerator2.default)(
493
- /*#__PURE__*/
494
- _regenerator.default.mark(function _callee6(refName, start, end) {
495
- var opts,
496
- chrName,
497
- view,
498
- _args6 = arguments;
499
- return _regenerator.default.wrap(function _callee6$(_context6) {
500
- while (1) {
501
- switch (_context6.prev = _context6.next) {
502
- case 0:
503
- opts = _args6.length > 3 && _args6[3] !== undefined ? _args6[3] : {
504
- scale: 1
505
- };
506
- _context6.next = 3;
507
- return this.getHeader(opts.signal);
508
-
509
- case 3:
510
- chrName = this.renameRefSeqs(refName);
511
-
512
- if (!opts.basesPerSpan) {
513
- _context6.next = 10;
514
- break;
515
- }
516
-
517
- _context6.next = 7;
518
- return this.getView(1 / opts.basesPerSpan, opts.signal);
519
-
520
- case 7:
521
- view = _context6.sent;
522
- _context6.next = 19;
523
- break;
524
-
525
- case 10:
526
- if (!opts.scale) {
527
- _context6.next = 16;
528
- break;
330
+ BBI.prototype.getFeatureStream = function (refName, start, end, opts) {
331
+ if (opts === void 0) { opts = {
332
+ scale: 1,
333
+ }; }
334
+ return __awaiter(this, void 0, void 0, function () {
335
+ var chrName, view;
336
+ return __generator(this, function (_a) {
337
+ switch (_a.label) {
338
+ case 0: return [4 /*yield*/, this.getHeader(opts)];
339
+ case 1:
340
+ _a.sent();
341
+ chrName = this.renameRefSeqs(refName);
342
+ if (!opts.basesPerSpan) return [3 /*break*/, 3];
343
+ return [4 /*yield*/, this.getView(1 / opts.basesPerSpan, opts)];
344
+ case 2:
345
+ view = _a.sent();
346
+ return [3 /*break*/, 7];
347
+ case 3:
348
+ if (!opts.scale) return [3 /*break*/, 5];
349
+ return [4 /*yield*/, this.getView(opts.scale, opts)];
350
+ case 4:
351
+ view = _a.sent();
352
+ return [3 /*break*/, 7];
353
+ case 5: return [4 /*yield*/, this.getView(1, opts)];
354
+ case 6:
355
+ view = _a.sent();
356
+ _a.label = 7;
357
+ case 7:
358
+ if (!view) {
359
+ throw new Error('unable to get block view for data');
360
+ }
361
+ return [2 /*return*/, new rxjs_1.Observable(function (observer) {
362
+ view.readWigData(chrName, start, end, observer, opts);
363
+ })];
529
364
  }
530
-
531
- _context6.next = 13;
532
- return this.getView(opts.scale, opts.signal);
533
-
534
- case 13:
535
- view = _context6.sent;
536
- _context6.next = 19;
537
- break;
538
-
539
- case 16:
540
- _context6.next = 18;
541
- return this.getView(1, opts.signal);
542
-
543
- case 18:
544
- view = _context6.sent;
545
-
546
- case 19:
547
- if (view) {
548
- _context6.next = 21;
549
- break;
365
+ });
366
+ });
367
+ };
368
+ BBI.prototype.getFeatures = function (refName, start, end, opts) {
369
+ if (opts === void 0) { opts = {
370
+ scale: 1,
371
+ }; }
372
+ return __awaiter(this, void 0, void 0, function () {
373
+ var ob, ret;
374
+ return __generator(this, function (_a) {
375
+ switch (_a.label) {
376
+ case 0: return [4 /*yield*/, this.getFeatureStream(refName, start, end, opts)];
377
+ case 1:
378
+ ob = _a.sent();
379
+ return [4 /*yield*/, ob
380
+ .pipe((0, operators_1.reduce)(function (acc, curr) { return acc.concat(curr); }))
381
+ .toPromise()];
382
+ case 2:
383
+ ret = _a.sent();
384
+ return [2 /*return*/, ret || []];
550
385
  }
551
-
552
- throw new Error('unable to get block view for data');
553
-
554
- case 21:
555
- return _context6.abrupt("return", new _rxjs.Observable(function (observer) {
556
- view.readWigData(chrName, start, end, observer, opts);
557
- }));
558
-
559
- case 22:
560
- case "end":
561
- return _context6.stop();
562
- }
563
- }
564
- }, _callee6, this);
565
- }));
566
-
567
- function getFeatureStream(_x7, _x8, _x9) {
568
- return _getFeatureStream.apply(this, arguments);
569
- }
570
-
571
- return getFeatureStream;
572
- }()
573
- }, {
574
- key: "getFeatures",
575
- value: function () {
576
- var _getFeatures = (0, _asyncToGenerator2.default)(
577
- /*#__PURE__*/
578
- _regenerator.default.mark(function _callee7(refName, start, end) {
579
- var opts,
580
- ob,
581
- ret,
582
- _args7 = arguments;
583
- return _regenerator.default.wrap(function _callee7$(_context7) {
584
- while (1) {
585
- switch (_context7.prev = _context7.next) {
586
- case 0:
587
- opts = _args7.length > 3 && _args7[3] !== undefined ? _args7[3] : {
588
- scale: 1
589
- };
590
- _context7.next = 3;
591
- return this.getFeatureStream(refName, start, end, opts);
592
-
593
- case 3:
594
- ob = _context7.sent;
595
- _context7.next = 6;
596
- return ob.pipe((0, _operators.reduce)(function (acc, curr) {
597
- return acc.concat(curr);
598
- })).toPromise();
599
-
600
- case 6:
601
- ret = _context7.sent;
602
- return _context7.abrupt("return", ret || []);
603
-
604
- case 8:
605
- case "end":
606
- return _context7.stop();
607
- }
608
- }
609
- }, _callee7, this);
610
- }));
611
-
612
- function getFeatures(_x10, _x11, _x12) {
613
- return _getFeatures.apply(this, arguments);
614
- }
615
-
616
- return getFeatures;
617
- }()
618
- }]);
619
- return BBI;
620
- }();
621
-
386
+ });
387
+ });
388
+ };
389
+ return BBI;
390
+ }());
622
391
  exports.BBI = BBI;
623
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9iYmkudHMiXSwibmFtZXMiOlsiQklHX1dJR19NQUdJQyIsIkJJR19CRURfTUFHSUMiLCJBYm9ydEF3YXJlQ2FjaGUiLCJNYXAiLCJmbiIsImNhY2hlIiwiYWJvcnRhYmxlTWVtb2l6ZUZuIiwic2lnbmFsIiwiaGFzIiwiZm5SZXR1cm4iLCJzZXQiLCJjYXRjaCIsImFib3J0ZWQiLCJkZWxldGUiLCJnZXQiLCJlIiwiY29kZSIsIm5hbWUiLCJnZXRQYXJzZXJzIiwiaXNCRSIsImxlIiwiaGVhZGVyUGFyc2VyIiwiUGFyc2VyIiwiZW5kaWFuZXNzIiwiaW50MzIiLCJ1aW50MTYiLCJ1aW50NjQiLCJ1aW50MzIiLCJhcnJheSIsImxlbmd0aCIsInR5cGUiLCJ0b3RhbFN1bW1hcnlQYXJzZXIiLCJkb3VibGUiLCJjaHJvbVRyZWVQYXJzZXIiLCJpc0xlYWZOb2RlIiwidWludDgiLCJza2lwIiwiQkJJIiwib3B0aW9ucyIsImZpbGVoYW5kbGUiLCJyZW5hbWVSZWZTZXFzIiwicGF0aCIsInVybCIsInMiLCJoZWFkZXJDYWNoZSIsImJiaSIsIlJlbW90ZUZpbGUiLCJMb2NhbEZpbGUiLCJFcnJvciIsImdldEhlYWRlciIsImFib3J0YWJsZU1lbW9pemUiLCJfZ2V0SGVhZGVyIiwiYmluZCIsImFib3J0U2lnbmFsIiwiX2dldE1haW5IZWFkZXIiLCJoZWFkZXIiLCJfcmVhZENocm9tVHJlZSIsImNocm9tcyIsInJlcXVlc3RTaXplIiwicmVhZCIsIkJ1ZmZlciIsImFsbG9jIiwiYnVmZmVyIiwiaXNCaWdFbmRpYW4iLCJfaXNCaWdFbmRpYW4iLCJyZXQiLCJwYXJzZSIsInJlc3VsdCIsImZpbGVUeXBlIiwibWFnaWMiLCJhc09mZnNldCIsInRvdGFsU3VtbWFyeU9mZnNldCIsImF1dG9TcWwiLCJzbGljZSIsImluZGV4T2YiLCJ0b1N0cmluZyIsInRhaWwiLCJ0b3RhbFN1bW1hcnkiLCJyZWFkSW50MzJMRSIsInJlYWRJbnQzMkJFIiwicmVmc0J5TnVtYmVyIiwicmVmc0J5TmFtZSIsImNocm9tVHJlZU9mZnNldCIsInVuem9vbWVkRGF0YU9mZnNldCIsImRhdGEiLCJwIiwia2V5U2l6ZSIsImxlYWZOb2RlUGFyc2VyIiwic3RyaW5nIiwic3RyaXBOdWxsIiwibm9ubGVhZk5vZGVQYXJzZXIiLCJyb290Tm9kZU9mZnNldCIsImJwdFJlYWROb2RlIiwiY3VycmVudE9mZnNldCIsIm9mZnNldCIsImNudCIsIm4iLCJsZWFmUmV0Iiwia2V5IiwicmVmSWQiLCJyZWZTaXplIiwicmVmUmVjIiwiaWQiLCJuZXh0Tm9kZXMiLCJub25sZWFmUmV0IiwiY2hpbGRPZmZzZXQiLCJwdXNoIiwiUHJvbWlzZSIsImFsbCIsInVuem9vbWVkSW5kZXhPZmZzZXQiLCJ6b29tTGV2ZWxzIiwidW5jb21wcmVzc0J1ZlNpemUiLCJuemwiLCJjaXJMZW4iLCJkYXRhT2Zmc2V0IiwiQmxvY2tWaWV3IiwicmVmTmFtZSIsInN0YXJ0IiwiZW5kIiwib3B0cyIsInNjYWxlIiwiY2hyTmFtZSIsImJhc2VzUGVyU3BhbiIsImdldFZpZXciLCJ2aWV3IiwiT2JzZXJ2YWJsZSIsIm9ic2VydmVyIiwicmVhZFdpZ0RhdGEiLCJnZXRGZWF0dXJlU3RyZWFtIiwib2IiLCJwaXBlIiwiYWNjIiwiY3VyciIsImNvbmNhdCIsInRvUHJvbWlzZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOzs7Ozs7QUFFQSxJQUFNQSxhQUFhLEdBQUcsQ0FBQyxVQUF2QjtBQUNBLElBQU1DLGFBQWEsR0FBRyxDQUFDLFVBQXZCOztBQTJDQTtJQUNNQyxlOzs7OztpREFDeUMsSUFBSUMsR0FBSixFOzs7Ozs7QUFFN0M7Ozs7OztxQ0FNd0JDLEUsRUFBb0Y7QUFBQSxVQUNsR0MsS0FEa0csR0FDeEYsSUFEd0YsQ0FDbEdBLEtBRGtHO0FBRTFHLGFBQU8sU0FBU0Msa0JBQVQsQ0FBNEJDLE1BQTVCLEVBQWdFO0FBQ3JFLFlBQUksQ0FBQ0Ys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RixrQkFBQUEsSUFBSSxDQUFDRyxXQUFMLENBQWlCTixPQUFqQixFQUEwQkosS0FBMUIsRUFBaUNDLEdBQWpDLEVBQXNDUSxRQUF0QyxFQUFnRFAsSUFBaEQ7QUFDRCxpQkFGTSxDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7a0RBTVBILE8sRUFDQUMsSyxFQUNBQyxHOzs7Ozs7Ozs7QUFDQUMsZ0JBQUFBLEksOERBQXdFO0FBQUVDLGtCQUFBQSxLQUFLLEVBQUU7QUFBVCxpQjs7dUJBRXZELEtBQUtRLGdCQUFMLENBQXNCWixPQUF0QixFQUErQkMsS0FBL0IsRUFBc0NDLEdBQXRDLEVBQTJDQyxJQUEzQyxDOzs7QUFBWFUsZ0JBQUFBLEU7O3VCQUNZQSxFQUFFLENBQUNDLElBQUgsQ0FBUSx1QkFBTyxVQUFDQyxHQUFELEVBQWlCQyxJQUFqQjtBQUFBLHlCQUFnREQsR0FBRyxDQUFDRSxNQUFKLENBQVdELElBQVgsQ0FBaEQ7QUFBQSxpQkFBUCxDQUFSLEVBQWtGRSxTQUFsRixFOzs7QUFBWnJFLGdCQUFBQSxHO2tEQUNDQSxHQUFHLElBQUksRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcnNlciB9IGZyb20gJ0BnbW9kL2JpbmFyeS1wYXJzZXInXG5pbXBvcnQgeyBMb2NhbEZpbGUsIFJlbW90ZUZpbGUsIEdlbmVyaWNGaWxlaGFuZGxlIH0gZnJvbSAnZ2VuZXJpYy1maWxlaGFuZGxlJ1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgT2JzZXJ2ZXIgfSBmcm9tICdyeGpzJ1xuaW1wb3J0IHsgcmVkdWNlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnXG5cbmltcG9ydCB7IEJsb2NrVmlldyB9IGZyb20gJy4vYmxvY2tWaWV3J1xuaW1wb3J0IHsgYWJvcnRCcmVha1BvaW50LCBBYm9ydEVycm9yIH0gZnJvbSAnLi91dGlsJ1xuXG5jb25zdCBCSUdfV0lHX01BR0lDID0gLTIwMDM4Mjk3MjJcbmNvbnN0IEJJR19CRURfTUFHSUMgPSAtMjAyMTAwMjUxN1xuXG5leHBvcnQgaW50ZXJmYWNlIEZlYXR1cmUge1xuICBzdGFydDogbnVtYmVyXG4gIGVuZDogbnVtYmVyXG4gIHNjb3JlOiBudW1iZXJcbiAgcmVzdD86IHN0cmluZyAvLyBmb3IgYmlnYmVkIGxpbmVcbiAgbWluU2NvcmU/OiBudW1iZXIgLy8gZm9yIHN1bW1hcnkgbGluZVxuICBtYXhTY29yZT86IG51bWJlciAvLyBmb3Igc3VtbWFyeSBsaW5lXG4gIHN1bW1hcnk/OiBib29sZWFuIC8vIGlzIHN1bW1hcnkgbGluZVxuICB1bmlxdWVJZD86IHN0cmluZyAvLyBmb3IgYmlnYmVkIGNvbnRhaW5zIHVuaXF1ZUlkIGNhbGN1bGF0ZWQgZnJvbSBmaWxlIG9mZnNldFxuICBmaWVsZD86IG51bWJlciAvLyB1c2VkIGluIGJpZ2JlZCBzZWFyY2hpbmdcbn1cbmludGVyZmFjZSBTdGF0aXN0aWNzIHtcbiAgc2NvcmVTdW06IG51bWJlclxuICBiYXNlc0NvdmVyZWQ6IG51bWJlclxuICBzY29yZVN1bVNxdWFyZXM6IG51bWJlclxufVxuXG5pbnRlcmZhY2UgUmVmSW5mbyB7XG4gIG5hbWU6IHN0cmluZ1xuICBpZDogbnVtYmVyXG4gIGxlbmd0aDogbnVtYmVyXG59XG5leHBvcnQgaW50ZXJmYWNlIEhlYWRlciB7XG4gIGF1dG9TcWw6IHN0cmluZ1xuICB0b3RhbFN1bW1hcnk6IFN0YXRpc3RpY3NcbiAgem9vbUxldmVsczogYW55XG4gIHVuem9vbWVkSW5kZXhPZmZzZXQ6IG51bWJlclxuICB1bnpvb21lZERhdGFPZmZzZXQ6IG51bWJlclxuICBkZWZpbmVkRmllbGRDb3VudDogbnVtYmVyXG4gIHVuY29tcHJlc3NCdWZTaXplOiBudW1iZXJcbiAgY2hyb21UcmVlT2Zmc2V0OiBudW1iZXJcbiAgZmlsZVNpemU6IG51bWJlclxuICBleHRIZWFkZXJPZmZzZXQ6IG51bWJlclxuICBpc0JpZ0VuZGlhbjogYm9vbGVhblxuICBmaWxlVHlwZTogc3RyaW5nXG4gIHJlZnNCeU5hbWU6IE1hcDxzdHJpbmcsIG51bWJlcj5cbiAgcmVmc0J5TnVtYmVyOiBNYXA8bnVtYmVyLCBSZWZJbmZvPlxufVxuXG50eXBlIEFib3J0YWJsZUNhbGxiYWNrID0gKHNpZ25hbDogQWJvcnRTaWduYWwpID0+IFByb21pc2U8YW55PlxuXG4vKiBBIGNsYXNzIHRoYXQgcHJvdmlkZXMgbWVtb2l6YXRpb24gZm9yIGFib3J0YWJsZSBjYWxscyAqL1xuY2xhc3MgQWJvcnRBd2FyZUNhY2hlIHtcbiAgcHJpdmF0ZSBjYWNoZTogTWFwPEFib3J0YWJsZUNhbGxiYWNrLCBhbnk+ID0gbmV3IE1hcCgpXG5cbiAgLypcbiAgICogVGFrZXMgYSBmdW5jdGlvbiB0aGF0IGhhcyBvbmUgYXJndW1lbnQsIGFib3J0U2lnbmFsLCB0aGF0IHJldHVybnMgYSBwcm9taXNlXG4gICAqIGFuZCBpdCB3b3JrcyBieSByZXRyeWluZyB0aGUgZnVuY3Rpb24gaWYgYSBwcmV2aW91cyBhdHRlbXB0IHRvIGluaXRpYWxpemUgdGhlIHBhcnNlIGNhY2hlIHdhcyBhYm9ydGVkXG4gICAqIEBwYXJhbSBmbiAtIGFuIEFib3J0YWJsZUNhbGxiYWNrXG4gICAqIEByZXR1cm4gYSBtZW1vaXplZCB2ZXJzaW9uIG9mIHRoZSBBYm9ydGFibGVDYWxsYmFjayB1c2luZyB0aGUgQWJvcnRBd2FyZUNhY2hlXG4gICAqL1xuICBwdWJsaWMgYWJvcnRhYmxlTWVtb2l6ZShmbjogKHNpZ25hbD86IEFib3J0U2lnbmFsKSA9PiBQcm9taXNlPGFueT4pOiAoc2lnbmFsPzogQWJvcnRTaWduYWwpID0+IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgeyBjYWNoZSB9ID0gdGhpc1xuICAgIHJldHVybiBmdW5jdGlvbiBhYm9ydGFibGVNZW1vaXplRm4oc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPGFueT4ge1xuICAgICAgaWYgKCFjYWNoZS5oYXMoZm4pKSB7XG4gICAgICAgIGNvbnN0IGZuUmV0dXJuID0gZm4oc2lnbmFsKVxuICAgICAgICBjYWNoZS5zZXQoZm4sIGZuUmV0dXJuKVxuICAgICAgICBpZiAoc2lnbmFsKSB7XG4gICAgICAgICAgZm5SZXR1cm4uY2F0Y2goKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgaWYgKHNpZ25hbC5hYm9ydGVkKSBjYWNoZS5kZWxldGUoZm4pXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FjaGUuZ2V0KGZuKVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNhY2hlLmdldChmbikuY2F0Y2goXG4gICAgICAgIChlOiBBYm9ydEVycm9yIHwgRE9NRXhjZXB0aW9uKTogUHJvbWlzZTxhbnk+ID0+IHtcbiAgICAgICAgICBpZiAoZS5jb2RlID09PSAnRVJSX0FCT1JURUQnIHx8IGUubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAgICAgICAgICByZXR1cm4gZm4oc2lnbmFsKVxuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlXG4gICAgICAgIH0sXG4gICAgICApXG4gICAgfVxuICB9XG59XG5cbi8qIGdldCB0aGUgY29tcGlsZWQgcGFyc2VycyBmb3IgZGlmZmVyZW50IHNlY3Rpb25zIG9mIHRoZSBiaWd3aWcgZmlsZVxuICpcbiAqIEBwYXJhbSBpc0JFIC0gaXMgYmlnIGVuZGlhbiwgdHlwaWNhbGx5IGZhbHNlXG4gKiBAcmV0dXJuIGFuIG9iamVjdCB3aXRoIGNvbXBpbGVkIHBhcnNlcnNcbiAqL1xuZnVuY3Rpb24gZ2V0UGFyc2Vycyhpc0JFOiBib29sZWFuKTogYW55IHtcbiAgY29uc3QgbGUgPSBpc0JFID8gJ2JpZycgOiAnbGl0dGxlJ1xuICBjb25zdCBoZWFkZXJQYXJzZXIgPSBuZXcgUGFyc2VyKClcbiAgICAuZW5kaWFuZXNzKGxlKVxuICAgIC5pbnQzMignbWFnaWMnKVxuICAgIC51aW50MTYoJ3ZlcnNpb24nKVxuICAgIC51aW50MTYoJ251bVpvb21MZXZlbHMnKVxuICAgIC51aW50NjQoJ2Nocm9tVHJlZU9mZnNldCcpXG4gICAgLnVpbnQ2NCgndW56b29tZWREYXRhT2Zmc2V0JylcbiAgICAudWludDY0KCd1bnpvb21lZEluZGV4T2Zmc2V0JylcbiAgICAudWludDE2KCdmaWVsZENvdW50JylcbiAgICAudWludDE2KCdkZWZpbmVkRmllbGRDb3VudCcpXG4gICAgLnVpbnQ2NCgnYXNPZmZzZXQnKSAvLyBhdXRvU3FsIG9mZnNldCwgdXNlZCBpbiBiaWdiZWRcbiAgICAudWludDY0KCd0b3RhbFN1bW1hcnlPZmZzZXQnKVxuICAgIC51aW50MzIoJ3VuY29tcHJlc3NCdWZTaXplJylcbiAgICAudWludDY0KCdleHRIZWFkZXJPZmZzZXQnKSAvLyBuYW1lIGluZGV4IG9mZnNldCwgdXNlZCBpbiBiaWdiZWRcbiAgICAuYXJyYXkoJ3pvb21MZXZlbHMnLCB7XG4gICAgICBsZW5ndGg6ICdudW1ab29tTGV2ZWxzJyxcbiAgICAgIHR5cGU6IG5ldyBQYXJzZXIoKVxuICAgICAgICAudWludDMyKCdyZWR1Y3Rpb25MZXZlbCcpXG4gICAgICAgIC51aW50MzIoJ3Jlc2VydmVkJylcbiAgICAgICAgLnVpbnQ2NCgnZGF0YU9mZnNldCcpXG4gICAgICAgIC51aW50NjQoJ2luZGV4T2Zmc2V0JyksXG4gICAgfSlcblxuICBjb25zdCB0b3RhbFN1bW1hcnlQYXJzZXIgPSBuZXcgUGFyc2VyKClcbiAgICAuZW5kaWFuZXNzKGxlKVxuICAgIC51aW50NjQoJ2Jhc2VzQ292ZXJlZCcpXG4gICAgLmRvdWJsZSgnc2NvcmVNaW4nKVxuICAgIC5kb3VibGUoJ3Njb3JlTWF4JylcbiAgICAuZG91YmxlKCdzY29yZVN1bScpXG4gICAgLmRvdWJsZSgnc2NvcmVTdW1TcXVhcmVzJylcblxuICBjb25zdCBjaHJvbVRyZWVQYXJzZXIgPSBuZXcgUGFyc2VyKClcbiAgICAuZW5kaWFuZXNzKGxlKVxuICAgIC51aW50MzIoJ21hZ2ljJylcbiAgICAudWludDMyKCdibG9ja1NpemUnKVxuICAgIC51aW50MzIoJ2tleVNpemUnKVxuICAgIC51aW50MzIoJ3ZhbFNpemUnKVxuICAgIC51aW50NjQoJ2l0ZW1Db3VudCcpXG5cbiAgY29uc3QgaXNMZWFmTm9kZSA9IG5ldyBQYXJzZXIoKVxuICAgIC5lbmRpYW5lc3MobGUpXG4gICAgLnVpbnQ4KCdpc0xlYWZOb2RlJylcbiAgICAuc2tpcCgxKVxuICAgIC51aW50MTYoJ2NudCcpXG5cbiAgcmV0dXJuIHtcbiAgICBjaHJvbVRyZWVQYXJzZXIsXG4gICAgdG90YWxTdW1tYXJ5UGFyc2VyLFxuICAgIGhlYWRlclBhcnNlcixcbiAgICBpc0xlYWZOb2RlLFxuICB9XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCQkkge1xuICBwcm90ZWN0ZWQgYmJpOiBHZW5lcmljRmlsZWhhbmRsZVxuXG4gIHByb3RlY3RlZCBoZWFkZXJDYWNoZTogQWJvcnRBd2FyZUNhY2hlXG5cbiAgcHJvdGVjdGVkIHJlbmFtZVJlZlNlcXM6IChhOiBzdHJpbmcpID0+IHN0cmluZ1xuXG4gIC8qIGZldGNoIGFuZCBwYXJzZSBoZWFkZXIgaW5mb3JtYXRpb24gZnJvbSBhIGJpZ3dpZyBvciBiaWdiZWQgZmlsZVxuICAgKiBAcGFyYW0gYWJvcnRTaWduYWwgLSBhYm9ydCB0aGUgb3BlcmF0aW9uLCBjYW4gYmUgbnVsbFxuICAgKiBAcmV0dXJuIGEgSGVhZGVyIG9iamVjdFxuICAgKi9cbiAgcHVibGljIGdldEhlYWRlcjogKGFib3J0U2lnbmFsPzogQWJvcnRTaWduYWwpID0+IFByb21pc2U8SGVhZGVyPlxuXG4gIC8qXG4gICAqIEBwYXJhbSBmaWxlaGFuZGxlIC0gYSBmaWxlaGFuZGxlIGZyb20gZ2VuZXJpYy1maWxlaGFuZGxlIG9yIGltcGxlbWVudGluZyBzb21ldGhpbmcgc2ltaWxhciB0byB0aGUgbm9kZTEwIGZzLnByb21pc2VzIEFQSVxuICAgKiBAcGFyYW0gcGF0aCAtIGEgTG9jYWwgZmlsZSBwYXRoIGFzIGEgc3RyaW5nXG4gICAqIEBwYXJhbSB1cmwgLSBhIFVSTCBzdHJpbmdcbiAgICogQHBhcmFtIHJlbmFtZVJlZlNlcXMgLSBhbiBvcHRpb25hbCBtZXRob2QgdG8gcmVuYW1lIHRoZSBpbnRlcm5hbCByZWZlcmVuY2Ugc2VxdWVuY2VzIHVzaW5nIGEgbWFwcGluZyBmdW5jdGlvblxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIGZpbGVoYW5kbGU/OiBHZW5lcmljRmlsZWhhbmRsZVxuICAgICAgcGF0aD86IHN0cmluZ1xuICAgICAgdXJsPzogc3RyaW5nXG4gICAgICByZW5hbWVSZWZTZXFzPzogKGE6IHN0cmluZykgPT4gc3RyaW5nXG4gICAgfSA9IHt9LFxuICApIHtcbiAgICBjb25zdCB7IGZpbGVoYW5kbGUsIHJlbmFtZVJlZlNlcXMsIHBhdGgsIHVybCB9ID0gb3B0aW9uc1xuICAgIHRoaXMucmVuYW1lUmVmU2VxcyA9IHJlbmFtZVJlZlNlcXMgfHwgKChzOiBzdHJpbmcpOiBzdHJpbmcgPT4gcylcbiAgICB0aGlzLmhlYWRlckNhY2hlID0gbmV3IEFib3J0QXdhcmVDYWNoZSgpXG4gICAgaWYgKGZpbGVoYW5kbGUpIHtcbiAgICAgIHRoaXMuYmJpID0gZmlsZWhhbmRsZVxuICAgIH0gZWxzZSBpZiAodXJsKSB7XG4gICAgICB0aGlzLmJiaSA9IG5ldyBSZW1vdGVGaWxlKHVybClcbiAgICB9IGVsc2UgaWYgKHBhdGgpIHtcbiAgICAgIHRoaXMuYmJpID0gbmV3IExvY2FsRmlsZShwYXRoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIGZpbGUgZ2l2ZW4nKVxuICAgIH1cbiAgICB0aGlzLmdldEhlYWRlciA9IHRoaXMuaGVhZGVyQ2FjaGUuYWJvcnRhYmxlTWVtb2l6ZSh0aGlzLl9nZXRIZWFkZXIuYmluZCh0aGlzKSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgX2dldEhlYWRlcihhYm9ydFNpZ25hbD86IEFib3J0U2lnbmFsKSB7XG4gICAgY29uc3QgaGVhZGVyID0gYXdhaXQgdGhpcy5fZ2V0TWFpbkhlYWRlcihhYm9ydFNpZ25hbClcbiAgICBjb25zdCBjaHJvbXMgPSBhd2FpdCB0aGlzLl9yZWFkQ2hyb21UcmVlKGhlYWRlciwgYWJvcnRTaWduYWwpXG4gICAgcmV0dXJuIHsgLi4uaGVhZGVyLCAuLi5jaHJvbXMgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfZ2V0TWFpbkhlYWRlcihhYm9ydFNpZ25hbD86IEFib3J0U2lnbmFsLCByZXF1ZXN0U2l6ZSA9IDIwMDApOiBQcm9taXNlPEhlYWRlcj4ge1xuICAgIGNvbnN0IHsgYnVmZmVyIH0gPSBhd2FpdCB0aGlzLmJiaS5yZWFkKEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSksIDAsIHJlcXVlc3RTaXplLCAwLCB7IHNpZ25hbDogYWJvcnRTaWduYWwgfSlcbiAgICBjb25zdCBpc0JpZ0VuZGlhbiA9IHRoaXMuX2lzQmlnRW5kaWFuKGJ1ZmZlcilcbiAgICBjb25zdCByZXQgPSBnZXRQYXJzZXJzKGlzQmlnRW5kaWFuKVxuICAgIGNvbnN0IGhlYWRlciA9IHJldC5oZWFkZXJQYXJzZXIucGFyc2UoYnVmZmVyKS5yZXN1bHRcbiAgICBoZWFkZXIuZmlsZVR5cGUgPSBoZWFkZXIubWFnaWMgPT09IEJJR19CRURfTUFHSUMgPyAnYmlnYmVkJyA6ICdiaWd3aWcnXG4gICAgaWYgKGhlYWRlci5hc09mZnNldCA+IHJlcXVlc3RTaXplIHx8IGhlYWRlci50b3RhbFN1bW1hcnlPZmZzZXQgPiByZXF1ZXN0U2l6ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldE1haW5IZWFkZXIoYWJvcnRTaWduYWwsIHJlcXVlc3RTaXplICogMilcbiAgICB9XG4gICAgaWYgKGhlYWRlci5hc09mZnNldCkge1xuICAgICAgaGVhZGVyLmF1dG9TcWwgPSBidWZmZXIuc2xpY2UoaGVhZGVyLmFzT2Zmc2V0LCBidWZmZXIuaW5kZXhPZigwLCBoZWFkZXIuYXNPZmZzZXQpKS50b1N0cmluZygndXRmOCcpXG4gICAgfVxuICAgIGlmIChoZWFkZXIudG90YWxTdW1tYXJ5T2Zmc2V0ID4gcmVxdWVzdFNpemUpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRNYWluSGVhZGVyKGFib3J0U2lnbmFsLCByZXF1ZXN0U2l6ZSAqIDIpXG4gICAgfVxuICAgIGlmIChoZWFkZXIudG90YWxTdW1tYXJ5T2Zmc2V0KSB7XG4gICAgICBjb25zdCB0YWlsID0gYnVmZmVyLnNsaWNlKGhlYWRlci50b3RhbFN1bW1hcnlPZmZzZXQpXG4gICAgICBoZWFkZXIudG90YWxTdW1tYXJ5ID0gcmV0LnRvdGFsU3VtbWFyeVBhcnNlci5wYXJzZSh0YWlsKS5yZXN1bHRcbiAgICB9XG4gICAgcmV0dXJuIHsgLi4uaGVhZGVyLCBpc0JpZ0VuZGlhbiB9XG4gIH1cblxuICBwcml2YXRlIF9pc0JpZ0VuZGlhbihidWZmZXI6IEJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgIGxldCByZXQgPSBidWZmZXIucmVhZEludDMyTEUoMClcbiAgICBpZiAocmV0ID09PSBCSUdfV0lHX01BR0lDIHx8IHJldCA9PT0gQklHX0JFRF9NQUdJQykge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHJldCA9IGJ1ZmZlci5yZWFkSW50MzJCRSgwKVxuICAgIGlmIChyZXQgPT09IEJJR19XSUdfTUFHSUMgfHwgcmV0ID09PSBCSUdfQkVEX01BR0lDKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ25vdCBhIEJpZ1dpZy9CaWdCZWQgZmlsZScpXG4gIH1cblxuICAvLyB0b2RvOiBhZGQgcHJvZ3Jlc3MgaWYgbG9uZyBydW5uaW5nXG4gIHByaXZhdGUgYXN5bmMgX3JlYWRDaHJvbVRyZWUoaGVhZGVyOiBIZWFkZXIsIGFib3J0U2lnbmFsPzogQWJvcnRTaWduYWwpIHtcbiAgICBjb25zdCBpc0JFID0gaGVhZGVyLmlzQmlnRW5kaWFuXG4gICAgY29uc3QgbGUgPSBpc0JFID8gJ2JpZycgOiAnbGl0dGxlJ1xuICAgIGNvbnN0IHJlZnNCeU51bWJlcjogeyBba2V5OiBudW1iZXJdOiB7IG5hbWU6IHN0cmluZzsgaWQ6IG51bWJlcjsgbGVuZ3RoOiBudW1iZXIgfSB9ID0gW11cbiAgICBjb25zdCByZWZzQnlOYW1lOiB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9ID0ge31cbiAgICBjb25zdCB7IGNocm9tVHJlZU9mZnNldCB9ID0gaGVhZGVyXG4gICAgbGV0IHsgdW56b29tZWREYXRhT2Zmc2V0IH0gPSBoZWFkZXJcblxuICAgIHdoaWxlICh1bnpvb21lZERhdGFPZmZzZXQgJSA0ICE9PSAwKSB7XG4gICAgICB1bnpvb21lZERhdGFPZmZzZXQgKz0gMVxuICAgIH1cblxuICAgIGNvbnN0IHsgYnVmZmVyOiBkYXRhIH0gPSBhd2FpdCB0aGlzLmJiaS5yZWFkKFxuICAgICAgQnVmZmVyLmFsbG9jKHVuem9vbWVkRGF0YU9mZnNldCAtIGNocm9tVHJlZU9mZnNldCksXG4gICAgICAwLFxuICAgICAgdW56b29tZWREYXRhT2Zmc2V0IC0gY2hyb21UcmVlT2Zmc2V0LFxuICAgICAgY2hyb21UcmVlT2Zmc2V0LFxuICAgICAgeyBzaWduYWw6IGFib3J0U2lnbmFsIH0sXG4gICAgKVxuXG4gICAgY29uc3QgcCA9IGdldFBhcnNlcnMoaXNCRSlcbiAgICBjb25zdCB7IGtleVNpemUgfSA9IHAuY2hyb21UcmVlUGFyc2VyLnBhcnNlKGRhdGEpLnJlc3VsdFxuICAgIGNvbnN0IGxlYWZOb2RlUGFyc2VyID0gbmV3IFBhcnNlcigpXG4gICAgICAuZW5kaWFuZXNzKGxlKVxuICAgICAgLnN0cmluZygna2V5JywgeyBzdHJpcE51bGw6IHRydWUsIGxlbmd0aDoga2V5U2l6ZSB9KVxuICAgICAgLnVpbnQzMigncmVmSWQnKVxuICAgICAgLnVpbnQzMigncmVmU2l6ZScpXG4gICAgY29uc3Qgbm9ubGVhZk5vZGVQYXJzZXIgPSBuZXcgUGFyc2VyKClcbiAgICAgIC5lbmRpYW5lc3MobGUpXG4gICAgICAuc2tpcChrZXlTaXplKVxuICAgICAgLnVpbnQ2NCgnY2hpbGRPZmZzZXQnKVxuICAgIGNvbnN0IHJvb3ROb2RlT2Zmc2V0ID0gMzJcbiAgICBjb25zdCBicHRSZWFkTm9kZSA9IGFzeW5jIChjdXJyZW50T2Zmc2V0OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgIGxldCBvZmZzZXQgPSBjdXJyZW50T2Zmc2V0XG4gICAgICBpZiAob2Zmc2V0ID49IGRhdGEubGVuZ3RoKSB0aHJvdyBuZXcgRXJyb3IoJ3JlYWRpbmcgYmV5b25kIGVuZCBvZiBidWZmZXInKVxuICAgICAgY29uc3QgcmV0ID0gcC5pc0xlYWZOb2RlLnBhcnNlKGRhdGEuc2xpY2Uob2Zmc2V0KSlcbiAgICAgIGNvbnN0IHsgaXNMZWFmTm9kZSwgY250IH0gPSByZXQucmVzdWx0XG4gICAgICBvZmZzZXQgKz0gcmV0Lm9mZnNldFxuICAgICAgYXdhaXQgYWJvcnRCcmVha1BvaW50KGFib3J0U2lnbmFsKVxuICAgICAgaWYgKGlzTGVhZk5vZGUpIHtcbiAgICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCBjbnQ7IG4gKz0gMSkge1xuICAgICAgICAgIGNvbnN0IGxlYWZSZXQgPSBsZWFmTm9kZVBhcnNlci5wYXJzZShkYXRhLnNsaWNlKG9mZnNldCkpXG4gICAgICAgICAgb2Zmc2V0ICs9IGxlYWZSZXQub2Zmc2V0XG4gICAgICAgICAgY29uc3QgeyBrZXksIHJlZklkLCByZWZTaXplIH0gPSBsZWFmUmV0LnJlc3VsdFxuICAgICAgICAgIGNvbnN0IHJlZlJlYyA9IHsgbmFtZToga2V5LCBpZDogcmVmSWQsIGxlbmd0aDogcmVmU2l6ZSB9XG4gICAgICAgICAgcmVmc0J5TmFtZVt0aGlzLnJlbmFtZVJlZlNlcXMoa2V5KV0gPSByZWZJZFxuICAgICAgICAgIHJlZnNCeU51bWJlcltyZWZJZF0gPSByZWZSZWNcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyc2UgaW5kZXggbm9kZVxuICAgICAgICBjb25zdCBuZXh0Tm9kZXMgPSBbXVxuICAgICAgICBmb3IgKGxldCBuID0gMDsgbiA8IGNudDsgbiArPSAxKSB7XG4gICAgICAgICAgY29uc3Qgbm9ubGVhZlJldCA9IG5vbmxlYWZOb2RlUGFyc2VyLnBhcnNlKGRhdGEuc2xpY2Uob2Zmc2V0KSlcbiAgICAgICAgICBsZXQgeyBjaGlsZE9mZnNldCB9ID0gbm9ubGVhZlJldC5yZXN1bHRcbiAgICAgICAgICBvZmZzZXQgKz0gbm9ubGVhZlJldC5vZmZzZXRcbiAgICAgICAgICBjaGlsZE9mZnNldCAtPSBjaHJvbVRyZWVPZmZzZXRcbiAgICAgICAgICBuZXh0Tm9kZXMucHVzaChicHRSZWFkTm9kZShjaGlsZE9mZnNldCkpXG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwobmV4dE5vZGVzKVxuICAgICAgfVxuICAgIH1cbiAgICBhd2FpdCBicHRSZWFkTm9kZShyb290Tm9kZU9mZnNldClcbiAgICByZXR1cm4ge1xuICAgICAgcmVmc0J5TmFtZSxcbiAgICAgIHJlZnNCeU51bWJlcixcbiAgICB9XG4gIH1cblxuICAvKlxuICAgKiBmZXRjaGVzIHRoZSBcInVuem9vbWVkXCIgdmlldyBvZiB0aGUgYmlnd2lnIGRhdGEuIHRoaXMgaXMgdGhlIGRlZmF1bHQgZm9yIGJpZ2JlZFxuICAgKiBAcGFyYW0gYWJvcnRTaWduYWwgLSBhIHNpZ25hbCB0byBvcHRpb25hbGx5IGFib3J0IHRoaXMgb3BlcmF0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0VW56b29tZWRWaWV3KGFib3J0U2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPEJsb2NrVmlldz4ge1xuICAgIGNvbnN0IHtcbiAgICAgIHVuem9vbWVkSW5kZXhPZmZzZXQsXG4gICAgICB6b29tTGV2ZWxzLFxuICAgICAgcmVmc0J5TmFtZSxcbiAgICAgIHVuY29tcHJlc3NCdWZTaXplLFxuICAgICAgaXNCaWdFbmRpYW4sXG4gICAgICBmaWxlVHlwZSxcbiAgICB9ID0gYXdhaXQgdGhpcy5nZXRIZWFkZXIoYWJvcnRTaWduYWwpXG4gICAgY29uc3QgbnpsID0gem9vbUxldmVsc1swXVxuICAgIGNvbnN0IGNpckxlbiA9IG56bCA/IG56bC5kYXRhT2Zmc2V0IC0gdW56b29tZWRJbmRleE9mZnNldCA6IDQwMDBcbiAgICByZXR1cm4gbmV3IEJsb2NrVmlldyhcbiAgICAgIHRoaXMuYmJpLFxuICAgICAgcmVmc0J5TmFtZSxcbiAgICAgIHVuem9vbWVkSW5kZXhPZmZzZXQsXG4gICAgICBjaXJMZW4sXG4gICAgICBpc0JpZ0VuZGlhbixcbiAgICAgIHVuY29tcHJlc3NCdWZTaXplID4gMCxcbiAgICAgIGZpbGVUeXBlLFxuICAgIClcbiAgfVxuXG4gIC8qXG4gICAqIGFic3RyYWN0IG1ldGhvZCAtIGdldCB0aGUgdmlldyBmb3IgYSBnaXZlbiBzY2FsZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIGdldFZpZXcoc2NhbGU6IG51bWJlciwgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8QmxvY2tWaWV3PlxuXG4gIC8qKlxuICAgKiBHZXRzIGZlYXR1cmVzIGZyb20gYSBCaWdXaWcgZmlsZVxuICAgKlxuICAgKiBAcGFyYW0gcmVmTmFtZSAtIFRoZSBjaHJvbW9zb21lIG5hbWVcbiAgICogQHBhcmFtIHN0YXJ0IC0gVGhlIHN0YXJ0IG9mIGEgcmVnaW9uXG4gICAqIEBwYXJhbSBlbmQgLSBUaGUgZW5kIG9mIGEgcmVnaW9uXG4gICAqIEBwYXJhbSBvcHRzIC0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFzZXNQZXJTcGFuIChlLmcuIHBpeGVscyBwZXIgYmFzZXBhaXIpIG9yIHNjYWxlIHVzZWQgdG8gaW5mZXIgdGhlIHpvb21MZXZlbCB0byB1c2VcbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRGZWF0dXJlU3RyZWFtKFxuICAgIHJlZk5hbWU6IHN0cmluZyxcbiAgICBzdGFydDogbnVtYmVyLFxuICAgIGVuZDogbnVtYmVyLFxuICAgIG9wdHM6IHsgYmFzZXNQZXJTcGFuPzogbnVtYmVyOyBzY2FsZT86IG51bWJlcjsgc2lnbmFsPzogQWJvcnRTaWduYWwgfSA9IHsgc2NhbGU6IDEgfSxcbiAgKTogUHJvbWlzZTxPYnNlcnZhYmxlPEZlYXR1cmVbXT4+IHtcbiAgICBhd2FpdCB0aGlzLmdldEhlYWRlcihvcHRzLnNpZ25hbClcbiAgICBjb25zdCBjaHJOYW1lID0gdGhpcy5yZW5hbWVSZWZTZXFzKHJlZk5hbWUpXG4gICAgbGV0IHZpZXc6IEJsb2NrVmlld1xuXG4gICAgaWYgKG9wdHMuYmFzZXNQZXJTcGFuKSB7XG4gICAgICB2aWV3ID0gYXdhaXQgdGhpcy5nZXRWaWV3KDEgLyBvcHRzLmJhc2VzUGVyU3Bhbiwgb3B0cy5zaWduYWwpXG4gICAgfSBlbHNlIGlmIChvcHRzLnNjYWxlKSB7XG4gICAgICB2aWV3ID0gYXdhaXQgdGhpcy5nZXRWaWV3KG9wdHMuc2NhbGUsIG9wdHMuc2lnbmFsKVxuICAgIH0gZWxzZSB7XG4gICAgICB2aWV3ID0gYXdhaXQgdGhpcy5nZXRWaWV3KDEsIG9wdHMuc2lnbmFsKVxuICAgIH1cblxuICAgIGlmICghdmlldykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bmFibGUgdG8gZ2V0IGJsb2NrIHZpZXcgZm9yIGRhdGEnKVxuICAgIH1cbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyOiBPYnNlcnZlcjxGZWF0dXJlW10+KTogdm9pZCA9PiB7XG4gICAgICB2aWV3LnJlYWRXaWdEYXRhKGNock5hbWUsIHN0YXJ0LCBlbmQsIG9ic2VydmVyLCBvcHRzKVxuICAgIH0pXG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0RmVhdHVyZXMoXG4gICAgcmVmTmFtZTogc3RyaW5nLFxuICAgIHN0YXJ0OiBudW1iZXIsXG4gICAgZW5kOiBudW1iZXIsXG4gICAgb3B0czogeyBiYXNlc1BlclNwYW4/OiBudW1iZXI7IHNjYWxlPzogbnVtYmVyOyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9ID0geyBzY2FsZTogMSB9LFxuICApOiBQcm9taXNlPEZlYXR1cmVbXT4ge1xuICAgIGNvbnN0IG9iID0gYXdhaXQgdGhpcy5nZXRGZWF0dXJlU3RyZWFtKHJlZk5hbWUsIHN0YXJ0LCBlbmQsIG9wdHMpXG4gICAgY29uc3QgcmV0ID0gYXdhaXQgb2IucGlwZShyZWR1Y2UoKGFjYzogRmVhdHVyZVtdLCBjdXJyOiBGZWF0dXJlW10pOiBGZWF0dXJlW10gPT4gYWNjLmNvbmNhdChjdXJyKSkpLnRvUHJvbWlzZSgpXG4gICAgcmV0dXJuIHJldCB8fCBbXVxuICB9XG59XG4iXX0=