description import { Message , Utf8ArrayToStr , MessageHeader } from "./Message" ; import { USING_LITTLE_ENDIAN } from "../base/Defines" ; type BinaryStreamConstructor = typeof BinaryStream ; type NumberStreamValueConstructor = typeof NumberStreamValue ; type StringStreamValueConstructor = typeof StringStreamValue ; export function serialize ( key , type ) ; export function serialize ( key , type , arrayType ) ; export function serialize ( key , type , mapKeyType , mapValueType ) ; export function serialize ( key , type , arrTypeOrMapKeyType ? , mapValueType ? ) { return function ( target , memberName ) { if ( Reflect . getOwnPropertyDescriptor ( target , '__serialize__' ) === undefined ) { let selfSerializeInfo = { } ; if ( Reflect . getPrototypeOf ( target ) [ '__serialize__' ] ) { if ( Reflect . getOwnPropertyDescriptor ( target , '__serialize__' ) === undefined ) { let parentSerializeInfo = Reflect . getPrototypeOf ( target ) [ '__serialize__' ] ; let serializeKeyList = Object . keys ( parentSerializeInfo ) ; for ( let len = serializeKeyList . length , i = 0 ; i < len ; i ++ ) { selfSerializeInfo [ serializeKeyList [ i ] ] = parentSerializeInfo [ serializeKeyList [ i ] ] . slice ( 0 ) ; } } } Reflect . defineProperty ( target , '__serialize__' , { value : selfSerializeInfo , } ) ; } if ( target [ '__serialize__' ] [ key ] ) { throw `SerializeKey has already been declared:${ key }` ; } target [ '__serialize__' ] [ key ] = [ memberName , type , arrTypeOrMapKeyType , mapValueType ] ; } ; } description interface IStreamValue { data : any ; read ( dataView , offset ) : number ; write ( dataView , offset ) : number ; size ( ) : number ; littleEndian : boolean ; } description class StreamValue < T > implements IStreamValue { data : T = null ; read ( dataView , offset ) { return 0 ; } write ( dataView , offset ) { return 0 ; } size ( ) { return 0 ; } description get littleEndian ( ) { return USING_LITTLE_ENDIAN ; } } description class NumberStreamValue extends StreamValue < number > { data = 0 ; } description class StringStreamValue extends StreamValue < string > { data = "" ; } const Buffer = require ( 'buffer' ) . Buffer ; description export class StringValue extends StringStreamValue { size ( ) { let byteSize = Uint32Array . BYTES_PER_ELEMENT ; let buffer = new Buffer ( this . data ) ; byteSize += buffer . length ; return byteSize ; } read ( dataView , offset ) { let readLen = 0 ; let length = dataView . getUint32 ( offset , this . littleEndian ) ; readLen = Uint32Array . BYTES_PER_ELEMENT ; offset = offset + readLen ; let arr = new Uint8Array ( length ) ; for ( let i = 0 ; i < length ; i ++ ) { arr [ i ] = dataView . getUint8 ( offset ) ; offset += Uint8Array . BYTES_PER_ELEMENT ; readLen += Uint8Array . BYTES_PER_ELEMENT ; } this . data = Utf8ArrayToStr ( arr ) ; return readLen ; } write ( dataView , offset ) { let writeLen = 0 ; let buffer = new Buffer ( this . data ) ; let byteLenght = buffer . length ; dataView . setUint32 ( offset , byteLenght , this . littleEndian ) ; writeLen += Uint32Array . BYTES_PER_ELEMENT ; offset += writeLen ; for ( let i = 0 ; i < buffer . length ; i ++ ) { dataView . setUint8 ( offset , buffer [ i ] ) ; offset += Uint8Array . BYTES_PER_ELEMENT ; writeLen += Uint8Array . BYTES_PER_ELEMENT ; } return writeLen ; } } description export class StringArrayValue extends StringValue { dataLength = 0 ; } export class Float32Value extends NumberStreamValue { size ( ) { return Float32Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getFloat32 ( offset , this . littleEndian ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setFloat32 ( offset , this . data , this . littleEndian ) ; return this . size ( ) ; } } export class Float64Value extends NumberStreamValue { size ( ) { return Float64Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getFloat64 ( offset , this . littleEndian ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setFloat64 ( offset , this . data , this . littleEndian ) ; return this . size ( ) ; } } export class Int8Value extends NumberStreamValue { size ( ) { return Int8Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getInt8 ( offset ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setInt8 ( offset , this . data ) ; return this . size ( ) ; } } export class Int16Value extends NumberStreamValue { size ( ) { return Int16Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getInt16 ( offset , this . littleEndian ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setInt16 ( offset , this . data , this . littleEndian ) ; return this . size ( ) ; } } export class Int32Value extends NumberStreamValue { size ( ) { return Int32Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getInt32 ( offset , this . littleEndian ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setInt32 ( offset , this . data , this . littleEndian ) ; return this . size ( ) ; } } export class Uint8Value extends NumberStreamValue { size ( ) { return Uint8Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getUint8 ( offset ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setUint8 ( offset , this . data ) ; return this . size ( ) ; } } export class Uint16Value extends NumberStreamValue { size ( ) { return Uint16Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getUint16 ( offset , this . littleEndian ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setUint16 ( offset , this . data , this . littleEndian ) ; return this . size ( ) ; } } export class Uint32Value extends NumberStreamValue { size ( ) { return Uint32Array . BYTES_PER_ELEMENT ; } read ( dataView , offset ) { this . data = dataView . getUint32 ( offset , this . littleEndian ) ; return this . size ( ) ; } write ( dataView , offset ) { dataView . setUint32 ( offset , this . data , this . littleEndian ) ; return this . size ( ) ; } } export class BinaryStream extends Message { protected _dataView : DataView = null ; description protected _byteOffset = 0 ; description encode ( ) { let size = this . size ( ) ; let buffer = new ArrayBuffer ( size ) ; this . _dataView = new DataView ( buffer ) ; this . _byteOffset = 0 ; this . serialize ( ) ; this . buffer = new Uint8Array ( this . _dataView . buffer ) ; let success = this . _byteOffset == this . _dataView . byteLength ; if ( ! success ) { cc . error ( `encode 当前读取大小为 : ${ this . _byteOffset } 数据大小为 : ${ this . _dataView . byteLength }` ) ; } return success ; } description private isNumberValue ( valueType ) { return valueType == Float32Value || valueType == Float64Value || valueType == Int8Value || valueType == Int16Value || valueType == Int32Value || valueType == Uint8Value || valueType == Uint16Value || valueType == Uint32Value ; } description private isStringValue ( valueType ) { return valueType == StringValue || valueType == StringArrayValue ; } description protected size ( ) { let byteSize = 0 ; let __serialize__ = Reflect . getPrototypeOf ( this ) [ '__serialize__' ] ; if ( ! __serialize__ ) return null ; let serializeKeyList = Object . keys ( __serialize__ ) ; for ( let len = serializeKeyList . length , i = 0 ; i < len ; i ++ ) { let serializeKey = serializeKeyList [ i ] ; let [ memberName , type , arrTypeOrMapKeyType , mapValueType ] = __serialize__ [ serializeKey ] ; let memberSize = this . memberSize ( this [ memberName ] , type , arrTypeOrMapKeyType , mapValueType ) ; if ( null === memberSize ) { cc . warn ( "Invalid serialize member size : " + memberName ) ; } byteSize += memberSize ; } return byteSize ; } description protected memberSize ( value , valueType , arrTypeOrMapKeyType , mapValueType ) { if ( this . isNumberValue ( valueType ) ) { return this . memberNumberSize ( value , valueType ) ; } else if ( this . isStringValue ( valueType ) ) { return this . memberStringSize ( value , valueType ) ; } else if ( value instanceof Array ) { return this . memberArraySize ( value , valueType , arrTypeOrMapKeyType , mapValueType ) ; } else if ( value instanceof Map ) { return this . memberMapSize ( value , valueType , arrTypeOrMapKeyType , mapValueType ) ; } else if ( value instanceof BinaryStream ) { return value . size ( ) ; } else if ( valueType == Number ) { return this . memberNumberSize ( value , Uint32Value ) ; } else if ( valueType == String ) { return this . memberStringSize ( value , StringValue ) ; } else { cc . warn ( "Invalid serialize value : " + value ) ; return 0 ; } } protected memberNumberSize ( value , valueType ) { let type = new valueType ( ) ; return type . size ( ) ; } protected memberStringSize ( value , valueType ) { let type = new valueType ( ) ; type . data = value ; return type . size ( ) ; } private memberArraySize ( value , valueType , arrTypeOrMapKeyType , mapValueType ) { let typeSize = Uint32Array . BYTES_PER_ELEMENT ; for ( let i = 0 ; i < value . length ; i ++ ) { typeSize += this . memberSize ( value [ i ] , arrTypeOrMapKeyType , null , null ) ; } return typeSize ; } private memberMapSize ( value , valueType , arrTypeOrMapKeyType , mapValueType ) { let typeSize = Uint32Array . BYTES_PER_ELEMENT ; value . forEach ( ( dataValue , key ) => { typeSize += this . memberSize ( key , arrTypeOrMapKeyType , null , null ) ; typeSize += this . memberSize ( dataValue , mapValueType , null , null ) ; } ) ; return typeSize ; } description private serialize ( ) { let __serialize__ = Reflect . getPrototypeOf ( this ) [ '__serialize__' ] ; if ( ! __serialize__ ) return null ; let serializeKeyList = Object . keys ( __serialize__ ) ; for ( let len = serializeKeyList . length , i = 0 ; i < len ; i ++ ) { let serializeKey = serializeKeyList [ i ] ; let [ memberName , type , arrTypeOrMapKeyType , mapValueType ] = __serialize__ [ serializeKey ] ; this . serializeMember ( this [ memberName ] , memberName , type , arrTypeOrMapKeyType , mapValueType ) ; } } description param value private serializeMember ( value , memberName , valueType , arrTypeOrMapKeyType , mapValueType ) { if ( this . isNumberValue ( valueType ) ) { this . serializeNumberStreamValue ( value , valueType ) ; } else if ( this . isStringValue ( valueType ) ) { this . serializeStringStreamValue ( value , valueType , arrTypeOrMapKeyType ) ; } else if ( value instanceof Array ) { this . serializeArray ( value , memberName , valueType , arrTypeOrMapKeyType , mapValueType ) ; } else if ( value instanceof Map ) { this . serializeMap ( value , memberName , valueType , arrTypeOrMapKeyType , mapValueType ) ; } else if ( value instanceof BinaryStream ) { value . _dataView = this . _dataView ; value . _byteOffset = this . _byteOffset ; value . serialize ( ) ; this . _byteOffset = value . _byteOffset ; } else { cc . error ( `序列化成员 : ${ memberName } 出错!!` ) ; } } private serializeNumberStreamValue ( value , valueType ) { let type = new valueType ( ) ; type . data = ( value === undefined || value === null || value == Number . NaN ) ? 0 : value ; this . _byteOffset += type . write ( this . _dataView , this . _byteOffset ) ; } private serializeStringStreamValue ( value , valueType , size ) { let type = new valueType ( ) ; type . data = ( value === undefined || value === null ) ? "" : value ; this . _byteOffset += type . write ( this . _dataView , this . _byteOffset ) ; } private serializeArray ( value , memberName , valueType , arrTypeOrMapKeyType , mapValueType ) { this . _dataView . setUint32 ( this . _byteOffset , value . length , USING_LITTLE_ENDIAN ) ; this . _byteOffset += Uint32Array . BYTES_PER_ELEMENT ; for ( let i = 0 ; i < value . length ; i ++ ) { this . serializeMember ( value [ i ] , `${ memberName }[${ i }]` , arrTypeOrMapKeyType , null , null ) ; } } private serializeMap ( value , memberName , valueType , arrTypeOrMapKeyType , mapValueType ) { this . _dataView . setUint32 ( this . _byteOffset , value . size , USING_LITTLE_ENDIAN ) ; this . _byteOffset += Uint32Array . BYTES_PER_ELEMENT ; value . forEach ( ( dataValue , dataKey ) => { if ( arrTypeOrMapKeyType == String ) { let keyValue = new StringValue ( ) ; keyValue . data = dataKey ; this . _byteOffset += keyValue . write ( this . _dataView , this . _byteOffset ) ; } else { this . _dataView . setUint32 ( this . _byteOffset , dataKey , USING_LITTLE_ENDIAN ) ; this . _byteOffset += Uint32Array . BYTES_PER_ELEMENT ; } this . serializeMember ( dataValue , `${ memberName }.${ dataKey }` , mapValueType , null , null ) ; } ) ; } description decode ( data ) { this . buffer = data ; this . _dataView = new DataView ( data . buffer ) ; this . _byteOffset = 0 ; this . deserialize ( ) ; let success = this . _dataView . byteLength == this . _byteOffset ; if ( ! success ) { cc . error ( `decode 当前读取大小为 : ${ this . _byteOffset } 数据大小为 : ${ this . _dataView . byteLength }` ) ; } return success ; } description param data protected deserialize ( ) { let __serializeInfo = Reflect . getPrototypeOf ( this ) [ '__serialize__' ] ; if ( ! __serializeInfo ) return true ; let serializeKeyList = Object . keys ( __serializeInfo ) ; for ( let len = serializeKeyList . length , i = 0 ; i < len ; i ++ ) { let serializeKey = serializeKeyList [ i ] ; let [ memberName , type , arrTypeOrMapKeyType , mapValueType ] = __serializeInfo [ serializeKey ] ; this . deserializeMember ( memberName , type , arrTypeOrMapKeyType , mapValueType ) ; } } description param memberName param memberType param arrTypeOrMapKeyType param mapValueType param value private deserializeMember ( memberName , memberType , arrTypeOrMapKeyType , mapValueType ) { try { let originValue = this [ memberName ] ; if ( this . isNumberValue ( memberType ) ) { this [ memberName ] = this . deserializeNumberStreamValue ( memberName , memberType ) ; } else if ( this . isStringValue ( memberType ) ) { this [ memberName ] = this . deserializeStringStreamValue ( memberName , memberType , arrTypeOrMapKeyType ) ; } else if ( originValue instanceof Array ) { this . deserializeArray ( memberName , memberType , arrTypeOrMapKeyType , mapValueType ) ; } else if ( originValue instanceof Map ) { this . deserializeMap ( memberName , memberType , arrTypeOrMapKeyType , mapValueType ) ; } else if ( originValue instanceof BinaryStream ) { originValue . _dataView = this . _dataView ; originValue . _byteOffset = this . _byteOffset ; originValue . deserialize ( ) ; this . _byteOffset = originValue . _byteOffset ; } else { cc . error ( `deserializeMember ${ memberName } error!!!` ) ; } } catch ( error ) { cc . warn ( error . message ) ; cc . error ( `deserializeMember ${ memberName } error!!!` ) ; } } private deserializeNumberStreamValue ( memberName , memberType ) { let value = new memberType ( ) ; this . _byteOffset += value . read ( this . _dataView , this . _byteOffset ) ; return value . data ; } private deserializeStringStreamValue ( memberName , memberType , arrTypeOrMapKeyType ) { let value = new memberType ( ) ; this . _byteOffset += value . read ( this . _dataView , this . _byteOffset ) ; return value . data ; } private deserializeArray ( memberName , memberType , arrTypeOrMapKeyType , mapValueType ) { this [ memberName ] = [ ] ; let size = this . _dataView . getUint32 ( this . _byteOffset , USING_LITTLE_ENDIAN ) ; this . _byteOffset += Uint32Array . BYTES_PER_ELEMENT ; for ( let i = 0 ; i < size ; i ++ ) { let type = new arrTypeOrMapKeyType ( ) ; if ( type instanceof BinaryStream ) { this [ memberName ] [ i ] = type . deserialize ( ) ; } else { this . _byteOffset += type . read ( this . _dataView , this . _byteOffset ) ; this [ memberName ] [ i ] = type . data ; } } } private deserializeMap ( memberName , memberType , arrTypeOrMapKeyType , mapValueType ) { this [ memberName ] = new Map ; let size = this . _dataView . getUint32 ( this . _byteOffset , USING_LITTLE_ENDIAN ) ; this . _byteOffset += Uint32Array . BYTES_PER_ELEMENT ; for ( let i = 0 ; i < size ; i ++ ) { let key = null ; if ( arrTypeOrMapKeyType == String ) { let keyValue = new StringValue ( ) ; this . _byteOffset += keyValue . read ( this . _dataView , this . _byteOffset ) ; key = keyValue . data ; } else { key = this . _dataView . getUint32 ( this . _byteOffset , USING_LITTLE_ENDIAN ) ; this . _byteOffset += Uint32Array . BYTES_PER_ELEMENT ; } let data = new mapValueType ( ) ; if ( mapValueType instanceof BinaryStream ) { data . deserialize ( ) ; } else { this . _byteOffset += data . read ( this . _dataView , this . _byteOffset ) ; data = data . data ; } this [ memberName ] . set ( key , data ) ; } } } export class BinaryStreamMessage extends BinaryStream { } export class BinaryStreamMessageHeader extends MessageHeader { }