mirror of
https://github.com/titanscouting/tra-analysis.git
synced 2024-11-14 23:26:18 +00:00
107 lines
3.6 KiB
JavaScript
107 lines
3.6 KiB
JavaScript
|
"use strict";
|
||
|
module.exports = decoder;
|
||
|
|
||
|
var Enum = require("./enum"),
|
||
|
types = require("./types"),
|
||
|
util = require("./util");
|
||
|
|
||
|
function missing(field) {
|
||
|
return "missing required '" + field.name + "'";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generates a decoder specific to the specified message type.
|
||
|
* @param {Type} mtype Message type
|
||
|
* @returns {Codegen} Codegen instance
|
||
|
*/
|
||
|
function decoder(mtype) {
|
||
|
/* eslint-disable no-unexpected-multiline */
|
||
|
var gen = util.codegen(["r", "l"], mtype.name + "$decode")
|
||
|
("if(!(r instanceof Reader))")
|
||
|
("r=Reader.create(r)")
|
||
|
("var c=l===undefined?r.len:r.pos+l,m=new this.ctor" + (mtype.fieldsArray.filter(function(field) { return field.map; }).length ? ",k" : ""))
|
||
|
("while(r.pos<c){")
|
||
|
("var t=r.uint32()");
|
||
|
if (mtype.group) gen
|
||
|
("if((t&7)===4)")
|
||
|
("break");
|
||
|
gen
|
||
|
("switch(t>>>3){");
|
||
|
|
||
|
var i = 0;
|
||
|
for (; i < /* initializes */ mtype.fieldsArray.length; ++i) {
|
||
|
var field = mtype._fieldsArray[i].resolve(),
|
||
|
type = field.resolvedType instanceof Enum ? "int32" : field.type,
|
||
|
ref = "m" + util.safeProp(field.name); gen
|
||
|
("case %i:", field.id);
|
||
|
|
||
|
// Map fields
|
||
|
if (field.map) { gen
|
||
|
("r.skip().pos++") // assumes id 1 + key wireType
|
||
|
("if(%s===util.emptyObject)", ref)
|
||
|
("%s={}", ref)
|
||
|
("k=r.%s()", field.keyType)
|
||
|
("r.pos++"); // assumes id 2 + value wireType
|
||
|
if (types.long[field.keyType] !== undefined) {
|
||
|
if (types.basic[type] === undefined) gen
|
||
|
("%s[typeof k===\"object\"?util.longToHash(k):k]=types[%i].decode(r,r.uint32())", ref, i); // can't be groups
|
||
|
else gen
|
||
|
("%s[typeof k===\"object\"?util.longToHash(k):k]=r.%s()", ref, type);
|
||
|
} else {
|
||
|
if (types.basic[type] === undefined) gen
|
||
|
("%s[k]=types[%i].decode(r,r.uint32())", ref, i); // can't be groups
|
||
|
else gen
|
||
|
("%s[k]=r.%s()", ref, type);
|
||
|
}
|
||
|
|
||
|
// Repeated fields
|
||
|
} else if (field.repeated) { gen
|
||
|
|
||
|
("if(!(%s&&%s.length))", ref, ref)
|
||
|
("%s=[]", ref);
|
||
|
|
||
|
// Packable (always check for forward and backward compatiblity)
|
||
|
if (types.packed[type] !== undefined) gen
|
||
|
("if((t&7)===2){")
|
||
|
("var c2=r.uint32()+r.pos")
|
||
|
("while(r.pos<c2)")
|
||
|
("%s.push(r.%s())", ref, type)
|
||
|
("}else");
|
||
|
|
||
|
// Non-packed
|
||
|
if (types.basic[type] === undefined) gen(field.resolvedType.group
|
||
|
? "%s.push(types[%i].decode(r))"
|
||
|
: "%s.push(types[%i].decode(r,r.uint32()))", ref, i);
|
||
|
else gen
|
||
|
("%s.push(r.%s())", ref, type);
|
||
|
|
||
|
// Non-repeated
|
||
|
} else if (types.basic[type] === undefined) gen(field.resolvedType.group
|
||
|
? "%s=types[%i].decode(r)"
|
||
|
: "%s=types[%i].decode(r,r.uint32())", ref, i);
|
||
|
else gen
|
||
|
("%s=r.%s()", ref, type);
|
||
|
gen
|
||
|
("break");
|
||
|
// Unknown fields
|
||
|
} gen
|
||
|
("default:")
|
||
|
("r.skipType(t&7)")
|
||
|
("break")
|
||
|
|
||
|
("}")
|
||
|
("}");
|
||
|
|
||
|
// Field presence
|
||
|
for (i = 0; i < mtype._fieldsArray.length; ++i) {
|
||
|
var rfield = mtype._fieldsArray[i];
|
||
|
if (rfield.required) gen
|
||
|
("if(!m.hasOwnProperty(%j))", rfield.name)
|
||
|
("throw util.ProtocolError(%j,{instance:m})", missing(rfield));
|
||
|
}
|
||
|
|
||
|
return gen
|
||
|
("return m");
|
||
|
/* eslint-enable no-unexpected-multiline */
|
||
|
}
|