version platform language version platform language export class Endian { version platform language version platform language public static LITTLE_ENDIAN : string = "littleEndian" ; version platform language version platform language public static BIG_ENDIAN : string = "bigEndian" ; } export const enum EndianConst { LITTLE_ENDIAN = 0 , BIG_ENDIAN = 1 } const enum ByteArraySize { SIZE_OF_BOOLEAN = 1 , SIZE_OF_INT8 = 1 , SIZE_OF_INT16 = 2 , SIZE_OF_INT32 = 4 , SIZE_OF_UINT8 = 1 , SIZE_OF_UINT16 = 2 , SIZE_OF_UINT32 = 4 , SIZE_OF_FLOAT32 = 4 , SIZE_OF_FLOAT64 = 8 } version platform includeExample language version platform includeExample language export class ByteArray { private protected bufferExtSize = 0 ; protected data : DataView ; protected _bytes : Uint8Array ; private protected _position : number ; protected type { number } memberOf protected write_position : number ; default version platform language default version platform language public get endian ( ) { return this . $endian === EndianConst . LITTLE_ENDIAN ? Endian . LITTLE_ENDIAN : Endian . BIG_ENDIAN ; } public set endian ( value ) { this . $endian = value === Endian . LITTLE_ENDIAN ? EndianConst . LITTLE_ENDIAN : EndianConst . BIG_ENDIAN ; } protected $endian : EndianConst ; version platform constructor ( buffer ? , bufferExtSize = 0 ) { if ( bufferExtSize < 0 ) { bufferExtSize = 0 ; } this . bufferExtSize = bufferExtSize ; let bytes , wpos = 0 ; if ( buffer ) { let uint8 ; if ( buffer instanceof Uint8Array ) { uint8 = buffer ; wpos = buffer . length ; } else { wpos = buffer . byteLength ; uint8 = new Uint8Array ( buffer ) ; } if ( bufferExtSize === 0 ) { bytes = new Uint8Array ( wpos ) ; } else { let multi = ( ( wpos / bufferExtSize ) | 0 ) + 1 ; bytes = new Uint8Array ( multi * bufferExtSize ) ; } bytes . set ( uint8 ) ; } else { bytes = new Uint8Array ( bufferExtSize ) ; } this . write_position = wpos ; this . _position = 0 ; this . _bytes = bytes ; this . data = new DataView ( bytes . buffer ) ; this . endian = Endian . BIG_ENDIAN ; } deprecated version platform public setArrayBuffer ( buffer ) { } returns memberOf public get readAvailable ( ) { return this . write_position - this . _position ; } public get buffer ( ) : ArrayBuffer { return this . data . buffer . slice ( 0 , this . write_position ) ; } public get rawBuffer ( ) : ArrayBuffer { return this . data . buffer ; } private public set buffer ( value ) { let wpos = value . byteLength ; let uint8 = new Uint8Array ( value ) ; let bufferExtSize = this . bufferExtSize ; let bytes ; if ( bufferExtSize === 0 ) { bytes = new Uint8Array ( wpos ) ; } else { let multi = ( ( wpos / bufferExtSize ) | 0 ) + 1 ; bytes = new Uint8Array ( multi * bufferExtSize ) ; } bytes . set ( uint8 ) ; this . write_position = wpos ; this . _bytes = bytes ; this . data = new DataView ( bytes . buffer ) ; } public get bytes ( ) : Uint8Array { return this . _bytes ; } private version platform public get dataView ( ) : DataView { return this . data ; } private public set dataView ( value ) { this . buffer = value . buffer ; } private public get bufferOffset ( ) : number { return this . data . byteOffset ; } version platform language version platform language public get position ( ) : number { return this . _position ; } public set position ( value ) { this . _position = value ; if ( value > this . write_position ) { this . write_position = value ; } } version platform language version platform language public get length ( ) : number { return this . write_position ; } public set length ( value ) { this . write_position = value ; if ( this . data . byteLength > value ) { this . _position = value ; } this . _validateBuffer ( value ) ; } protected _validateBuffer ( value ) { if ( this . data . byteLength < value ) { let be = this . bufferExtSize ; let tmp ; if ( be === 0 ) { tmp = new Uint8Array ( value ) ; } else { let nLen = ( ( ( value / be ) >> 0 ) + 1 ) * be ; tmp = new Uint8Array ( nLen ) ; } tmp . set ( this . _bytes ) ; this . _bytes = tmp ; this . data = new DataView ( tmp . buffer ) ; } } version platform language version platform language public get bytesAvailable ( ) : number { return this . data . byteLength - this . _position ; } version platform language version platform language public clear ( ) { let buffer = new ArrayBuffer ( this . bufferExtSize ) ; this . data = new DataView ( buffer ) ; this . _bytes = new Uint8Array ( buffer ) ; this . _position = 0 ; this . write_position = 0 ; } return version platform language return version platform language public readBoolean ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_BOOLEAN ) ) return ! ! this . _bytes [ this . position ++ ] ; } return version platform language return version platform language public readByte ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_INT8 ) ) return this . data . getInt8 ( this . position ++ ) ; } param bytes param offset param length version platform language param bytes param offset param length version platform language public readBytes ( bytes , offset = 0 , length = 0 ) { if ( ! bytes ) { return ; } let pos = this . _position ; let available = this . write_position - pos ; if ( available < 0 ) { throw new Error ( "1025" ) ; } if ( length === 0 ) { length = available ; } else if ( length > available ) { throw new Error ( "1025" ) ; } bytes . validateBuffer ( offset + length ) ; bytes . _bytes . set ( this . _bytes . subarray ( pos , pos + length ) , offset ) ; this . position += length ; } return version platform language return version platform language public readDouble ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_FLOAT64 ) ) { let value = this . data . getFloat64 ( this . _position , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_FLOAT64 ; return value ; } } return version platform language return version platform language public readFloat ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_FLOAT32 ) ) { let value = this . data . getFloat32 ( this . _position , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_FLOAT32 ; return value ; } } return version platform language return version platform language public readInt ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_INT32 ) ) { let value = this . data . getInt32 ( this . _position , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_INT32 ; return value ; } } return version platform language return version platform language public readShort ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_INT16 ) ) { let value = this . data . getInt16 ( this . _position , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_INT16 ; return value ; } } return version platform language return version platform language public readUnsignedByte ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_UINT8 ) ) return this . _bytes [ this . position ++ ] ; } return version platform language return version platform language public readUnsignedInt ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_UINT32 ) ) { let value = this . data . getUint32 ( this . _position , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_UINT32 ; return value ; } } return version platform language return version platform language public readUnsignedShort ( ) { if ( this . validate ( ByteArraySize . SIZE_OF_UINT16 ) ) { let value = this . data . getUint16 ( this . _position , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_UINT16 ; return value ; } } return version platform language return version platform language public readUTF ( ) { let length = this . readUnsignedShort ( ) ; if ( length > 0 ) { return this . readUTFBytes ( length ) ; } else { return "" ; } } param Specify return version platform language param length return version platform language public readUTFBytes ( length ) { if ( ! this . validate ( length ) ) { return ; } let data = this . data ; let bytes = new Uint8Array ( data . buffer , data . byteOffset + this . _position , length ) ; this . position += length ; return this . decodeUTF8 ( bytes ) ; } param value version platform language param value version platform language public writeBoolean ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_BOOLEAN ) ; this . _bytes [ this . position ++ ] = + value ; } param value version platform language param value version platform language public writeByte ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_INT8 ) ; this . _bytes [ this . position ++ ] = value & 0xff ; } param bytes param offset param length version platform language param bytes param offset param length version platform language public writeBytes ( bytes , offset = 0 , length = 0 ) { let writeLength ; if ( offset < 0 ) { return ; } if ( length < 0 ) { return ; } else if ( length === 0 ) { writeLength = bytes . length - offset ; } else { writeLength = Math . min ( bytes . length - offset , length ) ; } if ( writeLength > 0 ) { this . validateBuffer ( writeLength ) ; this . _bytes . set ( bytes . _bytes . subarray ( offset , offset + writeLength ) , this . _position ) ; this . position = this . _position + writeLength ; } } param value version platform language param value version platform language public writeDouble ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_FLOAT64 ) ; this . data . setFloat64 ( this . _position , value , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_FLOAT64 ; } param value version platform language param value version platform language public writeFloat ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_FLOAT32 ) ; this . data . setFloat32 ( this . _position , value , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_FLOAT32 ; } param value version platform language param value version platform language public writeInt ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_INT32 ) ; this . data . setInt32 ( this . _position , value , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_INT32 ; } param value version platform language param value version platform language public writeShort ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_INT16 ) ; this . data . setInt16 ( this . _position , value , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_INT16 ; } param value version platform language param value version platform language public writeUnsignedInt ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_UINT32 ) ; this . data . setUint32 ( this . _position , value , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_UINT32 ; } param value version platform language param value version platform language public writeUnsignedShort ( value ) { this . validateBuffer ( ByteArraySize . SIZE_OF_UINT16 ) ; this . data . setUint16 ( this . _position , value , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_UINT16 ; } param value version platform language param value version platform language public writeUTF ( value ) { let utf8bytes = this . encodeUTF8 ( value ) ; let length = utf8bytes . length ; this . validateBuffer ( ByteArraySize . SIZE_OF_UINT16 + length ) ; this . data . setUint16 ( this . _position , length , this . $endian === EndianConst . LITTLE_ENDIAN ) ; this . position += ByteArraySize . SIZE_OF_UINT16 ; this . _writeUint8Array ( utf8bytes , false ) ; } param value version platform language param value version platform language public writeUTFBytes ( value ) { this . _writeUint8Array ( this . encodeUTF8 ( value ) ) ; } returns version platform public toString ( ) { return "[ByteArray] length:" + this . length + ", bytesAvailable:" + this . bytesAvailable ; } private param bytes param validateBuffer public _writeUint8Array ( bytes , validateBuffer = true ) { let pos = this . _position ; let npos = pos + bytes . length ; if ( validateBuffer ) { this . validateBuffer ( npos ) ; } this . bytes . set ( bytes , pos ) ; this . position = npos ; } param len returns version platform private public validate ( len ) { let bl = this . _bytes . length ; if ( bl > 0 && this . _position + len <= bl ) { return true ; } else { console . error ( 1025 ) ; } } /**********************/ /**********************/ private param len param needReplace protected validateBuffer ( len ) { this . write_position = len > this . write_position ? len : this . write_position ; len += this . _position ; this . _validateBuffer ( len ) ; } private private encodeUTF8 ( str ) { let pos = 0 ; let codePoints = this . stringToCodePoints ( str ) ; let outputBytes = [ ] ; while ( codePoints . length > pos ) { let code_point = codePoints [ pos ++ ] ; if ( this . inRange ( code_point , 0xd800 , 0xdfff ) ) { this . encoderError ( code_point ) ; } else if ( this . inRange ( code_point , 0x0000 , 0x007f ) ) { outputBytes . push ( code_point ) ; } else { let count , offset ; if ( this . inRange ( code_point , 0x0080 , 0x07ff ) ) { count = 1 ; offset = 0xc0 ; } else if ( this . inRange ( code_point , 0x0800 , 0xffff ) ) { count = 2 ; offset = 0xe0 ; } else if ( this . inRange ( code_point , 0x10000 , 0x10ffff ) ) { count = 3 ; offset = 0xf0 ; } outputBytes . push ( this . div ( code_point , Math . pow ( 64 , count ) ) + offset ) ; while ( count > 0 ) { let temp = this . div ( code_point , Math . pow ( 64 , count - 1 ) ) ; outputBytes . push ( 0x80 + ( temp % 64 ) ) ; count -= 1 ; } } } return new Uint8Array ( outputBytes ) ; } private param data returns private decodeUTF8 ( data ) { let fatal = false ; let pos = 0 ; let result = "" ; let code_point ; let utf8_code_point = 0 ; let utf8_bytes_needed = 0 ; let utf8_bytes_seen = 0 ; let utf8_lower_boundary = 0 ; while ( data . length > pos ) { let _byte = data [ pos ++ ] ; if ( _byte === this . EOF_byte ) { if ( utf8_bytes_needed !== 0 ) { code_point = this . decoderError ( fatal ) ; } else { code_point = this . EOF_code_point ; } } else { if ( utf8_bytes_needed === 0 ) { if ( this . inRange ( _byte , 0x00 , 0x7f ) ) { code_point = _byte ; } else { if ( this . inRange ( _byte , 0xc2 , 0xdf ) ) { utf8_bytes_needed = 1 ; utf8_lower_boundary = 0x80 ; utf8_code_point = _byte - 0xc0 ; } else if ( this . inRange ( _byte , 0xe0 , 0xef ) ) { utf8_bytes_needed = 2 ; utf8_lower_boundary = 0x800 ; utf8_code_point = _byte - 0xe0 ; } else if ( this . inRange ( _byte , 0xf0 , 0xf4 ) ) { utf8_bytes_needed = 3 ; utf8_lower_boundary = 0x10000 ; utf8_code_point = _byte - 0xf0 ; } else { this . decoderError ( fatal ) ; } utf8_code_point = utf8_code_point * Math . pow ( 64 , utf8_bytes_needed ) ; code_point = null ; } } else if ( ! this . inRange ( _byte , 0x80 , 0xbf ) ) { utf8_code_point = 0 ; utf8_bytes_needed = 0 ; utf8_bytes_seen = 0 ; utf8_lower_boundary = 0 ; pos -- ; code_point = this . decoderError ( fatal , _byte ) ; } else { utf8_bytes_seen += 1 ; utf8_code_point = utf8_code_point + ( _byte - 0x80 ) * Math . pow ( 64 , utf8_bytes_needed - utf8_bytes_seen ) ; if ( utf8_bytes_seen !== utf8_bytes_needed ) { code_point = null ; } else { let cp = utf8_code_point ; let lower_boundary = utf8_lower_boundary ; utf8_code_point = 0 ; utf8_bytes_needed = 0 ; utf8_bytes_seen = 0 ; utf8_lower_boundary = 0 ; if ( this . inRange ( cp , lower_boundary , 0x10ffff ) && ! this . inRange ( cp , 0xd800 , 0xdfff ) ) { code_point = cp ; } else { code_point = this . decoderError ( fatal , _byte ) ; } } } } if ( code_point !== null && code_point !== this . EOF_code_point ) { if ( code_point <= 0xffff ) { if ( code_point > 0 ) result += String . fromCharCode ( code_point ) ; } else { code_point -= 0x10000 ; result += String . fromCharCode ( 0xd800 + ( ( code_point >> 10 ) & 0x3ff ) ) ; result += String . fromCharCode ( 0xdc00 + ( code_point & 0x3ff ) ) ; } } } return result ; } private param code_point private encoderError ( code_point ) { console . error ( 1026 , code_point ) ; } private param fatal param opt_code_point returns private decoderError ( fatal , opt_code_point ? ) { if ( fatal ) { console . error ( 1027 ) ; } return opt_code_point || 0xfffd ; } private private EOF_byte : number = - 1 ; private private EOF_code_point : number = - 1 ; private param a param min param max private inRange ( a , min , max ) { return min <= a && a <= max ; } private param n param d private div ( n , d ) { return Math . floor ( n / d ) ; } private param string private stringToCodePoints ( str ) { type { Array . < number > } let cps = [ ] ; let i = 0 , n = str . length ; while ( i < str . length ) { let c = str . charCodeAt ( i ) ; if ( ! this . inRange ( c , 0xd800 , 0xdfff ) ) { cps . push ( c ) ; } else if ( this . inRange ( c , 0xdc00 , 0xdfff ) ) { cps . push ( 0xfffd ) ; } else { if ( i === n - 1 ) { cps . push ( 0xfffd ) ; } else { let d = str . charCodeAt ( i + 1 ) ; if ( this . inRange ( d , 0xdc00 , 0xdfff ) ) { let a = c & 0x3ff ; let b = d & 0x3ff ; i += 1 ; cps . push ( 0x10000 + ( a << 10 ) + b ) ; } else { cps . push ( 0xfffd ) ; } } } i += 1 ; } return cps ; } }