• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16// Autogenerated file. DO NOT EDIT
17package escompat
18
19// initialized in _initializerBlock_.ets
20const IS_LITTLE_ENDIAN: boolean;
21
22class Uint8ClampedArrayIteratorKeys implements IterableIterator<number> {
23    private length: int = 0
24    private idx: int = 0
25
26    constructor(parent: Uint8ClampedArray) {
27        this.length = parent.length as int
28    }
29
30    public override $_iterator(): IterableIterator<Number> {
31        return this
32    }
33
34    override next(): IteratorResult<number> {
35        if (this.idx < 0 || this.idx >= this.length) {
36            return new IteratorResult<number>()
37        }
38        return new IteratorResult<number>(false, this.idx++ as number)
39    }
40}
41
42class Uint8ClampedArrayIterator implements IterableIterator<Number> {
43    private parent: Uint8ClampedArray
44    private idx: int = 0
45
46    constructor(parent: Uint8ClampedArray) {
47        this.parent = parent
48    }
49
50    public override $_iterator(): IterableIterator<Number> {
51        return this
52    }
53
54    override next(): IteratorResult<Number> {
55        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
56            return new IteratorResult<Number>()
57        }
58        return new IteratorResult<Number>(false, new Number(this.parent[this.idx++]))
59    }
60}
61
62class Uint8ClampedArrayIteratorEntries implements IterableIterator<[Number, Number]> {
63    private parent: Uint8ClampedArray
64    private idx: int = 0
65
66    constructor(parent: Uint8ClampedArray) {
67        this.parent = parent
68    }
69
70    public override $_iterator(): IterableIterator<[Number, Number]> {
71        return this
72    }
73
74    override next(): IteratorResult<[Number, Number]> {
75        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
76            return new IteratorResult<[Number, Number]>()
77        }
78        return new IteratorResult<[Number, Number]>(
79            false,
80            [new Number(this.idx), new Number(this.parent[this.idx++])]
81        )
82    }
83}
84
85/**
86 * JS Uint8ClampedArray API-compatible class
87 */
88export final class Uint8ClampedArray implements Iterable<Number>, ArrayLike<Number> {
89    public static readonly BYTES_PER_ELEMENT: number = 1
90    public readonly BYTES_PER_ELEMENT: number = Uint8ClampedArray.BYTES_PER_ELEMENT
91
92    /** Underlying Buffer */
93    public readonly buffer: ArrayBuffer
94
95    internal readonly byteOffsetInt: int
96    internal readonly byteLengthInt: int
97    internal readonly lengthInt: int
98
99    /**
100     * Creates an empty Uint8ClampedArray.
101     */
102    public constructor() {
103        this(0 as int)
104    }
105
106    /**
107     * Creates an Uint8ClampedArray with respect to data accessed via Iterable<Number> interface
108     */
109    public constructor(elements: Iterable<Number>) {
110        const items: Object = elements as Object
111        if (items instanceof ArrayLike) {
112            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
113            this.byteLengthInt = arr.length as int * Uint8ClampedArray.BYTES_PER_ELEMENT as int
114            this.lengthInt = arr.length as int
115            this.buffer = new ArrayBuffer(this.byteLengthInt)
116            this.byteOffsetInt = 0
117            for (let i: int = 0; i < this.lengthInt; ++i) {
118                this.setUnsafeClamp(i, arr.$_get(i) as int)
119            }
120        } else {
121            let x = Uint8ClampedArray.from(elements)
122            this.byteLengthInt = x.byteLengthInt
123            this.lengthInt = x.lengthInt
124            this.buffer = x.buffer
125            this.byteOffsetInt = x.byteOffsetInt
126        }
127    }
128
129    /**
130     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
131     *
132     * @param buf data initializer
133     *
134     * @param byteOffset byte offset from begin of the buf
135     *
136     * @param length size of elements of type int in newly created Uint8ClampedArray
137     */
138    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined, length: Number | undefined) {
139        let intByteOffset: int = 0
140        if (byteOffset != undefined) {
141            intByteOffset = byteOffset.toInt()
142            if (intByteOffset < 0) {
143                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
144            }
145        }
146        let intByteLength: int = buf.getByteLength() - intByteOffset
147        if (intByteLength < 0) {
148            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
149        }
150
151        let intLength: int
152        if (length != undefined) {
153            intLength = length.toInt()
154            if (intLength > intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int) {
155                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
156            }
157        } else {
158            intLength = intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int
159        }
160        if (intLength < 0) {
161            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
162        }
163        if (intLength < intByteLength / Uint8ClampedArray.BYTES_PER_ELEMENT as int) {
164            intByteLength = intLength * Uint8ClampedArray.BYTES_PER_ELEMENT as int
165        }
166        this.byteLengthInt = intByteLength
167        this.byteOffsetInt = intByteOffset
168        this.lengthInt = intLength
169        this.buffer = buf
170    }
171
172    /**
173     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
174     *
175     * @param buf data initializer
176     *
177     * @param byteOffset byte offset from begin of the buf
178     */
179    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined) {
180        this(buf, byteOffset, undefined)
181    }
182
183    /**
184     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
185     *
186     * @param buf data initializer
187     *
188     * @param byteOffset byte offset from begin of the buf
189     *
190     * @param length size of elements of type int in newly created Uint8ClampedArray
191     */
192    public constructor(buf: ArrayBuffer, byteOffset: number, length: number) {
193        this(buf, new Number(byteOffset), new Number(length))
194    }
195
196    /**
197     * Creates an Uint8ClampedArray with respect to buf and byteOffset.
198     *
199     * @param buf data initializer
200     *
201     * @param byteOffset byte offset from begin of the buf
202     */
203    public constructor(buf: ArrayBuffer, byteOffset: number) {
204        this(buf, new Number(byteOffset), undefined)
205    }
206
207    /**
208     * Creates an Uint8ClampedArray with respect to data, byteOffset and length.
209     *
210     * @param buf data initializer
211     *
212     * @param byteOffset byte offset from begin of the buf
213     *
214     * @param length size of elements of type int in newly created Uint8ClampedArray
215     */
216    public constructor(buf: ArrayBuffer, byteOffset: int, length: int) {
217        this(buf, new Number(byteOffset), new Number(length))
218    }
219
220    /**
221     * Creates an Uint8ClampedArray with respect to buf and byteOffset.
222     *
223     * @param buf data initializer
224     *
225     * @param byteOffset byte offset from begin of the buf
226     */
227    public constructor(buf: ArrayBuffer, byteOffset: int) {
228        this(buf, new Number(byteOffset), undefined)
229    }
230
231    /**
232     * Creates an Uint8ClampedArray with respect to buf.
233     *
234     * @param buf data initializer
235     */
236    public constructor(buf: ArrayLike<Number> | ArrayBuffer) {
237        if (buf instanceof ArrayBuffer) {
238            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
239            if (this.byteLengthInt % Uint8ClampedArray.BYTES_PER_ELEMENT as int != 0) {
240               throw new RangeError("ArrayBuffer.byteLength should be multiple of int as Uint8ClampedArray.BYTES_PER_ELEMENT")
241            }
242            this.lengthInt = this.byteLengthInt / Uint8ClampedArray.BYTES_PER_ELEMENT as int
243            this.buffer = buf as ArrayBuffer
244            this.byteOffsetInt = 0
245        } else if (buf instanceof ArrayLike) {
246            // NOTE (ikorobkov): dealing with this overload is tricky
247            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.ets
248            let arr = Array.from<Number>((buf as ArrayLike<Number>))
249            this.byteLengthInt = arr.length as int * Uint8ClampedArray.BYTES_PER_ELEMENT as int
250            this.lengthInt = arr.length as int
251            this.buffer = new ArrayBuffer(this.byteLengthInt)
252            this.byteOffsetInt = 0
253            for (let i: int = 0; i < this.lengthInt; ++i) {
254                this.setUnsafe(i, Uint8ClampedArray.clamp(arr.$_get(i).toInt()))
255            }
256        } else {
257            throw new Error("unexpected type of buf")
258        }
259    }
260
261    /**
262     * Creates an Uint8ClampedArray with respect to length.
263     *
264     * @param length data initializer
265     */
266    public constructor(length: int) {
267        this(length as number)
268    }
269
270    /**
271     * Creates an Uint8ClampedArray with respect to length.
272     *
273     * @param length data initializer
274     */
275    public constructor(length: number) {
276        if (length < 0 || length > (Int.MAX_VALUE / Uint8ClampedArray.BYTES_PER_ELEMENT)) {
277            throw new TypeError("Type Error: length " + length + " is outside the bounds of the buffer")
278        }
279        this.lengthInt = length as int
280        this.byteLengthInt = this.lengthInt * Uint8ClampedArray.BYTES_PER_ELEMENT as int
281        this.byteOffsetInt = 0
282        this.buffer = new ArrayBuffer(this.byteLengthInt)
283    }
284
285    /**
286     * Creates a copy of Uint8ClampedArray.
287     *
288     * @param other data initializer
289     */
290    public constructor(other: Uint8ClampedArray) {
291        this.buffer = other.buffer.slice(other.byteOffset as int, (other.byteOffset + other.byteLength) as int) as ArrayBuffer
292        this.byteLengthInt = other.byteLength as int
293        this.lengthInt = other.length as int
294        this.byteOffsetInt = 0
295    }
296
297    /**
298     * Creates an Uint8ClampedArray from FixedArray<number>
299     */
300    public constructor(numbers: FixedArray<number>) {
301        this(numbers.length)
302        for (let i: int = 0; i < this.lengthInt; ++i) {
303            this.setUnsafeClamp(i, numbers[i] as int)
304        }
305    }
306
307    /**
308     * Creates an Uint8ClampedArray from FixedArray<int>
309     */
310    public constructor(numbers: FixedArray<int>) {
311        this(numbers.length)
312        for (let i: int = 0; i < this.lengthInt; ++i) {
313            this.setUnsafeClamp(i, numbers[i] as int)
314        }
315    }
316
317    /**
318     * Iteratorable interface implementation
319     *
320     * @returns iterator over all elements
321     */
322    public override $_iterator(): IterableIterator<Number> {
323         return this.values()
324    }
325
326    /**
327     * Returns an instance of primitive type at passed index.
328     *
329     * @param index index to look at
330     *
331     * @returns a primitive at index
332     */
333    public at(index: number): Number | undefined {
334        return this.at(index as int)
335    }
336
337    /**
338     * Returns an instance of primitive type at passed index if index is correct.
339     *
340     * @param index index to look at
341     *
342     * @returns a primitive at index
343     */
344    public at(index: int): Number | undefined {
345        let k: int
346        if (index >= 0) {
347            k = index
348        } else {
349            k = this.lengthInt + index
350        }
351        if (k < 0 || k >= this.lengthInt) {
352            return undefined
353        }
354        return new Number(this.getUnsafe(k))
355    }
356
357    /**
358     * Returns an instance of number at passed index.
359     *
360     * @param index index to look at
361     *
362     * @returns a primitive at index
363     */
364    public override $_get(index: number): Number {
365        return this.$_get(index as int) as Number
366    }
367
368    /**
369     * Returns an instance of number at passed index.
370     *
371     * @param index index to look at
372     *
373     * @returns a primitive at index
374     */
375    public native $_get(i: int): number
376
377    /**
378     * Assigns val as element on index.
379     *
380     * @param val value to set
381     *
382     * @param index index to change
383     */
384    public $_set(index: number, val: number): void {
385        this.$_set(index as int, val)
386    }
387
388    /**
389     * Assigns val as element on index.
390     *
391     * @param val value to set
392     *
393     * @param index index to change
394     */
395    public $_set(index: int, val: number): void {
396        this.$_set(index, val as int)
397    }
398
399    /**
400     * Assigns val as element on index.
401     *
402     * @param val value to set
403     *
404     * @param index index to change
405     */
406    public $_set(index: number, val: int): void {
407        this.$_set(index as int, val)
408    }
409
410    /**
411     * Assigns val as element on index.
412     *
413     * @param val value to set
414     *
415     * @param index index to change
416     */
417    public native $_set(index: int, val: int): void
418
419    /**
420     * Makes a copy of internal elements to targetPos from startPos to endPos.
421     *
422     * @param target insert index to place copied elements
423     *
424     * @param start start index to begin copy from
425     *
426     * @param end last index to end copy from, excluded
427     *
428     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
429     */
430    public copyWithin(target: number, start: number, end?: number): Uint8ClampedArray {
431        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
432    }
433
434    /**
435     * Makes a copy of internal elements to targetPos from startPos to endPos.
436     *
437     * @param target insert index to place copied elements
438     *
439     * @param start start index to begin copy from
440     *
441     * @param end last index to end copy from, excluded
442     *
443     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
444     */
445    public copyWithin(target: int, start: number, end?: number): Uint8ClampedArray {
446        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
447    }
448
449    /**
450     * Makes a copy of internal elements to targetPos from startPos to endPos.
451     *
452     * @param target insert index to place copied elements
453     *
454     * @param start start index to begin copy from
455     *
456     * @param end last index to end copy from, excluded
457     *
458     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
459     */
460    public copyWithin(target: number, start: int, end?: number): Uint8ClampedArray {
461        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
462    }
463
464    /**
465     * Makes a copy of internal elements to targetPos from startPos to endPos.
466     *
467     * @param target insert index to place copied elements
468     *
469     * @param start start index to begin copy from
470     *
471     * @param end last index to end copy from, excluded
472     *
473     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
474     */
475    public copyWithin(target: int, start: int, end?: number): Uint8ClampedArray {
476        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
477    }
478
479    /**
480     * Makes a copy of internal elements to targetPos from startPos to endPos.
481     *
482     * @param insert insert index to place copied elements
483     *
484     * @param start start index to begin copy from
485     *
486     * @param end last index to end copy from, excluded
487     *
488     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
489     */
490    public native copyWithin(target: int, start: int, end: int): Uint8ClampedArray
491
492    /**
493     * Makes a copy of internal elements to targetPos from begin to end of Uint8ClampedArray.
494     *
495     * @param target insert index to place copied elements
496     *
497     * See rules of parameters normalization:
498     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
499     */
500    public copyWithin(target: number): Uint8ClampedArray {
501        return this.copyWithin(target as int)
502    }
503
504    /**
505     * Makes a copy of internal elements to targetPos from begin to end of Uint8ClampedArray.
506     *
507     * @param insert insert index to place copied elements
508     *
509     * See rules of parameters normalization:
510     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
511     */
512    public copyWithin(target: int): Uint8ClampedArray {
513        return this.copyWithin(target, 0, this.lengthInt)
514    }
515
516    /**
517     * Returns an array of key, value pairs for every entry in the Uint8ClampedArray
518     *
519     * @returns key, value pairs for every entry in the array
520     */
521    public entries(): IterableIterator<[Number, Number]> {
522        return new Uint8ClampedArrayIteratorEntries(this)
523    }
524
525    /**
526     * Fills the Uint8ClampedArray with specified value
527     *
528     * @param value new value
529     *
530     * @returns modified Uint8ClampedArray
531     */
532    public fill(value: number, start?: number, end?: number): Uint8ClampedArray {
533        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
534        return this
535    }
536
537    /**
538     * Fills the Uint8ClampedArray with specified value
539     *
540     * @param value new value
541     *
542     * @returns modified Uint8ClampedArray
543     */
544    public fill(value: number, start: int, end?: number): Uint8ClampedArray {
545        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
546        return this
547    }
548
549    /**
550     * Fills the Uint8ClampedArray with specified value
551     *
552     * @param value new value
553     *
554     * @returns modified Uint8ClampedArray
555     */
556    public fill(value: number, start: int, end: number): Uint8ClampedArray {
557        this.fill(value as int, start as int, end as int)
558        return this
559    }
560
561    /**
562     * Fills the Uint8ClampedArray with specified value
563     *
564     * @param value new value
565     *
566     * @returns modified Uint8ClampedArray
567     */
568    public fill(value: number, start: number, end: int): Uint8ClampedArray {
569        this.fill(value as int, start as int, end as int)
570        return this
571    }
572
573    /**
574     * Fills the Uint8ClampedArray with specified value
575     *
576     * @param value new value
577     *
578     * @returns modified Uint8ClampedArray
579     */
580    public fill(value: number, start: int, end: int): Uint8ClampedArray {
581        this.fill(value as int, start as int, end as int)
582        return this
583    }
584
585    /**
586     * Fills the Uint8ClampedArray with specified value
587     *
588     * @param value new value
589     *
590     * @returns modified Uint8ClampedArray
591     */
592    public fill(value: int, start?: number, end?: number): Uint8ClampedArray {
593        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
594        return this
595    }
596
597    /**
598     * Fills the Uint8ClampedArray with specified value
599     *
600     * @param value new value
601     *
602     * @returns modified Uint8ClampedArray
603     */
604    public fill(value: int, start: int, end?: number): Uint8ClampedArray {
605        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
606        return this
607    }
608
609    /**
610     * Fills the Uint8ClampedArray with specified value
611     *
612     * @param value new value
613     *
614     * @returns modified Uint8ClampedArray
615     */
616    public fill(value: int, start: int, end: number): Uint8ClampedArray {
617        this.fill(value, start as int, end as int)
618        return this
619    }
620
621    /**
622     * Fills the Uint8ClampedArray with specified value
623     *
624     * @param value new value
625     *
626     * @returns modified Uint8ClampedArray
627     */
628    public fill(value: int, start: number, end: int): Uint8ClampedArray {
629        this.fill(value, start as int, end as int)
630        return this
631    }
632
633    /**
634     * Fills the Uint8ClampedArray with specified value
635     *
636     * @param value new value
637     *
638     * @returns modified Uint8ClampedArray
639     */
640    public fill(value: int, start: int, end: int): Uint8ClampedArray {
641        value = Uint8ClampedArray.clamp(value)
642        const k = normalizeIndex(start, this.lengthInt)
643        const finalPos = normalizeIndex(end, this.lengthInt)
644        this.fillInternal(value, k, finalPos)
645        return this
646    }
647
648    private final native fillInternal(value: int, start: int, end: int): void
649
650    /**
651     * Assigns val as element on index.
652     *
653     * @param val value to set
654     *
655     * @param index index to change
656     */
657    public set(insertPos: number, val: number): void {
658        this.$_set(insertPos as int, val)
659    }
660
661    /**
662     * Assigns val as element on index.
663     *
664     * @param val value to set
665     *
666     * @param index index to change
667     */
668    public set(insertPos: int, val: number): void {
669        this.$_set(insertPos as int, val)
670    }
671
672    /**
673     * Assigns val as element on index.
674     *
675     * @param val value to set
676     *
677     * @param index index to change
678     */
679    public set(insertPos: number, val: int): void {
680        this.$_set(insertPos as int, val)
681    }
682
683    /**
684     * Assigns val as element on index.
685     *
686     * @param val value to set
687     *
688     * @param index index to change
689     */
690    public set(insertPos: int, val: int): void {
691        this.$_set(insertPos as int, val)
692    }
693
694    /**
695     * Copies all elements of arr to the current Uint8ClampedArray starting from insertPos.
696     *
697     * @param arr array to copy data from
698     *
699     * @param insertPos start index where data from arr will be inserted
700     *
701     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
702     */
703    public set(arr: FixedArray<number>, insertPos1: number): void {
704        const insertPos = insertPos1 as int
705        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
706            throw new RangeError("set(insertPos: int, arr: FixedArray<int>): size of arr is greater than Uint8ClampedArray.length")
707        }
708        for (let i = 0; i < arr.length; i++) {
709            this.setUnsafeClamp(insertPos as int + i as int, arr[i] as int)
710        }
711    }
712
713    /**
714     * Copies all elements of arr to the current Uint8ClampedArray starting from insertPos.
715     *
716     * @param arr array to copy data from
717     *
718     * @param insertPos start index where data from arr will be inserted
719     *
720     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
721     */
722    public set(arr: FixedArray<int>, insertPos: int): void {
723        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
724            throw new RangeError("set(insertPos: int, arr: FixedArray<int>): size of arr is greater than Uint8ClampedArray.length")
725        }
726        for (let i = 0; i < arr.length; i++) {
727            this.setUnsafeClamp(insertPos + i, arr[i])
728        }
729    }
730
731    /**
732     * Copies all elements of arr to the current Uint8ClampedArray.
733     *
734     * @param arr array to copy data from
735     */
736    public set(arr: FixedArray<number>): void {
737        this.set(arr, 0)
738    }
739
740    /**
741     * Copies all elements of arr to the current Uint8ClampedArray.
742     *
743     * @param arr array to copy data from
744     */
745    public set(arr: FixedArray<int>): void {
746        this.set(arr, 0)
747    }
748
749    public native set(array: Uint8ClampedArray): void
750
751    public native set(array: Uint8ClampedArray, offset: number): void
752
753    /**
754     * Copies elements from an ArrayLike object to the Uint8ClampedArray.
755     *
756     * @param array An ArrayLike object containing the elements to copy.
757     *
758     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
759     */
760    public set(array: ArrayLike<number>, offset: number = 0): void {
761        const insertPos = offset as int
762        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
763            throw new RangeError("offset is out of bounds")
764        }
765        for (let i = array.length - 1; i >= 0; --i) {
766            this.setUnsafeClamp(insertPos as int + i as int, array[i] as int)
767        }
768    }
769
770    /**
771     * Returns a new array from a set of elements.
772     *
773     * @param items a set of elements to include in the new array object.
774     *
775     * @returns new Uint8ClampedArray
776     */
777    public static of(...items: FixedArray<number>): Uint8ClampedArray {
778        let res = new Uint8ClampedArray(items.length as int)
779        for (let i: int = 0; i < items.length; i++) {
780            res.setUnsafeClamp(i, items[i] as int)
781        }
782        return res
783    }
784
785    /**
786     * Returns a new array from a set of elements.
787     *
788     * @param items a set of elements to include in the new array object.
789     *
790     * @returns new Uint8ClampedArray
791     */
792    public static of(...items: FixedArray<int>): Uint8ClampedArray {
793        let res = new Uint8ClampedArray(items.length as int)
794        for (let i: int = 0; i < items.length; i++) {
795            res.setUnsafeClamp(i, items[i])
796        }
797        return res
798    }
799
800    /**
801     * Returns a new array from a set of elements.
802     *
803     * @param items a set of elements to include in the new array object.
804     *
805     * @returns new Uint8ClampedArray
806     */
807    public static of(...items: FixedArray<short>): Uint8ClampedArray {
808        let res = new Uint8ClampedArray(items.length as int)
809        for (let i: int = 0; i < items.length; i++) {
810            res.setUnsafeClamp(i, items[i] as int)
811        }
812        return res
813    }
814
815    /**
816     * Returns a new array from a set of elements.
817     *
818     * @param items a set of elements to include in the new array object.
819     *
820     * @returns new Uint8ClampedArray
821     */
822    public static of(): Uint8ClampedArray {
823        return new Uint8ClampedArray(0 as int)
824    }
825
826    /**
827     * Creates an array from an array-like or iterable object.
828     *
829     * @param arrayLike An array-like or iterable object to convert to an array.
830     *
831     * @returns new Uint8ClampedArray
832     */
833    public static from(arr: ArrayLike<number>): Uint8ClampedArray {
834        return Uint8ClampedArray.from<number>(arr, (x: number, k: number): number => x)
835    }
836
837    /**
838     * Creates an array from an array-like or iterable object.
839     *
840     * @param arrayLike An array-like or iterable object to convert to an array.
841     *
842     * @param mapfn A mapping function to call on every element of the array.
843     *
844     * @returns new Uint8ClampedArray
845     */
846    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint8ClampedArray {
847        if (mapfn == undefined) {
848            mapfn = (v: number, k: number): number => { return v }
849        }
850
851        let iter = arrayLike.$_iterator()
852        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
853        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
854        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
855        //  we can make one pass through the iterator without the need for memory reallocation.
856        const maybeLength = tryGetIteratorLength(arrayLike)
857        if (maybeLength) {
858            const result = new Uint8ClampedArray(maybeLength)
859            for (let i = 0; i < maybeLength; ++i) {
860                const x = iter.next()
861                if (x.done) {
862                    return new Uint8ClampedArray(result.buffer, 0, i)
863                }
864                result.setUnsafeClamp(i, (mapfn)!(x.value!, i) as int)
865            }
866            return result
867        }
868
869        // NOTE (templin.konstantin): Create builtin array as buffer
870        let temp = new Uint8ClampedArray(6)
871        let index : FixedArray<int> = new int[1]
872        index[0] = 0
873
874        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
875            if (index[0] + 1 > temp.lengthInt) {
876                // NOTE (templin.konstantin): Progressive reallocation
877                const curLength = (temp.buffer as Buffer).getByteLength()
878                const tb = new ArrayBuffer(curLength * 2)
879                for (let i = 0; i < curLength; ++i) {
880                    tb.set(i, (temp.buffer as Buffer).at(i))
881                }
882                temp = new Uint8ClampedArray(tb)
883            }
884            temp.setUnsafeClamp(index[0], (mapfn)!(x, index[0]) as int)
885            index[0]++
886        })
887
888        return new Uint8ClampedArray(temp.buffer, 0, index[0])
889    }
890
891    /**
892     * Creates an array from an array-like or iterable object.
893     *
894     * @param arrayLike An array-like or iterable object to convert to an array.
895     *
896     * @param mapfn A mapping function to call on every element of the array.
897     *
898     * @returns new Uint8ClampedArray
899     */
900    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint8ClampedArray {
901        let res = new Uint8ClampedArray(arrayLike.length)
902        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
903        const idx : FixedArray<int> = new int[1]
904        idx[0] = 0
905        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
906            res.setUnsafeClamp(idx[0], mapfn(x as T, idx[0] as number) as int)
907            idx[0] += 1
908        })
909        return res
910    }
911
912    /**
913     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
914     *
915     * @param searchElement The element to search for
916     *
917     * @param fromIndex The position in this array at which to begin searching for searchElement
918     *
919     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
920     */
921    public includes(searchElement: number, fromIndex?: number): boolean {
922        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
923    }
924
925    /**
926     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
927     *
928     * @param searchElement The element to search for
929     *
930     * @param fromIndex The position in this array at which to begin searching for searchElement
931     *
932     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
933     */
934    public includes(searchElement: int, fromIndex: int): boolean {
935        return this.indexOf(searchElement as int, fromIndex) != -1
936    }
937
938    /**
939     * Determines whether Uint8ClampedArray includes a certain element, returning true or false as appropriate
940     *
941     * @param searchElement The element to search for
942     *
943     * @param fromIndex The position in this array at which to begin searching for searchElement
944     *
945     * @returns true if searchElement is in Uint8ClampedArray, false otherwise
946     */
947    public includes(searchElement: int): boolean {
948        return this.indexOf(searchElement as int, 0) != -1
949    }
950
951    /**
952     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
953     *
954     * @param searchElement The value to locate in the array.
955     *
956     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
957     *  search starts at index 0.
958     *
959     * @returns index of element if it presents, -1 otherwise
960     */
961    public indexOf(searchElement: number, fromIndex?: number): number {
962        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
963    }
964
965    /**
966     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
967     *
968     * @param searchElement The value to locate in the array.
969     *
970     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
971     *  search starts at index 0.
972     *
973     * @returns index of element if it presents, -1 otherwise
974     */
975    public indexOf(searchElement: number, fromIndex: int): number {
976            return this.indexOfImpl(searchElement, fromIndex)
977    }
978
979    /**
980     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
981     *
982     * @param searchElement The value to locate in the array.
983     *
984     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
985     *  search starts at index 0.
986     *
987     * @returns index of element if it presents, -1 otherwise
988     */
989    public indexOf(searchElement: int, fromIndex: int): number {
990        return this.indexOfImpl(searchElement as long, fromIndex)
991    }
992
993    /**
994     * Returns the index of the first occurrence of a value in Array.
995     *
996     * @param searchElement The value to locate in the array.
997     *
998     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
999     *  search starts at index 0.
1000     *
1001     * @returns index of element if it presents, -1 otherwise
1002     */
1003    private final native indexOfImpl(searchElement: number, fromIndex: int): number
1004
1005    /**
1006     * Returns the index of the first occurrence of a value in Array.
1007     *
1008     * @param searchElement The value to locate in the array.
1009     *
1010     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1011     *  search starts at index 0.
1012     *
1013     * @returns index of element if it presents, -1 otherwise
1014     */
1015    private final native indexOfImpl(searchElement: long, fromIndex: int): number
1016
1017    /**
1018     * Returns the index of the first occurrence of a value in Uint8ClampedArray.
1019     *
1020     * @param searchElement The value to locate in the array.
1021     *
1022     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1023     *  search starts at index 0.
1024     *
1025     * @returns index of element if it presents, -1 otherwise
1026     */
1027    public indexOf(searchElement: int): number {
1028        return this.indexOf(searchElement, 0)
1029    }
1030
1031
1032    /**
1033     * Converts all elements of an array to strings and joins them using the specified separator.
1034     *
1035     * @param separator - separates one element of an array from the next in the resulting String.
1036     *
1037     * @returns joined representation
1038     */
1039    private final native joinInternal(separator: String): string;
1040
1041    /**
1042     * Adds all the elements of an array separated by the specified separator string
1043     *
1044     * @param separator A string used to separate one element of an array from the next in the
1045     * resulting String. If omitted, the array elements are separated with a comma
1046     *
1047     * @returns joined representation
1048     */
1049    public join(separator?: String): string {
1050        if (separator == undefined) {
1051            return this.joinInternal(",")
1052        }
1053        return this.joinInternal(separator)
1054    }
1055
1056    /**
1057     * Returns an list of keys in Uint8ClampedArray
1058     *
1059     * @returns iterator over keys
1060     */
1061    public keys(): IterableIterator<number> {
1062        return new Uint8ClampedArrayIteratorKeys(this)
1063    }
1064
1065    /**
1066     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1067     *
1068     * @param searchElement The value to locate in the array.
1069     *
1070     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1071     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1072     *
1073     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1074     */
1075    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
1076        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
1077    }
1078
1079    /**
1080     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1081     *
1082     * @param searchElement The value to locate in the array.
1083     *
1084     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1085     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1086     *
1087     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1088     */
1089    public lastIndexOf(searchElement: number): number {
1090        return this.lastIndexOf(searchElement, this.lengthInt - 1)
1091    }
1092
1093    /**
1094     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1095     *
1096     * @param searchElement The value to locate in the array.
1097     *
1098     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1099     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1100     *
1101     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1102     */
1103    public lastIndexOf(searchElement: number, fromIndex: int): number {
1104            return this.lastIndexOfImpl(searchElement, fromIndex)
1105    }
1106
1107    /**
1108     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1109     *
1110     * @param searchElement The value to locate in the array.
1111     *
1112     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1113     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1114     *
1115     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1116     */
1117    public lastIndexOf(searchElement: int, fromIndex: int): number {
1118        return this.lastIndexOfImpl(searchElement as long, fromIndex)
1119    }
1120
1121    /**
1122     * Returns the index of the first occurrence of a value in Array.
1123     *
1124     * @param searchElement The value to locate in the array.
1125     *
1126     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1127     *  search starts at index 0.
1128     *
1129     * @returns index of element if it presents, -1 otherwise
1130     */
1131    private final native lastIndexOfImpl(searchElement: number, fromIndex: int): number
1132
1133    /**
1134     * Returns the index of the first occurrence of a value in Array.
1135     *
1136     * @param searchElement The value to locate in the array.
1137     *
1138     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
1139     *  search starts at index 0.
1140     *
1141     * @returns index of element if it presents, -1 otherwise
1142     */
1143    private final native lastIndexOfImpl(searchElement: long, fromIndex: int): number
1144
1145    /**
1146     * Returns the index of the last occurrence of a value in Uint8ClampedArray.
1147     *
1148     * @param searchElement The value to locate in the array.
1149     *
1150     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
1151     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
1152     *
1153     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
1154     */
1155    public lastIndexOf(searchElement: int): number {
1156        return this.lastIndexOf(searchElement, this.lengthInt - 1)
1157    }
1158
1159   /**
1160    * Creates a new Uint8ClampedArray using initializer
1161    *
1162    * @param data initializer
1163    *
1164    * @returns a new Uint8ClampedArray from data
1165    */
1166    public of(...data: FixedArray<number>): Uint8ClampedArray {
1167        throw new Error("Uint8ClampedArray.of: not implemented")
1168    }
1169
1170    /**
1171     * Creates a new Uint8ClampedArray using reversed data from the current one
1172     *
1173     * @returns a new Uint8ClampedArray using reversed data from the current one
1174     */
1175    public native reverse(): Uint8ClampedArray
1176
1177    /**
1178     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1179     *
1180     * @param begin start index to be taken into slice
1181     *
1182     * @param end last index to be taken into slice
1183     *
1184     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1185     *
1186     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1187     */
1188    public slice(begin?: number, end?: number): Uint8ClampedArray {
1189        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
1190    }
1191
1192    /**
1193     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1194     *
1195     * @param begin start index to be taken into slice
1196     *
1197     * @param end last index to be taken into slice
1198     *
1199     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1200     *
1201     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1202     */
1203    public slice(begin: number, end: number): Uint8ClampedArray {
1204        return this.slice(begin as int, end as int)
1205    }
1206
1207    /**
1208     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1209     *
1210     * @param begin start index to be taken into slice
1211     *
1212     * @param end last index to be taken into slice
1213     *
1214     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1215     *
1216     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1217     */
1218    public slice(begin: number, end: int): Uint8ClampedArray {
1219        return this.slice(begin as int, end as int)
1220    }
1221
1222    /**
1223     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1224     *
1225     * @param begin start index to be taken into slice
1226     *
1227     * @param end last index to be taken into slice
1228     *
1229     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1230     *
1231     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1232     */
1233    public slice(begin: int, end: number): Uint8ClampedArray {
1234        return this.slice(begin as int, end as int)
1235    }
1236
1237    /**
1238     * Creates a slice of current Uint8ClampedArray using range [begin, end)
1239     *
1240     * @param begin start index to be taken into slice
1241     *
1242     * @param end last index to be taken into slice
1243     *
1244     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin;end) where end index is excluded
1245     *
1246     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
1247     */
1248    public slice(begin: int, end: int): Uint8ClampedArray {
1249        const len: int = this.lengthInt
1250        const relStart = normalizeIndex(begin, len)
1251        const relEnd = normalizeIndex(end, len)
1252        let count = relEnd - relStart
1253        if (count < 0) {
1254            count = 0
1255        }
1256        let buf = this.buffer.slice(relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, relEnd * Uint8ClampedArray.BYTES_PER_ELEMENT as int) as ArrayBuffer
1257        return new Uint8ClampedArray(buf)
1258    }
1259
1260    /**
1261     * Creates a slice of current Uint8ClampedArray using range [begin, this.lengthInt).
1262     *
1263     * @param begin start index to be taken into slice
1264     *
1265     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin, this.lengthInt)
1266     */
1267    public slice(begin: number): Uint8ClampedArray {
1268        return this.slice(begin as int)
1269    }
1270
1271    /**
1272     * Creates a slice of current Uint8ClampedArray using range [begin, this.lengthInt).
1273     *
1274     * @param begin start index to be taken into slice
1275     *
1276     * @returns a new Uint8ClampedArray with elements of current Uint8ClampedArray[begin, this.lengthInt)
1277     */
1278    public slice(begin: int): Uint8ClampedArray {
1279        return this.slice(begin, this.lengthInt)
1280    }
1281
1282    /**
1283     * Sorts in-place by numeric value in ascending order.
1284     *
1285     * @returns sorted Array
1286     */
1287    public native sort(): this;
1288
1289    /**
1290     * Sorts in-place
1291     *
1292     * @param compareFn comparator _  used to determine the order of the elements.
1293     * compareFn returns a negative value if first argument is less than second argument,
1294     * zero if they're equal and a positive value otherwise.
1295     *
1296     * @returns sorted Uint8ClampedArray
1297     */
1298    public sort(compareFn?: (a: number, b: number) => number): this {
1299        if (compareFn == undefined) {
1300            this.sort()
1301            return this
1302        }
1303        let arr: FixedArray<int> = new int[this.lengthInt]
1304        for (let i = 0; i < this.lengthInt; ++i) {
1305            arr[i] = this.getUnsafe(i)
1306        }
1307
1308        let cmp = (l: int, r: int): number => {
1309            const result = compareFn!(l as number, r as number)
1310            return result
1311        }
1312        const MAX_SHORT_LENGTH = 24
1313        if (arr.length > MAX_SHORT_LENGTH) {
1314            arr = mergeSort(arr, cmp)
1315        } else {
1316            sort(arr, cmp)
1317        }
1318        for (let i = 0; i < arr.length; ++i) {
1319            this.setUnsafe(i, arr[i])
1320        }
1321        return this
1322    }
1323
1324    /**
1325     * Creates a Uint8ClampedArray with the same underlying Buffer
1326     *
1327     * @param begin start index, inclusive
1328     *
1329     * @param end last index, exclusive
1330     *
1331     * @returns new Uint8ClampedArray with the same underlying Buffer
1332     */
1333    public subarray(begin?: number, end?: number): Uint8ClampedArray {
1334        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
1335    }
1336
1337    /**
1338     * Creates a Uint8ClampedArray with the same underlying Buffer
1339     *
1340     * @param begin start index, inclusive
1341     *
1342     * @param end last index, exclusive
1343     *
1344     * @returns new Uint8ClampedArray with the same underlying Buffer
1345     */
1346    public subarray(begin: number, end: int): Uint8ClampedArray {
1347        return this.subarray(begin as int, end as int)
1348    }
1349
1350    /**
1351     * Creates a Uint8ClampedArray with the same underlying Buffer
1352     *
1353     * @param begin start index, inclusive
1354     *
1355     * @param end last index, exclusive
1356     *
1357     * @returns new Uint8ClampedArray with the same underlying Buffer
1358     */
1359    public subarray(begin: int, end: number): Uint8ClampedArray {
1360        return this.subarray(begin as int, end as int)
1361    }
1362
1363    /**
1364     * Creates a Uint8ClampedArray with the same underlying Buffer
1365     *
1366     * @param begin start index, inclusive
1367     *
1368     * @param end last index, exclusive
1369     *
1370     * @returns new Uint8ClampedArray with the same underlying Buffer
1371     */
1372    public subarray(begin: int, end: int | undefined = this.lengthInt): Uint8ClampedArray {
1373        const len: int = this.lengthInt
1374        const relStart = normalizeIndex(begin, len)
1375        const relEnd = normalizeIndex(end ?? this.lengthInt, len)
1376        let count = relEnd - relStart
1377        if (count < 0) {
1378            count = 0
1379        }
1380        return new Uint8ClampedArray(this.buffer, relStart * Uint8ClampedArray.BYTES_PER_ELEMENT as int, count)
1381    }
1382
1383    /**
1384     * Converts Uint8ClampedArray to a string with respect to locale
1385     *
1386     * @param locales
1387     *
1388     * @param options
1389     *
1390     * @returns string representation
1391     */
1392    public toLocaleString(locales: Object, options: Object): string {
1393        throw new Error("Uint8ClampedArray.toLocaleString: not implemented")
1394    }
1395
1396    /**
1397     * Converts Uint8ClampedArray to a string with respect to locale
1398     *
1399     * @param locales
1400     *
1401     * @returns string representation
1402     */
1403    public toLocaleString(locales: Object): string {
1404        return this.toLocaleString(new Object(), new Object())
1405    }
1406
1407    /**
1408     * Converts Uint8ClampedArray to a string with respect to locale
1409     *
1410     * @returns string representation
1411     */
1412    public toLocaleString(): string {
1413        let res: StringBuilder = new StringBuilder("")
1414        for (let i = 0; i < this.lengthInt - 1; ++i) {
1415            res.append((this.getUnsafe(i) as Number).toLocaleString())
1416            res.append(",")
1417        }
1418        if (this.lengthInt > 0) {
1419            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
1420        }
1421        return res.toString()
1422    }
1423
1424    /**
1425     * Creates a reversed copy
1426     *
1427     * @returns a reversed copy
1428     */
1429    public final native toReversed(): Uint8ClampedArray
1430
1431    /**
1432     * Creates a sorted copy
1433     *
1434     * @returns a sorted copy
1435     */
1436    public toSorted(): Uint8ClampedArray {
1437        return new Uint8ClampedArray(this).sort()
1438    }
1439
1440    /**
1441     * Returns a string representation of the Uint8ClampedArray
1442     *
1443     * @returns a string representation of the Uint8ClampedArray
1444     */
1445    public override toString(): string {
1446        return this.join(",")
1447    }
1448
1449    /**
1450     * Returns array values iterator
1451     *
1452     * @returns an iterator
1453     */
1454    public values(): IterableIterator<Number> {
1455         return new Uint8ClampedArrayIterator(this)
1456    }
1457
1458    /**
1459     * Creates a copy with replaced value on index
1460     *
1461     * @param index
1462     *
1463     * @param value
1464     *
1465     * @returns an Uint8ClampedArray with replaced value on index
1466     */
1467    public with(index: number, value: number): Uint8ClampedArray {
1468        return this.with(index as int, value as int)
1469    }
1470
1471    /**
1472     * Creates a copy with replaced value on index
1473     *
1474     * @param index
1475     *
1476     * @param value
1477     *
1478     * @returns an Uint8ClampedArray with replaced value on index
1479     */
1480    public with(index: int, value: int): Uint8ClampedArray {
1481        let res = new Uint8ClampedArray(this)
1482        res.setUnsafeClamp(index, value)
1483        return res
1484    }
1485
1486    /// === with element lambda functions ===
1487
1488    /**
1489     * Determines whether the specified callback function returns true for any element of an array.
1490     *
1491     * @param predicate A function that accepts three arguments.
1492     * The some method calls the predicate function for each element in the array
1493     * until the predicate returns a true or until the end of the array.
1494     *
1495     * @returns false unless predicate function returns true for an array element,
1496     * in which case true is immediately returned.
1497     */
1498    public some(predicate: (element: number, index: number, array: Uint8ClampedArray) => boolean): boolean {
1499        for (let i = 0; i < this.lengthInt; i++) {
1500            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
1501                return true
1502            }
1503        }
1504        return false
1505    }
1506
1507    /**
1508     * Calls the specified callback function for all the elements in an array.
1509     * The return value of the callback function is the accumulated result,
1510     * and is provided as an argument in the next call to the callback function.
1511     *
1512     * @param callbackfn A function that accepts four arguments.
1513     * The reduce method calls the callbackfn function one time for each element in the array.
1514     *
1515     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1516     * The first call to the callbackfn function provides this value as an argument.
1517     *
1518     * @returns The value that results from running the callback function to completion over the entire typed array.
1519     */
1520    public reduce<U = number>(
1521                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U,
1522                initialValue: U): U {
1523        let accumulatedValue = initialValue
1524        for (let i = 0; i < this.lengthInt; i++) {
1525            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1526        }
1527        return accumulatedValue
1528    }
1529
1530    /**
1531     * Calls the specified callback function for all the elements in an array.
1532     * The return value of the callback function is the accumulated result,
1533     * and is provided as an argument in the next call to the callback function.
1534     *
1535     * @param callbackfn A function that accepts four arguments.
1536     * The reduce method calls the callbackfn function one time for each element in the array.
1537     * The first call to the callbackfn function provides array first element value as an argument
1538     *
1539     * @returns The value that results from running the callback function to completion over the entire typed array.
1540     * calling reduce method on an empty array without an initial value creates a TypeError
1541     */
1542    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number {
1543        if (this.lengthInt == 0) {
1544            throw new TypeError("Reduce of empty array with no initial value")
1545        }
1546
1547        let accumulatedValue = this.$_get(0) as number
1548        for (let i = 1; i < this.lengthInt; i++) {
1549            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1550        }
1551        return accumulatedValue
1552    }
1553
1554    /**
1555     * Calls the specified callback function for all the elements in an array, in descending order.
1556     * The return value of the callback function is the accumulated result,
1557     * and is provided as an argument in the next call to the callback function.
1558     *
1559     * @param callbackfn A function that accepts four arguments.
1560     * The reduceRight method calls the callbackfn function one time for each element in the array.
1561     *
1562     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
1563     * The first call to the callbackfn function provides this value as an argument.
1564     *
1565     * @returns The value that results from running the callback function to completion over the entire typed array.
1566     */
1567    public reduceRight<U = number>(
1568                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U,
1569                initialValue: U): U {
1570        let accumulatedValue = initialValue
1571        for (let i = this.lengthInt - 1; i >= 0; i--) {
1572            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1573        }
1574        return accumulatedValue
1575    }
1576
1577    /**
1578     * Calls the specified callback function for all the elements in an array, in descending order.
1579     * The return value of the callback function is the accumulated result,
1580     * and is provided as an argument in the next call to the callback function.
1581     *
1582     * @param callbackfn A function that accepts four arguments.
1583     * The reduceRight method calls the callbackfn function one time for each element in the array.
1584     * The first call to the callbackfn function provides array last element value as an argument
1585     *
1586     * @returns The value that results from running the callback function to completion over the entire typed array.
1587     * calling reduceRight method on an empty array without an initial value creates a TypeError
1588     */
1589    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number {
1590        if (this.lengthInt == 0) {
1591            throw new TypeError("Reduce of empty array with no initial value")
1592        }
1593
1594        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
1595        for (let i = this.lengthInt - 2; i >= 0; i--) {
1596            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
1597        }
1598        return accumulatedValue
1599    }
1600
1601    /**
1602     * Creates a new Uint8ClampedArray using fn(arr[i]) over all elements of current Uint8ClampedArray.
1603     *
1604     * @param fn a function to apply for each element of current Uint8ClampedArray
1605     *
1606     * @returns a new Uint8ClampedArray where for each element from current Uint8ClampedArray fn was applied
1607     */
1608    public map(fn: (val: number, index: number, array: Uint8ClampedArray) => number): Uint8ClampedArray {
1609        let resBuf = new ArrayBuffer(this.lengthInt * Uint8ClampedArray.BYTES_PER_ELEMENT as int)
1610        let res = new Uint8ClampedArray(resBuf)
1611        for (let i = 0; i < this.lengthInt; i++) {
1612            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
1613            res.setUnsafeClamp(i, fnRes as int)
1614        }
1615        return res
1616    }
1617
1618    /**
1619     * Determines whether the specified callback function returns true for all elements of an array.
1620     *
1621     * @param predicate A function that accepts three arguments.
1622     * The every method calls the predicate function for each element in the array until the predicate returns a false,
1623     * or until the end of the array.
1624     *
1625     * @returns true unless predicate function returns a false for an array element,
1626     * in which case false is immediately returned.
1627     */
1628    public every(predicate: (element: number, index: number, array: Uint8ClampedArray) => boolean): boolean {
1629        for (let i = 0; i < this.lengthInt; i++) {
1630            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
1631                return false
1632            }
1633        }
1634        return true
1635    }
1636
1637    /**
1638     * Creates a new Uint8ClampedArray from current Uint8ClampedArray based on a condition fn.
1639     *
1640     * @param fn the condition to apply for each element
1641     *
1642     * @returns a new Uint8ClampedArray with elements from current Uint8ClampedArray that satisfy condition fn
1643     */
1644    public filter(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): Uint8ClampedArray {
1645        let markers : FixedArray<boolean> = new boolean[this.lengthInt]
1646        let resLen = 0
1647        for (let i = 0; i < this.lengthInt; i++) {
1648            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
1649            if (markers[i]) {
1650                ++resLen
1651            }
1652        }
1653        let res = new Uint8ClampedArray(resLen)
1654        for (let i = 0, j = 0; i < this.lengthInt; i++) {
1655            if (markers[i]) {
1656                res.setUnsafe(j, this.getUnsafe(i))
1657                ++j
1658            }
1659        }
1660        return res
1661    }
1662
1663    /**
1664     * Returns the value of the first element in the array where predicate is true, and undefined
1665     * otherwise
1666     *
1667     * @param predicate find calls predicate once for each element of the array, in ascending
1668     * order, until it finds one where predicate returns true. If such an element is found, find
1669     * immediately returns that element value. Otherwise, find returns undefined
1670     *
1671     * @returns number | undefined
1672     */
1673    public find(predicate: (value: number, index: number, array: Uint8ClampedArray) => boolean): number | undefined {
1674        for (let i = 0; i < this.lengthInt; i++) {
1675            let val = this.getUnsafe(i) as number
1676            if (predicate(val, i as number, this)) {
1677                return val
1678            }
1679        }
1680        return undefined
1681    }
1682
1683    /**
1684     * Returns the index of the first element in the array where predicate is true, and -1
1685     * otherwise
1686     *
1687     * @param predicate find calls predicate once for each element of the array, in ascending
1688     * order, until it finds one where predicate returns true. If such an element is found,
1689     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
1690     *
1691     * @returns number
1692     */
1693    public findIndex(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean): number {
1694        for (let i = 0; i < this.lengthInt; i++) {
1695            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
1696                return i as number
1697            }
1698        }
1699        return -1 as number
1700    }
1701
1702    /**
1703     * Finds the last element in the Uint8ClampedArray that satisfies the condition
1704     *
1705     * @param fn condition
1706     *
1707     * @returns the last element that satisfies fn
1708     */
1709    public findLast(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): number {
1710        for (let i = this.lengthInt - 1; i >= 0; i--) {
1711            let val = this.getUnsafe(i) as number
1712            if (fn(val, i as number, this)) {
1713                return val
1714            }
1715        }
1716        throw new Error("Uint8ClampedArray.findLast: not implemented if an element was not found")
1717    }
1718
1719    /**
1720     * Finds an index of the last element in the Uint8ClampedArray that satisfies the condition
1721     *
1722     * @param fn condition
1723     *
1724     * @returns the index of the last element that satisfies fn, -1 otherwise
1725     */
1726    public findLastIndex(fn: (val: number, index: number, array: Uint8ClampedArray) => boolean): number {
1727        for (let i = this.lengthInt - 1; i >= 0; i--) {
1728            if (fn(this.getUnsafe(i) as number, i as number, this)) {
1729                return i as number
1730            }
1731        }
1732        return -1 as number
1733    }
1734
1735    /**
1736     * Performs the specified action for each element in Uint8ClampedArray
1737     *
1738     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
1739     * callbackfn function one time for each element in the array.
1740     *
1741     * @returns None
1742     */
1743    public forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void): void {
1744        for (let i = 0; i < this.lengthInt; i++) {
1745            callbackfn(this.getUnsafe(i) as number, i as number, this)
1746        }
1747    }
1748
1749    /**
1750     * Returns the object itself
1751     *
1752     * @returns Uint8ClampedArray
1753     */
1754    public valueOf(): Uint8ClampedArray {
1755        return this
1756    }
1757
1758    /** Byte offset within the underlying Buffer */
1759    public get byteOffset(): number {
1760        return this.byteOffsetInt
1761    }
1762
1763    /** Number of bytes used */
1764    public get byteLength(): number {
1765        return this.byteLengthInt
1766    }
1767
1768    /** Number of int stored in Uint8ClampedArray */
1769    public get length(): number {
1770        return this.lengthInt
1771    }
1772
1773    /** String \"Uint8ClampedArray\" */
1774    public readonly name = "Uint8ClampedArray"
1775
1776    private static clamp(val: int): int {
1777        if (val > 255) {
1778            val = 255
1779        } else if (val < 0) {
1780            val = 0
1781        }
1782        return val
1783    }
1784
1785    internal setUnsafeClamp(insertPos: int, val: int): void {
1786        val = Uint8ClampedArray.clamp(val)
1787        this.setUnsafe(insertPos, val)
1788    }
1789
1790    private final native getUnsafe(index: int): int
1791
1792    internal setUnsafe(index: int, val: int): void {
1793        index = index * Uint8ClampedArray.BYTES_PER_ELEMENT as int + this.byteOffsetInt
1794        let res: int = 0
1795        if (IS_LITTLE_ENDIAN) {
1796            for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
1797                this.buffer.set(index + i, (val & 0xff) as byte)
1798                val = val >> 8
1799            }
1800        } else {
1801            for (let i = 0; i < Uint8ClampedArray.BYTES_PER_ELEMENT as int; i++) {
1802                this.buffer.set(index + 0 - i, (val & 0xff) as byte)
1803                val = val >> 8
1804            }
1805        }
1806    }
1807}
1808
1809
1810class Uint8ArrayIteratorKeys implements IterableIterator<number> {
1811    private length: int = 0
1812    private idx: int = 0
1813
1814    constructor(parent: Uint8Array) {
1815        this.length = parent.length as int
1816    }
1817
1818    public override $_iterator(): IterableIterator<Number> {
1819        return this
1820    }
1821
1822    override next(): IteratorResult<number> {
1823        if (this.idx < 0 || this.idx >= this.length) {
1824            return new IteratorResult<number>()
1825        }
1826        return new IteratorResult<number>(false, this.idx++ as number)
1827    }
1828}
1829
1830class Uint8ArrayIterator implements IterableIterator<Number> {
1831    private parent: Uint8Array
1832    private idx: int = 0
1833
1834    constructor(parent: Uint8Array) {
1835        this.parent = parent
1836    }
1837
1838    public override $_iterator(): IterableIterator<Number> {
1839        return this
1840    }
1841
1842    override next(): IteratorResult<Number> {
1843        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
1844            return new IteratorResult<Number>()
1845        }
1846        return new IteratorResult<Number>(false, new Number(this.parent[this.idx++]))
1847    }
1848}
1849
1850class Uint8ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
1851    private parent: Uint8Array
1852    private idx: int = 0
1853
1854    constructor(parent: Uint8Array) {
1855        this.parent = parent
1856    }
1857
1858    public override $_iterator(): IterableIterator<[Number, Number]> {
1859        return this
1860    }
1861
1862    override next(): IteratorResult<[Number, Number]> {
1863        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
1864            return new IteratorResult<[Number, Number]>()
1865        }
1866        return new IteratorResult<[Number, Number]>(
1867            false,
1868            [new Number(this.idx), new Number(this.parent[this.idx++])]
1869        )
1870    }
1871}
1872
1873/**
1874 * JS Uint8Array API-compatible class
1875 */
1876export final class Uint8Array implements Iterable<Number>, ArrayLike<Number> {
1877    public static readonly BYTES_PER_ELEMENT: number = 1
1878    public readonly BYTES_PER_ELEMENT: number = Uint8Array.BYTES_PER_ELEMENT
1879
1880    /** Underlying Buffer */
1881    public readonly buffer: ArrayBuffer
1882
1883    internal readonly byteOffsetInt: int
1884    internal readonly byteLengthInt: int
1885    internal readonly lengthInt: int
1886
1887    /**
1888     * Creates an empty Uint8Array.
1889     */
1890    public constructor() {
1891        this(0 as int)
1892    }
1893
1894    /**
1895     * Creates an Uint8Array with respect to data accessed via Iterable<Number> interface
1896     */
1897    public constructor(elements: Iterable<Number>) {
1898        const items: Object = elements as Object
1899        if (items instanceof ArrayLike) {
1900            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
1901            this.byteLengthInt = arr.length as int * Uint8Array.BYTES_PER_ELEMENT as int
1902            this.lengthInt = arr.length as int
1903            this.buffer = new ArrayBuffer(this.byteLengthInt)
1904            this.byteOffsetInt = 0
1905            for (let i: int = 0; i < this.lengthInt; ++i) {
1906                this.setUnsafeClamp(i, this.zeroIfInfinity(arr.$_get(i)) as int)
1907            }
1908        } else {
1909            let x = Uint8Array.from(elements)
1910            this.byteLengthInt = x.byteLengthInt
1911            this.lengthInt = x.lengthInt
1912            this.buffer = x.buffer
1913            this.byteOffsetInt = x.byteOffsetInt
1914        }
1915    }
1916
1917    /**
1918     * Creates an Uint8Array with respect to data, byteOffset and length.
1919     *
1920     * @param buf data initializer
1921     *
1922     * @param byteOffset byte offset from begin of the buf
1923     *
1924     * @param length size of elements of type int in newly created Uint8Array
1925     */
1926    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined, length: Number | undefined) {
1927        let intByteOffset: int = 0
1928        if (byteOffset != undefined) {
1929            intByteOffset = byteOffset.toInt()
1930            if (intByteOffset < 0) {
1931                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
1932            }
1933        }
1934        let intByteLength: int = buf.getByteLength() - intByteOffset
1935        if (intByteLength < 0) {
1936            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
1937        }
1938
1939        let intLength: int
1940        if (length != undefined) {
1941            intLength = length.toInt()
1942            if (intLength > intByteLength / Uint8Array.BYTES_PER_ELEMENT as int) {
1943                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
1944            }
1945        } else {
1946            intLength = intByteLength / Uint8Array.BYTES_PER_ELEMENT as int
1947        }
1948        if (intLength < 0) {
1949            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
1950        }
1951        if (intLength < intByteLength / Uint8Array.BYTES_PER_ELEMENT as int) {
1952            intByteLength = intLength * Uint8Array.BYTES_PER_ELEMENT as int
1953        }
1954        this.byteLengthInt = intByteLength
1955        this.byteOffsetInt = intByteOffset
1956        this.lengthInt = intLength
1957        this.buffer = buf
1958    }
1959
1960    /**
1961     * Creates an Uint8Array with respect to data, byteOffset and length.
1962     *
1963     * @param buf data initializer
1964     *
1965     * @param byteOffset byte offset from begin of the buf
1966     */
1967    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined) {
1968        this(buf, byteOffset, undefined)
1969    }
1970
1971    /**
1972     * Creates an Uint8Array with respect to data, byteOffset and length.
1973     *
1974     * @param buf data initializer
1975     *
1976     * @param byteOffset byte offset from begin of the buf
1977     *
1978     * @param length size of elements of type int in newly created Uint8Array
1979     */
1980    public constructor(buf: ArrayBuffer, byteOffset: number, length: number) {
1981        this(buf, new Number(byteOffset), new Number(length))
1982    }
1983
1984    /**
1985     * Creates an Uint8Array with respect to buf and byteOffset.
1986     *
1987     * @param buf data initializer
1988     *
1989     * @param byteOffset byte offset from begin of the buf
1990     */
1991    public constructor(buf: ArrayBuffer, byteOffset: number) {
1992        this(buf, new Number(byteOffset), undefined)
1993    }
1994
1995    /**
1996     * Creates an Uint8Array with respect to data, byteOffset and length.
1997     *
1998     * @param buf data initializer
1999     *
2000     * @param byteOffset byte offset from begin of the buf
2001     *
2002     * @param length size of elements of type int in newly created Uint8Array
2003     */
2004    public constructor(buf: ArrayBuffer, byteOffset: int, length: int) {
2005        this(buf, new Number(byteOffset), new Number(length))
2006    }
2007
2008    /**
2009     * Creates an Uint8Array with respect to buf and byteOffset.
2010     *
2011     * @param buf data initializer
2012     *
2013     * @param byteOffset byte offset from begin of the buf
2014     */
2015    public constructor(buf: ArrayBuffer, byteOffset: int) {
2016        this(buf, new Number(byteOffset), undefined)
2017    }
2018
2019    /**
2020     * Creates an Uint8Array with respect to buf.
2021     *
2022     * @param buf data initializer
2023     */
2024    public constructor(buf: ArrayLike<Number> | ArrayBuffer) {
2025        if (buf instanceof ArrayBuffer) {
2026            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
2027            if (this.byteLengthInt % Uint8Array.BYTES_PER_ELEMENT as int != 0) {
2028               throw new RangeError("ArrayBuffer.byteLength should be multiple of int as Uint8Array.BYTES_PER_ELEMENT")
2029            }
2030            this.lengthInt = this.byteLengthInt / Uint8Array.BYTES_PER_ELEMENT as int
2031            this.buffer = buf as ArrayBuffer
2032            this.byteOffsetInt = 0
2033        } else if (buf instanceof ArrayLike) {
2034            // NOTE (ikorobkov): dealing with this overload is tricky
2035            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.ets
2036            let arr = Array.from<Number>((buf as ArrayLike<Number>))
2037            this.byteLengthInt = arr.length as int * Uint8Array.BYTES_PER_ELEMENT as int
2038            this.lengthInt = arr.length as int
2039            this.buffer = new ArrayBuffer(this.byteLengthInt)
2040            this.byteOffsetInt = 0
2041            for (let i: int = 0; i < this.lengthInt; ++i) {
2042                this.setUnsafe(i, arr.$_get(i).toInt())
2043            }
2044        } else {
2045            throw new Error("unexpected type of buf")
2046        }
2047    }
2048
2049    /**
2050     * Creates an Uint8Array with respect to length.
2051     *
2052     * @param length data initializer
2053     */
2054    public constructor(length: int) {
2055        this(length as number)
2056    }
2057
2058    /**
2059     * Creates an Uint8Array with respect to length.
2060     *
2061     * @param length data initializer
2062     */
2063    public constructor(length: number) {
2064        if (length < 0 || length > (Int.MAX_VALUE / Uint8Array.BYTES_PER_ELEMENT)) {
2065            throw new TypeError("Type Error: length " + length + " is outside the bounds of the buffer")
2066        }
2067        this.lengthInt = length as int
2068        this.byteLengthInt = this.lengthInt * Uint8Array.BYTES_PER_ELEMENT as int
2069        this.byteOffsetInt = 0
2070        this.buffer = new ArrayBuffer(this.byteLengthInt)
2071    }
2072
2073    /**
2074     * Creates a copy of Uint8Array.
2075     *
2076     * @param other data initializer
2077     */
2078    public constructor(other: Uint8Array) {
2079        this.buffer = other.buffer.slice(other.byteOffset as int, (other.byteOffset + other.byteLength) as int) as ArrayBuffer
2080        this.byteLengthInt = other.byteLength as int
2081        this.lengthInt = other.length as int
2082        this.byteOffsetInt = 0
2083    }
2084
2085    /**
2086     * Creates an Uint8Array from FixedArray<number>
2087     */
2088    public constructor(numbers: FixedArray<number>) {
2089        this(numbers.length)
2090        for (let i: int = 0; i < this.lengthInt; ++i) {
2091            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
2092        }
2093    }
2094
2095    /**
2096     * Creates an Uint8Array from FixedArray<int>
2097     */
2098    public constructor(numbers: FixedArray<int>) {
2099        this(numbers.length)
2100        for (let i: int = 0; i < this.lengthInt; ++i) {
2101            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
2102        }
2103    }
2104    internal zeroIfInfinity(val: number): number {
2105        if ((val == Infinity) || (val == -Infinity)) {
2106            return 0 as number
2107        }
2108        return val as number
2109    }
2110
2111    internal zeroIfInfinity(val: int): int {
2112        if ((val == Infinity) || (val == -Infinity)) {
2113            return 0 as int
2114        }
2115        return val
2116    }
2117
2118    /**
2119     * Iteratorable interface implementation
2120     *
2121     * @returns iterator over all elements
2122     */
2123    public override $_iterator(): IterableIterator<Number> {
2124         return this.values()
2125    }
2126
2127    /**
2128     * Returns an instance of primitive type at passed index.
2129     *
2130     * @param index index to look at
2131     *
2132     * @returns a primitive at index
2133     */
2134    public at(index: number): Number | undefined {
2135        return this.at(index as int)
2136    }
2137
2138    /**
2139     * Returns an instance of primitive type at passed index if index is correct.
2140     *
2141     * @param index index to look at
2142     *
2143     * @returns a primitive at index
2144     */
2145    public at(index: int): Number | undefined {
2146        let k: int
2147        if (index >= 0) {
2148            k = index
2149        } else {
2150            k = this.lengthInt + index
2151        }
2152        if (k < 0 || k >= this.lengthInt) {
2153            return undefined
2154        }
2155        return new Number(this.getUnsafe(k))
2156    }
2157
2158    /**
2159     * Returns an instance of number at passed index.
2160     *
2161     * @param index index to look at
2162     *
2163     * @returns a primitive at index
2164     */
2165    public override $_get(index: number): Number {
2166        return this.$_get(index as int) as Number
2167    }
2168
2169    /**
2170     * Returns an instance of number at passed index.
2171     *
2172     * @param index index to look at
2173     *
2174     * @returns a primitive at index
2175     */
2176    public native $_get(i: int): number
2177
2178    /**
2179     * Assigns val as element on index.
2180     *
2181     * @param val value to set
2182     *
2183     * @param index index to change
2184     */
2185    public $_set(index: number, val: number): void {
2186        this.$_set(index as int, val)
2187    }
2188
2189    /**
2190     * Assigns val as element on index.
2191     *
2192     * @param val value to set
2193     *
2194     * @param index index to change
2195     */
2196    public $_set(index: int, val: number): void {
2197        let v = this.zeroIfInfinity(val)
2198        this.$_set(index, v as int)
2199    }
2200
2201    /**
2202     * Assigns val as element on index.
2203     *
2204     * @param val value to set
2205     *
2206     * @param index index to change
2207     */
2208    public $_set(index: number, val: int): void {
2209        this.$_set(index as int, val)
2210    }
2211
2212    /**
2213     * Assigns val as element on index.
2214     *
2215     * @param val value to set
2216     *
2217     * @param index index to change
2218     */
2219    public native $_set(index: int, val: int): void
2220
2221    /**
2222     * Makes a copy of internal elements to targetPos from startPos to endPos.
2223     *
2224     * @param target insert index to place copied elements
2225     *
2226     * @param start start index to begin copy from
2227     *
2228     * @param end last index to end copy from, excluded
2229     *
2230     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
2231     */
2232    public copyWithin(target: number, start: number, end?: number): Uint8Array {
2233        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
2234    }
2235
2236    /**
2237     * Makes a copy of internal elements to targetPos from startPos to endPos.
2238     *
2239     * @param target insert index to place copied elements
2240     *
2241     * @param start start index to begin copy from
2242     *
2243     * @param end last index to end copy from, excluded
2244     *
2245     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
2246     */
2247    public copyWithin(target: int, start: number, end?: number): Uint8Array {
2248        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
2249    }
2250
2251    /**
2252     * Makes a copy of internal elements to targetPos from startPos to endPos.
2253     *
2254     * @param target insert index to place copied elements
2255     *
2256     * @param start start index to begin copy from
2257     *
2258     * @param end last index to end copy from, excluded
2259     *
2260     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
2261     */
2262    public copyWithin(target: number, start: int, end?: number): Uint8Array {
2263        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
2264    }
2265
2266    /**
2267     * Makes a copy of internal elements to targetPos from startPos to endPos.
2268     *
2269     * @param target insert index to place copied elements
2270     *
2271     * @param start start index to begin copy from
2272     *
2273     * @param end last index to end copy from, excluded
2274     *
2275     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
2276     */
2277    public copyWithin(target: int, start: int, end?: number): Uint8Array {
2278        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
2279    }
2280
2281    /**
2282     * Makes a copy of internal elements to targetPos from startPos to endPos.
2283     *
2284     * @param insert insert index to place copied elements
2285     *
2286     * @param start start index to begin copy from
2287     *
2288     * @param end last index to end copy from, excluded
2289     *
2290     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
2291     */
2292    public native copyWithin(target: int, start: int, end: int): Uint8Array
2293
2294    /**
2295     * Makes a copy of internal elements to targetPos from begin to end of Uint8Array.
2296     *
2297     * @param target insert index to place copied elements
2298     *
2299     * See rules of parameters normalization:
2300     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
2301     */
2302    public copyWithin(target: number): Uint8Array {
2303        return this.copyWithin(target as int)
2304    }
2305
2306    /**
2307     * Makes a copy of internal elements to targetPos from begin to end of Uint8Array.
2308     *
2309     * @param insert insert index to place copied elements
2310     *
2311     * See rules of parameters normalization:
2312     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
2313     */
2314    public copyWithin(target: int): Uint8Array {
2315        return this.copyWithin(target, 0, this.lengthInt)
2316    }
2317
2318    /**
2319     * Returns an array of key, value pairs for every entry in the Uint8Array
2320     *
2321     * @returns key, value pairs for every entry in the array
2322     */
2323    public entries(): IterableIterator<[Number, Number]> {
2324        return new Uint8ArrayIteratorEntries(this)
2325    }
2326
2327    /**
2328     * Fills the Uint8Array with specified value
2329     *
2330     * @param value new value
2331     *
2332     * @returns modified Uint8Array
2333     */
2334    public fill(value: number, start?: number, end?: number): Uint8Array {
2335        value = this.zeroIfInfinity(value)
2336        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
2337        return this
2338    }
2339
2340    /**
2341     * Fills the Uint8Array with specified value
2342     *
2343     * @param value new value
2344     *
2345     * @returns modified Uint8Array
2346     */
2347    public fill(value: number, start: int, end?: number): Uint8Array {
2348        value = this.zeroIfInfinity(value)
2349        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
2350        return this
2351    }
2352
2353    /**
2354     * Fills the Uint8Array with specified value
2355     *
2356     * @param value new value
2357     *
2358     * @returns modified Uint8Array
2359     */
2360    public fill(value: number, start: int, end: number): Uint8Array {
2361        value = this.zeroIfInfinity(value)
2362        this.fill(value as int, start as int, end as int)
2363        return this
2364    }
2365
2366    /**
2367     * Fills the Uint8Array with specified value
2368     *
2369     * @param value new value
2370     *
2371     * @returns modified Uint8Array
2372     */
2373    public fill(value: number, start: number, end: int): Uint8Array {
2374        value = this.zeroIfInfinity(value)
2375        this.fill(value as int, start as int, end as int)
2376        return this
2377    }
2378
2379    /**
2380     * Fills the Uint8Array with specified value
2381     *
2382     * @param value new value
2383     *
2384     * @returns modified Uint8Array
2385     */
2386    public fill(value: number, start: int, end: int): Uint8Array {
2387        value = this.zeroIfInfinity(value)
2388        this.fill(value as int, start as int, end as int)
2389        return this
2390    }
2391
2392    /**
2393     * Fills the Uint8Array with specified value
2394     *
2395     * @param value new value
2396     *
2397     * @returns modified Uint8Array
2398     */
2399    public fill(value: int, start?: number, end?: number): Uint8Array {
2400        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
2401        return this
2402    }
2403
2404    /**
2405     * Fills the Uint8Array with specified value
2406     *
2407     * @param value new value
2408     *
2409     * @returns modified Uint8Array
2410     */
2411    public fill(value: int, start: int, end?: number): Uint8Array {
2412        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
2413        return this
2414    }
2415
2416    /**
2417     * Fills the Uint8Array with specified value
2418     *
2419     * @param value new value
2420     *
2421     * @returns modified Uint8Array
2422     */
2423    public fill(value: int, start: int, end: number): Uint8Array {
2424        this.fill(value, start as int, end as int)
2425        return this
2426    }
2427
2428    /**
2429     * Fills the Uint8Array with specified value
2430     *
2431     * @param value new value
2432     *
2433     * @returns modified Uint8Array
2434     */
2435    public fill(value: int, start: number, end: int): Uint8Array {
2436        this.fill(value, start as int, end as int)
2437        return this
2438    }
2439
2440    /**
2441     * Fills the Uint8Array with specified value
2442     *
2443     * @param value new value
2444     *
2445     * @returns modified Uint8Array
2446     */
2447    public fill(value: int, start: int, end: int): Uint8Array {
2448        const k = normalizeIndex(start, this.lengthInt)
2449        const finalPos = normalizeIndex(end, this.lengthInt)
2450        this.fillInternal(value, k, finalPos)
2451        return this
2452    }
2453
2454    private final native fillInternal(value: int, start: int, end: int): void
2455
2456    /**
2457     * Assigns val as element on index.
2458     *
2459     * @param val value to set
2460     *
2461     * @param index index to change
2462     */
2463    public set(insertPos: number, val: number): void {
2464        this.$_set(insertPos as int, val)
2465    }
2466
2467    /**
2468     * Assigns val as element on index.
2469     *
2470     * @param val value to set
2471     *
2472     * @param index index to change
2473     */
2474    public set(insertPos: int, val: number): void {
2475        this.$_set(insertPos as int, val)
2476    }
2477
2478    /**
2479     * Assigns val as element on index.
2480     *
2481     * @param val value to set
2482     *
2483     * @param index index to change
2484     */
2485    public set(insertPos: number, val: int): void {
2486        this.$_set(insertPos as int, val)
2487    }
2488
2489    /**
2490     * Assigns val as element on index.
2491     *
2492     * @param val value to set
2493     *
2494     * @param index index to change
2495     */
2496    public set(insertPos: int, val: int): void {
2497        this.$_set(insertPos as int, val)
2498    }
2499
2500    /**
2501     * Copies all elements of arr to the current Uint8Array starting from insertPos.
2502     *
2503     * @param arr array to copy data from
2504     *
2505     * @param insertPos start index where data from arr will be inserted
2506     *
2507     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
2508     */
2509    public set(arr: FixedArray<number>, insertPos1: number): void {
2510        const insertPos = insertPos1 as int
2511        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
2512            throw new RangeError("set(insertPos: int, arr: FixedArray<int>): size of arr is greater than Uint8Array.length")
2513        }
2514        for (let i = 0; i < arr.length; i++) {
2515            let v = this.zeroIfInfinity(arr[i])
2516            this.setUnsafeClamp(insertPos as int + i as int, v as int)
2517        }
2518    }
2519
2520    /**
2521     * Copies all elements of arr to the current Uint8Array starting from insertPos.
2522     *
2523     * @param arr array to copy data from
2524     *
2525     * @param insertPos start index where data from arr will be inserted
2526     *
2527     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
2528     */
2529    public set(arr: FixedArray<int>, insertPos: int): void {
2530        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
2531            throw new RangeError("set(insertPos: int, arr: FixedArray<int>): size of arr is greater than Uint8Array.length")
2532        }
2533        for (let i = 0; i < arr.length; i++) {
2534            let v = this.zeroIfInfinity(arr[i])
2535            this.setUnsafeClamp(insertPos + i, v)
2536        }
2537    }
2538
2539    /**
2540     * Copies all elements of arr to the current Uint8Array.
2541     *
2542     * @param arr array to copy data from
2543     */
2544    public set(arr: FixedArray<number>): void {
2545        this.set(arr, 0)
2546    }
2547
2548    /**
2549     * Copies all elements of arr to the current Uint8Array.
2550     *
2551     * @param arr array to copy data from
2552     */
2553    public set(arr: FixedArray<int>): void {
2554        this.set(arr, 0)
2555    }
2556
2557    public native set(array: Uint8Array): void
2558
2559    public native set(array: Uint8Array, offset: number): void
2560
2561    /**
2562     * Copies elements from an ArrayLike object to the Uint8Array.
2563     *
2564     * @param array An ArrayLike object containing the elements to copy.
2565     *
2566     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
2567     */
2568    public set(array: ArrayLike<number>, offset: number = 0): void {
2569        const insertPos = offset as int
2570        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
2571            throw new RangeError("offset is out of bounds")
2572        }
2573        for (let i = array.length - 1; i >= 0; --i) {
2574            let v = this.zeroIfInfinity(array[i])
2575            this.setUnsafeClamp(insertPos as int + i as int, v as int)
2576        }
2577    }
2578
2579    /**
2580     * Returns a new array from a set of elements.
2581     *
2582     * @param items a set of elements to include in the new array object.
2583     *
2584     * @returns new Uint8Array
2585     */
2586    public static of(...items: FixedArray<number>): Uint8Array {
2587        let res = new Uint8Array(items.length as int)
2588        for (let i: int = 0; i < items.length; i++) {
2589            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as int)
2590        }
2591        return res
2592    }
2593
2594    /**
2595     * Returns a new array from a set of elements.
2596     *
2597     * @param items a set of elements to include in the new array object.
2598     *
2599     * @returns new Uint8Array
2600     */
2601    public static of(...items: FixedArray<int>): Uint8Array {
2602        let res = new Uint8Array(items.length as int)
2603        for (let i: int = 0; i < items.length; i++) {
2604            res.setUnsafeClamp(i, items[i])
2605        }
2606        return res
2607    }
2608
2609    /**
2610     * Returns a new array from a set of elements.
2611     *
2612     * @param items a set of elements to include in the new array object.
2613     *
2614     * @returns new Uint8Array
2615     */
2616    public static of(...items: FixedArray<short>): Uint8Array {
2617        let res = new Uint8Array(items.length as int)
2618        for (let i: int = 0; i < items.length; i++) {
2619            res.setUnsafeClamp(i, items[i] as int)
2620        }
2621        return res
2622    }
2623
2624    /**
2625     * Returns a new array from a set of elements.
2626     *
2627     * @param items a set of elements to include in the new array object.
2628     *
2629     * @returns new Uint8Array
2630     */
2631    public static of(): Uint8Array {
2632        return new Uint8Array(0 as int)
2633    }
2634
2635    /**
2636     * Creates an array from an array-like or iterable object.
2637     *
2638     * @param arrayLike An array-like or iterable object to convert to an array.
2639     *
2640     * @returns new Uint8Array
2641     */
2642    public static from(arr: ArrayLike<number>): Uint8Array {
2643        return Uint8Array.from<number>(arr, (x: number, k: number): number => x)
2644    }
2645
2646    /**
2647     * Creates an array from an array-like or iterable object.
2648     *
2649     * @param arrayLike An array-like or iterable object to convert to an array.
2650     *
2651     * @param mapfn A mapping function to call on every element of the array.
2652     *
2653     * @returns new Uint8Array
2654     */
2655    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint8Array {
2656        if (mapfn == undefined) {
2657            mapfn = (v: number, k: number): number => { return v }
2658        }
2659
2660        let iter = arrayLike.$_iterator()
2661        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
2662        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
2663        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
2664        //  we can make one pass through the iterator without the need for memory reallocation.
2665        const maybeLength = tryGetIteratorLength(arrayLike)
2666        if (maybeLength) {
2667            const result = new Uint8Array(maybeLength)
2668            for (let i = 0; i < maybeLength; ++i) {
2669                const x = iter.next()
2670                if (x.done) {
2671                    return new Uint8Array(result.buffer, 0, i)
2672                }
2673                result.setUnsafeClamp(i, result.zeroIfInfinity((mapfn)!(x.value!, i)) as int)
2674            }
2675            return result
2676        }
2677
2678        // NOTE (templin.konstantin): Create builtin array as buffer
2679        let temp = new Uint8Array(6)
2680        let index : FixedArray<int> = new int[1]
2681        index[0] = 0
2682
2683        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
2684            if (index[0] + 1 > temp.lengthInt) {
2685                // NOTE (templin.konstantin): Progressive reallocation
2686                const curLength = (temp.buffer as Buffer).getByteLength()
2687                const tb = new ArrayBuffer(curLength * 2)
2688                for (let i = 0; i < curLength; ++i) {
2689                    tb.set(i, (temp.buffer as Buffer).at(i))
2690                }
2691                temp = new Uint8Array(tb)
2692            }
2693            temp.setUnsafeClamp(index[0], temp.zeroIfInfinity((mapfn)!(x, index[0])) as int)
2694            index[0]++
2695        })
2696
2697        return new Uint8Array(temp.buffer, 0, index[0])
2698    }
2699
2700    /**
2701     * Creates an array from an array-like or iterable object.
2702     *
2703     * @param arrayLike An array-like or iterable object to convert to an array.
2704     *
2705     * @param mapfn A mapping function to call on every element of the array.
2706     *
2707     * @returns new Uint8Array
2708     */
2709    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint8Array {
2710        let res = new Uint8Array(arrayLike.length)
2711        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
2712        const idx : FixedArray<int> = new int[1]
2713        idx[0] = 0
2714        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
2715            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as int)
2716            idx[0] += 1
2717        })
2718        return res
2719    }
2720
2721    /**
2722     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
2723     *
2724     * @param searchElement The element to search for
2725     *
2726     * @param fromIndex The position in this array at which to begin searching for searchElement
2727     *
2728     * @returns true if searchElement is in Uint8Array, false otherwise
2729     */
2730    public includes(searchElement: number, fromIndex?: number): boolean {
2731        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
2732    }
2733
2734    /**
2735     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
2736     *
2737     * @param searchElement The element to search for
2738     *
2739     * @param fromIndex The position in this array at which to begin searching for searchElement
2740     *
2741     * @returns true if searchElement is in Uint8Array, false otherwise
2742     */
2743    public includes(searchElement: int, fromIndex: int): boolean {
2744        return this.indexOf(searchElement as int, fromIndex) != -1
2745    }
2746
2747    /**
2748     * Determines whether Uint8Array includes a certain element, returning true or false as appropriate
2749     *
2750     * @param searchElement The element to search for
2751     *
2752     * @param fromIndex The position in this array at which to begin searching for searchElement
2753     *
2754     * @returns true if searchElement is in Uint8Array, false otherwise
2755     */
2756    public includes(searchElement: int): boolean {
2757        return this.indexOf(searchElement as int, 0) != -1
2758    }
2759
2760    /**
2761     * Returns the index of the first occurrence of a value in Uint8Array.
2762     *
2763     * @param searchElement The value to locate in the array.
2764     *
2765     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2766     *  search starts at index 0.
2767     *
2768     * @returns index of element if it presents, -1 otherwise
2769     */
2770    public indexOf(searchElement: number, fromIndex?: number): number {
2771        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
2772    }
2773
2774    /**
2775     * Returns the index of the first occurrence of a value in Uint8Array.
2776     *
2777     * @param searchElement The value to locate in the array.
2778     *
2779     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2780     *  search starts at index 0.
2781     *
2782     * @returns index of element if it presents, -1 otherwise
2783     */
2784    public indexOf(searchElement: number, fromIndex: int): number {
2785            return this.indexOfImpl(searchElement, fromIndex)
2786    }
2787
2788    /**
2789     * Returns the index of the first occurrence of a value in Uint8Array.
2790     *
2791     * @param searchElement The value to locate in the array.
2792     *
2793     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2794     *  search starts at index 0.
2795     *
2796     * @returns index of element if it presents, -1 otherwise
2797     */
2798    public indexOf(searchElement: int, fromIndex: int): number {
2799        return this.indexOfImpl(searchElement as long, fromIndex)
2800    }
2801
2802    /**
2803     * Returns the index of the first occurrence of a value in Array.
2804     *
2805     * @param searchElement The value to locate in the array.
2806     *
2807     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2808     *  search starts at index 0.
2809     *
2810     * @returns index of element if it presents, -1 otherwise
2811     */
2812    private final native indexOfImpl(searchElement: number, fromIndex: int): number
2813
2814    /**
2815     * Returns the index of the first occurrence of a value in Array.
2816     *
2817     * @param searchElement The value to locate in the array.
2818     *
2819     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2820     *  search starts at index 0.
2821     *
2822     * @returns index of element if it presents, -1 otherwise
2823     */
2824    private final native indexOfImpl(searchElement: long, fromIndex: int): number
2825
2826    /**
2827     * Returns the index of the first occurrence of a value in Uint8Array.
2828     *
2829     * @param searchElement The value to locate in the array.
2830     *
2831     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2832     *  search starts at index 0.
2833     *
2834     * @returns index of element if it presents, -1 otherwise
2835     */
2836    public indexOf(searchElement: int): number {
2837        return this.indexOf(searchElement, 0)
2838    }
2839
2840
2841    /**
2842     * Converts all elements of an array to strings and joins them using the specified separator.
2843     *
2844     * @param separator - separates one element of an array from the next in the resulting String.
2845     *
2846     * @returns joined representation
2847     */
2848    private final native joinInternal(separator: String): string;
2849
2850    /**
2851     * Adds all the elements of an array separated by the specified separator string
2852     *
2853     * @param separator A string used to separate one element of an array from the next in the
2854     * resulting String. If omitted, the array elements are separated with a comma
2855     *
2856     * @returns joined representation
2857     */
2858    public join(separator?: String): string {
2859        if (separator == undefined) {
2860            return this.joinInternal(",")
2861        }
2862        return this.joinInternal(separator)
2863    }
2864
2865    /**
2866     * Returns an list of keys in Uint8Array
2867     *
2868     * @returns iterator over keys
2869     */
2870    public keys(): IterableIterator<number> {
2871        return new Uint8ArrayIteratorKeys(this)
2872    }
2873
2874    /**
2875     * Returns the index of the last occurrence of a value in Uint8Array.
2876     *
2877     * @param searchElement The value to locate in the array.
2878     *
2879     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
2880     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
2881     *
2882     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
2883     */
2884    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
2885        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
2886    }
2887
2888    /**
2889     * Returns the index of the last occurrence of a value in Uint8Array.
2890     *
2891     * @param searchElement The value to locate in the array.
2892     *
2893     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
2894     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
2895     *
2896     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
2897     */
2898    public lastIndexOf(searchElement: number): number {
2899        return this.lastIndexOf(searchElement, this.lengthInt - 1)
2900    }
2901
2902    /**
2903     * Returns the index of the last occurrence of a value in Uint8Array.
2904     *
2905     * @param searchElement The value to locate in the array.
2906     *
2907     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
2908     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
2909     *
2910     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
2911     */
2912    public lastIndexOf(searchElement: number, fromIndex: int): number {
2913            return this.lastIndexOfImpl(searchElement, fromIndex)
2914    }
2915
2916    /**
2917     * Returns the index of the last occurrence of a value in Uint8Array.
2918     *
2919     * @param searchElement The value to locate in the array.
2920     *
2921     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
2922     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
2923     *
2924     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
2925     */
2926    public lastIndexOf(searchElement: int, fromIndex: int): number {
2927        return this.lastIndexOfImpl(searchElement as long, fromIndex)
2928    }
2929
2930    /**
2931     * Returns the index of the first occurrence of a value in Array.
2932     *
2933     * @param searchElement The value to locate in the array.
2934     *
2935     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2936     *  search starts at index 0.
2937     *
2938     * @returns index of element if it presents, -1 otherwise
2939     */
2940    private final native lastIndexOfImpl(searchElement: number, fromIndex: int): number
2941
2942    /**
2943     * Returns the index of the first occurrence of a value in Array.
2944     *
2945     * @param searchElement The value to locate in the array.
2946     *
2947     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
2948     *  search starts at index 0.
2949     *
2950     * @returns index of element if it presents, -1 otherwise
2951     */
2952    private final native lastIndexOfImpl(searchElement: long, fromIndex: int): number
2953
2954    /**
2955     * Returns the index of the last occurrence of a value in Uint8Array.
2956     *
2957     * @param searchElement The value to locate in the array.
2958     *
2959     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
2960     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
2961     *
2962     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
2963     */
2964    public lastIndexOf(searchElement: int): number {
2965        return this.lastIndexOf(searchElement, this.lengthInt - 1)
2966    }
2967
2968   /**
2969    * Creates a new Uint8Array using initializer
2970    *
2971    * @param data initializer
2972    *
2973    * @returns a new Uint8Array from data
2974    */
2975    public of(...data: FixedArray<number>): Uint8Array {
2976        throw new Error("Uint8Array.of: not implemented")
2977    }
2978
2979    /**
2980     * Creates a new Uint8Array using reversed data from the current one
2981     *
2982     * @returns a new Uint8Array using reversed data from the current one
2983     */
2984    public native reverse(): Uint8Array
2985
2986    /**
2987     * Creates a slice of current Uint8Array using range [begin, end)
2988     *
2989     * @param begin start index to be taken into slice
2990     *
2991     * @param end last index to be taken into slice
2992     *
2993     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
2994     *
2995     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
2996     */
2997    public slice(begin?: number, end?: number): Uint8Array {
2998        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
2999    }
3000
3001    /**
3002     * Creates a slice of current Uint8Array using range [begin, end)
3003     *
3004     * @param begin start index to be taken into slice
3005     *
3006     * @param end last index to be taken into slice
3007     *
3008     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3009     *
3010     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3011     */
3012    public slice(begin: number, end: number): Uint8Array {
3013        return this.slice(begin as int, end as int)
3014    }
3015
3016    /**
3017     * Creates a slice of current Uint8Array using range [begin, end)
3018     *
3019     * @param begin start index to be taken into slice
3020     *
3021     * @param end last index to be taken into slice
3022     *
3023     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3024     *
3025     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3026     */
3027    public slice(begin: number, end: int): Uint8Array {
3028        return this.slice(begin as int, end as int)
3029    }
3030
3031    /**
3032     * Creates a slice of current Uint8Array using range [begin, end)
3033     *
3034     * @param begin start index to be taken into slice
3035     *
3036     * @param end last index to be taken into slice
3037     *
3038     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3039     *
3040     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3041     */
3042    public slice(begin: int, end: number): Uint8Array {
3043        return this.slice(begin as int, end as int)
3044    }
3045
3046    /**
3047     * Creates a slice of current Uint8Array using range [begin, end)
3048     *
3049     * @param begin start index to be taken into slice
3050     *
3051     * @param end last index to be taken into slice
3052     *
3053     * @returns a new Uint8Array with elements of current Uint8Array[begin;end) where end index is excluded
3054     *
3055     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
3056     */
3057    public slice(begin: int, end: int): Uint8Array {
3058        const len: int = this.lengthInt
3059        const relStart = normalizeIndex(begin, len)
3060        const relEnd = normalizeIndex(end, len)
3061        let count = relEnd - relStart
3062        if (count < 0) {
3063            count = 0
3064        }
3065        let buf = this.buffer.slice(relStart * Uint8Array.BYTES_PER_ELEMENT as int, relEnd * Uint8Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
3066        return new Uint8Array(buf)
3067    }
3068
3069    /**
3070     * Creates a slice of current Uint8Array using range [begin, this.lengthInt).
3071     *
3072     * @param begin start index to be taken into slice
3073     *
3074     * @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)
3075     */
3076    public slice(begin: number): Uint8Array {
3077        return this.slice(begin as int)
3078    }
3079
3080    /**
3081     * Creates a slice of current Uint8Array using range [begin, this.lengthInt).
3082     *
3083     * @param begin start index to be taken into slice
3084     *
3085     * @returns a new Uint8Array with elements of current Uint8Array[begin, this.lengthInt)
3086     */
3087    public slice(begin: int): Uint8Array {
3088        return this.slice(begin, this.lengthInt)
3089    }
3090
3091    /**
3092     * Sorts in-place by numeric value in ascending order.
3093     *
3094     * @returns sorted Array
3095     */
3096    public native sort(): this;
3097
3098    /**
3099     * Sorts in-place
3100     *
3101     * @param compareFn comparator _  used to determine the order of the elements.
3102     * compareFn returns a negative value if first argument is less than second argument,
3103     * zero if they're equal and a positive value otherwise.
3104     *
3105     * @returns sorted Uint8Array
3106     */
3107    public sort(compareFn?: (a: number, b: number) => number): this {
3108        if (compareFn == undefined) {
3109            this.sort()
3110            return this
3111        }
3112        let arr: FixedArray<int> = new int[this.lengthInt]
3113        for (let i = 0; i < this.lengthInt; ++i) {
3114            arr[i] = this.getUnsafe(i)
3115        }
3116
3117        let cmp = (l: int, r: int): number => {
3118            const result = compareFn!(l as number, r as number)
3119            return result
3120        }
3121        const MAX_SHORT_LENGTH = 24
3122        if (arr.length > MAX_SHORT_LENGTH) {
3123            arr = mergeSort(arr, cmp)
3124        } else {
3125            sort(arr, cmp)
3126        }
3127        for (let i = 0; i < arr.length; ++i) {
3128            this.setUnsafe(i, arr[i])
3129        }
3130        return this
3131    }
3132
3133    /**
3134     * Creates a Uint8Array with the same underlying Buffer
3135     *
3136     * @param begin start index, inclusive
3137     *
3138     * @param end last index, exclusive
3139     *
3140     * @returns new Uint8Array with the same underlying Buffer
3141     */
3142    public subarray(begin?: number, end?: number): Uint8Array {
3143        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
3144    }
3145
3146    /**
3147     * Creates a Uint8Array with the same underlying Buffer
3148     *
3149     * @param begin start index, inclusive
3150     *
3151     * @param end last index, exclusive
3152     *
3153     * @returns new Uint8Array with the same underlying Buffer
3154     */
3155    public subarray(begin: number, end: int): Uint8Array {
3156        return this.subarray(begin as int, end as int)
3157    }
3158
3159    /**
3160     * Creates a Uint8Array with the same underlying Buffer
3161     *
3162     * @param begin start index, inclusive
3163     *
3164     * @param end last index, exclusive
3165     *
3166     * @returns new Uint8Array with the same underlying Buffer
3167     */
3168    public subarray(begin: int, end: number): Uint8Array {
3169        return this.subarray(begin as int, end as int)
3170    }
3171
3172    /**
3173     * Creates a Uint8Array with the same underlying Buffer
3174     *
3175     * @param begin start index, inclusive
3176     *
3177     * @param end last index, exclusive
3178     *
3179     * @returns new Uint8Array with the same underlying Buffer
3180     */
3181    public subarray(begin: int, end: int | undefined = this.lengthInt): Uint8Array {
3182        const len: int = this.lengthInt
3183        const relStart = normalizeIndex(begin, len)
3184        const relEnd = normalizeIndex(end ?? this.lengthInt, len)
3185        let count = relEnd - relStart
3186        if (count < 0) {
3187            count = 0
3188        }
3189        return new Uint8Array(this.buffer, relStart * Uint8Array.BYTES_PER_ELEMENT as int, count)
3190    }
3191
3192    /**
3193     * Converts Uint8Array to a string with respect to locale
3194     *
3195     * @param locales
3196     *
3197     * @param options
3198     *
3199     * @returns string representation
3200     */
3201    public toLocaleString(locales: Object, options: Object): string {
3202        throw new Error("Uint8Array.toLocaleString: not implemented")
3203    }
3204
3205    /**
3206     * Converts Uint8Array to a string with respect to locale
3207     *
3208     * @param locales
3209     *
3210     * @returns string representation
3211     */
3212    public toLocaleString(locales: Object): string {
3213        return this.toLocaleString(new Object(), new Object())
3214    }
3215
3216    /**
3217     * Converts Uint8Array to a string with respect to locale
3218     *
3219     * @returns string representation
3220     */
3221    public toLocaleString(): string {
3222        let res: StringBuilder = new StringBuilder("")
3223        for (let i = 0; i < this.lengthInt - 1; ++i) {
3224            res.append((this.getUnsafe(i) as Number).toLocaleString())
3225            res.append(",")
3226        }
3227        if (this.lengthInt > 0) {
3228            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
3229        }
3230        return res.toString()
3231    }
3232
3233    /**
3234     * Creates a reversed copy
3235     *
3236     * @returns a reversed copy
3237     */
3238    public final native toReversed(): Uint8Array
3239
3240    /**
3241     * Creates a sorted copy
3242     *
3243     * @returns a sorted copy
3244     */
3245    public toSorted(): Uint8Array {
3246        return new Uint8Array(this).sort()
3247    }
3248
3249    /**
3250     * Returns a string representation of the Uint8Array
3251     *
3252     * @returns a string representation of the Uint8Array
3253     */
3254    public override toString(): string {
3255        return this.join(",")
3256    }
3257
3258    /**
3259     * Returns array values iterator
3260     *
3261     * @returns an iterator
3262     */
3263    public values(): IterableIterator<Number> {
3264         return new Uint8ArrayIterator(this)
3265    }
3266
3267    /**
3268     * Creates a copy with replaced value on index
3269     *
3270     * @param index
3271     *
3272     * @param value
3273     *
3274     * @returns an Uint8Array with replaced value on index
3275     */
3276    public with(index: number, value: number): Uint8Array {
3277        return this.with(index as int, value as int)
3278    }
3279
3280    /**
3281     * Creates a copy with replaced value on index
3282     *
3283     * @param index
3284     *
3285     * @param value
3286     *
3287     * @returns an Uint8Array with replaced value on index
3288     */
3289    public with(index: int, value: int): Uint8Array {
3290        let res = new Uint8Array(this)
3291        res.setUnsafeClamp(index, value)
3292        return res
3293    }
3294
3295    /// === with element lambda functions ===
3296
3297    /**
3298     * Determines whether the specified callback function returns true for any element of an array.
3299     *
3300     * @param predicate A function that accepts three arguments.
3301     * The some method calls the predicate function for each element in the array
3302     * until the predicate returns a true or until the end of the array.
3303     *
3304     * @returns false unless predicate function returns true for an array element,
3305     * in which case true is immediately returned.
3306     */
3307    public some(predicate: (element: number, index: number, array: Uint8Array) => boolean): boolean {
3308        for (let i = 0; i < this.lengthInt; i++) {
3309            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
3310                return true
3311            }
3312        }
3313        return false
3314    }
3315
3316    /**
3317     * Calls the specified callback function for all the elements in an array.
3318     * The return value of the callback function is the accumulated result,
3319     * and is provided as an argument in the next call to the callback function.
3320     *
3321     * @param callbackfn A function that accepts four arguments.
3322     * The reduce method calls the callbackfn function one time for each element in the array.
3323     *
3324     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
3325     * The first call to the callbackfn function provides this value as an argument.
3326     *
3327     * @returns The value that results from running the callback function to completion over the entire typed array.
3328     */
3329    public reduce<U = number>(
3330                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U,
3331                initialValue: U): U {
3332        let accumulatedValue = initialValue
3333        for (let i = 0; i < this.lengthInt; i++) {
3334            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
3335        }
3336        return accumulatedValue
3337    }
3338
3339    /**
3340     * Calls the specified callback function for all the elements in an array.
3341     * The return value of the callback function is the accumulated result,
3342     * and is provided as an argument in the next call to the callback function.
3343     *
3344     * @param callbackfn A function that accepts four arguments.
3345     * The reduce method calls the callbackfn function one time for each element in the array.
3346     * The first call to the callbackfn function provides array first element value as an argument
3347     *
3348     * @returns The value that results from running the callback function to completion over the entire typed array.
3349     * calling reduce method on an empty array without an initial value creates a TypeError
3350     */
3351    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number {
3352        if (this.lengthInt == 0) {
3353            throw new TypeError("Reduce of empty array with no initial value")
3354        }
3355
3356        let accumulatedValue = this.$_get(0) as number
3357        for (let i = 1; i < this.lengthInt; i++) {
3358            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
3359        }
3360        return accumulatedValue
3361    }
3362
3363    /**
3364     * Calls the specified callback function for all the elements in an array, in descending order.
3365     * The return value of the callback function is the accumulated result,
3366     * and is provided as an argument in the next call to the callback function.
3367     *
3368     * @param callbackfn A function that accepts four arguments.
3369     * The reduceRight method calls the callbackfn function one time for each element in the array.
3370     *
3371     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
3372     * The first call to the callbackfn function provides this value as an argument.
3373     *
3374     * @returns The value that results from running the callback function to completion over the entire typed array.
3375     */
3376    public reduceRight<U = number>(
3377                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U,
3378                initialValue: U): U {
3379        let accumulatedValue = initialValue
3380        for (let i = this.lengthInt - 1; i >= 0; i--) {
3381            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
3382        }
3383        return accumulatedValue
3384    }
3385
3386    /**
3387     * Calls the specified callback function for all the elements in an array, in descending order.
3388     * The return value of the callback function is the accumulated result,
3389     * and is provided as an argument in the next call to the callback function.
3390     *
3391     * @param callbackfn A function that accepts four arguments.
3392     * The reduceRight method calls the callbackfn function one time for each element in the array.
3393     * The first call to the callbackfn function provides array last element value as an argument
3394     *
3395     * @returns The value that results from running the callback function to completion over the entire typed array.
3396     * calling reduceRight method on an empty array without an initial value creates a TypeError
3397     */
3398    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number {
3399        if (this.lengthInt == 0) {
3400            throw new TypeError("Reduce of empty array with no initial value")
3401        }
3402
3403        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
3404        for (let i = this.lengthInt - 2; i >= 0; i--) {
3405            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
3406        }
3407        return accumulatedValue
3408    }
3409
3410    /**
3411     * Creates a new Uint8Array using fn(arr[i]) over all elements of current Uint8Array.
3412     *
3413     * @param fn a function to apply for each element of current Uint8Array
3414     *
3415     * @returns a new Uint8Array where for each element from current Uint8Array fn was applied
3416     */
3417    public map(fn: (val: number, index: number, array: Uint8Array) => number): Uint8Array {
3418        let resBuf = new ArrayBuffer(this.lengthInt * Uint8Array.BYTES_PER_ELEMENT as int)
3419        let res = new Uint8Array(resBuf)
3420        for (let i = 0; i < this.lengthInt; i++) {
3421            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
3422            res.setUnsafeClamp(i, fnRes as int)
3423        }
3424        return res
3425    }
3426
3427    /**
3428     * Determines whether the specified callback function returns true for all elements of an array.
3429     *
3430     * @param predicate A function that accepts three arguments.
3431     * The every method calls the predicate function for each element in the array until the predicate returns a false,
3432     * or until the end of the array.
3433     *
3434     * @returns true unless predicate function returns a false for an array element,
3435     * in which case false is immediately returned.
3436     */
3437    public every(predicate: (element: number, index: number, array: Uint8Array) => boolean): boolean {
3438        for (let i = 0; i < this.lengthInt; i++) {
3439            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
3440                return false
3441            }
3442        }
3443        return true
3444    }
3445
3446    /**
3447     * Creates a new Uint8Array from current Uint8Array based on a condition fn.
3448     *
3449     * @param fn the condition to apply for each element
3450     *
3451     * @returns a new Uint8Array with elements from current Uint8Array that satisfy condition fn
3452     */
3453    public filter(fn: (val: number, index: number, array: Uint8Array) => boolean): Uint8Array {
3454        let markers : FixedArray<boolean> = new boolean[this.lengthInt]
3455        let resLen = 0
3456        for (let i = 0; i < this.lengthInt; i++) {
3457            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
3458            if (markers[i]) {
3459                ++resLen
3460            }
3461        }
3462        let res = new Uint8Array(resLen)
3463        for (let i = 0, j = 0; i < this.lengthInt; i++) {
3464            if (markers[i]) {
3465                res.setUnsafe(j, this.getUnsafe(i))
3466                ++j
3467            }
3468        }
3469        return res
3470    }
3471
3472    /**
3473     * Returns the value of the first element in the array where predicate is true, and undefined
3474     * otherwise
3475     *
3476     * @param predicate find calls predicate once for each element of the array, in ascending
3477     * order, until it finds one where predicate returns true. If such an element is found, find
3478     * immediately returns that element value. Otherwise, find returns undefined
3479     *
3480     * @returns number | undefined
3481     */
3482    public find(predicate: (value: number, index: number, array: Uint8Array) => boolean): number | undefined {
3483        for (let i = 0; i < this.lengthInt; i++) {
3484            let val = this.getUnsafe(i) as number
3485            if (predicate(val, i as number, this)) {
3486                return val
3487            }
3488        }
3489        return undefined
3490    }
3491
3492    /**
3493     * Returns the index of the first element in the array where predicate is true, and -1
3494     * otherwise
3495     *
3496     * @param predicate find calls predicate once for each element of the array, in ascending
3497     * order, until it finds one where predicate returns true. If such an element is found,
3498     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
3499     *
3500     * @returns number
3501     */
3502    public findIndex(predicate: (value: number, index: number, obj: Uint8Array) => boolean): number {
3503        for (let i = 0; i < this.lengthInt; i++) {
3504            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
3505                return i as number
3506            }
3507        }
3508        return -1 as number
3509    }
3510
3511    /**
3512     * Finds the last element in the Uint8Array that satisfies the condition
3513     *
3514     * @param fn condition
3515     *
3516     * @returns the last element that satisfies fn
3517     */
3518    public findLast(fn: (val: number, index: number, array: Uint8Array) => boolean): number {
3519        for (let i = this.lengthInt - 1; i >= 0; i--) {
3520            let val = this.getUnsafe(i) as number
3521            if (fn(val, i as number, this)) {
3522                return val
3523            }
3524        }
3525        throw new Error("Uint8Array.findLast: not implemented if an element was not found")
3526    }
3527
3528    /**
3529     * Finds an index of the last element in the Uint8Array that satisfies the condition
3530     *
3531     * @param fn condition
3532     *
3533     * @returns the index of the last element that satisfies fn, -1 otherwise
3534     */
3535    public findLastIndex(fn: (val: number, index: number, array: Uint8Array) => boolean): number {
3536        for (let i = this.lengthInt - 1; i >= 0; i--) {
3537            if (fn(this.getUnsafe(i) as number, i as number, this)) {
3538                return i as number
3539            }
3540        }
3541        return -1 as number
3542    }
3543
3544    /**
3545     * Performs the specified action for each element in Uint8Array
3546     *
3547     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
3548     * callbackfn function one time for each element in the array.
3549     *
3550     * @returns None
3551     */
3552    public forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void): void {
3553        for (let i = 0; i < this.lengthInt; i++) {
3554            callbackfn(this.getUnsafe(i) as number, i as number, this)
3555        }
3556    }
3557
3558    /**
3559     * Returns the object itself
3560     *
3561     * @returns Uint8Array
3562     */
3563    public valueOf(): Uint8Array {
3564        return this
3565    }
3566
3567    /** Byte offset within the underlying Buffer */
3568    public get byteOffset(): number {
3569        return this.byteOffsetInt
3570    }
3571
3572    /** Number of bytes used */
3573    public get byteLength(): number {
3574        return this.byteLengthInt
3575    }
3576
3577    /** Number of int stored in Uint8Array */
3578    public get length(): number {
3579        return this.lengthInt
3580    }
3581
3582    /** String \"Uint8Array\" */
3583    public readonly name = "Uint8Array"
3584
3585    private static clamp(val: int): int {
3586        return val
3587    }
3588
3589    internal setUnsafeClamp(insertPos: int, val: int): void {
3590        this.setUnsafe(insertPos, val)
3591    }
3592
3593    private final native getUnsafe(index: int): int
3594
3595    internal setUnsafe(index: int, val: int): void {
3596        index = index * Uint8Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
3597        let res: int = 0
3598        if (IS_LITTLE_ENDIAN) {
3599            for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
3600                this.buffer.set(index + i, (val & 0xff) as byte)
3601                val = val >> 8
3602            }
3603        } else {
3604            for (let i = 0; i < Uint8Array.BYTES_PER_ELEMENT as int; i++) {
3605                this.buffer.set(index + 0 - i, (val & 0xff) as byte)
3606                val = val >> 8
3607            }
3608        }
3609    }
3610}
3611
3612
3613class Uint16ArrayIteratorKeys implements IterableIterator<number> {
3614    private length: int = 0
3615    private idx: int = 0
3616
3617    constructor(parent: Uint16Array) {
3618        this.length = parent.length as int
3619    }
3620
3621    public override $_iterator(): IterableIterator<Number> {
3622        return this
3623    }
3624
3625    override next(): IteratorResult<number> {
3626        if (this.idx < 0 || this.idx >= this.length) {
3627            return new IteratorResult<number>()
3628        }
3629        return new IteratorResult<number>(false, this.idx++ as number)
3630    }
3631}
3632
3633class Uint16ArrayIterator implements IterableIterator<Number> {
3634    private parent: Uint16Array
3635    private idx: int = 0
3636
3637    constructor(parent: Uint16Array) {
3638        this.parent = parent
3639    }
3640
3641    public override $_iterator(): IterableIterator<Number> {
3642        return this
3643    }
3644
3645    override next(): IteratorResult<Number> {
3646        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
3647            return new IteratorResult<Number>()
3648        }
3649        return new IteratorResult<Number>(false, new Number(this.parent[this.idx++]))
3650    }
3651}
3652
3653class Uint16ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
3654    private parent: Uint16Array
3655    private idx: int = 0
3656
3657    constructor(parent: Uint16Array) {
3658        this.parent = parent
3659    }
3660
3661    public override $_iterator(): IterableIterator<[Number, Number]> {
3662        return this
3663    }
3664
3665    override next(): IteratorResult<[Number, Number]> {
3666        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
3667            return new IteratorResult<[Number, Number]>()
3668        }
3669        return new IteratorResult<[Number, Number]>(
3670            false,
3671            [new Number(this.idx), new Number(this.parent[this.idx++])]
3672        )
3673    }
3674}
3675
3676/**
3677 * JS Uint16Array API-compatible class
3678 */
3679export final class Uint16Array implements Iterable<Number>, ArrayLike<Number> {
3680    public static readonly BYTES_PER_ELEMENT: number = 2
3681    public readonly BYTES_PER_ELEMENT: number = Uint16Array.BYTES_PER_ELEMENT
3682
3683    /** Underlying Buffer */
3684    public readonly buffer: ArrayBuffer
3685
3686    internal readonly byteOffsetInt: int
3687    internal readonly byteLengthInt: int
3688    internal readonly lengthInt: int
3689
3690    /**
3691     * Creates an empty Uint16Array.
3692     */
3693    public constructor() {
3694        this(0 as int)
3695    }
3696
3697    /**
3698     * Creates an Uint16Array with respect to data accessed via Iterable<Number> interface
3699     */
3700    public constructor(elements: Iterable<Number>) {
3701        const items: Object = elements as Object
3702        if (items instanceof ArrayLike) {
3703            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
3704            this.byteLengthInt = arr.length as int * Uint16Array.BYTES_PER_ELEMENT as int
3705            this.lengthInt = arr.length as int
3706            this.buffer = new ArrayBuffer(this.byteLengthInt)
3707            this.byteOffsetInt = 0
3708            for (let i: int = 0; i < this.lengthInt; ++i) {
3709                this.setUnsafeClamp(i, this.zeroIfInfinity(arr.$_get(i)) as int)
3710            }
3711        } else {
3712            let x = Uint16Array.from(elements)
3713            this.byteLengthInt = x.byteLengthInt
3714            this.lengthInt = x.lengthInt
3715            this.buffer = x.buffer
3716            this.byteOffsetInt = x.byteOffsetInt
3717        }
3718    }
3719
3720    /**
3721     * Creates an Uint16Array with respect to data, byteOffset and length.
3722     *
3723     * @param buf data initializer
3724     *
3725     * @param byteOffset byte offset from begin of the buf
3726     *
3727     * @param length size of elements of type int in newly created Uint16Array
3728     */
3729    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined, length: Number | undefined) {
3730        let intByteOffset: int = 0
3731        if (byteOffset != undefined) {
3732            intByteOffset = byteOffset.toInt()
3733            if (intByteOffset < 0) {
3734                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
3735            }
3736        }
3737        let intByteLength: int = buf.getByteLength() - intByteOffset
3738        if (intByteLength < 0) {
3739            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
3740        }
3741
3742        if (intByteLength % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
3743            throw new RangeError("ArrayBuffer.byteLength should be multiple of 2 as Uint16Array.BYTES_PER_ELEMENT")
3744        }
3745        if (intByteOffset % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
3746            throw new RangeError("byteOffset should be multiple of 2 as Uint16Array.BYTES_PER_ELEMENT")
3747        }
3748
3749        let intLength: int
3750        if (length != undefined) {
3751            intLength = length.toInt()
3752            if (intLength > intByteLength / Uint16Array.BYTES_PER_ELEMENT as int) {
3753                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
3754            }
3755        } else {
3756            intLength = intByteLength / Uint16Array.BYTES_PER_ELEMENT as int
3757        }
3758        if (intLength < 0) {
3759            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
3760        }
3761        if (intLength < intByteLength / Uint16Array.BYTES_PER_ELEMENT as int) {
3762            intByteLength = intLength * Uint16Array.BYTES_PER_ELEMENT as int
3763        }
3764        this.byteLengthInt = intByteLength
3765        this.byteOffsetInt = intByteOffset
3766        this.lengthInt = intLength
3767        this.buffer = buf
3768    }
3769
3770    /**
3771     * Creates an Uint16Array with respect to data, byteOffset and length.
3772     *
3773     * @param buf data initializer
3774     *
3775     * @param byteOffset byte offset from begin of the buf
3776     */
3777    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined) {
3778        this(buf, byteOffset, undefined)
3779    }
3780
3781    /**
3782     * Creates an Uint16Array with respect to data, byteOffset and length.
3783     *
3784     * @param buf data initializer
3785     *
3786     * @param byteOffset byte offset from begin of the buf
3787     *
3788     * @param length size of elements of type int in newly created Uint16Array
3789     */
3790    public constructor(buf: ArrayBuffer, byteOffset: number, length: number) {
3791        this(buf, new Number(byteOffset), new Number(length))
3792    }
3793
3794    /**
3795     * Creates an Uint16Array with respect to buf and byteOffset.
3796     *
3797     * @param buf data initializer
3798     *
3799     * @param byteOffset byte offset from begin of the buf
3800     */
3801    public constructor(buf: ArrayBuffer, byteOffset: number) {
3802        this(buf, new Number(byteOffset), undefined)
3803    }
3804
3805    /**
3806     * Creates an Uint16Array with respect to data, byteOffset and length.
3807     *
3808     * @param buf data initializer
3809     *
3810     * @param byteOffset byte offset from begin of the buf
3811     *
3812     * @param length size of elements of type int in newly created Uint16Array
3813     */
3814    public constructor(buf: ArrayBuffer, byteOffset: int, length: int) {
3815        this(buf, new Number(byteOffset), new Number(length))
3816    }
3817
3818    /**
3819     * Creates an Uint16Array with respect to buf and byteOffset.
3820     *
3821     * @param buf data initializer
3822     *
3823     * @param byteOffset byte offset from begin of the buf
3824     */
3825    public constructor(buf: ArrayBuffer, byteOffset: int) {
3826        this(buf, new Number(byteOffset), undefined)
3827    }
3828
3829    /**
3830     * Creates an Uint16Array with respect to buf.
3831     *
3832     * @param buf data initializer
3833     */
3834    public constructor(buf: ArrayLike<Number> | ArrayBuffer) {
3835        if (buf instanceof ArrayBuffer) {
3836            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
3837            if (this.byteLengthInt % Uint16Array.BYTES_PER_ELEMENT as int != 0) {
3838               throw new RangeError("ArrayBuffer.byteLength should be multiple of int as Uint16Array.BYTES_PER_ELEMENT")
3839            }
3840            this.lengthInt = this.byteLengthInt / Uint16Array.BYTES_PER_ELEMENT as int
3841            this.buffer = buf as ArrayBuffer
3842            this.byteOffsetInt = 0
3843        } else if (buf instanceof ArrayLike) {
3844            // NOTE (ikorobkov): dealing with this overload is tricky
3845            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.ets
3846            let arr = Array.from<Number>((buf as ArrayLike<Number>))
3847            this.byteLengthInt = arr.length as int * Uint16Array.BYTES_PER_ELEMENT as int
3848            this.lengthInt = arr.length as int
3849            this.buffer = new ArrayBuffer(this.byteLengthInt)
3850            this.byteOffsetInt = 0
3851            for (let i: int = 0; i < this.lengthInt; ++i) {
3852                this.setUnsafe(i, arr.$_get(i).toInt())
3853            }
3854        } else {
3855            throw new Error("unexpected type of buf")
3856        }
3857    }
3858
3859    /**
3860     * Creates an Uint16Array with respect to length.
3861     *
3862     * @param length data initializer
3863     */
3864    public constructor(length: int) {
3865        this(length as number)
3866    }
3867
3868    /**
3869     * Creates an Uint16Array with respect to length.
3870     *
3871     * @param length data initializer
3872     */
3873    public constructor(length: number) {
3874        if (length < 0 || length > (Int.MAX_VALUE / Uint16Array.BYTES_PER_ELEMENT)) {
3875            throw new TypeError("Type Error: length " + length + " is outside the bounds of the buffer")
3876        }
3877        this.lengthInt = length as int
3878        this.byteLengthInt = this.lengthInt * Uint16Array.BYTES_PER_ELEMENT as int
3879        this.byteOffsetInt = 0
3880        this.buffer = new ArrayBuffer(this.byteLengthInt)
3881    }
3882
3883    /**
3884     * Creates a copy of Uint16Array.
3885     *
3886     * @param other data initializer
3887     */
3888    public constructor(other: Uint16Array) {
3889        this.buffer = other.buffer.slice(other.byteOffset as int, (other.byteOffset + other.byteLength) as int) as ArrayBuffer
3890        this.byteLengthInt = other.byteLength as int
3891        this.lengthInt = other.length as int
3892        this.byteOffsetInt = 0
3893    }
3894
3895    /**
3896     * Creates an Uint16Array from FixedArray<number>
3897     */
3898    public constructor(numbers: FixedArray<number>) {
3899        this(numbers.length)
3900        for (let i: int = 0; i < this.lengthInt; ++i) {
3901            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
3902        }
3903    }
3904
3905    /**
3906     * Creates an Uint16Array from FixedArray<int>
3907     */
3908    public constructor(numbers: FixedArray<int>) {
3909        this(numbers.length)
3910        for (let i: int = 0; i < this.lengthInt; ++i) {
3911            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as int)
3912        }
3913    }
3914    internal zeroIfInfinity(val: number): number {
3915        if ((val == Infinity) || (val == -Infinity)) {
3916            return 0 as number
3917        }
3918        return val as number
3919    }
3920
3921    internal zeroIfInfinity(val: int): int {
3922        if ((val == Infinity) || (val == -Infinity)) {
3923            return 0 as int
3924        }
3925        return val
3926    }
3927
3928    /**
3929     * Iteratorable interface implementation
3930     *
3931     * @returns iterator over all elements
3932     */
3933    public override $_iterator(): IterableIterator<Number> {
3934         return this.values()
3935    }
3936
3937    /**
3938     * Returns an instance of primitive type at passed index.
3939     *
3940     * @param index index to look at
3941     *
3942     * @returns a primitive at index
3943     */
3944    public at(index: number): Number | undefined {
3945        return this.at(index as int)
3946    }
3947
3948    /**
3949     * Returns an instance of primitive type at passed index if index is correct.
3950     *
3951     * @param index index to look at
3952     *
3953     * @returns a primitive at index
3954     */
3955    public at(index: int): Number | undefined {
3956        let k: int
3957        if (index >= 0) {
3958            k = index
3959        } else {
3960            k = this.lengthInt + index
3961        }
3962        if (k < 0 || k >= this.lengthInt) {
3963            return undefined
3964        }
3965        return new Number(this.getUnsafe(k))
3966    }
3967
3968    /**
3969     * Returns an instance of number at passed index.
3970     *
3971     * @param index index to look at
3972     *
3973     * @returns a primitive at index
3974     */
3975    public override $_get(index: number): Number {
3976        return this.$_get(index as int) as Number
3977    }
3978
3979    /**
3980     * Returns an instance of number at passed index.
3981     *
3982     * @param index index to look at
3983     *
3984     * @returns a primitive at index
3985     */
3986    public native $_get(i: int): number
3987
3988    /**
3989     * Assigns val as element on index.
3990     *
3991     * @param val value to set
3992     *
3993     * @param index index to change
3994     */
3995    public $_set(index: number, val: number): void {
3996        this.$_set(index as int, val)
3997    }
3998
3999    /**
4000     * Assigns val as element on index.
4001     *
4002     * @param val value to set
4003     *
4004     * @param index index to change
4005     */
4006    public $_set(index: int, val: number): void {
4007        let v = this.zeroIfInfinity(val)
4008        this.$_set(index, v as int)
4009    }
4010
4011    /**
4012     * Assigns val as element on index.
4013     *
4014     * @param val value to set
4015     *
4016     * @param index index to change
4017     */
4018    public $_set(index: number, val: int): void {
4019        this.$_set(index as int, val)
4020    }
4021
4022    /**
4023     * Assigns val as element on index.
4024     *
4025     * @param val value to set
4026     *
4027     * @param index index to change
4028     */
4029    public native $_set(index: int, val: int): void
4030
4031    /**
4032     * Makes a copy of internal elements to targetPos from startPos to endPos.
4033     *
4034     * @param target insert index to place copied elements
4035     *
4036     * @param start start index to begin copy from
4037     *
4038     * @param end last index to end copy from, excluded
4039     *
4040     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
4041     */
4042    public copyWithin(target: number, start: number, end?: number): Uint16Array {
4043        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
4044    }
4045
4046    /**
4047     * Makes a copy of internal elements to targetPos from startPos to endPos.
4048     *
4049     * @param target insert index to place copied elements
4050     *
4051     * @param start start index to begin copy from
4052     *
4053     * @param end last index to end copy from, excluded
4054     *
4055     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
4056     */
4057    public copyWithin(target: int, start: number, end?: number): Uint16Array {
4058        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
4059    }
4060
4061    /**
4062     * Makes a copy of internal elements to targetPos from startPos to endPos.
4063     *
4064     * @param target insert index to place copied elements
4065     *
4066     * @param start start index to begin copy from
4067     *
4068     * @param end last index to end copy from, excluded
4069     *
4070     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
4071     */
4072    public copyWithin(target: number, start: int, end?: number): Uint16Array {
4073        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
4074    }
4075
4076    /**
4077     * Makes a copy of internal elements to targetPos from startPos to endPos.
4078     *
4079     * @param target insert index to place copied elements
4080     *
4081     * @param start start index to begin copy from
4082     *
4083     * @param end last index to end copy from, excluded
4084     *
4085     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
4086     */
4087    public copyWithin(target: int, start: int, end?: number): Uint16Array {
4088        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
4089    }
4090
4091    /**
4092     * Makes a copy of internal elements to targetPos from startPos to endPos.
4093     *
4094     * @param insert insert index to place copied elements
4095     *
4096     * @param start start index to begin copy from
4097     *
4098     * @param end last index to end copy from, excluded
4099     *
4100     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
4101     */
4102    public native copyWithin(target: int, start: int, end: int): Uint16Array
4103
4104    /**
4105     * Makes a copy of internal elements to targetPos from begin to end of Uint16Array.
4106     *
4107     * @param target insert index to place copied elements
4108     *
4109     * See rules of parameters normalization:
4110     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
4111     */
4112    public copyWithin(target: number): Uint16Array {
4113        return this.copyWithin(target as int)
4114    }
4115
4116    /**
4117     * Makes a copy of internal elements to targetPos from begin to end of Uint16Array.
4118     *
4119     * @param insert insert index to place copied elements
4120     *
4121     * See rules of parameters normalization:
4122     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
4123     */
4124    public copyWithin(target: int): Uint16Array {
4125        return this.copyWithin(target, 0, this.lengthInt)
4126    }
4127
4128    /**
4129     * Returns an array of key, value pairs for every entry in the Uint16Array
4130     *
4131     * @returns key, value pairs for every entry in the array
4132     */
4133    public entries(): IterableIterator<[Number, Number]> {
4134        return new Uint16ArrayIteratorEntries(this)
4135    }
4136
4137    /**
4138     * Fills the Uint16Array with specified value
4139     *
4140     * @param value new value
4141     *
4142     * @returns modified Uint16Array
4143     */
4144    public fill(value: number, start?: number, end?: number): Uint16Array {
4145        value = this.zeroIfInfinity(value)
4146        this.fill(value as int, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
4147        return this
4148    }
4149
4150    /**
4151     * Fills the Uint16Array with specified value
4152     *
4153     * @param value new value
4154     *
4155     * @returns modified Uint16Array
4156     */
4157    public fill(value: number, start: int, end?: number): Uint16Array {
4158        value = this.zeroIfInfinity(value)
4159        this.fill(value as int, start as int, asIntOrDefault(end, this.lengthInt))
4160        return this
4161    }
4162
4163    /**
4164     * Fills the Uint16Array with specified value
4165     *
4166     * @param value new value
4167     *
4168     * @returns modified Uint16Array
4169     */
4170    public fill(value: number, start: int, end: number): Uint16Array {
4171        value = this.zeroIfInfinity(value)
4172        this.fill(value as int, start as int, end as int)
4173        return this
4174    }
4175
4176    /**
4177     * Fills the Uint16Array with specified value
4178     *
4179     * @param value new value
4180     *
4181     * @returns modified Uint16Array
4182     */
4183    public fill(value: number, start: number, end: int): Uint16Array {
4184        value = this.zeroIfInfinity(value)
4185        this.fill(value as int, start as int, end as int)
4186        return this
4187    }
4188
4189    /**
4190     * Fills the Uint16Array with specified value
4191     *
4192     * @param value new value
4193     *
4194     * @returns modified Uint16Array
4195     */
4196    public fill(value: number, start: int, end: int): Uint16Array {
4197        value = this.zeroIfInfinity(value)
4198        this.fill(value as int, start as int, end as int)
4199        return this
4200    }
4201
4202    /**
4203     * Fills the Uint16Array with specified value
4204     *
4205     * @param value new value
4206     *
4207     * @returns modified Uint16Array
4208     */
4209    public fill(value: int, start?: number, end?: number): Uint16Array {
4210        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
4211        return this
4212    }
4213
4214    /**
4215     * Fills the Uint16Array with specified value
4216     *
4217     * @param value new value
4218     *
4219     * @returns modified Uint16Array
4220     */
4221    public fill(value: int, start: int, end?: number): Uint16Array {
4222        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
4223        return this
4224    }
4225
4226    /**
4227     * Fills the Uint16Array with specified value
4228     *
4229     * @param value new value
4230     *
4231     * @returns modified Uint16Array
4232     */
4233    public fill(value: int, start: int, end: number): Uint16Array {
4234        this.fill(value, start as int, end as int)
4235        return this
4236    }
4237
4238    /**
4239     * Fills the Uint16Array with specified value
4240     *
4241     * @param value new value
4242     *
4243     * @returns modified Uint16Array
4244     */
4245    public fill(value: int, start: number, end: int): Uint16Array {
4246        this.fill(value, start as int, end as int)
4247        return this
4248    }
4249
4250    /**
4251     * Fills the Uint16Array with specified value
4252     *
4253     * @param value new value
4254     *
4255     * @returns modified Uint16Array
4256     */
4257    public fill(value: int, start: int, end: int): Uint16Array {
4258        const k = normalizeIndex(start, this.lengthInt)
4259        const finalPos = normalizeIndex(end, this.lengthInt)
4260        this.fillInternal(value, k, finalPos)
4261        return this
4262    }
4263
4264    private final native fillInternal(value: int, start: int, end: int): void
4265
4266    /**
4267     * Assigns val as element on index.
4268     *
4269     * @param val value to set
4270     *
4271     * @param index index to change
4272     */
4273    public set(insertPos: number, val: number): void {
4274        this.$_set(insertPos as int, val)
4275    }
4276
4277    /**
4278     * Assigns val as element on index.
4279     *
4280     * @param val value to set
4281     *
4282     * @param index index to change
4283     */
4284    public set(insertPos: int, val: number): void {
4285        this.$_set(insertPos as int, val)
4286    }
4287
4288    /**
4289     * Assigns val as element on index.
4290     *
4291     * @param val value to set
4292     *
4293     * @param index index to change
4294     */
4295    public set(insertPos: number, val: int): void {
4296        this.$_set(insertPos as int, val)
4297    }
4298
4299    /**
4300     * Assigns val as element on index.
4301     *
4302     * @param val value to set
4303     *
4304     * @param index index to change
4305     */
4306    public set(insertPos: int, val: int): void {
4307        this.$_set(insertPos as int, val)
4308    }
4309
4310    /**
4311     * Copies all elements of arr to the current Uint16Array starting from insertPos.
4312     *
4313     * @param arr array to copy data from
4314     *
4315     * @param insertPos start index where data from arr will be inserted
4316     *
4317     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
4318     */
4319    public set(arr: FixedArray<number>, insertPos1: number): void {
4320        const insertPos = insertPos1 as int
4321        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
4322            throw new RangeError("set(insertPos: int, arr: FixedArray<int>): size of arr is greater than Uint16Array.length")
4323        }
4324        for (let i = 0; i < arr.length; i++) {
4325            let v = this.zeroIfInfinity(arr[i])
4326            this.setUnsafeClamp(insertPos as int + i as int, v as int)
4327        }
4328    }
4329
4330    /**
4331     * Copies all elements of arr to the current Uint16Array starting from insertPos.
4332     *
4333     * @param arr array to copy data from
4334     *
4335     * @param insertPos start index where data from arr will be inserted
4336     *
4337     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
4338     */
4339    public set(arr: FixedArray<int>, insertPos: int): void {
4340        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
4341            throw new RangeError("set(insertPos: int, arr: FixedArray<int>): size of arr is greater than Uint16Array.length")
4342        }
4343        for (let i = 0; i < arr.length; i++) {
4344            let v = this.zeroIfInfinity(arr[i])
4345            this.setUnsafeClamp(insertPos + i, v)
4346        }
4347    }
4348
4349    /**
4350     * Copies all elements of arr to the current Uint16Array.
4351     *
4352     * @param arr array to copy data from
4353     */
4354    public set(arr: FixedArray<number>): void {
4355        this.set(arr, 0)
4356    }
4357
4358    /**
4359     * Copies all elements of arr to the current Uint16Array.
4360     *
4361     * @param arr array to copy data from
4362     */
4363    public set(arr: FixedArray<int>): void {
4364        this.set(arr, 0)
4365    }
4366
4367    public native set(array: Uint16Array): void
4368
4369    public native set(array: Uint16Array, offset: number): void
4370
4371    /**
4372     * Copies elements from an ArrayLike object to the Uint16Array.
4373     *
4374     * @param array An ArrayLike object containing the elements to copy.
4375     *
4376     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
4377     */
4378    public set(array: ArrayLike<number>, offset: number = 0): void {
4379        const insertPos = offset as int
4380        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
4381            throw new RangeError("offset is out of bounds")
4382        }
4383        for (let i = array.length - 1; i >= 0; --i) {
4384            let v = this.zeroIfInfinity(array[i])
4385            this.setUnsafeClamp(insertPos as int + i as int, v as int)
4386        }
4387    }
4388
4389    /**
4390     * Returns a new array from a set of elements.
4391     *
4392     * @param items a set of elements to include in the new array object.
4393     *
4394     * @returns new Uint16Array
4395     */
4396    public static of(...items: FixedArray<number>): Uint16Array {
4397        let res = new Uint16Array(items.length as int)
4398        for (let i: int = 0; i < items.length; i++) {
4399            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as int)
4400        }
4401        return res
4402    }
4403
4404    /**
4405     * Returns a new array from a set of elements.
4406     *
4407     * @param items a set of elements to include in the new array object.
4408     *
4409     * @returns new Uint16Array
4410     */
4411    public static of(...items: FixedArray<int>): Uint16Array {
4412        let res = new Uint16Array(items.length as int)
4413        for (let i: int = 0; i < items.length; i++) {
4414            res.setUnsafeClamp(i, items[i])
4415        }
4416        return res
4417    }
4418
4419    /**
4420     * Returns a new array from a set of elements.
4421     *
4422     * @param items a set of elements to include in the new array object.
4423     *
4424     * @returns new Uint16Array
4425     */
4426    public static of(): Uint16Array {
4427        return new Uint16Array(0 as int)
4428    }
4429
4430    /**
4431     * Creates an array from an array-like or iterable object.
4432     *
4433     * @param arrayLike An array-like or iterable object to convert to an array.
4434     *
4435     * @returns new Uint16Array
4436     */
4437    public static from(arr: ArrayLike<number>): Uint16Array {
4438        return Uint16Array.from<number>(arr, (x: number, k: number): number => x)
4439    }
4440
4441    /**
4442     * Creates an array from an array-like or iterable object.
4443     *
4444     * @param arrayLike An array-like or iterable object to convert to an array.
4445     *
4446     * @param mapfn A mapping function to call on every element of the array.
4447     *
4448     * @returns new Uint16Array
4449     */
4450    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint16Array {
4451        if (mapfn == undefined) {
4452            mapfn = (v: number, k: number): number => { return v }
4453        }
4454
4455        let iter = arrayLike.$_iterator()
4456        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
4457        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
4458        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
4459        //  we can make one pass through the iterator without the need for memory reallocation.
4460        const maybeLength = tryGetIteratorLength(arrayLike)
4461        if (maybeLength) {
4462            const result = new Uint16Array(maybeLength)
4463            for (let i = 0; i < maybeLength; ++i) {
4464                const x = iter.next()
4465                if (x.done) {
4466                    return new Uint16Array(result.buffer, 0, i)
4467                }
4468                result.setUnsafeClamp(i, result.zeroIfInfinity((mapfn)!(x.value!, i)) as int)
4469            }
4470            return result
4471        }
4472
4473        // NOTE (templin.konstantin): Create builtin array as buffer
4474        let temp = new Uint16Array(6)
4475        let index : FixedArray<int> = new int[1]
4476        index[0] = 0
4477
4478        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
4479            if (index[0] + 1 > temp.lengthInt) {
4480                // NOTE (templin.konstantin): Progressive reallocation
4481                const curLength = (temp.buffer as Buffer).getByteLength()
4482                const tb = new ArrayBuffer(curLength * 2)
4483                for (let i = 0; i < curLength; ++i) {
4484                    tb.set(i, (temp.buffer as Buffer).at(i))
4485                }
4486                temp = new Uint16Array(tb)
4487            }
4488            temp.setUnsafeClamp(index[0], temp.zeroIfInfinity((mapfn)!(x, index[0])) as int)
4489            index[0]++
4490        })
4491
4492        return new Uint16Array(temp.buffer, 0, index[0])
4493    }
4494
4495    /**
4496     * Creates an array from an array-like or iterable object.
4497     *
4498     * @param arrayLike An array-like or iterable object to convert to an array.
4499     *
4500     * @param mapfn A mapping function to call on every element of the array.
4501     *
4502     * @returns new Uint16Array
4503     */
4504    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint16Array {
4505        let res = new Uint16Array(arrayLike.length)
4506        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
4507        const idx : FixedArray<int> = new int[1]
4508        idx[0] = 0
4509        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
4510            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as int)
4511            idx[0] += 1
4512        })
4513        return res
4514    }
4515
4516    /**
4517     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
4518     *
4519     * @param searchElement The element to search for
4520     *
4521     * @param fromIndex The position in this array at which to begin searching for searchElement
4522     *
4523     * @returns true if searchElement is in Uint16Array, false otherwise
4524     */
4525    public includes(searchElement: number, fromIndex?: number): boolean {
4526        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
4527    }
4528
4529    /**
4530     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
4531     *
4532     * @param searchElement The element to search for
4533     *
4534     * @param fromIndex The position in this array at which to begin searching for searchElement
4535     *
4536     * @returns true if searchElement is in Uint16Array, false otherwise
4537     */
4538    public includes(searchElement: int, fromIndex: int): boolean {
4539        return this.indexOf(searchElement as int, fromIndex) != -1
4540    }
4541
4542    /**
4543     * Determines whether Uint16Array includes a certain element, returning true or false as appropriate
4544     *
4545     * @param searchElement The element to search for
4546     *
4547     * @param fromIndex The position in this array at which to begin searching for searchElement
4548     *
4549     * @returns true if searchElement is in Uint16Array, false otherwise
4550     */
4551    public includes(searchElement: int): boolean {
4552        return this.indexOf(searchElement as int, 0) != -1
4553    }
4554
4555    /**
4556     * Returns the index of the first occurrence of a value in Uint16Array.
4557     *
4558     * @param searchElement The value to locate in the array.
4559     *
4560     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4561     *  search starts at index 0.
4562     *
4563     * @returns index of element if it presents, -1 otherwise
4564     */
4565    public indexOf(searchElement: number, fromIndex?: number): number {
4566        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
4567    }
4568
4569    /**
4570     * Returns the index of the first occurrence of a value in Uint16Array.
4571     *
4572     * @param searchElement The value to locate in the array.
4573     *
4574     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4575     *  search starts at index 0.
4576     *
4577     * @returns index of element if it presents, -1 otherwise
4578     */
4579    public indexOf(searchElement: number, fromIndex: int): number {
4580            return this.indexOfImpl(searchElement, fromIndex)
4581    }
4582
4583    /**
4584     * Returns the index of the first occurrence of a value in Uint16Array.
4585     *
4586     * @param searchElement The value to locate in the array.
4587     *
4588     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4589     *  search starts at index 0.
4590     *
4591     * @returns index of element if it presents, -1 otherwise
4592     */
4593    public indexOf(searchElement: int, fromIndex: int): number {
4594        return this.indexOfImpl(searchElement as long, fromIndex)
4595    }
4596
4597    /**
4598     * Returns the index of the first occurrence of a value in Array.
4599     *
4600     * @param searchElement The value to locate in the array.
4601     *
4602     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4603     *  search starts at index 0.
4604     *
4605     * @returns index of element if it presents, -1 otherwise
4606     */
4607    private final native indexOfImpl(searchElement: number, fromIndex: int): number
4608
4609    /**
4610     * Returns the index of the first occurrence of a value in Array.
4611     *
4612     * @param searchElement The value to locate in the array.
4613     *
4614     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4615     *  search starts at index 0.
4616     *
4617     * @returns index of element if it presents, -1 otherwise
4618     */
4619    private final native indexOfImpl(searchElement: long, fromIndex: int): number
4620
4621    /**
4622     * Returns the index of the first occurrence of a value in Uint16Array.
4623     *
4624     * @param searchElement The value to locate in the array.
4625     *
4626     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4627     *  search starts at index 0.
4628     *
4629     * @returns index of element if it presents, -1 otherwise
4630     */
4631    public indexOf(searchElement: int): number {
4632        return this.indexOf(searchElement, 0)
4633    }
4634
4635
4636    /**
4637     * Converts all elements of an array to strings and joins them using the specified separator.
4638     *
4639     * @param separator - separates one element of an array from the next in the resulting String.
4640     *
4641     * @returns joined representation
4642     */
4643    private final native joinInternal(separator: String): string;
4644
4645    /**
4646     * Adds all the elements of an array separated by the specified separator string
4647     *
4648     * @param separator A string used to separate one element of an array from the next in the
4649     * resulting String. If omitted, the array elements are separated with a comma
4650     *
4651     * @returns joined representation
4652     */
4653    public join(separator?: String): string {
4654        if (separator == undefined) {
4655            return this.joinInternal(",")
4656        }
4657        return this.joinInternal(separator)
4658    }
4659
4660    /**
4661     * Returns an list of keys in Uint16Array
4662     *
4663     * @returns iterator over keys
4664     */
4665    public keys(): IterableIterator<number> {
4666        return new Uint16ArrayIteratorKeys(this)
4667    }
4668
4669    /**
4670     * Returns the index of the last occurrence of a value in Uint16Array.
4671     *
4672     * @param searchElement The value to locate in the array.
4673     *
4674     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
4675     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
4676     *
4677     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
4678     */
4679    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
4680        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
4681    }
4682
4683    /**
4684     * Returns the index of the last occurrence of a value in Uint16Array.
4685     *
4686     * @param searchElement The value to locate in the array.
4687     *
4688     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
4689     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
4690     *
4691     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
4692     */
4693    public lastIndexOf(searchElement: number): number {
4694        return this.lastIndexOf(searchElement, this.lengthInt - 1)
4695    }
4696
4697    /**
4698     * Returns the index of the last occurrence of a value in Uint16Array.
4699     *
4700     * @param searchElement The value to locate in the array.
4701     *
4702     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
4703     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
4704     *
4705     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
4706     */
4707    public lastIndexOf(searchElement: number, fromIndex: int): number {
4708            return this.lastIndexOfImpl(searchElement, fromIndex)
4709    }
4710
4711    /**
4712     * Returns the index of the last occurrence of a value in Uint16Array.
4713     *
4714     * @param searchElement The value to locate in the array.
4715     *
4716     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
4717     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
4718     *
4719     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
4720     */
4721    public lastIndexOf(searchElement: int, fromIndex: int): number {
4722        return this.lastIndexOfImpl(searchElement as long, fromIndex)
4723    }
4724
4725    /**
4726     * Returns the index of the first occurrence of a value in Array.
4727     *
4728     * @param searchElement The value to locate in the array.
4729     *
4730     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4731     *  search starts at index 0.
4732     *
4733     * @returns index of element if it presents, -1 otherwise
4734     */
4735    private final native lastIndexOfImpl(searchElement: number, fromIndex: int): number
4736
4737    /**
4738     * Returns the index of the first occurrence of a value in Array.
4739     *
4740     * @param searchElement The value to locate in the array.
4741     *
4742     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
4743     *  search starts at index 0.
4744     *
4745     * @returns index of element if it presents, -1 otherwise
4746     */
4747    private final native lastIndexOfImpl(searchElement: long, fromIndex: int): number
4748
4749    /**
4750     * Returns the index of the last occurrence of a value in Uint16Array.
4751     *
4752     * @param searchElement The value to locate in the array.
4753     *
4754     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
4755     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
4756     *
4757     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
4758     */
4759    public lastIndexOf(searchElement: int): number {
4760        return this.lastIndexOf(searchElement, this.lengthInt - 1)
4761    }
4762
4763   /**
4764    * Creates a new Uint16Array using initializer
4765    *
4766    * @param data initializer
4767    *
4768    * @returns a new Uint16Array from data
4769    */
4770    public of(...data: FixedArray<number>): Uint16Array {
4771        throw new Error("Uint16Array.of: not implemented")
4772    }
4773
4774    /**
4775     * Creates a new Uint16Array using reversed data from the current one
4776     *
4777     * @returns a new Uint16Array using reversed data from the current one
4778     */
4779    public native reverse(): Uint16Array
4780
4781    /**
4782     * Creates a slice of current Uint16Array using range [begin, end)
4783     *
4784     * @param begin start index to be taken into slice
4785     *
4786     * @param end last index to be taken into slice
4787     *
4788     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
4789     *
4790     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
4791     */
4792    public slice(begin?: number, end?: number): Uint16Array {
4793        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
4794    }
4795
4796    /**
4797     * Creates a slice of current Uint16Array using range [begin, end)
4798     *
4799     * @param begin start index to be taken into slice
4800     *
4801     * @param end last index to be taken into slice
4802     *
4803     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
4804     *
4805     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
4806     */
4807    public slice(begin: number, end: number): Uint16Array {
4808        return this.slice(begin as int, end as int)
4809    }
4810
4811    /**
4812     * Creates a slice of current Uint16Array using range [begin, end)
4813     *
4814     * @param begin start index to be taken into slice
4815     *
4816     * @param end last index to be taken into slice
4817     *
4818     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
4819     *
4820     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
4821     */
4822    public slice(begin: number, end: int): Uint16Array {
4823        return this.slice(begin as int, end as int)
4824    }
4825
4826    /**
4827     * Creates a slice of current Uint16Array using range [begin, end)
4828     *
4829     * @param begin start index to be taken into slice
4830     *
4831     * @param end last index to be taken into slice
4832     *
4833     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
4834     *
4835     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
4836     */
4837    public slice(begin: int, end: number): Uint16Array {
4838        return this.slice(begin as int, end as int)
4839    }
4840
4841    /**
4842     * Creates a slice of current Uint16Array using range [begin, end)
4843     *
4844     * @param begin start index to be taken into slice
4845     *
4846     * @param end last index to be taken into slice
4847     *
4848     * @returns a new Uint16Array with elements of current Uint16Array[begin;end) where end index is excluded
4849     *
4850     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
4851     */
4852    public slice(begin: int, end: int): Uint16Array {
4853        const len: int = this.lengthInt
4854        const relStart = normalizeIndex(begin, len)
4855        const relEnd = normalizeIndex(end, len)
4856        let count = relEnd - relStart
4857        if (count < 0) {
4858            count = 0
4859        }
4860        let buf = this.buffer.slice(relStart * Uint16Array.BYTES_PER_ELEMENT as int, relEnd * Uint16Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
4861        return new Uint16Array(buf)
4862    }
4863
4864    /**
4865     * Creates a slice of current Uint16Array using range [begin, this.lengthInt).
4866     *
4867     * @param begin start index to be taken into slice
4868     *
4869     * @returns a new Uint16Array with elements of current Uint16Array[begin, this.lengthInt)
4870     */
4871    public slice(begin: number): Uint16Array {
4872        return this.slice(begin as int)
4873    }
4874
4875    /**
4876     * Creates a slice of current Uint16Array using range [begin, this.lengthInt).
4877     *
4878     * @param begin start index to be taken into slice
4879     *
4880     * @returns a new Uint16Array with elements of current Uint16Array[begin, this.lengthInt)
4881     */
4882    public slice(begin: int): Uint16Array {
4883        return this.slice(begin, this.lengthInt)
4884    }
4885
4886    /**
4887     * Sorts in-place by numeric value in ascending order.
4888     *
4889     * @returns sorted Array
4890     */
4891    public native sort(): this;
4892
4893    /**
4894     * Sorts in-place
4895     *
4896     * @param compareFn comparator _  used to determine the order of the elements.
4897     * compareFn returns a negative value if first argument is less than second argument,
4898     * zero if they're equal and a positive value otherwise.
4899     *
4900     * @returns sorted Uint16Array
4901     */
4902    public sort(compareFn?: (a: number, b: number) => number): this {
4903        if (compareFn == undefined) {
4904            this.sort()
4905            return this
4906        }
4907        let arr: FixedArray<int> = new int[this.lengthInt]
4908        for (let i = 0; i < this.lengthInt; ++i) {
4909            arr[i] = this.getUnsafe(i)
4910        }
4911
4912        let cmp = (l: int, r: int): number => {
4913            const result = compareFn!(l as number, r as number)
4914            return result
4915        }
4916        const MAX_SHORT_LENGTH = 24
4917        if (arr.length > MAX_SHORT_LENGTH) {
4918            arr = mergeSort(arr, cmp)
4919        } else {
4920            sort(arr, cmp)
4921        }
4922        for (let i = 0; i < arr.length; ++i) {
4923            this.setUnsafe(i, arr[i])
4924        }
4925        return this
4926    }
4927
4928    /**
4929     * Creates a Uint16Array with the same underlying Buffer
4930     *
4931     * @param begin start index, inclusive
4932     *
4933     * @param end last index, exclusive
4934     *
4935     * @returns new Uint16Array with the same underlying Buffer
4936     */
4937    public subarray(begin?: number, end?: number): Uint16Array {
4938        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
4939    }
4940
4941    /**
4942     * Creates a Uint16Array with the same underlying Buffer
4943     *
4944     * @param begin start index, inclusive
4945     *
4946     * @param end last index, exclusive
4947     *
4948     * @returns new Uint16Array with the same underlying Buffer
4949     */
4950    public subarray(begin: number, end: int): Uint16Array {
4951        return this.subarray(begin as int, end as int)
4952    }
4953
4954    /**
4955     * Creates a Uint16Array with the same underlying Buffer
4956     *
4957     * @param begin start index, inclusive
4958     *
4959     * @param end last index, exclusive
4960     *
4961     * @returns new Uint16Array with the same underlying Buffer
4962     */
4963    public subarray(begin: int, end: number): Uint16Array {
4964        return this.subarray(begin as int, end as int)
4965    }
4966
4967    /**
4968     * Creates a Uint16Array with the same underlying Buffer
4969     *
4970     * @param begin start index, inclusive
4971     *
4972     * @param end last index, exclusive
4973     *
4974     * @returns new Uint16Array with the same underlying Buffer
4975     */
4976    public subarray(begin: int, end: int | undefined = this.lengthInt): Uint16Array {
4977        const len: int = this.lengthInt
4978        const relStart = normalizeIndex(begin, len)
4979        const relEnd = normalizeIndex(end ?? this.lengthInt, len)
4980        let count = relEnd - relStart
4981        if (count < 0) {
4982            count = 0
4983        }
4984        return new Uint16Array(this.buffer, relStart * Uint16Array.BYTES_PER_ELEMENT as int, count)
4985    }
4986
4987    /**
4988     * Converts Uint16Array to a string with respect to locale
4989     *
4990     * @param locales
4991     *
4992     * @param options
4993     *
4994     * @returns string representation
4995     */
4996    public toLocaleString(locales: Object, options: Object): string {
4997        throw new Error("Uint16Array.toLocaleString: not implemented")
4998    }
4999
5000    /**
5001     * Converts Uint16Array to a string with respect to locale
5002     *
5003     * @param locales
5004     *
5005     * @returns string representation
5006     */
5007    public toLocaleString(locales: Object): string {
5008        return this.toLocaleString(new Object(), new Object())
5009    }
5010
5011    /**
5012     * Converts Uint16Array to a string with respect to locale
5013     *
5014     * @returns string representation
5015     */
5016    public toLocaleString(): string {
5017        let res: StringBuilder = new StringBuilder("")
5018        for (let i = 0; i < this.lengthInt - 1; ++i) {
5019            res.append((this.getUnsafe(i) as Number).toLocaleString())
5020            res.append(",")
5021        }
5022        if (this.lengthInt > 0) {
5023            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
5024        }
5025        return res.toString()
5026    }
5027
5028    /**
5029     * Creates a reversed copy
5030     *
5031     * @returns a reversed copy
5032     */
5033    public final native toReversed(): Uint16Array
5034
5035    /**
5036     * Creates a sorted copy
5037     *
5038     * @returns a sorted copy
5039     */
5040    public toSorted(): Uint16Array {
5041        return new Uint16Array(this).sort()
5042    }
5043
5044    /**
5045     * Returns a string representation of the Uint16Array
5046     *
5047     * @returns a string representation of the Uint16Array
5048     */
5049    public override toString(): string {
5050        return this.join(",")
5051    }
5052
5053    /**
5054     * Returns array values iterator
5055     *
5056     * @returns an iterator
5057     */
5058    public values(): IterableIterator<Number> {
5059         return new Uint16ArrayIterator(this)
5060    }
5061
5062    /**
5063     * Creates a copy with replaced value on index
5064     *
5065     * @param index
5066     *
5067     * @param value
5068     *
5069     * @returns an Uint16Array with replaced value on index
5070     */
5071    public with(index: number, value: number): Uint16Array {
5072        return this.with(index as int, value as int)
5073    }
5074
5075    /**
5076     * Creates a copy with replaced value on index
5077     *
5078     * @param index
5079     *
5080     * @param value
5081     *
5082     * @returns an Uint16Array with replaced value on index
5083     */
5084    public with(index: int, value: int): Uint16Array {
5085        let res = new Uint16Array(this)
5086        res.setUnsafeClamp(index, value)
5087        return res
5088    }
5089
5090    /// === with element lambda functions ===
5091
5092    /**
5093     * Determines whether the specified callback function returns true for any element of an array.
5094     *
5095     * @param predicate A function that accepts three arguments.
5096     * The some method calls the predicate function for each element in the array
5097     * until the predicate returns a true or until the end of the array.
5098     *
5099     * @returns false unless predicate function returns true for an array element,
5100     * in which case true is immediately returned.
5101     */
5102    public some(predicate: (element: number, index: number, array: Uint16Array) => boolean): boolean {
5103        for (let i = 0; i < this.lengthInt; i++) {
5104            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
5105                return true
5106            }
5107        }
5108        return false
5109    }
5110
5111    /**
5112     * Calls the specified callback function for all the elements in an array.
5113     * The return value of the callback function is the accumulated result,
5114     * and is provided as an argument in the next call to the callback function.
5115     *
5116     * @param callbackfn A function that accepts four arguments.
5117     * The reduce method calls the callbackfn function one time for each element in the array.
5118     *
5119     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
5120     * The first call to the callbackfn function provides this value as an argument.
5121     *
5122     * @returns The value that results from running the callback function to completion over the entire typed array.
5123     */
5124    public reduce<U = number>(
5125                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U,
5126                initialValue: U): U {
5127        let accumulatedValue = initialValue
5128        for (let i = 0; i < this.lengthInt; i++) {
5129            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
5130        }
5131        return accumulatedValue
5132    }
5133
5134    /**
5135     * Calls the specified callback function for all the elements in an array.
5136     * The return value of the callback function is the accumulated result,
5137     * and is provided as an argument in the next call to the callback function.
5138     *
5139     * @param callbackfn A function that accepts four arguments.
5140     * The reduce method calls the callbackfn function one time for each element in the array.
5141     * The first call to the callbackfn function provides array first element value as an argument
5142     *
5143     * @returns The value that results from running the callback function to completion over the entire typed array.
5144     * calling reduce method on an empty array without an initial value creates a TypeError
5145     */
5146    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number {
5147        if (this.lengthInt == 0) {
5148            throw new TypeError("Reduce of empty array with no initial value")
5149        }
5150
5151        let accumulatedValue = this.$_get(0) as number
5152        for (let i = 1; i < this.lengthInt; i++) {
5153            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
5154        }
5155        return accumulatedValue
5156    }
5157
5158    /**
5159     * Calls the specified callback function for all the elements in an array, in descending order.
5160     * The return value of the callback function is the accumulated result,
5161     * and is provided as an argument in the next call to the callback function.
5162     *
5163     * @param callbackfn A function that accepts four arguments.
5164     * The reduceRight method calls the callbackfn function one time for each element in the array.
5165     *
5166     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
5167     * The first call to the callbackfn function provides this value as an argument.
5168     *
5169     * @returns The value that results from running the callback function to completion over the entire typed array.
5170     */
5171    public reduceRight<U = number>(
5172                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U,
5173                initialValue: U): U {
5174        let accumulatedValue = initialValue
5175        for (let i = this.lengthInt - 1; i >= 0; i--) {
5176            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
5177        }
5178        return accumulatedValue
5179    }
5180
5181    /**
5182     * Calls the specified callback function for all the elements in an array, in descending order.
5183     * The return value of the callback function is the accumulated result,
5184     * and is provided as an argument in the next call to the callback function.
5185     *
5186     * @param callbackfn A function that accepts four arguments.
5187     * The reduceRight method calls the callbackfn function one time for each element in the array.
5188     * The first call to the callbackfn function provides array last element value as an argument
5189     *
5190     * @returns The value that results from running the callback function to completion over the entire typed array.
5191     * calling reduceRight method on an empty array without an initial value creates a TypeError
5192     */
5193    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number {
5194        if (this.lengthInt == 0) {
5195            throw new TypeError("Reduce of empty array with no initial value")
5196        }
5197
5198        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
5199        for (let i = this.lengthInt - 2; i >= 0; i--) {
5200            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
5201        }
5202        return accumulatedValue
5203    }
5204
5205    /**
5206     * Creates a new Uint16Array using fn(arr[i]) over all elements of current Uint16Array.
5207     *
5208     * @param fn a function to apply for each element of current Uint16Array
5209     *
5210     * @returns a new Uint16Array where for each element from current Uint16Array fn was applied
5211     */
5212    public map(fn: (val: number, index: number, array: Uint16Array) => number): Uint16Array {
5213        let resBuf = new ArrayBuffer(this.lengthInt * Uint16Array.BYTES_PER_ELEMENT as int)
5214        let res = new Uint16Array(resBuf)
5215        for (let i = 0; i < this.lengthInt; i++) {
5216            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
5217            res.setUnsafeClamp(i, fnRes as int)
5218        }
5219        return res
5220    }
5221
5222    /**
5223     * Determines whether the specified callback function returns true for all elements of an array.
5224     *
5225     * @param predicate A function that accepts three arguments.
5226     * The every method calls the predicate function for each element in the array until the predicate returns a false,
5227     * or until the end of the array.
5228     *
5229     * @returns true unless predicate function returns a false for an array element,
5230     * in which case false is immediately returned.
5231     */
5232    public every(predicate: (element: number, index: number, array: Uint16Array) => boolean): boolean {
5233        for (let i = 0; i < this.lengthInt; i++) {
5234            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
5235                return false
5236            }
5237        }
5238        return true
5239    }
5240
5241    /**
5242     * Creates a new Uint16Array from current Uint16Array based on a condition fn.
5243     *
5244     * @param fn the condition to apply for each element
5245     *
5246     * @returns a new Uint16Array with elements from current Uint16Array that satisfy condition fn
5247     */
5248    public filter(fn: (val: number, index: number, array: Uint16Array) => boolean): Uint16Array {
5249        let markers : FixedArray<boolean> = new boolean[this.lengthInt]
5250        let resLen = 0
5251        for (let i = 0; i < this.lengthInt; i++) {
5252            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
5253            if (markers[i]) {
5254                ++resLen
5255            }
5256        }
5257        let res = new Uint16Array(resLen)
5258        for (let i = 0, j = 0; i < this.lengthInt; i++) {
5259            if (markers[i]) {
5260                res.setUnsafe(j, this.getUnsafe(i))
5261                ++j
5262            }
5263        }
5264        return res
5265    }
5266
5267    /**
5268     * Returns the value of the first element in the array where predicate is true, and undefined
5269     * otherwise
5270     *
5271     * @param predicate find calls predicate once for each element of the array, in ascending
5272     * order, until it finds one where predicate returns true. If such an element is found, find
5273     * immediately returns that element value. Otherwise, find returns undefined
5274     *
5275     * @returns number | undefined
5276     */
5277    public find(predicate: (value: number, index: number, array: Uint16Array) => boolean): number | undefined {
5278        for (let i = 0; i < this.lengthInt; i++) {
5279            let val = this.getUnsafe(i) as number
5280            if (predicate(val, i as number, this)) {
5281                return val
5282            }
5283        }
5284        return undefined
5285    }
5286
5287    /**
5288     * Returns the index of the first element in the array where predicate is true, and -1
5289     * otherwise
5290     *
5291     * @param predicate find calls predicate once for each element of the array, in ascending
5292     * order, until it finds one where predicate returns true. If such an element is found,
5293     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
5294     *
5295     * @returns number
5296     */
5297    public findIndex(predicate: (value: number, index: number, obj: Uint16Array) => boolean): number {
5298        for (let i = 0; i < this.lengthInt; i++) {
5299            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
5300                return i as number
5301            }
5302        }
5303        return -1 as number
5304    }
5305
5306    /**
5307     * Finds the last element in the Uint16Array that satisfies the condition
5308     *
5309     * @param fn condition
5310     *
5311     * @returns the last element that satisfies fn
5312     */
5313    public findLast(fn: (val: number, index: number, array: Uint16Array) => boolean): number {
5314        for (let i = this.lengthInt - 1; i >= 0; i--) {
5315            let val = this.getUnsafe(i) as number
5316            if (fn(val, i as number, this)) {
5317                return val
5318            }
5319        }
5320        throw new Error("Uint16Array.findLast: not implemented if an element was not found")
5321    }
5322
5323    /**
5324     * Finds an index of the last element in the Uint16Array that satisfies the condition
5325     *
5326     * @param fn condition
5327     *
5328     * @returns the index of the last element that satisfies fn, -1 otherwise
5329     */
5330    public findLastIndex(fn: (val: number, index: number, array: Uint16Array) => boolean): number {
5331        for (let i = this.lengthInt - 1; i >= 0; i--) {
5332            if (fn(this.getUnsafe(i) as number, i as number, this)) {
5333                return i as number
5334            }
5335        }
5336        return -1 as number
5337    }
5338
5339    /**
5340     * Performs the specified action for each element in Uint16Array
5341     *
5342     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
5343     * callbackfn function one time for each element in the array.
5344     *
5345     * @returns None
5346     */
5347    public forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void): void {
5348        for (let i = 0; i < this.lengthInt; i++) {
5349            callbackfn(this.getUnsafe(i) as number, i as number, this)
5350        }
5351    }
5352
5353    /**
5354     * Returns the object itself
5355     *
5356     * @returns Uint16Array
5357     */
5358    public valueOf(): Uint16Array {
5359        return this
5360    }
5361
5362    /** Byte offset within the underlying Buffer */
5363    public get byteOffset(): number {
5364        return this.byteOffsetInt
5365    }
5366
5367    /** Number of bytes used */
5368    public get byteLength(): number {
5369        return this.byteLengthInt
5370    }
5371
5372    /** Number of int stored in Uint16Array */
5373    public get length(): number {
5374        return this.lengthInt
5375    }
5376
5377    /** String \"Uint16Array\" */
5378    public readonly name = "Uint16Array"
5379
5380    private static clamp(val: int): int {
5381        return val
5382    }
5383
5384    internal setUnsafeClamp(insertPos: int, val: int): void {
5385        this.setUnsafe(insertPos, val)
5386    }
5387
5388    private final native getUnsafe(index: int): int
5389
5390    internal setUnsafe(index: int, val: int): void {
5391        index = index * Uint16Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
5392        let res: int = 0
5393        if (IS_LITTLE_ENDIAN) {
5394            for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
5395                this.buffer.set(index + i, (val & 0xff) as byte)
5396                val = val >> 8
5397            }
5398        } else {
5399            for (let i = 0; i < Uint16Array.BYTES_PER_ELEMENT as int; i++) {
5400                this.buffer.set(index + 1 - i, (val & 0xff) as byte)
5401                val = val >> 8
5402            }
5403        }
5404    }
5405}
5406
5407
5408class Uint32ArrayIteratorKeys implements IterableIterator<number> {
5409    private length: int = 0
5410    private idx: int = 0
5411
5412    constructor(parent: Uint32Array) {
5413        this.length = parent.length as int
5414    }
5415
5416    public override $_iterator(): IterableIterator<Number> {
5417        return this
5418    }
5419
5420    override next(): IteratorResult<number> {
5421        if (this.idx < 0 || this.idx >= this.length) {
5422            return new IteratorResult<number>()
5423        }
5424        return new IteratorResult<number>(false, this.idx++ as number)
5425    }
5426}
5427
5428class Uint32ArrayIterator implements IterableIterator<Number> {
5429    private parent: Uint32Array
5430    private idx: int = 0
5431
5432    constructor(parent: Uint32Array) {
5433        this.parent = parent
5434    }
5435
5436    public override $_iterator(): IterableIterator<Number> {
5437        return this
5438    }
5439
5440    override next(): IteratorResult<Number> {
5441        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
5442            return new IteratorResult<Number>()
5443        }
5444        return new IteratorResult<Number>(false, new Number(this.parent[this.idx++]))
5445    }
5446}
5447
5448class Uint32ArrayIteratorEntries implements IterableIterator<[Number, Number]> {
5449    private parent: Uint32Array
5450    private idx: int = 0
5451
5452    constructor(parent: Uint32Array) {
5453        this.parent = parent
5454    }
5455
5456    public override $_iterator(): IterableIterator<[Number, Number]> {
5457        return this
5458    }
5459
5460    override next(): IteratorResult<[Number, Number]> {
5461        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
5462            return new IteratorResult<[Number, Number]>()
5463        }
5464        return new IteratorResult<[Number, Number]>(
5465            false,
5466            [new Number(this.idx), new Number(this.parent[this.idx++])]
5467        )
5468    }
5469}
5470
5471/**
5472 * JS Uint32Array API-compatible class
5473 */
5474export final class Uint32Array implements Iterable<Number>, ArrayLike<Number> {
5475    public static readonly BYTES_PER_ELEMENT: number = 4
5476    public readonly BYTES_PER_ELEMENT: number = Uint32Array.BYTES_PER_ELEMENT
5477
5478    /** Underlying Buffer */
5479    public readonly buffer: ArrayBuffer
5480
5481    internal readonly byteOffsetInt: int
5482    internal readonly byteLengthInt: int
5483    internal readonly lengthInt: int
5484
5485    /**
5486     * Creates an empty Uint32Array.
5487     */
5488    public constructor() {
5489        this(0 as int)
5490    }
5491
5492    /**
5493     * Creates an Uint32Array with respect to data accessed via Iterable<Number> interface
5494     */
5495    public constructor(elements: Iterable<Number>) {
5496        const items: Object = elements as Object
5497        if (items instanceof ArrayLike) {
5498            const arr = Types.identity_cast<Number>(items as ArrayLike<Number>)
5499            this.byteLengthInt = arr.length as int * Uint32Array.BYTES_PER_ELEMENT as int
5500            this.lengthInt = arr.length as int
5501            this.buffer = new ArrayBuffer(this.byteLengthInt)
5502            this.byteOffsetInt = 0
5503            for (let i: int = 0; i < this.lengthInt; ++i) {
5504                this.setUnsafeClamp(i, this.zeroIfInfinity(arr.$_get(i)) as long)
5505            }
5506        } else {
5507            let x = Uint32Array.from(elements)
5508            this.byteLengthInt = x.byteLengthInt
5509            this.lengthInt = x.lengthInt
5510            this.buffer = x.buffer
5511            this.byteOffsetInt = x.byteOffsetInt
5512        }
5513    }
5514
5515    /**
5516     * Creates an Uint32Array with respect to data, byteOffset and length.
5517     *
5518     * @param buf data initializer
5519     *
5520     * @param byteOffset byte offset from begin of the buf
5521     *
5522     * @param length size of elements of type long in newly created Uint32Array
5523     */
5524    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined, length: Number | undefined) {
5525        let intByteOffset: int = 0
5526        if (byteOffset != undefined) {
5527            intByteOffset = byteOffset.toInt()
5528            if (intByteOffset < 0) {
5529                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
5530            }
5531        }
5532        let intByteLength: int = buf.getByteLength() - intByteOffset
5533        if (intByteLength < 0) {
5534            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
5535        }
5536
5537        if (intByteLength % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
5538            throw new RangeError("ArrayBuffer.byteLength should be multiple of 4 as Uint32Array.BYTES_PER_ELEMENT")
5539        }
5540        if (intByteOffset % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
5541            throw new RangeError("byteOffset should be multiple of 4 as Uint32Array.BYTES_PER_ELEMENT")
5542        }
5543
5544        let intLength: int
5545        if (length != undefined) {
5546            intLength = length.toInt()
5547            if (intLength > intByteLength / Uint32Array.BYTES_PER_ELEMENT as int) {
5548                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
5549            }
5550        } else {
5551            intLength = intByteLength / Uint32Array.BYTES_PER_ELEMENT as int
5552        }
5553        if (intLength < 0) {
5554            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
5555        }
5556        if (intLength < intByteLength / Uint32Array.BYTES_PER_ELEMENT as int) {
5557            intByteLength = intLength * Uint32Array.BYTES_PER_ELEMENT as int
5558        }
5559        this.byteLengthInt = intByteLength
5560        this.byteOffsetInt = intByteOffset
5561        this.lengthInt = intLength
5562        this.buffer = buf
5563    }
5564
5565    /**
5566     * Creates an Uint32Array with respect to data, byteOffset and length.
5567     *
5568     * @param buf data initializer
5569     *
5570     * @param byteOffset byte offset from begin of the buf
5571     */
5572    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined) {
5573        this(buf, byteOffset, undefined)
5574    }
5575
5576    /**
5577     * Creates an Uint32Array with respect to data, byteOffset and length.
5578     *
5579     * @param buf data initializer
5580     *
5581     * @param byteOffset byte offset from begin of the buf
5582     *
5583     * @param length size of elements of type long in newly created Uint32Array
5584     */
5585    public constructor(buf: ArrayBuffer, byteOffset: number, length: number) {
5586        this(buf, new Number(byteOffset), new Number(length))
5587    }
5588
5589    /**
5590     * Creates an Uint32Array with respect to buf and byteOffset.
5591     *
5592     * @param buf data initializer
5593     *
5594     * @param byteOffset byte offset from begin of the buf
5595     */
5596    public constructor(buf: ArrayBuffer, byteOffset: number) {
5597        this(buf, new Number(byteOffset), undefined)
5598    }
5599
5600    /**
5601     * Creates an Uint32Array with respect to data, byteOffset and length.
5602     *
5603     * @param buf data initializer
5604     *
5605     * @param byteOffset byte offset from begin of the buf
5606     *
5607     * @param length size of elements of type long in newly created Uint32Array
5608     */
5609    public constructor(buf: ArrayBuffer, byteOffset: int, length: int) {
5610        this(buf, new Number(byteOffset), new Number(length))
5611    }
5612
5613    /**
5614     * Creates an Uint32Array with respect to buf and byteOffset.
5615     *
5616     * @param buf data initializer
5617     *
5618     * @param byteOffset byte offset from begin of the buf
5619     */
5620    public constructor(buf: ArrayBuffer, byteOffset: int) {
5621        this(buf, new Number(byteOffset), undefined)
5622    }
5623
5624    /**
5625     * Creates an Uint32Array with respect to buf.
5626     *
5627     * @param buf data initializer
5628     */
5629    public constructor(buf: ArrayLike<Number> | ArrayBuffer) {
5630        if (buf instanceof ArrayBuffer) {
5631            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
5632            if (this.byteLengthInt % Uint32Array.BYTES_PER_ELEMENT as int != 0) {
5633               throw new RangeError("ArrayBuffer.byteLength should be multiple of long as Uint32Array.BYTES_PER_ELEMENT")
5634            }
5635            this.lengthInt = this.byteLengthInt / Uint32Array.BYTES_PER_ELEMENT as int
5636            this.buffer = buf as ArrayBuffer
5637            this.byteOffsetInt = 0
5638        } else if (buf instanceof ArrayLike) {
5639            // NOTE (ikorobkov): dealing with this overload is tricky
5640            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.ets
5641            let arr = Array.from<Number>((buf as ArrayLike<Number>))
5642            this.byteLengthInt = arr.length as int * Uint32Array.BYTES_PER_ELEMENT as int
5643            this.lengthInt = arr.length as int
5644            this.buffer = new ArrayBuffer(this.byteLengthInt)
5645            this.byteOffsetInt = 0
5646            for (let i: int = 0; i < this.lengthInt; ++i) {
5647                this.setUnsafe(i, arr.$_get(i).toLong())
5648            }
5649        } else {
5650            throw new Error("unexpected type of buf")
5651        }
5652    }
5653
5654    /**
5655     * Creates an Uint32Array with respect to length.
5656     *
5657     * @param length data initializer
5658     */
5659    public constructor(length: int) {
5660        this(length as number)
5661    }
5662
5663    /**
5664     * Creates an Uint32Array with respect to length.
5665     *
5666     * @param length data initializer
5667     */
5668    public constructor(length: number) {
5669        if (length < 0 || length > (Int.MAX_VALUE / Uint32Array.BYTES_PER_ELEMENT)) {
5670            throw new TypeError("Type Error: length " + length + " is outside the bounds of the buffer")
5671        }
5672        this.lengthInt = length as int
5673        this.byteLengthInt = this.lengthInt * Uint32Array.BYTES_PER_ELEMENT as int
5674        this.byteOffsetInt = 0
5675        this.buffer = new ArrayBuffer(this.byteLengthInt)
5676    }
5677
5678    /**
5679     * Creates a copy of Uint32Array.
5680     *
5681     * @param other data initializer
5682     */
5683    public constructor(other: Uint32Array) {
5684        this.buffer = other.buffer.slice(other.byteOffset as int, (other.byteOffset + other.byteLength) as int) as ArrayBuffer
5685        this.byteLengthInt = other.byteLength as int
5686        this.lengthInt = other.length as int
5687        this.byteOffsetInt = 0
5688    }
5689
5690    /**
5691     * Creates an Uint32Array from FixedArray<number>
5692     */
5693    public constructor(numbers: FixedArray<number>) {
5694        this(numbers.length)
5695        for (let i: int = 0; i < this.lengthInt; ++i) {
5696            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as long)
5697        }
5698    }
5699
5700    /**
5701     * Creates an Uint32Array from FixedArray<int>
5702     */
5703    public constructor(numbers: FixedArray<int>) {
5704        this(numbers.length)
5705        for (let i: int = 0; i < this.lengthInt; ++i) {
5706            this.setUnsafeClamp(i, this.zeroIfInfinity(numbers[i]) as long)
5707        }
5708    }
5709    internal zeroIfInfinity(val: number): number {
5710        if ((val == Infinity) || (val == -Infinity)) {
5711            return 0 as number
5712        }
5713        return val as number
5714    }
5715
5716    internal zeroIfInfinity(val: long): long {
5717        if ((val == Infinity) || (val == -Infinity)) {
5718            return 0 as long
5719        }
5720        return val
5721    }
5722
5723    /**
5724     * Iteratorable interface implementation
5725     *
5726     * @returns iterator over all elements
5727     */
5728    public override $_iterator(): IterableIterator<Number> {
5729         return this.values()
5730    }
5731
5732    /**
5733     * Returns an instance of primitive type at passed index.
5734     *
5735     * @param index index to look at
5736     *
5737     * @returns a primitive at index
5738     */
5739    public at(index: number): Number | undefined {
5740        return this.at(index as int)
5741    }
5742
5743    /**
5744     * Returns an instance of primitive type at passed index if index is correct.
5745     *
5746     * @param index index to look at
5747     *
5748     * @returns a primitive at index
5749     */
5750    public at(index: int): Number | undefined {
5751        let k: int
5752        if (index >= 0) {
5753            k = index
5754        } else {
5755            k = this.lengthInt + index
5756        }
5757        if (k < 0 || k >= this.lengthInt) {
5758            return undefined
5759        }
5760        return new Number(this.getUnsafe(k))
5761    }
5762
5763    /**
5764     * Returns an instance of number at passed index.
5765     *
5766     * @param index index to look at
5767     *
5768     * @returns a primitive at index
5769     */
5770    public override $_get(index: number): Number {
5771        return this.$_get(index as int) as Number
5772    }
5773
5774    /**
5775     * Returns an instance of number at passed index.
5776     *
5777     * @param index index to look at
5778     *
5779     * @returns a primitive at index
5780     */
5781    public native $_get(i: int): number
5782
5783    /**
5784     * Assigns val as element on index.
5785     *
5786     * @param val value to set
5787     *
5788     * @param index index to change
5789     */
5790    public $_set(index: number, val: number): void {
5791        this.$_set(index as int, val)
5792    }
5793
5794    /**
5795     * Assigns val as element on index.
5796     *
5797     * @param val value to set
5798     *
5799     * @param index index to change
5800     */
5801    public $_set(index: int, val: number): void {
5802        let v = this.zeroIfInfinity(val)
5803        this.$_set(index, v as long)
5804    }
5805
5806    /**
5807     * Assigns val as element on index.
5808     *
5809     * @param val value to set
5810     *
5811     * @param index index to change
5812     */
5813    public $_set(index: number, val: long): void {
5814        this.$_set(index as int, val)
5815    }
5816
5817    /**
5818     * Assigns val as element on index.
5819     *
5820     * @param val value to set
5821     *
5822     * @param index index to change
5823     */
5824    public native $_set(index: int, val: long): void
5825
5826    /**
5827     * Assigns val as element on index.
5828     *
5829     * @param val value to set
5830     *
5831     * @param index index to change
5832     */
5833    public $_set(index: number, val: int): void {
5834        this.$_set(index as int, val as int)
5835    }
5836
5837    /**
5838     * Assigns val as element on index.
5839     *
5840     * @param val value to set
5841     *
5842     * @param index index to change
5843     */
5844    public native $_set(index: int, val: int): void
5845
5846    /**
5847     * Makes a copy of internal elements to targetPos from startPos to endPos.
5848     *
5849     * @param target insert index to place copied elements
5850     *
5851     * @param start start index to begin copy from
5852     *
5853     * @param end last index to end copy from, excluded
5854     *
5855     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5856     */
5857    public copyWithin(target: number, start: number, end?: number): Uint32Array {
5858        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5859    }
5860
5861    /**
5862     * Makes a copy of internal elements to targetPos from startPos to endPos.
5863     *
5864     * @param target insert index to place copied elements
5865     *
5866     * @param start start index to begin copy from
5867     *
5868     * @param end last index to end copy from, excluded
5869     *
5870     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5871     */
5872    public copyWithin(target: int, start: number, end?: number): Uint32Array {
5873        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5874    }
5875
5876    /**
5877     * Makes a copy of internal elements to targetPos from startPos to endPos.
5878     *
5879     * @param target insert index to place copied elements
5880     *
5881     * @param start start index to begin copy from
5882     *
5883     * @param end last index to end copy from, excluded
5884     *
5885     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5886     */
5887    public copyWithin(target: number, start: int, end?: number): Uint32Array {
5888        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5889    }
5890
5891    /**
5892     * Makes a copy of internal elements to targetPos from startPos to endPos.
5893     *
5894     * @param target insert index to place copied elements
5895     *
5896     * @param start start index to begin copy from
5897     *
5898     * @param end last index to end copy from, excluded
5899     *
5900     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5901     */
5902    public copyWithin(target: int, start: int, end?: number): Uint32Array {
5903        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
5904    }
5905
5906    /**
5907     * Makes a copy of internal elements to targetPos from startPos to endPos.
5908     *
5909     * @param insert insert index to place copied elements
5910     *
5911     * @param start start index to begin copy from
5912     *
5913     * @param end last index to end copy from, excluded
5914     *
5915     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
5916     */
5917    public native copyWithin(target: int, start: int, end: int): Uint32Array
5918
5919    /**
5920     * Makes a copy of internal elements to targetPos from begin to end of Uint32Array.
5921     *
5922     * @param target insert index to place copied elements
5923     *
5924     * See rules of parameters normalization:
5925     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
5926     */
5927    public copyWithin(target: number): Uint32Array {
5928        return this.copyWithin(target as int)
5929    }
5930
5931    /**
5932     * Makes a copy of internal elements to targetPos from begin to end of Uint32Array.
5933     *
5934     * @param insert insert index to place copied elements
5935     *
5936     * See rules of parameters normalization:
5937     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
5938     */
5939    public copyWithin(target: int): Uint32Array {
5940        return this.copyWithin(target, 0, this.lengthInt)
5941    }
5942
5943    /**
5944     * Returns an array of key, value pairs for every entry in the Uint32Array
5945     *
5946     * @returns key, value pairs for every entry in the array
5947     */
5948    public entries(): IterableIterator<[Number, Number]> {
5949        return new Uint32ArrayIteratorEntries(this)
5950    }
5951
5952    /**
5953     * Fills the Uint32Array with specified value
5954     *
5955     * @param value new value
5956     *
5957     * @returns modified Uint32Array
5958     */
5959    public fill(value: number, start?: number, end?: number): Uint32Array {
5960        value = this.zeroIfInfinity(value)
5961        this.fill(value as long, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
5962        return this
5963    }
5964
5965    /**
5966     * Fills the Uint32Array with specified value
5967     *
5968     * @param value new value
5969     *
5970     * @returns modified Uint32Array
5971     */
5972    public fill(value: number, start: int, end?: number): Uint32Array {
5973        value = this.zeroIfInfinity(value)
5974        this.fill(value as long, start as int, asIntOrDefault(end, this.lengthInt))
5975        return this
5976    }
5977
5978    /**
5979     * Fills the Uint32Array with specified value
5980     *
5981     * @param value new value
5982     *
5983     * @returns modified Uint32Array
5984     */
5985    public fill(value: number, start: int, end: number): Uint32Array {
5986        value = this.zeroIfInfinity(value)
5987        this.fill(value as long, start as int, end as int)
5988        return this
5989    }
5990
5991    /**
5992     * Fills the Uint32Array with specified value
5993     *
5994     * @param value new value
5995     *
5996     * @returns modified Uint32Array
5997     */
5998    public fill(value: number, start: number, end: int): Uint32Array {
5999        value = this.zeroIfInfinity(value)
6000        this.fill(value as long, start as int, end as int)
6001        return this
6002    }
6003
6004    /**
6005     * Fills the Uint32Array with specified value
6006     *
6007     * @param value new value
6008     *
6009     * @returns modified Uint32Array
6010     */
6011    public fill(value: number, start: int, end: int): Uint32Array {
6012        value = this.zeroIfInfinity(value)
6013        this.fill(value as long, start as int, end as int)
6014        return this
6015    }
6016
6017    /**
6018     * Fills the Uint32Array with specified value
6019     *
6020     * @param value new value
6021     *
6022     * @returns modified Uint32Array
6023     */
6024    public fill(value: long, start?: number, end?: number): Uint32Array {
6025        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
6026        return this
6027    }
6028
6029    /**
6030     * Fills the Uint32Array with specified value
6031     *
6032     * @param value new value
6033     *
6034     * @returns modified Uint32Array
6035     */
6036    public fill(value: long, start: int, end?: number): Uint32Array {
6037        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
6038        return this
6039    }
6040
6041    /**
6042     * Fills the Uint32Array with specified value
6043     *
6044     * @param value new value
6045     *
6046     * @returns modified Uint32Array
6047     */
6048    public fill(value: long, start: int, end: number): Uint32Array {
6049        this.fill(value, start as int, end as int)
6050        return this
6051    }
6052
6053    /**
6054     * Fills the Uint32Array with specified value
6055     *
6056     * @param value new value
6057     *
6058     * @returns modified Uint32Array
6059     */
6060    public fill(value: long, start: number, end: int): Uint32Array {
6061        this.fill(value, start as int, end as int)
6062        return this
6063    }
6064
6065    /**
6066     * Fills the Uint32Array with specified value
6067     *
6068     * @param value new value
6069     *
6070     * @returns modified Uint32Array
6071     */
6072    public fill(value: long, start: int, end: int): Uint32Array {
6073        const k = normalizeIndex(start, this.lengthInt)
6074        const finalPos = normalizeIndex(end, this.lengthInt)
6075        this.fillInternal(value, k, finalPos)
6076        return this
6077    }
6078
6079    private final native fillInternal(value: long, start: int, end: int): void
6080
6081    /**
6082     * Assigns val as element on index.
6083     *
6084     * @param val value to set
6085     *
6086     * @param index index to change
6087     */
6088    public set(insertPos: number, val: number): void {
6089        this.$_set(insertPos as int, val)
6090    }
6091
6092    /**
6093     * Assigns val as element on index.
6094     *
6095     * @param val value to set
6096     *
6097     * @param index index to change
6098     */
6099    public set(insertPos: int, val: number): void {
6100        this.$_set(insertPos as int, val)
6101    }
6102
6103    /**
6104     * Assigns val as element on index.
6105     *
6106     * @param val value to set
6107     *
6108     * @param index index to change
6109     */
6110    public set(insertPos: number, val: long): void {
6111        this.$_set(insertPos as int, val)
6112    }
6113
6114    /**
6115     * Assigns val as element on index.
6116     *
6117     * @param val value to set
6118     *
6119     * @param index index to change
6120     */
6121    public set(insertPos: int, val: long): void {
6122        this.$_set(insertPos as int, val)
6123    }
6124
6125    /**
6126     * Copies all elements of arr to the current Uint32Array starting from insertPos.
6127     *
6128     * @param arr array to copy data from
6129     *
6130     * @param insertPos start index where data from arr will be inserted
6131     *
6132     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
6133     */
6134    public set(arr: FixedArray<number>, insertPos1: number): void {
6135        const insertPos = insertPos1 as int
6136        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
6137            throw new RangeError("set(insertPos: int, arr: FixedArray<long>): size of arr is greater than Uint32Array.length")
6138        }
6139        for (let i = 0; i < arr.length; i++) {
6140            let v = this.zeroIfInfinity(arr[i])
6141            this.setUnsafeClamp(insertPos as int + i as int, v as long)
6142        }
6143    }
6144
6145    /**
6146     * Copies all elements of arr to the current Uint32Array starting from insertPos.
6147     *
6148     * @param arr array to copy data from
6149     *
6150     * @param insertPos start index where data from arr will be inserted
6151     *
6152     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
6153     */
6154    public set(arr: FixedArray<long>, insertPos: int): void {
6155        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
6156            throw new RangeError("set(insertPos: int, arr: FixedArray<long>): size of arr is greater than Uint32Array.length")
6157        }
6158        for (let i = 0; i < arr.length; i++) {
6159            let v = this.zeroIfInfinity(arr[i])
6160            this.setUnsafeClamp(insertPos + i, v)
6161        }
6162    }
6163
6164    /**
6165     * Copies all elements of arr to the current Uint32Array.
6166     *
6167     * @param arr array to copy data from
6168     */
6169    public set(arr: FixedArray<number>): void {
6170        this.set(arr, 0)
6171    }
6172
6173    /**
6174     * Copies all elements of arr to the current Uint32Array.
6175     *
6176     * @param arr array to copy data from
6177     */
6178    public set(arr: FixedArray<long>): void {
6179        this.set(arr, 0)
6180    }
6181
6182    public native set(array: Uint32Array): void
6183
6184    public native set(array: Uint32Array, offset: number): void
6185
6186    /**
6187     * Copies elements from an ArrayLike object to the Uint32Array.
6188     *
6189     * @param array An ArrayLike object containing the elements to copy.
6190     *
6191     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
6192     */
6193    public set(array: ArrayLike<number>, offset: number = 0): void {
6194        const insertPos = offset as int
6195        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
6196            throw new RangeError("offset is out of bounds")
6197        }
6198        for (let i = array.length - 1; i >= 0; --i) {
6199            let v = this.zeroIfInfinity(array[i])
6200            this.setUnsafeClamp(insertPos as int + i as int, v as long)
6201        }
6202    }
6203
6204    /**
6205     * Returns a new array from a set of elements.
6206     *
6207     * @param items a set of elements to include in the new array object.
6208     *
6209     * @returns new Uint32Array
6210     */
6211    public static of(...items: FixedArray<number>): Uint32Array {
6212        let res = new Uint32Array(items.length as int)
6213        for (let i: int = 0; i < items.length; i++) {
6214            res.setUnsafeClamp(i, res.zeroIfInfinity(items[i]) as long)
6215        }
6216        return res
6217    }
6218
6219    /**
6220     * Returns a new array from a set of elements.
6221     *
6222     * @param items a set of elements to include in the new array object.
6223     *
6224     * @returns new Uint32Array
6225     */
6226    public static of(...items: FixedArray<int>): Uint32Array {
6227        let res = new Uint32Array(items.length as int)
6228        for (let i: int = 0; i < items.length; i++) {
6229            res.setUnsafeClamp(i, items[i] as long)
6230        }
6231        return res
6232    }
6233
6234    /**
6235     * Returns a new array from a set of elements.
6236     *
6237     * @param items a set of elements to include in the new array object.
6238     *
6239     * @returns new Uint32Array
6240     */
6241    public static of(...items: FixedArray<long>): Uint32Array {
6242        let res = new Uint32Array(items.length as int)
6243        for (let i: int = 0; i < items.length; i++) {
6244            res.setUnsafeClamp(i, items[i])
6245        }
6246        return res
6247    }
6248
6249    /**
6250     * Returns a new array from a set of elements.
6251     *
6252     * @param items a set of elements to include in the new array object.
6253     *
6254     * @returns new Uint32Array
6255     */
6256    public static of(): Uint32Array {
6257        return new Uint32Array(0 as int)
6258    }
6259
6260    /**
6261     * Creates an array from an array-like or iterable object.
6262     *
6263     * @param arrayLike An array-like or iterable object to convert to an array.
6264     *
6265     * @returns new Uint32Array
6266     */
6267    public static from(arr: ArrayLike<number>): Uint32Array {
6268        return Uint32Array.from<number>(arr, (x: number, k: number): number => x)
6269    }
6270
6271    /**
6272     * Creates an array from an array-like or iterable object.
6273     *
6274     * @param arrayLike An array-like or iterable object to convert to an array.
6275     *
6276     * @param mapfn A mapping function to call on every element of the array.
6277     *
6278     * @returns new Uint32Array
6279     */
6280    public static from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number): Uint32Array {
6281        if (mapfn == undefined) {
6282            mapfn = (v: number, k: number): number => { return v }
6283        }
6284
6285        let iter = arrayLike.$_iterator()
6286        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
6287        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
6288        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
6289        //  we can make one pass through the iterator without the need for memory reallocation.
6290        const maybeLength = tryGetIteratorLength(arrayLike)
6291        if (maybeLength) {
6292            const result = new Uint32Array(maybeLength)
6293            for (let i = 0; i < maybeLength; ++i) {
6294                const x = iter.next()
6295                if (x.done) {
6296                    return new Uint32Array(result.buffer, 0, i)
6297                }
6298                result.setUnsafeClamp(i, result.zeroIfInfinity((mapfn)!(x.value!, i)) as long)
6299            }
6300            return result
6301        }
6302
6303        // NOTE (templin.konstantin): Create builtin array as buffer
6304        let temp = new Uint32Array(6)
6305        let index : FixedArray<int> = new int[1]
6306        index[0] = 0
6307
6308        iteratorForEach<number>(arrayLike.$_iterator(), (x: number): void => {
6309            if (index[0] + 1 > temp.lengthInt) {
6310                // NOTE (templin.konstantin): Progressive reallocation
6311                const curLength = (temp.buffer as Buffer).getByteLength()
6312                const tb = new ArrayBuffer(curLength * 2)
6313                for (let i = 0; i < curLength; ++i) {
6314                    tb.set(i, (temp.buffer as Buffer).at(i))
6315                }
6316                temp = new Uint32Array(tb)
6317            }
6318            temp.setUnsafeClamp(index[0], temp.zeroIfInfinity((mapfn)!(x, index[0])) as long)
6319            index[0]++
6320        })
6321
6322        return new Uint32Array(temp.buffer, 0, index[0])
6323    }
6324
6325    /**
6326     * Creates an array from an array-like or iterable object.
6327     *
6328     * @param arrayLike An array-like or iterable object to convert to an array.
6329     *
6330     * @param mapfn A mapping function to call on every element of the array.
6331     *
6332     * @returns new Uint32Array
6333     */
6334    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number): Uint32Array {
6335        let res = new Uint32Array(arrayLike.length)
6336        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
6337        const idx : FixedArray<int> = new int[1]
6338        idx[0] = 0
6339        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
6340            res.setUnsafeClamp(idx[0], res.zeroIfInfinity(mapfn(x as T, idx[0] as number)) as long)
6341            idx[0] += 1
6342        })
6343        return res
6344    }
6345
6346    /**
6347     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
6348     *
6349     * @param searchElement The element to search for
6350     *
6351     * @param fromIndex The position in this array at which to begin searching for searchElement
6352     *
6353     * @returns true if searchElement is in Uint32Array, false otherwise
6354     */
6355    public includes(searchElement: number, fromIndex?: number): boolean {
6356        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
6357    }
6358
6359    /**
6360     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
6361     *
6362     * @param searchElement The element to search for
6363     *
6364     * @param fromIndex The position in this array at which to begin searching for searchElement
6365     *
6366     * @returns true if searchElement is in Uint32Array, false otherwise
6367     */
6368    public includes(searchElement: long, fromIndex: int): boolean {
6369        return this.indexOf(searchElement as int, fromIndex) != -1
6370    }
6371
6372    /**
6373     * Determines whether Uint32Array includes a certain element, returning true or false as appropriate
6374     *
6375     * @param searchElement The element to search for
6376     *
6377     * @param fromIndex The position in this array at which to begin searching for searchElement
6378     *
6379     * @returns true if searchElement is in Uint32Array, false otherwise
6380     */
6381    public includes(searchElement: long): boolean {
6382        return this.indexOf(searchElement as int, 0) != -1
6383    }
6384
6385    /**
6386     * Returns the index of the first occurrence of a value in Uint32Array.
6387     *
6388     * @param searchElement The value to locate in the array.
6389     *
6390     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6391     *  search starts at index 0.
6392     *
6393     * @returns index of element if it presents, -1 otherwise
6394     */
6395    public indexOf(searchElement: number, fromIndex?: number): number {
6396        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
6397    }
6398
6399    /**
6400     * Returns the index of the first occurrence of a value in Uint32Array.
6401     *
6402     * @param searchElement The value to locate in the array.
6403     *
6404     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6405     *  search starts at index 0.
6406     *
6407     * @returns index of element if it presents, -1 otherwise
6408     */
6409    public indexOf(searchElement: number, fromIndex: int): number {
6410            return this.indexOfImpl(searchElement, fromIndex)
6411    }
6412
6413    /**
6414     * Returns the index of the first occurrence of a value in Uint32Array.
6415     *
6416     * @param searchElement The value to locate in the array.
6417     *
6418     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6419     *  search starts at index 0.
6420     *
6421     * @returns index of element if it presents, -1 otherwise
6422     */
6423    public indexOf(searchElement: int, fromIndex: int): number {
6424        return this.indexOfImpl(searchElement as long, fromIndex)
6425    }
6426
6427    /**
6428     * Returns the index of the first occurrence of a value in Array.
6429     *
6430     * @param searchElement The value to locate in the array.
6431     *
6432     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6433     *  search starts at index 0.
6434     *
6435     * @returns index of element if it presents, -1 otherwise
6436     */
6437    private final native indexOfImpl(searchElement: number, fromIndex: int): number
6438
6439    /**
6440     * Returns the index of the first occurrence of a value in Array.
6441     *
6442     * @param searchElement The value to locate in the array.
6443     *
6444     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6445     *  search starts at index 0.
6446     *
6447     * @returns index of element if it presents, -1 otherwise
6448     */
6449    private final native indexOfImpl(searchElement: long, fromIndex: int): number
6450
6451    /**
6452     * Returns the index of the first occurrence of a value in Uint32Array.
6453     *
6454     * @param searchElement The value to locate in the array.
6455     *
6456     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6457     *  search starts at index 0.
6458     *
6459     * @returns index of element if it presents, -1 otherwise
6460     */
6461    public indexOf(searchElement: int): number {
6462        return this.indexOf(searchElement, 0)
6463    }
6464
6465
6466    /**
6467     * Converts all elements of an array to strings and joins them using the specified separator.
6468     *
6469     * @param separator - separates one element of an array from the next in the resulting String.
6470     *
6471     * @returns joined representation
6472     */
6473    private final native joinInternal(separator: String): string;
6474
6475    /**
6476     * Adds all the elements of an array separated by the specified separator string
6477     *
6478     * @param separator A string used to separate one element of an array from the next in the
6479     * resulting String. If omitted, the array elements are separated with a comma
6480     *
6481     * @returns joined representation
6482     */
6483    public join(separator?: String): string {
6484        if (separator == undefined) {
6485            return this.joinInternal(",")
6486        }
6487        return this.joinInternal(separator)
6488    }
6489
6490    /**
6491     * Returns an list of keys in Uint32Array
6492     *
6493     * @returns iterator over keys
6494     */
6495    public keys(): IterableIterator<number> {
6496        return new Uint32ArrayIteratorKeys(this)
6497    }
6498
6499    /**
6500     * Returns the index of the last occurrence of a value in Uint32Array.
6501     *
6502     * @param searchElement The value to locate in the array.
6503     *
6504     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6505     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6506     *
6507     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6508     */
6509    public lastIndexOf(searchElement: number, fromIndex: number|undefined): number {
6510        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
6511    }
6512
6513    /**
6514     * Returns the index of the last occurrence of a value in Uint32Array.
6515     *
6516     * @param searchElement The value to locate in the array.
6517     *
6518     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6519     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6520     *
6521     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6522     */
6523    public lastIndexOf(searchElement: number): number {
6524        return this.lastIndexOf(searchElement, this.lengthInt - 1)
6525    }
6526
6527    /**
6528     * Returns the index of the last occurrence of a value in Uint32Array.
6529     *
6530     * @param searchElement The value to locate in the array.
6531     *
6532     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6533     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6534     *
6535     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6536     */
6537    public lastIndexOf(searchElement: number, fromIndex: int): number {
6538            return this.lastIndexOfImpl(searchElement, fromIndex)
6539    }
6540
6541    /**
6542     * Returns the index of the last occurrence of a value in Uint32Array.
6543     *
6544     * @param searchElement The value to locate in the array.
6545     *
6546     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6547     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6548     *
6549     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6550     */
6551    public lastIndexOf(searchElement: int, fromIndex: int): number {
6552        return this.lastIndexOfImpl(searchElement as long, fromIndex)
6553    }
6554
6555    /**
6556     * Returns the index of the first occurrence of a value in Array.
6557     *
6558     * @param searchElement The value to locate in the array.
6559     *
6560     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6561     *  search starts at index 0.
6562     *
6563     * @returns index of element if it presents, -1 otherwise
6564     */
6565    private final native lastIndexOfImpl(searchElement: number, fromIndex: int): number
6566
6567    /**
6568     * Returns the index of the first occurrence of a value in Array.
6569     *
6570     * @param searchElement The value to locate in the array.
6571     *
6572     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
6573     *  search starts at index 0.
6574     *
6575     * @returns index of element if it presents, -1 otherwise
6576     */
6577    private final native lastIndexOfImpl(searchElement: long, fromIndex: int): number
6578
6579    /**
6580     * Returns the index of the last occurrence of a value in Uint32Array.
6581     *
6582     * @param searchElement The value to locate in the array.
6583     *
6584     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
6585     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
6586     *
6587     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
6588     */
6589    public lastIndexOf(searchElement: int): number {
6590        return this.lastIndexOf(searchElement, this.lengthInt - 1)
6591    }
6592
6593   /**
6594    * Creates a new Uint32Array using initializer
6595    *
6596    * @param data initializer
6597    *
6598    * @returns a new Uint32Array from data
6599    */
6600    public of(...data: FixedArray<number>): Uint32Array {
6601        throw new Error("Uint32Array.of: not implemented")
6602    }
6603
6604    /**
6605     * Creates a new Uint32Array using reversed data from the current one
6606     *
6607     * @returns a new Uint32Array using reversed data from the current one
6608     */
6609    public native reverse(): Uint32Array
6610
6611    /**
6612     * Creates a slice of current Uint32Array using range [begin, end)
6613     *
6614     * @param begin start index to be taken into slice
6615     *
6616     * @param end last index to be taken into slice
6617     *
6618     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
6619     *
6620     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6621     */
6622    public slice(begin?: number, end?: number): Uint32Array {
6623        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
6624    }
6625
6626    /**
6627     * Creates a slice of current Uint32Array using range [begin, end)
6628     *
6629     * @param begin start index to be taken into slice
6630     *
6631     * @param end last index to be taken into slice
6632     *
6633     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
6634     *
6635     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6636     */
6637    public slice(begin: number, end: number): Uint32Array {
6638        return this.slice(begin as int, end as int)
6639    }
6640
6641    /**
6642     * Creates a slice of current Uint32Array using range [begin, end)
6643     *
6644     * @param begin start index to be taken into slice
6645     *
6646     * @param end last index to be taken into slice
6647     *
6648     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
6649     *
6650     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6651     */
6652    public slice(begin: number, end: int): Uint32Array {
6653        return this.slice(begin as int, end as int)
6654    }
6655
6656    /**
6657     * Creates a slice of current Uint32Array using range [begin, end)
6658     *
6659     * @param begin start index to be taken into slice
6660     *
6661     * @param end last index to be taken into slice
6662     *
6663     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
6664     *
6665     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6666     */
6667    public slice(begin: int, end: number): Uint32Array {
6668        return this.slice(begin as int, end as int)
6669    }
6670
6671    /**
6672     * Creates a slice of current Uint32Array using range [begin, end)
6673     *
6674     * @param begin start index to be taken into slice
6675     *
6676     * @param end last index to be taken into slice
6677     *
6678     * @returns a new Uint32Array with elements of current Uint32Array[begin;end) where end index is excluded
6679     *
6680     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
6681     */
6682    public slice(begin: int, end: int): Uint32Array {
6683        const len: int = this.lengthInt
6684        const relStart = normalizeIndex(begin, len)
6685        const relEnd = normalizeIndex(end, len)
6686        let count = relEnd - relStart
6687        if (count < 0) {
6688            count = 0
6689        }
6690        let buf = this.buffer.slice(relStart * Uint32Array.BYTES_PER_ELEMENT as int, relEnd * Uint32Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
6691        return new Uint32Array(buf)
6692    }
6693
6694    /**
6695     * Creates a slice of current Uint32Array using range [begin, this.lengthInt).
6696     *
6697     * @param begin start index to be taken into slice
6698     *
6699     * @returns a new Uint32Array with elements of current Uint32Array[begin, this.lengthInt)
6700     */
6701    public slice(begin: number): Uint32Array {
6702        return this.slice(begin as int)
6703    }
6704
6705    /**
6706     * Creates a slice of current Uint32Array using range [begin, this.lengthInt).
6707     *
6708     * @param begin start index to be taken into slice
6709     *
6710     * @returns a new Uint32Array with elements of current Uint32Array[begin, this.lengthInt)
6711     */
6712    public slice(begin: int): Uint32Array {
6713        return this.slice(begin, this.lengthInt)
6714    }
6715
6716    /**
6717     * Sorts in-place by numeric value in ascending order.
6718     *
6719     * @returns sorted Array
6720     */
6721    public native sort(): this;
6722
6723    /**
6724     * Sorts in-place
6725     *
6726     * @param compareFn comparator _  used to determine the order of the elements.
6727     * compareFn returns a negative value if first argument is less than second argument,
6728     * zero if they're equal and a positive value otherwise.
6729     *
6730     * @returns sorted Uint32Array
6731     */
6732    public sort(compareFn?: (a: number, b: number) => number): this {
6733        if (compareFn == undefined) {
6734            this.sort()
6735            return this
6736        }
6737        let arr: FixedArray<long> = new long[this.lengthInt]
6738        for (let i = 0; i < this.lengthInt; ++i) {
6739            arr[i] = this.getUnsafe(i)
6740        }
6741
6742        let cmp = (l: long, r: long): number => {
6743            const result = compareFn!(l as number, r as number)
6744            return result
6745        }
6746        const MAX_SHORT_LENGTH = 24
6747        if (arr.length > MAX_SHORT_LENGTH) {
6748            arr = mergeSort(arr, cmp)
6749        } else {
6750            sort(arr, cmp)
6751        }
6752        for (let i = 0; i < arr.length; ++i) {
6753            this.setUnsafe(i, arr[i])
6754        }
6755        return this
6756    }
6757
6758    /**
6759     * Creates a Uint32Array with the same underlying Buffer
6760     *
6761     * @param begin start index, inclusive
6762     *
6763     * @param end last index, exclusive
6764     *
6765     * @returns new Uint32Array with the same underlying Buffer
6766     */
6767    public subarray(begin?: number, end?: number): Uint32Array {
6768        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
6769    }
6770
6771    /**
6772     * Creates a Uint32Array with the same underlying Buffer
6773     *
6774     * @param begin start index, inclusive
6775     *
6776     * @param end last index, exclusive
6777     *
6778     * @returns new Uint32Array with the same underlying Buffer
6779     */
6780    public subarray(begin: number, end: int): Uint32Array {
6781        return this.subarray(begin as int, end as int)
6782    }
6783
6784    /**
6785     * Creates a Uint32Array with the same underlying Buffer
6786     *
6787     * @param begin start index, inclusive
6788     *
6789     * @param end last index, exclusive
6790     *
6791     * @returns new Uint32Array with the same underlying Buffer
6792     */
6793    public subarray(begin: int, end: number): Uint32Array {
6794        return this.subarray(begin as int, end as int)
6795    }
6796
6797    /**
6798     * Creates a Uint32Array with the same underlying Buffer
6799     *
6800     * @param begin start index, inclusive
6801     *
6802     * @param end last index, exclusive
6803     *
6804     * @returns new Uint32Array with the same underlying Buffer
6805     */
6806    public subarray(begin: int, end: int | undefined = this.lengthInt): Uint32Array {
6807        const len: int = this.lengthInt
6808        const relStart = normalizeIndex(begin, len)
6809        const relEnd = normalizeIndex(end ?? this.lengthInt, len)
6810        let count = relEnd - relStart
6811        if (count < 0) {
6812            count = 0
6813        }
6814        return new Uint32Array(this.buffer, relStart * Uint32Array.BYTES_PER_ELEMENT as int, count)
6815    }
6816
6817    /**
6818     * Converts Uint32Array to a string with respect to locale
6819     *
6820     * @param locales
6821     *
6822     * @param options
6823     *
6824     * @returns string representation
6825     */
6826    public toLocaleString(locales: Object, options: Object): string {
6827        throw new Error("Uint32Array.toLocaleString: not implemented")
6828    }
6829
6830    /**
6831     * Converts Uint32Array to a string with respect to locale
6832     *
6833     * @param locales
6834     *
6835     * @returns string representation
6836     */
6837    public toLocaleString(locales: Object): string {
6838        return this.toLocaleString(new Object(), new Object())
6839    }
6840
6841    /**
6842     * Converts Uint32Array to a string with respect to locale
6843     *
6844     * @returns string representation
6845     */
6846    public toLocaleString(): string {
6847        let res: StringBuilder = new StringBuilder("")
6848        for (let i = 0; i < this.lengthInt - 1; ++i) {
6849            res.append((this.getUnsafe(i) as Number).toLocaleString())
6850            res.append(",")
6851        }
6852        if (this.lengthInt > 0) {
6853            res.append((this.getUnsafe(this.lengthInt - 1) as Number).toLocaleString())
6854        }
6855        return res.toString()
6856    }
6857
6858    /**
6859     * Creates a reversed copy
6860     *
6861     * @returns a reversed copy
6862     */
6863    public final native toReversed(): Uint32Array
6864
6865    /**
6866     * Creates a sorted copy
6867     *
6868     * @returns a sorted copy
6869     */
6870    public toSorted(): Uint32Array {
6871        return new Uint32Array(this).sort()
6872    }
6873
6874    /**
6875     * Returns a string representation of the Uint32Array
6876     *
6877     * @returns a string representation of the Uint32Array
6878     */
6879    public override toString(): string {
6880        return this.join(",")
6881    }
6882
6883    /**
6884     * Returns array values iterator
6885     *
6886     * @returns an iterator
6887     */
6888    public values(): IterableIterator<Number> {
6889         return new Uint32ArrayIterator(this)
6890    }
6891
6892    /**
6893     * Creates a copy with replaced value on index
6894     *
6895     * @param index
6896     *
6897     * @param value
6898     *
6899     * @returns an Uint32Array with replaced value on index
6900     */
6901    public with(index: number, value: number): Uint32Array {
6902        return this.with(index as int, value as long)
6903    }
6904
6905    /**
6906     * Creates a copy with replaced value on index
6907     *
6908     * @param index
6909     *
6910     * @param value
6911     *
6912     * @returns an Uint32Array with replaced value on index
6913     */
6914    public with(index: int, value: long): Uint32Array {
6915        let res = new Uint32Array(this)
6916        res.setUnsafeClamp(index, value)
6917        return res
6918    }
6919
6920    /// === with element lambda functions ===
6921
6922    /**
6923     * Determines whether the specified callback function returns true for any element of an array.
6924     *
6925     * @param predicate A function that accepts three arguments.
6926     * The some method calls the predicate function for each element in the array
6927     * until the predicate returns a true or until the end of the array.
6928     *
6929     * @returns false unless predicate function returns true for an array element,
6930     * in which case true is immediately returned.
6931     */
6932    public some(predicate: (element: number, index: number, array: Uint32Array) => boolean): boolean {
6933        for (let i = 0; i < this.lengthInt; i++) {
6934            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
6935                return true
6936            }
6937        }
6938        return false
6939    }
6940
6941    /**
6942     * Calls the specified callback function for all the elements in an array.
6943     * The return value of the callback function is the accumulated result,
6944     * and is provided as an argument in the next call to the callback function.
6945     *
6946     * @param callbackfn A function that accepts four arguments.
6947     * The reduce method calls the callbackfn function one time for each element in the array.
6948     *
6949     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6950     * The first call to the callbackfn function provides this value as an argument.
6951     *
6952     * @returns The value that results from running the callback function to completion over the entire typed array.
6953     */
6954    public reduce<U = number>(
6955                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U,
6956                initialValue: U): U {
6957        let accumulatedValue = initialValue
6958        for (let i = 0; i < this.lengthInt; i++) {
6959            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
6960        }
6961        return accumulatedValue
6962    }
6963
6964    /**
6965     * Calls the specified callback function for all the elements in an array.
6966     * The return value of the callback function is the accumulated result,
6967     * and is provided as an argument in the next call to the callback function.
6968     *
6969     * @param callbackfn A function that accepts four arguments.
6970     * The reduce method calls the callbackfn function one time for each element in the array.
6971     * The first call to the callbackfn function provides array first element value as an argument
6972     *
6973     * @returns The value that results from running the callback function to completion over the entire typed array.
6974     * calling reduce method on an empty array without an initial value creates a TypeError
6975     */
6976    public reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number {
6977        if (this.lengthInt == 0) {
6978            throw new TypeError("Reduce of empty array with no initial value")
6979        }
6980
6981        let accumulatedValue = this.$_get(0) as number
6982        for (let i = 1; i < this.lengthInt; i++) {
6983            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
6984        }
6985        return accumulatedValue
6986    }
6987
6988    /**
6989     * Calls the specified callback function for all the elements in an array, in descending order.
6990     * The return value of the callback function is the accumulated result,
6991     * and is provided as an argument in the next call to the callback function.
6992     *
6993     * @param callbackfn A function that accepts four arguments.
6994     * The reduceRight method calls the callbackfn function one time for each element in the array.
6995     *
6996     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
6997     * The first call to the callbackfn function provides this value as an argument.
6998     *
6999     * @returns The value that results from running the callback function to completion over the entire typed array.
7000     */
7001    public reduceRight<U = number>(
7002                callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U,
7003                initialValue: U): U {
7004        let accumulatedValue = initialValue
7005        for (let i = this.lengthInt - 1; i >= 0; i--) {
7006            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7007        }
7008        return accumulatedValue
7009    }
7010
7011    /**
7012     * Calls the specified callback function for all the elements in an array, in descending order.
7013     * The return value of the callback function is the accumulated result,
7014     * and is provided as an argument in the next call to the callback function.
7015     *
7016     * @param callbackfn A function that accepts four arguments.
7017     * The reduceRight method calls the callbackfn function one time for each element in the array.
7018     * The first call to the callbackfn function provides array last element value as an argument
7019     *
7020     * @returns The value that results from running the callback function to completion over the entire typed array.
7021     * calling reduceRight method on an empty array without an initial value creates a TypeError
7022     */
7023    public reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number {
7024        if (this.lengthInt == 0) {
7025            throw new TypeError("Reduce of empty array with no initial value")
7026        }
7027
7028        let accumulatedValue: number = this.$_get(this.lengthInt - 1) as number
7029        for (let i = this.lengthInt - 2; i >= 0; i--) {
7030            accumulatedValue = callbackfn(accumulatedValue, this.getUnsafe(i) as number, i as number, this)
7031        }
7032        return accumulatedValue
7033    }
7034
7035    /**
7036     * Creates a new Uint32Array using fn(arr[i]) over all elements of current Uint32Array.
7037     *
7038     * @param fn a function to apply for each element of current Uint32Array
7039     *
7040     * @returns a new Uint32Array where for each element from current Uint32Array fn was applied
7041     */
7042    public map(fn: (val: number, index: number, array: Uint32Array) => number): Uint32Array {
7043        let resBuf = new ArrayBuffer(this.lengthInt * Uint32Array.BYTES_PER_ELEMENT as int)
7044        let res = new Uint32Array(resBuf)
7045        for (let i = 0; i < this.lengthInt; i++) {
7046            const fnRes = fn(this.getUnsafe(i) as number, i as number, this)
7047            res.setUnsafeClamp(i, fnRes as long)
7048        }
7049        return res
7050    }
7051
7052    /**
7053     * Determines whether the specified callback function returns true for all elements of an array.
7054     *
7055     * @param predicate A function that accepts three arguments.
7056     * The every method calls the predicate function for each element in the array until the predicate returns a false,
7057     * or until the end of the array.
7058     *
7059     * @returns true unless predicate function returns a false for an array element,
7060     * in which case false is immediately returned.
7061     */
7062    public every(predicate: (element: number, index: number, array: Uint32Array) => boolean): boolean {
7063        for (let i = 0; i < this.lengthInt; i++) {
7064            if (!predicate(this.getUnsafe(i) as number, i as number, this)) {
7065                return false
7066            }
7067        }
7068        return true
7069    }
7070
7071    /**
7072     * Creates a new Uint32Array from current Uint32Array based on a condition fn.
7073     *
7074     * @param fn the condition to apply for each element
7075     *
7076     * @returns a new Uint32Array with elements from current Uint32Array that satisfy condition fn
7077     */
7078    public filter(fn: (val: number, index: number, array: Uint32Array) => boolean): Uint32Array {
7079        let markers : FixedArray<boolean> = new boolean[this.lengthInt]
7080        let resLen = 0
7081        for (let i = 0; i < this.lengthInt; i++) {
7082            markers[i] = fn(this.getUnsafe(i) as number, i as number, this)
7083            if (markers[i]) {
7084                ++resLen
7085            }
7086        }
7087        let res = new Uint32Array(resLen)
7088        for (let i = 0, j = 0; i < this.lengthInt; i++) {
7089            if (markers[i]) {
7090                res.setUnsafe(j, this.getUnsafe(i))
7091                ++j
7092            }
7093        }
7094        return res
7095    }
7096
7097    /**
7098     * Returns the value of the first element in the array where predicate is true, and undefined
7099     * otherwise
7100     *
7101     * @param predicate find calls predicate once for each element of the array, in ascending
7102     * order, until it finds one where predicate returns true. If such an element is found, find
7103     * immediately returns that element value. Otherwise, find returns undefined
7104     *
7105     * @returns number | undefined
7106     */
7107    public find(predicate: (value: number, index: number, array: Uint32Array) => boolean): number | undefined {
7108        for (let i = 0; i < this.lengthInt; i++) {
7109            let val = this.getUnsafe(i) as number
7110            if (predicate(val, i as number, this)) {
7111                return val
7112            }
7113        }
7114        return undefined
7115    }
7116
7117    /**
7118     * Returns the index of the first element in the array where predicate is true, and -1
7119     * otherwise
7120     *
7121     * @param predicate find calls predicate once for each element of the array, in ascending
7122     * order, until it finds one where predicate returns true. If such an element is found,
7123     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
7124     *
7125     * @returns number
7126     */
7127    public findIndex(predicate: (value: number, index: number, obj: Uint32Array) => boolean): number {
7128        for (let i = 0; i < this.lengthInt; i++) {
7129            if (predicate(this.getUnsafe(i) as number, i as number, this)) {
7130                return i as number
7131            }
7132        }
7133        return -1 as number
7134    }
7135
7136    /**
7137     * Finds the last element in the Uint32Array that satisfies the condition
7138     *
7139     * @param fn condition
7140     *
7141     * @returns the last element that satisfies fn
7142     */
7143    public findLast(fn: (val: number, index: number, array: Uint32Array) => boolean): number {
7144        for (let i = this.lengthInt - 1; i >= 0; i--) {
7145            let val = this.getUnsafe(i) as number
7146            if (fn(val, i as number, this)) {
7147                return val
7148            }
7149        }
7150        throw new Error("Uint32Array.findLast: not implemented if an element was not found")
7151    }
7152
7153    /**
7154     * Finds an index of the last element in the Uint32Array that satisfies the condition
7155     *
7156     * @param fn condition
7157     *
7158     * @returns the index of the last element that satisfies fn, -1 otherwise
7159     */
7160    public findLastIndex(fn: (val: number, index: number, array: Uint32Array) => boolean): number {
7161        for (let i = this.lengthInt - 1; i >= 0; i--) {
7162            if (fn(this.getUnsafe(i) as number, i as number, this)) {
7163                return i as number
7164            }
7165        }
7166        return -1 as number
7167    }
7168
7169    /**
7170     * Performs the specified action for each element in Uint32Array
7171     *
7172     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
7173     * callbackfn function one time for each element in the array.
7174     *
7175     * @returns None
7176     */
7177    public forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void): void {
7178        for (let i = 0; i < this.lengthInt; i++) {
7179            callbackfn(this.getUnsafe(i) as number, i as number, this)
7180        }
7181    }
7182
7183    /**
7184     * Returns the object itself
7185     *
7186     * @returns Uint32Array
7187     */
7188    public valueOf(): Uint32Array {
7189        return this
7190    }
7191
7192    /** Byte offset within the underlying Buffer */
7193    public get byteOffset(): number {
7194        return this.byteOffsetInt
7195    }
7196
7197    /** Number of bytes used */
7198    public get byteLength(): number {
7199        return this.byteLengthInt
7200    }
7201
7202    /** Number of long stored in Uint32Array */
7203    public get length(): number {
7204        return this.lengthInt
7205    }
7206
7207    /** String \"Uint32Array\" */
7208    public readonly name = "Uint32Array"
7209
7210    private static clamp(val: long): long {
7211        return val
7212    }
7213
7214    internal setUnsafeClamp(insertPos: int, val: long): void {
7215        this.setUnsafe(insertPos, val)
7216    }
7217
7218    private final native getUnsafe(index: int): long
7219
7220    internal setUnsafe(index: int, val: long): void {
7221        index = index * Uint32Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
7222        let res: long = 0
7223        if (IS_LITTLE_ENDIAN) {
7224            for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
7225                this.buffer.set(index + i, (val & 0xff) as byte)
7226                val = val >> 8
7227            }
7228        } else {
7229            for (let i = 0; i < Uint32Array.BYTES_PER_ELEMENT as int; i++) {
7230                this.buffer.set(index + 3 - i, (val & 0xff) as byte)
7231                val = val >> 8
7232            }
7233        }
7234    }
7235}
7236
7237
7238class BigUint64ArrayIteratorKeys implements IterableIterator<number> {
7239    private length: int = 0
7240    private idx: int = 0
7241
7242    constructor(parent: BigUint64Array) {
7243        this.length = parent.length as int
7244    }
7245
7246    public override $_iterator(): IterableIterator<Number> {
7247        return this
7248    }
7249
7250    override next(): IteratorResult<number> {
7251        if (this.idx < 0 || this.idx >= this.length) {
7252            return new IteratorResult<number>()
7253        }
7254        return new IteratorResult<number>(false, this.idx++ as number)
7255    }
7256}
7257
7258class BigUint64ArrayIterator implements IterableIterator<BigInt> {
7259    private parent: BigUint64Array
7260    private idx: int = 0
7261
7262    constructor(parent: BigUint64Array) {
7263        this.parent = parent
7264    }
7265
7266    public override $_iterator(): IterableIterator<BigInt> {
7267        return this
7268    }
7269
7270    override next(): IteratorResult<BigInt> {
7271        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
7272            return new IteratorResult<BigInt>()
7273        }
7274        return new IteratorResult<BigInt>(false, new BigInt(this.parent[this.idx++]))
7275    }
7276}
7277
7278class BigUint64ArrayIteratorEntries implements IterableIterator<[Number, BigInt]> {
7279    private parent: BigUint64Array
7280    private idx: int = 0
7281
7282    constructor(parent: BigUint64Array) {
7283        this.parent = parent
7284    }
7285
7286    public override $_iterator(): IterableIterator<[Number, BigInt]> {
7287        return this
7288    }
7289
7290    override next(): IteratorResult<[Number, BigInt]> {
7291        if (this.idx < 0 || this.idx >= this.parent.lengthInt) {
7292            return new IteratorResult<[Number, BigInt]>()
7293        }
7294        return new IteratorResult<[Number, BigInt]>(
7295            false,
7296            [new Number(this.idx), new BigInt(this.parent[this.idx++])] as [Number, BigInt]
7297        )
7298    }
7299}
7300
7301/**
7302 * JS BigUint64Array API-compatible class
7303 */
7304export final class BigUint64Array implements Iterable<BigInt>, ArrayLike<BigInt> {
7305    public static readonly BYTES_PER_ELEMENT: number = 8
7306    public readonly BYTES_PER_ELEMENT: number = BigUint64Array.BYTES_PER_ELEMENT
7307
7308    /** Underlying Buffer */
7309    public readonly buffer: ArrayBuffer
7310
7311    internal readonly byteOffsetInt: int
7312    internal readonly byteLengthInt: int
7313    internal readonly lengthInt: int
7314
7315    /**
7316     * Creates an empty BigUint64Array.
7317     */
7318    public constructor() {
7319        this(0 as int)
7320    }
7321
7322    /**
7323     * Creates an BigUint64Array with respect to data accessed via Iterable<Number> interface
7324     */
7325    public constructor(elements: Iterable<BigInt>) {
7326        const items: Object = elements as Object
7327        if (items instanceof ArrayLike) {
7328            const arr = Types.identity_cast<BigInt>(items as ArrayLike<BigInt>)
7329            this.byteLengthInt = arr.length as int * BigUint64Array.BYTES_PER_ELEMENT as int
7330            this.lengthInt = arr.length as int
7331            this.buffer = new ArrayBuffer(this.byteLengthInt)
7332            this.byteOffsetInt = 0
7333            for (let i: int = 0; i < this.lengthInt; ++i) {
7334                this.setUnsafeClamp(i, arr.$_get(i).getULong())
7335            }
7336        } else {
7337            let x = BigUint64Array.from(elements)
7338            this.byteLengthInt = x.byteLengthInt
7339            this.lengthInt = x.lengthInt
7340            this.buffer = x.buffer
7341            this.byteOffsetInt = x.byteOffsetInt
7342        }
7343    }
7344
7345    /**
7346     * Creates an BigUint64Array with respect to data, byteOffset and length.
7347     *
7348     * @param buf data initializer
7349     *
7350     * @param byteOffset byte offset from begin of the buf
7351     *
7352     * @param length size of elements of type long in newly created BigUint64Array
7353     */
7354    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined, length: Number | undefined) {
7355        let intByteOffset: int = 0
7356        if (byteOffset != undefined) {
7357            intByteOffset = byteOffset.toInt()
7358            if (intByteOffset < 0) {
7359                throw new RangeError("Range Error: byteOffset " + intByteOffset + " is outside the bounds of the buffer")
7360            }
7361        }
7362        let intByteLength: int = buf.getByteLength() - intByteOffset
7363        if (intByteLength < 0) {
7364            throw new RangeError("Range Error: byteLength " + intByteLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
7365        }
7366
7367        if (intByteLength % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
7368            throw new RangeError("ArrayBuffer.byteLength should be multiple of 8 as BigUint64Array.BYTES_PER_ELEMENT")
7369        }
7370        if (intByteOffset % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
7371            throw new RangeError("byteOffset should be multiple of 8 as BigUint64Array.BYTES_PER_ELEMENT")
7372        }
7373
7374        let intLength: int
7375        if (length != undefined) {
7376            intLength = length.toInt()
7377            if (intLength > intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int) {
7378                throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer with byteOffset " + intByteOffset)
7379            }
7380        } else {
7381            intLength = intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int
7382        }
7383        if (intLength < 0) {
7384            throw new RangeError("Range Error: length " + intLength + " is outside the bounds of the buffer")
7385        }
7386        if (intLength < intByteLength / BigUint64Array.BYTES_PER_ELEMENT as int) {
7387            intByteLength = intLength * BigUint64Array.BYTES_PER_ELEMENT as int
7388        }
7389        this.byteLengthInt = intByteLength
7390        this.byteOffsetInt = intByteOffset
7391        this.lengthInt = intLength
7392        this.buffer = buf
7393    }
7394
7395    /**
7396     * Creates an BigUint64Array with respect to data, byteOffset and length.
7397     *
7398     * @param buf data initializer
7399     *
7400     * @param byteOffset byte offset from begin of the buf
7401     */
7402    public constructor(buf: ArrayBuffer, byteOffset: Number | undefined) {
7403        this(buf, byteOffset, undefined)
7404    }
7405
7406    /**
7407     * Creates an BigUint64Array with respect to data, byteOffset and length.
7408     *
7409     * @param buf data initializer
7410     *
7411     * @param byteOffset byte offset from begin of the buf
7412     *
7413     * @param length size of elements of type long in newly created BigUint64Array
7414     */
7415    public constructor(buf: ArrayBuffer, byteOffset: number, length: number) {
7416        this(buf, new Number(byteOffset), new Number(length))
7417    }
7418
7419    /**
7420     * Creates an BigUint64Array with respect to buf and byteOffset.
7421     *
7422     * @param buf data initializer
7423     *
7424     * @param byteOffset byte offset from begin of the buf
7425     */
7426    public constructor(buf: ArrayBuffer, byteOffset: number) {
7427        this(buf, new Number(byteOffset), undefined)
7428    }
7429
7430    /**
7431     * Creates an BigUint64Array with respect to data, byteOffset and length.
7432     *
7433     * @param buf data initializer
7434     *
7435     * @param byteOffset byte offset from begin of the buf
7436     *
7437     * @param length size of elements of type long in newly created BigUint64Array
7438     */
7439    public constructor(buf: ArrayBuffer, byteOffset: int, length: int) {
7440        this(buf, new Number(byteOffset), new Number(length))
7441    }
7442
7443    /**
7444     * Creates an BigUint64Array with respect to buf and byteOffset.
7445     *
7446     * @param buf data initializer
7447     *
7448     * @param byteOffset byte offset from begin of the buf
7449     */
7450    public constructor(buf: ArrayBuffer, byteOffset: int) {
7451        this(buf, new Number(byteOffset), undefined)
7452    }
7453
7454    /**
7455     * Creates an BigUint64Array with respect to buf.
7456     *
7457     * @param buf data initializer
7458     */
7459    public constructor(buf: ArrayLike<Number> | ArrayBuffer) {
7460        if (buf instanceof ArrayBuffer) {
7461            this.byteLengthInt = (buf as ArrayBuffer).getByteLength()
7462            if (this.byteLengthInt % BigUint64Array.BYTES_PER_ELEMENT as int != 0) {
7463               throw new RangeError("ArrayBuffer.byteLength should be multiple of long as BigUint64Array.BYTES_PER_ELEMENT")
7464            }
7465            this.lengthInt = this.byteLengthInt / BigUint64Array.BYTES_PER_ELEMENT as int
7466            this.buffer = buf as ArrayBuffer
7467            this.byteOffsetInt = 0
7468        } else if (buf instanceof ArrayLike) {
7469            // NOTE (ikorobkov): dealing with this overload is tricky
7470            // with banned `instanceof` generic, so it is delegated to array here. Initial idea from Set.ets
7471            let arr = Array.from<Number>((buf as ArrayLike<Number>))
7472            this.byteLengthInt = arr.length as int * BigUint64Array.BYTES_PER_ELEMENT as int
7473            this.lengthInt = arr.length as int
7474            this.buffer = new ArrayBuffer(this.byteLengthInt)
7475            this.byteOffsetInt = 0
7476            for (let i: int = 0; i < this.lengthInt; ++i) {
7477                this.setUnsafe(i, arr.$_get(i).toLong())
7478            }
7479        } else {
7480            throw new Error("unexpected type of buf")
7481        }
7482    }
7483
7484    /**
7485     * Creates an BigUint64Array with respect to length.
7486     *
7487     * @param length data initializer
7488     */
7489    public constructor(length: int) {
7490        this(length as number)
7491    }
7492
7493    /**
7494     * Creates an BigUint64Array with respect to length.
7495     *
7496     * @param length data initializer
7497     */
7498    public constructor(length: number) {
7499        if (length < 0 || length > (Int.MAX_VALUE / BigUint64Array.BYTES_PER_ELEMENT)) {
7500            throw new TypeError("Type Error: length " + length + " is outside the bounds of the buffer")
7501        }
7502        this.lengthInt = length as int
7503        this.byteLengthInt = this.lengthInt * BigUint64Array.BYTES_PER_ELEMENT as int
7504        this.byteOffsetInt = 0
7505        this.buffer = new ArrayBuffer(this.byteLengthInt)
7506    }
7507
7508    /**
7509     * Creates a copy of BigUint64Array.
7510     *
7511     * @param other data initializer
7512     */
7513    public constructor(other: BigUint64Array) {
7514        this.buffer = other.buffer.slice(other.byteOffset as int, (other.byteOffset + other.byteLength) as int) as ArrayBuffer
7515        this.byteLengthInt = other.byteLength as int
7516        this.lengthInt = other.length as int
7517        this.byteOffsetInt = 0
7518    }
7519
7520    /**
7521     * Creates an BigUint64Array from FixedArray<number>
7522     */
7523    public constructor(numbers: FixedArray<number>) {
7524        this(numbers.length)
7525        for (let i: int = 0; i < this.lengthInt; ++i) {
7526            this.setUnsafeClamp(i, new BigInt(numbers[i]).getULong())
7527        }
7528    }
7529
7530    /**
7531     * Creates an BigUint64Array from FixedArray<int>
7532     */
7533    public constructor(numbers: FixedArray<int>) {
7534        this(numbers.length)
7535        for (let i: int = 0; i < this.lengthInt; ++i) {
7536            this.setUnsafeClamp(i, new BigInt(numbers[i]).getULong())
7537        }
7538    }
7539
7540    /**
7541     * Creates an BigUint64Array from FixedArray<bigint>
7542     */
7543    public constructor(numbers: FixedArray<bigint>) {
7544        this(numbers.length)
7545        for (let i: int = 0; i < this.lengthInt; ++i) {
7546            this.setUnsafe(i, numbers[i].getULong())
7547        }
7548    }
7549
7550    /**
7551     * Iteratorable interface implementation
7552     *
7553     * @returns iterator over all elements
7554     */
7555    public override $_iterator(): IterableIterator<BigInt> {
7556         return this.values()
7557    }
7558
7559    /**
7560     * Returns an instance of primitive type at passed index.
7561     *
7562     * @param index index to look at
7563     *
7564     * @returns a primitive at index
7565     */
7566    public at(index: number): BigInt | undefined {
7567        return this.at(index as int)
7568    }
7569
7570    /**
7571     * Returns an instance of primitive type at passed index if index is correct.
7572     *
7573     * @param index index to look at
7574     *
7575     * @returns a primitive at index
7576     */
7577    public at(index: int): BigInt | undefined {
7578        let k: int
7579        if (index >= 0) {
7580            k = index
7581        } else {
7582            k = this.lengthInt + index
7583        }
7584        if (k < 0 || k >= this.lengthInt) {
7585            return undefined
7586        }
7587        return BigInt.fromULong(this.getUnsafe(k))
7588    }
7589
7590    /**
7591     * Returns an instance of BigInt at passed index.
7592     *
7593     * @param index index to look at
7594     *
7595     * @returns a primitive at index
7596     */
7597    public override $_get(index: number): BigInt {
7598        return this.$_get(index as int) as BigInt
7599    }
7600
7601    /**
7602     * Returns an instance of BigInt at passed index.
7603     *
7604     * @param index index to look at
7605     *
7606     * @returns a primitive at index
7607     */
7608    public $_get(i: int): BigInt {
7609        return BigInt.fromULong(this.getLong(i))
7610    }
7611    private native getLong(i: int): long
7612
7613    /**
7614     * Assigns val as element on index.
7615     *
7616     * @param val value to set
7617     *
7618     * @param index index to change
7619     */
7620    public $_set(index: number, val: BigInt): void {
7621        this.$_set(index as int, val)
7622    }
7623
7624    /**
7625     * Assigns val as element on index.
7626     *
7627     * @param val value to set
7628     *
7629     * @param index index to change
7630     */
7631    public $_set(index: int, val: BigInt): void {
7632        this.$_set(index, val.getULong())
7633    }
7634
7635    /**
7636     * Assigns val as element on index.
7637     *
7638     * @param val value to set
7639     *
7640     * @param index index to change
7641     */
7642    public $_set(index: number, val: long): void {
7643        this.$_set(index as int, val)
7644    }
7645
7646    /**
7647     * Assigns val as element on index.
7648     *
7649     * @param val value to set
7650     *
7651     * @param index index to change
7652     */
7653    public native $_set(index: int, val: long): void
7654
7655    /**
7656     * Assigns val as element on index.
7657     *
7658     * @param val value to set
7659     *
7660     * @param index index to change
7661     */
7662    public $_set(index: number, val: int): void {
7663        this.$_set(index as int, val as int)
7664    }
7665
7666    /**
7667     * Assigns val as element on index.
7668     *
7669     * @param val value to set
7670     *
7671     * @param index index to change
7672     */
7673    public native $_set(index: int, val: int): void
7674
7675    /**
7676     * Makes a copy of internal elements to targetPos from startPos to endPos.
7677     *
7678     * @param target insert index to place copied elements
7679     *
7680     * @param start start index to begin copy from
7681     *
7682     * @param end last index to end copy from, excluded
7683     *
7684     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
7685     */
7686    public copyWithin(target: number, start: number, end?: number): BigUint64Array {
7687        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
7688    }
7689
7690    /**
7691     * Makes a copy of internal elements to targetPos from startPos to endPos.
7692     *
7693     * @param target insert index to place copied elements
7694     *
7695     * @param start start index to begin copy from
7696     *
7697     * @param end last index to end copy from, excluded
7698     *
7699     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
7700     */
7701    public copyWithin(target: int, start: number, end?: number): BigUint64Array {
7702        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
7703    }
7704
7705    /**
7706     * Makes a copy of internal elements to targetPos from startPos to endPos.
7707     *
7708     * @param target insert index to place copied elements
7709     *
7710     * @param start start index to begin copy from
7711     *
7712     * @param end last index to end copy from, excluded
7713     *
7714     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
7715     */
7716    public copyWithin(target: number, start: int, end?: number): BigUint64Array {
7717        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
7718    }
7719
7720    /**
7721     * Makes a copy of internal elements to targetPos from startPos to endPos.
7722     *
7723     * @param target insert index to place copied elements
7724     *
7725     * @param start start index to begin copy from
7726     *
7727     * @param end last index to end copy from, excluded
7728     *
7729     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
7730     */
7731    public copyWithin(target: int, start: int, end?: number): BigUint64Array {
7732        return this.copyWithin(target as int, start as int, asIntOrDefault(end, this.lengthInt))
7733    }
7734
7735    /**
7736     * Makes a copy of internal elements to targetPos from startPos to endPos.
7737     *
7738     * @param insert insert index to place copied elements
7739     *
7740     * @param start start index to begin copy from
7741     *
7742     * @param end last index to end copy from, excluded
7743     *
7744     * See rules of parameters normalization on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin | MDN}
7745     */
7746    public native copyWithin(target: int, start: int, end: int): BigUint64Array
7747
7748    /**
7749     * Makes a copy of internal elements to targetPos from begin to end of BigUint64Array.
7750     *
7751     * @param target insert index to place copied elements
7752     *
7753     * See rules of parameters normalization:
7754     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
7755     */
7756    public copyWithin(target: number): BigUint64Array {
7757        return this.copyWithin(target as int)
7758    }
7759
7760    /**
7761     * Makes a copy of internal elements to targetPos from begin to end of BigUint64Array.
7762     *
7763     * @param insert insert index to place copied elements
7764     *
7765     * See rules of parameters normalization:
7766     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin}
7767     */
7768    public copyWithin(target: int): BigUint64Array {
7769        return this.copyWithin(target, 0, this.lengthInt)
7770    }
7771
7772    /**
7773     * Returns an array of key, value pairs for every entry in the BigUint64Array
7774     *
7775     * @returns key, value pairs for every entry in the array
7776     */
7777    public entries(): IterableIterator<[Number, BigInt]> {
7778        return new BigUint64ArrayIteratorEntries(this)
7779    }
7780
7781    /**
7782     * Fills the BigUint64Array with specified value
7783     *
7784     * @param value new value
7785     *
7786     * @returns modified BigUint64Array
7787     */
7788    public fill(value: BigInt, start?: number, end?: number): BigUint64Array {
7789        this.fill(value.getULong(), asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
7790        return this
7791    }
7792
7793    /**
7794     * Fills the BigUint64Array with specified value
7795     *
7796     * @param value new value
7797     *
7798     * @returns modified BigUint64Array
7799     */
7800    public fill(value: BigInt, start: int, end?: number): BigUint64Array {
7801        this.fill(value.getULong(), start as int, asIntOrDefault(end, this.lengthInt))
7802        return this
7803    }
7804
7805    /**
7806     * Fills the BigUint64Array with specified value
7807     *
7808     * @param value new value
7809     *
7810     * @returns modified BigUint64Array
7811     */
7812    public fill(value: BigInt, start: int, end: number): BigUint64Array {
7813        this.fill(value.getULong(), start as int, end as int)
7814        return this
7815    }
7816
7817    /**
7818     * Fills the BigUint64Array with specified value
7819     *
7820     * @param value new value
7821     *
7822     * @returns modified BigUint64Array
7823     */
7824    public fill(value: BigInt, start: number, end: int): BigUint64Array {
7825        this.fill(value.getULong(), start as int, end as int)
7826        return this
7827    }
7828
7829    /**
7830     * Fills the BigUint64Array with specified value
7831     *
7832     * @param value new value
7833     *
7834     * @returns modified BigUint64Array
7835     */
7836    public fill(value: BigInt, start: int, end: int): BigUint64Array {
7837        this.fill(value.getULong(), start as int, end as int)
7838        return this
7839    }
7840
7841    /**
7842     * Fills the BigUint64Array with specified value
7843     *
7844     * @param value new value
7845     *
7846     * @returns modified BigUint64Array
7847     */
7848    public fill(value: long, start?: number, end?: number): BigUint64Array {
7849        this.fill(value, asIntOrDefault(start, 0 as int), asIntOrDefault(end, this.lengthInt))
7850        return this
7851    }
7852
7853    /**
7854     * Fills the BigUint64Array with specified value
7855     *
7856     * @param value new value
7857     *
7858     * @returns modified BigUint64Array
7859     */
7860    public fill(value: long, start: int, end?: number): BigUint64Array {
7861        this.fill(value, start as int, asIntOrDefault(end, this.lengthInt))
7862        return this
7863    }
7864
7865    /**
7866     * Fills the BigUint64Array with specified value
7867     *
7868     * @param value new value
7869     *
7870     * @returns modified BigUint64Array
7871     */
7872    public fill(value: long, start: int, end: number): BigUint64Array {
7873        this.fill(value, start as int, end as int)
7874        return this
7875    }
7876
7877    /**
7878     * Fills the BigUint64Array with specified value
7879     *
7880     * @param value new value
7881     *
7882     * @returns modified BigUint64Array
7883     */
7884    public fill(value: long, start: number, end: int): BigUint64Array {
7885        this.fill(value, start as int, end as int)
7886        return this
7887    }
7888
7889    /**
7890     * Fills the BigUint64Array with specified value
7891     *
7892     * @param value new value
7893     *
7894     * @returns modified BigUint64Array
7895     */
7896    public fill(value: long, start: int, end: int): BigUint64Array {
7897        const k = normalizeIndex(start, this.lengthInt)
7898        const finalPos = normalizeIndex(end, this.lengthInt)
7899        this.fillInternal(value, k, finalPos)
7900        return this
7901    }
7902
7903    private final native fillInternal(value: long, start: int, end: int): void
7904
7905    /**
7906     * Assigns val as element on index.
7907     *
7908     * @param val value to set
7909     *
7910     * @param index index to change
7911     */
7912    public set(insertPos: number, val: BigInt): void {
7913        this.$_set(insertPos as int, val)
7914    }
7915
7916    /**
7917     * Assigns val as element on index.
7918     *
7919     * @param val value to set
7920     *
7921     * @param index index to change
7922     */
7923    public set(insertPos: int, val: BigInt): void {
7924        this.$_set(insertPos as int, val)
7925    }
7926
7927    /**
7928     * Assigns val as element on index.
7929     *
7930     * @param val value to set
7931     *
7932     * @param index index to change
7933     */
7934    public set(insertPos: number, val: long): void {
7935        this.$_set(insertPos as int, val)
7936    }
7937
7938    /**
7939     * Assigns val as element on index.
7940     *
7941     * @param val value to set
7942     *
7943     * @param index index to change
7944     */
7945    public set(insertPos: int, val: long): void {
7946        this.$_set(insertPos as int, val)
7947    }
7948
7949    /**
7950     * Copies all elements of arr to the current BigUint64Array starting from insertPos.
7951     *
7952     * @param arr array to copy data from
7953     *
7954     * @param insertPos start index where data from arr will be inserted
7955     *
7956     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
7957     */
7958    public set(arr: FixedArray<BigInt>, insertPos1: number): void {
7959        const insertPos = insertPos1 as int
7960        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
7961            throw new RangeError("set(insertPos: int, arr: FixedArray<long>): size of arr is greater than BigUint64Array.length")
7962        }
7963        for (let i = 0; i < arr.length; i++) {
7964            this.setUnsafeClamp(insertPos as int + i as int, arr[i].getULong())
7965        }
7966    }
7967
7968    /**
7969     * Copies all elements of arr to the current BigUint64Array starting from insertPos.
7970     *
7971     * @param arr array to copy data from
7972     *
7973     * @param insertPos start index where data from arr will be inserted
7974     *
7975     * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set}
7976     */
7977    public set(arr: FixedArray<long>, insertPos: int): void {
7978        if (insertPos < 0 || insertPos + arr.length > this.lengthInt) {
7979            throw new RangeError("set(insertPos: int, arr: FixedArray<long>): size of arr is greater than BigUint64Array.length")
7980        }
7981        for (let i = 0; i < arr.length; i++) {
7982            this.setUnsafeClamp(insertPos + i, arr[i])
7983        }
7984    }
7985
7986    /**
7987     * Copies all elements of arr to the current BigUint64Array.
7988     *
7989     * @param arr array to copy data from
7990     */
7991    public set(arr: FixedArray<BigInt>): void {
7992        this.set(arr, 0)
7993    }
7994
7995    /**
7996     * Copies all elements of arr to the current BigUint64Array.
7997     *
7998     * @param arr array to copy data from
7999     */
8000    public set(arr: FixedArray<long>): void {
8001        this.set(arr, 0)
8002    }
8003
8004    public native set(array: BigUint64Array): void
8005
8006    public native set(array: BigUint64Array, offset: number): void
8007
8008    /**
8009     * Copies elements from an ArrayLike object to the BigUint64Array.
8010     *
8011     * @param array An ArrayLike object containing the elements to copy.
8012     *
8013     * @param offset Optional. The offset into the target array at which to begin writing values from the source array
8014     */
8015    public set(array: ArrayLike<BigInt>, offset: number = 0): void {
8016        const insertPos = offset as int
8017        if (insertPos < 0 || insertPos + array.length > this.lengthInt) {
8018            throw new RangeError("offset is out of bounds")
8019        }
8020        for (let i = array.length - 1; i >= 0; --i) {
8021            this.setUnsafeClamp(insertPos as int + i as int, array[i].getULong())
8022        }
8023    }
8024
8025    /**
8026     * Returns a new array from a set of elements.
8027     *
8028     * @param items a set of elements to include in the new array object.
8029     *
8030     * @returns new BigUint64Array
8031     */
8032    public static of(...items: FixedArray<number>): BigUint64Array {
8033        let res = new BigUint64Array(items.length as int)
8034        for (let i: int = 0; i < items.length; i++) {
8035            res.setUnsafeClamp(i, (new BigInt(items[i])).getULong())
8036        }
8037        return res
8038    }
8039
8040    /**
8041     * Returns a new array from a set of elements.
8042     *
8043     * @param items a set of elements to include in the new array object.
8044     *
8045     * @returns new BigUint64Array
8046     */
8047    public static of(...items: FixedArray<int>): BigUint64Array {
8048        let res = new BigUint64Array(items.length as int)
8049        for (let i: int = 0; i < items.length; i++) {
8050            res.setUnsafeClamp(i, items[i] as long)
8051        }
8052        return res
8053    }
8054
8055    /**
8056     * Returns a new array from a set of elements.
8057     *
8058     * @param items a set of elements to include in the new array object.
8059     *
8060     * @returns new BigUint64Array
8061     */
8062    public static of(...items: FixedArray<long>): BigUint64Array {
8063        let res = new BigUint64Array(items.length as int)
8064        for (let i: int = 0; i < items.length; i++) {
8065            res.setUnsafeClamp(i, items[i])
8066        }
8067        return res
8068    }
8069
8070    /**
8071     * Returns a new array from a set of elements.
8072     *
8073     * @param items a set of elements to include in the new array object.
8074     *
8075     * @returns new BigUint64Array
8076     */
8077    public static of(...items: FixedArray<bigint>): BigUint64Array {
8078        let res = new BigUint64Array(items.length as int)
8079        for (let i: int = 0; i < items.length; i++) {
8080            res.setUnsafeClamp(i, items[i].getULong())
8081        }
8082        return res
8083    }
8084
8085    /**
8086     * Returns a new array from a set of elements.
8087     *
8088     * @param items a set of elements to include in the new array object.
8089     *
8090     * @returns new BigUint64Array
8091     */
8092    public static of(): BigUint64Array {
8093        return new BigUint64Array(0 as int)
8094    }
8095
8096    /**
8097     * Creates an array from an array-like or iterable object.
8098     *
8099     * @param arrayLike An array-like or iterable object to convert to an array.
8100     *
8101     * @returns new BigUint64Array
8102     */
8103    public static from(arr: ArrayLike<BigInt>): BigUint64Array {
8104        throw new Error("BigUint64Array.from: not implemented")
8105    }
8106
8107    /**
8108     * Creates an array from an array-like or iterable object.
8109     *
8110     * @param arrayLike An array-like or iterable object to convert to an array.
8111     *
8112     * @param mapfn A mapping function to call on every element of the array.
8113     *
8114     * @returns new BigUint64Array
8115     */
8116    public static from(arrayLike: Iterable<BigInt>, mapfn?: (v: BigInt, k: number) => BigInt): BigUint64Array {
8117        if (mapfn == undefined) {
8118            mapfn = (v: BigInt, k: number): BigInt => { return v }
8119        }
8120
8121        let iter = arrayLike.$_iterator()
8122        // NOTE (templin.konstantin): This code section is responsible for optimizing for some types
8123        //  of iterators that we can learn the length of (e.g. ArrayValuesIterator).
8124        //  We are trying to use "reflection" to find the "__Iterator_getLength" method and if it exists,
8125        //  we can make one pass through the iterator without the need for memory reallocation.
8126        const maybeLength = tryGetIteratorLength(arrayLike)
8127        if (maybeLength) {
8128            const result = new BigUint64Array(maybeLength)
8129            for (let i = 0; i < maybeLength; ++i) {
8130                const x = iter.next()
8131                if (x.done) {
8132                    return new BigUint64Array(result.buffer, 0, i)
8133                }
8134                result.setUnsafeClamp(i, ((mapfn)!(x.value!, i)).getULong())
8135            }
8136            return result
8137        }
8138
8139        // NOTE (templin.konstantin): Create builtin array as buffer
8140        let temp = new BigUint64Array(6)
8141        let index : FixedArray<int> = new int[1]
8142        index[0] = 0
8143
8144        iteratorForEach<BigInt>(arrayLike.$_iterator(), (x: BigInt): void => {
8145            if (index[0] + 1 > temp.lengthInt) {
8146                // NOTE (templin.konstantin): Progressive reallocation
8147                const curLength = (temp.buffer as Buffer).getByteLength()
8148                const tb = new ArrayBuffer(curLength * 2)
8149                for (let i = 0; i < curLength; ++i) {
8150                    tb.set(i, (temp.buffer as Buffer).at(i))
8151                }
8152                temp = new BigUint64Array(tb)
8153            }
8154            temp.setUnsafeClamp(index[0], ((mapfn)!(x, index[0])).getULong())
8155            index[0]++
8156        })
8157
8158        return new BigUint64Array(temp.buffer, 0, index[0])
8159    }
8160
8161    /**
8162     * Creates an array from an array-like or iterable object.
8163     *
8164     * @param arrayLike An array-like or iterable object to convert to an array.
8165     *
8166     * @param mapfn A mapping function to call on every element of the array.
8167     *
8168     * @returns new BigUint64Array
8169     */
8170    public static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => BigInt): BigUint64Array {
8171        let res = new BigUint64Array(arrayLike.length)
8172        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
8173        const idx : FixedArray<int> = new int[1]
8174        idx[0] = 0
8175        iteratorForEach<T>(arrayLike.$_iterator(), (x: T): void => {
8176            res.setUnsafeClamp(idx[0], (mapfn(x as T, idx[0] as number)).getULong())
8177            idx[0] += 1
8178        })
8179        return res
8180    }
8181
8182    /**
8183     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
8184     *
8185     * @param searchElement The element to search for
8186     *
8187     * @param fromIndex The position in this array at which to begin searching for searchElement
8188     *
8189     * @returns true if searchElement is in BigUint64Array, false otherwise
8190     */
8191    public includes(searchElement: BigInt, fromIndex?: number): boolean {
8192        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0)) != -1
8193    }
8194
8195    /**
8196     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
8197     *
8198     * @param searchElement The element to search for
8199     *
8200     * @param fromIndex The position in this array at which to begin searching for searchElement
8201     *
8202     * @returns true if searchElement is in BigUint64Array, false otherwise
8203     */
8204    public includes(searchElement: long, fromIndex: int): boolean {
8205        return this.indexOf(searchElement as int, fromIndex) != -1
8206    }
8207
8208    /**
8209     * Determines whether BigUint64Array includes a certain element, returning true or false as appropriate
8210     *
8211     * @param searchElement The element to search for
8212     *
8213     * @param fromIndex The position in this array at which to begin searching for searchElement
8214     *
8215     * @returns true if searchElement is in BigUint64Array, false otherwise
8216     */
8217    public includes(searchElement: long): boolean {
8218        return this.indexOf(searchElement as int, 0) != -1
8219    }
8220
8221    /**
8222     * Returns the index of the first occurrence of a value in BigUint64Array.
8223     *
8224     * @param searchElement The value to locate in the array.
8225     *
8226     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8227     *  search starts at index 0.
8228     *
8229     * @returns index of element if it presents, -1 otherwise
8230     */
8231    public indexOf(searchElement: BigInt, fromIndex?: number): number {
8232        return this.indexOf(searchElement, asIntOrDefault(fromIndex, 0))
8233    }
8234
8235    /**
8236     * Returns the index of the first occurrence of a value in BigUint64Array.
8237     *
8238     * @param searchElement The value to locate in the array.
8239     *
8240     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8241     *  search starts at index 0.
8242     *
8243     * @returns index of element if it presents, -1 otherwise
8244     */
8245    public indexOf(searchElement: BigInt, fromIndex: int): number {
8246            return this.indexOfImpl(searchElement.getLong(), fromIndex)
8247    }
8248
8249    /**
8250     * Returns the index of the first occurrence of a value in BigUint64Array.
8251     *
8252     * @param searchElement The value to locate in the array.
8253     *
8254     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8255     *  search starts at index 0.
8256     *
8257     * @returns index of element if it presents, -1 otherwise
8258     */
8259    public indexOf(searchElement: int, fromIndex: int): number {
8260        return this.indexOfImpl(searchElement as long, fromIndex)
8261    }
8262
8263    /**
8264     * Returns the index of the first occurrence of a value in Array.
8265     *
8266     * @param searchElement The value to locate in the array.
8267     *
8268     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8269     *  search starts at index 0.
8270     *
8271     * @returns index of element if it presents, -1 otherwise
8272     */
8273    private final native indexOfImpl(searchElement: number, fromIndex: int): number
8274
8275    /**
8276     * Returns the index of the first occurrence of a value in Array.
8277     *
8278     * @param searchElement The value to locate in the array.
8279     *
8280     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8281     *  search starts at index 0.
8282     *
8283     * @returns index of element if it presents, -1 otherwise
8284     */
8285    private final native indexOfImpl(searchElement: long, fromIndex: int): number
8286
8287    /**
8288     * Returns the index of the first occurrence of a value in BigUint64Array.
8289     *
8290     * @param searchElement The value to locate in the array.
8291     *
8292     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8293     *  search starts at index 0.
8294     *
8295     * @returns index of element if it presents, -1 otherwise
8296     */
8297    public indexOf(searchElement: int): number {
8298        return this.indexOf(searchElement, 0)
8299    }
8300
8301
8302    /**
8303     * Converts all elements of an array to strings and joins them using the specified separator.
8304     *
8305     * @param separator - separates one element of an array from the next in the resulting String.
8306     *
8307     * @returns joined representation
8308     */
8309    private final native joinInternal(separator: String): string;
8310
8311    /**
8312     * Adds all the elements of an array separated by the specified separator string
8313     *
8314     * @param separator A string used to separate one element of an array from the next in the
8315     * resulting String. If omitted, the array elements are separated with a comma
8316     *
8317     * @returns joined representation
8318     */
8319    public join(separator?: String): string {
8320        if (separator == undefined) {
8321            return this.joinInternal(",")
8322        }
8323        return this.joinInternal(separator)
8324    }
8325
8326    /**
8327     * Returns an list of keys in BigUint64Array
8328     *
8329     * @returns iterator over keys
8330     */
8331    public keys(): IterableIterator<number> {
8332        return new BigUint64ArrayIteratorKeys(this)
8333    }
8334
8335    /**
8336     * Returns the index of the last occurrence of a value in BigUint64Array.
8337     *
8338     * @param searchElement The value to locate in the array.
8339     *
8340     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8341     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8342     *
8343     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8344     */
8345    public lastIndexOf(searchElement: BigInt, fromIndex: number|undefined): number {
8346        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0))
8347    }
8348
8349    /**
8350     * Returns the index of the last occurrence of a value in BigUint64Array.
8351     *
8352     * @param searchElement The value to locate in the array.
8353     *
8354     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8355     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8356     *
8357     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8358     */
8359    public lastIndexOf(searchElement: BigInt): number {
8360        return this.lastIndexOf(searchElement, this.lengthInt - 1)
8361    }
8362
8363    /**
8364     * Returns the index of the last occurrence of a value in BigUint64Array.
8365     *
8366     * @param searchElement The value to locate in the array.
8367     *
8368     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8369     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8370     *
8371     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8372     */
8373    public lastIndexOf(searchElement: BigInt, fromIndex: int): number {
8374            return this.lastIndexOfImpl(searchElement.getLong(), fromIndex)
8375    }
8376
8377    /**
8378     * Returns the index of the last occurrence of a value in BigUint64Array.
8379     *
8380     * @param searchElement The value to locate in the array.
8381     *
8382     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8383     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8384     *
8385     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8386     */
8387    public lastIndexOf(searchElement: int, fromIndex: int): number {
8388        return this.lastIndexOfImpl(searchElement as long, fromIndex)
8389    }
8390
8391    /**
8392     * Returns the index of the first occurrence of a value in Array.
8393     *
8394     * @param searchElement The value to locate in the array.
8395     *
8396     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8397     *  search starts at index 0.
8398     *
8399     * @returns index of element if it presents, -1 otherwise
8400     */
8401    private final native lastIndexOfImpl(searchElement: number, fromIndex: int): number
8402
8403    /**
8404     * Returns the index of the first occurrence of a value in Array.
8405     *
8406     * @param searchElement The value to locate in the array.
8407     *
8408     * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
8409     *  search starts at index 0.
8410     *
8411     * @returns index of element if it presents, -1 otherwise
8412     */
8413    private final native lastIndexOfImpl(searchElement: long, fromIndex: int): number
8414
8415    /**
8416     * Returns the index of the last occurrence of a value in BigUint64Array.
8417     *
8418     * @param searchElement The value to locate in the array.
8419     *
8420     * @param fromIndex The array index at which to begin the search. If fromIndex is undefined, the
8421     * search starts at index 0. If fromIndex is ommited, the search begins at index length-1
8422     *
8423     * @returns right-most index of searchElement. It must be less or equal than fromIndex. -1 if not found
8424     */
8425    public lastIndexOf(searchElement: int): number {
8426        return this.lastIndexOf(searchElement, this.lengthInt - 1)
8427    }
8428
8429   /**
8430    * Creates a new BigUint64Array using initializer
8431    *
8432    * @param data initializer
8433    *
8434    * @returns a new BigUint64Array from data
8435    */
8436    public of(...data: FixedArray<BigInt>): BigUint64Array {
8437        throw new Error("BigUint64Array.of: not implemented")
8438    }
8439
8440    /**
8441     * Creates a new BigUint64Array using reversed data from the current one
8442     *
8443     * @returns a new BigUint64Array using reversed data from the current one
8444     */
8445    public native reverse(): BigUint64Array
8446
8447    /**
8448     * Creates a slice of current BigUint64Array using range [begin, end)
8449     *
8450     * @param begin start index to be taken into slice
8451     *
8452     * @param end last index to be taken into slice
8453     *
8454     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
8455     *
8456     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8457     */
8458    public slice(begin?: number, end?: number): BigUint64Array {
8459        return this.slice(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
8460    }
8461
8462    /**
8463     * Creates a slice of current BigUint64Array using range [begin, end)
8464     *
8465     * @param begin start index to be taken into slice
8466     *
8467     * @param end last index to be taken into slice
8468     *
8469     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
8470     *
8471     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8472     */
8473    public slice(begin: number, end: number): BigUint64Array {
8474        return this.slice(begin as int, end as int)
8475    }
8476
8477    /**
8478     * Creates a slice of current BigUint64Array using range [begin, end)
8479     *
8480     * @param begin start index to be taken into slice
8481     *
8482     * @param end last index to be taken into slice
8483     *
8484     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
8485     *
8486     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8487     */
8488    public slice(begin: number, end: int): BigUint64Array {
8489        return this.slice(begin as int, end as int)
8490    }
8491
8492    /**
8493     * Creates a slice of current BigUint64Array using range [begin, end)
8494     *
8495     * @param begin start index to be taken into slice
8496     *
8497     * @param end last index to be taken into slice
8498     *
8499     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
8500     *
8501     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8502     */
8503    public slice(begin: int, end: number): BigUint64Array {
8504        return this.slice(begin as int, end as int)
8505    }
8506
8507    /**
8508     * Creates a slice of current BigUint64Array using range [begin, end)
8509     *
8510     * @param begin start index to be taken into slice
8511     *
8512     * @param end last index to be taken into slice
8513     *
8514     * @returns a new BigUint64Array with elements of current BigUint64Array[begin;end) where end index is excluded
8515     *
8516     * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
8517     */
8518    public slice(begin: int, end: int): BigUint64Array {
8519        const len: int = this.lengthInt
8520        const relStart = normalizeIndex(begin, len)
8521        const relEnd = normalizeIndex(end, len)
8522        let count = relEnd - relStart
8523        if (count < 0) {
8524            count = 0
8525        }
8526        let buf = this.buffer.slice(relStart * BigUint64Array.BYTES_PER_ELEMENT as int, relEnd * BigUint64Array.BYTES_PER_ELEMENT as int) as ArrayBuffer
8527        return new BigUint64Array(buf)
8528    }
8529
8530    /**
8531     * Creates a slice of current BigUint64Array using range [begin, this.lengthInt).
8532     *
8533     * @param begin start index to be taken into slice
8534     *
8535     * @returns a new BigUint64Array with elements of current BigUint64Array[begin, this.lengthInt)
8536     */
8537    public slice(begin: number): BigUint64Array {
8538        return this.slice(begin as int)
8539    }
8540
8541    /**
8542     * Creates a slice of current BigUint64Array using range [begin, this.lengthInt).
8543     *
8544     * @param begin start index to be taken into slice
8545     *
8546     * @returns a new BigUint64Array with elements of current BigUint64Array[begin, this.lengthInt)
8547     */
8548    public slice(begin: int): BigUint64Array {
8549        return this.slice(begin, this.lengthInt)
8550    }
8551
8552    /**
8553     * Sorts in-place by numeric value in ascending order.
8554     *
8555     * @returns sorted Array
8556     */
8557    public native sort(): this;
8558
8559    /**
8560     * Sorts in-place
8561     *
8562     * @param compareFn comparator _  used to determine the order of the elements.
8563     * compareFn returns a negative value if first argument is less than second argument,
8564     * zero if they're equal and a positive value otherwise.
8565     *
8566     * @returns sorted BigUint64Array
8567     */
8568    public sort(compareFn?: (a: BigInt, b: BigInt) => number | BigInt): this {
8569        if (compareFn == undefined) {
8570            this.sort()
8571            return this
8572        }
8573        let arr: FixedArray<long> = new long[this.lengthInt]
8574        for (let i = 0; i < this.lengthInt; ++i) {
8575            arr[i] = this.getUnsafe(i)
8576        }
8577
8578        let cmp = (l: long, r: long): number => {
8579            const result = compareFn!(new BigInt(l), new BigInt(r))
8580            if (result instanceof BigInt) {
8581                return (result as BigInt).getLong()
8582            } else {
8583                return result as number
8584            }
8585        }
8586        const MAX_SHORT_LENGTH = 24
8587        if (arr.length > MAX_SHORT_LENGTH) {
8588            arr = mergeSort(arr, cmp)
8589        } else {
8590            sort(arr, cmp)
8591        }
8592        for (let i = 0; i < arr.length; ++i) {
8593            this.setUnsafe(i, arr[i])
8594        }
8595        return this
8596    }
8597
8598    /**
8599     * Creates a BigUint64Array with the same underlying Buffer
8600     *
8601     * @param begin start index, inclusive
8602     *
8603     * @param end last index, exclusive
8604     *
8605     * @returns new BigUint64Array with the same underlying Buffer
8606     */
8607    public subarray(begin?: number, end?: number): BigUint64Array {
8608        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
8609    }
8610
8611    /**
8612     * Creates a BigUint64Array with the same underlying Buffer
8613     *
8614     * @param begin start index, inclusive
8615     *
8616     * @param end last index, exclusive
8617     *
8618     * @returns new BigUint64Array with the same underlying Buffer
8619     */
8620    public subarray(begin: number, end: int): BigUint64Array {
8621        return this.subarray(begin as int, end as int)
8622    }
8623
8624    /**
8625     * Creates a BigUint64Array with the same underlying Buffer
8626     *
8627     * @param begin start index, inclusive
8628     *
8629     * @param end last index, exclusive
8630     *
8631     * @returns new BigUint64Array with the same underlying Buffer
8632     */
8633    public subarray(begin: int, end: number): BigUint64Array {
8634        return this.subarray(begin as int, end as int)
8635    }
8636
8637    /**
8638     * Creates a BigUint64Array with the same underlying Buffer
8639     *
8640     * @param begin start index, inclusive
8641     *
8642     * @param end last index, exclusive
8643     *
8644     * @returns new BigUint64Array with the same underlying Buffer
8645     */
8646    public subarray(begin: int, end: int | undefined = this.lengthInt): BigUint64Array {
8647        const len: int = this.lengthInt
8648        const relStart = normalizeIndex(begin, len)
8649        const relEnd = normalizeIndex(end ?? this.lengthInt, len)
8650        let count = relEnd - relStart
8651        if (count < 0) {
8652            count = 0
8653        }
8654        return new BigUint64Array(this.buffer, relStart * BigUint64Array.BYTES_PER_ELEMENT as int, count)
8655    }
8656
8657    /**
8658     * Converts BigUint64Array to a string with respect to locale
8659     *
8660     * @param locales
8661     *
8662     * @param options
8663     *
8664     * @returns string representation
8665     */
8666    public toLocaleString(locales: Object, options: Object): string {
8667        throw new Error("BigUint64Array.toLocaleString: not implemented")
8668    }
8669
8670    /**
8671     * Converts BigUint64Array to a string with respect to locale
8672     *
8673     * @param locales
8674     *
8675     * @returns string representation
8676     */
8677    public toLocaleString(locales: Object): string {
8678        return this.toLocaleString(new Object(), new Object())
8679    }
8680
8681    /**
8682     * Converts BigUint64Array to a string with respect to locale
8683     *
8684     * @returns string representation
8685     */
8686    public toLocaleString(): string {
8687        let res: StringBuilder = new StringBuilder("")
8688        for (let i = 0; i < this.lengthInt - 1; ++i) {
8689            res.append(new BigInt(this.getUnsafe(i)).toLocaleString())
8690            res.append(",")
8691        }
8692        if (this.lengthInt > 0) {
8693            res.append(new BigInt(this.getUnsafe(this.lengthInt - 1)).toLocaleString())
8694        }
8695        return res.toString()
8696    }
8697
8698    /**
8699     * Creates a reversed copy
8700     *
8701     * @returns a reversed copy
8702     */
8703    public final native toReversed(): BigUint64Array
8704
8705    /**
8706     * Creates a sorted copy
8707     *
8708     * @returns a sorted copy
8709     */
8710    public toSorted(): BigUint64Array {
8711        return new BigUint64Array(this).sort()
8712    }
8713
8714    /**
8715     * Returns a string representation of the BigUint64Array
8716     *
8717     * @returns a string representation of the BigUint64Array
8718     */
8719    public override toString(): string {
8720        return this.join(",")
8721    }
8722
8723    /**
8724     * Returns array values iterator
8725     *
8726     * @returns an iterator
8727     */
8728    public values(): IterableIterator<BigInt> {
8729         return new BigUint64ArrayIterator(this)
8730    }
8731
8732    /**
8733     * Creates a copy with replaced value on index
8734     *
8735     * @param index
8736     *
8737     * @param value
8738     *
8739     * @returns an BigUint64Array with replaced value on index
8740     */
8741    public with(index: number, value: BigInt): BigUint64Array {
8742        return this.with(index as int, value.getULong())
8743    }
8744
8745    /**
8746     * Creates a copy with replaced value on index
8747     *
8748     * @param index
8749     *
8750     * @param value
8751     *
8752     * @returns an BigUint64Array with replaced value on index
8753     */
8754    public with(index: int, value: long): BigUint64Array {
8755        let res = new BigUint64Array(this)
8756        res.setUnsafeClamp(index, value)
8757        return res
8758    }
8759
8760    /// === with element lambda functions ===
8761
8762    /**
8763     * Determines whether the specified callback function returns true for any element of an array.
8764     *
8765     * @param predicate A function that accepts three arguments.
8766     * The some method calls the predicate function for each element in the array
8767     * until the predicate returns a true or until the end of the array.
8768     *
8769     * @returns false unless predicate function returns true for an array element,
8770     * in which case true is immediately returned.
8771     */
8772    public some(predicate: (element: BigInt, index: number, array: BigUint64Array) => boolean): boolean {
8773        for (let i = 0; i < this.lengthInt; i++) {
8774            if (predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
8775                return true
8776            }
8777        }
8778        return false
8779    }
8780
8781    /**
8782     * Calls the specified callback function for all the elements in an array.
8783     * The return value of the callback function is the accumulated result,
8784     * and is provided as an argument in the next call to the callback function.
8785     *
8786     * @param callbackfn A function that accepts four arguments.
8787     * The reduce method calls the callbackfn function one time for each element in the array.
8788     *
8789     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
8790     * The first call to the callbackfn function provides this value as an argument.
8791     *
8792     * @returns The value that results from running the callback function to completion over the entire typed array.
8793     */
8794    public reduce<U = BigInt>(
8795                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => U,
8796                initialValue: U): U {
8797        let accumulatedValue = initialValue
8798        for (let i = 0; i < this.lengthInt; i++) {
8799            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
8800        }
8801        return accumulatedValue
8802    }
8803
8804    /**
8805     * Calls the specified callback function for all the elements in an array.
8806     * The return value of the callback function is the accumulated result,
8807     * and is provided as an argument in the next call to the callback function.
8808     *
8809     * @param callbackfn A function that accepts four arguments.
8810     * The reduce method calls the callbackfn function one time for each element in the array.
8811     * The first call to the callbackfn function provides array first element value as an argument
8812     *
8813     * @returns The value that results from running the callback function to completion over the entire typed array.
8814     * calling reduce method on an empty array without an initial value creates a TypeError
8815     */
8816    public reduce(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => BigInt): BigInt {
8817        if (this.lengthInt == 0) {
8818            throw new TypeError("Reduce of empty array with no initial value")
8819        }
8820
8821        let accumulatedValue = new BigInt(this.$_get(0))
8822        for (let i = 1; i < this.lengthInt; i++) {
8823            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
8824        }
8825        return accumulatedValue
8826    }
8827
8828    /**
8829     * Calls the specified callback function for all the elements in an array, in descending order.
8830     * The return value of the callback function is the accumulated result,
8831     * and is provided as an argument in the next call to the callback function.
8832     *
8833     * @param callbackfn A function that accepts four arguments.
8834     * The reduceRight method calls the callbackfn function one time for each element in the array.
8835     *
8836     * @param initialValue The parameter which value is used as the initial value to start the accumulation.
8837     * The first call to the callbackfn function provides this value as an argument.
8838     *
8839     * @returns The value that results from running the callback function to completion over the entire typed array.
8840     */
8841    public reduceRight<U = BigInt>(
8842                callbackfn: (previousValue: U, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => U,
8843                initialValue: U): U {
8844        let accumulatedValue = initialValue
8845        for (let i = this.lengthInt - 1; i >= 0; i--) {
8846            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
8847        }
8848        return accumulatedValue
8849    }
8850
8851    /**
8852     * Calls the specified callback function for all the elements in an array, in descending order.
8853     * The return value of the callback function is the accumulated result,
8854     * and is provided as an argument in the next call to the callback function.
8855     *
8856     * @param callbackfn A function that accepts four arguments.
8857     * The reduceRight method calls the callbackfn function one time for each element in the array.
8858     * The first call to the callbackfn function provides array last element value as an argument
8859     *
8860     * @returns The value that results from running the callback function to completion over the entire typed array.
8861     * calling reduceRight method on an empty array without an initial value creates a TypeError
8862     */
8863    public reduceRight(callbackfn: (previousValue: BigInt, currentValue: BigInt, currentIndex: number, array: BigUint64Array) => BigInt): BigInt {
8864        if (this.lengthInt == 0) {
8865            throw new TypeError("Reduce of empty array with no initial value")
8866        }
8867
8868        let accumulatedValue: BigInt = new BigInt(this.$_get(this.lengthInt - 1))
8869        for (let i = this.lengthInt - 2; i >= 0; i--) {
8870            accumulatedValue = callbackfn(accumulatedValue, new BigInt(this.getUnsafe(i)), i as number, this)
8871        }
8872        return accumulatedValue
8873    }
8874
8875    /**
8876     * Creates a new BigUint64Array using fn(arr[i]) over all elements of current BigUint64Array.
8877     *
8878     * @param fn a function to apply for each element of current BigUint64Array
8879     *
8880     * @returns a new BigUint64Array where for each element from current BigUint64Array fn was applied
8881     */
8882    public map(fn: (val: BigInt, index: number, array: BigUint64Array) => BigInt): BigUint64Array {
8883        let resBuf = new ArrayBuffer(this.lengthInt * BigUint64Array.BYTES_PER_ELEMENT as int)
8884        let res = new BigUint64Array(resBuf)
8885        for (let i = 0; i < this.lengthInt; i++) {
8886            const fnRes = fn(new BigInt(this.getUnsafe(i)), i as number, this)
8887            res.setUnsafeClamp(i, fnRes.getULong())
8888        }
8889        return res
8890    }
8891
8892    /**
8893     * Determines whether the specified callback function returns true for all elements of an array.
8894     *
8895     * @param predicate A function that accepts three arguments.
8896     * The every method calls the predicate function for each element in the array until the predicate returns a false,
8897     * or until the end of the array.
8898     *
8899     * @returns true unless predicate function returns a false for an array element,
8900     * in which case false is immediately returned.
8901     */
8902    public every(predicate: (element: BigInt, index: number, array: BigUint64Array) => boolean): boolean {
8903        for (let i = 0; i < this.lengthInt; i++) {
8904            if (!predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
8905                return false
8906            }
8907        }
8908        return true
8909    }
8910
8911    /**
8912     * Creates a new BigUint64Array from current BigUint64Array based on a condition fn.
8913     *
8914     * @param fn the condition to apply for each element
8915     *
8916     * @returns a new BigUint64Array with elements from current BigUint64Array that satisfy condition fn
8917     */
8918    public filter(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): BigUint64Array {
8919        let markers : FixedArray<boolean> = new boolean[this.lengthInt]
8920        let resLen = 0
8921        for (let i = 0; i < this.lengthInt; i++) {
8922            markers[i] = fn(new BigInt(this.getUnsafe(i)), i as number, this)
8923            if (markers[i]) {
8924                ++resLen
8925            }
8926        }
8927        let res = new BigUint64Array(resLen)
8928        for (let i = 0, j = 0; i < this.lengthInt; i++) {
8929            if (markers[i]) {
8930                res.setUnsafe(j, this.getUnsafe(i))
8931                ++j
8932            }
8933        }
8934        return res
8935    }
8936
8937    /**
8938     * Returns the value of the first element in the array where predicate is true, and undefined
8939     * otherwise
8940     *
8941     * @param predicate find calls predicate once for each element of the array, in ascending
8942     * order, until it finds one where predicate returns true. If such an element is found, find
8943     * immediately returns that element value. Otherwise, find returns undefined
8944     *
8945     * @returns BigInt | undefined
8946     */
8947    public find(predicate: (value: BigInt, index: number, array: BigUint64Array) => boolean): BigInt | undefined {
8948        for (let i = 0; i < this.lengthInt; i++) {
8949            let val = new BigInt(this.getUnsafe(i))
8950            if (predicate(val, i as number, this)) {
8951                return val
8952            }
8953        }
8954        return undefined
8955    }
8956
8957    /**
8958     * Returns the index of the first element in the array where predicate is true, and -1
8959     * otherwise
8960     *
8961     * @param predicate find calls predicate once for each element of the array, in ascending
8962     * order, until it finds one where predicate returns true. If such an element is found,
8963     * findIndex immediately returns that element index. Otherwise, findIndex returns -1
8964     *
8965     * @returns number
8966     */
8967    public findIndex(predicate: (value: BigInt, index: number, obj: BigUint64Array) => boolean): number {
8968        for (let i = 0; i < this.lengthInt; i++) {
8969            if (predicate(new BigInt(this.getUnsafe(i)), i as number, this)) {
8970                return i as number
8971            }
8972        }
8973        return -1 as number
8974    }
8975
8976    /**
8977     * Finds the last element in the BigUint64Array that satisfies the condition
8978     *
8979     * @param fn condition
8980     *
8981     * @returns the last element that satisfies fn
8982     */
8983    public findLast(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): BigInt {
8984        for (let i = this.lengthInt - 1; i >= 0; i--) {
8985            let val = new BigInt(this.getUnsafe(i))
8986            if (fn(val, i as number, this)) {
8987                return val
8988            }
8989        }
8990        throw new Error("BigUint64Array.findLast: not implemented if an element was not found")
8991    }
8992
8993    /**
8994     * Finds an index of the last element in the BigUint64Array that satisfies the condition
8995     *
8996     * @param fn condition
8997     *
8998     * @returns the index of the last element that satisfies fn, -1 otherwise
8999     */
9000    public findLastIndex(fn: (val: BigInt, index: number, array: BigUint64Array) => boolean): number {
9001        for (let i = this.lengthInt - 1; i >= 0; i--) {
9002            if (fn(new BigInt(this.getUnsafe(i)), i as number, this)) {
9003                return i as number
9004            }
9005        }
9006        return -1 as number
9007    }
9008
9009    /**
9010     * Performs the specified action for each element in BigUint64Array
9011     *
9012     * @param callbackfn  A function that accepts up to three arguments. forEach calls the
9013     * callbackfn function one time for each element in the array.
9014     *
9015     * @returns None
9016     */
9017    public forEach(callbackfn: (value: BigInt, index: number, array: BigUint64Array) => void): void {
9018        for (let i = 0; i < this.lengthInt; i++) {
9019            callbackfn(new BigInt(this.getUnsafe(i)), i as number, this)
9020        }
9021    }
9022
9023    /**
9024     * Returns the object itself
9025     *
9026     * @returns BigUint64Array
9027     */
9028    public valueOf(): BigUint64Array {
9029        return this
9030    }
9031
9032    /** Byte offset within the underlying Buffer */
9033    public get byteOffset(): number {
9034        return this.byteOffsetInt
9035    }
9036
9037    /** Number of bytes used */
9038    public get byteLength(): number {
9039        return this.byteLengthInt
9040    }
9041
9042    /** Number of long stored in BigUint64Array */
9043    public get length(): number {
9044        return this.lengthInt
9045    }
9046
9047    /** String \"BigUint64Array\" */
9048    public readonly name = "BigUint64Array"
9049
9050    private static clamp(val: long): long {
9051        return val
9052    }
9053
9054    internal setUnsafeClamp(insertPos: int, val: long): void {
9055        this.setUnsafe(insertPos, val)
9056    }
9057
9058    private final native getUnsafe(index: int): long
9059
9060    internal setUnsafe(index: int, val: long): void {
9061        index = index * BigUint64Array.BYTES_PER_ELEMENT as int + this.byteOffsetInt
9062        let res: long = 0
9063        if (IS_LITTLE_ENDIAN) {
9064            for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
9065                this.buffer.set(index + i, (val & 0xff) as byte)
9066                val = val >> 8
9067            }
9068        } else {
9069            for (let i = 0; i < BigUint64Array.BYTES_PER_ELEMENT as int; i++) {
9070                this.buffer.set(index + 7 - i, (val & 0xff) as byte)
9071                val = val >> 8
9072            }
9073        }
9074    }
9075}
9076