//message 消息对象 import protobuf.parser.template; namespace protobuf.parser class field {} class message{ ctor( ){ this.fieldTypes = {} this.subMessage = {} this.subEnum = {} this.parent = null; }; push = function( field ){ ..table.push( this.fieldTypes, field ); } nameSpace = ""; findType = function(name,member){ if(!name) error("参数不能为null",2) var msg = this; do{ if( msg.subMessage[name] || msg.subEnum[name] ){ var t = combineNamespace( combineNamespace( msg.nameSpace,msg.name) ,name); if(member) t = combineNamespace( t,member) return ".." + t; } if(msg.isRootPackage){ break; } msg = msg.parent }while(msg) var package = this.parentPackageNode; var msg = package[name]; if(!msg){ msg = ..table.get(name,this.packageTree); if( msg && !msg.isClass){ error("Error message type:" + name,2) } } if( msg && msg.isClass){ var t = combineNamespace( this.nameSpace,name); if(member) t = combineNamespace( t,member) return ".." + t; } if( msg &&( msg.subMessage[name] || msg.subEnum[name]) ){ var t = combineNamespace( msg.nameSpace,name); if(member) t = combineNamespace( t,member) return ".." + t; } error("Error message type:" + name,2) } parseFullTypeName = function(){ var fieldTypes = this.fieldTypes; if(fieldTypes){ for(i=1;#fieldTypes;1){ var field = fieldTypes[i]; field.fullTypeName = ..protobuf.parser.message.baseTypes[field.typeName] if(!field.fullTypeName){ field.fullTypeName = this.findType(field.typeName) ; } } } for(k,message in this.subMessage){ message.parseFullTypeName(); } } serializeSubEnum = function(){ var template = ..protobuf.parser.template; var tabEnum = {}; for(name,body in this.subEnum){ var enum = template.enum.format( name = name; body = body; ) ..table.push(tabEnum,enum ); } var strSubEnum = ""; if( #tabEnum ){ strSubEnum = indentString( ..string.join(tabEnum,'\r\n')," "); } return strSubEnum; } serializeField = function(){ var template = ..protobuf.parser.template; var tabField = {}; var tabMetaField = {}; var fieldKeys = {}; var allFieldOneOf = {}; for(i=1;#this.fieldTypes;1){ var field = this.fieldTypes[i]; var fieldValue; var fieldMetaTemplate; var fieldTemplate = template.field; var mapKeyType,mapValueType; var fieldOneOf = field.oneof; if(field.oneof){ allFieldOneOf[field.oneof] = 1; fieldValue = field.default===null?"null":field.default; fieldTemplate = template.fieldOneOf; fieldMetaTemplate = template.fieldMeta; } elseif(field.typeName == "map"){ fieldTemplate = template.fieldMap; fieldMetaTemplate = template.fieldMeta; fieldValue = `{}`; mapKeyType = ..protobuf.parser.message.baseTypes[field.mapKeyTypeName] if(!mapKeyType){ mapKeyType = this.findType(field.mapKeyTypeName) ; } mapValueType = ..protobuf.parser.message.baseTypes[field.mapValueTypeName] if(!mapValueType){ mapValueType = this.findType(field.mapValueTypeName) ; } } elseif(field.repeated){ if(field.packed){ fieldTemplate = template.fieldPackedArray; fieldValue = `[]`; } else { fieldTemplate = template.fieldArray; fieldValue = `[]`; } fieldMetaTemplate = template.fieldArrayMeta; } elseif(..string.endsWith(field.varName,"time",true) ){ fieldValue = field.default===null?"null":field.default; fieldMetaTemplate = template.fieldTimeMeta; } else{ fieldValue = field.default===null?"null":field.default; fieldMetaTemplate = template.fieldMeta; } ..table.push(tabField,fieldTemplate.format( idx = field.fieldIndex; typeName = field.fullTypeName; value = fieldValue; mapKeyType = mapKeyType; mapValueType = mapValueType; oneof = fieldOneOf; varName = field.varName; )); ..table.push(tabMetaField,fieldMetaTemplate.format( fieldIndex = field.fieldIndex; varName = field.varName; )); ..table.push(fieldKeys,'"'+field.varName+'"'); } for(k,v in allFieldOneOf){ ..table.push(tabMetaField,template.fieldOneOfMeta.format( oneof = k; )); } var strTabField = ""; var strMetaField = ""; if( #tabField ){ strTabField = indentString( ..string.join(tabField,'\r\n')," "); strMetaField = indentString( ..string.join(tabMetaField,'\r\n')," "); strFieldKeys = ..string.join(fieldKeys,';') ; } return strTabField,strMetaField,strFieldKeys; } serializeIntellisense = function(indentSpace=""){ var template = ..protobuf.parser.template; var intellisense = '/**intelli' + 'sense()\r\n' var intellPath = combineNamespace( this.nameSpace,this.name) intellCls = ..string.replace( intellPath,"@.","_"); if(#intellCls>32){ intellCls = ..string.format("%x", ..string.crc32(intellCls) ) ++ ..string.right(intellCls,16); } var intellClsDot = "!" + intellCls + '.' intellisense ++= intellPath + " = " + 'Protobuf 消息对象\r\n' intellisense ++= intellPath + "() = " + '创建 Protobuf 消息对象。\\n' + intellClsDot + '\r\n' intellisense ++= intellClsDot + 'parseFromString(__/*字符串*/) = 二进制数据反序列化到消息对象\\n此函数自动清空所有数组值,但不会重置其他非数组字段值.\\n因此应对新创建的对象调用此函数.\r\n' intellisense ++= intellClsDot + 'parseValue() = 调用 table.parseValue 获取纯值表。\\n纯值表只包含纯值类型数据,\\n纯值类型指的是:字符串、数值、布尔值、buffer、指针、纯值表。\\n纯值表要么是数组,要么是包含名值对的表。\\n\\n纯值表是可保持原值序列化的表,并且兼容 JSON\r\n' intellisense ++= intellClsDot + 'serializeToString() = 序列化消息对象,返回二进制字符串\r\n' intellisense ++= intellClsDot + 'eachName() = @for k,v in ??.eachName(){\n __/*遍历此消息对象的所有字段,\nk 为字段名,v 为字段值。*/\n}\r\n' for(i=1;#this.fieldTypes;1){ var field = this.fieldTypes[i] var vtype = ..string.trim(field.fullTypeName,".") var scalarType = ..string.startsWith(vtype,"protobuf.type.") var inellCustomType = ..string.replace( vtype,"@.","_"); if(#inellCustomType>32){ inellCustomType = ..string.format("%x", ..string.crc32(inellCustomType) ) ++ ..string.right(inellCustomType,16); } if(field.repeated){ if( !scalarType ){ intellisense ++= intellClsDot + field.varName + "() = " + "!" + inellCustomType + '.\r\n'; } intellisense = ..string.concat( intellisense , intellClsDot , field.varName , " = " , field.comment ,#field.comment ? "\n" : "" ,"不作为函数调用时,用于返回或设置数组。 ",'\r\n' ); intellisense = ..string.concat( intellisense , intellClsDot , field.varName , "(.(index,value) = " , field.comment ,#field.comment ? "\n" : "" ,"如果作为函数调用:\n修改值时参数 @index 指定元素索引,参数 @value 指定元素值。\n获取值时用参数 @index 指定数组索引即可",'\r\n' ); } else{ if(field.typeName!="map"){ intellisense = ..string.concat( intellisense , intellClsDot , field.varName , " = " , field.comment ,#field.comment ? "\n" : "" ,scalarType? vtype : ("!" + inellCustomType + ".") , '\r\n' ); } else { intellisense = ..string.concat( intellisense , intellClsDot , field.varName , " = " , field.comment ,#field.comment ? "\n" : "" , `protobuf.type.map<` + field.mapKeyTypeName+`,`+field.mapValueTypeName+`>`, '\r\n' ); } } } var allOneOf = {} for(i=1;#this.fieldTypes;1){ var field = this.fieldTypes[i] if(!field.oneof || allOneOf[field.oneof]){ continue; } allOneOf[field.oneof] = true; intellisense = ..string.concat( intellisense , intellClsDot , field.oneof , " = 此属性只读\n值为同一 oneof 类型内的唯一非 null 字段名。" , #field.comment?"\n":"",field.comment, '\r\n' ); } intellisense ++= "end intell" + "isense**/"; return intellisense; } serializeSubMessage = function(indentSpace=""){ var tabSubMessage = {}; for(k,message in this.subMessage){ ..table.push(tabSubMessage,message.serialize( indentSpace + " " ) ); } return ..string.join(tabSubMessage,'\r\n'); } serialize = function(indentSpace=""){ var template = ..protobuf.parser.template; if( !this.isClass ){ //package var clsNamespace = template.classNamespace.format( className = this.name; fieldMetas = fieldMetas; subClasses = this.serializeSubMessage(indentSpace); subEnums = this.serializeSubEnum(indentSpace); fieldKeys = fieldKeys; ); clsNamespace = indentString(clsNamespace,indentSpace); return '\r\n' + clsNamespace + '\r\n'; } var fileds,fieldMetas,fieldKeys = this.serializeField(indentSpace); var clsDefine = template.classDefine.format( className = this.name; fileds = fileds ); clsDefine = indentString(clsDefine,indentSpace); var clsNamespace = template.classNamespace.format( className = this.name; fieldMetas = fieldMetas; subClasses = this.serializeSubMessage(indentSpace); subEnums = this.serializeSubEnum(indentSpace); fieldKeys = fieldKeys; ); clsNamespace = indentString(clsNamespace,indentSpace); return clsDefine + '\r\n' + clsNamespace + '\r\n' + this.serializeIntellisense(indentSpace); } } namespace message{ indentString = function(str,space){ return space ++ ..string.replace(str,"\n",'\n'+space) } baseTypes = { double = '..protobuf.type.double'; float = '..protobuf.type.float'; int32 = '..protobuf.type.int32'; int64 = '..protobuf.type.int64'; uint32 = '..protobuf.type.uint32'; uint64 = '..protobuf.type.uint64'; sint32 = '..protobuf.type.sint32'; sint64 = '..protobuf.type.sint64'; fixed32 = '..protobuf.type.fixed32'; fixed64 = '..protobuf.type.fixed64'; sfixed32 = '..protobuf.type.sfixed32'; sfixed64 = '..protobuf.type.sfixed64'; bool = '..protobuf.type.bool'; string = '..protobuf.type.string'; bytes = '..protobuf.type.bytes'; map = '..protobuf.type.map' }; combineNamespace = function(path,name){ if(!name) error("name 不能为空",2) return ..string.trim( ..string.format("%s.%s",path,name ) ,"." ) } } /**intellisense() ?protobuf.parser.field = !protobufparserfield. !protobufparserfield.index = 字段索引 !protobufparserfield.varName = 字段名称 !protobufparserfield.fullTypeName = 字段类型名 !protobufparserfield.default = 字段默认值 !protobufparserfield.isArray = 是否数组 !protobufparserfield.isOptional = 是否可选 ?protobuf.parser.field = !protobufparserfield. end intellisense**/