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