@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
JavaScript
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==