UNPKG

@tensorflow/tfjs-backend-wasm

Version:

This package adds a WebAssembly backend to TensorFlow.js. It currently supports the following models from our [models](https://github.com/tensorflow/tfjs-models) repo: - BlazeFace - BodyPix - CocoSSD - Face landmarks detection - HandPose - KNN classifier

102 lines 15.8 kB
/** * @license * Copyright 2021 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. * ============================================================================= */ import { backend_util, SparseReshape, util } from '@tensorflow/tfjs-core'; let wasmSparseReshape; function setup(backend) { wasmSparseReshape = backend.wasm.cwrap(SparseReshape, null /*void*/, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number', // exceptionValuesId ]); } function sparseReshape(args) { const { backend, inputs } = args; const { inputIndices, inputShape, newShape } = inputs; if (inputIndices.shape.length !== 2) { throw new Error(`Input indices should be a matrix but received shape ${inputIndices.shape}`); } if (inputShape.shape.length !== 1) { throw new Error(`Input shape should be a vector but received shape ${inputShape.shape}`); } if (newShape.shape.length !== 1) { throw new Error(`Target shape should be a vector but received shape ${newShape.shape}`); } const inputIndicesId = backend.dataIdMap.get(inputIndices.dataId).id; const inputShapeId = backend.dataIdMap.get(inputShape.dataId).id; const newShapeId = backend.dataIdMap.get(newShape.dataId).id; const nnz = inputIndices.shape[0]; const outputRank = util.sizeFromShape(newShape.shape); const newIndices = backend.makeOutput([nnz, outputRank], inputIndices.dtype); const newIndicesId = backend.dataIdMap.get(newIndices.dataId).id; const outputShape = backend.makeOutput([outputRank], newShape.dtype); const outputShapeId = backend.dataIdMap.get(outputShape.dataId).id; const exceptionValues = backend.makeOutput([3], 'int32'); const exceptionValuesId = backend.dataIdMap.get(exceptionValues.dataId).id; wasmSparseReshape(inputIndicesId, inputShapeId, newShapeId, nnz, newIndicesId, outputShapeId, exceptionValuesId); const exceptionValuesArray = backend.readSync(exceptionValues.dataId); let exceptionMessage; switch (exceptionValuesArray[0]) { case 0: { exceptionMessage = backend_util.getSparseReshapeMultipleNegativeOneOutputDimErrorMessage(exceptionValuesArray[1], exceptionValuesArray[2]); break; } case 1: { exceptionMessage = backend_util.getSparseReshapeNegativeOutputDimErrorMessage(exceptionValuesArray[1], exceptionValuesArray[2]); break; } case 2: exceptionMessage = backend_util.getSparseReshapeEmptyTensorZeroOutputDimErrorMessage(); break; case 3: { const inputShapeValues = Array.from(backend.readSync(inputShape.dataId)), outputShapeValues = Array.from(backend.readSync(outputShape.dataId)); exceptionMessage = backend_util.getSparseReshapeInputOutputMultipleErrorMessage(inputShapeValues, outputShapeValues); break; } case 4: { const inputShapeValues = Array.from(backend.readSync(inputShape.dataId)), outputShapeValues = Array.from(backend.readSync(outputShape.dataId)); exceptionMessage = backend_util.getSparseReshapeInputOutputMismatchErrorMessage(inputShapeValues, outputShapeValues); break; } default: exceptionMessage = ''; } backend.disposeData(exceptionValues.dataId); if (exceptionMessage) { backend.disposeData(newIndices.dataId); backend.disposeData(outputShape.dataId); throw new Error(exceptionMessage); } return [newIndices, outputShape]; } export const sparseReshapeConfig = { kernelName: SparseReshape, backendName: 'wasm', setupFunc: setup, kernelFunc: sparseReshape }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BhcnNlUmVzaGFwZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RmanMtYmFja2VuZC13YXNtL3NyYy9rZXJuZWxzL1NwYXJzZVJlc2hhcGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFDLFlBQVksRUFBNEIsYUFBYSxFQUFtQyxJQUFJLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUluSSxJQUFJLGlCQUdrQyxDQUFDO0FBRXZDLFNBQVMsS0FBSyxDQUFDLE9BQW9CO0lBQ2pDLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFO1FBQ25FLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVE7UUFDUixRQUFRO1FBQ1IsUUFBUTtRQUNSLFFBQVEsRUFBRyxvQkFBb0I7S0FDaEMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLElBR3RCO0lBQ0MsTUFBTSxFQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUMsR0FBRyxJQUFJLENBQUM7SUFDL0IsTUFBTSxFQUFDLFlBQVksRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFDLEdBQUcsTUFBTSxDQUFDO0lBRXBELElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ25DLE1BQU0sSUFBSSxLQUFLLENBQUM7VUFDVixZQUFZLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztLQUM3QjtJQUNELElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUM7VUFDVixVQUFVLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztLQUMzQjtJQUNELElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxF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RUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQzdDLE1BQU07U0FDUDtRQUNELEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDTixNQUFNLGdCQUFnQixHQUNsQixLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBZSxDQUFDLEVBQzNELGlCQUFpQixHQUNiLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFlLENBQUMsQ0FBQztZQUN6RSxnQkFBZ0I7Z0JBQ1osWUFBWSxDQUFDLCtDQUErQyxDQUN4RCxnQkFBZ0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQzdDLE1BQU07U0FDUDtRQUNEO1lBQ0UsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0tBQ3pCO0lBRUQsT0FBTyxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUMsSUFBSSxnQkFBZ0IsRUFBRTtRQUNwQixPQUFPLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QyxPQUFPLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QyxNQUFNLElBQUksS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7S0FDbkM7SUFFRCxPQUFPLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBQ25DLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBaUI7SUFDL0MsVUFBVSxFQUFFLGFBQWE7SUFDekIsV0FBVyxFQUFFLE1BQU07SUFDbkIsU0FBUyxFQUFFLEtBQUs7SUFDaEIsVUFBVSxFQUFFLGFBQXNDO0NBQ25ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCB7YmFja2VuZF91dGlsLCBLZXJuZWxDb25maWcsIEtlcm5lbEZ1bmMsIFNwYXJzZVJlc2hhcGUsIFNwYXJzZVJlc2hhcGVJbnB1dHMsIFRlbnNvckluZm8sIHV0aWx9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZSc7XG5cbmltcG9ydCB7QmFja2VuZFdhc219IGZyb20gJy4uL2JhY2tlbmRfd2FzbSc7XG5cbmxldCB3YXNtU3BhcnNlUmVzaGFwZTogKFxuICAgIGlucHV0SW5kaWNlc0lkOiBudW1iZXIsIGlucHV0U2hhcGVJZDogbnVtYmVyLCBuZXdTaGFwZUlkOiBudW1iZXIsXG4gICAgbm56OiBudW1iZXIsIG5ld0luZGljZXNJZDogbnVtYmVyLCBvdXRwdXRTaGFwZUlkOiBudW1iZXIsXG4gICAgZXhjZXB0aW9uVmFsdWVzSWQ6IG51bWJlcikgPT4gdm9pZDtcblxuZnVuY3Rpb24gc2V0dXAoYmFja2VuZDogQmFja2VuZFdhc20pOiB2b2lkIHtcbiAgd2FzbVNwYXJzZVJlc2hhcGUgPSBiYWNrZW5kLndhc20uY3dyYXAoU3BhcnNlUmVzaGFwZSwgbnVsbCAvKnZvaWQqLywgW1xuICAgICdudW1iZXInLCAgLy8gaW5wdXRJbmRpY2VzSWRcbiAgICAnbnVtYmVyJywgIC8vIGlucHV0U2hhcGVJZFxuICAgICdudW1iZXInLCAgLy8gbmV3U2hhcGVJZFxuICAgICdudW1iZXInLCAgLy8gbm56XG4gICAgJ251bWJlcicsICAvLyBuZXdJbmRpY2VzSWRcbiAgICAnbnVtYmVyJywgIC8vIG91dHB1dFNoYXBlSWRcbiAgICAnbnVtYmVyJywgIC8vIGV4Y2VwdGlvblZhbHVlc0lkXG4gIF0pO1xufVxuXG5mdW5jdGlvbiBzcGFyc2VSZXNoYXBlKGFyZ3M6IHtcbiAgYmFja2VuZDogQmFja2VuZFdhc20sXG4gIGlucHV0czogU3BhcnNlUmVzaGFwZUlucHV0cyxcbn0pOiBbVGVuc29ySW5mbywgVGVuc29ySW5mb10ge1xuICBjb25zdCB7YmFja2VuZCwgaW5wdXRzfSA9IGFyZ3M7XG4gIGNvbnN0IHtpbnB1dEluZGljZXMsIGlucHV0U2hhcGUsIG5ld1NoYXBlfSA9IGlucHV0cztcblxuICBpZiAoaW5wdXRJbmRpY2VzLnNoYXBlLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgaW5kaWNlcyBzaG91bGQgYmUgYSBtYXRyaXggYnV0IHJlY2VpdmVkIHNoYXBlXG4gICAgICAgICR7aW5wdXRJbmRpY2VzLnNoYXBlfWApO1xuICB9XG4gIGlmIChpbnB1dFNoYXBlLnNoYXBlLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgc2hhcGUgc2hvdWxkIGJlIGEgdmVjdG9yIGJ1dCByZWNlaXZlZCBzaGFwZVxuICAgICAgICAke2lucHV0U2hhcGUuc2hhcGV9YCk7XG4gIH1cbiAgaWYgKG5ld1NoYXBlLnNoYXBlLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRhcmdldCBzaGFwZSBzaG91bGQgYmUgYSB2ZWN0b3IgYnV0IHJlY2VpdmVkIHNoYXBlICR7bmV3U2hhcGUuc2hhcGV9YCk7XG4gIH1cblxuICBjb25zdCBpbnB1dEluZGljZXNJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChpbnB1dEluZGljZXMuZGF0YUlkKS5pZDtcbiAgY29uc3QgaW5wdXRTaGFwZUlkID0gYmFja2VuZC5kYXRhSWRNYXAuZ2V0KGlucHV0U2hhcGUuZGF0YUlkKS5pZDtcbiAgY29uc3QgbmV3U2hhcGVJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChuZXdTaGFwZS5kYXRhSWQpLmlkO1xuXG4gIGNvbnN0IG5ueiA9IGlucHV0SW5kaWNlcy5zaGFwZVswXTtcbiAgY29uc3Qgb3V0cHV0UmFuayA9IHV0aWwuc2l6ZUZyb21TaGFwZShuZXdTaGFwZS5zaGFwZSk7XG5cbiAgY29uc3QgbmV3SW5kaWNlcyA9IGJhY2tlbmQubWFrZU91dHB1dChbbm56LCBvdXRwdXRSYW5rXSwgaW5wdXRJbmRpY2VzLmR0eXBlKTtcbiAgY29uc3QgbmV3SW5kaWNlc0lkID0gYmFja2VuZC5kYXRhSWRNYXAuZ2V0KG5ld0luZGljZXMuZGF0YUlkKS5pZDtcblxuICBjb25zdCBvdXRwdXRTaGFwZSA9IGJhY2tlbmQubWFrZU91dHB1dChbb3V0cHV0UmFua10sIG5ld1NoYXBlLmR0eXBlKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGVJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChvdXRwdXRTaGFwZS5kYXRhSWQpLmlkO1xuXG4gIGNvbnN0IGV4Y2VwdGlvblZhbHVlcyA9IGJhY2tlbmQubWFrZU91dHB1dChbM10sICdpbnQzMicpO1xuICBjb25zdCBleGNlcHRpb25WYWx1ZXNJZCA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChleGNlcHRpb25WYWx1ZXMuZGF0YUlkKS5pZDtcblxuICB3YXNtU3BhcnNlUmVzaGFwZShcbiAgICAgIGlucHV0SW5kaWNlc0lkLCBpbnB1dFNoYXBlSWQsIG5ld1NoYXBlSWQsIG5ueiwgbmV3SW5kaWNlc0lkLFxuICAgICAgb3V0cHV0U2hhcGVJZCwgZXhjZXB0aW9uVmFsdWVzSWQpO1xuXG4gIGNvbnN0IGV4Y2VwdGlvblZhbHVlc0FycmF5ID1cbiAgICAgIGJhY2tlbmQucmVhZFN5bmMoZXhjZXB0aW9uVmFsdWVzLmRhdGFJZCkgYXMgSW50MzJBcnJheTtcblxuICBsZXQgZXhjZXB0aW9uTWVzc2FnZTogc3RyaW5nO1xuICBzd2l0Y2ggKGV4Y2VwdGlvblZhbHVlc0FycmF5WzBdKSB7XG4gICAgY2FzZSAwOiB7XG4gICAgICBleGNlcHRpb25NZXNzYWdlID1cbiAgICAgICAgICBiYWNrZW5kX3V0aWwuZ2V0U3BhcnNlUmVzaGFwZU11bHRpcGxlTmVnYXRpdmVPbmVPdXRwdXREaW1FcnJvck1lc3NhZ2UoXG4gICAgICAgICAgICAgIGV4Y2VwdGlvblZhbHVlc0FycmF5WzFdLCBleGNlcHRpb25WYWx1ZXNBcnJheVsyXSk7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2FzZSAxOiB7XG4gICAgICBleGNlcHRpb25NZXNzYWdlID1cbiAgICAgICAgICBiYWNrZW5kX3V0aWwuZ2V0U3BhcnNlUmVzaGFwZU5lZ2F0aXZlT3V0cHV0RGltRXJyb3JNZXNzYWdlKFxuICAgICAgICAgICAgICBleGNlcHRpb25WYWx1ZXNBcnJheVsxXSwgZXhjZXB0aW9uVmFsdWVzQXJyYXlbMl0pO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNhc2UgMjpcbiAgICAgIGV4Y2VwdGlvbk1lc3NhZ2UgPVxuICAgICAgICAgIGJhY2tlbmRfdXRpbC5nZXRTcGFyc2VSZXNoYXBlRW1wdHlUZW5zb3JaZXJvT3V0cHV0RGltRXJyb3JNZXNzYWdlKCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6IHtcbiAgICAgIGNvbnN0IGlucHV0U2hhcGVWYWx1ZXMgPVxuICAgICAgICAgIEFycmF5LmZyb20oYmFja2VuZC5yZWFkU3luYyhpbnB1dFNoYXBlLmRhdGFJZCkgYXMgSW50MzJBcnJheSksXG4gICAgICAgICAgICBvdXRwdXRTaGFwZVZhbHVlcyA9XG4gICAgICAgICAgICAgICAgQXJyYXkuZnJvbShiYWNrZW5kLnJlYWRTeW5jKG91dHB1dFNoYXBlLmRhdGFJZCkgYXMgSW50MzJBcnJheSk7XG4gICAgICBleGNlcHRpb25NZXNzYWdlID1cbiAgICAgICAgICBiYWNrZW5kX3V0aWwuZ2V0U3BhcnNlUmVzaGFwZUlucHV0T3V0cHV0TXVsdGlwbGVFcnJvck1lc3NhZ2UoXG4gICAgICAgICAgICAgIGlucHV0U2hhcGVWYWx1ZXMsIG91dHB1dFNoYXBlVmFsdWVzKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlIDQ6IHtcbiAgICAgIGNvbnN0IGlucHV0U2hhcGVWYWx1ZXMgPVxuICAgICAgICAgIEFycmF5LmZyb20oYmFja2VuZC5yZWFkU3luYyhpbnB1dFNoYXBlLmRhdGFJZCkgYXMgSW50MzJBcnJheSksXG4gICAgICAgICAgICBvdXRwdXRTaGFwZVZhbHVlcyA9XG4gICAgICAgICAgICAgICAgQXJyYXkuZnJvbShiYWNrZW5kLnJlYWRTeW5jKG91dHB1dFNoYXBlLmRhdGFJZCkgYXMgSW50MzJBcnJheSk7XG4gICAgICBleGNlcHRpb25NZXNzYWdlID1cbiAgICAgICAgICBiYWNrZW5kX3V0aWwuZ2V0U3BhcnNlUmVzaGFwZUlucHV0T3V0cHV0TWlzbWF0Y2hFcnJvck1lc3NhZ2UoXG4gICAgICAgICAgICAgIGlucHV0U2hhcGVWYWx1ZXMsIG91dHB1dFNoYXBlVmFsdWVzKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgZXhjZXB0aW9uTWVzc2FnZSA9ICcnO1xuICB9XG5cbiAgYmFja2VuZC5kaXNwb3NlRGF0YShleGNlcHRpb25WYWx1ZXMuZGF0YUlkKTtcbiAgaWYgKGV4Y2VwdGlvbk1lc3NhZ2UpIHtcbiAgICBiYWNrZW5kLmRpc3Bvc2VEYXRhKG5ld0luZGljZXMuZGF0YUlkKTtcbiAgICBiYWNrZW5kLmRpc3Bvc2VEYXRhKG91dHB1dFNoYXBlLmRhdGFJZCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGV4Y2VwdGlvbk1lc3NhZ2UpO1xuICB9XG5cbiAgcmV0dXJuIFtuZXdJbmRpY2VzLCBvdXRwdXRTaGFwZV07XG59XG5cbmV4cG9ydCBjb25zdCBzcGFyc2VSZXNoYXBlQ29uZmlnOiBLZXJuZWxDb25maWcgPSB7XG4gIGtlcm5lbE5hbWU6IFNwYXJzZVJlc2hhcGUsXG4gIGJhY2tlbmROYW1lOiAnd2FzbScsXG4gIHNldHVwRnVuYzogc2V0dXAsXG4gIGtlcm5lbEZ1bmM6IHNwYXJzZVJlc2hhcGUgYXMgdW5rbm93biBhcyBLZXJuZWxGdW5jXG59O1xuIl19