File size: 4,239 Bytes
f8f5b35 761e469 f8f5b35 761e469 f8f5b35 761e469 f8f5b35 761e469 f8f5b35 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
"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", "e"], 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,value" : ""))
("while(r.pos<c){")
("var t=r.uint32()")
("if(t===e)")
("break")
("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
("if(%s===util.emptyObject)", ref)
("%s={}", ref)
("var c2 = r.uint32()+r.pos");
if (types.defaults[field.keyType] !== undefined) gen
("k=%j", types.defaults[field.keyType]);
else gen
("k=null");
if (types.defaults[type] !== undefined) gen
("value=%j", types.defaults[type]);
else gen
("value=null");
gen
("while(r.pos<c2){")
("var tag2=r.uint32()")
("switch(tag2>>>3){")
("case 1: k=r.%s(); break", field.keyType)
("case 2:");
if (types.basic[type] === undefined) gen
("value=types[%i].decode(r,r.uint32())", i); // can't be groups
else gen
("value=r.%s()", type);
gen
("break")
("default:")
("r.skipType(tag2&7)")
("break")
("}")
("}");
if (types.long[field.keyType] !== undefined) gen
("%s[typeof k===\"object\"?util.longToHash(k):k]=value", ref);
else gen
("%s[k]=value", ref);
// 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.delimited
? "%s.push(types[%i].decode(r,undefined,((t&~7)|4)))"
: "%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.delimited
? "%s=types[%i].decode(r,undefined,((t&~7)|4))"
: "%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 */
}
|