forked from protobufjs/protobuf.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecoder.js
129 lines (110 loc) · 4.05 KB
/
decoder.js
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
129
"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,value" : ""))
("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
("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")
("}")
("}");
gen
("if(! %s )", ref)
("%s={}", ref);
gen
("%s[String(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.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));
}
const result = gen
("return m");
return result;
/* eslint-enable no-unexpected-multiline */
}