import { ByteArray } from "./ByteArray" ; import { Protobuf } from "./protobuf" ; import { Protocol } from "./protocol" ; import { Routedic } from "./route-dic" ; interface IMessage { param id param route param msg return encode ( id , route , msg ) : ByteArray ; param buffer return decode ( buffer ) : any ; } declare global { interface IPinusDecodeMessage { id : number ; /**
         * Message.TYPE_xxx
         */ type : number ; route : string ; body : any ; } } export class Message implements IMessage { public static MSG_FLAG_BYTES : number = 1 ; public static MSG_ROUTE_CODE_BYTES : number = 2 ; public static MSG_ID_MAX_BYTES : number = 5 ; public static MSG_ROUTE_LEN_BYTES : number = 1 ; public static MSG_ROUTE_CODE_MAX : number = 0xffff ; public static MSG_COMPRESS_ROUTE_MASK : number = 0x1 ; public static MSG_TYPE_MASK : number = 0x7 ; static TYPE_REQUEST : number = 0 ; static TYPE_NOTIFY : number = 1 ; static TYPE_RESPONSE : number = 2 ; static TYPE_PUSH : number = 3 ; constructor ( private routeMap ) { } public encode ( id , route , msg ) { let buffer = new ByteArray ( ) ; let type = id ? Message . TYPE_REQUEST : Message . TYPE_NOTIFY ; let byte = Protobuf . encode ( route , msg ) || Protocol . strencode ( JSON . stringify ( msg ) ) ; let rot = Routedic . getID ( route ) || route ; buffer . writeByte ( ( type << 1 ) | ( typeof rot === "string" ? 0 : 1 ) ) ; if ( id ) { do { let tmp = id % 128 ; let next = Math . floor ( id / 128 ) ; if ( next !== 0 ) { tmp = tmp + 128 ; } buffer . writeByte ( tmp ) ; id = next ; } while ( id !== 0 ) ; } if ( rot ) { if ( typeof rot === "string" ) { buffer . writeByte ( rot . length & 0xff ) ; buffer . writeUTFBytes ( rot ) ; } else { buffer . writeByte ( ( rot >> 8 ) & 0xff ) ; buffer . writeByte ( rot & 0xff ) ; } } if ( byte ) { buffer . writeBytes ( byte ) ; } return buffer ; } public decode ( buffer ) { let flag = buffer . readUnsignedByte ( ) ; let compressRoute = flag & Message . MSG_COMPRESS_ROUTE_MASK ; let type = ( flag >> 1 ) & Message . MSG_TYPE_MASK ; let route ; let id = 0 ; if ( type === Message . TYPE_REQUEST || type === Message . TYPE_RESPONSE ) { let i = 0 ; let m ; do { m = buffer . readUnsignedByte ( ) ; id = id + ( m & 0x7f ) * Math . pow ( 2 , 7 * i ) ; i ++ ; } while ( m >= 128 ) ; } if ( type === Message . TYPE_REQUEST || type === Message . TYPE_NOTIFY || type === Message . TYPE_PUSH ) { if ( compressRoute ) { route = buffer . readUnsignedShort ( ) ; } else { let routeLen = buffer . readUnsignedByte ( ) ; route = routeLen ? buffer . readUTFBytes ( routeLen ) : "" ; } } else if ( type === Message . TYPE_RESPONSE ) { route = this . routeMap [ id ] ; } if ( ! id && ! ( typeof route === "string" ) ) { route = Routedic . getName ( route ) ; } let body = Protobuf . decode ( route , buffer ) || JSON . parse ( Protocol . strdecode ( buffer ) ) ; return { id : id , type : type , route : route , body : body } ; } }