/**
|
* @license
|
* Copyright 2019 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 { env } from './environment';
|
import { getGlobal } from './global_util';
|
import * as log from './log';
|
const kernelRegistry = getGlobal('kernelRegistry', () => new Map());
|
const gradRegistry = getGlobal('gradRegistry', () => new Map());
|
/**
|
* Returns the kernel function (code) associated with the provided names.
|
*
|
* @param kernelName The official name of the kernel.
|
* @param backendName The official name of the backend.
|
*/
|
export function getKernel(kernelName, backendName) {
|
const key = makeKey(kernelName, backendName);
|
return kernelRegistry.get(key);
|
}
|
/**
|
* Returns the registered gradient info associated with the provided kernel.
|
* @param kernelName The official TF kernel name.
|
*/
|
export function getGradient(kernelName) {
|
return gradRegistry.get(kernelName);
|
}
|
export function getKernelsForBackend(backendName) {
|
const it = kernelRegistry.entries();
|
const result = [];
|
while (true) {
|
const { done, value } = it.next();
|
if (done) {
|
break;
|
}
|
const [key, config] = value;
|
const [backend,] = key.split('_');
|
if (backend === backendName) {
|
result.push(config);
|
}
|
}
|
return result;
|
}
|
/**
|
* Registers the function (forward pass) for the kernel in a global registry.
|
*
|
* @param config A config object with the following properties:
|
* - `kernelName` The official name of the kernel.
|
* - `backendName` The official name of the backend.
|
* - `kernelFunc` The function to run during the forward pass of the kernel.
|
* - `setupFunc` Optional. Gets called once, after the backend initializes.
|
* - `disposeFunc` Optional. Gets called once, right before the backend is
|
* disposed.
|
*/
|
export function registerKernel(config) {
|
const { kernelName, backendName } = config;
|
const key = makeKey(kernelName, backendName);
|
if (kernelRegistry.has(key)) {
|
log.warn(`The kernel '${kernelName}' for backend ` +
|
`'${backendName}' is already registered`);
|
}
|
kernelRegistry.set(key, config);
|
}
|
/**
|
* Registers a gradient function for a given kernel in the global registry,
|
* to be used during the back-propagation of that kernel.
|
*
|
* @param config An object with the following properties:
|
* - `kernelName` The name of the kernel that the gradient function is for.
|
* - `gradFunc` The function to run during back-propagation.
|
*/
|
export function registerGradient(config) {
|
const { kernelName } = config;
|
if (gradRegistry.has(kernelName)) {
|
// TODO (yassogba) after 3.0 assess whether we need to keep this gated
|
// to debug mode.
|
if (env().getBool('DEBUG')) {
|
log.warn(`Overriding the gradient for '${kernelName}'`);
|
}
|
}
|
gradRegistry.set(kernelName, config);
|
}
|
/**
|
* Removes the kernel function from the registry.
|
*
|
* @param kernelName The official name of the kernel.
|
* @param backendName The official name of the backend.
|
*
|
*/
|
export function unregisterKernel(kernelName, backendName) {
|
const key = makeKey(kernelName, backendName);
|
if (!kernelRegistry.has(key)) {
|
throw new Error(`The kernel '${kernelName}' for backend ` +
|
`'${backendName}' is not registered`);
|
}
|
kernelRegistry.delete(key);
|
}
|
/** Removes the registered gradient from the global registry. */
|
export function unregisterGradient(kernelName) {
|
if (!gradRegistry.has(kernelName)) {
|
throw new Error(`The gradient '${kernelName}' for backend is not registered`);
|
}
|
gradRegistry.delete(kernelName);
|
}
|
/**
|
* Finds kernels that have already been registered to a backend and re-registers
|
* them for a new backend. Useful for registering custom backends.
|
* @param registeredBackendName Already registered backend.
|
* @param newBackendName New backend.
|
*/
|
export function copyRegisteredKernels(registeredBackendName, newBackendName) {
|
const kernels = getKernelsForBackend(registeredBackendName);
|
kernels.forEach(kernelConfig => {
|
const newKernelConfig = Object.assign({}, kernelConfig, { backendName: newBackendName });
|
registerKernel(newKernelConfig);
|
});
|
}
|
function makeKey(kernelName, backendName) {
|
return `${backendName}_${kernelName}`;
|
}
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2VybmVsX3JlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9rZXJuZWxfcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsT0FBTyxFQUFDLEdBQUcsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNsQyxPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDO0FBTTdCLE1BQU0sY0FBYyxHQUNsQixTQUFTLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxHQUFHLEVBQ3hCLENBQUMsQ0FBQztBQUNyQixNQUFNLFlBQVksR0FDaEIsU0FBUyxDQUFDLGNBQWMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBc0IsQ0FBQyxDQUFDO0FBcURqRTs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQ3JCLFVBQWtCLEVBQUUsV0FBbUI7SUFDekMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUM3QyxPQUFPLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsVUFBa0I7SUFDNUMsT0FBTyxZQUFZLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3RDLENBQUM7QUFFRCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsV0FBbUI7SUFDdEQsTUFBTSxFQUFFLEdBQUcsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3BDLE1BQU0sTUFBTSxHQUFtQixFQUFFLENBQUM7SUFFbEMsT0FBTyxJQUFJLEVBQUU7UUFDWCxNQUFNLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBQyxHQUFHLEVBQUUs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QUFPLENBQUMsVUFBa0IsRUFDbEIsV0FBbUI7SUFDbEMsT0FBTyxHQUFHLFdBQVcsSUFBSSxVQUFVLEVBQUUsQ0FBQztBQUN4QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuaW1wb3J0IHtlbnZ9IGZyb20gJy4vZW52aXJvbm1lbnQnO1xuaW1wb3J0IHtnZXRHbG9iYWx9IGZyb20gJy4vZ2xvYmFsX3V0aWwnO1xuaW1wb3J0ICogYXMgbG9nIGZyb20gJy4vbG9nJztcbmltcG9ydCB7TmFtZWRHcmFkaWVudE1hcH0gZnJvbSAnLi90YXBlJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuL3RlbnNvcic7XG5pbXBvcnQge1RlbnNvckluZm99IGZyb20gJy4vdGVuc29yX2luZm8nO1xuaW1wb3J0IHtSZWN1cnNpdmVBcnJheX0gZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IGtlcm5lbFJlZ2lzdHJ5ID1cbiAgZ2V0R2xvYmFsKCdrZXJuZWxSZWdpc3RyeScsICgpID0+IG5ldyBNYXA8YCR7c3RyaW5nfV8ke3N0cmluZ31gLFxuICAgIEtlcm5lbENvbmZpZz4oKSk7XG5jb25zdCBncmFkUmVnaXN0cnkgPVxuICBnZXRHbG9iYWwoJ2dyYWRSZWdpc3RyeScsICgpID0+IG5ldyBNYXA8c3RyaW5nLCBHcmFkQ29uZmlnPigpKTtcblxudHlwZSBBdHRyaWJ1dGVWYWx1ZSA9XG4gIG51bWJlciB8IG51bWJlcltdIHwgYm9vbGVhbiB8IGJvb2xlYW5bXSB8IHN0cmluZyB8IHN0cmluZ1tdIHwgTmFtZWRBdHRyTWFwO1xuXG4vKiogVGhlc2UgYXJlIGV4dHJhIG5vbi10ZW5zb3IvcHJpbWl0aXZlIHBhcmFtcyBwYXNzZWQgdG8ga2VybmVsIGZ1bmN0aW9ucy4gKi9cbmV4cG9ydCB0eXBlIEF0dHJpYnV0ZSA9IEF0dHJpYnV0ZVZhbHVlIHwgUmVjdXJzaXZlQXJyYXk8QXR0cmlidXRlVmFsdWU+O1xuXG4vKiogU3BlY2lmaWVzIHRoZSBjb2RlIHRvIHJ1biB3aGVuIGV4ZWN1dGluZyBhIGtlcm5lbC4gKi9cbmV4cG9ydCB0eXBlIEtlcm5lbEZ1bmMgPSAocGFyYW1zOiB7XG4gIGlucHV0czogTmFtZWRUZW5zb3JJbmZvTWFwLFxuICBiYWNrZW5kOiB7fSxcbiAgYXR0cnM/OiBOYW1lZEF0dHJNYXAsXG59KSA9PiBUZW5zb3JJbmZvIHwgVGVuc29ySW5mb1tdO1xuXG4vKiogVGhlIGZ1bmN0aW9uIHRvIHJ1biB3aGVuIGNvbXB1dGluZyBhIGdyYWRpZW50IGR1cmluZyBiYWNrcHJvcC4gKi9cbmV4cG9ydCB0eXBlIEdyYWRGdW5jID1cbiAgKGR5OiBUZW5zb3IgfCBUZW5zb3JbXSwgc2F2ZWQ6IFRlbnNvcltdLCBhdHRyczogTmFtZWRBdHRyTWFwKSA9PlxuICAgIE5hbWVkR3JhZGllbnRNYXA7XG5cbi8qKiBGdW5jdGlvbiB0aGF0IGdldHMgY2FsbGVkIGFmdGVyIHRoZSBiYWNrZW5kIGluaXRpYWxpemVzLiAqL1xuZXhwb3J0IHR5cGUgS2VybmVsU2V0dXBGdW5jID0gKGJhY2tlbmQ6IHt9KSA9PiB2b2lkO1xuLyoqIEZ1bmN0aW9uIHRoYXQgZ2V0cyBjYWxsZWQgcmlnaHQgYmVmb3JlIHRoZSBiYWNrZW5kIGlzIGRpc3Bvc2VkLiAqL1xuZXhwb3J0IHR5cGUgS2VybmVsRGlzcG9zZUZ1bmMgPSBLZXJuZWxTZXR1cEZ1bmM7XG5cbi8qKiBDb25maWcgb2JqZWN0IGZvciByZWdpc3RlcmluZyBhIGtlcm5lbCBpbiB0aGUgZ2xvYmFsIHJlZ2lzdHJ5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBLZXJuZWxDb25maWcge1xuICBrZXJuZWxOYW1lOiBzdHJpbmc7XG4gIGJhY2tlbmROYW1lOiBzdHJpbmc7XG4gIGtlcm5lbEZ1bmM6IEtlcm5lbEZ1bmM7XG4gIHNldHVwRnVuYz86IEtlcm5lbFNldHVwRnVuYztcbiAgZGlzcG9zZUZ1bmM/OiBLZXJuZWxEaXNwb3NlRnVuYztcbn1cblxuLyoqIENvbmZpZyBvYmplY3QgZm9yIHJlZ2lzdGVyaW5nIGEgZ3JhZGllbnQgaW4gdGhlIGdsb2JhbCByZWdpc3RyeS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3JhZENvbmZpZyB7XG4gIGtlcm5lbE5hbWU6IHN0cmluZztcbiAgaW5wdXRzVG9TYXZlPzogc3RyaW5nW107XG4gIC8vIFdoZW4gc2F2ZUFsbElucHV0cyBpcyB0cnVlLCBhbGwgaW5wdXRzIHdpbGwgYmUgc2F2ZWQuIE9ubHkgdXNlIHRoaXMgZmxhZ1xuICAvLyBpZiBpbnB1dHMgaXMgYW4gYXJyYXkgb2YgVGVuc29ycy5cbiAgc2F2ZUFsbElucHV0cz86IGJvb2xlYW47XG4gIG91dHB1dHNUb1NhdmU/OiBib29sZWFuW107XG4gIGdyYWRGdW5jOiBHcmFkRnVuYztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOYW1lZFRlbnNvckluZm9NYXAge1xuICBbbmFtZTogc3RyaW5nXTogVGVuc29ySW5mb3x1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmFtZWRBdHRyTWFwIHtcbiAgW25hbWU6IHN0cmluZ106IEF0dHJpYnV0ZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBrZXJuZWwgZnVuY3Rpb24gKGNvZGUpIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJvdmlkZWQgbmFtZXMuXG4gKlxuICogQHBhcmFtIGtlcm5lbE5hbWUgVGhlIG9mZmljaWFsIG5hbWUgb2YgdGhlIGtlcm5lbC5cbiAqIEBwYXJhbSBiYWNrZW5kTmFtZSBUaGUgb2ZmaWNpYWwgbmFtZSBvZiB0aGUgYmFja2VuZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEtlcm5lbChcbiAgICBrZXJuZWxOYW1lOiBzdHJpbmcsIGJhY2tlbmROYW1lOiBzdHJpbmcpOiBLZXJuZWxDb25maWcge1xuICBjb25zdCBrZXkgPSBtYWtlS2V5KGtlcm5lbE5hbWUsIGJhY2tlbmROYW1lKTtcbiAgcmV0dXJuIGtlcm5lbFJlZ2lzdHJ5LmdldChrZXkpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHJlZ2lzdGVyZWQgZ3JhZGllbnQgaW5mbyBhc3NvY2lhdGVkIHdpdGggdGhlIHByb3ZpZGVkIGtlcm5lbC5cbiAqIEBwYXJhbSBrZXJuZWxOYW1lIFRoZSBvZmZpY2lhbCBURiBrZXJuZWwgbmFtZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdyYWRpZW50KGtlcm5lbE5hbWU6IHN0cmluZyk6IEdyYWRDb25maWcge1xuICByZXR1cm4gZ3JhZFJlZ2lzdHJ5LmdldChrZXJuZWxOYW1lKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEtlcm5lbHNGb3JCYWNrZW5kKGJhY2tlbmROYW1lOiBzdHJpbmcpOiBLZXJuZWxDb25maWdbXSB7XG4gIGNvbnN0IGl0ID0ga2VybmVsUmVnaXN0cnkuZW50cmllcygpO1xuICBjb25zdCByZXN1bHQ6IEtlcm5lbENvbmZpZ1tdID0gW107XG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBjb25zdCB7ZG9uZSwgdmFsdWV9ID0gaXQubmV4dCgpO1xuICAgIGlmIChkb25lKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY29uc3QgW2tleSwgY29uZmlnXSA9IHZhbHVlO1xuICAgIGNvbnN0IFtiYWNrZW5kLCBdID0ga2V5LnNwbGl0KCdfJyk7XG4gICAgaWYgKGJhY2tlbmQgPT09IGJhY2tlbmROYW1lKSB7XG4gICAgICByZXN1bHQucHVzaChjb25maWcpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgZnVuY3Rpb24gKGZvcndhcmQgcGFzcykgZm9yIHRoZSBrZXJuZWwgaW4gYSBnbG9iYWwgcmVnaXN0cnkuXG4gKlxuICogQHBhcmFtIGNvbmZpZyBBIGNvbmZpZyBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKiAtIGBrZXJuZWxOYW1lYCBUaGUgb2ZmaWNpYWwgbmFtZSBvZiB0aGUga2VybmVsLlxuICogLSBgYmFja2VuZE5hbWVgIFRoZSBvZmZpY2lhbCBuYW1lIG9mIHRoZSBiYWNrZW5kLlxuICogLSBga2VybmVsRnVuY2AgVGhlIGZ1bmN0aW9uIHRvIHJ1biBkdXJpbmcgdGhlIGZvcndhcmQgcGFzcyBvZiB0aGUga2VybmVsLlxuICogLSBgc2V0dXBGdW5jYCBPcHRpb25hbC4gR2V0cyBjYWxsZWQgb25jZSwgYWZ0ZXIgdGhlIGJhY2tlbmQgaW5pdGlhbGl6ZXMuXG4gKiAtIGBkaXNwb3NlRnVuY2AgT3B0aW9uYWwuIEdldHMgY2FsbGVkIG9uY2UsIHJpZ2h0IGJlZm9yZSB0aGUgYmFja2VuZCBpc1xuICogZGlzcG9zZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3Rlcktlcm5lbChjb25maWc6IEtlcm5lbENvbmZpZykge1xuICBjb25zdCB7a2VybmVsTmFtZSwgYmFja2VuZE5hbWV9ID0gY29uZmlnO1xuICBjb25zdCBrZXkgPSBtYWtlS2V5KGtlcm5lbE5hbWUsIGJhY2tlbmROYW1lKTtcbiAgaWYgKGtlcm5lbFJlZ2lzdHJ5LmhhcyhrZXkpKSB7XG4gICAgbG9nLndhcm4oXG4gICAgICAgIGBUaGUga2VybmVsICcke2tlcm5lbE5hbWV9JyBmb3IgYmFja2VuZCBgICtcbiAgICAgICAgYCcke2JhY2tlbmROYW1lfScgaXMgYWxyZWFkeSByZWdpc3RlcmVkYCk7XG4gIH1cbiAga2VybmVsUmVnaXN0cnkuc2V0KGtleSwgY29uZmlnKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBncmFkaWVudCBmdW5jdGlvbiBmb3IgYSBnaXZlbiBrZXJuZWwgaW4gdGhlIGdsb2JhbCByZWdpc3RyeSxcbiAqIHRvIGJlIHVzZWQgZHVyaW5nIHRoZSBiYWNrLXByb3BhZ2F0aW9uIG9mIHRoYXQga2VybmVsLlxuICpcbiAqIEBwYXJhbSBjb25maWcgQW4gb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICogLSBga2VybmVsTmFtZWAgVGhlIG5hbWUgb2YgdGhlIGtlcm5lbCB0aGF0IHRoZSBncmFkaWVudCBmdW5jdGlvbiBpcyBmb3IuXG4gKiAtIGBncmFkRnVuY2AgVGhlIGZ1bmN0aW9uIHRvIHJ1biBkdXJpbmcgYmFjay1wcm9wYWdhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyR3JhZGllbnQoY29uZmlnOiBHcmFkQ29uZmlnKSB7XG4gIGNvbnN0IHtrZXJuZWxOYW1lfSA9IGNvbmZpZztcblxuICBpZiAoZ3JhZFJlZ2lzdHJ5LmhhcyhrZXJuZWxOYW1lKSkge1xuICAgIC8vIFRPRE8gKHlhc3NvZ2JhKSBhZnRlciAzLjAgYXNzZXNzIHdoZXRoZXIgd2UgbmVlZCB0byBrZWVwIHRoaXMgZ2F0ZWRcbiAgICAvLyB0byBkZWJ1ZyBtb2RlLlxuICAgIGlmIChlbnYoKS5nZXRCb29sKCdERUJVRycpKSB7XG4gICAgICBsb2cud2FybihgT3ZlcnJpZGluZyB0aGUgZ3JhZGllbnQgZm9yICcke2tlcm5lbE5hbWV9J2ApO1xuICAgIH1cbiAgfVxuICBncmFkUmVnaXN0cnkuc2V0KGtlcm5lbE5hbWUsIGNvbmZpZyk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyB0aGUga2VybmVsIGZ1bmN0aW9uIGZyb20gdGhlIHJlZ2lzdHJ5LlxuICpcbiAqIEBwYXJhbSBrZXJuZWxOYW1lIFRoZSBvZmZpY2lhbCBuYW1lIG9mIHRoZSBrZXJuZWwuXG4gKiBAcGFyYW0gYmFja2VuZE5hbWUgVGhlIG9mZmljaWFsIG5hbWUgb2YgdGhlIGJhY2tlbmQuXG4gKlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5yZWdpc3Rlcktlcm5lbChcbiAgICBrZXJuZWxOYW1lOiBzdHJpbmcsIGJhY2tlbmROYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3Qga2V5ID0gbWFrZUtleShrZXJuZWxOYW1lLCBiYWNrZW5kTmFtZSk7XG4gIGlmICgha2VybmVsUmVnaXN0cnkuaGFzKGtleSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUaGUga2VybmVsICcke2tlcm5lbE5hbWV9JyBmb3IgYmFja2VuZCBgICtcbiAgICAgICAgYCcke2JhY2tlbmROYW1lfScgaXMgbm90IHJlZ2lzdGVyZWRgKTtcbiAgfVxuICBrZXJuZWxSZWdpc3RyeS5kZWxldGUoa2V5KTtcbn1cblxuLyoqIFJlbW92ZXMgdGhlIHJlZ2lzdGVyZWQgZ3JhZGllbnQgZnJvbSB0aGUgZ2xvYmFsIHJlZ2lzdHJ5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVucmVnaXN0ZXJHcmFkaWVudChrZXJuZWxOYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCFncmFkUmVnaXN0cnkuaGFzKGtlcm5lbE5hbWUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIGdyYWRpZW50ICcke2tlcm5lbE5hbWV9JyBmb3IgYmFja2VuZCBpcyBub3QgcmVnaXN0ZXJlZGApO1xuICB9XG4gIGdyYWRSZWdpc3RyeS5kZWxldGUoa2VybmVsTmFtZSk7XG59XG5cbi8qKlxuICogRmluZHMga2VybmVscyB0aGF0IGhhdmUgYWxyZWFkeSBiZWVuIHJlZ2lzdGVyZWQgdG8gYSBiYWNrZW5kIGFuZCByZS1yZWdpc3RlcnNcbiAqIHRoZW0gZm9yIGEgbmV3IGJhY2tlbmQuIFVzZWZ1bCBmb3IgcmVnaXN0ZXJpbmcgY3VzdG9tIGJhY2tlbmRzLlxuICogQHBhcmFtIHJlZ2lzdGVyZWRCYWNrZW5kTmFtZSBBbHJlYWR5IHJlZ2lzdGVyZWQgYmFja2VuZC5cbiAqIEBwYXJhbSBuZXdCYWNrZW5kTmFtZSBOZXcgYmFja2VuZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvcHlSZWdpc3RlcmVkS2VybmVscyhcbiAgICByZWdpc3RlcmVkQmFja2VuZE5hbWU6IHN0cmluZywgbmV3QmFja2VuZE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBrZXJuZWxzID0gZ2V0S2VybmVsc0ZvckJhY2tlbmQocmVnaXN0ZXJlZEJhY2tlbmROYW1lKTtcbiAga2VybmVscy5mb3JFYWNoKGtlcm5lbENvbmZpZyA9PiB7XG4gICAgY29uc3QgbmV3S2VybmVsQ29uZmlnID1cbiAgICAgICAgT2JqZWN0LmFzc2lnbih7fSwga2VybmVsQ29uZmlnLCB7YmFja2VuZE5hbWU6IG5ld0JhY2tlbmROYW1lfSk7XG4gICAgcmVnaXN0ZXJLZXJuZWwobmV3S2VybmVsQ29uZmlnKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VLZXkoa2VybmVsTmFtZTogc3RyaW5nLFxuICAgICAgICAgICAgICAgICBiYWNrZW5kTmFtZTogc3RyaW5nKTogYCR7c3RyaW5nfV8ke3N0cmluZ31gIHtcbiAgcmV0dXJuIGAke2JhY2tlbmROYW1lfV8ke2tlcm5lbE5hbWV9YDtcbn1cbiJdfQ==
|