//message 消息对象 import protobuf.reader.inputString; import protobuf.type.scalar; import protobuf.type.enum; import protobuf.type.bytes; import protobuf.type.string; import protobuf.type.int32; import protobuf.type.int64; import protobuf.type.sint32; import protobuf.type.sint64; import protobuf.type.sfixed32; import protobuf.type.sfixed64; import protobuf.type.fixed32; import protobuf.type.fixed64; import protobuf.type.uint32; import protobuf.type.uint64; import protobuf.type.float; import protobuf.type.double; import protobuf.type.bool; import protobuf.type.map; import inet.http; import inet.url; namespace protobuf; class message { ctor( reader ) { this.chunk = ''; this.wiredType = wiredTypeLengthDelimited; this.reader = reader; this.value = this; this.fieldValues = {}; this.fieldNames = {}; this.fieldTypes = {}; this.fieldMapKeyValueType = {}; this.fieldIsArray = {}; this.fieldIsPacked = {}; this.fieldOneOf = {}; }; _getFieldClass = function( index ){ var cls = eval( this.fieldTypes[ index ] ) if(!cls) error( '\nWrong protobuf message class:' + this.fieldTypes[ index ] ,2) return cls; }; _createFieldObject = function( index,value ){ var msg = this._getFieldClass( index )( this.reader ); msg.keyValueType = this.fieldMapKeyValueType[index]; if(value !== null) msg.value = value; return msg; }; setFieldValue = function (index, value) { if (value[["_isProtobufMessage"]]) { this.fieldValues[index] = value; } else { this.fieldValues[index] = this._createFieldObject(index,value); } return this.fieldValues[index];//return object; }; getFieldValue = function (index) { var value = this.fieldValues[index]; if( value[["_isProtobufValueType"]] ) return value[["value"]] return value }; setFieldTime = function(index, value,format){ value.format = format; return owner.setFieldValue( index,tostring(value) ); }; getFieldTime = function(index,format){ var str = owner.getFieldValue(index) return ..time(str,format); }; getFieldArray = function (index) { return this.fieldValues[index] ; }; setFieldArray = function (index,items) { this.fieldValues[index] = items; }; getFieldArrayItem = function (index, key) { var value = this.fieldValues[index][key]; if( value[["_isProtobufValueType"]] ) return value[["value"]] return value; }; setFieldArrayItem = function ( index, index_arr, value) { if (value[["_isProtobufMessage"]]) { this.fieldValues[index][index_arr] = value; } else { this.fieldValues[index][index_arr] = this._createFieldObject(index,value); } return this.fieldValues[index][index_arr] ;//return object; }; getFieldArraySize = function (index) { return #(this.fieldValues[index]); }; encodeVarUint64 = function(n) { n = ..math.size64(n); var s = {} var l,h = n.split32(); while ( (l & ~0x7F) || h) { s[#s+1] = (l & 0xFF) | 0x80; n = n.rshift(7); l,h = n.split32(); } s[#s+1] = l; return ..string.pack(s) }; getFieldTag = lambda(number) { wiredType = number & 2#111; fieldNum = number >> 3; }; serialize = function( rec = - 1) { var str = ''; if (rec > -1){ str ++= this.encodeVarUint64(rec << 3 | this.wiredType); } var stringinner = ''; for(index,field in this.fieldTypes ){ var value = this.fieldValues[index] if ( this.fieldIsArray[index] ) { if( this.fieldIsPacked[index] ){ var fieldObject = this._createFieldObject(index); var packedStr = ''; for(i=1;#value;1){ if(value[i][["_isProtobufMessage"]]){ packedStr = packedStr ++ value[i].serialize(-1); } else { fieldObject.value = value[i]; packedStr = packedStr ++ fieldObject.serialize(-1); } } stringinner = stringinner ++ this.encodeVarUint64( index << 3 | wiredTypeLengthDelimited ); stringinner = stringinner ++ this.encodeVarUint64( # packedStr ); stringinner = stringinner ++ packedStr; } else { var fieldObject = this._createFieldObject(index); for(i=1;#value;1){ if( value[i][["_isProtobufMessage"]] ){ stringinner = stringinner ++ value[i].serialize(index); } else { fieldObject.value = value[i]; stringinner = stringinner ++ fieldObject.serialize(index); } } } } else if( value !== null ) { if (value[["_isProtobufMessage"]]) { stringinner = stringinner ++ value.serialize(index); } else { stringinner = stringinner ++ this._createFieldObject(index,value).serialize(index); } } } stringinner = stringinner ++ this.chunk; if (this.wiredType == ..protobuf.message.wiredTypeLengthDelimited && rec > -1){ stringinner = this.encodeVarUint64(#stringinner) ++ stringinner; } return str ++ stringinner; }; deserialize = function (){ this.chunk = ''; var length = this.reader.nextUInt32(); return this.deserializeAux(length); }; deserializeAux = function ( length = 99999999 ) { var consume; var reader = this.reader var _begin = reader.getPointer(); while (reader.getPointer() - _begin < length) { var oldpointer = reader.getPointer(); var next = reader.nextUInt32(); if ( ! next ) break; var fieldTag = this.getFieldTag(next); if (! this.fieldTypes[ fieldTag.fieldNum ] ) { if (fieldTag['wiredType'] == wiredTypeLengthDelimited ) { consume =..protobuf.type.string(reader); } else if (fieldTag['wiredType'] == wiredTypeVarint) { consume = ..protobuf.type.int32(reader); } else { error('I dont understand this wired code:' ++ fieldTag['wiredType'],3); } consume.deserialize(); this.chunk ++= reader.getMessageFrom(oldpointer); continue; } var fieldNum = fieldTag['fieldNum']; var value = this.fieldValues[fieldNum]; var msg = this._createFieldObject( fieldNum ); if (fieldTag['wiredType'] != msg.wiredType) { if(fieldTag['wiredType'] == wiredTypeLengthDelimited && this.fieldIsArray[fieldNum] && this.fieldIsArray[fieldNum] ){ var length = this.reader.nextUInt32(); var _begin = reader.getPointer(); var items = this.fieldValues[fieldNum]; while (reader.getPointer() - _begin < length) { msg.deserialize() if(msg[["_isProtobufValueType"]]){ ..table.push( items, msg.value ); } else { ..table.push( items, msg ); } msg = this._createFieldObject( fieldNum ); } continue; } else{ error('\r\n' ++ 'Pb type:' ++ fieldTag['wiredType'] ++ '\r\n' ++ 'but message type ' ++ msg.wiredType ++ '\r\n' ++ "message class:" ++ this.fieldTypes[fieldNum] ); } } if(this.fieldOneOf[fieldNum]){ var oneof = this.fieldOneOf[fieldNum]; for(k,v in this.fieldOneOf){ if(this.fieldOneOf[k] === oneof ){ this.fieldValues[k] = null; } } } if ( this.fieldIsArray[fieldNum] ) { msg.deserialize(); if(k[["_isProtobufValueType"]]){ ..table.push( this.fieldValues[fieldNum] , msg.value); } else { ..table.push( this.fieldValues[fieldNum] , msg); } } elseif ( this.fieldMapKeyValueType[fieldNum] ) { msg.value = this.fieldValues[fieldNum]; var k,v = msg.deserialize(); } else { this.fieldValues[fieldNum] = msg; msg.deserialize() } } return this; }; serializeToString = function(){ return this.serialize(); }; parseFromString = function (message) { if(!#message) error("参数不能为空字符串",2) for(k,v in this.fieldValues){ if( this.fieldIsArray[k] ) this.fieldValues[k] = []; elseif( this.fieldMapKeyValueType[k] ) this.fieldValues[k] = {}; } this.reader = ..protobuf.reader.inputString(message); this.deserializeAux(); }; tostring = function(){ return this.serialize(); }; fromString = function(){ return this.parseFromString(); }; _isProtobufMessage = true; } namespace message { wiredTypeVarint = 0; wiredType64Bit = 1; wiredTypeLengthDelimited = 2; wiredTypeString = 2; wiredType32Bit = 5; } //@guide [示例](doc://example/Network/protobuf/QuickStart.html) /**intellisense() protobuf = Protobuf 序列化协议,\n支持 proto2,proto3 语法。\n用法 请参考:aardio 范例 > 网络应用 > protobuf protobuf.message = Protobuf 消息对象,\nProtobuf 中所有类型都是继承自 protobuf.message。\n字段名中下划线后接小写字母会自动去掉下划线转换为驼峰式命名\nProtobuf 消息对象可以用 JSON.stringify 转换为 json,\n也可以用 JSON.strip 转换为纯 table 对象 end intellisense**/