• 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) {
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 one_byte: number = 1;
257const two_bytes: number = 2;
258const three_bytes: number = 3;
259const four_bytes: number = 4;
260const five_bytes: number = 5;
261const six_bytes: number = 6;
262const seven_bytes: number = 7;
263const eight_bytes: 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() {
275  poolSize = initialPoolSize;
276  pool = new Buffer(poolSize);
277  poolOffset = 0;
278}
279
280function alignPool() {
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 str_t = bufArr[i].toString(16); // 16: hexadecimal
301        str_t = (str_t.length === 1) ? `0${str_t}` : str_t;
302        str += ` ${str_t}`;
303      }
304      return str;
305    }
306    let msg = '';
307    if (bufArr.length > 50) { // 50: Maximum number of log displays
308      let bufStr = getStr(bufArr, 50);
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  EIGHT_BITS: 0xFF,
423  SIXTYFOUR_BIT: 0xFFFFFFFFn,
424
425  getLowerEight(value: number): number {
426      return value & this.EIGHT_BITS
427  },
428  getLowerSixtyFour(value: bigint): bigint {
429    return value & this.SIXTYFOUR_BIT
430  }
431}
432
433enum Style {
434  IntBE = 0,
435  IntLE,
436  UIntBE,
437  UIntLE
438}
439
440class HandlerBuffer {
441  get(obj: Buffer, prop: any): 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: any, value: any): 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() {
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; // 8: 8 bit
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)); // 32 means offset 32-bits
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; // 8: 8 bit
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", one_byte, six_bytes);
666    if (style == Style.IntBE) {
667      switch (byteLength) {
668        case one_byte:
669          return this.readInt8(offset);
670        case two_bytes:
671          return this.readInt16BE(offset);
672        case three_bytes:
673          return this.readInt24BE(offset);
674        case four_bytes:
675          return this.readInt32BE(offset);
676        case five_bytes:
677          return this.readInt40BE(offset);
678        case six_bytes:
679          return this.readInt48BE(offset);
680        default:
681          break;
682      }
683    } else if (style == Style.IntLE) {
684      switch (byteLength) {
685        case one_byte:
686          return this.readInt8(offset);
687        case two_bytes:
688          return this.readInt16LE(offset);
689        case three_bytes:
690          return this.readInt24LE(offset);
691        case four_bytes:
692          return this.readInt32LE(offset);
693        case five_bytes:
694          return this.readInt40LE(offset);
695        case six_bytes:
696          return this.readInt48LE(offset);
697        default:
698          break;
699      }
700    } else if (style == Style.UIntLE) {
701      switch (byteLength) {
702        case one_byte:
703          return this.readUInt8(offset);
704        case two_bytes:
705          return this.readUInt16LE(offset);
706        case three_bytes:
707          return this.readUInt24LE(offset);
708        case four_bytes:
709          return this.readUInt32LE(offset);
710        case five_bytes:
711          return this.readUInt40LE(offset);
712        case six_bytes:
713          return this.readUInt48LE(offset);
714        default:
715          break;
716      }
717    } else if (style == Style.UIntBE) {
718      switch (byteLength) {
719        case one_byte:
720          return this.readUInt8(offset);
721        case two_bytes:
722          return this.readUInt16BE(offset);
723        case three_bytes:
724          return this.readUInt24BE(offset);
725        case four_bytes:
726          return this.readUInt32BE(offset);
727        case five_bytes:
728          return this.readUInt40BE(offset);
729        case six_bytes:
730          return this.readUInt48BE(offset);
731        default:
732          break;
733      }
734    }
735  }
736
737  private writeData(value: number, offset: number, byteLength: number, style: Style) : number | undefined {
738    rangeErrorCheck(byteLength, "byteLength", one_byte, six_bytes);
739    if (style == Style.IntBE) {
740      switch (byteLength) {
741        case one_byte:
742          return this.writeInt8(value, offset);
743        case two_bytes:
744          return this.writeInt16BE(value, offset);
745        case three_bytes:
746          return this.writeUInt24BE(value, offset);
747        case four_bytes:
748          return this.writeInt32BE(value, offset);
749        case five_bytes:
750          return this.writeUInt40BE(value, offset);
751        case six_bytes:
752          return this.writeUInt48BE(value, offset);
753        default:
754          break;
755      }
756    } else if (style == Style.IntLE) {
757      switch (byteLength) {
758        case one_byte:
759          return this.writeUInt8(value, offset);
760        case two_bytes:
761          return this.writeUInt16LE(value, offset);
762        case three_bytes:
763          return this.writeUInt24LE(value, offset);
764        case four_bytes:
765          return this.writeUInt32LE(value, offset);
766        case five_bytes:
767          return this.writeUInt40LE(value, offset);
768        case six_bytes:
769          return this.writeUInt48LE(value, offset);
770        default:
771          break;
772      }
773    } else if (style == Style.UIntLE) {
774      switch (byteLength) {
775        case one_byte:
776          return this.writeUInt8(value, offset);
777        case two_bytes:
778          return this.writeUInt16LE(value, offset);
779        case three_bytes:
780          return this.writeUInt24LE(value, offset);
781        case four_bytes:
782          return this.writeUInt32LE(value, offset);
783        case five_bytes:
784          return this.writeUInt40LE(value, offset);
785        case six_bytes:
786          return this.writeUInt48LE(value, offset);
787        default:
788          break;
789      }
790    } else if (style == Style.UIntBE) {
791      switch (byteLength) {
792        case one_byte:
793          return this.writeUInt8(value, offset);
794        case two_bytes:
795          return this.writeUInt16BE(value, offset);
796        case three_bytes:
797          return this.writeUInt24BE(value, offset);
798        case four_bytes:
799          return this.writeUInt32BE(value, offset);
800        case five_bytes:
801          return this.writeUInt40BE(value, offset);
802        case six_bytes:
803          return this.writeUInt48BE(value, offset);
804        default:
805          break;
806      }
807    }
808  }
809
810  writeBigInt64BE(value: bigint, offset: number = 0): number {
811    typeErrorCheck(value, ['bigint'], "value");
812    typeErrorCheck(offset, ['number'], "offset");
813    this.checkOffsetRange(offset, eight_bytes);
814    // 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
815    rangeErrorCheck(value, "value", -(2n ** 63n), 2n ** 63n, "-(2n ** 63n)", "2n ** 63n");
816    return this.convertToBig64BE(value, offset);
817  }
818
819  readBigInt64BE(offset: number = 0): bigint {
820    typeErrorCheck(offset, ['number'], "offset");
821    this.checkOffsetRange(offset, eight_bytes);
822    // 24 : the first val for this[offset] shifts left by 3 bytes
823    const val = (this[offset] << 24) + this.calculationBE(offset + 1, 3);
824    // 32 : Shift left by 4 bytes
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, eight_bytes);
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); // 8 means offset 8 bits
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); // 8 means offset 8 bits
851    }
852    return result;
853  }
854
855  readBigInt64LE(offset: number = 0): bigint {
856    typeErrorCheck(offset, ['number'], "offset");
857    this.checkOffsetRange(offset, eight_bytes);
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, eight_bytes);
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, eight_bytes);
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, eight_bytes);
885    // 2n : 64n : 1n : The range of 64-bit BigUInt value is from 0 to the 64st power of 2 minus 1
886    rangeErrorCheck(value, "value", 0, 2n ** 64n - 1n, "0", "2n ** 64n - 1n");
887
888    return this.convertToBig64LE(value, offset);
889  }
890
891  readBigUInt64LE(offset: number = 0): bigint {
892    typeErrorCheck(offset, ['number'], "offset");
893    this.checkOffsetRange(offset, eight_bytes);
894    const lo = this.calculationLE(offset, 4);
895    const hi = this.calculationLE(offset + 4, 4);
896    return BigInt(lo) + (BigInt(hi) << 32n); // 32 means offset 32-bits left
897  }
898
899  writeInt8(value: number, offset: number = 0): number {
900    typeErrorCheck(value, ['number'], "value");
901    typeErrorCheck(offset, ['number'], "offset");
902    this.checkOffsetRange(offset, one_byte);
903    // 2 : 7 : The range of 8-bit Int value is from negative the 7st power of 2 to the 7st power of 2 minus 1
904    rangeErrorCheck(value, "value", -(Math.pow(2, 7)), (Math.pow(2, 7) -1));
905    value = +value;
906
907    this[offset] = value;
908    return offset + 1;
909  }
910
911  readInt8(offset: number = 0): number {
912    typeErrorCheck(offset, ['number'], "offset");
913    this.checkOffsetRange(offset, one_byte);
914    const val = this[offset];
915
916    return val | (val & Math.pow(2, 7)) * 0x1fffffe;
917  }
918
919  writeInt16BE(value: number, offset: number = 0): number {
920    typeErrorCheck(value, ['number'], "value");
921    typeErrorCheck(offset, ['number'], "offset");
922    this.checkOffsetRange(offset, two_bytes);
923    // 2 : 15 : The range of 16-bit Int value is from negative the 15st power of 2 to the 15st power of 2 minus 1
924    rangeErrorCheck(value, "value", -(Math.pow(2, 15)), (Math.pow(2, 15) -1));
925    value = +value;
926    this[offset++] = (value >>> 8);
927    this[offset++] = value;
928    return offset;
929  }
930
931  readInt16BE(offset: number = 0): number {
932    typeErrorCheck(offset, ['number'], "offset");
933    this.checkOffsetRange(offset, two_bytes);
934    const val = this.calculationBE(offset, 2);
935    // 2 : 15 : 0x1fffe : The number of 2 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
936    return val | (val & Math.pow(2, 15)) * 0x1fffe;
937  }
938
939  writeInt16LE(value: number, offset: number = 0): number {
940    typeErrorCheck(value, ['number'], "value");
941    typeErrorCheck(offset, ['number'], "offset");
942    this.checkOffsetRange(offset, two_bytes);
943    // 2 : 15 : The range of 16-bit Int value is from negative the 15st power of 2 to the 15st power of 2 minus 1
944    rangeErrorCheck(value, "value", -(Math.pow(2, 15)), (Math.pow(2, 15) -1));
945    value = +value;
946    this[offset++] = value;
947    this[offset++] = (value >>> 8);
948    return offset;
949  }
950
951  readInt16LE(offset: number = 0): number {
952    typeErrorCheck(offset, ['number'], "offset");
953    this.checkOffsetRange(offset, two_bytes);
954    const val = this[offset] + this[offset + 1] * Math.pow(2, 8); // 8 means offset 8 bits
955    // 2 : 15 : 0x1fffe : The number of 2 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
956    return val | (val & Math.pow(2, 15)) * 0x1fffe;
957  }
958
959  readUInt16LE(offset: number = 0): number {
960    typeErrorCheck(offset, ['number'], "offset");
961    this.checkOffsetRange(offset, two_bytes);
962    return this[offset] + this[offset + 1] * Math.pow(2, 8); // 8 means offset 8 bits
963  }
964
965  writeUInt8(value: number, offset: number = 0): number {
966    typeErrorCheck(value, ['number'], "value");
967    typeErrorCheck(offset, ['number'], "offset");
968    this.checkOffsetRange(offset, one_byte);
969    // 0 : 255 : The range of 8-bit UInt value is from 0 to the 8st power of 2 minus 1
970    rangeErrorCheck(value, "value", 0, 255);
971    value = +value;
972
973    this[offset] = value;
974    return offset + 1;
975  }
976
977  readUInt8(offset: number = 0): number {
978    typeErrorCheck(offset, ['number'], "offset");
979    this.checkOffsetRange(offset, one_byte);
980    const val = this[offset];
981    return val;
982  }
983
984  writeIntBE(value: number, offset: number, byteLength: number): number | undefined {
985    typeErrorCheck(value, ['number'], "value");
986    typeErrorCheck(offset, ['number'], "offset");
987    typeErrorCheck(byteLength, ['number'], "byteLength");
988    return this.writeData(value, offset, byteLength, Style.IntBE);
989  }
990
991  private writeUInt24BE(value: number, offset: number = 0) {
992    this.checkOffsetRange(offset, three_bytes);
993    // 2 : 24 : The range of 24-bit UInt value is from 0 to the 24st power of 2 minus 1
994    rangeErrorCheck(value, "value", 0, 2**24 - 1, "0", "2**24 - 1");
995    value = +value;
996    for(let i: number = 2; i > 0; i--) {
997      this[offset + i] = value;
998      value = value >>> 8; // 8 means offset 8 bits
999    }
1000    this[offset] = value;
1001    return offset + 3; // 3 means offset 3 bytes
1002  }
1003
1004  private writeUInt40BE(value: number, offset: number = 0) {
1005    this.checkOffsetRange(offset, five_bytes);
1006    // 2 : 40 : The range of 40-bit UInt value is from 0 to the 40st power of 2 minus 1
1007    rangeErrorCheck(value, "value", 0, 2**40 - 1, "0", "2**40 - 1");
1008    value = +value;
1009    this[offset++] = Math.floor(value * Math.pow(2, -32)); // -32 means offset 32 bits to left
1010    for(let i: number = 3; i > 0; i--) {
1011      this[offset + i] = value;
1012      value = value >>> 8; // 8 means offset 8 bits
1013    }
1014    this[offset] = value;
1015    return offset + 4; // 4 means offset 4 bytes
1016  }
1017
1018  private writeUInt48BE(value: number, offset: number = 0) {
1019    this.checkOffsetRange(offset, six_bytes);
1020    // 2 : 48 : The range of 48-bit UInt value is from 0 to the 48st power of 2 minus 1
1021    rangeErrorCheck(value, "value", 0, 2**48 - 1, "0", "2**48 - 1");
1022    value = +value;
1023    const newVal = Math.floor(value * Math.pow(2, -32)); // -32 means offset 32 bits to left
1024    this[offset++] = (newVal >>> 8);
1025    this[offset++] = newVal;
1026    for(let i: number = 3; i > 0; i--) {
1027      this[offset + i] = value;
1028      value = value >>> 8; // 8 means offset 8 bits
1029    }
1030    this[offset] = value;
1031    return offset + 4; // 4 means offset 4 bytes
1032  }
1033
1034  readIntBE(offset: number, byteLength: number): number | undefined {
1035    typeErrorCheck(offset, ['number'], "offset");
1036    typeErrorCheck(byteLength, ['number'], "byteLength");
1037    return this.readData(offset, byteLength, Style.IntBE);
1038  }
1039
1040  private readInt48BE(offset: number = 0) {
1041    this.checkOffsetRange(offset, six_bytes);
1042    const val = this.calculationBE(offset, 2);
1043    // 2 : 15 : 0x1fffe : The number of 2 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
1044    return (val | (val & Math.pow(2, 15)) * 0x1fffe) * Math.pow(2, 32) + this.calculationBE(offset + 2, 4);
1045  }
1046
1047  private readInt40BE(offset: number = 0) {
1048    this.checkOffsetRange(offset, five_bytes);
1049    const first = this[offset];
1050    const last = this[offset + 4];
1051    // 2 : 7 : 0x1fffffe : The number of 1 byte changes to 4 bytes, positive high fill 0, negative high fill 1.
1052    return (this[offset] | (this[offset] & Math.pow(2, 7)) * 0x1fffffe) * Math.pow(2, 32) + // 32 means offset 32 bits
1053      this.calculationBE(++offset, 4); // 4 means offset 4 bytes
1054  }
1055
1056
1057  private readInt24BE(offset: number = 0) {
1058    this.checkOffsetRange(offset, three_bytes);
1059    const val = this.calculationBE(offset, 3);
1060    // 2 : 23 : 0x1fe : The number of 3 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
1061    return val | (val & Math.pow(2, 23)) * 0x1fe;
1062  }
1063
1064  writeIntLE(value: number, offset: number, byteLength: number): number | undefined {
1065    typeErrorCheck(value, ['number'], "value");
1066    typeErrorCheck(offset, ['number'], "offset");
1067    typeErrorCheck(byteLength, ['number'], "byteLength");
1068    return this.writeData(value, offset, byteLength, Style.IntLE);
1069  }
1070
1071  private writeUInt48LE(value: number, offset: number = 0) {
1072    this.checkOffsetRange(offset, six_bytes);
1073    // 2 : 48 : The range of 48-bit UInt value is from 0 to the 48st power of 2 minus 1
1074    rangeErrorCheck(value, "value", 0, 2**48 - 1, "0", "2**48 - 1");
1075    value = +value;
1076    const newVal = Math.floor(value * Math.pow(2, -32)); // -32 means offset 32 bits to left
1077    for(let i: number = 3; i > 0; i--) {
1078      this[offset++] = value;
1079      value = value >>> 8; // 8 means offset 8 bits
1080    }
1081    this[offset++] = value;
1082    this[offset++] = newVal;
1083    this[offset++] = (newVal >>> 8); // 8 means offset 8 bits
1084    return offset;
1085  }
1086
1087  private writeUInt40LE(value: number, offset: number = 0) {
1088    this.checkOffsetRange(offset, five_bytes);
1089    // 2 : 40 : The range of 40-bit UInt value is from 0 to the 40st power of 2 minus 1
1090    rangeErrorCheck(value, "value", 0, 2**40 - 1, "0", "2**40 - 1");
1091    value = +value;
1092    const newVal = value;
1093    for(let i: number = 3; i > 0; i--) {
1094      this[offset++] = value;
1095      value = value >>> 8; // 8 means offset 8 bits
1096    }
1097    this[offset++] = value;
1098    this[offset++] = Math.floor(newVal * Math.pow(2, -32)); // -32 means offset 32 bits to left
1099    return offset;
1100  }
1101
1102  private writeUInt24LE(value: number, offset: number = 0) {
1103    this.checkOffsetRange(offset, three_bytes);
1104    // 2 : 24 : The range of 24-bit UInt value is from 0 to the 24st power of 2 minus 1
1105    rangeErrorCheck(value, "value", 0, 2**24 - 1, "0", "2**24 - 1");
1106    value = +value;
1107    for(let i: number = 2; i > 0; i--) {
1108      this[offset++] = value;
1109      value = value >>> 8; // 8 means offset 8 bits
1110    }
1111    this[offset++] = value;
1112    return offset;
1113  }
1114
1115  readIntLE(offset: number, byteLength: number): number | undefined {
1116    typeErrorCheck(offset, ['number'], "offset");
1117    typeErrorCheck(byteLength, ['number'], "byteLength");
1118    return this.readData(offset, byteLength, Style.IntLE);
1119  }
1120
1121  private readInt48LE(offset: number = 0) {
1122    this.checkOffsetRange(offset, six_bytes);
1123    const val = this.calculationLE(offset + 4, 2);
1124    // 2 : 15 : 0x1fffe : The number of 2 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
1125    return (val | (val & Math.pow(2, 15)) * 0x1fffe) * Math.pow(2, 32) + this.calculationLE(offset, 4);
1126  }
1127
1128  private readInt40LE(offset: number = 0) {
1129    this.checkOffsetRange(offset, five_bytes);
1130    // 2 : 7 : 0x1fffffe : The number of 1 byte changes to 4 bytes, positive high fill 0, negative high fill 1.
1131    return (this[offset + 4] | (this[offset + 4] & Math.pow(2, 7)) * 0x1fffffe) * Math.pow(2, 32) + // 32 means offset 32 bits
1132      this.calculationLE(offset, 4); // 4 means offset 4 bytes
1133  }
1134
1135  private readInt24LE(offset: number = 0) {
1136    this.checkOffsetRange(offset, three_bytes);
1137    const val = this.calculationLE(offset, 3); // 3 means get 3 bytes
1138    // 2 : 23 : 0x1fe : The number of 3 bytes changes to 4 bytes, positive high fill 0, negative high fill 1.
1139    return val | (val & Math.pow(2, 23)) * 0x1fe;
1140  }
1141
1142  writeUIntLE(value: number, offset: number, byteLength: number): number | undefined {
1143    typeErrorCheck(value, ['number'], "value");
1144    typeErrorCheck(offset, ['number'], "offset");
1145    typeErrorCheck(byteLength, ['number'], "byteLength");
1146    return this.writeData(value, offset, byteLength, Style.UIntLE);
1147  }
1148
1149  readUIntLE(offset: number, byteLength: number): number | undefined {
1150    typeErrorCheck(offset, ['number'], "offset");
1151    typeErrorCheck(byteLength, ['number'], "byteLength");
1152    return this.readData(offset, byteLength, Style.UIntLE);
1153  }
1154
1155  private readUInt48LE(offset: number = 0) {
1156    this.checkOffsetRange(offset, six_bytes);
1157    return this.calculationLE(offset, 4) +
1158      (this.calculationLE(offset + 4, 2)) * Math.pow(2, 32); // 32 means offset 32 bits
1159  }
1160
1161  private readUInt40LE(offset: number = 0) {
1162    this.checkOffsetRange(offset, five_bytes);
1163    return this.calculationLE(offset, 5); // 5 means get 5 bytes
1164  }
1165
1166  private readUInt24LE(offset: number = 0) {
1167    this.checkOffsetRange(offset, three_bytes);
1168    return this.calculationLE(offset, 3); // 3 means get 3 bytes
1169  }
1170
1171  writeUIntBE(value: number, offset: number, byteLength: number): number | undefined {
1172    typeErrorCheck(value, ['number'], "value");
1173    typeErrorCheck(offset, ['number'], "offset");
1174    typeErrorCheck(byteLength, ['number'], "byteLength");
1175    return this.writeData(value, offset, byteLength, Style.UIntBE);
1176  }
1177
1178  readUIntBE(offset: number, byteLength: number): number | undefined {
1179    typeErrorCheck(offset, ['number'], "offset");
1180    typeErrorCheck(byteLength, ['number'], "byteLength");
1181    return this.readData(offset, byteLength, Style.UIntBE);
1182  }
1183
1184  private readUInt48BE(offset: number = 0) {
1185    this.checkOffsetRange(offset, six_bytes);
1186    return (this.calculationBE(offset, 2)) * Math.pow(2, 32) + // 32 means offset 32 bits
1187      this.calculationBE(offset + 2, 4); // 4 means get 4 bytes
1188  }
1189
1190  private readUInt40BE(offset: number = 0) {
1191    this.checkOffsetRange(offset, five_bytes);
1192    return this.calculationBE(offset, 5); // 5 means get 5 bytes
1193  }
1194
1195  private readUInt24BE(offset: number = 0) {
1196    this.checkOffsetRange(offset, three_bytes);
1197    return this.calculationBE(offset, 3); // 3 means get 3 bytes
1198  }
1199
1200  writeInt32BE(value: number, offset: number = 0): number {
1201    typeErrorCheck(value, ['number'], "value");
1202    typeErrorCheck(offset, ['number'], "offset");
1203    this.checkOffsetRange(offset, four_bytes);
1204    // 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
1205    rangeErrorCheck(value, "value", -(Math.pow(2, 31)), (Math.pow(2, 31) -1));
1206
1207    value = +value;
1208    this[bufferSymbol].writeInt32BE(value, offset);
1209    return offset + 4; // 4 means offset 4 bytes
1210  }
1211
1212  private checkOffsetRange(offset: number, size: number): void {
1213    rangeErrorCheck(offset, "offset", 0, this.length - size);
1214  }
1215
1216  readInt32BE(offset: number = 0): number {
1217    typeErrorCheck(offset, ['number'], "offset");
1218    this.checkOffsetRange(offset, four_bytes);
1219    return this[bufferSymbol].readInt32BE(offset);
1220  }
1221
1222  writeInt32LE(value: number, offset: number = 0): number {
1223    typeErrorCheck(value, ['number'], "value");
1224    typeErrorCheck(offset, ['number'], "offset");
1225    this.checkOffsetRange(offset, four_bytes);
1226    // 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
1227    rangeErrorCheck(value, "value", -(Math.pow(2, 31)), (Math.pow(2, 31) -1));
1228
1229    value = +value;
1230    this[bufferSymbol].writeInt32LE(value, offset);
1231    return offset + 4; // 4 means offset 4 bytes
1232  }
1233
1234  readInt32LE(offset: number = 0) : number {
1235    typeErrorCheck(offset, ['number'], "offset");
1236    this.checkOffsetRange(offset, four_bytes);
1237    return this[bufferSymbol].readInt32LE(offset);
1238  }
1239
1240  writeUInt32BE(value: number, offset: number = 0): number {
1241    typeErrorCheck(value, ['number'], "value");
1242    typeErrorCheck(offset, ['number'], "offset");
1243    this.checkOffsetRange(offset, four_bytes);
1244    // 2 : 32 : The range of 32-bit UInt value is from zero to the 32st power of 2 minus 1
1245    rangeErrorCheck(value, "value", 0, (Math.pow(2, 32) - 1));
1246    value = +value;
1247    this[bufferSymbol].writeUInt32BE(value, offset);
1248    return offset + 4; // 4 means offset 4 bytes
1249  }
1250
1251  readUInt32BE(offset: number = 0): number {
1252    typeErrorCheck(offset, ['number'], "offset");
1253    this.checkOffsetRange(offset, four_bytes);
1254    return this[bufferSymbol].readUInt32BE(offset);
1255  }
1256
1257  writeUInt32LE(value: number, offset: number = 0): number {
1258    typeErrorCheck(value, ['number'], "value");
1259    typeErrorCheck(offset, ['number'], "offset");
1260    this.checkOffsetRange(offset, four_bytes);
1261    // 2 : 32 : The range of 32-bit UInt value is from zero to the 32st power of 2 minus 1
1262    rangeErrorCheck(value, "value", 0, (Math.pow(2, 32) -1));
1263    value = +value;
1264    this[bufferSymbol].writeUInt32LE(value, offset);
1265    return offset + 4; // 4 means offset 4 bytes
1266  }
1267
1268  readUInt32LE(offset: number = 0): number {
1269    typeErrorCheck(offset, ['number'], "offset");
1270    this.checkOffsetRange(offset, four_bytes);
1271    return this[bufferSymbol].readUInt32LE(offset);
1272  }
1273
1274  writeDoubleBE(value: number, offset: number = 0): number {
1275    typeErrorCheck(value, ['number'], "value");
1276    typeErrorCheck(offset, ['number'], "offset");
1277    this.checkOffsetRange(offset, eight_bytes);
1278
1279    value = +value;
1280    float64Array[0] = value;
1281    let i: number = 7; // 7 is uInt8Float64Array->maxIndex
1282    while (i >= 0) {
1283      this[offset++] = uInt8Float64Array[i--];
1284    }
1285    return offset;
1286  }
1287
1288  readDoubleBE(offset: number = 0): number {
1289    typeErrorCheck(offset, ['number'], "offset");
1290    this.checkOffsetRange(offset, eight_bytes);
1291
1292    let i: number = 7; // 7 is uInt8Float64Array->maxIndex
1293    while (i >= 0) {
1294      uInt8Float64Array[i--] = this[offset++];
1295    }
1296    return float64Array[0];
1297  }
1298
1299  writeDoubleLE(value: number, offset: number = 0): number {
1300    typeErrorCheck(value, ['number'], "value");
1301    typeErrorCheck(offset, ['number'], "offset");
1302    this.checkOffsetRange(offset, eight_bytes);
1303
1304    value = +value;
1305    float64Array[0] = value;
1306    let i: number = 0;
1307    while (i <= 7) { // 7 is uInt8Float64Array->maxIndex
1308      this[offset++] = uInt8Float64Array[i++];
1309    }
1310    return offset;
1311  }
1312
1313  readDoubleLE(offset: number = 0): number {
1314    typeErrorCheck(offset, ['number'], "offset");
1315    this.checkOffsetRange(offset, eight_bytes);
1316
1317    let i: number = 0;
1318    while (i <= 7) { // 7 is uInt8Float64Array->maxIndex
1319      uInt8Float64Array[i++] = this[offset++];
1320    }
1321    return float64Array[0];
1322  }
1323
1324  writeFloatBE(value: number, offset: number = 0): number {
1325    typeErrorCheck(value, ['number'], "value");
1326    typeErrorCheck(offset, ['number'], "offset");
1327    this.checkOffsetRange(offset, four_bytes);
1328
1329    value = +value;
1330    float32Array[0] = value;
1331    let i: number = 3; // 3 is uInt8Float32Array->maxIndex
1332    while (i >= 0) {
1333      this[offset++] = uInt8Float32Array[i--];
1334    }
1335    return offset;
1336  }
1337
1338  readFloatBE(offset: number = 0): number {
1339    typeErrorCheck(offset, ['number'], "offset");
1340    this.checkOffsetRange(offset, four_bytes);
1341
1342    let i: number = 3; // 3 is uInt8Float32Array->maxIndex
1343    while (i >= 0) {
1344      uInt8Float32Array[i--] = this[offset++];
1345    }
1346    return float32Array[0];
1347  }
1348
1349  writeFloatLE(value: number, offset: number = 0): number {
1350    typeErrorCheck(value, ['number'], "value");
1351    typeErrorCheck(offset, ['number'], "offset");
1352    this.checkOffsetRange(offset, four_bytes);
1353
1354    value = +value;
1355    float32Array[0] = value;
1356    let i: number = 0;
1357    while (i <= 3) {  // 3 is uInt8Float32Array->maxIndex
1358      this[offset++] = uInt8Float32Array[i++];
1359    }
1360    return offset;
1361  }
1362
1363  readFloatLE(offset: number): number {
1364    typeErrorCheck(offset, ['number'], "offset");
1365    this.checkOffsetRange(offset, four_bytes);
1366
1367    let i: number = 0;
1368    while (i <= 3) { // 3 is uInt8Float32Array->maxIndex
1369      uInt8Float32Array[i++] = this[offset++];
1370    }
1371    return float32Array[0];
1372  }
1373
1374  writeUInt16BE(value: number, offset: number = 0): number {
1375    typeErrorCheck(value, ['number'], "value");
1376    typeErrorCheck(offset, ['number'], "offset");
1377    this.checkOffsetRange(offset, two_bytes);
1378    // 2 : 16 : The range of 32-bit Int value is from zero to the 16st power of 2 minus 1
1379    rangeErrorCheck(value, "value", 0, Math.pow(2, 16) - 1);
1380    value = +value;
1381    this[offset++] = (value >>> 8); // 8 means offset 8 bits
1382    this[offset++] = value;
1383    return offset;
1384  }
1385
1386  readUInt16BE(offset: number = 0) : number {
1387    typeErrorCheck(offset, ['number'], "offset");
1388    this.checkOffsetRange(offset, two_bytes);
1389    const first = this[offset];
1390    const last = this[offset + 1];
1391    return first * Math.pow(2, 8) + last; // 8 means offset 8 bits
1392  }
1393
1394  writeUInt16LE(value: number, offset: number = 0): number {
1395    typeErrorCheck(value, ['number'], "value");
1396    typeErrorCheck(offset, ['number'], "offset");
1397    this.checkOffsetRange(offset, two_bytes);
1398    // 2 : 16 : The range of 32-bit Int value is from zero to the 16st power of 2 minus 1
1399    rangeErrorCheck(value, "value", 0, Math.pow(2, 16) - 1);
1400    value = +value;
1401    this[offset++] = value;
1402    this[offset++] = (value >>> 8); // 8 means offset 8 bits
1403    return offset;
1404  }
1405
1406  compare(target: Buffer | Uint8Array, targetStart: number = 0, targetEnd: number = target.length,
1407          sourceStart: number = 0, sourceEnd: number = this.length): -1 | 0 | 1 {
1408    typeErrorCheck(target, ['Buffer', 'Uint8Array'], "target");
1409    typeErrorCheck(targetStart, ['number'], "targetStart");
1410    typeErrorCheck(targetEnd, ['number'], "targetEnd");
1411    typeErrorCheck(sourceStart, ['number'], "sourceStart");
1412    typeErrorCheck(sourceEnd, ['number'], "sourceEnd");
1413    rangeErrorCheck(targetStart, "targetStart", 0, UINT32MAX);
1414    rangeErrorCheck(targetEnd, "targetEnd", 0, UINT32MAX);
1415    rangeErrorCheck(targetEnd, "targetEnd", 0, target.length);
1416    rangeErrorCheck(sourceEnd, "sourceEnd", 0, this.length);
1417    if (sourceStart >= sourceEnd) {
1418      return (targetStart >= targetEnd ? 0 : -1);
1419    }
1420    if (targetStart >= targetEnd) {
1421      return 1;
1422    }
1423    let length1: number = sourceEnd - sourceStart;
1424    let length2: number = targetEnd - targetStart;
1425    let length: number = length1 > length2 ? length2 : length1;
1426    if (target instanceof Buffer) {
1427      let val = this[bufferSymbol].compare(target[bufferSymbol], targetStart, sourceStart, length);
1428      if (val == 0) {
1429        if (length1 == length2) {
1430          return 0;
1431        }
1432        return length1 < length2 ? -1 : 1;
1433      } else {
1434        return val < 0 ? 1 : -1;
1435      }
1436    } else {
1437      let bufData1 = this[bufferSymbol].getBufferData();
1438      for (let i = 0; i < length; i++) {
1439        let value1 = +bufData1[i + sourceStart];
1440        let value2 = +target[i + targetStart];
1441        if (value1 == value2) {
1442          continue;
1443        }
1444        return value1 < value2 ? -1 : 1;
1445      }
1446      if (length1 == length2) {
1447        return 0;
1448      }
1449      return length1 < length2 ? -1 : 1;
1450    }
1451  }
1452
1453  equals(otherBuffer: Uint8Array | Buffer): boolean {
1454    typeErrorCheck(otherBuffer, ['Buffer', 'Uint8Array'], "otherBuffer");
1455    let res = this.compare(otherBuffer, 0, otherBuffer.length, 0, this.length);
1456    return res === 0 ? true : false;
1457  }
1458
1459  subarray(start: number = 0, end: number = this.length): Buffer {
1460    let newBuf = Object.create(this);
1461    start = isNaN(start) ? 0 : Number(start);
1462    end = isNaN(end) ? 0 : Number(end);
1463    end = (end > this.length) ? this.length : end;
1464    if (start < 0 || end < 0 || end <= start) {
1465      return new Buffer(0);
1466    }
1467    newBuf[bufferSymbol] = this[bufferSymbol].subBuffer(start, end);
1468    newBuf[lengthSymbol] = (end - start);
1469    return newBuf;
1470  }
1471
1472  copy(target: Buffer | Uint8Array, targetStart: number = 0, sourceStart: number = 0,
1473       sourceEnd: number = this.length): number {
1474    typeErrorCheck(target, ['Buffer', 'Uint8Array'], "target");
1475    targetStart = isNaN(targetStart) ? 0 : Number(targetStart);
1476    sourceStart = isNaN(sourceStart) ? 0 : Number(sourceStart);
1477    sourceEnd = isNaN(sourceEnd) ? 0 : Number(sourceEnd);
1478    rangeLeftErrorCheck(targetStart, "targetStart", 0);
1479    rangeLeftErrorCheck(sourceStart, "sourceStart", 0);
1480    rangeLeftErrorCheck(sourceEnd, "sourceEnd", 0);
1481    if (targetStart >= target.length) {
1482      return 0;
1483    }
1484    if (sourceEnd <= sourceStart || sourceStart >= this.length) {
1485      return 0;
1486    }
1487    if (target instanceof Buffer) {
1488      return this[bufferSymbol].copy(target[bufferSymbol], targetStart, sourceStart, sourceEnd);
1489    }
1490    let sLength: number = sourceEnd;
1491    let tLength: number = target.length;
1492    let length = tLength > sLength ? sLength : tLength;
1493    for (let i = targetStart; i < length; i++) {
1494      target[i] = this[i];
1495    }
1496    return length - targetStart;
1497  }
1498
1499  toString(encoding: string = 'utf8',start: number = 0, end: number = this.length): string {
1500    let encodObj = getEncodingByType(encoding);
1501    if (!encodObj) {
1502      throw typeErrorForEncoding(encoding, "encoding");
1503    }
1504    start = isNaN(start) ? 0 : (Number(start) < 0 ? 0 : Number(start));
1505    end = isNaN(end) ? 0 : Number(end);
1506    let bufLength = this.length;
1507    if (start >= bufLength || start > end) {
1508      return "";
1509    }
1510    end = end > bufLength ? bufLength : end;
1511    return encodObj.toString(this, start, end);
1512  }
1513
1514  toJSON(): Object {
1515    if (this.length <= 0) {
1516      return { type: 'Buffer', data: [] };
1517    }
1518    let data = this[bufferSymbol].getBufferData();
1519    return { type: 'Buffer', data };
1520  }
1521
1522  indexOf(value: string | number | Buffer | Uint8Array, byteOffset: number = 0, encoding: string = 'utf8'): number {
1523    typeErrorCheck(value, ['string', 'number', 'Buffer', 'Uint8Array'], "value");
1524    if (typeof value === 'string') {
1525      if (typeof byteOffset == 'string') {
1526        encoding = byteOffset;
1527      }
1528      if (typeof byteOffset !== 'number') {
1529        byteOffset = 0;
1530      }
1531      encoding = encodingTypeErrorCheck(encoding);
1532      return this[bufferSymbol].indexOf(value, byteOffset, encoding, false);
1533    } else if (typeof value === 'number') {
1534      value = +value;
1535      if (value < 0 || value > utils.EIGHT_BITS) {
1536        return -1;
1537      }
1538      let data = this[bufferSymbol].getBufferData();
1539      return data.indexOf(value, byteOffset);
1540    } else {
1541      let sourceData = this[bufferSymbol].getBufferData();
1542      if (value instanceof Buffer) {
1543        let targetData = value[bufferSymbol].getBufferData();
1544        return sourceData.join(',').indexOf(targetData.join(','), byteOffset);
1545      }
1546      return sourceData.join(',').indexOf(value.join(','), byteOffset);
1547    }
1548  }
1549
1550  lastIndexOf(value: string | number | Buffer | Uint8Array, byteOffset: number = 0,
1551              encoding: string = 'utf8'): number {
1552    typeErrorCheck(value, ['string', 'number', 'Buffer', 'Uint8Array'], "value");
1553    if (typeof value === 'string') {
1554      if (typeof byteOffset == 'string') {
1555        encoding = byteOffset;
1556      }
1557      if (typeof byteOffset !== 'number') {
1558        byteOffset = 0;
1559      }
1560      encoding = encodingTypeErrorCheck(encoding);
1561      return this[bufferSymbol].indexOf(value, byteOffset, encoding, true);
1562    } else if (typeof value === 'number') {
1563      value = +value;
1564      if (value < 0 || value > utils.EIGHT_BITS) {
1565        return -1;
1566      }
1567      let data = this[bufferSymbol].getBufferData();
1568      return data.lastIndexOf(value, byteOffset);
1569    } else {
1570      let sourceData = this[bufferSymbol].getBufferData();
1571      if (value instanceof Buffer) {
1572        let targetData = value[bufferSymbol].getBufferData();
1573        return sourceData.join(',').lastIndexOf(targetData.join(','), byteOffset);
1574      }
1575      return sourceData.join(',').lastIndexOf(value.join(','), byteOffset);
1576    }
1577  }
1578
1579  includes(value: string | number | Buffer | Uint8Array, byteOffset: number = 0, encoding: string = 'utf8'): boolean {
1580    typeErrorCheck(value, ['string', 'number', 'Buffer', 'Uint8Array'], "value");
1581    encoding = encodingTypeErrorCheck(encoding);
1582    return this.indexOf(value, byteOffset, encoding) !== -1;
1583  }
1584
1585  reverseBits(dealNum: number): Buffer {
1586    const len: number = this.length;
1587    const dealLen: number = dealNum;
1588    for (let i = 0; i < len / dealLen; i++) {
1589      let times: number = 0;
1590      let startIndex: number = dealLen * i;
1591      let endIndex: number = startIndex + dealLen - 1;
1592      while (times < dealLen / 2) {
1593        let tmp = this[startIndex + times];
1594        this[startIndex + times] = this[endIndex - times];
1595        this[endIndex - times] = tmp;
1596        times++;
1597      }
1598    }
1599    return this;
1600  }
1601
1602  swap16(): Buffer {
1603    const len = this.length;
1604    const dealLen: number = 2;  // Process every 2 bits
1605    if (len % dealLen !== 0) {
1606      throw bufferSizeError("16-bits");
1607    }
1608    return this.reverseBits(dealLen);
1609  }
1610
1611  swap32(): Buffer {
1612    const len = this.length;
1613    const dealLen: number = 4;  // Process every 4 bits
1614    if (len % dealLen !== 0) {
1615      throw bufferSizeError("32-bits");
1616    }
1617    return this.reverseBits(dealLen);
1618  }
1619
1620  swap64(): Buffer {
1621    const len = this.length;
1622    const dealLen: number = 8;  // Process every 8 bits
1623    if (len % dealLen !== 0) {
1624      throw bufferSizeError("64-bits");
1625    }
1626    return this.reverseBits(dealLen);
1627  }
1628
1629  keys(): IterableIterator<number> {
1630    return this[bufferSymbol].getBufferData().keys();
1631  }
1632
1633  values(): IterableIterator<number> {
1634    return this[bufferSymbol].getBufferData().values();
1635  }
1636
1637  entries(): IterableIterator<[number, number]> {
1638    return this[bufferSymbol].getBufferData().entries();
1639  }
1640
1641  [Symbol.iterator]() {
1642    return this[bufferSymbol].getBufferData().entries();
1643  }
1644}
1645
1646function typeError(param: unknown, paramName: string, excludedTypes: string[]): BusinessError {
1647  let msg = new ErrorMessage(errorMap.TypeError, paramName).setTypeInfo(excludedTypes, param).getString();
1648  return new BusinessError(msg, errorMap.TypeError);
1649}
1650
1651function typeErrorForEncoding(param: unknown, paramName: string): BusinessError {
1652  let msg = new ErrorMessage(errorMap.TypeError, paramName).setEncodingTypeInfo(['BufferEncoding'], param).getString();
1653  return new BusinessError(msg, errorMap.TypeError);
1654}
1655
1656function typeErrorForProperty(typeName: string): BusinessError {
1657  let msg = new ErrorMessage(errorMap.TypeErrorForProperty).setProperty(typeName).getString();
1658  return new BusinessError(msg, errorMap.TypeErrorForProperty);
1659}
1660
1661function typeErrorForSize(param: unknown, paramName: string, excludedTypes: string[]): BusinessError {
1662  let msg = new ErrorMessage(errorMap.TypeError, paramName).setSizeTypeInfo(excludedTypes, param).getString();
1663  return new BusinessError(msg, errorMap.TypeError);
1664}
1665
1666function rangeError(paramName: string, rangeLeft: string | bigint | number, rangeRight: string | bigint | number,
1667                    receivedValue: number | bigint): BusinessError {
1668  let msg =
1669    new ErrorMessage(errorMap.RangeError, paramName).setRangeInfo(rangeLeft, rangeRight, receivedValue).getString();
1670  return new BusinessError(msg, errorMap.RangeError);
1671}
1672
1673function rangeLeftError(paramName: string, rangeLeft: number, receivedValue: number): BusinessError {
1674  let msg = new ErrorMessage(errorMap.RangeError, paramName).setRangeLeftInfo(rangeLeft, receivedValue).getString();
1675  return new BusinessError(msg, errorMap.RangeError);
1676}
1677
1678function bufferSizeError(size: string): BusinessError {
1679  let msg = new ErrorMessage(errorMap.BufferSizeError).setSizeInfo(size).getString();
1680  return new BusinessError(msg, errorMap.BufferSizeError);
1681}
1682
1683function typeErrorCheck(param: unknown, types: string[], paramName: string) {
1684  let typeName = getTypeName(param);
1685  if (!types.includes(typeName)) {
1686      throw typeError(param, paramName, types);
1687  }
1688}
1689
1690function sizeErrorCheck(param: unknown, paramName: string, types: string[], rangeLeft: number, rangeRight: number) {
1691  let typeName = getTypeName(param);
1692  if (!types.includes(typeName)) {
1693    throw typeErrorForSize(param, paramName, types);
1694  }
1695  if (Number(param) < rangeLeft || Number(param) > rangeRight) {
1696    let typeString = types.join(', ');
1697    typeString = typeString.replace(',' , ' or');
1698    let msg = 'The type of "' + paramName + '" must be ' + typeString +
1699              ' and the value cannot be negative. Received value is: ' + Number(param).toString();
1700    throw  new BusinessError(msg, errorMap.TypeError);
1701  }
1702}
1703
1704function encodingTypeErrorCheck(encoding: string): string {
1705  const normalizedEncoding = normalizeEncoding(encoding);
1706  if (normalizedEncoding === undefined) {
1707    throw typeErrorForEncoding(encoding, "encoding");
1708  }
1709  return normalizedEncoding;
1710}
1711
1712function rangeErrorCheck(param: number | bigint, paramName: string, rangeLeft: bigint | number,
1713                         rangeRight: bigint | number, rangeLeftExpr: string = "", rangeRightExpr: string = "") {
1714  let left = BigInt(rangeLeft);
1715  let right = BigInt(rangeRight);
1716  if (param < left || param > right) {
1717    throw rangeError(paramName, rangeLeftExpr == "" ? rangeLeft : rangeLeftExpr,
1718                     rangeRightExpr == "" ? rangeRight : rangeRightExpr, param);
1719  }
1720}
1721
1722function rangeLeftErrorCheck(param: number, paramName: string, rangeLeft: number) {
1723  if (param < rangeLeft) {
1724    throw rangeLeftError(paramName, rangeLeft, param);
1725  }
1726}
1727
1728function concat(list: Buffer[] | Uint8Array[], totalLength?: number): Buffer {
1729  typeErrorCheck(list, ['Array'], "list");
1730  if (!(typeof totalLength === 'number' || typeof totalLength === 'undefined')) {
1731    throw typeError(totalLength, "totalLength", ['number']);
1732  }
1733  if (list.length === 0) {
1734    return new Buffer(0);
1735  }
1736  if (!totalLength) {
1737    totalLength = 0;
1738    for (let i = 0, len = list.length; i < len; i++) {
1739      let buf = list[i];
1740      if (buf instanceof Uint8Array || buf instanceof Buffer) {
1741        totalLength += list[i].length;
1742      }
1743    }
1744  }
1745
1746  rangeErrorCheck(totalLength, "totalLength", 0, UINT32MAX);
1747
1748  let buffer = allocUninitializedFromPool(totalLength);
1749  let offset = 0;
1750  for (let i = 0, len = list.length; i < len; i++) {
1751    const buf = list[i];
1752    if (buf instanceof Uint8Array) {
1753      buf.forEach((val) => buffer[offset++] = val);
1754    } else if (buf instanceof Buffer) {
1755      buf.copy(buffer, offset);
1756      offset += buf.length;
1757    }
1758  }
1759  return buffer;
1760}
1761
1762function alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer
1763{
1764  sizeErrorCheck(size, "size", ['number'], 0, MAX_LENGTH);
1765  const buf = new Buffer(size);
1766  buf.fill(0);
1767  if(arguments.length === 2 && fill !== undefined && fill !== 0) {
1768    buf.fill(fill);
1769  } else if (arguments.length === 3) {
1770    typeErrorCheck(encoding, ['string'], "encoding");
1771    if (fill !== undefined && fill !== 0) {
1772      buf.fill(fill, undefined, undefined, encoding);
1773    }
1774  }
1775  return buf;
1776}
1777
1778function allocUninitializedFromPool(size: number): Buffer
1779{
1780  sizeErrorCheck(size, "size", ['number'], 0, MAX_LENGTH);
1781  if (!pool) {
1782    createPool();
1783  }
1784  if (size < (poolSize >>> 1)) {
1785    if (size > (poolSize - poolOffset)) {
1786      createPool();
1787    }
1788    const b = new Buffer(pool, poolOffset, size);
1789    poolOffset += size;
1790    alignPool();
1791    return b;
1792  }
1793  return new Buffer(size);
1794}
1795
1796function allocUninitialized(size: number): Buffer
1797{
1798  sizeErrorCheck(size, "size", ['number'], 0, MAX_LENGTH);
1799  const buf = new Buffer(size);
1800  return buf;
1801}
1802
1803function normalizeEncoding(enc: string) {
1804  enc = enc.toLowerCase();
1805  if (bufferEncoding.includes(enc)) {
1806    if (enc === 'ucs2' || enc === 'ucs-2' || enc === 'utf-16le') {
1807      enc = 'utf16le';
1808    }
1809    if (enc === 'utf-8') {
1810      enc = 'utf8';
1811    }
1812    return enc;
1813  } else {
1814    return undefined;
1815  }
1816}
1817
1818function from(value: Buffer | Uint8Array | ArrayBuffer | SharedArrayBuffer | string | object | Array<number>,
1819              offsetOrEncoding?: number | string, length?: number): Buffer
1820{
1821  if (value instanceof ArrayBuffer || value instanceof SharedArrayBuffer ) {
1822    offsetOrEncoding = isNaN(Number(offsetOrEncoding)) ? 0 : Number(offsetOrEncoding);
1823    if (offsetOrEncoding < 0) {
1824      throw typeError(offsetOrEncoding, "offset", ['number']);
1825    }
1826    if (!length) {
1827      length = value.byteLength - offsetOrEncoding;
1828    } else {
1829      length = isNaN(Number(length)) ? 0 : Number(length);
1830    }
1831    rangeErrorCheck(offsetOrEncoding, "byteOffset", 0, value.byteLength);
1832    rangeErrorCheck(length, "length", 0, value.byteLength - offsetOrEncoding);
1833    return new Buffer(value, offsetOrEncoding, length);
1834  }
1835  if (value instanceof Buffer) {
1836    return new Buffer(value);
1837  }
1838  if (value instanceof Uint8Array) {
1839    return new Buffer(value);
1840  }
1841  if (value instanceof Array) {
1842    if (!pool) {
1843      createPool()
1844    }
1845    let buffer = new Buffer(pool, poolOffset, value.length);
1846    poolOffset += value.length;
1847    alignPool();
1848    buffer[bufferSymbol].setArray(value);
1849    return buffer;
1850  }
1851  let encoding = "";
1852  if (typeof value === 'string' || typeof value[Symbol.toPrimitive] === 'function') {
1853    offsetOrEncoding = offsetOrEncoding ? offsetOrEncoding :"utf8";
1854    if (typeof offsetOrEncoding !== 'string') {
1855      throw typeError(getTypeName(offsetOrEncoding), "offsetOrEncoding", ['string']);
1856    } else {
1857      encoding = encodingTypeErrorCheck(offsetOrEncoding);
1858    }
1859  }
1860  if (typeof value === 'string') {
1861    return fromString(value, encoding);
1862  }
1863  if (typeof value === 'object' && value !== null) {
1864    const valueOf = value.valueOf && value.valueOf();
1865    if (valueOf != null &&
1866        valueOf !== value &&
1867        (typeof valueOf === 'string' || typeof valueOf === 'object')) {
1868      return from(valueOf, offsetOrEncoding, length);
1869    }
1870    if (typeof value[Symbol.toPrimitive] === 'function') {
1871      const primitive = value[Symbol.toPrimitive]('string');
1872      if (typeof primitive === 'string') {
1873        return fromString(primitive, encoding);
1874      }
1875    }
1876  }
1877  throw typeError(getTypeName(value), "value", ['Buffer', 'ArrayBuffer', 'Array', 'Array-like']);
1878}
1879
1880function hexStrtoNumbers(hex: string): Array<number>
1881{
1882  let arr = hex.split("");
1883  let nums: Array<number> = [];
1884  for (let i = 0, len = arr.length; i < len / 2; i++) {
1885    let tmp = "0x" + arr[i * 2] + arr[i * 2 + 1]
1886    let hexNum = Number(tmp);
1887    if (isNaN(hexNum)) {
1888      if (i == 0) {
1889        throw new Error(`The argument 'value' is invalid. Received "${hex}"`)
1890      }
1891      break;
1892    }
1893    nums[i] = Number(tmp);
1894  }
1895  return nums;
1896}
1897
1898function fromString(value: string, encoding: string): Buffer
1899{
1900  let enc = normalizeEncoding(encoding);
1901  if (!enc) {
1902    throw typeErrorForEncoding(encoding, "encoding");
1903  }
1904  let size = byteLength(value, enc);
1905  let buffer = allocUninitializedFromPool(size);
1906  buffer[bufferSymbol].fromString(value, enc, size);
1907  buffer[lengthSymbol] = buffer[bufferSymbol].getLength();
1908  return buffer;
1909}
1910
1911function isTypedArray(self: unknown) : boolean{
1912  let typeArr = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array,
1913                 Int32Array, Uint32Array, Float32Array, Float64Array];
1914  for (let i = 0, len = typeArr.length; i < len; i++) {
1915    if (self instanceof typeArr[i]) {
1916      return true;
1917    }
1918  }
1919  return false;
1920}
1921
1922function isBuffer(obj: Object): boolean {
1923  return obj instanceof Buffer;
1924}
1925
1926function isEncoding(encoding: string): boolean {
1927  if (typeof encoding !== 'string' || encoding.length === 0) {
1928    return false;
1929  }
1930  return getEncodingByType(encoding) ? true : false;
1931}
1932
1933function byteLength(string: string | BackingType, encoding: string = "utf8"): number {
1934  if (typeof string === 'string' || isTypedArray(string) ||
1935      string instanceof DataView || string instanceof ArrayBuffer ||
1936      string instanceof SharedArrayBuffer) {
1937    if (string instanceof Buffer) {
1938      return string.length;
1939    } else if(typeof string === 'string') {
1940      if (string.length === 0) {
1941        return 0;
1942      }
1943      let encodRes = getEncodingByType(encoding);
1944      if (!encodRes) {
1945        return getUtf8ByteLength(string);
1946      }
1947      return encodRes.byteLength(string);
1948    } else {
1949      return string.byteLength;
1950    }
1951  } else {
1952    throw typeError(string, "string", ['string', 'Buffer', 'ArrayBuffer']);
1953  }
1954}
1955
1956function transcode(source: Buffer | Uint8Array, fromEnc: string, toEnc: string): Buffer {
1957  typeErrorCheck(source, ['Buffer', 'Uint8Array'], "source");
1958  typeErrorCheck(fromEnc, ['string'], "fromEnc");
1959  typeErrorCheck(toEnc, ['string'], "toEnc");
1960  let from = source.toString(fromEnc);
1961  return fromString(from, toEnc);
1962}
1963
1964function toUtf8(self: Buffer, start: number, end: number): string {
1965  return self[bufferSymbol].toUtf8(start, end);
1966}
1967
1968function toAscii(self: Buffer, start: number, end: number): string {
1969  let bufData = self[bufferSymbol].getBufferData();
1970  let val = '';
1971  for (let i = start; i < end; i++) {
1972    val += String.fromCharCode(+bufData[i] & 0x7F); // 0x7F : get the lower 15-bits
1973  }
1974  return val;
1975}
1976
1977function toBinary(self: Buffer, start: number, end: number): string {
1978  let bufData = self[bufferSymbol].getBufferData();
1979  let val = '';
1980  for (let i = start; i < end; i++) {
1981    val += String.fromCharCode(+bufData[i]);
1982  }
1983  return val;
1984}
1985
1986function toHex(self: Buffer, start: number, end: number): string {
1987  let bufData = self[bufferSymbol].getBufferData();
1988  let str = "";
1989  for (let i = start, len = end; i < len; i++) {
1990    let tmpstr = Number(bufData[i]).toString(16); // 16 : 16 decimal
1991    tmpstr = (tmpstr.length === 1)? `0${tmpstr}` : tmpstr;
1992    str += tmpstr;
1993  }
1994  return str;
1995}
1996
1997function toUtf16LE(self: Buffer, start: number, end: number): string {
1998  let bufData = self[bufferSymbol].getBufferData();
1999  let val = '';
2000  for (let i = start; i + 1 < end; i += 2) {
2001    val += String.fromCodePoint((bufData[i + 1] << 8) + (bufData[i])) // 8 means offset 8 bits
2002  }
2003  return val;
2004}
2005
2006function toBase64(self: Buffer, start: number, end: number): string {
2007  let str = self[bufferSymbol].toBase64(start, end);
2008  return str;
2009}
2010
2011function getEncodingByType(type: string) {
2012  type = type.toLowerCase();
2013  switch (type) {
2014    case 'utf8':
2015    case 'utf-8':
2016      return {
2017        byteLength: getUtf8ByteLength,
2018        toString: toUtf8
2019      }
2020    case 'ucs2':
2021    case 'ucs-2':
2022      return {
2023        byteLength: (str: string) => str.length * 2, // 2 : 2 times of ascii
2024        toString: toUtf16LE
2025      }
2026    case 'ascii':
2027    case 'latin1':
2028      return {
2029        byteLength: (str: string) => str.length,
2030        toString: toAscii
2031      }
2032    case 'binary':
2033      return {
2034        byteLength: (str: string) => str.length,
2035        toString: toBinary
2036      }
2037    case 'utf16le':
2038    case 'utf-16le':
2039      return {
2040        byteLength: (str: string) => str.length * 2, // 2 : 2 times of ascii
2041        toString: toUtf16LE
2042      }
2043    case 'base64':
2044    case 'base64url':
2045      return {
2046        byteLength: getBase64ByteLength,
2047        toString: toBase64
2048      }
2049    case 'hex':
2050      return {
2051        byteLength: (str: string) => str.length >>> 1, // 1 : one-half
2052        toString: toHex
2053      }
2054    default:
2055      return undefined;
2056  }
2057}
2058
2059function getUtf8ByteLength(str: string): number {
2060  return InternalBuffer.utf8ByteLength(str);
2061}
2062
2063function getBase64ByteLength(str: string): number {
2064  let bytes = str.length;
2065  for (let i = 0, len = str.length; i < len; i++) {
2066    if (str.charCodeAt(i) === 0x3D) { // 0x3D : ascii code represent of '='
2067      bytes--;
2068    }
2069    if (bytes > 1 && str.charCodeAt(i) === 0x3D) { // 0x3D : ascii code represent of '='
2070      bytes--;
2071    }
2072  }
2073  return (bytes * 3) >>> 2; // 3 : 4 : Base64 ratio: 3/4
2074}
2075
2076function compare(buf1: Buffer | Uint8Array, buf2: Buffer | Uint8Array): 1 | 0 | -1 {
2077  if (!(buf1 instanceof Buffer) && !(buf1 instanceof Uint8Array)) {
2078    throw new BusinessError(new ErrorMessage(errorMap.TypeError, "buf1").setTypeInfo(['Buffer', 'Uint8Array'], getTypeName(buf1)).getString(), errorMap.TypeError);
2079  }
2080  if (!(buf2 instanceof Buffer) && !(buf2 instanceof Uint8Array)) {
2081    throw new BusinessError(new ErrorMessage(errorMap.TypeError, "buf2").setTypeInfo(['Buffer', 'Uint8Array'], getTypeName(buf2)).getString(), errorMap.TypeError);
2082  }
2083
2084  let bufData1: Array<number> | Uint8Array, bufData2: Array<number> | Uint8Array;
2085  if (buf1 instanceof Buffer) {
2086    bufData1 = buf1[bufferSymbol].getBufferData();
2087  } else {
2088    bufData1 = buf1;
2089  }
2090  if (buf2 instanceof Buffer) {
2091    bufData2 = buf2[bufferSymbol].getBufferData();
2092  } else {
2093    bufData2 = buf2;
2094  }
2095  let length1: number = bufData1.length;
2096  let length2: number = bufData2.length;
2097  let length: number = length1 > length2 ? length2 : length1;
2098  for (let i = 0; i < length; i++) {
2099    let value1 = +bufData1[i];
2100    let value2 = +bufData2[i];
2101    if (value1 > value2) {
2102      return 1;
2103    } else if (value1 < value2) {
2104      return -1;
2105    }
2106  }
2107  if (length1 > length2) {
2108    return 1;
2109  } else if (length1 < length2) {
2110    return -1;
2111  }
2112  return 0;
2113}
2114
2115export default {
2116  Buffer,
2117  Blob,
2118  from,
2119  alloc,
2120  allocUninitializedFromPool,
2121  allocUninitialized,
2122  byteLength,
2123  isBuffer,
2124  isEncoding,
2125  compare,
2126  concat,
2127  transcode
2128}
2129