• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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
16function getTypeName(obj: unknown): string {
17  if (obj === null) {
18    return 'null';
19  }
20  if (typeof obj !== 'object') {
21    return typeof obj;
22  }
23  if (obj != null && obj.constructor != null) {
24    return obj.constructor.name;
25  }
26  return 'unknown';
27}
28
29class BusinessError extends Error {
30  errorNumber: number;
31  constructor(message: string, errorNumber: number) {
32    super(message);
33    this.name = 'BusinessError';
34    this.errorNumber = errorNumber;
35  }
36}
37
38const ERROR_CODES = {
39  TYPE_ERROR: 401, // 401: TYPE_ ERROR code value
40  RANGE_ERROR: 10200001, // 10200001: RANGE_ERROR code value
41  BUFFER_SIZE_ERROR: 10200009, // 10200009: BUFFER_SIZE_ERROR code value
42  PROPERTY_TYPE_ERROR: 10200013 // 10200013: TYPE_ ERROR code value
43};
44
45let errorMap = {
46  'typeError': ERROR_CODES.TYPE_ERROR,
47  'rangeError': ERROR_CODES.RANGE_ERROR,
48  'bufferSizeError': ERROR_CODES.BUFFER_SIZE_ERROR,
49  'typeErrorForProperty': ERROR_CODES.PROPERTY_TYPE_ERROR
50};
51
52enum TypeErrorCategories {
53  COMMON = 0,
54  SIZE,
55  ENCODING,
56  PROPERTY
57};
58enum RangeErrorCategories {
59  WHOLE = 0,
60  LEFT
61};
62
63const UINT32MAX = 4294967296;
64
65class ErrorMessage {
66  public errorNumber: number = 0;
67  public argument: string = '';
68  public types: string[] = [];
69  public receivedObj: unknown = '';
70  public rangeLeft: string | bigint | number = 0;
71  public rangeRight: string | bigint | number = 0;
72
73  public typeErrorCat: TypeErrorCategories = TypeErrorCategories.COMMON;
74  public rangeErrorCat: RangeErrorCategories = RangeErrorCategories.WHOLE;
75
76  constructor(errNo: number, argument?: string) {
77    this.errorNumber = errNo;
78    this.argument = argument === undefined ? '' : argument;
79  }
80
81  public setTypeInfo(types: string[], receivedObj: unknown): ErrorMessage {
82    this.types = types;
83    this.receivedObj = receivedObj;
84    return this;
85  }
86
87  public setSizeTypeInfo(types: string[], receivedObj: unknown): ErrorMessage {
88    this.types = types;
89    this.receivedObj = receivedObj;
90    this.typeErrorCat = TypeErrorCategories.SIZE;
91    return this;
92  }
93
94  public setEncodingTypeInfo(types: string[], receivedObj: unknown): ErrorMessage {
95    this.types = types;
96    this.receivedObj = receivedObj;
97    this.typeErrorCat = TypeErrorCategories.ENCODING;
98    return this;
99  }
100
101  public setProperty(argument: string): ErrorMessage {
102    this.typeErrorCat = TypeErrorCategories.PROPERTY;
103    this.argument = argument;
104    return this;
105  }
106
107  public setRangeInfo(rangeLeft: string | bigint | number, rangeRight: string | bigint | number, receivedObj: unknown): ErrorMessage {
108    this.rangeLeft = rangeLeft;
109    this.rangeRight = rangeRight;
110    this.receivedObj = receivedObj;
111    return this;
112  }
113
114  public setRangeLeftInfo(rangeLeft: string | number, receivedObj: unknown): ErrorMessage {
115    this.rangeLeft = rangeLeft;
116    this.receivedObj = receivedObj;
117    this.rangeErrorCat = RangeErrorCategories.LEFT;
118    return this;
119  }
120
121  public setSizeInfo(receivedObj: string): ErrorMessage {
122    this.receivedObj = receivedObj;
123    return this;
124  }
125
126  private getErrorTypeStrings(types: string[]): string {
127    let ret = types.join(', ');
128    ret = ret.replace(',', ' or');
129    return ret;
130  }
131
132  private getArgumentStr(): string {
133    return 'The type of "' + this.argument + '" must be ';
134  }
135
136  private getTypeString(): string {
137    let str = '';
138    switch (this.typeErrorCat) {
139      case TypeErrorCategories.COMMON:
140        str += this.getArgumentStr() + this.getErrorTypeStrings(this.types) +
141          '. Received value is: ' + getTypeName(this.receivedObj);
142        break;
143      case TypeErrorCategories.SIZE:
144        str += this.getArgumentStr() + this.getErrorTypeStrings(this.types) +
145          ' and the value cannot be negative. Received value is: ' + getTypeName(this.receivedObj);
146        break;
147      case TypeErrorCategories.ENCODING:
148        str += this.getArgumentStr() + this.getErrorTypeStrings(this.types) +
149          '. the encoding ' + this.receivedObj + ' is unknown';
150        break;
151      case TypeErrorCategories.PROPERTY:
152        str += 'Cannot set property ' + this.argument + ' of Buffer which has only a getter';
153      default:
154        break;
155    }
156    return str;
157  }
158
159  private getRangeString(): string {
160    let str = '';
161    switch (this.rangeErrorCat) {
162      case RangeErrorCategories.WHOLE:
163        str += 'The value of "' + this.argument + '" is out of range. It must be >= ' + this.rangeLeft +
164          ' and <= ' + this.rangeRight + '. Received value is: ' + this.receivedObj;
165        break;
166      case RangeErrorCategories.LEFT:
167        str += 'The value of "' + this.argument + '" is out of range. It must be >= ' + this.rangeLeft +
168          '. Received value is: ' + this.receivedObj;
169        break;
170      default:
171        break;
172    }
173    return str;
174  }
175
176  public getString(): string {
177    let str = '';
178    switch (this.errorNumber) {
179      case ERROR_CODES.TYPE_ERROR:
180      case ERROR_CODES.PROPERTY_TYPE_ERROR:
181        str = this.getTypeString();
182        break;
183      case ERROR_CODES.RANGE_ERROR:
184        str = this.getRangeString();
185        break;
186      case ERROR_CODES.BUFFER_SIZE_ERROR:
187        str = 'Buffer size must be a multiple of ' + this.receivedObj;
188        break;
189      default:
190        break;
191    }
192    return str;
193  }
194}
195
196interface NativeBuffer {
197  new(type: number, length: number): NativeBuffer;
198  new(type: number, array: number[]): NativeBuffer;
199  new(type: number, raw: NativeBuffer): NativeBuffer;
200  new(type: number, str: string, encoding: string): NativeBuffer;
201  new(type: number, arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): NativeBuffer;
202  new(type: number, pool: NativeBuffer, poolOffset: number, length: number): NativeBuffer;
203  setArray(array: Array<number>): undefined;
204  getLength(): number;
205  getByteOffset(): number;
206  writeString(value: string, offset: number, length: number, encoding: string): number;
207  fromString(str: string, encoding: string, size: number): NativeBuffer;
208  fillString(value: string, offset: number, end: number, encoding: string): undefined;
209  fillNumbers(value: number[], offset: number, end: number): undefined;
210  fillBuffer(value: NativeBuffer, offset: number, end: number): undefined;
211  writeInt32BE(value: number, offset: number): number;
212  readInt32BE(offset: number): number;
213  writeInt32LE(value: number, offset: number): number;
214  readInt32LE(offset: number): number;
215  writeUInt32BE(value: number, offset: number): number;
216  readUInt32BE(offset: number): number;
217  writeUInt32LE(value: number, offset: number): number;
218  readUInt32LE(offset: number): number;
219  getBufferData(): Array<number>;
220  get(index: number): number;
221  set(index: number, value: number): undefined;
222  subBuffer(target: NativeBuffer, start: number, end: number): undefined;
223  copy(target: NativeBuffer, targetStart: number, sourceStart: number, sourceEnd: number): number;
224  compare(target: NativeBuffer, targetStart: number, sourceStart: number, length: number): number;
225  toUtf8(start: number, end: number): string;
226  toBase64(start: number, end: number): string;
227  indexOf(value: string, byteOffset: number, encoding: string, isReverse: boolean): number;
228}
229interface NativeBlob {
230  new(src: Array<number>): NativeBlob;
231  new(blob: NativeBlob, start: number, end?: number): NativeBlob;
232  arraybuffer(): Promise<ArrayBuffer>;
233  text(): Promise<string>;
234  getBytes(): Array<number>;
235}
236interface IBuffer {
237  Buffer: NativeBuffer;
238  Blob: NativeBlob;
239  utf8ByteLength(str: string): number;
240  utf8StringToNumbers(str: string): Array<number>;
241}
242
243declare function requireInternal(s: string): IBuffer;
244const internalBuffer = requireInternal('buffer');
245const bufferSymbol = Symbol('bufferClass');
246const lengthSymbol = Symbol('bufferLength');
247const bufferEncoding = ['ascii', 'utf8', 'utf-8', 'utf16le', 'utf-16le', 'ucs2', 'ucs-2',
248  'base64', 'base64url', 'latin1', 'binary', 'hex'];
249
250enum ParaType {
251  NUMBER = 0,
252  BUFFER,
253  UINT8ARRAY,
254  ARRAYBUFFER,
255  NUMBERS,
256  STRING
257}
258const initialPoolSize: number = 8 * 1024; // 8 * 1024 : initialPoolSize number
259let poolSize: number;
260let poolOffset: number;
261let pool: Buffer;
262const MAX_LENGTH: number = Math.pow(2, 32); // 2 : 32 : MAX_LENGTH code
263const TWO_POW_FIFTEEN: number = Math.pow(2, 15); // 2 : 15 : two to power of fifteen code
264const TWO_POW_SEVEN: number = Math.pow(2, 7); // 2 : 7 : two to power of seven code
265const oneByte: number = 1; // 1 : one Byte
266const twoBytes: number = 2; // 2 : two Bytes
267const threeBytes: number = 3; // 3 : three Bytes
268const fourBytes: number = 4; // 4 : four Bytes
269const fiveBytes: number = 5; // 5 : five Bytes
270const sixBytes: number = 6; // 6 : six Bytes
271const sevenBytes: number = 7; // 7 : seven Bytes
272const eightBytes: number = 8; // 8 : eight Bytes
273
274
275type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array |
276Int32Array | Uint32Array | Float32Array | Float64Array;
277type BackingType = Buffer | TypedArray | DataView | ArrayBuffer | SharedArrayBuffer;
278const float64Array: Float64Array = new Float64Array(1);
279const uInt8Float64Array: Uint8Array = new Uint8Array(float64Array.buffer);
280const float32Array: Float32Array = new Float32Array(1);
281const uInt8Float32Array: Uint8Array = new Uint8Array(float32Array.buffer);
282
283function createPool(): void {
284  poolSize = initialPoolSize;
285  pool = new Buffer(poolSize);
286  poolOffset = 0;
287}
288
289function alignPool(): void {
290  if (poolOffset & 0x7) {
291    poolOffset |= 0x7; // 0x7 : align offset based of 8-bits
292    poolOffset++;
293  }
294}
295type Options = {
296  type: string,
297  endings: string
298};
299
300const _log = console.log;
301
302console.log = function (...args) {
303  if (args.length === 1 && args[0] instanceof Buffer) {
304    let buf: Buffer = args[0];
305    let bufArr: Array<number> = buf[bufferSymbol].getBufferData();
306    let getStr = function (bufArr: Array<number>, len: number): string {
307      let str: string = '';
308      for (let i = 0; i < len; i++) {
309        let strTemp: string = bufArr[i].toString(16); // 16 : convert the element to a hexadecimal string
310        strTemp = (strTemp.length === 1) ? `0${strTemp}` : strTemp;
311        str += ` ${strTemp}`;
312      }
313      return str;
314    };
315    let msg: string = '';
316    if (bufArr.length > 50) {
317      let bufStr: string = getStr(bufArr, 50); // 50: Maximum number of log displays
318      msg = bufStr + ` ... ${bufArr.length - 50} more bytes`;
319    } else {
320      msg = getStr(bufArr, bufArr.length);
321    }
322    _log.call(console, `<Buffer ${msg}>`);
323  } else {
324    _log(...args);
325  }
326};
327
328class Blob {
329  blobClass: NativeBlob;
330  private _size: number;
331  private _type: string;
332
333  public get size(): number {
334    return this._size;
335  }
336
337  public get type(): string {
338    return this._type;
339  }
340
341  constructor(sources: string[] | ArrayBuffer[] | TypedArray[] | DataView[] | Blob[], options: Options) {
342    if (options === undefined || options === null) {
343      options = {
344        type: '',
345        endings: 'transparent'
346      };
347    }
348    typeErrorCheck(options, ['Object'], 'options');
349
350    let type = options.type ? options.type : '';
351    let endings = options.endings ? options.endings : 'transparent';
352    if (endings !== 'transparent' && endings !== 'native') {
353      throw new BusinessError('invalid arg value of options.endings', errorMap.typeError);
354    }
355    let arr: Array<number> = [];
356    if (sources instanceof Array || isTypedArray(sources)) {
357      for (const value of sources) {
358        arr = arr.concat(this.normalizeSource(value));
359      }
360    } else {
361      throw typeError(sources, 'sources', ['Iterable']);
362    }
363    this._size = arr.length;
364    this._type = type;
365    this.blobClass = new internalBuffer.Blob(arr);
366  }
367
368  normalizeSource(source: string | ArrayBuffer | TypedArray | DataView | Blob | Buffer): Array<number> {
369    let ret: Array<number> = [];
370    if (typeof source === 'string') {
371      return internalBuffer.utf8StringToNumbers(source);
372    } else if (source instanceof ArrayBuffer) {
373      return Array.prototype.slice.call(new Uint8Array(source));
374    } else if (isTypedArray(source)) {
375      let numbers = Array.prototype.slice.call(source);
376      let str = '';
377      for (let i = 0, len = numbers.length; i < len; i++) {
378        str += numbers[i].toString();
379      }
380      let charCodeArr = [];
381      for (let i = 0, len = str.length; i < len; i++) {
382        let code = str.charCodeAt(i);
383        charCodeArr.push(code);
384      }
385      return charCodeArr;
386    } else if (source instanceof DataView) {
387      return Array.prototype.slice.call(new Uint8Array(source.buffer));
388    } else if (source instanceof Blob) {
389      return source.blobClass.getBytes();
390    } else if (source instanceof Buffer) {
391      for (let i = 0, len = source.length; i < len; i++) {
392        ret[i] = source[i];
393      }
394      return ret;
395    }
396    return [];
397  }
398
399  arrayBuffer(): Promise<ArrayBuffer> {
400    return this.blobClass.arraybuffer();
401  }
402
403  text(): Promise<string> {
404    return this.blobClass.text();
405  }
406
407  slice(start?: number, end?: number, type?: string): Blob {
408    let newBlob = Object.create(this);
409    if (type !== undefined) {
410      newBlob._type = type;
411    }
412    if (start === undefined || start === null) {
413      return newBlob;
414    }
415    if (end === undefined || end === null) {
416      newBlob.blobClass = new internalBuffer.Blob(this.blobClass, start);
417      return newBlob;
418    }
419    if (start > end) {
420      return newBlob;
421    }
422    if ((start > 0 && end < 0) || (start < 0 && end > 0)) {
423      return newBlob;
424    }
425    newBlob.blobClass = new internalBuffer.Blob(this.blobClass, start, end);
426    return newBlob;
427  }
428}
429
430let utils = {
431  eightBits: 0xFF,
432  sixtyFourBit: 0xFFFFFFFFn,
433
434  getLowerEight(value: number): number {
435    return value & this.eightBits;
436  },
437  getLowerSixtyFour(value: bigint): bigint {
438    return value & this.sixtyFourBit;
439  }
440};
441
442enum Style {
443  intBE = 0,
444  intLE,
445  uintBE,
446  uintLE
447};
448
449class HandlerBuffer {
450  get(obj: Buffer, prop: string): number | undefined {
451    if (typeof prop === 'number') {
452      if (prop >= obj.length) {
453        return obj[prop];
454      }
455      return obj[bufferSymbol].get(prop);
456    }
457    return obj[prop];
458  }
459  set(obj: Buffer, prop: string | symbol, value: number): boolean {
460    if (typeof prop === 'number') {
461      if (prop >= obj.length) {
462        return false;
463      }
464      value = utils.getLowerEight(value);
465      obj[bufferSymbol].set(prop, value);
466      return true;
467    }
468
469    if (prop === lengthSymbol || prop === bufferSymbol) {
470      obj[prop] = value;
471      return true;
472    } else if (prop === 'length' || prop === 'buffer' || prop === 'byteOffset') {
473      throw typeErrorForProperty(prop);
474    }
475    return false;
476  }
477  ownKeys(obj: Buffer): Array<string> {
478    let keys: Array<string> = [];
479    for (let i = 0, len = obj.length; i < len; i++) {
480      keys.push(i.toString());
481    }
482    return keys;
483  }
484}
485class Buffer {
486  private _arrayBuffer: ArrayBuffer | undefined;
487
488  public get length(): number {
489    return this[lengthSymbol];
490  }
491
492  public get byteOffset(): number {
493    return this[bufferSymbol].getByteOffset();
494  }
495
496  public get buffer(): ArrayBufferLike {
497    if (this._arrayBuffer) {
498      return this._arrayBuffer;
499    }
500    let arr = this[bufferSymbol].getBufferData();
501    return new Uint8Array(arr).buffer;
502  }
503
504  constructor(value: number | Buffer | Uint8Array | ArrayBuffer | Array<number> | string,
505    byteOffsetOrEncoding?: number | string, length?: number) {
506    if (arguments.length === 1) {
507      if (typeof value === 'number') {
508        this[bufferSymbol] = new internalBuffer.Buffer(ParaType.NUMBER, value);
509      } else if (value instanceof Buffer) {
510        this[bufferSymbol] = new internalBuffer.Buffer(ParaType.BUFFER, value[bufferSymbol]);
511      } else if (value instanceof Uint8Array) {
512        this[bufferSymbol] = new internalBuffer.Buffer(ParaType.UINT8ARRAY, value);
513      } else if (value instanceof Array) {
514        this[bufferSymbol] = new internalBuffer.Buffer(ParaType.NUMBERS, value);
515      }
516    } else if (arguments.length === 3 && typeof byteOffsetOrEncoding === 'number' && typeof length === 'number') {
517      if (value instanceof ArrayBuffer) {
518        this[bufferSymbol] = new internalBuffer.Buffer(ParaType.ARRAYBUFFER, value, byteOffsetOrEncoding, length);
519        this._arrayBuffer = value;
520      } else if (value instanceof Buffer) {
521        this[bufferSymbol] = new internalBuffer.Buffer(ParaType.BUFFER, value[bufferSymbol], byteOffsetOrEncoding, length);
522      }
523    } else if (arguments.length === twoBytes && typeof value === 'string' && typeof byteOffsetOrEncoding === 'string') {
524      this[bufferSymbol] = new internalBuffer.Buffer(ParaType.STRING, value, byteOffsetOrEncoding);
525    } else {
526      this[bufferSymbol] = new internalBuffer.Buffer(ParaType.NUMBER, 0);
527    }
528    this[lengthSymbol] = this[bufferSymbol].getLength();
529    return new Proxy(this, new HandlerBuffer());
530  }
531
532  /**
533   * Fills buf with the specified value. If the offset and end are not given, the entire buf will be filled.
534   * @since 9
535   * @syscap SystemCapability.Utils.Lang
536   * @param value The value with which to fill buf
537   * @param [offset = 0] Number of bytes to skip before starting to fill buf
538   * @param [end = buf.length] Where to stop filling buf (not inclusive)
539   * @param [encoding='utf8'] The encoding for value if value is a string
540   * @return A reference to buf
541   */
542  fill(value: string | Buffer | Uint8Array | number, offset: number = 0, end: number = this.length,
543    encoding: string = 'utf8'): Buffer {
544    if (this.length === 0) {
545      return this;
546    }
547    if (offset === null) {
548      offset = 0;
549    }
550    if (end === null) {
551      end = this.length;
552    }
553    if (encoding === null) {
554      encoding = 'utf8';
555    }
556    if (arguments.length === twoBytes) {
557      if (typeof offset === 'string') {
558        encoding = offset;
559        offset = 0;
560      }
561    } else if (arguments.length === 3) {
562      if (typeof end === 'string') {
563        encoding = end;
564        end = this.length;
565      }
566    }
567    if (typeof offset !== 'number') {
568      typeErrorCheck(offset, ['number'], 'offset');
569    }
570    if (typeof end === 'number') {
571      typeErrorCheck(end, ['number'], 'end');
572    }
573    if (typeof encoding !== 'string') {
574      typeErrorCheck(encoding, ['string'], 'encoding');
575    }
576
577    const normalizedEncoding = encodingTypeErrorCheck(encoding);
578
579    rangeErrorCheck(offset, 'offset', 0, UINT32MAX);
580    rangeErrorCheck(end, 'end', 0, this.length);
581
582    if (offset > end - 1) {
583      return this;
584    }
585    if (typeof value === 'string') {
586      if (normalizedEncoding === 'hex') {
587        let numbers = hexStrtoNumbers(value);
588        this[bufferSymbol].fillNumbers(numbers, offset, end);
589      } else {
590        this[bufferSymbol].fillString(value, offset, end, normalizedEncoding);
591      }
592    }
593    if (typeof value === 'number') {
594      let nums: Array<number> = [];
595      nums.push(value & 0xFF); // 0xFF : get lower 8-bits
596      this[bufferSymbol].fillNumbers(nums, offset, end);
597    }
598    if (value instanceof Buffer) {
599      this[bufferSymbol].fillBuffer(value[bufferSymbol], offset, end);
600    }
601    if (value instanceof Uint8Array) {
602      let nums = Array.from(value);
603      this[bufferSymbol].fillNumbers(nums, offset, end);
604    }
605    return this;
606  }
607
608  write(str: string, offset: number = 0, length: number = this.length - offset, encoding: string = 'utf8'): number {
609    typeErrorCheck(str, ['string'], 'str');
610    if (offset === null) {
611      offset = 0;
612    }
613    if (length === null) {
614      length = this.length - offset;
615    }
616    if (encoding === null) {
617      encoding = 'utf8';
618    }
619    if (arguments.length === 1) {
620      return this[bufferSymbol].writeString(str, 0, length, 'utf8');
621    } else if (arguments.length === twoBytes) {
622      if (typeof offset === 'string') {
623        encoding = offset;
624        let encode = encodingTypeErrorCheck(encoding);
625        return this[bufferSymbol].writeString(str, 0, this.length, encode);
626      } else if (typeof offset === 'number') {
627        rangeErrorCheck(offset, 'offset', 0, this.length - 1);
628        return this[bufferSymbol].writeString(str, offset, length, 'utf8');
629      } else {
630        throw typeError(offset, 'offset', ['number']);
631      }
632    } else if (arguments.length === 3) {
633      typeErrorCheck(offset, ['number'], 'offset');
634      rangeErrorCheck(offset, 'offset', 0, this.length - 1);
635      if (typeof length === 'number') {
636        rangeErrorCheck(length, 'length', 0, this.length);
637        length = (length > this.length - offset) ? (this.length - offset) : length;
638        return this[bufferSymbol].writeString(str, offset, length, 'utf8');
639      } else if (typeof length === 'string') {
640        encoding = length;
641        length = this.length - offset;
642        let encode = encodingTypeErrorCheck(encoding);
643        return this[bufferSymbol].writeString(str, offset, length, encode);
644      } else {
645        throw typeError(length, 'length', ['number']);
646      }
647    } else {
648      if (typeof offset !== 'number') {
649        throw typeError(offset, 'offset', ['number']);
650      } else if (typeof length !== 'number') {
651        throw typeError(length, 'length', ['number']);
652      } else {
653        rangeErrorCheck(offset, 'offset', 0, this.length - 1);
654        let encode = encodingTypeErrorCheck(encoding);
655        length = (length > this.length - offset) ? (this.length - offset) : length;
656        return this[bufferSymbol].writeString(str, offset, length, encode);
657      }
658    }
659  }
660
661  convertToBig64BE(value: bigint, offset: number): number {
662    let byteValue = Number(utils.getLowerSixtyFour(value));
663    let bitNum: number = eightBytes;
664    for (let i = bitNum - 1; i > 0; i--) {
665      this[offset + i] = byteValue;
666      if (i === fourBytes) {
667        byteValue = Number(utils.getLowerSixtyFour(value >> 32n));
668      } else {
669        byteValue = byteValue >> eightBytes;
670      }
671    }
672    this[offset] = byteValue;
673    return offset + eightBytes;
674  }
675
676  convertToBig64LE(value: bigint, offset: number): number {
677    let byteValue = Number(utils.getLowerSixtyFour(value));
678    let bitNum = eightBytes;
679    for (let i = 0; i < bitNum - 1; i++) {
680      this[offset++] = byteValue;
681      if (i === 3) {
682        byteValue = Number(utils.getLowerSixtyFour(value >> 32n)); // 32 means offset 32-bits
683      } else {
684        byteValue = byteValue >> eightBytes;
685      }
686    }
687    this[offset++] = byteValue;
688    return offset;
689  }
690
691  private readData(offset: number, byteLength: number, style: Style): number | undefined {
692    rangeErrorCheck(byteLength, 'byteLength', oneByte, sixBytes);
693    if (style === Style.intBE) {
694      switch (byteLength) {
695        case oneByte:
696          return this.readInt8(offset);
697        case twoBytes:
698          return this.readInt16BE(offset);
699        case threeBytes:
700          return this.readInt24BE(offset);
701        case fourBytes:
702          return this.readInt32BE(offset);
703        case fiveBytes:
704          return this.readInt40BE(offset);
705        case sixBytes:
706          return this.readInt48BE(offset);
707        default:
708          break;
709      }
710    } else if (style === Style.intLE) {
711      switch (byteLength) {
712        case oneByte:
713          return this.readInt8(offset);
714        case twoBytes:
715          return this.readInt16LE(offset);
716        case threeBytes:
717          return this.readInt24LE(offset);
718        case fourBytes:
719          return this.readInt32LE(offset);
720        case fiveBytes:
721          return this.readInt40LE(offset);
722        case sixBytes:
723          return this.readInt48LE(offset);
724        default:
725          break;
726      }
727    } else if (style === Style.uintLE) {
728      switch (byteLength) {
729        case oneByte:
730          return this.readUInt8(offset);
731        case twoBytes:
732          return this.readUInt16LE(offset);
733        case threeBytes:
734          return this.readUInt24LE(offset);
735        case fourBytes:
736          return this.readUInt32LE(offset);
737        case fiveBytes:
738          return this.readUInt40LE(offset);
739        case sixBytes:
740          return this.readUInt48LE(offset);
741        default:
742          break;
743      }
744    } else if (style === Style.uintBE) {
745      switch (byteLength) {
746        case oneByte:
747          return this.readUInt8(offset);
748        case twoBytes:
749          return this.readUInt16BE(offset);
750        case threeBytes:
751          return this.readUInt24BE(offset);
752        case fourBytes:
753          return this.readUInt32BE(offset);
754        case fiveBytes:
755          return this.readUInt40BE(offset);
756        case sixBytes:
757          return this.readUInt48BE(offset);
758        default:
759          break;
760      }
761    }
762    return undefined;
763  }
764
765  private writeData(value: number, offset: number, byteLength: number, style: Style): number | undefined {
766    rangeErrorCheck(byteLength, 'byteLength', oneByte, sixBytes);
767    if (style === Style.intBE) {
768      switch (byteLength) {
769        case oneByte:
770          return this.writeInt8(value, offset);
771        case twoBytes:
772          return this.writeInt16BE(value, offset);
773        case threeBytes:
774          return this.writeUInt24BE(value, offset);
775        case fourBytes:
776          return this.writeInt32BE(value, offset);
777        case fiveBytes:
778          return this.writeUInt40BE(value, offset);
779        case sixBytes:
780          return this.writeUInt48BE(value, offset);
781        default:
782          break;
783      }
784    } else if (style === Style.intLE) {
785      switch (byteLength) {
786        case oneByte:
787          return this.writeUInt8(value, offset);
788        case twoBytes:
789          return this.writeUInt16LE(value, offset);
790        case threeBytes:
791          return this.writeUInt24LE(value, offset);
792        case fourBytes:
793          return this.writeUInt32LE(value, offset);
794        case fiveBytes:
795          return this.writeUInt40LE(value, offset);
796        case sixBytes:
797          return this.writeUInt48LE(value, offset);
798        default:
799          break;
800      }
801    } else if (style === Style.uintLE) {
802      switch (byteLength) {
803        case oneByte:
804          return this.writeUInt8(value, offset);
805        case twoBytes:
806          return this.writeUInt16LE(value, offset);
807        case threeBytes:
808          return this.writeUInt24LE(value, offset);
809        case fourBytes:
810          return this.writeUInt32LE(value, offset);
811        case fiveBytes:
812          return this.writeUInt40LE(value, offset);
813        case sixBytes:
814          return this.writeUInt48LE(value, offset);
815        default:
816          break;
817      }
818    } else if (style === Style.uintBE) {
819      switch (byteLength) {
820        case oneByte:
821          return this.writeUInt8(value, offset);
822        case twoBytes:
823          return this.writeUInt16BE(value, offset);
824        case threeBytes:
825          return this.writeUInt24BE(value, offset);
826        case fourBytes:
827          return this.writeUInt32BE(value, offset);
828        case fiveBytes:
829          return this.writeUInt40BE(value, offset);
830        case sixBytes:
831          return this.writeUInt48BE(value, offset);
832        default:
833          break;
834      }
835    }
836    return undefined;
837  }
838
839  writeBigInt64BE(value: bigint, offset: number = 0): number {
840    typeErrorCheck(value, ['bigint'], 'value');
841    if (offset === null) {
842      offset = 0;
843    }
844    typeErrorCheck(offset, ['number'], 'offset');
845    this.checkOffsetRange(offset, eightBytes);
846    // 2n : 63n : 1n : The range of 64-bit BigInt value is from negative the 63st power of 2 to the 63st power of 2 minus 1
847    rangeErrorCheck(value, 'value', -(2n ** 63n), 2n ** 63n, '-(2n ** 63n)', '2n ** 63n');
848    return this.convertToBig64BE(value, offset);
849  }
850
851  readBigInt64BE(offset: number = 0): bigint {
852    if (offset === null) {
853      offset = 0;
854    }
855    typeErrorCheck(offset, ['number'], 'offset');
856    this.checkOffsetRange(offset, eightBytes);
857    const val = (this[offset] << 24) + this.calculationBE(offset + 1, threeBytes); // 24 : the first val for this[offset]
858    return (BigInt(val) << 32n) + // 32 means offset 32-bits left
859      BigInt(this.calculationBE(offset + fourBytes, fourBytes));
860  }
861
862  writeBigInt64LE(value: bigint, offset: number = 0): number {
863    typeErrorCheck(value, ['bigint'], 'value');
864    if (offset === null) {
865      offset = 0;
866    }
867    typeErrorCheck(offset, ['number'], 'offset');
868    this.checkOffsetRange(offset, eightBytes);
869    // 2n : 63n : 1n : The range of 64-bit BigInt value is from negative the 63st power of 2 to the 63st power of 2 minus 1
870    rangeErrorCheck(value, 'value', -(2n ** 63n), 2n ** 63n, '-(2n ** 63n)', '2n ** 63n');
871
872    return this.convertToBig64LE(value, offset);
873  }
874
875  private calculationLE(offset: number, count: number): number {
876    let result: number = 0;
877    for (let i = 0; i < count; i++) {
878      result += this[offset++] * Math.pow(twoBytes, eightBytes * i);
879    }
880    return result;
881  }
882
883  private calculationBE(offset: number, count: number): number {
884    let result: number = 0;
885    for (let i = count - 1; i >= 0; i--) {
886      result += this[offset++] * Math.pow(twoBytes, eightBytes * i);
887    }
888    return result;
889  }
890
891  readBigInt64LE(offset: number = 0): bigint {
892    if (offset === null) {
893      offset = 0;
894    }
895    typeErrorCheck(offset, ['number'], 'offset');
896    this.checkOffsetRange(offset, eightBytes);
897    const val = this.calculationLE(offset + fourBytes, threeBytes) + (this[offset + sevenBytes] << 24); // 24 means offset 24-bits left
898    return (BigInt(val) << 32n) + BigInt(this.calculationLE(offset, fourBytes)); // 32 means offset 32-bits left
899  }
900
901  writeBigUInt64BE(value: bigint, offset: number = 0): number {
902    typeErrorCheck(value, ['bigint'], 'value');
903    if (offset === null) {
904      offset = 0;
905    }
906    typeErrorCheck(offset, ['number'], 'offset');
907    this.checkOffsetRange(offset, eightBytes);
908    // 2n : 64n : 1n : The range of 64-bit BigUInt value is from 0 to the 64st power of 2 minus 1
909    rangeErrorCheck(value, 'value', 0, 2n ** 64n - 1n, '0', '2n ** 64n - 1n');
910
911    return this.convertToBig64BE(value, offset);
912  }
913
914  readBigUInt64BE(offset: number = 0): bigint {
915    if (offset === null) {
916      offset = 0;
917    }
918    typeErrorCheck(offset, ['number'], 'offset');
919    this.checkOffsetRange(offset, eightBytes);
920    const hi = this.calculationBE(offset, fourBytes);
921
922    const lo = this.calculationBE(offset + fourBytes, fourBytes);
923    return (BigInt(hi) << 32n) + BigInt(lo); // 32 means offset 32-bits left
924  }
925
926  writeBigUInt64LE(value: bigint, offset: number = 0): number {
927    typeErrorCheck(value, ['bigint'], 'value');
928    if (offset === null) {
929      offset = 0;
930    }
931    typeErrorCheck(offset, ['number'], 'offset');
932    this.checkOffsetRange(offset, eightBytes);
933    rangeErrorCheck(value, 'value', 0, 2n ** 64n - 1n, '0', '2n ** 64n - 1n'); // 2n : 64n : 1n : The range of BigUInt
934
935    return this.convertToBig64LE(value, offset);
936  }
937
938  readBigUInt64LE(offset: number = 0): bigint {
939    if (offset === null) {
940      offset = 0;
941    }
942    typeErrorCheck(offset, ['number'], 'offset');
943    this.checkOffsetRange(offset, eightBytes);
944    const lo = this.calculationLE(offset, fourBytes);
945    const hi = this.calculationLE(offset + fourBytes, fourBytes);
946    return BigInt(lo) + (BigInt(hi) << 32n); // 32 means offset 32-bits left
947  }
948
949  writeInt8(value: number, offset: number = 0): number {
950    typeErrorCheck(value, ['number'], 'value');
951    if (offset === null) {
952      offset = 0;
953    }
954    typeErrorCheck(offset, ['number'], 'offset');
955    this.checkOffsetRange(offset, oneByte);
956    rangeErrorCheck(value, 'value', - (TWO_POW_SEVEN), (TWO_POW_SEVEN - 1));
957    value = +value;
958
959    this[offset] = value;
960    return offset + 1;
961  }
962
963  readInt8(offset: number = 0): number {
964    if (offset === null) {
965      offset = 0;
966    }
967    typeErrorCheck(offset, ['number'], 'offset');
968    this.checkOffsetRange(offset, oneByte);
969    const val = this[offset];
970
971    return val | (val & TWO_POW_SEVEN) * 0x1fffffe; // 0x1fffffe mean the decimal value is 33554430"
972  }
973
974  writeInt16BE(value: number, offset: number = 0): number {
975    typeErrorCheck(value, ['number'], 'value');
976    if (offset === null) {
977      offset = 0;
978    }
979    typeErrorCheck(offset, ['number'], 'offset');
980    this.checkOffsetRange(offset, twoBytes);
981    rangeErrorCheck(value, 'value', - (TWO_POW_FIFTEEN), (TWO_POW_FIFTEEN - 1));
982    value = +value;
983    this[offset++] = (value >>> eightBytes);
984    this[offset++] = value;
985    return offset;
986  }
987
988  readInt16BE(offset: number = 0): number {
989    if (offset === null) {
990      offset = 0;
991    }
992    typeErrorCheck(offset, ['number'], 'offset');
993    this.checkOffsetRange(offset, twoBytes);
994    const val = this.calculationBE(offset, twoBytes);
995    return val | (val & TWO_POW_FIFTEEN) * 0x1fffe; // 0x1fffe mean the decimal value is 131070"
996  }
997
998  writeInt16LE(value: number, offset: number = 0): number {
999    typeErrorCheck(value, ['number'], 'value');
1000    if (offset === null) {
1001      offset = 0;
1002    }
1003    typeErrorCheck(offset, ['number'], 'offset');
1004    this.checkOffsetRange(offset, twoBytes);
1005    rangeErrorCheck(value, 'value', -(TWO_POW_FIFTEEN), (TWO_POW_FIFTEEN - 1));
1006    value = +value;
1007    this[offset++] = value;
1008    this[offset++] = (value >>> eightBytes);
1009    return offset;
1010  }
1011
1012  readInt16LE(offset: number = 0): number {
1013    if (offset === null) {
1014      offset = 0;
1015    }
1016    typeErrorCheck(offset, ['number'], 'offset');
1017    this.checkOffsetRange(offset, twoBytes);
1018    const val = this[offset] + this[offset + 1] * Math.pow(twoBytes, eightBytes);
1019    return val | (val & TWO_POW_FIFTEEN) * 0x1fffe; // 0x1fffe mean the decimal value is 131070"
1020  }
1021
1022  readUInt16LE(offset: number = 0): number {
1023    if (offset === null) {
1024      offset = 0;
1025    }
1026    typeErrorCheck(offset, ['number'], 'offset');
1027    this.checkOffsetRange(offset, twoBytes);
1028    return this[offset] + this[offset + 1] * Math.pow(twoBytes, eightBytes); // 8 means offset 8 bits
1029  }
1030
1031  writeUInt8(value: number, offset: number = 0): number {
1032    typeErrorCheck(value, ['number'], 'value');
1033    if (offset === null) {
1034      offset = 0;
1035    }
1036    typeErrorCheck(offset, ['number'], 'offset');
1037    this.checkOffsetRange(offset, oneByte);
1038    rangeErrorCheck(value, 'value', 0, 255); // 255 : The range of 8-bit UInt value is from 0 to the 255
1039    value = +value;
1040
1041    this[offset] = value;
1042    return offset + 1;
1043  }
1044
1045  readUInt8(offset: number = 0): number {
1046    if (offset === null) {
1047      offset = 0;
1048    }
1049    typeErrorCheck(offset, ['number'], 'offset');
1050    this.checkOffsetRange(offset, oneByte);
1051    const val = this[offset];
1052    return val;
1053  }
1054
1055  writeIntBE(value: number, offset: number, byteLength: number): number | undefined {
1056    typeErrorCheck(value, ['number'], 'value');
1057    typeErrorCheck(offset, ['number'], 'offset');
1058    typeErrorCheck(byteLength, ['number'], 'byteLength');
1059    return this.writeData(value, offset, byteLength, Style.intBE);
1060  }
1061
1062  private writeUInt24BE(value: number, offset: number = 0): number {
1063    this.checkOffsetRange(offset, threeBytes);
1064    // 24 : The range of 24-bit UInt value is from 0 to the 24st power of 2 minus 1
1065    rangeErrorCheck(value, 'value', 0, twoBytes ** 24 - 1, '0', '2**24 - 1');
1066    value = +value;
1067    for (let i: number = twoBytes; i > 0; i--) {
1068      this[offset + i] = value;
1069      value = value >>> eightBytes;
1070    }
1071    this[offset] = value;
1072    return offset + threeBytes;
1073  }
1074
1075  private writeUInt40BE(value: number, offset: number = 0): number {
1076    this.checkOffsetRange(offset, fiveBytes);
1077    // 2 : 40 : The range of 40-bit UInt value is from 0 to the 40st power of 2 minus 1
1078    rangeErrorCheck(value, 'value', 0, twoBytes ** 40 - 1, '0', '2**40 - 1');
1079    value = +value;
1080    this[offset++] = Math.floor(value * Math.pow(twoBytes, -32)); // -32 means offset 32 bits to left
1081    for (let i: number = 3; i > 0; i--) { // 3 is array->maxIndex
1082      this[offset + i] = value;
1083      value = value >>> eightBytes;
1084    }
1085    this[offset] = value;
1086    return offset + fourBytes;
1087  }
1088
1089  private writeUInt48BE(value: number, offset: number = 0): number {
1090    this.checkOffsetRange(offset, sixBytes);
1091    // 48 : The range of 48-bit UInt value is from 0 to the 48st power of 2 minus 1
1092    rangeErrorCheck(value, 'value', 0, twoBytes ** 48 - 1, '0', '2**48 - 1');
1093    value = +value;
1094    const newVal = Math.floor(value * Math.pow(twoBytes, -32)); // -32 means offset 32 bits to left
1095    this[offset++] = (newVal >>> eightBytes);
1096    this[offset++] = newVal;
1097    for (let i: number = 3; i > 0; i--) { // 3 is array->maxIndex
1098      this[offset + i] = value;
1099      value = value >>> eightBytes;
1100    }
1101    this[offset] = value;
1102    return offset + fourBytes;
1103  }
1104
1105  readIntBE(offset: number, byteLength: number): number | undefined {
1106    typeErrorCheck(offset, ['number'], 'offset');
1107    typeErrorCheck(byteLength, ['number'], 'byteLength');
1108    return this.readData(offset, byteLength, Style.intBE);
1109  }
1110
1111  private readInt48BE(offset: number = 0): number {
1112    this.checkOffsetRange(offset, sixBytes);
1113    const val = this.calculationBE(offset, twoBytes);
1114    return (val | (val & TWO_POW_FIFTEEN) * 0x1fffe) * MAX_LENGTH + this.calculationBE(offset + twoBytes, fourBytes);
1115  }
1116
1117  private readInt40BE(offset: number = 0): number {
1118    this.checkOffsetRange(offset, fiveBytes);
1119    const first = this[offset];
1120    const last = this[offset + fourBytes];
1121    return (this[offset] | (this[offset] & TWO_POW_SEVEN) * 0x1fffffe) * MAX_LENGTH +
1122      this.calculationBE(++offset, fourBytes);
1123  }
1124
1125
1126  private readInt24BE(offset: number = 0): number {
1127    this.checkOffsetRange(offset, threeBytes);
1128    const val = this.calculationBE(offset, threeBytes);
1129    // 23 : 0x1fe : The number of 3 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
1130    return val | (val & Math.pow(twoBytes, 23)) * 0x1fe;
1131  }
1132
1133  writeIntLE(value: number, offset: number, byteLength: number): number | undefined {
1134    typeErrorCheck(value, ['number'], 'value');
1135    typeErrorCheck(offset, ['number'], 'offset');
1136    typeErrorCheck(byteLength, ['number'], 'byteLength');
1137    return this.writeData(value, offset, byteLength, Style.intLE);
1138  }
1139
1140  private writeUInt48LE(value: number, offset: number = 0): number {
1141    this.checkOffsetRange(offset, sixBytes);
1142    // 2 : 48 : The range of 48-bit UInt value is from 0 to the 48st power of 2 minus 1
1143    rangeErrorCheck(value, 'value', 0, twoBytes ** 48 - 1, '0', '2**48 - 1');
1144    value = +value;
1145    const newVal = Math.floor(value * Math.pow(twoBytes, -32)); // -32 means offset 32 bits to left
1146    for (let i: number = 3; i > 0; i--) {
1147      this[offset++] = value;
1148      value = value >>> eightBytes;
1149    }
1150    this[offset++] = value;
1151    this[offset++] = newVal;
1152    this[offset++] = (newVal >>> eightBytes);
1153    return offset;
1154  }
1155
1156  private writeUInt40LE(value: number, offset: number = 0): number {
1157    this.checkOffsetRange(offset, fiveBytes);
1158    // 2 : 40 : The range of 40-bit UInt value is from 0 to the 40st power of 2 minus 1
1159    rangeErrorCheck(value, 'value', 0, twoBytes ** 40 - 1, '0', '2**40 - 1');
1160    value = +value;
1161    const newVal = value;
1162    for (let i: number = 3; i > 0; i--) {
1163      this[offset++] = value;
1164      value = value >>> eightBytes;
1165    }
1166    this[offset++] = value;
1167    this[offset++] = Math.floor(newVal * Math.pow(twoBytes, -32)); // -32 means offset 32 bits to left
1168    return offset;
1169  }
1170
1171  private writeUInt24LE(value: number, offset: number = 0): number {
1172    this.checkOffsetRange(offset, threeBytes);
1173    // 2 : 24 : The range of 24-bit UInt value is from 0 to the 24st power of 2 minus 1
1174    rangeErrorCheck(value, 'value', 0, twoBytes ** 24 - 1, '0', '2**24 - 1');
1175    value = +value;
1176    for (let i: number = twoBytes; i > 0; i--) {
1177      this[offset++] = value;
1178      value = value >>> eightBytes;
1179    }
1180    this[offset++] = value;
1181    return offset;
1182  }
1183
1184  readIntLE(offset: number, byteLength: number): number | undefined {
1185    typeErrorCheck(offset, ['number'], 'offset');
1186    typeErrorCheck(byteLength, ['number'], 'byteLength');
1187    return this.readData(offset, byteLength, Style.intLE);
1188  }
1189
1190  private readInt48LE(offset: number = 0): number {
1191    this.checkOffsetRange(offset, sixBytes);
1192    const val = this.calculationLE(offset + fourBytes, twoBytes);
1193    return (val | (val & TWO_POW_FIFTEEN) * 0x1fffe) * MAX_LENGTH + this.calculationLE(offset, fourBytes);
1194  }
1195
1196  private readInt40LE(offset: number = 0): number {
1197    this.checkOffsetRange(offset, fiveBytes);
1198    return (this[offset + fourBytes] | (this[offset + fourBytes] & TWO_POW_SEVEN) * 0x1fffffe) * MAX_LENGTH +
1199      this.calculationLE(offset, fourBytes);
1200  }
1201
1202  private readInt24LE(offset: number = 0): number {
1203    this.checkOffsetRange(offset, threeBytes);
1204    const val = this.calculationLE(offset, threeBytes);
1205    // 2 : 23 : 0x1fe : The number of 3 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
1206    return val | (val & Math.pow(twoBytes, 23)) * 0x1fe;
1207  }
1208
1209  writeUIntLE(value: number, offset: number, byteLength: number): number | undefined {
1210    typeErrorCheck(value, ['number'], 'value');
1211    typeErrorCheck(offset, ['number'], 'offset');
1212    typeErrorCheck(byteLength, ['number'], 'byteLength');
1213    return this.writeData(value, offset, byteLength, Style.uintLE);
1214  }
1215
1216  readUIntLE(offset: number, byteLength: number): number | undefined {
1217    typeErrorCheck(offset, ['number'], 'offset');
1218    typeErrorCheck(byteLength, ['number'], 'byteLength');
1219    return this.readData(offset, byteLength, Style.uintLE);
1220  }
1221
1222  private readUInt48LE(offset: number = 0): number {
1223    this.checkOffsetRange(offset, sixBytes);
1224    return this.calculationLE(offset, fourBytes) +
1225      (this.calculationLE(offset + fourBytes, twoBytes)) * MAX_LENGTH;
1226  }
1227
1228  private readUInt40LE(offset: number = 0): number {
1229    this.checkOffsetRange(offset, fiveBytes);
1230    return this.calculationLE(offset, fiveBytes);
1231  }
1232
1233  private readUInt24LE(offset: number = 0): number {
1234    this.checkOffsetRange(offset, threeBytes);
1235    return this.calculationLE(offset, threeBytes);
1236  }
1237
1238  writeUIntBE(value: number, offset: number, byteLength: number): number | undefined {
1239    typeErrorCheck(value, ['number'], 'value');
1240    typeErrorCheck(offset, ['number'], 'offset');
1241    typeErrorCheck(byteLength, ['number'], 'byteLength');
1242    return this.writeData(value, offset, byteLength, Style.uintBE);
1243  }
1244
1245  readUIntBE(offset: number, byteLength: number): number | undefined {
1246    typeErrorCheck(offset, ['number'], 'offset');
1247    typeErrorCheck(byteLength, ['number'], 'byteLength');
1248    return this.readData(offset, byteLength, Style.uintBE);
1249  }
1250
1251  private readUInt48BE(offset: number = 0): number {
1252    this.checkOffsetRange(offset, sixBytes);
1253    return (this.calculationBE(offset, twoBytes)) * MAX_LENGTH + this.calculationBE(offset + twoBytes, fourBytes);
1254  }
1255
1256  private readUInt40BE(offset: number = 0): number {
1257    this.checkOffsetRange(offset, fiveBytes);
1258    return this.calculationBE(offset, fiveBytes);
1259  }
1260
1261  private readUInt24BE(offset: number = 0): number {
1262    this.checkOffsetRange(offset, threeBytes);
1263    return this.calculationBE(offset, threeBytes);
1264  }
1265
1266  writeInt32BE(value: number, offset: number = 0): number {
1267    typeErrorCheck(value, ['number'], 'value');
1268    if (offset === null) {
1269      offset = 0;
1270    }
1271    typeErrorCheck(offset, ['number'], 'offset');
1272    this.checkOffsetRange(offset, fourBytes);
1273    // 2 : 31 : The range of 32-bit Int value is from negative the 31st power of 2 to the 31st power of 2 minus 1
1274    rangeErrorCheck(value, 'value', - (Math.pow(twoBytes, 31)), (Math.pow(twoBytes, 31) - 1));
1275
1276    value = +value;
1277    this[bufferSymbol].writeInt32BE(value, offset);
1278    return offset + fourBytes;
1279  }
1280
1281  private checkOffsetRange(offset: number, size: number): void {
1282    rangeErrorCheck(offset, 'offset', 0, this.length - size);
1283  }
1284
1285  readInt32BE(offset: number = 0): number {
1286    if (offset === null) {
1287      offset = 0;
1288    }
1289    typeErrorCheck(offset, ['number'], 'offset');
1290    this.checkOffsetRange(offset, fourBytes);
1291    return this[bufferSymbol].readInt32BE(offset);
1292  }
1293
1294  writeInt32LE(value: number, offset: number = 0): number {
1295    typeErrorCheck(value, ['number'], 'value');
1296    if (offset === null) {
1297      offset = 0;
1298    }
1299    typeErrorCheck(offset, ['number'], 'offset');
1300    this.checkOffsetRange(offset, fourBytes);
1301    // 2 : 31 : The range of 32-bit Int value is from negative the 31st power of 2 to the 31st power of 2 minus 1
1302    rangeErrorCheck(value, 'value', - (Math.pow(twoBytes, 31)), (Math.pow(twoBytes, 31) - 1));
1303
1304    value = +value;
1305    this[bufferSymbol].writeInt32LE(value, offset);
1306    return offset + fourBytes;
1307  }
1308
1309  readInt32LE(offset: number = 0): number {
1310    if (offset === null) {
1311      offset = 0;
1312    }
1313    typeErrorCheck(offset, ['number'], 'offset');
1314    this.checkOffsetRange(offset, fourBytes);
1315    return this[bufferSymbol].readInt32LE(offset);
1316  }
1317
1318  writeUInt32BE(value: number, offset: number = 0): number {
1319    typeErrorCheck(value, ['number'], 'value');
1320    if (offset === null) {
1321      offset = 0;
1322    }
1323    typeErrorCheck(offset, ['number'], 'offset');
1324    this.checkOffsetRange(offset, fourBytes);
1325    // 2 : 32 : The range of 32-bit UInt value is from zero to the 32st power of 2 minus 1
1326    rangeErrorCheck(value, 'value', 0, (MAX_LENGTH - 1));
1327    value = +value;
1328    this[bufferSymbol].writeUInt32BE(value, offset);
1329    return offset + fourBytes;
1330  }
1331
1332  readUInt32BE(offset: number = 0): number {
1333    if (offset === null) {
1334      offset = 0;
1335    }
1336    typeErrorCheck(offset, ['number'], 'offset');
1337    this.checkOffsetRange(offset, fourBytes);
1338    return this[bufferSymbol].readUInt32BE(offset);
1339  }
1340
1341  writeUInt32LE(value: number, offset: number = 0): number {
1342    typeErrorCheck(value, ['number'], 'value');
1343    if (offset === null) {
1344      offset = 0;
1345    }
1346    typeErrorCheck(offset, ['number'], 'offset');
1347    this.checkOffsetRange(offset, fourBytes);
1348    rangeErrorCheck(value, 'value', 0, (MAX_LENGTH - 1));
1349    value = +value;
1350    this[bufferSymbol].writeUInt32LE(value, offset);
1351    return offset + fourBytes;
1352  }
1353
1354  readUInt32LE(offset: number = 0): number {
1355    if (offset === null) {
1356      offset = 0;
1357    }
1358    typeErrorCheck(offset, ['number'], 'offset');
1359    this.checkOffsetRange(offset, fourBytes);
1360    return this[bufferSymbol].readUInt32LE(offset);
1361  }
1362
1363  writeDoubleBE(value: number, offset: number = 0): number {
1364    typeErrorCheck(value, ['number'], 'value');
1365    if (offset === null) {
1366      offset = 0;
1367    }
1368    typeErrorCheck(offset, ['number'], 'offset');
1369    this.checkOffsetRange(offset, eightBytes);
1370
1371    value = +value;
1372    float64Array[0] = value;
1373    let i: number = 7; // 7 is uInt8Float64Array->maxIndex
1374    while (i >= 0) {
1375      this[offset++] = uInt8Float64Array[i--];
1376    }
1377    return offset;
1378  }
1379
1380  readDoubleBE(offset: number = 0): number {
1381    if (offset === null) {
1382      offset = 0;
1383    }
1384    typeErrorCheck(offset, ['number'], 'offset');
1385    this.checkOffsetRange(offset, eightBytes);
1386
1387    let i: number = 7; // 7 is uInt8Float64Array->maxIndex
1388    while (i >= 0) {
1389      uInt8Float64Array[i--] = this[offset++];
1390    }
1391    return float64Array[0];
1392  }
1393
1394  writeDoubleLE(value: number, offset: number = 0): number {
1395    typeErrorCheck(value, ['number'], 'value');
1396    if (offset === null) {
1397      offset = 0;
1398    }
1399    typeErrorCheck(offset, ['number'], 'offset');
1400    this.checkOffsetRange(offset, eightBytes);
1401
1402    value = +value;
1403    float64Array[0] = value;
1404    let i: number = 0;
1405    while (i <= 7) { // 7 is uInt8Float64Array->maxIndex
1406      this[offset++] = uInt8Float64Array[i++];
1407    }
1408    return offset;
1409  }
1410
1411  readDoubleLE(offset: number = 0): number {
1412    if (offset === null) {
1413      offset = 0;
1414    }
1415    typeErrorCheck(offset, ['number'], 'offset');
1416    this.checkOffsetRange(offset, eightBytes);
1417
1418    let i: number = 0;
1419    while (i <= 7) { // 7 is uInt8Float64Array->maxIndex
1420      uInt8Float64Array[i++] = this[offset++];
1421    }
1422    return float64Array[0];
1423  }
1424
1425  writeFloatBE(value: number, offset: number = 0): number {
1426    typeErrorCheck(value, ['number'], 'value');
1427    if (offset === null) {
1428      offset = 0;
1429    }
1430    typeErrorCheck(offset, ['number'], 'offset');
1431    this.checkOffsetRange(offset, fourBytes);
1432
1433    value = +value;
1434    float32Array[0] = value;
1435    let i: number = 3; // 3 is uInt8Float32Array->maxIndex
1436    while (i >= 0) {
1437      this[offset++] = uInt8Float32Array[i--];
1438    }
1439    return offset;
1440  }
1441
1442  readFloatBE(offset: number = 0): number {
1443    if (offset === null) {
1444      offset = 0;
1445    }
1446    typeErrorCheck(offset, ['number'], 'offset');
1447    this.checkOffsetRange(offset, fourBytes);
1448
1449    let i: number = 3; // 3 is uInt8Float32Array->maxIndex
1450    while (i >= 0) {
1451      uInt8Float32Array[i--] = this[offset++];
1452    }
1453    return float32Array[0];
1454  }
1455
1456  writeFloatLE(value: number, offset: number = 0): number {
1457    typeErrorCheck(value, ['number'], 'value');
1458    if (offset === null) {
1459      offset = 0;
1460    }
1461    typeErrorCheck(offset, ['number'], 'offset');
1462    this.checkOffsetRange(offset, fourBytes);
1463
1464    value = +value;
1465    float32Array[0] = value;
1466    let i: number = 0;
1467    while (i <= 3) { // 3 is uInt8Float32Array->maxIndex
1468      this[offset++] = uInt8Float32Array[i++];
1469    }
1470    return offset;
1471  }
1472
1473  readFloatLE(offset: number): number {
1474    if (offset === undefined || offset === null) {
1475      offset = 0;
1476    }
1477    typeErrorCheck(offset, ['number'], 'offset');
1478    this.checkOffsetRange(offset, fourBytes);
1479    let i: number = 0;
1480    while (i <= 3) { // 3 is uInt8Float32Array->maxIndex
1481      uInt8Float32Array[i++] = this[offset++];
1482    }
1483    return float32Array[0];
1484  }
1485
1486  writeUInt16BE(value: number, offset: number = 0): number {
1487    typeErrorCheck(value, ['number'], 'value');
1488    if (offset === null) {
1489      offset = 0;
1490    }
1491    typeErrorCheck(offset, ['number'], 'offset');
1492    this.checkOffsetRange(offset, twoBytes);
1493    // 2 : 16 : The range of 32-bit Int value is from zero to the 16st power of 2 minus 1
1494    rangeErrorCheck(value, 'value', 0, Math.pow(twoBytes, 16) - 1);
1495    value = +value;
1496    this[offset++] = (value >>> eightBytes);
1497    this[offset++] = value;
1498    return offset;
1499  }
1500
1501  readUInt16BE(offset: number = 0): number {
1502    if (offset === null) {
1503      offset = 0;
1504    }
1505    typeErrorCheck(offset, ['number'], 'offset');
1506    this.checkOffsetRange(offset, twoBytes);
1507    const first = this[offset];
1508    const last = this[offset + 1];
1509    return first * Math.pow(twoBytes, eightBytes) + last;
1510  }
1511
1512  writeUInt16LE(value: number, offset: number = 0): number {
1513    typeErrorCheck(value, ['number'], 'value');
1514    if (offset === null) {
1515      offset = 0;
1516    }
1517    typeErrorCheck(offset, ['number'], 'offset');
1518    this.checkOffsetRange(offset, twoBytes);
1519    // 2 : 16 : The range of 32-bit Int value is from zero to the 16st power of 2 minus 1
1520    rangeErrorCheck(value, 'value', 0, Math.pow(twoBytes, 16) - 1);
1521    value = +value;
1522    this[offset++] = value;
1523    this[offset++] = (value >>> eightBytes);
1524    return offset;
1525  }
1526
1527  compare(target: Buffer | Uint8Array, targetStart: number = 0, targetEnd: number = target.length,
1528    sourceStart: number = 0, sourceEnd: number = this.length): number {
1529    if (targetStart === null) {
1530      targetStart = 0;
1531    }
1532    if (targetEnd === null) {
1533      targetEnd = target.length;
1534    }
1535    if (sourceStart === null) {
1536      sourceStart = 0;
1537    }
1538    if (sourceEnd === null) {
1539      sourceEnd = this.length;
1540    }
1541    typeErrorCheck(target, ['Buffer', 'Uint8Array'], 'target');
1542    typeErrorCheck(targetStart, ['number'], 'targetStart');
1543    typeErrorCheck(targetEnd, ['number'], 'targetEnd');
1544    typeErrorCheck(sourceStart, ['number'], 'sourceStart');
1545    typeErrorCheck(sourceEnd, ['number'], 'sourceEnd');
1546    rangeErrorCheck(targetStart, 'targetStart', 0, UINT32MAX);
1547    rangeErrorCheck(targetEnd, 'targetEnd', 0, UINT32MAX);
1548    rangeErrorCheck(targetEnd, 'targetEnd', 0, target.length);
1549    rangeErrorCheck(sourceEnd, 'sourceEnd', 0, this.length);
1550    if (sourceStart >= sourceEnd) {
1551      return (targetStart >= targetEnd ? 0 : -1);
1552    }
1553    if (targetStart >= targetEnd) {
1554      return 1;
1555    }
1556    let length1: number = sourceEnd - sourceStart;
1557    let length2: number = targetEnd - targetStart;
1558    let length: number = length1 > length2 ? length2 : length1;
1559    if (target instanceof Buffer) {
1560      let val = this[bufferSymbol].compare(target[bufferSymbol], targetStart, sourceStart, length);
1561      if (val === 0) {
1562        if (length1 === length2) {
1563          return 0;
1564        }
1565        return length1 < length2 ? -1 : 1;
1566      } else {
1567        return val < 0 ? 1 : -1;
1568      }
1569    } else {
1570      let bufData1 = this[bufferSymbol].getBufferData();
1571      for (let i = 0; i < length; i++) {
1572        let value1 = +bufData1[i + sourceStart];
1573        let value2 = +target[i + targetStart];
1574        if (value1 === value2) {
1575          continue;
1576        }
1577        return value1 < value2 ? -1 : 1;
1578      }
1579      if (length1 === length2) {
1580        return 0;
1581      }
1582      return length1 < length2 ? -1 : 1;
1583    }
1584  }
1585
1586  equals(otherBuffer: Uint8Array | Buffer): boolean {
1587    typeErrorCheck(otherBuffer, ['Buffer', 'Uint8Array'], 'otherBuffer');
1588    let res = this.compare(otherBuffer, 0, otherBuffer.length, 0, this.length);
1589    return res === 0 ? true : false;
1590  }
1591
1592  subarray(start: number = 0, end: number = this.length): Buffer {
1593    let newBuf: Buffer = new Buffer(0);
1594    start = isNaN(start) ? 0 : Number(start);
1595    end = isNaN(end) ? 0 : Number(end);
1596    end = (end > this.length) ? this.length : end;
1597    if (start < 0 || end < 0 || end <= start) {
1598      return newBuf;
1599    }
1600    newBuf[bufferSymbol].subBuffer(this[bufferSymbol], start, end);
1601    newBuf[lengthSymbol] = (end - start);
1602    return newBuf;
1603  }
1604
1605  copy(target: Buffer | Uint8Array, targetStart: number = 0, sourceStart: number = 0,
1606    sourceEnd: number = this.length): number {
1607    typeErrorCheck(target, ['Buffer', 'Uint8Array'], 'target');
1608    targetStart = isNaN(targetStart) ? 0 : Number(targetStart);
1609    sourceStart = isNaN(sourceStart) ? 0 : Number(sourceStart);
1610    sourceEnd = isNaN(sourceEnd) ? 0 : Number(sourceEnd);
1611    rangeLeftErrorCheck(targetStart, 'targetStart', 0);
1612    rangeLeftErrorCheck(sourceStart, 'sourceStart', 0);
1613    rangeLeftErrorCheck(sourceEnd, 'sourceEnd', 0);
1614    if (targetStart >= target.length) {
1615      return 0;
1616    }
1617    if (sourceEnd <= sourceStart || sourceStart >= this.length) {
1618      return 0;
1619    }
1620    if (target instanceof Buffer) {
1621      return this[bufferSymbol].copy(target[bufferSymbol], targetStart, sourceStart, sourceEnd);
1622    }
1623    let sLength: number = sourceEnd;
1624    let tLength: number = target.length;
1625    let length = tLength > sLength ? sLength : tLength;
1626    for (let i = targetStart; i < length; i++) {
1627      target[i] = this[i];
1628    }
1629    return length - targetStart;
1630  }
1631
1632  toString(encoding: string = 'utf8', start: number = 0, end: number = this.length): string {
1633    if (encoding === null) {
1634      encoding = 'utf8';
1635    }
1636    let encodObj = getEncodingByType(encoding);
1637    if (!encodObj) {
1638      throw typeErrorForEncoding(encoding, 'encoding');
1639    }
1640    start = isNaN(start) ? 0 : (Number(start) < 0 ? 0 : Number(start));
1641    end = isNaN(end) ? 0 : Number(end);
1642    let bufLength = this.length;
1643    if (start >= bufLength || start > end) {
1644      return '';
1645    }
1646    end = end > bufLength ? bufLength : end;
1647    return encodObj.toString(this, start, end);
1648  }
1649
1650  toJSON(): Object {
1651    if (this.length <= 0) {
1652      return { type: 'Buffer', data: [] };
1653    }
1654    let data = this[bufferSymbol].getBufferData();
1655    return { type: 'Buffer', data };
1656  }
1657
1658  indexOf(value: string | number | Buffer | Uint8Array, byteOffset: number = 0, encoding: string = 'utf8'): number {
1659    typeErrorCheck(value, ['string', 'number', 'Buffer', 'Uint8Array'], 'value');
1660    if (typeof value === 'string') {
1661      if (typeof byteOffset === 'string') {
1662        encoding = byteOffset;
1663      }
1664      if (typeof byteOffset !== 'number') {
1665        byteOffset = 0;
1666      }
1667      if (encoding === null) {
1668        encoding = 'utf8';
1669      }
1670      encoding = encodingTypeErrorCheck(encoding);
1671      return this[bufferSymbol].indexOf(value, byteOffset, encoding, false);
1672    } else if (typeof value === 'number') {
1673      value = +value;
1674      if (value < 0 || value > utils.eightBits) {
1675        return -1;
1676      }
1677      let data = this[bufferSymbol].getBufferData();
1678      return data.indexOf(value, byteOffset);
1679    } else {
1680      let sourceData = this[bufferSymbol].getBufferData();
1681      if (value instanceof Buffer) {
1682        let targetData = value[bufferSymbol].getBufferData();
1683        return sourceData.join(',').indexOf(targetData.join(','), byteOffset);
1684      }
1685      return sourceData.join(',').indexOf(value.join(','), byteOffset);
1686    }
1687  }
1688
1689  lastIndexOf(value: string | number | Buffer | Uint8Array, byteOffset: number = 0,
1690    encoding: string = 'utf8'): number {
1691    typeErrorCheck(value, ['string', 'number', 'Buffer', 'Uint8Array'], 'value');
1692    if (typeof value === 'string') {
1693      if (typeof byteOffset === 'string') {
1694        encoding = byteOffset;
1695      }
1696      if (typeof byteOffset !== 'number') {
1697        byteOffset = 0;
1698      }
1699      if (encoding === null) {
1700        encoding = 'utf8';
1701      }
1702      encoding = encodingTypeErrorCheck(encoding);
1703      return this[bufferSymbol].indexOf(value, byteOffset, encoding, true);
1704    } else if (typeof value === 'number') {
1705      value = +value;
1706      if (value < 0 || value > utils.eightBits) {
1707        return -1;
1708      }
1709      let data = this[bufferSymbol].getBufferData();
1710      return data.lastIndexOf(value, byteOffset);
1711    } else {
1712      let sourceData = this[bufferSymbol].getBufferData();
1713      if (value instanceof Buffer) {
1714        let targetData = value[bufferSymbol].getBufferData();
1715        return sourceData.join(',').lastIndexOf(targetData.join(','), byteOffset);
1716      }
1717      return sourceData.join(',').lastIndexOf(value.join(','), byteOffset);
1718    }
1719  }
1720
1721  includes(value: string | number | Buffer | Uint8Array, byteOffset: number = 0, encoding: string = 'utf8'): boolean {
1722    typeErrorCheck(value, ['string', 'number', 'Buffer', 'Uint8Array'], 'value');
1723    if (encoding === null) {
1724      encoding = 'utf8';
1725    }
1726    encoding = encodingTypeErrorCheck(encoding);
1727    return this.indexOf(value, byteOffset, encoding) !== -1;
1728  }
1729
1730  reverseBits(dealNum: number): Buffer {
1731    const len: number = this.length;
1732    const dealLen: number = dealNum;
1733    for (let i = 0; i < len / dealLen; i++) {
1734      let times: number = 0;
1735      let startIndex: number = dealLen * i;
1736      let endIndex: number = startIndex + dealLen - 1;
1737      while (times < dealLen / twoBytes) {
1738        let tmp = this[startIndex + times];
1739        this[startIndex + times] = this[endIndex - times];
1740        this[endIndex - times] = tmp;
1741        times++;
1742      }
1743    }
1744    return this;
1745  }
1746
1747  swap16(): Buffer {
1748    const len = this.length;
1749    const dealLen: number = twoBytes;
1750    if (len % dealLen !== 0) {
1751      throw bufferSizeError('16-bits');
1752    }
1753    return this.reverseBits(dealLen);
1754  }
1755
1756  swap32(): Buffer {
1757    const len = this.length;
1758    const dealLen: number = 4; // Process every 4 bits
1759    if (len % dealLen !== 0) {
1760      throw bufferSizeError('32-bits');
1761    }
1762    return this.reverseBits(dealLen);
1763  }
1764
1765  swap64(): Buffer {
1766    const len = this.length;
1767    const dealLen: number = eightBytes;
1768    if (len % dealLen !== 0) {
1769      throw bufferSizeError('64-bits');
1770    }
1771    return this.reverseBits(dealLen);
1772  }
1773
1774  keys(): IterableIterator<number> {
1775    return this[bufferSymbol].getBufferData().keys();
1776  }
1777
1778  values(): IterableIterator<number> {
1779    return this[bufferSymbol].getBufferData().values();
1780  }
1781
1782  entries(): IterableIterator<[number, number]> {
1783    return this[bufferSymbol].getBufferData().entries();
1784  }
1785
1786  [Symbol.iterator]() {
1787    return this[bufferSymbol].getBufferData().entries();
1788  }
1789}
1790
1791function typeError(param: unknown, paramName: string, excludedTypes: string[]): BusinessError {
1792  let msg = new ErrorMessage(errorMap.typeError, paramName).setTypeInfo(excludedTypes, param).getString();
1793  return new BusinessError(msg, errorMap.typeError);
1794}
1795
1796function typeErrorForEncoding(param: unknown, paramName: string): BusinessError {
1797  let msg = new ErrorMessage(errorMap.typeError, paramName).setEncodingTypeInfo(['BufferEncoding'], param).getString();
1798  return new BusinessError(msg, errorMap.typeError);
1799}
1800
1801function typeErrorForProperty(typeName: string): BusinessError {
1802  let msg = new ErrorMessage(errorMap.typeErrorForProperty).setProperty(typeName).getString();
1803  return new BusinessError(msg, errorMap.typeErrorForProperty);
1804}
1805
1806function typeErrorForSize(param: unknown, paramName: string, excludedTypes: string[]): BusinessError {
1807  let msg = new ErrorMessage(errorMap.typeError, paramName).setSizeTypeInfo(excludedTypes, param).getString();
1808  return new BusinessError(msg, errorMap.typeError);
1809}
1810
1811function rangeError(paramName: string, rangeLeft: string | bigint | number, rangeRight: string | bigint | number,
1812  receivedValue: number | bigint): BusinessError {
1813  let msg =
1814    new ErrorMessage(errorMap.rangeError, paramName).setRangeInfo(rangeLeft, rangeRight, receivedValue).getString();
1815  return new BusinessError(msg, errorMap.rangeError);
1816}
1817
1818function rangeLeftError(paramName: string, rangeLeft: number, receivedValue: number): BusinessError {
1819  let msg = new ErrorMessage(errorMap.rangeError, paramName).setRangeLeftInfo(rangeLeft, receivedValue).getString();
1820  return new BusinessError(msg, errorMap.rangeError);
1821}
1822
1823function bufferSizeError(size: string): BusinessError {
1824  let msg = new ErrorMessage(errorMap.bufferSizeError).setSizeInfo(size).getString();
1825  return new BusinessError(msg, errorMap.bufferSizeError);
1826}
1827
1828function typeErrorCheck(param: unknown, types: string[], paramName: string): void {
1829  let typeName = getTypeName(param);
1830  if (!types.includes(typeName)) {
1831    throw typeError(param, paramName, types);
1832  }
1833}
1834
1835function sizeErrorCheck(param: unknown, paramName: string, types: string[],
1836  rangeLeft: number, rangeRight: number): void {
1837  let typeName = getTypeName(param);
1838  if (!types.includes(typeName)) {
1839    throw typeErrorForSize(param, paramName, types);
1840  }
1841  if (Number(param) < rangeLeft || Number(param) > rangeRight) {
1842    let typeString = types.join(', ');
1843    typeString = typeString.replace(',', ' or');
1844    let msg = 'The type of "' + paramName + '" must be ' + typeString +
1845      ' and the value cannot be negative. Received value is: ' + Number(param).toString();
1846    throw new BusinessError(msg, errorMap.typeError);
1847  }
1848}
1849
1850function encodingTypeErrorCheck(encoding: string): string {
1851  const normalizedEncoding = normalizeEncoding(encoding);
1852  if (normalizedEncoding === undefined) {
1853    throw typeErrorForEncoding(encoding, 'encoding');
1854  }
1855  return normalizedEncoding;
1856}
1857
1858function rangeErrorCheck(param: number | bigint, paramName: string, rangeLeft: bigint | number,
1859  rangeRight: bigint | number, rangeLeftExpr: string = '', rangeRightExpr: string = ''): void {
1860  let left = BigInt(rangeLeft);
1861  let right = BigInt(rangeRight);
1862  if (param < left || param > right) {
1863    throw rangeError(paramName, rangeLeftExpr === '' ? rangeLeft : rangeLeftExpr,
1864      rangeRightExpr === '' ? rangeRight : rangeRightExpr, param);
1865  }
1866}
1867
1868function rangeLeftErrorCheck(param: number, paramName: string, rangeLeft: number): void {
1869  if (param < rangeLeft) {
1870    throw rangeLeftError(paramName, rangeLeft, param);
1871  }
1872}
1873
1874function concat(list: Buffer[] | Uint8Array[], totalLength?: number): Buffer {
1875  typeErrorCheck(list, ['Array'], 'list');
1876  if (!(typeof totalLength === 'number' || typeof totalLength === 'undefined' || 'null')) {
1877    throw typeError(totalLength, 'totalLength', ['number']);
1878  }
1879  if (list.length === 0) {
1880    return new Buffer(0);
1881  }
1882  if (!totalLength) {
1883    totalLength = 0;
1884    for (let i = 0, len = list.length; i < len; i++) {
1885      let buf = list[i];
1886      if (buf instanceof Uint8Array || buf instanceof Buffer) {
1887        totalLength += list[i].length;
1888      }
1889    }
1890  }
1891
1892  rangeErrorCheck(totalLength, 'totalLength', 0, UINT32MAX);
1893
1894  let buffer = allocUninitializedFromPool(totalLength);
1895  let offset = 0;
1896  for (let i = 0, len = list.length; i < len; i++) {
1897    const buf = list[i];
1898    if (buf instanceof Uint8Array) {
1899      buf.forEach((val) => buffer[offset++] = val);
1900    } else if (buf instanceof Buffer) {
1901      buf.copy(buffer, offset);
1902      offset += buf.length;
1903    }
1904  }
1905  return buffer;
1906}
1907
1908function alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer {
1909  sizeErrorCheck(size, 'size', ['number'], 0, MAX_LENGTH);
1910  const buf = new Buffer(size);
1911  buf.fill(0);
1912  if (arguments.length === twoBytes && fill !== undefined && fill !== 0) {
1913    buf.fill(fill);
1914  } else if (arguments.length === 3) { // 3 is array->maxIndex
1915    if (encoding === undefined || encoding === null) {
1916      encoding = 'utf-8';
1917    }
1918    typeErrorCheck(encoding, ['string'], 'encoding');
1919    if (fill !== undefined && fill !== 0) {
1920      buf.fill(fill, undefined, undefined, encoding);
1921    }
1922  }
1923  return buf;
1924}
1925
1926function allocUninitializedFromPool(size: number): Buffer {
1927  sizeErrorCheck(size, 'size', ['number'], 0, MAX_LENGTH);
1928  if (!pool) {
1929    createPool();
1930  }
1931  if (size < (poolSize >>> 1)) {
1932    if (size > (poolSize - poolOffset)) {
1933      createPool();
1934    }
1935    const b = new Buffer(pool, poolOffset, size);
1936    poolOffset += size;
1937    alignPool();
1938    return b;
1939  }
1940  return new Buffer(size);
1941}
1942
1943function allocUninitialized(size: number): Buffer {
1944  sizeErrorCheck(size, 'size', ['number'], 0, MAX_LENGTH);
1945  const buf = new Buffer(size);
1946  return buf;
1947}
1948
1949function normalizeEncoding(enc: string): string | undefined {
1950  enc = enc.toLowerCase();
1951  if (bufferEncoding.includes(enc)) {
1952    if (enc === 'ucs2' || enc === 'ucs-2' || enc === 'utf-16le') {
1953      enc = 'utf16le';
1954    }
1955    if (enc === 'utf-8') {
1956      enc = 'utf8';
1957    }
1958    return enc;
1959  } else {
1960    return undefined;
1961  }
1962}
1963
1964function from(value: Buffer | Uint8Array | ArrayBuffer | SharedArrayBuffer | string | object | Array<number>,
1965  offsetOrEncoding?: number | string, length?: number): Buffer {
1966  if (value instanceof ArrayBuffer || value instanceof SharedArrayBuffer) {
1967    return createBufferFromArrayBuffer(value, offsetOrEncoding, length);
1968  }
1969  if (value instanceof Buffer || value instanceof Uint8Array) {
1970    return new Buffer(value);
1971  }
1972  if (value instanceof Array) {
1973    return createBufferFromArray(value);
1974  }
1975  let encoding = '';
1976  if (typeof value === 'string' || typeof value[Symbol.toPrimitive] === 'function') {
1977    offsetOrEncoding = offsetOrEncoding ? offsetOrEncoding : 'utf8';
1978    if (typeof offsetOrEncoding !== 'string') {
1979      throw typeError(getTypeName(offsetOrEncoding), 'offsetOrEncoding', ['string']);
1980    } else {
1981      encoding = encodingTypeErrorCheck(offsetOrEncoding);
1982    }
1983  }
1984  if (typeof value === 'string') {
1985    return fromString(value, encoding);
1986  }
1987  if (typeof value === 'object' && value !== null) {
1988    const valueOf = value.valueOf && value.valueOf();
1989    if (valueOf != null && valueOf !== value &&
1990      (typeof valueOf === 'string' || typeof valueOf === 'object')) {
1991      return from(valueOf, offsetOrEncoding, length);
1992    }
1993    if (typeof value[Symbol.toPrimitive] === 'function') {
1994      const primitive = value[Symbol.toPrimitive]('string');
1995      if (typeof primitive === 'string') {
1996        return fromString(primitive, encoding);
1997      }
1998    }
1999  }
2000  throw typeError(getTypeName(value), 'value', ['Buffer', 'ArrayBuffer', 'Array', 'Array-like']);
2001}
2002
2003function createBufferFromArrayBuffer(value: ArrayBuffer | SharedArrayBuffer,
2004  offsetOrEncoding?: number | string, length?: number): Buffer {
2005  offsetOrEncoding = isNaN(Number(offsetOrEncoding)) ? 0 : Number(offsetOrEncoding);
2006  if (offsetOrEncoding < 0) {
2007    throw typeError(offsetOrEncoding, 'offset', ['number']);
2008  }
2009  if (!length) {
2010    length = value.byteLength - offsetOrEncoding;
2011  } else {
2012    length = isNaN(Number(length)) ? 0 : Number(length);
2013  }
2014  rangeErrorCheck(offsetOrEncoding, 'byteOffset', 0, value.byteLength);
2015  rangeErrorCheck(length, 'length', 0, value.byteLength - offsetOrEncoding);
2016  return new Buffer(value, offsetOrEncoding, length);
2017}
2018
2019function createBufferFromArray(value: Array<number>): Buffer {
2020  if (!pool) {
2021    createPool();
2022  }
2023  const buffer = new Buffer(pool, poolOffset, value.length);
2024  poolOffset += value.length;
2025  alignPool();
2026  buffer[bufferSymbol].setArray(value);
2027  return buffer;
2028}
2029
2030function hexStrtoNumbers(hex: string): Array<number> {
2031  let arr = hex.split('');
2032  let nums: Array<number> = [];
2033  for (let i = 0, len = arr.length; i < len / twoBytes; i++) {
2034    let tmp = '0x' + arr[i * twoBytes] + arr[i * twoBytes + 1];
2035    let hexNum = Number(tmp);
2036    if (isNaN(hexNum)) {
2037      if (i === 0) {
2038        throw new Error(`The argument 'value' is invalid. Received "${hex}"`);
2039      }
2040      break;
2041    }
2042    nums[i] = Number(tmp);
2043  }
2044  return nums;
2045}
2046
2047function fromString(value: string, encoding: string): Buffer {
2048  if (encoding === 'base64') {
2049    value = value.replace(/[\r\n]/g, '');
2050  }
2051  let enc = normalizeEncoding(encoding);
2052  if (!enc) {
2053    throw typeErrorForEncoding(encoding, 'encoding');
2054  }
2055  let size = byteLength(value, enc);
2056  let buffer = allocUninitializedFromPool(size);
2057  buffer[bufferSymbol].fromString(value, enc, size);
2058  buffer[lengthSymbol] = buffer[bufferSymbol].getLength();
2059  return buffer;
2060}
2061
2062function isTypedArray(self: unknown): boolean {
2063  let typeArr = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array,
2064    Int32Array, Uint32Array, Float32Array, Float64Array];
2065  for (let i = 0, len = typeArr.length; i < len; i++) {
2066    if (self instanceof typeArr[i]) {
2067      return true;
2068    }
2069  }
2070  return false;
2071}
2072
2073function isBuffer(obj: Object): boolean {
2074  return obj instanceof Buffer;
2075}
2076
2077function isEncoding(encoding: string): boolean {
2078  if (typeof encoding !== 'string' || encoding.length === 0) {
2079    return false;
2080  }
2081  return getEncodingByType(encoding) ? true : false;
2082}
2083
2084function byteLength(string: string | BackingType, encoding: string = 'utf8'): number {
2085  if (typeof string === 'string' || isTypedArray(string) ||
2086    string instanceof DataView || string instanceof ArrayBuffer ||
2087    string instanceof SharedArrayBuffer) {
2088    if (string instanceof Buffer) {
2089      return string.length;
2090    } else if (typeof string === 'string') {
2091      if (string.length === 0) {
2092        return 0;
2093      }
2094      if (encoding === null) {
2095        encoding = 'utf8';
2096      }
2097      let encodRes = getEncodingByType(encoding);
2098      if (!encodRes) {
2099        return getUtf8ByteLength(string);
2100      }
2101      return encodRes.byteLength(string);
2102    } else {
2103      return string.byteLength;
2104    }
2105  } else {
2106    throw typeError(string, 'string', ['string', 'Buffer', 'ArrayBuffer']);
2107  }
2108}
2109
2110function transcode(source: Buffer | Uint8Array, fromEnc: string, toEnc: string): Buffer {
2111  typeErrorCheck(source, ['Buffer', 'Uint8Array'], 'source');
2112  typeErrorCheck(fromEnc, ['string'], 'fromEnc');
2113  typeErrorCheck(toEnc, ['string'], 'toEnc');
2114  let from = source.toString(fromEnc);
2115  return fromString(from, toEnc);
2116}
2117
2118function toUtf8(self: Buffer, start: number, end: number): string {
2119  return self[bufferSymbol].toUtf8(start, end);
2120}
2121
2122function toAscii(self: Buffer, start: number, end: number): string {
2123  let bufData = self[bufferSymbol].getBufferData();
2124  let val = '';
2125  for (let i = start; i < end; i++) {
2126    val += String.fromCharCode(+bufData[i] & 0x7F); // 0x7F : get the lower 15-bits
2127  }
2128  return val;
2129}
2130
2131function toBinary(self: Buffer, start: number, end: number): string {
2132  let bufData = self[bufferSymbol].getBufferData();
2133  let val = '';
2134  for (let i = start; i < end; i++) {
2135    val += String.fromCharCode(+bufData[i]);
2136  }
2137  return val;
2138}
2139
2140function toHex(self: Buffer, start: number, end: number): string {
2141  let bufData = self[bufferSymbol].getBufferData();
2142  let str = '';
2143  for (let i = start, len = end; i < len; i++) {
2144    let tmpstr = Number(bufData[i]).toString(16); // 16 : 16 decimal
2145    tmpstr = (tmpstr.length === 1) ? `0${tmpstr}` : tmpstr;
2146    str += tmpstr;
2147  }
2148  return str;
2149}
2150
2151function toUtf16LE(self: Buffer, start: number, end: number): string {
2152  let bufData: Array<number> = self[bufferSymbol].getBufferData();
2153  let val = '';
2154  for (let i = start; i + 1 < end; i += 2) { // 2 is array->NextIndex
2155    val += String.fromCodePoint((bufData[i + 1] << eightBytes) + (bufData[i]));
2156  }
2157  return val;
2158}
2159
2160function toBase64(self: Buffer, start: number, end: number): string {
2161  let str = self[bufferSymbol].toBase64(start, end);
2162  return str;
2163}
2164
2165function getEncodingByType(type: string): {
2166  byteLength: (str: string) => number;
2167  toString: (self: Buffer, start: number, end: number) => string;
2168} | undefined {
2169  type = type.toLowerCase();
2170  switch (type) {
2171    case 'utf8':
2172    case 'utf-8':
2173      return {
2174        byteLength: getUtf8ByteLength,
2175        toString: toUtf8
2176      };
2177    case 'ucs2':
2178    case 'ucs-2':
2179      return {
2180        byteLength: (str: string) => str.length * twoBytes, // 2 : 2 times of ascii
2181        toString: toUtf16LE
2182      };
2183    case 'ascii':
2184    case 'latin1':
2185      return {
2186        byteLength: (str: string) => str.length,
2187        toString: toAscii
2188      };
2189    case 'binary':
2190      return {
2191        byteLength: (str: string) => str.length,
2192        toString: toBinary
2193      };
2194    case 'utf16le':
2195    case 'utf-16le':
2196      return {
2197        byteLength: (str: string) => str.length * twoBytes,
2198        toString: toUtf16LE
2199      };
2200    case 'base64':
2201    case 'base64url':
2202      return {
2203        byteLength: getBase64ByteLength,
2204        toString: toBase64
2205      };
2206    case 'hex':
2207      return {
2208        byteLength: (str: string) => str.length >>> 1, // 1 : one-half
2209        toString: toHex
2210      };
2211    default:
2212      return undefined;
2213  }
2214}
2215
2216function getUtf8ByteLength(str: string): number {
2217  return internalBuffer.utf8ByteLength(str);
2218}
2219
2220function getBase64ByteLength(str: string): number {
2221  let bytes = str.length;
2222  for (let i = 0, len = str.length; i < len; i++) {
2223    if (bytes > 1 && str.charCodeAt(i) === 0x3D) { // 0x3D : ascii code represent of '='
2224      bytes--;
2225    }
2226  }
2227  return (bytes * threeBytes) >>> twoBytes;
2228}
2229
2230function compare(buf1: Buffer | Uint8Array, buf2: Buffer | Uint8Array): 1 | 0 | -1 {
2231  if (!(buf1 instanceof Buffer) && !(buf1 instanceof Uint8Array)) {
2232    throw new BusinessError(new ErrorMessage(errorMap.typeError, 'buf1').setTypeInfo(['Buffer', 'Uint8Array'],
2233      getTypeName(buf1)).getString(), errorMap.typeError);
2234  }
2235  if (!(buf2 instanceof Buffer) && !(buf2 instanceof Uint8Array)) {
2236    throw new BusinessError(new ErrorMessage(errorMap.typeError, 'buf2').setTypeInfo(['Buffer', 'Uint8Array'],
2237      getTypeName(buf2)).getString(), errorMap.typeError);
2238  }
2239
2240  let bufData1: Array<number> | Uint8Array;
2241  let bufData2: Array<number> | Uint8Array;
2242  if (buf1 instanceof Buffer) {
2243    bufData1 = buf1[bufferSymbol].getBufferData();
2244  } else {
2245    bufData1 = buf1;
2246  }
2247  if (buf2 instanceof Buffer) {
2248    bufData2 = buf2[bufferSymbol].getBufferData();
2249  } else {
2250    bufData2 = buf2;
2251  }
2252  let length1: number = bufData1.length;
2253  let length2: number = bufData2.length;
2254  let length: number = length1 > length2 ? length2 : length1;
2255  for (let i = 0; i < length; i++) {
2256    let value1 = +bufData1[i];
2257    let value2 = +bufData2[i];
2258    if (value1 > value2) {
2259      return 1;
2260    } else if (value1 < value2) {
2261      return -1;
2262    }
2263  }
2264  if (length1 > length2) {
2265    return 1;
2266  } else if (length1 < length2) {
2267    return -1;
2268  }
2269  return 0;
2270}
2271
2272export default {
2273  Buffer,
2274  Blob,
2275  from,
2276  alloc,
2277  allocUninitializedFromPool,
2278  allocUninitialized,
2279  byteLength,
2280  isBuffer,
2281  isEncoding,
2282  compare,
2283  concat,
2284  transcode
2285};
2286