@@ -2,31 +2,31 @@ module.exports = static_target;
2
2
3
3
static_target . private = true ;
4
4
5
- // This file contains the beginnings of static code generation.
6
- // It doesn't generate anything useful, yet, but can be used as a starting point.
5
+ // Currently, this file contains initial static code for CommonJS modules.
7
6
8
7
// TBD:
9
8
// - Generate a single file or scaffold an entire project directory? Both?
10
9
// - Targets: ES5, ES6, TypeScript? CommonJS? AMD?
11
- // - Is there a need for a minimal runtime composed only of Reader/Writer/minimal util?
12
- // - What about generating comments and typescript definitions for non-ts targets?
10
+ // - What about generating typescript definitions for non-ts targets?
13
11
14
12
var protobuf = require ( "../.." ) ;
15
13
16
14
var Type = protobuf . Type ,
17
15
Service = protobuf . Service ,
18
16
Enum = protobuf . Enum ,
19
17
Namespace = protobuf . Namespace ,
20
- codegen = protobuf . util . codegen ;
18
+ encoder = protobuf . encoder ,
19
+ decoder = protobuf . decoder ,
20
+ verifier = protobuf . verifier ,
21
+ util = protobuf . util ;
21
22
22
23
var out = [ ] ;
24
+ var indent = 0 ;
23
25
24
26
function static_target ( root , options , callback ) {
25
27
tree = { } ;
26
28
try {
27
- out . push ( "var protobuf = require(\"protobufjs\");" ) ;
28
- out . push ( "var root = exports;" ) ;
29
- buildNamespace ( "root" , root ) ;
29
+ buildNamespace ( "module.exports" , root ) ;
30
30
callback ( null , out . join ( '\n' ) ) ;
31
31
} catch ( err ) {
32
32
callback ( err ) ;
@@ -35,33 +35,215 @@ function static_target(root, options, callback) {
35
35
}
36
36
}
37
37
38
+ function push ( line ) {
39
+ if ( line === "" )
40
+ return out . push ( "" ) ;
41
+ var ind = "" ;
42
+ for ( var i = 0 ; i < indent ; ++ i )
43
+ ind += " " ;
44
+ out . push ( ind + line ) ;
45
+ }
46
+
47
+ function pushComment ( lines ) {
48
+ push ( "/**" ) ;
49
+ lines . forEach ( function ( line , i ) {
50
+ push ( " * " + line ) ;
51
+ } ) ;
52
+ push ( " */" ) ;
53
+ }
54
+
55
+ function name ( name ) {
56
+ if ( ! name )
57
+ return "$root" ;
58
+ return name ;
59
+ }
60
+
38
61
function buildNamespace ( ref , ns ) {
39
62
if ( ! ns )
40
63
return ;
64
+ if ( ns . name === "" ) { // root
65
+ push ( name ( ref ) + " = (function() {" ) ;
66
+ ++ indent ;
67
+ push ( '"use strict";' ) ;
68
+ push ( "" ) ;
69
+ push ( "// Minimal static codegen runtime" ) ;
70
+ push ( "var $runtime = require(\"protobufjs/runtime\");" )
71
+ push ( "" ) ;
72
+ push ( "// Lazily resolved type references" ) ;
73
+ push ( "var $lazyTypes = [];" ) ;
74
+ } else {
75
+ push ( "" ) ;
76
+ push ( "/** @alias " + ns . fullName . substring ( 1 ) + " */" ) ;
77
+ push ( name ( ref ) + "." + name ( ns . name ) + " = (function() {" ) ;
78
+ ++ indent ;
79
+ }
80
+
81
+ if ( ns instanceof Type ) {
82
+ buildType ( undefined , ns ) ;
83
+ } else if ( ns instanceof Service )
84
+ buildService ( undefined , ns ) ;
85
+ else {
86
+ push ( "" ) ;
87
+ push ( "/** @alias " + ( ns . name && ns . fullName . substring ( 1 ) || "exports" ) + " */" ) ;
88
+ push ( "var " + name ( ns . name ) + " = {};" ) ;
89
+ }
90
+
41
91
ns . nestedArray . forEach ( function ( nested ) {
42
- if ( nested instanceof Type )
43
- buildType ( ref , nested ) ;
44
- else if ( nested instanceof Service )
45
- buildService ( ref , nested ) ;
46
- else if ( nested instanceof Enum )
47
- buildEnum ( ref , nested ) ;
92
+ if ( nested instanceof Enum )
93
+ buildEnum ( ns . name , nested ) ;
48
94
else if ( nested instanceof Namespace )
49
- buildNamespace ( ref , nested ) ;
95
+ buildNamespace ( ns . name , nested ) ;
96
+ } ) ;
97
+ push ( "" ) ;
98
+ if ( ns . name === "" ) // root
99
+ push ( "return $runtime.resolve($root, $lazyTypes);" ) ;
100
+ else
101
+ push ( "return " + name ( ns . name ) + ";" ) ;
102
+ -- indent ;
103
+ push ( "})();" ) ;
104
+ }
105
+
106
+ function buildFunction ( type , functionName , gen , scope ) {
107
+ var lines = gen . str ( functionName )
108
+ . replace ( "(this.getCtor())" , " $root" + type . fullName )
109
+ . split ( / \n / g) ;
110
+ push ( name ( type . name ) + "." + functionName + " = (function() {" ) ;
111
+ ++ indent ;
112
+ push ( "/* eslint-disable */" ) ;
113
+ Object . keys ( scope ) . forEach ( function ( key ) {
114
+ push ( "var " + key + " = " + scope [ key ] + ";" ) ;
115
+ } ) ;
116
+ push ( "var types; $lazyTypes.push(types = [" + type . fieldsArray . map ( function ( field ) {
117
+ return field . resolve ( ) . resolvedType
118
+ ? JSON . stringify ( field . resolvedType . fullName . substring ( 1 ) )
119
+ : "null" ;
120
+ } ) . join ( ',' ) + "]);" ) ;
121
+ push ( "return " + lines [ 0 ] ) ;
122
+ lines . slice ( 1 ) . forEach ( function ( line ) {
123
+ if ( line === '\t"use strict"' )
124
+ return ;
125
+ var prev = indent ;
126
+ var i = 0 ;
127
+ while ( line . charAt ( i ++ ) === "\t" )
128
+ ++ indent ;
129
+ push ( line . trim ( ) ) ;
130
+ indent = prev ;
50
131
} ) ;
132
+ push ( "/* eslint-enable */" ) ;
133
+ -- indent ;
134
+ push ( "})();" ) ;
51
135
}
52
136
53
137
function buildType ( ref , type ) {
54
- out . push ( "" ) ;
55
- out . push ( ref + "." + type . name + " = function " + type . name + "() {};" ) ; // currently just an empty function
56
- buildNamespace ( ref + "." + type . name , type ) ;
138
+ var fullName = type . fullName . substring ( 1 ) ;
139
+
140
+ push ( "" ) ;
141
+ pushComment ( [
142
+ "Constructs a new " + type . name + "." ,
143
+ "@exports " + fullName ,
144
+ "@constructor" ,
145
+ "@param {Object} [properties] Properties to set"
146
+ ] ) ;
147
+ push ( "function " + name ( type . name ) + "(properties) {" ) ;
148
+ ++ indent ;
149
+ push ( "if (properties) {" ) ;
150
+ ++ indent ;
151
+ push ( "var keys = Object.keys(properties);" ) ;
152
+ push ( "for (var i = 0; i < keys.length; ++i)" ) ;
153
+ ++ indent ;
154
+ push ( "this[keys[i]] = properties[keys[i]];" ) ;
155
+ -- indent ;
156
+ -- indent ;
157
+ push ( "}" ) ;
158
+ -- indent ;
159
+ push ( "}" ) ;
160
+ push ( "" ) ;
161
+ type . fieldsArray . forEach ( function ( field ) {
162
+ field . resolve ( ) ;
163
+ if ( typeof field . defaultValue === 'object' && field . defaultValue )
164
+ return ;
165
+ push ( name ( type . name ) + ".prototype." + name ( field . name ) + " = " + JSON . stringify ( field . defaultValue ) + ";" ) ;
166
+ } ) ;
167
+
168
+ // #encode
169
+ push ( "" ) ;
170
+ pushComment ( [
171
+ "Encodes the specified " + type . name + "." ,
172
+ "@function" ,
173
+ "@param {" + fullName + "|Object} message " + type . name + " or plain object to encode" ,
174
+ "@param {Writer} [writer] Writer to encode to" ,
175
+ "@returns {Writer} Writer"
176
+ ] ) ;
177
+ buildFunction ( type , "encode" , encoder . generate ( type ) , {
178
+ Writer : "$runtime.Writer" ,
179
+ util : "$runtime.util"
180
+ } ) ;
181
+
182
+ // #encodeDelimited
183
+ push ( "" ) ;
184
+ pushComment ( [
185
+ "Encodes the specified " + type . name + ", length delimited." ,
186
+ "@param {" + fullName + "|Object} message " + type . name + " or plain object to encode" ,
187
+ "@param {Writer} [writer] Writer to encode to" ,
188
+ "@returns {Writer} Writer"
189
+ ] ) ;
190
+ push ( name ( type . name ) + ".encodeDelimited = function encodeDelimited(message, writer) {" ) ;
191
+ ++ indent ;
192
+ push ( "return this.encode(message, writer).ldelim();" ) ;
193
+ -- indent ;
194
+ push ( "};" ) ;
195
+
196
+ // #decode
197
+ push ( "" ) ;
198
+ pushComment ( [
199
+ "Decodes a " + type . name + " from the specified reader or buffer." ,
200
+ "@function" ,
201
+ "@param {Reader|Uint8Array} readerOrBuffer Reader or buffer to decode from" ,
202
+ "@param {number} [length] Message length if known beforehand" ,
203
+ "@returns {" + fullName + "} " + type . name
204
+ ] ) ;
205
+ buildFunction ( type , "decode" , decoder . generate ( type ) , {
206
+ Reader : "$runtime.Reader" ,
207
+ util : "$runtime.util"
208
+ } ) ;
209
+
210
+ // #decodeDelimited
211
+ push ( "" ) ;
212
+ pushComment ( [
213
+ "Decodes a " + type . name + " from the specified reader or buffer, length delimited." ,
214
+ "@param {Reader|Uint8Array} readerOrBuffer Reader or buffer to decode from" ,
215
+ "@returns {" + fullName + "} " + type . name
216
+ ] ) ;
217
+ push ( name ( type . name ) + ".decodeDelimited = function decodeDelimited(readerOrBuffer) {" ) ;
218
+ ++ indent ;
219
+ push ( "readerOrBuffer = readerOrBuffer instanceof Reader ? readerOrBuffer : Reader(readerOrBuffer);" ) ;
220
+ push ( "return this.decode(readerOrBuffer, readerOrBuffer.uint32());" ) ;
221
+ -- indent ;
222
+ push ( "};" ) ;
223
+
224
+ // #verify
225
+ push ( "" ) ;
226
+ pushComment ( [
227
+ "Verifies a " + type . name + "." ,
228
+ "@param {" + fullName + "|Object} message " + type . name + " or plain object to verify" ,
229
+ "@returns {?string} `null` if valid, otherwise the reason why it is not"
230
+ ] ) ;
231
+ buildFunction ( type , "verify" , verifier . generate ( type ) , { } ) ;
57
232
}
58
233
59
234
function buildService ( ref , service ) {
60
- out . push ( "" ) ;
61
- out . push ( ref + "." + service . name + " = {};" ) ; // currently just an empty object
235
+ push ( "" ) ;
236
+ push ( name ( ref ) + "." + name ( service . name ) + " = {};" ) ; // currently just an empty object
62
237
}
63
238
64
239
function buildEnum ( ref , enm ) {
65
- out . push ( "" ) ;
66
- out . push ( ref + "." + enm . name + " = " + JSON . stringify ( enm . values , null , "\t" ) + ";" ) ;
240
+ push ( "" ) ;
241
+ push ( ref + "." + enm . name + " = {" ) ;
242
+ ++ indent ;
243
+ push ( "" ) ;
244
+ Object . keys ( enm . values ) . forEach ( function ( key ) {
245
+ push ( name ( key ) + ": " + enm . values [ key ] . toString ( 10 ) + "," ) ;
246
+ } ) ;
247
+ -- indent ;
248
+ push ( "};" ) ;
67
249
}
0 commit comments