UNPKG

beson

Version:

Yet an another binary representation of json format

2,281 lines (1,845 loc) 73.7 kB
(()=>{"use strict"; const writable=true, configurable=true, enumerable=false; const ___IS_LITTLE_ENDIAN = (new Uint8Array(Uint16Array.from([0x1234])))[0] === 0x34; if ( !___IS_LITTLE_ENDIAN ) { throw new Error( "Beson only supports little endian environment!" ) } const HAS_NODE_BUFFER = (typeof Buffer !== "undefined"); const DATA_TYPE = Object.freeze({ NULL: 1, FALSE: 2, TRUE: 3, STRING: 4, INT8: 5, INT16: 6, INT32: 7, INT64: 8, INT128: 9, INT256: 10, INT512: 11, // INTVAR: 12, UINT8: 13, UINT16: 14, UINT32: 15, UINT64: 16, UINT128: 17, UINT256: 18, UINT512: 19, // UINTVAR: 20, FLOAT32: 21, FLOAT64: 22, ARRAY: 23, SET: 24, OBJECT: 25, MAP: 26, ARRAY_BUFFER: 27, INT8_ARRAY: 28, UINT8_ARRAY: 29, INT16_ARRAY: 30, UINT16_ARRAY: 31, INT32_ARRAY: 32, UINT32_ARRAY: 33, FLOAT32_ARRAY: 34, FLOAT64_ARRAY: 35, DATA_VIEW: 36, SPECIAL_BUFFER: 37, DATE: 38, REGEX: 39, END: 99, BINARIZABLE: 100, }); const TYPE_HEADER = Object.freeze({ END: 0x00, NULL: 0x10, FALSE: 0x20, TRUE: 0x21, STRING: 0x30, INT8: 0x40, INT16: 0x41, INT32: 0x42, INT64: 0x43, INT128: 0x44, INT256: 0x45, INT512: 0x46, // INTVAR: 0x4F, UINT8: 0x50, UINT16: 0x51, UINT32: 0x52, UINT64: 0x53, UINT128: 0x54, UINT256: 0x55, UINT512: 0x56, // UINTVAR: 0x5F, FLOAT32: 0x60, FLOAT64: 0x61, ARRAY: 0x70, SET: 0x71, OBJECT: 0x80, MAP: 0x81, ARRAY_BUFFER: 0x90, INT8_ARRAY: 0x91, UINT8_ARRAY: 0x92, INT16_ARRAY: 0x93, UINT16_ARRAY: 0x94, INT32_ARRAY: 0x95, UINT32_ARRAY: 0x96, FLOAT32_ARRAY: 0x97, FLOAT64_ARRAY: 0x98, DATA_VIEW: 0x9E, SPECIAL_BUFFER: 0x9F, DATE: 0xA0, REGEX: 0xA1 }); const HEX_FORMAT_CHECKER = /^0x([0-9a-fA-F]{2})+$/; const BIN_FORMAT_CHECKER = /^0b([01]{8})+$/; const INT_FORMAT_CHECKER = /^[+-]?\d+$/; const DECIMAL_STEPPER = new Uint8Array([0x00, 0xCA, 0x9A, 0x3B]); // 1000000000 ( 0x3B9ACA00 ) const HEX_MAP_INVERSE = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 }; const UTF8_DECODE_CHUNK_SIZE = 100; function ReadBuffer(input){ if( HAS_NODE_BUFFER ){ if( input instanceof Buffer ){ let buff = Buffer.alloc(input.length); input.copy(buff, 0); return buff.buffer; } } if( ArrayBuffer.isView(input) ){ return input.buffer; } if( input instanceof ArrayBuffer ){ return input; } return null; } function MergeArrayBuffers(...array_buffers) { if( !array_buffers[0] instanceof ArrayBuffer ) { throw new TypeError("Given inputs must be ArrayBuffers!"); } if ( Array.isArray(array_buffers[0]) ) { array_buffers = array_buffers[0]; } let totalLength = 0; for( let ab of array_buffers ) { totalLength += ab.byteLength; } // NOTE: Copy all data const newInst = new Uint8Array(totalLength); let offset = 0; for( let ab of array_buffers ){ newInst.set(new Uint8Array(ab), offset); offset += ab.byteLength; } return newInst.buffer; } function HexToBuffer(inputStr, length = null){ if( !HEX_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( inputStr.length % 2 === 1 ){ inputStr = '0' + inputStr; } let buffer = new Uint8Array(inputStr.length / 2); for( let pointer = 0; pointer < buffer.length; pointer++ ){ let offset = pointer * 2; buffer[pointer] = HEX_MAP_INVERSE[inputStr[offset + 1]] | (HEX_MAP_INVERSE[inputStr[offset]] << 4); } return buffer.buffer; } function UTF8Encode(str){ let codePoints = []; let i=0; while( i < str.length ) { let codePoint = str.codePointAt(i); // 1-byte sequence if( (codePoint & 0xffffff80) === 0 ) { codePoints.push(codePoint); } // 2-byte sequence else if( (codePoint & 0xfffff800) === 0 ) { codePoints.push( 0xc0 | (0x1f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } // 3-byte sequence else if( (codePoint & 0xffff0000) === 0 ) { codePoints.push( 0xe0 | (0x0f & (codePoint >> 12)), 0x80 | (0x3f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } // 4-byte sequence else if( (codePoint & 0xffe00000) === 0 ) { codePoints.push( 0xf0 | (0x07 & (codePoint >> 18)), 0x80 | (0x3f & (codePoint >> 12)), 0x80 | (0x3f & (codePoint >> 6)), 0x80 | (0x3f & codePoint) ); } i += (codePoint>0xFFFF) ? 2 : 1; } return new Uint8Array(codePoints); } function UTF8Decode(buffer){ let uint8 = new Uint8Array(buffer); let codePoints = []; let i = 0; while( i < uint8.length ) { let codePoint = uint8[i] & 0xff; // 1-byte sequence (0 ~ 127) if( (codePoint & 0x80) === 0 ){ codePoints.push(codePoint); i += 1; } // 2-byte sequence (192 ~ 223) else if( (codePoint & 0xE0) === 0xC0 ){ codePoint = ((0x1f & uint8[i]) << 6) | (0x3f & uint8[i + 1]); codePoints.push(codePoint); i += 2; } // 3-byte sequence (224 ~ 239) else if( (codePoint & 0xf0) === 0xe0 ){ codePoint = ((0x0f & uint8[i]) << 12) | ((0x3f & uint8[i + 1]) << 6) | (0x3f & uint8[i + 2]); codePoints.push(codePoint); i += 3; } // 4-byte sequence (249 ~ ) else if( (codePoint & 0xF8) === 0xF0 ){ codePoint = ((0x07 & uint8[i]) << 18) | ((0x3f & uint8[i + 1]) << 12) | ((0x3f & uint8[i + 2]) << 6) | (0x3f & uint8[i + 3]); codePoints.push(codePoint); i += 4; } else { i += 1; } } let result_string = ""; while(codePoints.length > 0) { const chunk = codePoints.splice(0, UTF8_DECODE_CHUNK_SIZE); result_string += String.fromCodePoint(...chunk); } return result_string; } function BitwiseNot(input){ input = ReadBuffer(input); if( input === null ){ throw new TypeError("Given input must be an ArrayBuffer!"); } const buffer = new Uint8Array(input); for( let off = 0; off < buffer.length; off++ ){ buffer[off] = ~buffer[off]; } } function BitwiseAnd(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } const bufferA = new Uint8Array(a); const bufferB = new Uint8Array(b); for( let off = 0; off < bufferA.length; off++ ){ bufferA[off] = bufferA[off] & (bufferB[off] || 0); } } function BitwiseOr(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } const bufferA = new Uint8Array(a); const bufferB = new Uint8Array(b); for( let off = 0; off < bufferA.length; off++ ){ bufferA[off] = bufferA[off] | (bufferB[off] || 0); } } function BitwiseXor(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } const bufferA = new Uint8Array(a); const bufferB = new Uint8Array(b); for( let off = 0; off < bufferA.length; off++ ){ bufferA[off] = bufferA[off] ^ (bufferB[off] || 0); } } function BitwiseIsZero(input){ const buff = new Uint8Array(ReadBuffer(input)); let isZero = true; for( let i = 0; i < buff.length; i++ ){ isZero = isZero && (buff[i] === 0); } return isZero; } function __COPY_BYTES(target, source, length, source_start=0, target_start=0) { for(let i=0; i<length; i++) { target[target_start+i] = source[source_start+i]; } } function ___SET_BINARY_BUFFER(array_buffer){ if( !(array_buffer instanceof ArrayBuffer) ){ throw new TypeError("Given input must be an ArrayBuffer!"); } this._ab = array_buffer; this._ba = new Uint8Array(this._ab); return this; } // region [ Little Endian Operations ] function BufferFromHexStrLE(inputStr, size = null){ if( !HEX_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( inputStr.length % 2 === 1 ){ inputStr = '0' + inputStr; } let inputLen = Math.floor(inputStr.length / 2); if( arguments.length <= 1 ){ size = inputLen; } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < inputLen; pointer++ ){ let offset = (inputLen - pointer - 1) * 2; buffer[pointer] = HEX_MAP_INVERSE[inputStr[offset + 1]] | (HEX_MAP_INVERSE[inputStr[offset]] << 4); } return buffer; } function BufferFromBinStrLE(inputStr, size = null){ if( !BIN_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); let inputLen = Math.floor(inputStr.length / 8); if( arguments.length <= 1 ){ size = inputLen; } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < inputLen; pointer++ ){ let offset = (inputLen - pointer - 1) * 8; buffer[pointer] = Number.parseInt(inputStr.substring(offset, offset + 8), 2); } return buffer; } function DumpHexStringLE(input){ let val = new Uint8Array(ReadBuffer(input)); let str = ''; for( let i = val.length - 1; i >= 0; i-- ){ let value = val[i].toString(16); str += `${ value.length === 1 ? '0' : '' }${ value }`; } return str; } function DumpBinaryStringLE(input){ let val = new Uint8Array(ReadBuffer(input)); let str = ''; for( let i = val.length - 1; i >= 0; i-- ){ let value = val[i]; for( let s = 0; s < 8; s++ ){ str += ((value << s) & 0x80) ? '1' : '0'; } } return str; } function BitwiseCompareLE(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } // NOTE: Compare nothing... if( a.byteLength === 0 && b.byteLength === 0 ){ return 0; } let A = new Uint8Array(a); let B = new Uint8Array(b); let valA, valB; for( let i = Math.max(A.length, B.length); i > 0; i-- ){ valA = A[i-1] || 0; valB = B[i-1] || 0; if( valA === valB ){ continue; } return valA > valB ? 1 : -1; } return 0; } function BitwiseRightShiftLE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits number must be a number"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ buffer.fill(padding); } else{ const OFFSET = (shift / 8) | 0; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const HI_MASK = REAL_SHIFT ? ___GEN_8BITS_MASK(REAL_SHIFT) : 0; const LOOP_END = buffer.byteLength - OFFSET; for( let off = 0; off < LOOP_END; off++ ){ let shift = off + OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = (shift >= buffer.byteLength - 1) ? padding : buffer[shift + 1]; buffer[off] = (shiftVal >>> REAL_SHIFT) | ((next & HI_MASK) << REAL_SHIFT_I); } } for( let off = LOOP_END; off < buffer.byteLength; off++ ){ buffer[off] = padding; } } } } function BitwiseLeftShiftLE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits must be a number!"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ buffer.fill(padding); } else{ const OFFSET = (shift / 8) | 0; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const LO_MASK = REAL_SHIFT ? (___GEN_8BITS_MASK(REAL_SHIFT) << REAL_SHIFT_I) : 0; for( let off = buffer.byteLength - 1; off >= OFFSET; off-- ){ let shift = off - OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = (shift <= 0) ? padding : buffer[shift - 1]; buffer[off] = (shiftVal << REAL_SHIFT) | ((next & LO_MASK) >> REAL_SHIFT_I); } } buffer.fill(padding, 0, OFFSET); } } } function BitwiseIsNegativeLE(input){ const buff = new Uint8Array(ReadBuffer(input)); return ((buff[buff.length - 1] & 0x80) !== 0) } // region [ Little Endian exclusive functions ] function BufferFromIntStrLE(inputStr, size = null){ if( !INT_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } let negative = false; if( inputStr[0] === "-" ){ negative = true; inputStr = inputStr.substring(1); } else if( inputStr[0] === "+" ){ inputStr = inputStr.substring(1); } let force_size = true; let inputLen = Math.ceil(Math.ceil(inputStr.length * Math.log2(10)) / 8); if( arguments.length <= 1 ){ force_size = false; size = inputLen; } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } const inputs = []; while( inputStr.length > 0 ){ let anchor = inputStr.length - 9; inputs.push(Number.parseInt(inputStr.substring(anchor), 10)); inputStr = inputStr.substring(0, anchor); } inputs.reverse(); const buffer = new Uint8Array(size); const part = new Uint32Array(1); for( let i = 0; i < inputs.length; i++ ){ part[0] = inputs[i]; BitwiseMultiplicationLE(buffer, DECIMAL_STEPPER); BitwiseAdditionLE(buffer, part); } // NOTE: In case that the highest bit is 1 ( the size is not efficient to represent the value ) let _result = buffer; if( !force_size ){ let real_len = size - 1; while( (real_len > 0) && ((buffer[real_len] & 0xFF) === 0) ){ real_len--; } if( (buffer[real_len] & 0x80) !== 0 ){ real_len++; } _result = (real_len === size) ? buffer : buffer.slice(0, real_len + 1); } if( negative ){ BitwiseTwoComplimentLE(_result); } return _result; } function DumpIntStringLE(input, unsigned = false){ let is_negative = false; const value = new Uint8Array(ReadBuffer(input).slice(0)); if( !unsigned && BitwiseIsNegativeLE(value) ){ BitwiseTwoComplimentLE(value); is_negative = true; } let result = ''; const remainder = new Uint8Array(value.length); const stepper = new Uint8Array(value.length); stepper[0] = 100; BitwiseDivisionLE(value, stepper, true, remainder); while( !BitwiseIsZero(value) ){ let part = remainder[0].toString(10); result = ((part.length === 1) ? `0${ part }` : part) + result; BitwiseDivisionLE(value, stepper, true, remainder); } return (is_negative ? '-' : '') + remainder[0].toString(10) + result; } function BitwiseMultiplicationLE(multiplier, multiplicand){ const a = new Uint8Array(ReadBuffer(multiplier)); const b = new Uint8Array(ReadBuffer(multiplicand)); const res = new Uint8Array(a.length); let carriage = 0; for( let i = 0; i < res.length; i++ ){ for( let j = 0; j <= i; j++ ){ carriage += a[j] * (b[i - j] || 0) } res[i] = carriage; carriage = (carriage / 256) | 0; } a.set(res); } function BitwiseAdditionLE(addend_a, addend_b){ let a = new Uint8Array(ReadBuffer(addend_a)); let b = new Uint8Array(ReadBuffer(addend_b)); let carriage = 0; for( let i = 0; i < a.length; i++ ){ carriage += a[i] + (b[i] || 0); a[i] = carriage; carriage = (carriage / 256) | 0; } } function BitwiseSubtractionLE(minuend, subtrahend){ const a = new Uint8Array(ReadBuffer(minuend)); const b = new Uint8Array(ReadBuffer(subtrahend)); const negB = new Uint8Array(b); BitwiseTwoComplimentLE(negB); BitwiseAdditionLE(a, negB); } function BitwiseDivisionLE(dividend, divisor, unsigned = false, remainder_buff = null){ const raw_a = new Uint8Array(ReadBuffer(dividend)); const raw_b = new Uint8Array(ReadBuffer(divisor)); const a = raw_a; const b = new Uint8Array(a.length); b.set(raw_b); if( BitwiseIsZero(b) ){ throw new TypeError("Dividing zero is not allowed!"); } let neg_dividend = 0x00, neg_divisor = 0x00; if( !unsigned ){ neg_dividend = BitwiseIsNegativeLE(a) ? 0x01 : 0x00; if( neg_dividend ){ BitwiseTwoComplimentLE(a); } neg_divisor = BitwiseIsNegativeLE(b) ? 0x01 : 0x00; if( neg_divisor ){ BitwiseTwoComplimentLE(b); } } const remainder = new Uint8Array((remainder_buff !== null) ? ReadBuffer(remainder_buff) : a.length); remainder.set(a); const quotient = a; quotient.fill(0); if( BitwiseCompareLE(remainder, b) >= 0 ){ let _remainder = remainder.slice(0); let _divisor = b; // region [ Align divisor and remainder ] let d_padding = 0, r_padding = 0, count = _remainder.length * 8; while( count-- > 0 ){ if( (_remainder[_remainder.length - 1] & 0x80) !== 0 ){ break; } BitwiseLeftShiftLE(_remainder, 1); r_padding++; } _remainder = remainder; count = _divisor.length * 8; while( count-- > 0 ){ if( (_divisor[_divisor.length - 1] & 0x80) !== 0 ){ break; } BitwiseLeftShiftLE(_divisor, 1); d_padding++; } BitwiseRightShiftLE(_divisor, r_padding); // endregion // region [ Calc division ] count = d_padding - r_padding + 1; while( count-- > 0 ){ if( BitwiseCompareLE(_remainder, _divisor) >= 0 ){ BitwiseSubtractionLE(_remainder, _divisor); quotient[0] = quotient[0] | 0x01; } if( count > 0 ){ BitwiseLeftShiftLE(quotient, 1); BitwiseRightShiftLE(_divisor, 1); } } // endregion } if( neg_divisor ^ neg_dividend ){ BitwiseTwoComplimentLE(quotient); } return remainder; } function BitwiseTwoComplimentLE(input){ input = ReadBuffer(input); if( input === null ){ throw new TypeError("Given input must be an ArrayBuffer!"); } const buffer = new Uint8Array(input); let carriage = 1; for( let off = 0; off < buffer.length; off++ ){ carriage += ((~buffer[off] >>> 0) & 0xFF); buffer[off] = carriage; carriage = (carriage / 256) | 0; } } // endregion // endregion // region [ Big Endian Operations ] function BufferFromHexStrBE(inputStr, size = 0){ if( !HEX_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( inputStr.length % 2 === 1 ){ inputStr = '0' + inputStr; } if( arguments.length <= 1 ){ size = Math.floor(inputStr.length / 2); } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < buffer.length; pointer++ ){ let offset = pointer * 2; buffer[pointer] = HEX_MAP_INVERSE[inputStr[offset + 1]] | (HEX_MAP_INVERSE[inputStr[offset]] << 4); } return buffer; } function BufferFromBinStrBE(inputStr, size = null){ if( !BIN_FORMAT_CHECKER.test(inputStr) ){ throw new SyntaxError("Given hex string is not a valid hex string!"); } inputStr = inputStr.slice(2); if( arguments.length <= 1 ){ size = Math.floor(inputStr.length / 8); } else if( size < 0 ){ throw new RangeError("Given buffer size should greater than or equal to 0!"); } let buffer = new Uint8Array(size); for( let pointer = 0; pointer < buffer.length; pointer++ ){ let offset = pointer * 8; buffer[pointer] = Number.parseInt(inputStr.substring(offset, offset + 8), 2); } return buffer; } function DumpHexStringBE(input){ let val = new Uint8Array(ReadBuffer(input)); const length = val.length; let str = ''; for( let i = 0; i < length; i++ ){ let value = val[i].toString(16); str += `${ value.length === 1 ? '0' : '' }${ value }`; } return str; } function DumpBinaryStringBE(input){ let val = new Uint8Array(ReadBuffer(input)); const length = val.length; let str = ''; for( let i = 0; i < length; i++ ){ let value = val[i]; for( let s = 0; s < 8; s++ ){ str += ((value << s) & 0x80) ? '1' : '0'; } } return str; } function BitwiseIsNegativeBE(input){ const buff = new Uint8Array(ReadBuffer(input)); return ((buff[0] & 0x80) !== 0) } function BitwiseCompareBE(a, b){ a = ReadBuffer(a); b = ReadBuffer(b); if( a === null || b === null ){ throw new TypeError("Given inputs must be ArrayBuffers!"); } // NOTE: Compare nothing... if( a.byteLength === 0 && b.byteLength === 0 ){ return 0; } let A = new Uint8Array(a); let B = new Uint8Array(b); let valA, valB, max = Math.max(A.length, B.length); for( let i = 0; i < max; i++ ){ valA = A[i] || 0; valB = B[i] || 0; if( valA === valB ){ continue; } return valA > valB ? 1 : -1; } return 0; } function BitwiseRightShiftBE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits number must be a number"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ for( let off = 0; off < buffer.length; off++ ){ buffer.fill(padding); } } else{ const OFFSET = (shift / 8) | 0; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const HI_MASK = REAL_SHIFT ? ___GEN_8BITS_MASK(REAL_SHIFT) : 0; for( let off = (buffer.byteLength - 1); off >= OFFSET; off-- ){ let shift = off - OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = (shift === 0) ? padding : buffer[shift - 1]; buffer[off] = (shiftVal >>> REAL_SHIFT) | ((next & HI_MASK) << REAL_SHIFT_I); } } for( let off = OFFSET - 1; off >= 0; off-- ){ buffer[off] = padding; } } } } function BitwiseLeftShiftBE(value, shift, padding = 0){ if( typeof shift !== "number" ){ throw new TypeError("Shift bits must be a number!"); } value = ReadBuffer(value); if( value === null ){ throw new TypeError("Given value must be an ArrayBuffer!"); } const buffer = new Uint8Array(value); if( shift > 0 ){ padding = padding ? 0xFF : 0x00; if( shift >= buffer.byteLength * 8 ){ for( let off = 0; off < buffer.length; off++ ){ buffer.fill(padding); } } else{ const OFFSET = (shift / 8) | 0; const LAST_OFFSET = buffer.byteLength - OFFSET; const REAL_SHIFT = shift % 8; const REAL_SHIFT_I = 8 - REAL_SHIFT; const LO_MASK = REAL_SHIFT ? (___GEN_8BITS_MASK(REAL_SHIFT) << REAL_SHIFT_I) : 0; for( let off = 0; off < LAST_OFFSET; off++ ){ let shift = off + OFFSET; if( REAL_SHIFT === 0 ){ buffer[off] = buffer[shift]; } else{ let shiftVal = buffer[shift]; let next = shift >= (buffer.byteLength - 1) ? padding : buffer[shift + 1]; buffer[off] = (shiftVal << REAL_SHIFT) | ((next & LO_MASK) >> REAL_SHIFT_I); } } for( let off = LAST_OFFSET; off < buffer.byteLength; off++ ){ buffer[off] = padding; } } } } // endregion /** * Generate a 8-bits mask * @param {Number} BITS * @private **/ function ___GEN_8BITS_MASK(BITS){ if( BITS > 8 ) return 0xFF; if( BITS < 0 ) return 0; let val = 0; while( BITS-- > 0 ){ val = ((val << 1) | 1) >>> 0; } return val; } const DEFAULT_AB = new ArrayBuffer(0); const DEFAULT_BA = new Uint8Array(DEFAULT_AB); class BinaryData { constructor(length=0) { if ( arguments.length === 0 ) { this._ab = DEFAULT_AB; this._ba = DEFAULT_BA; } if ( typeof length !== "number" || length < 0 ) { throw new TypeError( "Given length must be an integer that is equal or greater than 0!" ); } this._ab = new ArrayBuffer(length); this._ba = new Uint8Array(this._ab); } toBytes(size=null) { size = (size===null) ? this._ba.length : size; if ( typeof size !== "number" || size < 0 ) { throw new Error( "Given size argument must be a number greater than zero!" ); } const buffer = new Uint8Array(size); buffer.set(this._ba); return buffer; } toString(bits=16) { switch(bits) { case 2: return DumpBinaryStringBE(this._ab); case 16: return DumpHexStringBE(this._ab); default: throw new RangeError( "BinaryData.toString only supports binary & hex representation!" ); } } compare(inst) { return this.compareBE(inst); } compareLE(inst) { return BitwiseCompareLE(this._ab, inst); } compareBE(inst) { return BitwiseCompareBE(this._ab, inst); } get size() { return this._ab.byteLength; } [Symbol.toPrimitive](hint) { return this.toString(16); } static isBinaryData(input){ if ( input instanceof BinaryData ) { return true; } if ( Object(input) !== input ) { return false; } let check = true; check = check && (input._ab instanceof ArrayBuffer); check = check && (input._ba instanceof Uint8Array); check = check && (typeof input.toBytes === "function"); return check; } } class BinaryInt extends BinaryData { constructor() { super(); this._ta = this._ba; } rshift(bits) { const newVal = this.constructor.from(this); const padding = this.isPositive ? 0x00 : 0xFF; BitwiseRightShiftLE(newVal._ab, bits, padding); return newVal; } lshift(bits) { const newVal = this.constructor.from(this); BitwiseLeftShiftLE(newVal._ab, bits, 0x00); return newVal; } not() { const newVal = this.constructor.from(this); BitwiseNot(newVal._ab); return newVal; } or(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseOr(newVal._ab, val._ab); return newVal; } and(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseAnd(newVal._ab, val._ab); return newVal; } xor(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseXor(newVal._ab, val._ab); return newVal; } add(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseAdditionLE(newVal._ab, val._ab); return newVal; } sub(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseSubtractionLE(newVal._ab, val._ab); return newVal; } multipliedBy(value) { return this.mul(value); } mul(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseMultiplicationLE(newVal._ab, val._ab); return newVal; } dividedBy(value) { return this.div(value); } div(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); BitwiseDivisionLE(newVal._ab, val._ab, !this.isSignedInt); return newVal; } modulo(value) { return this.mod(value); } mod(value) { const newVal = this.constructor.from(this); const val = this.constructor.from(value); const result = BitwiseDivisionLE(newVal._ab, val._ab, !this.isSignedInt); newVal._ba.set(result); return newVal; } compare(value) { const val = this.constructor.from(value); return this.compareLE(val._ab); } isZero() { return BitwiseIsZero(this._ab); } toBytes(size=null) { if ( size === null ) { return this._ba.slice(0); } if ( typeof size !== "number" || size < 0 ) { throw new Error( "Given size argument must be a number greater than zero!" ); } if ( this._ba.length === size ) { return this._ba.slice(0); } if ( this._ba.length > size ) { return this._ba.slice(0, size); } const fill = this.isPositive ? 0 : 0xFF; const buffer = new Uint8Array(size); buffer.fill(fill, this._ba.length, buffer.length).set(this._ba); return buffer; } toString(bits=10) { switch(bits) { case 10: return DumpIntStringLE(this._ab, !this.isSignedInt); case 2: return DumpBinaryStringLE(this._ab); case 16: return DumpHexStringLE(this._ab); default: throw new RangeError( "BinaryData.toString only supports binary & hex representation!" ); } } __set_value(val) { const type = typeof val; if ( type === "number" ) { let do_negate = false; val = Math.floor(val); if ( val < 0 ) { do_negate = true; val = Math.abs(val); } for(let i=0; i<this._ba.length; i++) { this._ba[i] = val % 256; val = Math.floor(val/256); } if ( do_negate ) { BitwiseTwoComplimentLE(this._ab); } return; } if ( type === "string" ) { val = val.trim(); let buffer; const prefix = val.substring(0, 2); if ( prefix === "0x" ) { buffer = BufferFromHexStrLE(val, this.size); } else if ( prefix === "0b" ) { buffer = BufferFromBinStrLE(val, this.size); } else { buffer = BufferFromIntStrLE(val, this.size); } this._ba.set(buffer); return; } if ( Array.isArray(val) ) { for(let i=0; i<val.length; i++) { if ( typeof val[i] !== "number" ) { throw new Error( "Given array should contains only numbers" ); } } this._ba.set(val); return; } const buffer = ReadBuffer(val); if ( buffer ) { this._ba.set(new Uint8Array(buffer)); return; } if ( BinaryData.isBinaryData(val) ) { this._ba.set(val.toBytes(this.size)); return; } throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } set value(val) { this.__set_value(val); } get isSignedInt() { return false; } get isPositive() { if ( !this.isSignedInt ) { return true; } const last_byte = this._ba[this._ba.length-1]; return (last_byte & 0x80) === 0; } [Symbol.toPrimitive](hint) { const str = this.toString(10); if( hint === 'string' ){ return str; } return +str; } static isBinaryInt(input) { if ( input instanceof BinaryInt ) { return true; } if ( !BinaryData.isBinaryData(input) ) { return false; } return typeof input.isSignedInt === 'boolean'; } } const MIN_INT8 = -128; const MAX_INT8 = 127; const MAX_UINT8 = 0xFF; const MIN_INT16 = -32768; const MAX_INT16 = 32767; const MAX_UINT16 = 0xFFFF; const MIN_INT32 = -2147483648; const MAX_INT32 = 2147483647; const MAX_UINT32 = 0xFFFFFFFF; const MAX_FLT32_SAFE_INT = 0x4B7FFFFF; const MIN_FLT32_SAFE_INT = 0xCB7FFFFF; const MAX_FLT32 = new Uint8Array([0xFF, 0xFF, 0x7F, 0x7F]); // 0x7F7FFFFF const MIN_FLT32 = new Uint8Array([0xFF, 0xFF, 0x7F, 0x80]); // 0x807FFFFF const NAN_FLT23 = new Uint8Array([0xFF, 0xFF, 0xFF, 0x7F]); // 0x7FFFFFFF const POS_INF_FLT32 = new Uint8Array([0x00, 0x00, 0x80, 0x7F]); // 0x7F800000 const NEG_INF_FLT32 = new Uint8Array([0x00, 0x00, 0x80, 0xFF]); // 0xFF800000 class BinarySmallNumber extends BinaryInt { [Symbol.toPrimitive](hint) { return (hint === 'string') ? `${this._ta[0]}` : this._ta[0]; } toString(bits=10) { if ( bits === 10 ) { return this._ta[0].toString(); } return super.toString(bits); } } class UInt32 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(4)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Uint32Array(_val.slice(0, 1)); this._ta[0] = buff[0]; } static from(value=0) { return new UInt32(value); } static get ZERO() { return new UInt32(0); } static get MAX() { return new UInt32(MAX_UINT32); } } class Int32 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(4)); this._ta = new Int32Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Int32Array(_val.slice(0, 1)); this._ta[0] = buff[0]; } static from(value=0) { return new Int32(value); } static get ZERO() { return new Int32(0); } static get MAX() { return new Int32(MAX_INT32); } static get MIN() { return new Int32(MIN_INT32); } } class UInt16 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(2)); this._ta = new Uint16Array(this._ab); this.__set_value(value); } get isSignedInt() { return false; } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Uint16Array(_val.slice(0, 1)); this._ta[0] = buff[0]; } static from(value=0) { return new UInt16(value); } static get ZERO() { return new UInt16(0); } static get MAX() { return new UInt16(MAX_UINT16); } } class Int16 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(2)); this._ta = new Int16Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Int16Array(_val.slice(0, 1)); this._ta[0] = buff[0]; } static from(value=0) { return new Int16(value); } static get ZERO() { return new Int16(0); } static get MAX() { return new Int16(MAX_INT16); } static get MIN() { return new Int16(MIN_INT16); } } class UInt8 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(1)); this._ta = this._ba = new Uint8Array(this._ab); this.__set_value(value); } get isSignedInt() { return false; } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Uint8Array(_val.slice(0, 1)); this._ta[0] = buff[0]; } static from(value=0) { return new UInt8(value); } static get ZERO() { return new UInt8(0); } static get MAX() { return new UInt8(MAX_UINT8); } } class Int8 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(1)); this._ta = new Int8Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Int8Array(_val.slice(0, 1)); this._ta[0] = buff[0]; } static from(value=0) { return new Int8(value); } static get ZERO() { return new Int8(0); } static get MAX() { return new Int8(MAX_INT8); } static get MIN() { return new Int8(MIN_INT8); } } class Float32 extends BinarySmallNumber { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(4)); this._ta = new Float32Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } __set_value(val) { if ( typeof val === "number" ) { this._ta[0] = val; return; } let _val = null; if ( BinaryData.isBinaryData(val) ) { _val = val._ab; } else { _val = ReadBuffer(val); } if ( _val === null ) { throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } const buff = new Float32Array(_val.slice(0, 4)); this._ta[0] = buff[0]; } static from(value=0) { return new Float32(value); } static get ZERO() { return new Float32(0); } static get NaN() { return new Float32(NAN_FLT23); } static get MAX_INFINITY() { return new Float32(POS_INF_FLT32); } static get MIN_INFINITY() { return new Float32(NEG_INF_FLT32); } static get MAX_INT() { return new Float32(MAX_FLT32_SAFE_INT); } static get MIN_INT() { return new Float32(MIN_FLT32_SAFE_INT); } static get MAX() { return new Float32(MAX_FLT32); } static get MIN() { return new Float32(MIN_FLT32); } } class BinaryVariableLengthInt extends BinaryInt { constructor(value=0, size=null) { super(); if ( size !== null ) { ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(size)); this._ta = this._ba; this.__set_value(value); return; } if ( Array.isArray(value) ) { for(let i=0; i<value.length; i++) { if ( typeof value[i] !== "number" ) { throw new Error( "Given array should contains only numbers" ); } } ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(value.length)); this._ba.set(value); this._ta = this._ba; return; } let buffer = ReadBuffer(value); if ( buffer !== null ) { ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(buffer.byteLength)); this._ba.set(new Uint8Array(buffer)); this._ta = this._ba; return; } if ( BinaryData.isBinaryData(value)) { this._ta = this._ba = value.toBytes(); this._ab = this._ba.buffer; return; } let type = typeof value; if ( type === "number" ) { type = "string"; value = Math.floor(value).toString(10); } if ( type === "string" ) { value = value.trim(); let buffer; const prefix = value.substring(0, 2); if ( prefix === "0x" ) { buffer = BufferFromHexStrLE(value); } else if ( prefix === "0b" ) { buffer = BufferFromBinStrLE(value); } else { buffer = BufferFromIntStrLE(value); } this._ta = this._ba = buffer; this._ab = buffer.buffer; return; } throw new TypeError( "Given value cannot be casted into ArrayBuffer!" ); } resize(size) { if ( size === this.size ) return; let original = this._ba; ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(size)); this._ba.set(original); this._ta = this._ba; } } class UIntVar extends BinaryVariableLengthInt { static from(value=0) { return new UIntVar(value); } static ZERO(size) { if ( typeof size !== "number" && size <= 0 ) { throw new Error( "Given size must be a number greater than zero!" ); } let input = []; for(let i=0; i<size; i++) { input.push(0); } return new UIntVar(input); } static MAX(size) { if ( typeof size !== "number" && size <= 0 ) { throw new Error( "Given size must be a number greater than zero!" ); } let input = []; for(let i=0; i<size; i++) { input.push(0xFF); } return new UIntVar(input); } } class IntVar extends BinaryVariableLengthInt { get isSignedInt() { return true; } static from(value=0) { return new IntVar(value); } static ZERO(size) { if ( typeof size !== "number" && size <= 0 ) { throw new Error( "Given size must be a number greater than zero!" ); } let input = []; for(let i=0; i<size; i++) { input.push(0); } return new IntVar(input); } static MAX(size) { if ( typeof size !== "number" && size <= 0 ) { throw new Error( "Given size must be a number greater than zero!" ); } let input = []; for(let i=0; i<size-1; i++) { input.push(0xFF); } input[size-1] = 0x7F; return new IntVar(input); } static MIN(size) { if ( typeof size !== "number" && size <= 0 ) { throw new Error( "Given size must be a number greater than zero!" ); } let input = []; for(let i=0; i<size-1; i++) { input.push(0); } input[size-1] = 0x80; return new IntVar(input); } } class UInt64 extends BinaryInt { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(8)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } static from(value=0) { return new UInt64(value); } static get ZERO() { return new UInt64(); } static get MAX() { const val = new UInt64(); val._ta[0] = 0xFFFFFFFF; val._ta[1] = 0xFFFFFFFF; return val; } } class Int64 extends BinaryInt { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(8)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } static from(value=0) { return new Int64(value); } static get ZERO() { return new Int64(); } static get MAX() { const val = new Int64(); val._ta[1] = 0x7FFFFFFF; val._ta[0] = 0xFFFFFFFF; return val; } static get MIN() { const val = new Int64(); val._ta[1] = 0x80000000; val._ta[0] = 0x00000000; return val; } } class UInt128 extends BinaryInt { constructor(value=0) { super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(16)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } static from(value=0) { return new UInt128(value); } static get ZERO() { return new UInt128(); } static get MAX() { return new UInt128([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]); } } class Int128 extends BinaryInt { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(16)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } static from(value=0) { return new Int128(value); } static get ZERO() { return new Int128(); } static get MAX() { return new Int128([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, ]); } static get MIN() { return new Int128([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, ]); } } class UInt256 extends BinaryInt { constructor(value=0) { super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(32)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } static from(value=0) { return new UInt256(value); } static get ZERO() { return new UInt256(); } static get MAX() { return new UInt256([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]); } } class Int256 extends BinaryInt { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(32)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } static from(value=0) { return new Int256(value); } static get ZERO() { return new Int256(); } static get MAX() { return new Int256([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, ]); } static get MIN() { return new Int256([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, ]); } } class UInt512 extends BinaryInt { constructor(value=0) { super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(64)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } static from(value=0) { return new UInt512(value); } static get ZERO() { return new UInt512(); } static get MAX() { return new UInt512([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]); } } class Int512 extends BinaryInt { constructor(value=0){ super(); ___SET_BINARY_BUFFER.call(this, new ArrayBuffer(64)); this._ta = new Uint32Array(this._ab); this.__set_value(value); } get isSignedInt() { return true; } static from(value=0) { return new Int512(value); } static get ZERO() { return new Int512(); } static get MAX() { return new Int512([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, ]); } static get MIN() { return new Int512([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, ]); } } const SEQUENCE_END = (new Uint8Array([0x00]).buffer); function Serialize(data) { const chunks = []; SerializeData(data, (chunk)=>{ chunks.push(chunk); }); return new Uint8Array(MergeArrayBuffers(chunks)); } function SerializeData(data, data_cb) { const type = __serializeType("$", data, data_cb); __serializeTypeData("$", type, data, data_cb); } function __serializeType(path, data, data_cb) { if ( data === undefined ) return; if ( data === null ) { data_cb(Uint8Array.from([TYPE_HEADER.NULL]).buffer); return DATA_TYPE.NULL; } const data_type = typeof data; if ( data_type === 'boolean') { data_cb(Uint8Array.from([data ? TYPE_HEADER.TRUE : TYPE_HEADER.FALSE]).buffer); return data ? DATA_TYPE.TRUE : DATA_TYPE.FALSE; } if ( data_type === "number" ) { data_cb(Uint8Array.from([TYPE_HEADER.FLOAT64]).buffer); return DATA_TYPE.FLOAT64; } if ( data_type === "string" ) { data_cb(Uint8Array.from([ TYPE_HEADER.STRING ]).buffer); return DATA_TYPE.STRING; } if (Array.isArray(data)) { data_cb(Uint8Array.from([ TYPE_HEADER.ARRAY ]).buffer); return DATA_TYPE.ARRAY; } if ( data instanceof Int8 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT8 ]).buffer); return DATA_TYPE.INT8; } if ( data instanceof UInt8 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT8 ]).buffer); return DATA_TYPE.UINT8; } if ( data instanceof Int16 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT16 ]).buffer); return DATA_TYPE.INT16; } if ( data instanceof UInt16 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT16 ]).buffer); return DATA_TYPE.UINT16; } if ( data instanceof Int32 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT32 ]).buffer); return DATA_TYPE.INT32; } if ( data instanceof UInt32 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT32 ]).buffer); return DATA_TYPE.UINT32; } if ( data instanceof Int64 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT64 ]).buffer); return DATA_TYPE.INT64; } if ( data instanceof UInt64 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT64 ]).buffer); return DATA_TYPE.UINT64; } if ( data instanceof Int128 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT128 ]).buffer); return DATA_TYPE.INT128; } if ( data instanceof UInt128 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT128 ]).buffer); return DATA_TYPE.UINT128; } if ( data instanceof Int256 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT256 ]).buffer); return DATA_TYPE.INT256; } if ( data instanceof UInt256 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT256 ]).buffer); return DATA_TYPE.UINT256; } if ( data instanceof Int512 ) { data_cb(Uint8Array.from([ TYPE_HEADER.INT512 ]).buffer); return DATA_TYPE.INT512; } if ( data instanceof UInt512 ) { data_cb(Uint8Array.from([ TYPE_HEADER.UINT512 ]).buffer); return DATA_TYPE.UINT512; } if ( data instanceof Float32 ) { data_cb(Uint8Array.from([ TYPE_HEADER.FLOAT32 ]).buffer); return DATA_TYPE.FLOAT32; } if (data instanceof Date) { data_cb(Uint8Array.from([ TYPE_HEADER.DATE ]).buffer); return DATA_TYPE.DATE; } if (data instanceof RegExp) { data_cb(Uint8Array.from([ TYPE_HEADER.REGEX ]).buffer); return DATA_TYPE.REGEX; } if (data instanceof Map) { data_cb(Uint8Array.from([ TYPE_HEADER.MAP ]).buffer); return DATA_TYPE.MAP; } if (data instanceof Set) { data_cb(Uint8Array.from([ TYPE_HEADER.SET ]).buffer); return DATA_TYPE.SET; } if ( data instanceof ArrayBuffer) { data_cb(Uint8Array.from([ TYPE_HEADER.ARRAY_BUFFER ]).buffer); return DATA_TYPE.ARRAY_BUFFER; } if ( data instanceof DataView) { data_cb(Uint8Array.from([ TYPE_HEADER.DATA_VIEW ]).buffer); return DATA_TYPE.DATA_VIEW; } // NOTE: This line must be prior to Uint8Array since NodeJS Buffer is defined to be inheritance of Uint8Array if ( HAS_NODE_BUFFER && data instanceof Buffer ) { data