• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2024 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
16package escompat;
17
18export final class DataView implements ArrayBufferView {
19    /** Underlying buffer */
20    private readonly buffer_: ArrayBufferLike
21    /** Count of bytes in a view */
22    private readonly byteLength_: int
23    /** Offset from start of {@link buffer} */
24    private readonly byteOffset_: int
25
26    public get buffer(): ArrayBufferLike {
27        return this.buffer_
28    }
29
30    public get byteLength(): number {
31        return this.byteLength_
32    }
33
34    public get byteOffset(): number {
35        return this.byteOffset_
36    }
37
38    private readonly actualBuffer: Buffer
39
40    /**
41     * Constructs view
42     * @param buffer underlying buffer
43     * @param byteOffset offset to start from
44     * @throws RangeError if offset is out of array
45     */
46    public constructor(buffer: ArrayBufferLike, byteOffset: int) {
47        this(buffer, byteOffset, (buffer as Buffer).getByteLength() - byteOffset)
48    }
49
50    /**
51     * Constructs view
52     * @param buffer underlying buffer
53     * @param byteOffset offset to start from
54     * @param byteLength lenth of bytes to take
55     * @throws RangeError if provided indicies are invalid
56     */
57    public constructor(buffer: ArrayBufferLike, byteOffset: int, byteLength: int) {
58        this.buffer_ = buffer
59        this.actualBuffer = buffer
60        const bufLen = this.actualBuffer.getByteLength()
61        if (byteOffset < 0 || byteLength < 0 || byteOffset > bufLen || byteOffset + byteLength > bufLen) {
62            throw new RangeError("invalid arguments")
63        }
64        this.byteOffset_ = byteOffset
65        this.byteLength_ = byteLength
66    }
67
68    /**
69     * Constructs view
70     * @param buffer underlying buffer
71     * @param byteOffset offset to start from
72     * @param byteLength lenth of bytes to take
73     * @throws RangeError if provided indicies are invalid
74     */
75    public constructor(buffer: ArrayBufferLike, byteOffset?: Number, byteLength?: Number) {
76        this(buffer, asIntOrDefault(byteOffset, 0), asIntOrDefault(byteLength, (buffer as Buffer).getByteLength()))
77    }
78    // === Int8 ===
79
80    /**
81     * Read bytes as they represent given type
82     * @param byteOffset zero index to read
83     * @returns read value (big endian)
84     */
85    public getInt8(byteOffset: int): int {
86        return this.getInt8Big(byteOffset)
87    }
88
89    /**
90     * Sets bytes as they represent given type
91     * @param byteOffset zero index to write (big endian)
92     */
93    public setInt8(byteOffset: int, value: int): void {
94        this.setInt8Big(byteOffset, value)
95    }
96
97    /**
98     * Read bytes as they represent given type
99     * @param byteOffset zero index to read
100     * @returns read value (big endian)
101     */
102    public getInt8(byteOffset: number): number {
103        return this.getInt8Big(byteOffset)
104    }
105
106    /**
107     * Sets bytes as they represent given type
108     * @param byteOffset zero index to write (big endian)
109     */
110    public setInt8(byteOffset: number, value: number): void {
111        this.setInt8Big(byteOffset, value)
112    }
113    private getInt8Big(byteOffset: int): int {
114        if (byteOffset + 1 > this.byteLength_) {
115            throw new RangeError("wrong index")
116        }
117        let res: int = 0;
118        const startByte = this.byteOffset_ + byteOffset
119        for (let i = 0; i < 1; i++) {
120            let byteVal = this.actualBuffer.at(startByte + 0 - i) as int;
121            byteVal &= 0xff
122            res = (res | byteVal << (8 * i)) as int;
123        }
124        return (res as byte) as int
125    }
126    private getInt8Big(byteOffset: number): number {
127        let res = this.getInt8Big(byteOffset as int)
128        return res;
129    }
130
131    private setInt8Big(byteOffset: int, value: int): void {
132        if (byteOffset < 0 || byteOffset + 1.0 > this.byteLength_) {
133            throw new RangeError("wrong index")
134        }
135        let bits = value;
136        const startByte = this.byteOffset_ + byteOffset
137        for (let i = 0; i < 1; i++) {
138            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
139            this.actualBuffer.set(startByte + 0 - i,  byteVal)
140        }
141    }
142    private setInt8Big(byteOffset: number, value: number): void {
143        const val: int = value as int;
144        this.setInt8Big(byteOffset as int, val)
145    }
146    // === Uint8 ===
147
148    /**
149     * Read bytes as they represent given type
150     * @param byteOffset zero index to read
151     * @returns read value (big endian)
152     */
153    public getUint8(byteOffset: int): int {
154        return this.getUint8Big(byteOffset)
155    }
156
157    /**
158     * Sets bytes as they represent given type
159     * @param byteOffset zero index to write (big endian)
160     */
161    public setUint8(byteOffset: int, value: int): void {
162        this.setUint8Big(byteOffset, value)
163    }
164
165    /**
166     * Read bytes as they represent given type
167     * @param byteOffset zero index to read
168     * @returns read value (big endian)
169     */
170    public getUint8(byteOffset: number): number {
171        return this.getUint8Big(byteOffset)
172    }
173
174    /**
175     * Sets bytes as they represent given type
176     * @param byteOffset zero index to write (big endian)
177     */
178    public setUint8(byteOffset: number, value: number): void {
179        this.setUint8Big(byteOffset, value)
180    }
181    private getUint8Big(byteOffset: int): int {
182        if (byteOffset + 1 > this.byteLength_) {
183            throw new RangeError("wrong index")
184        }
185        let res: int = 0;
186        const startByte = this.byteOffset_ + byteOffset
187        for (let i = 0; i < 1; i++) {
188            let byteVal = this.actualBuffer.at(startByte + 0 - i) as int;
189            byteVal &= 0xff
190            res = (res | byteVal << (8 * i)) as int;
191        }
192        return res
193    }
194    private getUint8Big(byteOffset: number): number {
195        let res = this.getUint8Big(byteOffset as int)
196        return res;
197    }
198
199    private setUint8Big(byteOffset: int, value: int): void {
200        if (byteOffset < 0 || byteOffset + 1.0 > this.byteLength_) {
201            throw new RangeError("wrong index")
202        }
203        let bits = value;
204        const startByte = this.byteOffset_ + byteOffset
205        for (let i = 0; i < 1; i++) {
206            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
207            this.actualBuffer.set(startByte + 0 - i,  byteVal)
208        }
209    }
210    private setUint8Big(byteOffset: number, value: number): void {
211        const val: int = value as int;
212        this.setUint8Big(byteOffset as int, val)
213    }
214    // === Int16 ===
215
216    /**
217     * Read bytes as they represent given type
218     * @param byteOffset zero index to read
219     * @returns read value (big endian)
220     */
221    public getInt16(byteOffset: int): int {
222        return this.getInt16Big(byteOffset)
223    }
224
225    /**
226     * Sets bytes as they represent given type
227     * @param byteOffset zero index to write (big endian)
228     */
229    public setInt16(byteOffset: int, value: int): void {
230        this.setInt16Big(byteOffset, value)
231    }
232    /**
233     * Sets bytes as they represent given type
234     * @param byteOffset zero index to write
235     * @param littleEndian read as little or big endian
236     */
237    public setInt16(byteOffset: number, value: number, littleEndian?: boolean): void {
238        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
239            this.setInt16Little(byteOffset, value)
240        } else {
241            this.setInt16Big(byteOffset, value)
242        }
243    }
244
245    /**
246     * Sets bytes as they represent given type
247     * @param byteOffset zero index to write
248     * @param littleEndian read as little or big endian
249     */
250    public setInt16(byteOffset: int, value: int, littleEndian: boolean): void {
251        if (littleEndian) {
252            this.setInt16Little(byteOffset, value)
253        } else {
254            this.setInt16Big(byteOffset, value)
255        }
256    }
257
258    /**
259     * Read bytes as they represent given type
260     * @param byteOffset zero index to read
261     * @param littleEndian read as little or big endian
262     * @returns read value
263     */
264    public getInt16(byteOffset: number, littleEndian?: boolean): number {
265        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
266            return this.getInt16Little(byteOffset)
267        } else {
268            return this.getInt16Big(byteOffset)
269        }
270    }
271
272    /**
273     * Read bytes as they represent given type
274     * @param byteOffset zero index to read
275     * @param littleEndian read as little or big endian
276     * @returns read value
277     */
278    public getInt16(byteOffset: int, littleEndian: boolean): int {
279        if (littleEndian) {
280            return this.getInt16Little(byteOffset)
281        } else {
282            return this.getInt16Big(byteOffset)
283        }
284    }
285    private getInt16Little(byteOffset: int): int {
286        if (byteOffset + 2 > this.byteLength_) {
287            throw new RangeError("wrong index")
288        }
289        let res: int = 0;
290        const startByte = this.byteOffset_ + byteOffset
291        for (let i = 0; i < 2; i++) {
292            let byteVal = this.actualBuffer.at(startByte + i) as int;
293            byteVal &= 0xff
294            res = (res | byteVal << (8 * i)) as int;
295        }
296        return (res as short) as int
297    }
298    private getInt16Little(byteOffset: number): number {
299        let res = this.getInt16Little(byteOffset as int)
300        return res;
301    }
302
303    private setInt16Little(byteOffset: int, value: int): void {
304        if (byteOffset < 0 || byteOffset + 2.0 > this.byteLength_) {
305            throw new RangeError("wrong index")
306        }
307        let bits = value;
308        const startByte = this.byteOffset_ + byteOffset
309        for (let i = 0; i < 2; i++) {
310            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
311            this.actualBuffer.set(startByte + i,  byteVal)
312        }
313    }
314    private setInt16Little(byteOffset: number, value: number): void {
315        const val: int = value as int;
316        this.setInt16Little(byteOffset as int, val)
317    }
318    private getInt16Big(byteOffset: int): int {
319        if (byteOffset + 2 > this.byteLength_) {
320            throw new RangeError("wrong index")
321        }
322        let res: int = 0;
323        const startByte = this.byteOffset_ + byteOffset
324        for (let i = 0; i < 2; i++) {
325            let byteVal = this.actualBuffer.at(startByte + 1 - i) as int;
326            byteVal &= 0xff
327            res = (res | byteVal << (8 * i)) as int;
328        }
329        return (res as short) as int
330    }
331    private getInt16Big(byteOffset: number): number {
332        let res = this.getInt16Big(byteOffset as int)
333        return res;
334    }
335
336    private setInt16Big(byteOffset: int, value: int): void {
337        if (byteOffset < 0 || byteOffset + 2.0 > this.byteLength_) {
338            throw new RangeError("wrong index")
339        }
340        let bits = value;
341        const startByte = this.byteOffset_ + byteOffset
342        for (let i = 0; i < 2; i++) {
343            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
344            this.actualBuffer.set(startByte + 1 - i,  byteVal)
345        }
346    }
347    private setInt16Big(byteOffset: number, value: number): void {
348        const val: int = value as int;
349        this.setInt16Big(byteOffset as int, val)
350    }
351    // === Uint16 ===
352
353    /**
354     * Read bytes as they represent given type
355     * @param byteOffset zero index to read
356     * @returns read value (big endian)
357     */
358    public getUint16(byteOffset: int): int {
359        return this.getUint16Big(byteOffset)
360    }
361
362    /**
363     * Sets bytes as they represent given type
364     * @param byteOffset zero index to write (big endian)
365     */
366    public setUint16(byteOffset: int, value: int): void {
367        this.setUint16Big(byteOffset, value)
368    }
369    /**
370     * Sets bytes as they represent given type
371     * @param byteOffset zero index to write
372     * @param littleEndian read as little or big endian
373     */
374    public setUint16(byteOffset: number, value: number, littleEndian?: boolean): void {
375        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
376            this.setUint16Little(byteOffset, value)
377        } else {
378            this.setUint16Big(byteOffset, value)
379        }
380    }
381
382    /**
383     * Sets bytes as they represent given type
384     * @param byteOffset zero index to write
385     * @param littleEndian read as little or big endian
386     */
387    public setUint16(byteOffset: int, value: int, littleEndian: boolean): void {
388        if (littleEndian) {
389            this.setUint16Little(byteOffset, value)
390        } else {
391            this.setUint16Big(byteOffset, value)
392        }
393    }
394
395    /**
396     * Read bytes as they represent given type
397     * @param byteOffset zero index to read
398     * @param littleEndian read as little or big endian
399     * @returns read value
400     */
401    public getUint16(byteOffset: number, littleEndian?: boolean): number {
402        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
403            return this.getUint16Little(byteOffset)
404        } else {
405            return this.getUint16Big(byteOffset)
406        }
407    }
408
409    /**
410     * Read bytes as they represent given type
411     * @param byteOffset zero index to read
412     * @param littleEndian read as little or big endian
413     * @returns read value
414     */
415    public getUint16(byteOffset: int, littleEndian: boolean): int {
416        if (littleEndian) {
417            return this.getUint16Little(byteOffset)
418        } else {
419            return this.getUint16Big(byteOffset)
420        }
421    }
422    private getUint16Little(byteOffset: int): int {
423        if (byteOffset + 2 > this.byteLength_) {
424            throw new RangeError("wrong index")
425        }
426        let res: int = 0;
427        const startByte = this.byteOffset_ + byteOffset
428        for (let i = 0; i < 2; i++) {
429            let byteVal = this.actualBuffer.at(startByte + i) as int;
430            byteVal &= 0xff
431            res = (res | byteVal << (8 * i)) as int;
432        }
433        return res
434    }
435    private getUint16Little(byteOffset: number): number {
436        let res = this.getUint16Little(byteOffset as int)
437        return res;
438    }
439
440    private setUint16Little(byteOffset: int, value: int): void {
441        if (byteOffset < 0 || byteOffset + 2.0 > this.byteLength_) {
442            throw new RangeError("wrong index")
443        }
444        let bits = value;
445        const startByte = this.byteOffset_ + byteOffset
446        for (let i = 0; i < 2; i++) {
447            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
448            this.actualBuffer.set(startByte + i,  byteVal)
449        }
450    }
451    private setUint16Little(byteOffset: number, value: number): void {
452        const val: int = value as int;
453        this.setUint16Little(byteOffset as int, val)
454    }
455    private getUint16Big(byteOffset: int): int {
456        if (byteOffset + 2 > this.byteLength_) {
457            throw new RangeError("wrong index")
458        }
459        let res: int = 0;
460        const startByte = this.byteOffset_ + byteOffset
461        for (let i = 0; i < 2; i++) {
462            let byteVal = this.actualBuffer.at(startByte + 1 - i) as int;
463            byteVal &= 0xff
464            res = (res | byteVal << (8 * i)) as int;
465        }
466        return res
467    }
468    private getUint16Big(byteOffset: number): number {
469        let res = this.getUint16Big(byteOffset as int)
470        return res;
471    }
472
473    private setUint16Big(byteOffset: int, value: int): void {
474        if (byteOffset < 0 || byteOffset + 2.0 > this.byteLength_) {
475            throw new RangeError("wrong index")
476        }
477        let bits = value;
478        const startByte = this.byteOffset_ + byteOffset
479        for (let i = 0; i < 2; i++) {
480            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
481            this.actualBuffer.set(startByte + 1 - i,  byteVal)
482        }
483    }
484    private setUint16Big(byteOffset: number, value: number): void {
485        const val: int = value as int;
486        this.setUint16Big(byteOffset as int, val)
487    }
488    // === Int32 ===
489
490    /**
491     * Read bytes as they represent given type
492     * @param byteOffset zero index to read
493     * @returns read value (big endian)
494     */
495    public getInt32(byteOffset: int): int {
496        return this.getInt32Big(byteOffset)
497    }
498
499    /**
500     * Sets bytes as they represent given type
501     * @param byteOffset zero index to write (big endian)
502     */
503    public setInt32(byteOffset: int, value: int): void {
504        this.setInt32Big(byteOffset, value)
505    }
506    /**
507     * Sets bytes as they represent given type
508     * @param byteOffset zero index to write
509     * @param littleEndian read as little or big endian
510     */
511    public setInt32(byteOffset: number, value: number, littleEndian?: boolean): void {
512        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
513            this.setInt32Little(byteOffset, value)
514        } else {
515            this.setInt32Big(byteOffset, value)
516        }
517    }
518
519    /**
520     * Sets bytes as they represent given type
521     * @param byteOffset zero index to write
522     * @param littleEndian read as little or big endian
523     */
524    public setInt32(byteOffset: int, value: int, littleEndian: boolean): void {
525        if (littleEndian) {
526            this.setInt32Little(byteOffset, value)
527        } else {
528            this.setInt32Big(byteOffset, value)
529        }
530    }
531
532    /**
533     * Read bytes as they represent given type
534     * @param byteOffset zero index to read
535     * @param littleEndian read as little or big endian
536     * @returns read value
537     */
538    public getInt32(byteOffset: number, littleEndian?: boolean): number {
539        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
540            return this.getInt32Little(byteOffset)
541        } else {
542            return this.getInt32Big(byteOffset)
543        }
544    }
545
546    /**
547     * Read bytes as they represent given type
548     * @param byteOffset zero index to read
549     * @param littleEndian read as little or big endian
550     * @returns read value
551     */
552    public getInt32(byteOffset: int, littleEndian: boolean): int {
553        if (littleEndian) {
554            return this.getInt32Little(byteOffset)
555        } else {
556            return this.getInt32Big(byteOffset)
557        }
558    }
559    private getInt32Little(byteOffset: int): int {
560        if (byteOffset + 4 > this.byteLength_) {
561            throw new RangeError("wrong index")
562        }
563        let res: int = 0;
564        const startByte = this.byteOffset_ + byteOffset
565        for (let i = 0; i < 4; i++) {
566            let byteVal = this.actualBuffer.at(startByte + i) as int;
567            byteVal &= 0xff
568            res = (res | byteVal << (8 * i)) as int;
569        }
570        return (res as int) as int
571    }
572    private getInt32Little(byteOffset: number): number {
573        let res = this.getInt32Little(byteOffset as int)
574        return res;
575    }
576
577    private setInt32Little(byteOffset: int, value: int): void {
578        if (byteOffset < 0 || byteOffset + 4.0 > this.byteLength_) {
579            throw new RangeError("wrong index")
580        }
581        let bits = value;
582        const startByte = this.byteOffset_ + byteOffset
583        for (let i = 0; i < 4; i++) {
584            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
585            this.actualBuffer.set(startByte + i,  byteVal)
586        }
587    }
588    private setInt32Little(byteOffset: number, value: number): void {
589        const val: int = value as int;
590        this.setInt32Little(byteOffset as int, val)
591    }
592    private getInt32Big(byteOffset: int): int {
593        if (byteOffset + 4 > this.byteLength_) {
594            throw new RangeError("wrong index")
595        }
596        let res: int = 0;
597        const startByte = this.byteOffset_ + byteOffset
598        for (let i = 0; i < 4; i++) {
599            let byteVal = this.actualBuffer.at(startByte + 3 - i) as int;
600            byteVal &= 0xff
601            res = (res | byteVal << (8 * i)) as int;
602        }
603        return (res as int) as int
604    }
605    private getInt32Big(byteOffset: number): number {
606        let res = this.getInt32Big(byteOffset as int)
607        return res;
608    }
609
610    private setInt32Big(byteOffset: int, value: int): void {
611        if (byteOffset < 0 || byteOffset + 4.0 > this.byteLength_) {
612            throw new RangeError("wrong index")
613        }
614        let bits = value;
615        const startByte = this.byteOffset_ + byteOffset
616        for (let i = 0; i < 4; i++) {
617            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
618            this.actualBuffer.set(startByte + 3 - i,  byteVal)
619        }
620    }
621    private setInt32Big(byteOffset: number, value: number): void {
622        const val: int = value as int;
623        this.setInt32Big(byteOffset as int, val)
624    }
625    // === Uint32 ===
626
627    /**
628     * Read bytes as they represent given type
629     * @param byteOffset zero index to read
630     * @returns read value (big endian)
631     */
632    public getUint32(byteOffset: int): long {
633        return this.getUint32Big(byteOffset)
634    }
635
636    /**
637     * Sets bytes as they represent given type
638     * @param byteOffset zero index to write (big endian)
639     */
640    public setUint32(byteOffset: int, value: long): void {
641        this.setUint32Big(byteOffset, value)
642    }
643    /**
644     * Sets bytes as they represent given type
645     * @param byteOffset zero index to write
646     * @param littleEndian read as little or big endian
647     */
648    public setUint32(byteOffset: number, value: number, littleEndian?: boolean): void {
649        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
650            this.setUint32Little(byteOffset, value)
651        } else {
652            this.setUint32Big(byteOffset, value)
653        }
654    }
655
656    /**
657     * Sets bytes as they represent given type
658     * @param byteOffset zero index to write
659     * @param littleEndian read as little or big endian
660     */
661    public setUint32(byteOffset: int, value: long, littleEndian: boolean): void {
662        if (littleEndian) {
663            this.setUint32Little(byteOffset, value)
664        } else {
665            this.setUint32Big(byteOffset, value)
666        }
667    }
668
669    /**
670     * Read bytes as they represent given type
671     * @param byteOffset zero index to read
672     * @param littleEndian read as little or big endian
673     * @returns read value
674     */
675    public getUint32(byteOffset: number, littleEndian?: boolean): number {
676        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
677            return this.getUint32Little(byteOffset)
678        } else {
679            return this.getUint32Big(byteOffset)
680        }
681    }
682
683    /**
684     * Read bytes as they represent given type
685     * @param byteOffset zero index to read
686     * @param littleEndian read as little or big endian
687     * @returns read value
688     */
689    public getUint32(byteOffset: int, littleEndian: boolean): long {
690        if (littleEndian) {
691            return this.getUint32Little(byteOffset)
692        } else {
693            return this.getUint32Big(byteOffset)
694        }
695    }
696    private getUint32Little(byteOffset: int): long {
697        if (byteOffset + 4 > this.byteLength_) {
698            throw new RangeError("wrong index")
699        }
700        let res: long = 0;
701        const startByte = this.byteOffset_ + byteOffset
702        for (let i = 0; i < 4; i++) {
703            let byteVal = this.actualBuffer.at(startByte + i) as long;
704            byteVal &= 0xff
705            res = (res | byteVal << (8 * i)) as long;
706        }
707        return res
708    }
709    private getUint32Little(byteOffset: number): number {
710        let res = this.getUint32Little(byteOffset as int)
711        return res;
712    }
713
714    private setUint32Little(byteOffset: int, value: long): void {
715        if (byteOffset < 0 || byteOffset + 4.0 > this.byteLength_) {
716            throw new RangeError("wrong index")
717        }
718        let bits = value;
719        const startByte = this.byteOffset_ + byteOffset
720        for (let i = 0; i < 4; i++) {
721            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
722            this.actualBuffer.set(startByte + i,  byteVal)
723        }
724    }
725    private setUint32Little(byteOffset: number, value: number): void {
726        const val: long = value as long;
727        this.setUint32Little(byteOffset as int, val)
728    }
729    private getUint32Big(byteOffset: int): long {
730        if (byteOffset + 4 > this.byteLength_) {
731            throw new RangeError("wrong index")
732        }
733        let res: long = 0;
734        const startByte = this.byteOffset_ + byteOffset
735        for (let i = 0; i < 4; i++) {
736            let byteVal = this.actualBuffer.at(startByte + 3 - i) as long;
737            byteVal &= 0xff
738            res = (res | byteVal << (8 * i)) as long;
739        }
740        return res
741    }
742    private getUint32Big(byteOffset: number): number {
743        let res = this.getUint32Big(byteOffset as int)
744        return res;
745    }
746
747    private setUint32Big(byteOffset: int, value: long): void {
748        if (byteOffset < 0 || byteOffset + 4.0 > this.byteLength_) {
749            throw new RangeError("wrong index")
750        }
751        let bits = value;
752        const startByte = this.byteOffset_ + byteOffset
753        for (let i = 0; i < 4; i++) {
754            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
755            this.actualBuffer.set(startByte + 3 - i,  byteVal)
756        }
757    }
758    private setUint32Big(byteOffset: number, value: number): void {
759        const val: long = value as long;
760        this.setUint32Big(byteOffset as int, val)
761    }
762    // === Float32 ===
763
764    /**
765     * Read bytes as they represent given type
766     * @param byteOffset zero index to read
767     * @returns read value (big endian)
768     */
769    public getFloat32(byteOffset: int): float {
770        return this.getFloat32Big(byteOffset)
771    }
772
773    /**
774     * Sets bytes as they represent given type
775     * @param byteOffset zero index to write (big endian)
776     */
777    public setFloat32(byteOffset: int, value: float): void {
778        this.setFloat32Big(byteOffset, value)
779    }
780    /**
781     * Sets bytes as they represent given type
782     * @param byteOffset zero index to write
783     * @param littleEndian read as little or big endian
784     */
785    public setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void {
786        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
787            this.setFloat32Little(byteOffset, value)
788        } else {
789            this.setFloat32Big(byteOffset, value)
790        }
791    }
792
793    /**
794     * Sets bytes as they represent given type
795     * @param byteOffset zero index to write
796     * @param littleEndian read as little or big endian
797     */
798    public setFloat32(byteOffset: int, value: float, littleEndian: boolean): void {
799        if (littleEndian) {
800            this.setFloat32Little(byteOffset, value)
801        } else {
802            this.setFloat32Big(byteOffset, value)
803        }
804    }
805
806    /**
807     * Read bytes as they represent given type
808     * @param byteOffset zero index to read
809     * @param littleEndian read as little or big endian
810     * @returns read value
811     */
812    public getFloat32(byteOffset: number, littleEndian?: boolean): number {
813        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
814            return this.getFloat32Little(byteOffset)
815        } else {
816            return this.getFloat32Big(byteOffset)
817        }
818    }
819
820    /**
821     * Read bytes as they represent given type
822     * @param byteOffset zero index to read
823     * @param littleEndian read as little or big endian
824     * @returns read value
825     */
826    public getFloat32(byteOffset: int, littleEndian: boolean): float {
827        if (littleEndian) {
828            return this.getFloat32Little(byteOffset)
829        } else {
830            return this.getFloat32Big(byteOffset)
831        }
832    }
833    private getFloat32Little(byteOffset: int): float {
834        if (byteOffset + 4 > this.byteLength_) {
835            throw new RangeError("wrong index")
836        }
837        let res: int = 0;
838        const startByte = this.byteOffset_ + byteOffset
839        for (let i = 0; i < 4; i++) {
840            let byteVal = this.actualBuffer.at(startByte + i) as int;
841            byteVal &= 0xff
842            res = (res | byteVal << (8 * i)) as int;
843        }
844        return Float.bitCastFromInt(res)
845    }
846    private getFloat32Little(byteOffset: number): number {
847        let res = this.getFloat32Little(byteOffset as int)
848        return res;
849    }
850
851    private setFloat32Little(byteOffset: int, value: float): void {
852        if (byteOffset < 0 || byteOffset + 4.0 > this.byteLength_) {
853            throw new RangeError("wrong index")
854        }
855        let bits = Float.bitCastToInt(value);
856        const startByte = this.byteOffset_ + byteOffset
857        for (let i = 0; i < 4; i++) {
858            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
859            this.actualBuffer.set(startByte + i,  byteVal)
860        }
861    }
862    private setFloat32Little(byteOffset: number, value: number): void {
863        const val: float = value as float;
864        this.setFloat32Little(byteOffset as int, val)
865    }
866    private getFloat32Big(byteOffset: int): float {
867        if (byteOffset + 4 > this.byteLength_) {
868            throw new RangeError("wrong index")
869        }
870        let res: int = 0;
871        const startByte = this.byteOffset_ + byteOffset
872        for (let i = 0; i < 4; i++) {
873            let byteVal = this.actualBuffer.at(startByte + 3 - i) as int;
874            byteVal &= 0xff
875            res = (res | byteVal << (8 * i)) as int;
876        }
877        return Float.bitCastFromInt(res)
878    }
879    private getFloat32Big(byteOffset: number): number {
880        let res = this.getFloat32Big(byteOffset as int)
881        return res;
882    }
883
884    private setFloat32Big(byteOffset: int, value: float): void {
885        if (byteOffset < 0 || byteOffset + 4.0 > this.byteLength_) {
886            throw new RangeError("wrong index")
887        }
888        let bits = Float.bitCastToInt(value);
889        const startByte = this.byteOffset_ + byteOffset
890        for (let i = 0; i < 4; i++) {
891            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
892            this.actualBuffer.set(startByte + 3 - i,  byteVal)
893        }
894    }
895    private setFloat32Big(byteOffset: number, value: number): void {
896        const val: float = value as float;
897        this.setFloat32Big(byteOffset as int, val)
898    }
899    // === Int64 ===
900
901    /**
902     * Read bytes as they represent given type
903     * @param byteOffset zero index to read
904     * @returns read value (big endian)
905     */
906    public getBigInt64(byteOffset: int): long {
907        return this.getBigInt64Big(byteOffset)
908    }
909
910    /**
911     * Sets bytes as they represent given type
912     * @param byteOffset zero index to write (big endian)
913     */
914    public setBigInt64(byteOffset: int, value: long): void {
915        this.setBigInt64Big(byteOffset, value)
916    }
917    /**
918     * Sets bytes as they represent given type
919     * @param byteOffset zero index to write
920     * @param littleEndian read as little or big endian
921     */
922    public setBigInt64(byteOffset: number, value: bigint, littleEndian?: boolean): void {
923        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
924            this.setBigInt64Little(byteOffset, value)
925        } else {
926            this.setBigInt64Big(byteOffset, value)
927        }
928    }
929
930    /**
931     * Sets bytes as they represent given type
932     * @param byteOffset zero index to write
933     * @param littleEndian read as little or big endian
934     */
935    public setBigInt64(byteOffset: int, value: long, littleEndian: boolean): void {
936        if (littleEndian) {
937            this.setBigInt64Little(byteOffset, value)
938        } else {
939            this.setBigInt64Big(byteOffset, value)
940        }
941    }
942
943    /**
944     * Read bytes as they represent given type
945     * @param byteOffset zero index to read
946     * @param littleEndian read as little or big endian
947     * @returns read value
948     */
949    public getBigInt64(byteOffset: number, littleEndian?: boolean): bigint {
950        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
951            return this.getBigInt64Little(byteOffset)
952        } else {
953            return this.getBigInt64Big(byteOffset)
954        }
955    }
956
957    /**
958     * Read bytes as they represent given type
959     * @param byteOffset zero index to read
960     * @param littleEndian read as little or big endian
961     * @returns read value
962     */
963    public getBigInt64(byteOffset: int, littleEndian: boolean): long {
964        if (littleEndian) {
965            return this.getBigInt64Little(byteOffset)
966        } else {
967            return this.getBigInt64Big(byteOffset)
968        }
969    }
970    private getBigInt64Little(byteOffset: int): long {
971        if (byteOffset + 8 > this.byteLength_) {
972            throw new RangeError("wrong index")
973        }
974        let res: long = 0;
975        const startByte = this.byteOffset_ + byteOffset
976        for (let i = 0; i < 8; i++) {
977            let byteVal = this.actualBuffer.at(startByte + i) as long;
978            byteVal &= 0xff
979            res = (res | byteVal << (8 * i)) as long;
980        }
981        return (res as long) as long
982    }
983    private getBigInt64Little(byteOffset: number): bigint {
984        let res = this.getBigInt64Little(byteOffset as int)
985        return new BigInt(res)
986    }
987
988    private setBigInt64Little(byteOffset: int, value: long): void {
989        if (byteOffset < 0 || byteOffset + 8.0 > this.byteLength_) {
990            throw new RangeError("wrong index")
991        }
992        let bits = value;
993        const startByte = this.byteOffset_ + byteOffset
994        for (let i = 0; i < 8; i++) {
995            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
996            this.actualBuffer.set(startByte + i,  byteVal)
997        }
998    }
999    private setBigInt64Little(byteOffset: number, value: bigint): void {
1000        const val: long = value.getLong();
1001        this.setBigInt64Little(byteOffset as int, val)
1002    }
1003    private getBigInt64Big(byteOffset: int): long {
1004        if (byteOffset + 8 > this.byteLength_) {
1005            throw new RangeError("wrong index")
1006        }
1007        let res: long = 0;
1008        const startByte = this.byteOffset_ + byteOffset
1009        for (let i = 0; i < 8; i++) {
1010            let byteVal = this.actualBuffer.at(startByte + 7 - i) as long;
1011            byteVal &= 0xff
1012            res = (res | byteVal << (8 * i)) as long;
1013        }
1014        return (res as long) as long
1015    }
1016    private getBigInt64Big(byteOffset: number): bigint {
1017        let res = this.getBigInt64Big(byteOffset as int)
1018        return new BigInt(res)
1019    }
1020
1021    private setBigInt64Big(byteOffset: int, value: long): void {
1022        if (byteOffset < 0 || byteOffset + 8.0 > this.byteLength_) {
1023            throw new RangeError("wrong index")
1024        }
1025        let bits = value;
1026        const startByte = this.byteOffset_ + byteOffset
1027        for (let i = 0; i < 8; i++) {
1028            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
1029            this.actualBuffer.set(startByte + 7 - i,  byteVal)
1030        }
1031    }
1032    private setBigInt64Big(byteOffset: number, value: bigint): void {
1033        const val: long = value.getLong();
1034        this.setBigInt64Big(byteOffset as int, val)
1035    }
1036    // === Uint64 ===
1037
1038    /**
1039     * Read bytes as they represent given type
1040     * @param byteOffset zero index to read
1041     * @returns read value (big endian)
1042     */
1043    public getBigUint64(byteOffset: int): long {
1044        return this.getBigUint64Big(byteOffset)
1045    }
1046
1047    /**
1048     * Sets bytes as they represent given type
1049     * @param byteOffset zero index to write (big endian)
1050     */
1051    public setBigUint64(byteOffset: int, value: long): void {
1052        this.setBigUint64Big(byteOffset, value)
1053    }
1054    /**
1055     * Sets bytes as they represent given type
1056     * @param byteOffset zero index to write
1057     * @param littleEndian read as little or big endian
1058     */
1059    public setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void {
1060        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
1061            this.setBigUint64Little(byteOffset, value)
1062        } else {
1063            this.setBigUint64Big(byteOffset, value)
1064        }
1065    }
1066
1067    /**
1068     * Sets bytes as they represent given type
1069     * @param byteOffset zero index to write
1070     * @param littleEndian read as little or big endian
1071     */
1072    public setBigUint64(byteOffset: int, value: long, littleEndian: boolean): void {
1073        if (littleEndian) {
1074            this.setBigUint64Little(byteOffset, value)
1075        } else {
1076            this.setBigUint64Big(byteOffset, value)
1077        }
1078    }
1079
1080    /**
1081     * Read bytes as they represent given type
1082     * @param byteOffset zero index to read
1083     * @param littleEndian read as little or big endian
1084     * @returns read value
1085     */
1086    public getBigUint64(byteOffset: number, littleEndian?: boolean): bigint {
1087        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
1088            return this.getBigUint64Little(byteOffset)
1089        } else {
1090            return this.getBigUint64Big(byteOffset)
1091        }
1092    }
1093
1094    /**
1095     * Read bytes as they represent given type
1096     * @param byteOffset zero index to read
1097     * @param littleEndian read as little or big endian
1098     * @returns read value
1099     */
1100    public getBigUint64(byteOffset: int, littleEndian: boolean): long {
1101        if (littleEndian) {
1102            return this.getBigUint64Little(byteOffset)
1103        } else {
1104            return this.getBigUint64Big(byteOffset)
1105        }
1106    }
1107    private getBigUint64Little(byteOffset: int): long {
1108        if (byteOffset + 8 > this.byteLength_) {
1109            throw new RangeError("wrong index")
1110        }
1111        let res: long = 0;
1112        const startByte = this.byteOffset_ + byteOffset
1113        for (let i = 0; i < 8; i++) {
1114            let byteVal = this.actualBuffer.at(startByte + i) as long;
1115            byteVal &= 0xff
1116            res = (res | byteVal << (8 * i)) as long;
1117        }
1118        return res
1119    }
1120    private getBigUint64Little(byteOffset: number): bigint {
1121        let res = this.getBigUint64Little(byteOffset as int)
1122        return DataView.bigintFromULong(res)
1123    }
1124
1125    private setBigUint64Little(byteOffset: int, value: long): void {
1126        if (byteOffset < 0 || byteOffset + 8.0 > this.byteLength_) {
1127            throw new RangeError("wrong index")
1128        }
1129        let bits = value;
1130        const startByte = this.byteOffset_ + byteOffset
1131        for (let i = 0; i < 8; i++) {
1132            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
1133            this.actualBuffer.set(startByte + i,  byteVal)
1134        }
1135    }
1136    private setBigUint64Little(byteOffset: number, value: bigint): void {
1137        const val: long = value.getLong();
1138        this.setBigUint64Little(byteOffset as int, val)
1139    }
1140    private getBigUint64Big(byteOffset: int): long {
1141        if (byteOffset + 8 > this.byteLength_) {
1142            throw new RangeError("wrong index")
1143        }
1144        let res: long = 0;
1145        const startByte = this.byteOffset_ + byteOffset
1146        for (let i = 0; i < 8; i++) {
1147            let byteVal = this.actualBuffer.at(startByte + 7 - i) as long;
1148            byteVal &= 0xff
1149            res = (res | byteVal << (8 * i)) as long;
1150        }
1151        return res
1152    }
1153    private getBigUint64Big(byteOffset: number): bigint {
1154        let res = this.getBigUint64Big(byteOffset as int)
1155        return DataView.bigintFromULong(res)
1156    }
1157
1158    private setBigUint64Big(byteOffset: int, value: long): void {
1159        if (byteOffset < 0 || byteOffset + 8.0 > this.byteLength_) {
1160            throw new RangeError("wrong index")
1161        }
1162        let bits = value;
1163        const startByte = this.byteOffset_ + byteOffset
1164        for (let i = 0; i < 8; i++) {
1165            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
1166            this.actualBuffer.set(startByte + 7 - i,  byteVal)
1167        }
1168    }
1169    private setBigUint64Big(byteOffset: number, value: bigint): void {
1170        const val: long = value.getLong();
1171        this.setBigUint64Big(byteOffset as int, val)
1172    }
1173    // === Float64 ===
1174
1175    /**
1176     * Read bytes as they represent given type
1177     * @param byteOffset zero index to read
1178     * @returns read value (big endian)
1179     */
1180    public getFloat64(byteOffset: int): number {
1181        return this.getFloat64Big(byteOffset)
1182    }
1183
1184    /**
1185     * Sets bytes as they represent given type
1186     * @param byteOffset zero index to write (big endian)
1187     */
1188    public setFloat64(byteOffset: int, value: number): void {
1189        this.setFloat64Big(byteOffset, value)
1190    }
1191    /**
1192     * Sets bytes as they represent given type
1193     * @param byteOffset zero index to write
1194     * @param littleEndian read as little or big endian
1195     */
1196    public setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void {
1197        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
1198            this.setFloat64Little(byteOffset, value)
1199        } else {
1200            this.setFloat64Big(byteOffset, value)
1201        }
1202    }
1203
1204    /**
1205     * Sets bytes as they represent given type
1206     * @param byteOffset zero index to write
1207     * @param littleEndian read as little or big endian
1208     */
1209    public setFloat64(byteOffset: int, value: number, littleEndian: boolean): void {
1210        if (littleEndian) {
1211            this.setFloat64Little(byteOffset, value)
1212        } else {
1213            this.setFloat64Big(byteOffset, value)
1214        }
1215    }
1216
1217    /**
1218     * Read bytes as they represent given type
1219     * @param byteOffset zero index to read
1220     * @param littleEndian read as little or big endian
1221     * @returns read value
1222     */
1223    public getFloat64(byteOffset: number, littleEndian?: boolean): number {
1224        if (littleEndian !== undefined && littleEndian.valueOf() == true) {
1225            return this.getFloat64Little(byteOffset)
1226        } else {
1227            return this.getFloat64Big(byteOffset)
1228        }
1229    }
1230
1231    /**
1232     * Read bytes as they represent given type
1233     * @param byteOffset zero index to read
1234     * @param littleEndian read as little or big endian
1235     * @returns read value
1236     */
1237    public getFloat64(byteOffset: int, littleEndian: boolean): number {
1238        if (littleEndian) {
1239            return this.getFloat64Little(byteOffset)
1240        } else {
1241            return this.getFloat64Big(byteOffset)
1242        }
1243    }
1244    private getFloat64Little(byteOffset: int): number {
1245        if (byteOffset + 8 > this.byteLength_) {
1246            throw new RangeError("wrong index")
1247        }
1248        let res: long = 0;
1249        const startByte = this.byteOffset_ + byteOffset
1250        for (let i = 0; i < 8; i++) {
1251            let byteVal = this.actualBuffer.at(startByte + i) as long;
1252            byteVal &= 0xff
1253            res = (res | byteVal << (8 * i)) as long;
1254        }
1255        return Double.bitCastFromLong(res)
1256    }
1257    private getFloat64Little(byteOffset: number): number {
1258        let res = this.getFloat64Little(byteOffset as int)
1259        return res;
1260    }
1261
1262    private setFloat64Little(byteOffset: int, value: number): void {
1263        if (byteOffset < 0 || byteOffset + 8.0 > this.byteLength_) {
1264            throw new RangeError("wrong index")
1265        }
1266        let bits = Double.bitCastToLong(value);
1267        const startByte = this.byteOffset_ + byteOffset
1268        for (let i = 0; i < 8; i++) {
1269            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
1270            this.actualBuffer.set(startByte + i,  byteVal)
1271        }
1272    }
1273    private setFloat64Little(byteOffset: number, value: number): void {
1274        const val: number = value as number;
1275        this.setFloat64Little(byteOffset as int, val)
1276    }
1277    private getFloat64Big(byteOffset: int): number {
1278        if (byteOffset + 8 > this.byteLength_) {
1279            throw new RangeError("wrong index")
1280        }
1281        let res: long = 0;
1282        const startByte = this.byteOffset_ + byteOffset
1283        for (let i = 0; i < 8; i++) {
1284            let byteVal = this.actualBuffer.at(startByte + 7 - i) as long;
1285            byteVal &= 0xff
1286            res = (res | byteVal << (8 * i)) as long;
1287        }
1288        return Double.bitCastFromLong(res)
1289    }
1290    private getFloat64Big(byteOffset: number): number {
1291        let res = this.getFloat64Big(byteOffset as int)
1292        return res;
1293    }
1294
1295    private setFloat64Big(byteOffset: int, value: number): void {
1296        if (byteOffset < 0 || byteOffset + 8.0 > this.byteLength_) {
1297            throw new RangeError("wrong index")
1298        }
1299        let bits = Double.bitCastToLong(value);
1300        const startByte = this.byteOffset_ + byteOffset
1301        for (let i = 0; i < 8; i++) {
1302            let byteVal = ((bits >>> (i * 8)) & 0xff) as byte
1303            this.actualBuffer.set(startByte + 7 - i,  byteVal)
1304        }
1305    }
1306    private setFloat64Big(byteOffset: number, value: number): void {
1307        const val: number = value as number;
1308        this.setFloat64Big(byteOffset as int, val)
1309    }
1310
1311    private static bigintFromULong(x: long): bigint {
1312        const noSignMask: long = ((1 as long) << 63) - 1
1313        return new BigInt(x & noSignMask) + (new BigInt((x >> 63) & 0x1) << new BigInt(63))
1314    }
1315}
1316