/** * @license * Copyright 2020 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ export const EPSILON_FLOAT32 = 1e-7; export const EPSILON_FLOAT16 = 1e-4; /** Convenient class for storing tensor-related data. */ export class DataStorage { constructor(backend, dataMover) { this.backend = backend; this.dataMover = dataMover; this.data = new WeakMap(); this.dataIdsCount = 0; } get(dataId) { if (!this.data.has(dataId)) { this.dataMover.moveData(this.backend, dataId); } return this.data.get(dataId); } set(dataId, value) { this.dataIdsCount++; this.data.set(dataId, value); } has(dataId) { return this.data.has(dataId); } delete(dataId) { this.dataIdsCount--; return this.data.delete(dataId); } numDataIds() { return this.dataIdsCount; } } /** * The interface that defines the kernels that should be implemented when * adding a new backend. New backends don't need to implement every one of the * methods, this can be done gradually (throw an error for unimplemented * methods). */ export class KernelBackend { refCount(dataId) { return notYetImplemented('refCount'); } incRef(dataId) { return notYetImplemented('incRef'); } timerAvailable() { return true; } time(f) { return notYetImplemented('time'); } read(dataId) { return notYetImplemented('read'); } readSync(dataId) { return notYetImplemented('readSync'); } readToGPU(dataId, options) { return notYetImplemented('readToGPU'); } numDataIds() { return notYetImplemented('numDataIds'); } disposeData(dataId, force) { return notYetImplemented('disposeData'); } write(values, shape, dtype) { return notYetImplemented('write'); } move(dataId, values, shape, dtype, refCount) { return notYetImplemented('move'); } createTensorFromGPUData(values, shape, dtype) { return notYetImplemented('createTensorFromGPUData'); } memory() { return notYetImplemented('memory'); } /** Returns the highest precision for floats in bits (e.g. 16 or 32) */ floatPrecision() { return notYetImplemented('floatPrecision'); } /** Returns the smallest representable number. */ epsilon() { return this.floatPrecision() === 32 ? EPSILON_FLOAT32 : EPSILON_FLOAT16; } dispose() { return notYetImplemented('dispose'); } } function notYetImplemented(kernelName) { throw new Error(`'${kernelName}' not yet implemented or not found in the registry. ` + `This kernel may not be supported by the tfjs backend you have chosen`); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2VuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RmanMtY29yZS9zcmMvYmFja2VuZHMvYmFja2VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFNSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDO0FBQ3BDLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUM7QUF1QnBDLHdEQUF3RDtBQUN4RCxNQUFNLE9BQU8sV0FBVztJQUl0QixZQUFvQixPQUFzQixFQUFVLFNBQW9CO1FBQXBELFlBQU8sR0FBUCxPQUFPLENBQWU7UUFBVSxjQUFTLEdBQVQsU0FBUyxDQUFXO1FBSGhFLFNBQUksR0FBRyxJQUFJLE9BQU8sRUFBYSxDQUFDO1FBQ2hDLGlCQUFZLEdBQUcsQ0FBQyxDQUFDO0lBRWtELENBQUM7SUFFNUUsR0FBRyxDQUFDLE1BQWM7UUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzFCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDL0M7UUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRCxHQUFHLENBQUMsTUFBYyxFQUFFLEtBQVE7UUFDMUIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRUQsR0FBRyxDQUFDLE1BQWM7UUFDaEIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRUQsTUFBTSxDQUFDLE1BQWM7UUFDbkIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVELFVBQVU7UUFDUixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztDQUNGO0FBaUJEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFDeEIsUUFBUSxDQUFDLE1BQWM7UUFDckIsT0FBTyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBQ0QsTUFBTSxDQUFDLE1BQWM7UUFDbkIsT0FBTyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBQ0QsY0FBYztRQUNaLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELElBQUksQ0FBQyxDQUFhO1FBQ2hCLE9BQU8saUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUNELElBQUksQ0FBQyxNQUFjO1FBQ2pCLE9BQU8saUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUNELFFBQVEsQ0FBQyxNQUFjO1FBQ3JCLE9BQU8saUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUNELFNBQVMsQ0FBQyxNQUFjLEVBQUUsT0FBMEI7UUFDbEQsT0FBTyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBQ0QsVUFBVTtRQUNSLE9BQU8saUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUNELFdBQVcsQ0FBQyxNQUFjLEVBQUUsS0FBZTtRQUN6QyxPQUFPLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFDRCxLQUFLLENBQUMsTUFBcUIsRUFBRSxLQUFlLEVBQUUsS0FBZTtRQUMzRCxPQUFPLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFDRCxJQUFJLENBQ0EsTUFBYyxFQUFFLE1BQXFCLEVBQUUsS0FBZSxFQUFFLEtBQWUsRUFDdkUsUUFBZ0I7UUFDbEIsT0FBTyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsdUJBQXVCLENBQ25CLE1BQTRCLEVBQUUsS0FBZSxFQUFFLEtBQWU7UUFDaEUsT0FBTyxpQkFBaUIsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRCxNQUFNO1FBQ0osT0FBTyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBQ0QsdUVBQXVFO0lBQ3ZFLGNBQWM7UUFDWixPQUFPLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUNELGtEQUFrRDtJQUNsRCxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsY0FBYyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQztJQUMxRSxDQUFDO0lBQ0QsT0FBTztRQUNMLE9BQU8saUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdEMsQ0FBQztDQUNGO0FBRUQsU0FBUyxpQkFBaUIsQ0FBQyxVQUFrQjtJQUMzQyxNQUFNLElBQUksS0FBSyxDQUNYLElBQUksVUFBVSxzREFBc0Q7UUFDcEUsc0VBQXNFLENBQUMsQ0FBQztBQUM5RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQge0JhY2tlbmQsIERhdGFUb0dQVU9wdGlvbnMsIEdQVURhdGEsIFRlbnNvcn0gZnJvbSAnLi4vdGVuc29yJztcbmltcG9ydCB7RGF0YUlkfSBmcm9tICcuLi90ZW5zb3JfaW5mbyc7XG5pbXBvcnQge0JhY2tlbmRWYWx1ZXMsIERhdGFUeXBlLCBXZWJHTERhdGEsIFdlYkdQVURhdGF9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGNvbnN0IEVQU0lMT05fRkxPQVQzMiA9IDFlLTc7XG5leHBvcnQgY29uc3QgRVBTSUxPTl9GTE9BVDE2ID0gMWUtNDtcblxuLy8gUmVxdWlyZWQgaW5mb3JtYXRpb24gZm9yIGFsbCBiYWNrZW5kcy5cbmV4cG9ydCBpbnRlcmZhY2UgQmFja2VuZFRpbWluZ0luZm8ge1xuICBrZXJuZWxNczogbnVtYmVyfHtlcnJvcjogc3RyaW5nfTtcbiAgZ2V0RXh0cmFQcm9maWxlSW5mbz8oKTogc3RyaW5nOyAgLy8gYSBmaWVsZCBmb3IgYWRkaXRpb25hbCB0aW1pbmcgaW5mb3JtYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZS5nLiBwYWNraW5nIC8gdW5wYWNraW5nIGZvciBXZWJHTCBiYWNrZW5kXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yU3RvcmFnZSB7XG4gIHJlYWQoZGF0YUlkOiBEYXRhSWQpOiBQcm9taXNlPEJhY2tlbmRWYWx1ZXM+O1xuICByZWFkU3luYyhkYXRhSWQ6IERhdGFJZCk6IEJhY2tlbmRWYWx1ZXM7XG4gIGRpc3Bvc2VEYXRhKGRhdGFJZDogRGF0YUlkLCBmb3JjZT86IGJvb2xlYW4pOiBib29sZWFuO1xuICB3cml0ZSh2YWx1ZXM6IEJhY2tlbmRWYWx1ZXMsIHNoYXBlOiBudW1iZXJbXSwgZHR5cGU6IERhdGFUeXBlKTogRGF0YUlkO1xuICBtb3ZlKFxuICAgICAgZGF0YUlkOiBEYXRhSWQsIHZhbHVlczogQmFja2VuZFZhbHVlcywgc2hhcGU6IG51bWJlcltdLCBkdHlwZTogRGF0YVR5cGUsXG4gICAgICByZWZDb3VudDogbnVtYmVyKTogdm9pZDtcbiAgbWVtb3J5KCk6IHt1bnJlbGlhYmxlOiBib29sZWFuO307ICAvLyBCYWNrZW5kLXNwZWNpZmljIGluZm9ybWF0aW9uLlxuICAvKiogUmV0dXJucyBudW1iZXIgb2YgZGF0YSBpZHMgY3VycmVudGx5IGluIHRoZSBzdG9yYWdlLiAqL1xuICBudW1EYXRhSWRzKCk6IG51bWJlcjtcbiAgcmVmQ291bnQoZGF0YUlkOiBEYXRhSWQpOiBudW1iZXI7XG59XG5cbi8qKiBDb252ZW5pZW50IGNsYXNzIGZvciBzdG9yaW5nIHRlbnNvci1yZWxhdGVkIGRhdGEuICovXG5leHBvcnQgY2xhc3MgRGF0YVN0b3JhZ2U8VD4ge1xuICBwcml2YXRlIGRhdGEgPSBuZXcgV2Vha01hcDxEYXRhSWQsIFQ+KCk7XG4gIHByaXZhdGUgZGF0YUlkc0NvdW50ID0gMDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGJhY2tlbmQ6IEtlcm5lbEJhY2tlbmQsIHByaXZhdGUgZGF0YU1vdmVyOiBEYXRhTW92ZXIpIHt9XG5cbiAgZ2V0KGRhdGFJZDogRGF0YUlkKSB7XG4gICAgaWYgKCF0aGlzLmRhdGEuaGFzKGRhdGFJZCkpIHtcbiAgICAgIHRoaXMuZGF0YU1vdmVyLm1vdmVEYXRhKHRoaXMuYmFja2VuZCwgZGF0YUlkKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZGF0YS5nZXQoZGF0YUlkKTtcbiAgfVxuXG4gIHNldChkYXRhSWQ6IERhdGFJZCwgdmFsdWU6IFQpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGFJZHNDb3VudCsrO1xuICAgIHRoaXMuZGF0YS5zZXQoZGF0YUlkLCB2YWx1ZSk7XG4gIH1cblxuICBoYXMoZGF0YUlkOiBEYXRhSWQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLmhhcyhkYXRhSWQpO1xuICB9XG5cbiAgZGVsZXRlKGRhdGFJZDogRGF0YUlkKTogYm9vbGVhbiB7XG4gICAgdGhpcy5kYXRhSWRzQ291bnQtLTtcbiAgICByZXR1cm4gdGhpcy5kYXRhLmRlbGV0ZShkYXRhSWQpO1xuICB9XG5cbiAgbnVtRGF0YUlkcygpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmRhdGFJZHNDb3VudDtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFNb3ZlciB7XG4gIC8qKlxuICAgKiBUbyBiZSBjYWxsZWQgYnkgYmFja2VuZHMgd2hlbmV2ZXIgdGhleSBzZWUgYSBkYXRhSWQgdGhhdCB0aGV5IGRvbid0IG93bi5cbiAgICogVXBvbiBjYWxsaW5nIHRoaXMgbWV0aG9kLCB0aGUgbW92ZXIgd2lsbCBmZXRjaCB0aGUgdGVuc29yIGZyb20gYW5vdGhlclxuICAgKiBiYWNrZW5kIGFuZCByZWdpc3RlciBpdCB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBiYWNrZW5kLlxuICAgKi9cbiAgbW92ZURhdGEoYmFja2VuZDogS2VybmVsQmFja2VuZCwgZGF0YUlkOiBEYXRhSWQpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJhY2tlbmRUaW1lciB7XG4gIC8vIGNoZWNrIGlmIGJhY2tlbmQgdGltZXIgaXMgYXZhaWxhYmxlXG4gIHRpbWVyQXZhaWxhYmxlKCk6IGJvb2xlYW47XG4gIHRpbWUoZjogKCkgPT4gdm9pZCk6IFByb21pc2U8QmFja2VuZFRpbWluZ0luZm8+O1xufVxuXG4vKipcbiAqIFRoZSBpbnRlcmZhY2UgdGhhdCBkZWZpbmVzIHRoZSBrZXJuZWxzIHRoYXQgc2hvdWxkIGJlIGltcGxlbWVudGVkIHdoZW5cbiAqIGFkZGluZyBhIG5ldyBiYWNrZW5kLiBOZXcgYmFja2VuZHMgZG9uJ3QgbmVlZCB0byBpbXBsZW1lbnQgZXZlcnkgb25lIG9mIHRoZVxuICogbWV0aG9kcywgdGhpcyBjYW4gYmUgZG9uZSBncmFkdWFsbHkgKHRocm93IGFuIGVycm9yIGZvciB1bmltcGxlbWVudGVkXG4gKiBtZXRob2RzKS5cbiAqL1xuZXhwb3J0IGNsYXNzIEtlcm5lbEJhY2tlbmQgaW1wbGVtZW50cyBUZW5zb3JTdG9yYWdlLCBCYWNrZW5kLCBCYWNrZW5kVGltZXIge1xuICByZWZDb3VudChkYXRhSWQ6IERhdGFJZCk6IG51bWJlciB7XG4gICAgcmV0dXJuIG5vdFlldEltcGxlbWVudGVkKCdyZWZDb3VudCcpO1xuICB9XG4gIGluY1JlZihkYXRhSWQ6IERhdGFJZCk6IHZvaWQge1xuICAgIHJldHVybiBub3RZZXRJbXBsZW1lbnRlZCgnaW5jUmVmJyk7XG4gIH1cbiAgdGltZXJBdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgdGltZShmOiAoKSA9PiB2b2lkKTogUHJvbWlzZTxCYWNrZW5kVGltaW5nSW5mbz4ge1xuICAgIHJldHVybiBub3RZZXRJbXBsZW1lbnRlZCgndGltZScpO1xuICB9XG4gIHJlYWQoZGF0YUlkOiBvYmplY3QpOiBQcm9taXNlPEJhY2tlbmRWYWx1ZXM+IHtcbiAgICByZXR1cm4gbm90WWV0SW1wbGVtZW50ZWQoJ3JlYWQnKTtcbiAgfVxuICByZWFkU3luYyhkYXRhSWQ6IG9iamVjdCk6IEJhY2tlbmRWYWx1ZXMge1xuICAgIHJldHVybiBub3RZZXRJbXBsZW1lbnRlZCgncmVhZFN5bmMnKTtcbiAgfVxuICByZWFkVG9HUFUoZGF0YUlkOiBvYmplY3QsIG9wdGlvbnM/OiBEYXRhVG9HUFVPcHRpb25zKTogR1BVRGF0YSB7XG4gICAgcmV0dXJuIG5vdFlldEltcGxlbWVudGVkKCdyZWFkVG9HUFUnKTtcbiAgfVxuICBudW1EYXRhSWRzKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIG5vdFlldEltcGxlbWVudGVkKCdudW1EYXRhSWRzJyk7XG4gIH1cbiAgZGlzcG9zZURhdGEoZGF0YUlkOiBvYmplY3QsIGZvcmNlPzogYm9vbGVhbik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBub3RZZXRJbXBsZW1lbnRlZCgnZGlzcG9zZURhdGEnKTtcbiAgfVxuICB3cml0ZSh2YWx1ZXM6IEJhY2tlbmRWYWx1ZXMsIHNoYXBlOiBudW1iZXJbXSwgZHR5cGU6IERhdGFUeXBlKTogRGF0YUlkIHtcbiAgICByZXR1cm4gbm90WWV0SW1wbGVtZW50ZWQoJ3dyaXRlJyk7XG4gIH1cbiAgbW92ZShcbiAgICAgIGRhdGFJZDogRGF0YUlkLCB2YWx1ZXM6IEJhY2tlbmRWYWx1ZXMsIHNoYXBlOiBudW1iZXJbXSwgZHR5cGU6IERhdGFUeXBlLFxuICAgICAgcmVmQ291bnQ6IG51bWJlcik6IHZvaWQge1xuICAgIHJldHVybiBub3RZZXRJbXBsZW1lbnRlZCgnbW92ZScpO1xuICB9XG5cbiAgY3JlYXRlVGVuc29yRnJvbUdQVURhdGEoXG4gICAgICB2YWx1ZXM6IFdlYkdMRGF0YXxXZWJHUFVEYXRhLCBzaGFwZTogbnVtYmVyW10sIGR0eXBlOiBEYXRhVHlwZSk6IFRlbnNvciB7XG4gICAgcmV0dXJuIG5vdFlldEltcGxlbWVudGVkKCdjcmVhdGVUZW5zb3JGcm9tR1BVRGF0YScpO1xuICB9XG5cbiAgbWVtb3J5KCk6IHt1bnJlbGlhYmxlOiBib29sZWFuOyByZWFzb25zPzogc3RyaW5nW119IHtcbiAgICByZXR1cm4gbm90WWV0SW1wbGVtZW50ZWQoJ21lbW9yeScpO1xuICB9XG4gIC8qKiBSZXR1cm5zIHRoZSBoaWdoZXN0IHByZWNpc2lvbiBmb3IgZmxvYXRzIGluIGJpdHMgKGUuZy4gMTYgb3IgMzIpICovXG4gIGZsb2F0UHJlY2lzaW9uKCk6IDE2fDMyIHtcbiAgICByZXR1cm4gbm90WWV0SW1wbGVtZW50ZWQoJ2Zsb2F0UHJlY2lzaW9uJyk7XG4gIH1cbiAgLyoqIFJldHVybnMgdGhlIHNtYWxsZXN0IHJlcHJlc2VudGFibGUgbnVtYmVyLiAgKi9cbiAgZXBzaWxvbigpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmZsb2F0UHJlY2lzaW9uKCkgPT09IDMyID8gRVBTSUxPTl9GTE9BVDMyIDogRVBTSUxPTl9GTE9BVDE2O1xuICB9XG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgcmV0dXJuIG5vdFlldEltcGxlbWVudGVkKCdkaXNwb3NlJyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gbm90WWV0SW1wbGVtZW50ZWQoa2VybmVsTmFtZTogc3RyaW5nKTogbmV2ZXIge1xuICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJyR7a2VybmVsTmFtZX0nIG5vdCB5ZXQgaW1wbGVtZW50ZWQgb3Igbm90IGZvdW5kIGluIHRoZSByZWdpc3RyeS4gYCArXG4gICAgICBgVGhpcyBrZXJuZWwgbWF5IG5vdCBiZSBzdXBwb3J0ZWQgYnkgdGhlIHRmanMgYmFja2VuZCB5b3UgaGF2ZSBjaG9zZW5gKTtcbn1cbiJdfQ==