UNPKG

@cute-dw/core

Version:

This TypeScript library is the main part of a more powerfull package designed for the fast WEB software development. The cornerstone of the library is the **DataStore** class, which might be useful when you need a full control of the data, but do not need

150 lines 19.2 kB
import { ArrayList } from "../collections/ArrayList"; import { Comparator } from "./Comparator"; import { Objects } from "./Objects"; import { from } from "rxjs"; /** * This class consists exclusively of static methods that operate on or return arrays */ export class Arrays { /** * Returns a list object initialized with specified values * @param args Initial values by which the list will be backed * @returns A new list object that contains the specifies values * @static */ static asList(...args) { return new ArrayList(args); } /** * Searches the specified array for the specified value using the binary search algorithm. The array must be sorted * prior to making this call. If it is not sorted, the results are undefined. If the array contains multiple elements with * the specified value, there is no guarantee which one will be found. * @param sortedArray The array to be searched * @param key The value to be searched for * @param compareFn Optional compare function * @returns Index of the search key, if it is contained in the array; otherwise -1 * @static * @since 0.5.0 */ static binarySearch(sortedArray, key, compareFn) { // Let's create comparator from the compareFn function. // Comparator object will give us common comparison methods like equal() and lessThen(). const comparator = compareFn ? new Comparator(compareFn) : Comparator.getInstance(); // These two indices will contain current array (sub-array) boundaries. let startIndex = 0; let endIndex = sortedArray.length - 1; let middleIndex; // Let's continue to split array until boundaries are collapsed // and there is nothing to split anymore. while (startIndex <= endIndex) { // Let's calculate the index of the middle element. middleIndex = startIndex + Math.floor((endIndex - startIndex) / 2); // If we've found the element just return its position. if (comparator.equal(sortedArray[middleIndex], key)) { return middleIndex; } // Decide which half to choose for seeking next: left or right one. if (comparator.lessThan(sortedArray[middleIndex], key)) { // Go to the right half of the array. startIndex = middleIndex + 1; } else { // Go to the left half of the array. endIndex = middleIndex - 1; } } // Return -1 if we have not found anything. return -1; } /** * Returns `true` if the two specified arrays are deeply equal to one another. * @param a1 one array to be tested for equality * @param a2 the other array to be tested for equality * @returns `true` if the two arrays are equal * @since 0.5.0 */ static deepEquals(a1, a2) { return Objects.deepEqual(a1, a2); } /** * Returns _true_ if the two specified arrays of chars are _equal_ to one another. Two arrays are considered equal if both arrays contain the same * number of elements, and all corresponding pairs of elements in the two arrays are equal. In other words, two arrays are equal if they contain * the same elements in the same order. Also, two array references are considered equal if both are _null_. * @param arr1 one array to be tested for equality * @param arr2 the other array to be tested for equality * @returns _true_ if the two arrays are equal * @since 0.5.0 */ static equals(arr1, arr2) { let eq = ((arr1 == null && arr2 == null) || arr1 === arr2); if (!eq) { eq = Objects.deepEqual(arr1, arr2); } return eq; } /** * Pads the source array with a given `filler` value (possibly repeated) so that the array's size reaches a given length `len`. * Filling is performed from the end of the source array. * @param arr Source array * @param len Required minimum size of the source array * @param filler The value to be filled in * @returns Source array with modified length * @static * @since 0.5.0 * @see {@link padStart} */ static padEnd(arr, len, filler) { if (len > arr.length) { const oldLen = arr.length; arr.length = len; return arr.fill(filler, oldLen); } return arr; } /** * Pads the source array with a given `filler` value (possibly repeated) so that the array's size reaches a given length `len`. * Filling is performed from the start of the source array. * @param arr Source array * @param len Required minimum size of the source array * @param filler The value to be filled in * @returns Source array with modified length * @static * @since 0.5.0 * @see {@link padEnd} */ static padStart(arr, len, filler) { if (len > arr.length) { const vals = Array(len - arr.length).fill(filler); arr.unshift(...vals); } return arr; } /** * Copies the specified array, truncating or padding with null characters (if necessary), so the copy has the specified length * @param arr The array to be copied * @param newLength The length of the copy to be returned * @returns a copy of the original array, truncated or padded with null characters to obtain the specified length * @static * @since 0.5.0 */ static copyOf(arr, newLength) { if (newLength != null && newLength > 0) { if (newLength <= arr.length) { return arr.slice(0, newLength); } const copyArr = arr.slice(); return Arrays.padEnd(copyArr, newLength, null); } return arr.slice(); } /** * Returns a sequential `Observable` object with the specified array as its source * @param arr The array, assumed to be unmodified during use * @returns An Observable for the array `arr` * @since 0.5.0 */ static stream(arr) { return from(arr); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXJyYXlzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY3V0ZS1jb3JlL3NyYy9saWIvdXRpbC9BcnJheXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXJELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFMUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUMsSUFBSSxFQUFhLE1BQU0sTUFBTSxDQUFDO0FBSXRDOztHQUVHO0FBQ0gsTUFBTSxPQUFPLE1BQU07SUFDakI7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsTUFBTSxDQUFJLEdBQUcsSUFBUztRQUMzQixPQUFPLElBQUksU0FBUyxDQUFJLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFDRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsTUFBTSxDQUFDLFlBQVksQ0FBSSxXQUFxQixFQUFFLEdBQU0sRUFBRSxTQUFzQjtRQUMxRSx1REFBdUQ7UUFDdkQsd0ZBQXdGO1FBQ3hGLE1BQU0sVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUVwRix1RUFBdUU7UUFDdkUsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLElBQUksUUFBUSxHQUFHLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLElBQUksV0FBbUIsQ0FBQztRQUV4QiwrREFBK0Q7UUFDL0QseUNBQXlDO1FBQ3pDLE9BQU8sVUFBVSxJQUFJLFFBQVEsRUFBRTtZQUM3QixtREFBbUQ7WUFDbkQsV0FBVyxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FB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Q0FBQyxDQUFDO0lBQ25CLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFycmF5TGlzdCB9IGZyb20gXCIuLi9jb2xsZWN0aW9ucy9BcnJheUxpc3RcIjtcclxuaW1wb3J0IHsgTGlzdCB9IGZyb20gXCIuLi9jb2xsZWN0aW9ucy9MaXN0XCI7XHJcbmltcG9ydCB7IENvbXBhcmF0b3IgfSBmcm9tIFwiLi9Db21wYXJhdG9yXCI7XHJcbmltcG9ydCB7IENvbXBhcmUgfSBmcm9tIFwiLi9mdW5jdGlvbi9Db21wYXJlXCI7XHJcbmltcG9ydCB7IE9iamVjdHMgfSBmcm9tIFwiLi9PYmplY3RzXCI7XHJcbmltcG9ydCB7ZnJvbSwgT2JzZXJ2YWJsZX0gZnJvbSBcInJ4anNcIjtcclxuXHJcbmV4cG9ydCB0eXBlIFR5cGVkQXJyYXkgPSBJbnQ4QXJyYXkgfCBVaW50OEFycmF5IHwgVWludDhDbGFtcGVkQXJyYXkgfCBJbnQxNkFycmF5IHwgVWludDE2QXJyYXkgfCBJbnQzMkFycmF5IHwgVWludDMyQXJyYXkgfCBGbG9hdDMyQXJyYXkgfCBGbG9hdDY0QXJyYXkgfCBCaWdJbnQ2NEFycmF5IHwgQmlnVWludDY0QXJyYXk7XHJcblxyXG4vKipcclxuICogVGhpcyBjbGFzcyBjb25zaXN0cyBleGNsdXNpdmVseSBvZiBzdGF0aWMgbWV0aG9kcyB0aGF0IG9wZXJhdGUgb24gb3IgcmV0dXJuIGFycmF5c1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEFycmF5cyB7XHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBhIGxpc3Qgb2JqZWN0IGluaXRpYWxpemVkIHdpdGggc3BlY2lmaWVkIHZhbHVlc1xyXG4gICAqIEBwYXJhbSBhcmdzIEluaXRpYWwgdmFsdWVzIGJ5IHdoaWNoIHRoZSBsaXN0IHdpbGwgYmUgYmFja2VkXHJcbiAgICogQHJldHVybnMgQSBuZXcgbGlzdCBvYmplY3QgdGhhdCBjb250YWlucyB0aGUgc3BlY2lmaWVzIHZhbHVlc1xyXG4gICAqIEBzdGF0aWNcclxuICAgKi9cclxuICBzdGF0aWMgYXNMaXN0PFQ+KC4uLmFyZ3M6IFRbXSk6IExpc3Q8VD4ge1xyXG4gICAgcmV0dXJuIG5ldyBBcnJheUxpc3Q8VD4oYXJncyk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFNlYXJjaGVzIHRoZSBzcGVjaWZpZWQgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgdmFsdWUgdXNpbmcgdGhlIGJpbmFyeSBzZWFyY2ggYWxnb3JpdGhtLiBUaGUgYXJyYXkgbXVzdCBiZSBzb3J0ZWRcclxuICAgKiBwcmlvciB0byBtYWtpbmcgdGhpcyBjYWxsLiBJZiBpdCBpcyBub3Qgc29ydGVkLCB0aGUgcmVzdWx0cyBhcmUgdW5kZWZpbmVkLiBJZiB0aGUgYXJyYXkgY29udGFpbnMgbXVsdGlwbGUgZWxlbWVudHMgd2l0aFxyXG4gICAqIHRoZSBzcGVjaWZpZWQgdmFsdWUsIHRoZXJlIGlzIG5vIGd1YXJhbnRlZSB3aGljaCBvbmUgd2lsbCBiZSBmb3VuZC5cclxuICAgKiBAcGFyYW0gc29ydGVkQXJyYXkgIFRoZSBhcnJheSB0byBiZSBzZWFyY2hlZFxyXG4gICAqIEBwYXJhbSBrZXkgVGhlIHZhbHVlIHRvIGJlIHNlYXJjaGVkIGZvclxyXG4gICAqIEBwYXJhbSBjb21wYXJlRm4gT3B0aW9uYWwgY29tcGFyZSBmdW5jdGlvblxyXG4gICAqIEByZXR1cm5zIEluZGV4IG9mIHRoZSBzZWFyY2gga2V5LCBpZiBpdCBpcyBjb250YWluZWQgaW4gdGhlIGFycmF5OyBvdGhlcndpc2UgLTFcclxuICAgKiBAc3RhdGljXHJcbiAgICogQHNpbmNlIDAuNS4wXHJcbiAgICovXHJcbiAgc3RhdGljIGJpbmFyeVNlYXJjaDxUPihzb3J0ZWRBcnJheTogQXJyYXk8VD4sIGtleTogVCwgY29tcGFyZUZuPzogQ29tcGFyZTxUPik6IG51bWJlciB7XHJcbiAgICAvLyBMZXQncyBjcmVhdGUgY29tcGFyYXRvciBmcm9tIHRoZSBjb21wYXJlRm4gZnVuY3Rpb24uXHJcbiAgICAvLyBDb21wYXJhdG9yIG9iamVjdCB3aWxsIGdpdmUgdXMgY29tbW9uIGNvbXBhcmlzb24gbWV0aG9kcyBsaWtlIGVxdWFsKCkgYW5kIGxlc3NUaGVuKCkuXHJcbiAgICBjb25zdCBjb21wYXJhdG9yID0gY29tcGFyZUZuID8gbmV3IENvbXBhcmF0b3IoY29tcGFyZUZuKSA6IENvbXBhcmF0b3IuZ2V0SW5zdGFuY2UoKTtcclxuXHJcbiAgICAvLyBUaGVzZSB0d28gaW5kaWNlcyB3aWxsIGNvbnRhaW4gY3VycmVudCBhcnJheSAoc3ViLWFycmF5KSBib3VuZGFyaWVzLlxyXG4gICAgbGV0IHN0YXJ0SW5kZXggPSAwO1xyXG4gICAgbGV0IGVuZEluZGV4ID0gc29ydGVkQXJyYXkubGVuZ3RoIC0gMTtcclxuICAgIGxldCBtaWRkbGVJbmRleDogbnVtYmVyO1xyXG5cclxuICAgIC8vIExldCdzIGNvbnRpbnVlIHRvIHNwbGl0IGFycmF5IHVudGlsIGJvdW5kYXJpZXMgYXJlIGNvbGxhcHNlZFxyXG4gICAgLy8gYW5kIHRoZXJlIGlzIG5vdGhpbmcgdG8gc3BsaXQgYW55bW9yZS5cclxuICAgIHdoaWxlIChzdGFydEluZGV4IDw9IGVuZEluZGV4KSB7XHJcbiAgICAgIC8vIExldCdzIGNhbGN1bGF0ZSB0aGUgaW5kZXggb2YgdGhlIG1pZGRsZSBlbGVtZW50LlxyXG4gICAgICBtaWRkbGVJbmRleCA9IHN0YXJ0SW5kZXggKyBNYXRoLmZsb29yKChlbmRJbmRleCAtIHN0YXJ0SW5kZXgpIC8gMik7XHJcblxyXG4gICAgICAvLyBJZiB3ZSd2ZSBmb3VuZCB0aGUgZWxlbWVudCBqdXN0IHJldHVybiBpdHMgcG9zaXRpb24uXHJcbiAgICAgIGlmIChjb21wYXJhdG9yLmVxdWFsKHNvcnRlZEFycmF5W21pZGRsZUluZGV4XSwga2V5KSkge1xyXG4gICAgICAgIHJldHVybiBtaWRkbGVJbmRleDtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gRGVjaWRlIHdoaWNoIGhhbGYgdG8gY2hvb3NlIGZvciBzZWVraW5nIG5leHQ6IGxlZnQgb3IgcmlnaHQgb25lLlxyXG4gICAgICBpZiAoY29tcGFyYXRvci5sZXNzVGhhbihzb3J0ZWRBcnJheVttaWRkbGVJbmRleF0sIGtleSkpIHtcclxuICAgICAgICAvLyBHbyB0byB0aGUgcmlnaHQgaGFsZiBvZiB0aGUgYXJyYXkuXHJcbiAgICAgICAgc3RhcnRJbmRleCA9IG1pZGRsZUluZGV4ICsgMTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBHbyB0byB0aGUgbGVmdCBoYWxmIG9mIHRoZSBhcnJheS5cclxuICAgICAgICBlbmRJbmRleCA9IG1pZGRsZUluZGV4IC0gMTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy8gUmV0dXJuIC0xIGlmIHdlIGhhdmUgbm90IGZvdW5kIGFueXRoaW5nLlxyXG4gICAgcmV0dXJuIC0xO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdHdvIHNwZWNpZmllZCBhcnJheXMgYXJlIGRlZXBseSBlcXVhbCB0byBvbmUgYW5vdGhlci5cclxuICAgKiBAcGFyYW0gYTEgIG9uZSBhcnJheSB0byBiZSB0ZXN0ZWQgZm9yIGVxdWFsaXR5XHJcbiAgICogQHBhcmFtIGEyICB0aGUgb3RoZXIgYXJyYXkgdG8gYmUgdGVzdGVkIGZvciBlcXVhbGl0eVxyXG4gICAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgdHdvIGFycmF5cyBhcmUgZXF1YWxcclxuICAgKiBAc2luY2UgMC41LjBcclxuICAgKi9cclxuICBzdGF0aWMgZGVlcEVxdWFsczxUPWFueT4oYTE6IEFycmF5PFQ+fG51bGwsIGEyOiBBcnJheTxUPnxudWxsKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gT2JqZWN0cy5kZWVwRXF1YWwoYTEsIGEyKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBfdHJ1ZV8gaWYgdGhlIHR3byBzcGVjaWZpZWQgYXJyYXlzIG9mIGNoYXJzIGFyZSBfZXF1YWxfIHRvIG9uZSBhbm90aGVyLiBUd28gYXJyYXlzIGFyZSBjb25zaWRlcmVkIGVxdWFsIGlmIGJvdGggYXJyYXlzIGNvbnRhaW4gdGhlIHNhbWVcclxuICAgKiBudW1iZXIgb2YgZWxlbWVudHMsIGFuZCBhbGwgY29ycmVzcG9uZGluZyBwYWlycyBvZiBlbGVtZW50cyBpbiB0aGUgdHdvIGFycmF5cyBhcmUgZXF1YWwuIEluIG90aGVyIHdvcmRzLCB0d28gYXJyYXlzIGFyZSBlcXVhbCBpZiB0aGV5IGNvbnRhaW5cclxuICAgKiB0aGUgc2FtZSBlbGVtZW50cyBpbiB0aGUgc2FtZSBvcmRlci4gQWxzbywgdHdvIGFycmF5IHJlZmVyZW5jZXMgYXJlIGNvbnNpZGVyZWQgZXF1YWwgaWYgYm90aCBhcmUgX251bGxfLlxyXG4gICAqIEBwYXJhbSBhcnIxIG9uZSBhcnJheSB0byBiZSB0ZXN0ZWQgZm9yIGVxdWFsaXR5XHJcbiAgICogQHBhcmFtIGFycjIgdGhlIG90aGVyIGFycmF5IHRvIGJlIHRlc3RlZCBmb3IgZXF1YWxpdHlcclxuICAgKiBAcmV0dXJucyBfdHJ1ZV8gaWYgdGhlIHR3byBhcnJheXMgYXJlIGVxdWFsXHJcbiAgICogQHNpbmNlIDAuNS4wXHJcbiAgICovXHJcbiAgc3RhdGljIGVxdWFsczxUPWFueT4oYXJyMTogQXJyYXk8VD4sIGFycjI6IEFycmF5PFQ+KTogYm9vbGVhbiB7XHJcbiAgICBsZXQgZXE6IGJvb2xlYW4gPSAoKGFycjEgPT0gbnVsbCAmJiBhcnIyID09IG51bGwpIHx8IGFycjEgPT09IGFycjIpO1xyXG4gICAgaWYgKCFlcSkge1xyXG4gICAgICBlcSA9IE9iamVjdHMuZGVlcEVxdWFsKGFycjEsIGFycjIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGVxO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBQYWRzIHRoZSBzb3VyY2UgYXJyYXkgd2l0aCBhIGdpdmVuIGBmaWxsZXJgIHZhbHVlIChwb3NzaWJseSByZXBlYXRlZCkgc28gdGhhdCB0aGUgYXJyYXkncyBzaXplIHJlYWNoZXMgYSBnaXZlbiBsZW5ndGggYGxlbmAuXHJcbiAgICogRmlsbGluZyBpcyBwZXJmb3JtZWQgZnJvbSB0aGUgZW5kIG9mIHRoZSBzb3VyY2UgYXJyYXkuXHJcbiAgICogQHBhcmFtIGFyciBTb3VyY2UgYXJyYXlcclxuICAgKiBAcGFyYW0gbGVuIFJlcXVpcmVkIG1pbmltdW0gc2l6ZSBvZiB0aGUgc291cmNlIGFycmF5XHJcbiAgICogQHBhcmFtIGZpbGxlciBUaGUgdmFsdWUgdG8gYmUgZmlsbGVkIGluXHJcbiAgICogQHJldHVybnMgU291cmNlIGFycmF5IHdpdGggbW9kaWZpZWQgbGVuZ3RoXHJcbiAgICogQHN0YXRpY1xyXG4gICAqIEBzaW5jZSAwLjUuMFxyXG4gICAqIEBzZWUge0BsaW5rIHBhZFN0YXJ0fVxyXG4gICAqL1xyXG4gIHN0YXRpYyBwYWRFbmQ8VD4oYXJyOiBUW10sIGxlbjogbnVtYmVyLCBmaWxsZXI6IFQpOiBBcnJheTxUPiB7XHJcbiAgICBpZiAobGVuID4gYXJyLmxlbmd0aCkge1xyXG4gICAgICBjb25zdCBvbGRMZW4gPSBhcnIubGVuZ3RoO1xyXG4gICAgICBhcnIubGVuZ3RoID0gbGVuO1xyXG4gICAgICByZXR1cm4gYXJyLmZpbGwoZmlsbGVyLCBvbGRMZW4pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFycjtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUGFkcyB0aGUgc291cmNlIGFycmF5IHdpdGggYSBnaXZlbiBgZmlsbGVyYCB2YWx1ZSAocG9zc2libHkgcmVwZWF0ZWQpIHNvIHRoYXQgdGhlIGFycmF5J3Mgc2l6ZSByZWFjaGVzIGEgZ2l2ZW4gbGVuZ3RoIGBsZW5gLlxyXG4gICAqIEZpbGxpbmcgaXMgcGVyZm9ybWVkIGZyb20gdGhlIHN0YXJ0IG9mIHRoZSBzb3VyY2UgYXJyYXkuXHJcbiAgICogQHBhcmFtIGFyciBTb3VyY2UgYXJyYXlcclxuICAgKiBAcGFyYW0gbGVuIFJlcXVpcmVkIG1pbmltdW0gc2l6ZSBvZiB0aGUgc291cmNlIGFycmF5XHJcbiAgICogQHBhcmFtIGZpbGxlciBUaGUgdmFsdWUgdG8gYmUgZmlsbGVkIGluXHJcbiAgICogQHJldHVybnMgU291cmNlIGFycmF5IHdpdGggbW9kaWZpZWQgbGVuZ3RoXHJcbiAgICogQHN0YXRpY1xyXG4gICAqIEBzaW5jZSAwLjUuMFxyXG4gICAqIEBzZWUge0BsaW5rIHBhZEVuZH1cclxuICAgKi9cclxuICBzdGF0aWMgcGFkU3RhcnQ8VD4oYXJyOiBUW10sIGxlbjogbnVtYmVyLCBmaWxsZXI6IFQpOiBBcnJheTxUPiB7XHJcbiAgICBpZiAobGVuID4gYXJyLmxlbmd0aCkge1xyXG4gICAgICBjb25zdCB2YWxzID0gQXJyYXkobGVuIC0gYXJyLmxlbmd0aCkuZmlsbChmaWxsZXIpO1xyXG4gICAgICBhcnIudW5zaGlmdCguLi52YWxzKTtcclxuICAgIH1cclxuICAgIHJldHVybiBhcnI7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIENvcGllcyB0aGUgc3BlY2lmaWVkIGFycmF5LCB0cnVuY2F0aW5nIG9yIHBhZGRpbmcgd2l0aCBudWxsIGNoYXJhY3RlcnMgKGlmIG5lY2Vzc2FyeSksIHNvIHRoZSBjb3B5IGhhcyB0aGUgc3BlY2lmaWVkIGxlbmd0aFxyXG4gICAqIEBwYXJhbSBhcnIgVGhlIGFycmF5IHRvIGJlIGNvcGllZFxyXG4gICAqIEBwYXJhbSBuZXdMZW5ndGggIFRoZSBsZW5ndGggb2YgdGhlIGNvcHkgdG8gYmUgcmV0dXJuZWRcclxuICAgKiBAcmV0dXJucyBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGFycmF5LCB0cnVuY2F0ZWQgb3IgcGFkZGVkIHdpdGggbnVsbCBjaGFyYWN0ZXJzIHRvIG9idGFpbiB0aGUgc3BlY2lmaWVkIGxlbmd0aFxyXG4gICAqIEBzdGF0aWNcclxuICAgKiBAc2luY2UgMC41LjBcclxuICAgKi9cclxuICBzdGF0aWMgY29weU9mPFQ+KGFycjogVFtdLCBuZXdMZW5ndGg/OiBudW1iZXIpOiBBcnJheTxUIHwgbnVsbD4ge1xyXG4gICAgaWYgKG5ld0xlbmd0aCAhPSBudWxsICYmIG5ld0xlbmd0aCA+IDApIHtcclxuICAgICAgaWYgKG5ld0xlbmd0aCA8PSBhcnIubGVuZ3RoKSB7XHJcbiAgICAgICAgcmV0dXJuIGFyci5zbGljZSgwLCBuZXdMZW5ndGgpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGNvcHlBcnIgPSBhcnIuc2xpY2UoKTtcclxuICAgICAgcmV0dXJuIEFycmF5cy5wYWRFbmQoY29weUFyciwgbmV3TGVuZ3RoLCBudWxsKTtcclxuICAgIH1cclxuICAgIHJldHVybiBhcnIuc2xpY2UoKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBhIHNlcXVlbnRpYWwgYE9ic2VydmFibGVgIG9iamVjdCB3aXRoIHRoZSBzcGVjaWZpZWQgYXJyYXkgYXMgaXRzIHNvdXJjZVxyXG4gICAqIEBwYXJhbSBhcnIgVGhlIGFycmF5LCBhc3N1bWVkIHRvIGJlIHVubW9kaWZpZWQgZHVyaW5nIHVzZVxyXG4gICAqIEByZXR1cm5zIEFuIE9ic2VydmFibGUgZm9yIHRoZSBhcnJheSBgYXJyYFxyXG4gICAqIEBzaW5jZSAwLjUuMFxyXG4gICAqL1xyXG4gIHN0YXRpYyBzdHJlYW08VD4oYXJyOiBUW10pOiBPYnNlcnZhYmxlPFQ+IHtcclxuICAgIHJldHVybiBmcm9tKGFycik7XHJcbiAgfVxyXG59XHJcbiJdfQ==