/
verify.js
91 lines (75 loc) · 3.11 KB
/
verify.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
"use strict";
/**
* Runtime message verifier using code generation on top of reflection that also provides a fallback.
* @exports codegen.verify
* @namespace
*/
var verify = exports;
var Enum = require("../enum"),
Type = require("../type"),
util = require("../util"),
codegen = require("../codegen");
/**
* Verifies a runtime message of `this` message type.
* @param {Prototype|Object} message Runtime message or plain object to verify
* @returns {?string} `null` if valid, otherwise the reason why it is not
* @this {Type}
*/
verify.fallback = function verify_fallback(message) {
var fields = this.getFieldsArray(),
i = 0;
while (i < fields.length) {
var field = fields[i++].resolve(),
value = message[field.name];
if (value === undefined) {
if (field.required)
return "missing required field " + field.name + " in " + this.getFullName();
} else if (field.resolvedType instanceof Enum && field.resolvedType.getValuesById()[value] === undefined) {
return "invalid enum value " + field.name + " = " + value + " in " + this.getFullName();
} else if (field.resolvedType instanceof Type) {
if (!value && field.required)
return "missing required field " + field.name + " in " + this.getFullName();
var reason;
if ((reason = field.resolvedType.verify(value)) !== null)
return reason;
}
}
return null;
};
/**
* Generates a verifier specific to the specified message type, with an identical signature to {@link codegen.verify.fallback}.
* @param {Type} mtype Message type
* @returns {CodegenInstance} {@link codegen|Codegen} instance
*/
verify.generate = function verify_generate(mtype) {
/* eslint-disable no-unexpected-multiline */
var fields = mtype.getFieldsArray();
var gen = codegen("m");
var hasReasonVar = false;
for (var i = 0; i < fields.length; ++i) {
var field = fields[i].resolve(),
prop = util.safeProp(field.name);
if (field.required) { gen
("if(m%s===undefined)", prop)
("return 'missing required field %s in %s'", field.name, mtype.getFullName());
} else if (field.resolvedType instanceof Enum) {
var values = util.toArray(field.resolvedType.values); gen
("switch(m%s){", prop)
("default:")
("return 'invalid enum value %s = '+m%s+' in %s'", field.name, prop, mtype.getFullName());
for (var j = 0, l = values.length; j < l; ++j) gen
("case %d:", values[j]); gen
("}");
} else if (field.resolvedType instanceof Type) {
if (field.required) gen
("if(!m%s)", prop)
("return 'missing required field %s in %s'", field.name, mtype.getFullName());
if (!hasReasonVar) { gen("var r"); hasReasonVar = true; } gen
("if((r=types[%d].verify(m%s))!==null)", i, prop)
("return r");
}
}
return gen
("return null");
/* eslint-enable no-unexpected-multiline */
};