protobuf-closure-library 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/
5
+ tmp/
6
+ lib/protoc_js_core.*
7
+ *.pb.cc
8
+ *.pb.h
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in protobuf-closure-library.gemspec
4
+ gemspec
@@ -0,0 +1,31 @@
1
+ Protocol buffer javascript compiler for closure library
2
+ -------------------------------------------------------
3
+
4
+ This gem is a wrapper for native protocol buffer javascript compiler which generates closure library proto2 messages.
5
+
6
+ At the time of writing this gem, google does not provide an official protocol buffer compiler for closure library. An almost identical open source alternative is `protobuf-plugin-closure <http://code.google.com/p/protobuf-plugin-closure/>`_ which this gem is based on.
7
+
8
+ Installation
9
+ ++++++++++++
10
+
11
+ `Protobuf <http://code.google.com/p/protobuf/>`_ runtime compiler and development header and libraries must be present at gem installation time.
12
+
13
+ * Under linux, user the right development package, eg ``libprotobuf-dev`` for ubuntu.
14
+ * Under osx, use ``brew install protobuf``.
15
+ * under windows, use the `official protobuf binaries <http://code.google.com/p/protobuf/downloads/list>`_.
16
+
17
+ Then, install the gem:
18
+
19
+ ::
20
+
21
+ gem install protobuf-closure-library
22
+
23
+ Usage
24
+ +++++
25
+
26
+ ::
27
+
28
+ ProtobufClosureLibrary::ProtocJs.compile input_proto_file,
29
+ output_dir, optional_protoc_arg, ...
30
+
31
+ This generated a ``.pb.js`` file correponded to ``input_proto_file`` in ``output_dir``. The output file contains a subclass of `goog.proto2.Message <http://closure-library.googlecode.com/svn/docs/class_goog_proto2_Message.html>`_.
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ require 'bundler/gem_tasks'
9
+ require 'rake/extensiontask'
10
+ require 'rake/testtask'
11
+
12
+ def gemspec
13
+ @gemspec ||= eval(File.read File.expand_path('../protobuf-closure-library.gemspec', __FILE__))
14
+ end
15
+
16
+ Rake::ExtensionTask.new :protoc_js_core, gemspec
17
+
18
+ Rake::TestTask.new :test do |t|
19
+ t.libs << 'lib'
20
+ t.libs << 'test'
21
+ t.pattern = 'test/**/*_test.rb'
22
+ t.verbose = true
23
+ end
@@ -0,0 +1,732 @@
1
+ // Copyright (c) 2010-2011 SameGoal LLC.
2
+ // All Rights Reserved.
3
+ // Author: Andy Hochhaus <ahochhaus@samegoal.com>
4
+
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+
17
+ #include "code_generator.h"
18
+
19
+ #include <string>
20
+ #include <iostream> // NOLINT
21
+ #include <sstream> // NOLINT
22
+
23
+ #include "google/protobuf/descriptor.h"
24
+ #include "google/protobuf/io/printer.h"
25
+ #include "google/protobuf/io/zero_copy_stream.h"
26
+ #include "google/protobuf/stubs/common.h"
27
+
28
+ #include "int64_encoding.pb.h"
29
+ #include "javascript_package.pb.h"
30
+
31
+ namespace sg {
32
+ namespace protobuf {
33
+ namespace js {
34
+
35
+ CodeGenerator::CodeGenerator(const std::string &name)
36
+ : name_(name) {}
37
+
38
+ CodeGenerator::~CodeGenerator() {}
39
+
40
+ bool CodeGenerator::Generate(
41
+ const google::protobuf::FileDescriptor *file,
42
+ const std::string &/* parameter */,
43
+ google::protobuf::compiler::OutputDirectory *output_directory,
44
+ std::string *error) const {
45
+
46
+ const std::string file_name = file->name();
47
+ std::string output_file_name = file->name();
48
+ std::size_t loc = output_file_name.rfind(".");
49
+ output_file_name.erase(loc, output_file_name.length() - loc);
50
+ output_file_name.append(".pb.js");
51
+
52
+ google::protobuf::internal::scoped_ptr<
53
+ google::protobuf::io::ZeroCopyOutputStream> output(
54
+ output_directory->Open(output_file_name));
55
+ google::protobuf::io::Printer printer(output.get(), '$');
56
+ printer.Print(
57
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n");
58
+ printer.Print("// source: $file_name$\n", "file_name", file_name);
59
+ printer.Print("\n");
60
+ printer.Print(
61
+ "/**\n"
62
+ " * @fileoverview Generated Protocol Buffer code for file $file_name$.\n"
63
+ " */\n", "file_name", file_name);
64
+ printer.Print("\n");
65
+
66
+ // goog.provide all messages and enums
67
+ for (int i = 0; i < file->message_type_count(); ++i) {
68
+ CodeGenerator::GenDescriptorGoogProvides(
69
+ file->message_type(i),
70
+ &printer);
71
+ }
72
+ for (int i = 0; i < file->enum_type_count(); ++i) {
73
+ CodeGenerator::GenEnumDescriptorGoogProvides(
74
+ file->enum_type(i),
75
+ &printer);
76
+ }
77
+
78
+ printer.Print("\n");
79
+ printer.Print("goog.require('goog.proto2.Message');\n"
80
+ "\n");
81
+ for (int i = 0; i < file->dependency_count(); ++i) {
82
+ for (int j = 0; j < file->dependency(i)->message_type_count(); j++) {
83
+ printer.Print(
84
+ "goog.require('$file$');\n",
85
+ "file",
86
+ JsFullName(file->dependency(i)->message_type(j)->file(),
87
+ file->dependency(i)->message_type(j)->full_name()));
88
+ }
89
+ }
90
+
91
+ printer.Print("\n");
92
+
93
+ // generate accessor functions
94
+ for (int i = 0; i < file->message_type_count(); ++i) {
95
+ CodeGenerator::GenDescriptor(
96
+ file->message_type(i),
97
+ &printer);
98
+ }
99
+ for (int i = 0; i < file->enum_type_count(); ++i) {
100
+ CodeGenerator::GenEnumDescriptor(
101
+ file->enum_type(i),
102
+ &printer);
103
+ }
104
+
105
+ printer.Print("\n");
106
+
107
+ // generate metadata
108
+ for (int i = 0; i < file->message_type_count(); ++i) {
109
+ CodeGenerator::GenDescriptorMetadata(
110
+ file->message_type(i),
111
+ &printer);
112
+ }
113
+
114
+ if (printer.failed()) {
115
+ *error = "CodeGenerator detected write error.";
116
+ return false;
117
+ }
118
+
119
+ return true;
120
+ }
121
+
122
+ std::string CodeGenerator::JsFullName(
123
+ const google::protobuf::FileDescriptor *file,
124
+ const std::string &full_name) {
125
+ std::string new_name = full_name;
126
+ const std::string package = file->package();
127
+
128
+ std::string prefix = file->options().GetExtension(javascript_package);
129
+ if (prefix.length() > 0) {
130
+ if (package.length() > 0) {
131
+ new_name.erase(0, package.length() + 1);
132
+ }
133
+ new_name = prefix + "." + new_name;
134
+ }
135
+ return new_name;
136
+ }
137
+
138
+ void CodeGenerator::GenDescriptorGoogProvides(
139
+ const google::protobuf::Descriptor *message,
140
+ google::protobuf::io::Printer *printer) {
141
+ printer->Print("goog.provide('$name$');\n",
142
+ "name", JsFullName(message->file(),
143
+ message->full_name()));
144
+
145
+ // enums
146
+ for (int i = 0; i < message->enum_type_count(); ++i) {
147
+ CodeGenerator::GenEnumDescriptorGoogProvides(
148
+ message->enum_type(i),
149
+ printer);
150
+ }
151
+
152
+ // Recursively process nested messages
153
+ for (int i = 0; i < message->nested_type_count(); ++i) {
154
+ CodeGenerator::GenDescriptorGoogProvides(
155
+ message->nested_type(i),
156
+ printer);
157
+ }
158
+ }
159
+
160
+ void CodeGenerator::GenEnumDescriptorGoogProvides(
161
+ const google::protobuf::EnumDescriptor *enum_desc,
162
+ google::protobuf::io::Printer *printer) {
163
+ printer->Print("goog.provide('$name$');\n",
164
+ "name", JsFullName(enum_desc->file(),
165
+ enum_desc->full_name()));
166
+ }
167
+
168
+ void CodeGenerator::GenDescriptor(
169
+ const google::protobuf::Descriptor *message,
170
+ google::protobuf::io::Printer *printer) {
171
+ printer->Print("\n"
172
+ "/**\n"
173
+ " * Message $name$.\n"
174
+ " * @constructor\n"
175
+ " * @extends {goog.proto2.Message}\n"
176
+ " */\n",
177
+ "name", message->name());
178
+ printer->Print("$name$ = function() {\n",
179
+ "name", JsFullName(message->file(),
180
+ message->full_name()));
181
+ printer->Indent();
182
+ printer->Print("goog.proto2.Message.apply(this);\n");
183
+ printer->Outdent();
184
+ printer->Print("};\n"
185
+ "goog.inherits($name$, goog.proto2.Message);\n"
186
+ "\n"
187
+ "\n",
188
+ "name", JsFullName(message->file(),
189
+ message->full_name()));
190
+
191
+ printer->Print(
192
+ "/**\n"
193
+ " * Overrides {@link goog.proto2.Message#clone} to specify its exact "
194
+ "return type.\n"
195
+ " * @return {!$name$} The cloned message.\n"
196
+ " * @override\n"
197
+ " */\n"
198
+ "$name$.prototype.clone;\n",
199
+ "name", JsFullName(message->file(),
200
+ message->full_name()));
201
+
202
+ // fields
203
+ for (int i = 0; i < message->field_count(); ++i) {
204
+ CodeGenerator::GenFieldDescriptor(
205
+ message->field(i),
206
+ printer);
207
+ }
208
+
209
+ // enums
210
+ for (int i = 0; i < message->enum_type_count(); ++i) {
211
+ CodeGenerator::GenEnumDescriptor(
212
+ message->enum_type(i),
213
+ printer);
214
+ }
215
+
216
+ // nested messages (recursively process)
217
+ for (int i = 0; i < message->nested_type_count(); ++i) {
218
+ CodeGenerator::GenDescriptor(
219
+ message->nested_type(i),
220
+ printer);
221
+ printer->Print("\n"
222
+ "\n");
223
+ }
224
+ }
225
+
226
+ void CodeGenerator::GenFieldDescriptor(
227
+ const google::protobuf::FieldDescriptor *field,
228
+ google::protobuf::io::Printer *printer) {
229
+ printer->Print("\n");
230
+ std::string type;
231
+ bool type_is_primitive = false;
232
+ bool as_number = field->options().GetExtension(jstype);
233
+ if (field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) {
234
+ type = "boolean";
235
+ type_is_primitive = true;
236
+ } else if (
237
+ field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES ||
238
+ field->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
239
+ ((field->type() == google::protobuf::FieldDescriptor::TYPE_INT64 ||
240
+ field->type() == google::protobuf::FieldDescriptor::TYPE_UINT64 ||
241
+ field->type() == google::protobuf::FieldDescriptor::TYPE_SINT64 ||
242
+ field->type() == google::protobuf::FieldDescriptor::TYPE_FIXED64 ||
243
+ field->type() == google::protobuf::FieldDescriptor::TYPE_SFIXED64) &&
244
+ !as_number)) {
245
+ type = "string";
246
+ type_is_primitive = true;
247
+ } else if (
248
+ field->type() == google::protobuf::FieldDescriptor::TYPE_GROUP ||
249
+ field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
250
+ type = JsFullName(field->message_type()->file(),
251
+ field->message_type()->full_name());
252
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_ENUM) {
253
+ type = JsFullName(field->enum_type()->file(),
254
+ field->enum_type()->full_name());
255
+ type_is_primitive = true;
256
+ } else {
257
+ type = "number";
258
+ type_is_primitive = true;
259
+ }
260
+
261
+ std::ostringstream number;
262
+ number << field->number();
263
+
264
+ std::string upper_name = field->camelcase_name();
265
+ if (upper_name[0] >= 97 && upper_name[0] <= 122) {
266
+ upper_name[0] -= 32;
267
+ }
268
+
269
+ // get
270
+ if (field->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
271
+ printer->Print(
272
+ "\n"
273
+ "/**\n"
274
+ " * Gets the value of the $name$ field at the index given.\n"
275
+ " * @param {number} index The index to lookup.\n",
276
+ "name", field->name());
277
+ printer->Print(
278
+ " * @return {$opt$$type$} The value.\n"
279
+ " */\n",
280
+ "opt", type_is_primitive ? "?" : "",
281
+ "type", type);
282
+ printer->Print(
283
+ "$prefix$.prototype.get$field$ = function(index) {\n",
284
+ "prefix", JsFullName(field->containing_type()->file(),
285
+ field->containing_type()->full_name()),
286
+ "field", upper_name);
287
+ printer->Indent();
288
+ printer->Print(
289
+ "return /** @type {$opt$$type$} */ ",
290
+ "opt", type_is_primitive ? "?" : "",
291
+ "type", type);
292
+ printer->Print(
293
+ "(this.get$$Value($number$, index));\n",
294
+ "number", number.str());
295
+ printer->Outdent();
296
+ printer->Print(
297
+ "};\n"
298
+ "\n");
299
+
300
+ printer->Print(
301
+ "\n"
302
+ "/**\n"
303
+ " * Gets the value of the $name$ field at the index given or the "
304
+ "default value if not set.\n"
305
+ " * @param {number} index The index to lookup.\n",
306
+ "name", field->name());
307
+ printer->Print(
308
+ " * @return {$opt$$type$} The value.\n"
309
+ " */\n",
310
+ "opt", type_is_primitive ? "" : "!",
311
+ "type", type);
312
+ printer->Print(
313
+ "$prefix$.prototype.get$field$OrDefault = function(index) {\n",
314
+ "prefix", JsFullName(field->containing_type()->file(),
315
+ field->containing_type()->full_name()),
316
+ "field", upper_name);
317
+ printer->Indent();
318
+ printer->Print(
319
+ "return /** @type {$opt$$type$} */ (",
320
+ "opt", type_is_primitive ? "" : "!",
321
+ "type", type);
322
+ printer->Print(
323
+ "this.get$$ValueOrDefault($number$, "
324
+ "index));\n",
325
+ "number", number.str());
326
+ printer->Outdent();
327
+ printer->Print(
328
+ "};\n"
329
+ "\n");
330
+ } else {
331
+ printer->Print(
332
+ "\n"
333
+ "/**\n"
334
+ " * Gets the value of the $name$ field.\n",
335
+ "name", field->name());
336
+ printer->Print(
337
+ " * @return {$opt$$type$} The value.\n"
338
+ " */\n",
339
+ "opt", type_is_primitive ? "?" : "",
340
+ "type", type);
341
+ printer->Print(
342
+ "$prefix$.prototype.get$field$ = function() {\n",
343
+ "prefix", JsFullName(field->containing_type()->file(),
344
+ field->containing_type()->full_name()),
345
+ "field", upper_name);
346
+ printer->Indent();
347
+ printer->Print(
348
+ "return /** @type {$opt$$type$} */ ",
349
+ "opt", type_is_primitive ? "?" : "",
350
+ "type", type);
351
+ printer->Print(
352
+ "(this.get$$Value($number$));\n",
353
+ "number", number.str());
354
+ printer->Outdent();
355
+ printer->Print(
356
+ "};\n"
357
+ "\n");
358
+
359
+ printer->Print(
360
+ "\n"
361
+ "/**\n"
362
+ " * Gets the value of the $name$ field or the default value if not "
363
+ "set.\n",
364
+ "name", field->name());
365
+ printer->Print(
366
+ " * @return {$opt$$type$} The value.\n"
367
+ " */\n",
368
+ "opt", type_is_primitive ? "" : "!",
369
+ "type", type);
370
+ printer->Print(
371
+ "$prefix$.prototype.get$field$OrDefault = function() {\n",
372
+ "prefix", JsFullName(field->containing_type()->file(),
373
+ field->containing_type()->full_name()),
374
+ "field", upper_name);
375
+ printer->Indent();
376
+ printer->Print(
377
+ "return /** @type {$opt$$type$} */ (",
378
+ "opt", type_is_primitive ? "" : "!",
379
+ "type", type);
380
+ printer->Print(
381
+ "this.get$$ValueOrDefault($number$));\n",
382
+ "number", number.str());
383
+ printer->Outdent();
384
+ printer->Print(
385
+ "};\n"
386
+ "\n");
387
+ }
388
+
389
+ // set
390
+ if (field->label() != google::protobuf::FieldDescriptor::LABEL_REPEATED) {
391
+ printer->Print("\n"
392
+ "/**\n"
393
+ " * Sets the value of the $name$ field.\n",
394
+ "name", field->name());
395
+ printer->Print(" * @param {$opt$$type$} value The value.\n"
396
+ " */\n",
397
+ "opt", type_is_primitive ? "" : "!",
398
+ "type", type);
399
+ printer->Print("$prefix$.prototype.set$field$ = function(value) {\n",
400
+ "prefix", JsFullName(field->containing_type()->file(),
401
+ field->containing_type()->full_name()),
402
+ "field", upper_name);
403
+ printer->Indent();
404
+ printer->Print(
405
+ "this.set$$Value($number$, value);\n",
406
+ "number", number.str());
407
+ printer->Outdent();
408
+ printer->Print("};\n"
409
+ "\n");
410
+ }
411
+
412
+ // add, Array
413
+ if (field->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
414
+ printer->Print("\n"
415
+ "/**\n"
416
+ " * Adds a value to the $name$ field.\n",
417
+ "name", field->name());
418
+ printer->Print(" * @param {$opt$$type$} value The value to add.\n"
419
+ " */\n",
420
+ "opt", type_is_primitive ? "" : "!",
421
+ "type", type);
422
+ printer->Print("$prefix$.prototype.add$field$ = function(value) {\n",
423
+ "prefix", JsFullName(field->containing_type()->file(),
424
+ field->containing_type()->full_name()),
425
+ "field", upper_name);
426
+ printer->Indent();
427
+ printer->Print(
428
+ "this.add$$Value($number$, value);\n",
429
+ "number", number.str());
430
+ printer->Outdent();
431
+ printer->Print("};\n"
432
+ "\n");
433
+
434
+ printer->Print("\n"
435
+ "/**\n"
436
+ " * Returns the array of values in the $name$ field.\n",
437
+ "name", field->name());
438
+ printer->Print(
439
+ " * @return {!Array.<$opt$$type$>} The values in the field.\n"
440
+ " */\n",
441
+ "opt", type_is_primitive ? "" : "!",
442
+ "type", type);
443
+ printer->Print("$prefix$.prototype.$field$Array = function() {\n",
444
+ "prefix", JsFullName(field->containing_type()->file(),
445
+ field->containing_type()->full_name()),
446
+ "field", field->camelcase_name());
447
+ printer->Indent();
448
+ printer->Print(
449
+ "return /** @type {!Array.<$opt$$type$>} */ (",
450
+ "type", type,
451
+ "opt", type_is_primitive ? "" : "!");
452
+ printer->Print(
453
+ "this.array$$Values($number$));"
454
+ "\n",
455
+ "number", number.str());
456
+ printer->Outdent();
457
+ printer->Print("};\n"
458
+ "\n");
459
+ }
460
+
461
+ // has
462
+ printer->Print("\n"
463
+ "/**\n"
464
+ " * @return {boolean} Whether the $name$ field has a value.\n"
465
+ " */\n",
466
+ "name", field->name());
467
+ printer->Print("$prefix$.prototype.has$field$ = function() {\n",
468
+ "prefix", JsFullName(field->containing_type()->file(),
469
+ field->containing_type()->full_name()),
470
+ "field", upper_name);
471
+ printer->Indent();
472
+ printer->Print("return this.has$$Value($number$);\n",
473
+ "number", number.str());
474
+ printer->Outdent();
475
+ printer->Print("};\n"
476
+ "\n");
477
+
478
+ // count
479
+ printer->Print(
480
+ "\n"
481
+ "/**\n"
482
+ " * @return {number} The number of values in the $name$ field.\n"
483
+ " */\n",
484
+ "name", field->name());
485
+ printer->Print("$prefix$.prototype.$field$Count = function() {\n",
486
+ "prefix", JsFullName(field->containing_type()->file(),
487
+ field->containing_type()->full_name()),
488
+ "field", field->camelcase_name());
489
+ printer->Indent();
490
+ printer->Print("return this.count$$Values($number$);\n",
491
+ "number", number.str());
492
+ printer->Outdent();
493
+ printer->Print("};\n"
494
+ "\n");
495
+
496
+ // clear
497
+ printer->Print("\n"
498
+ "/**\n"
499
+ " * Clears the values in the $name$ field.\n"
500
+ " */\n",
501
+ "name", field->name());
502
+ printer->Print("$prefix$.prototype.clear$field$ = function() {\n",
503
+ "prefix", JsFullName(field->containing_type()->file(),
504
+ field->containing_type()->full_name()),
505
+ "field", upper_name);
506
+ printer->Indent();
507
+ printer->Print("this.clear$$Field($number$);\n",
508
+ "number", number.str());
509
+ printer->Outdent();
510
+ printer->Print("};\n");
511
+ }
512
+
513
+ void CodeGenerator::GenEnumDescriptor(
514
+ const google::protobuf::EnumDescriptor *enum_desc,
515
+ google::protobuf::io::Printer *printer) {
516
+ printer->Print("\n"
517
+ "\n"
518
+ "/**\n"
519
+ " * Enumeration $name$.\n"
520
+ " * @enum {number}\n"
521
+ " */\n",
522
+ "name", enum_desc->name());
523
+ printer->Print("$name$ = {\n",
524
+ "name", JsFullName(enum_desc->file(),
525
+ enum_desc->full_name()));
526
+ printer->Indent();
527
+ for (int i = 0; i < enum_desc->value_count(); ++i) {
528
+ std::string format = "$key$: $value$,\n";
529
+ if (i == enum_desc->value_count() - 1) {
530
+ format = "$key$: $value$\n";
531
+ }
532
+ std::ostringstream number;
533
+ number << enum_desc->value(i)->number();
534
+ printer->Print(format.c_str(),
535
+ "key", enum_desc->value(i)->name(),
536
+ "value", number.str());
537
+ }
538
+ printer->Outdent();
539
+ printer->Print("};\n"
540
+ "\n"
541
+ "\n");
542
+ }
543
+
544
+ void CodeGenerator::GenDescriptorMetadata(
545
+ const google::protobuf::Descriptor *message,
546
+ google::protobuf::io::Printer *printer) {
547
+ printer->Print("\n"
548
+ "\n"
549
+ "goog.proto2.Message.set$$Metadata($name$, {\n",
550
+ "name", JsFullName(message->file(),
551
+ message->full_name()));
552
+ printer->Indent();
553
+ printer->Print("0: {\n");
554
+ printer->Indent();
555
+ printer->Print("name: '$name$',\n",
556
+ "name", message->name());
557
+ if (message->containing_type() != NULL) {
558
+ printer->Print("containingType: $type$,\n",
559
+ "type",
560
+ JsFullName(message->containing_type()->file(),
561
+ message->containing_type()->full_name()));
562
+ }
563
+ printer->Print("fullName: '$fullname$'\n",
564
+ "fullname", message->full_name());
565
+ printer->Outdent();
566
+ if (message->field_count() > 0) {
567
+ printer->Print("},\n");
568
+ } else {
569
+ printer->Print("}\n");
570
+ }
571
+ // fields
572
+ for (int i = 0; i < message->field_count(); ++i) {
573
+ CodeGenerator::GenFieldDescriptorMetadata(
574
+ message->field(i),
575
+ printer);
576
+ if (i != message->field_count() - 1) {
577
+ printer->Print(",\n");
578
+ } else {
579
+ printer->Print("\n");
580
+ }
581
+ }
582
+ printer->Outdent();
583
+ printer->Print("});\n");
584
+
585
+ // nested messages (recursively process)
586
+ for (int i = 0; i < message->nested_type_count(); ++i) {
587
+ CodeGenerator::GenDescriptorMetadata(
588
+ message->nested_type(i),
589
+ printer);
590
+ }
591
+ }
592
+
593
+ void CodeGenerator::GenFieldDescriptorMetadata(
594
+ const google::protobuf::FieldDescriptor *field,
595
+ google::protobuf::io::Printer *printer) {
596
+ std::ostringstream number;
597
+ number << field->number();
598
+
599
+ std::ostringstream default_value;
600
+ std::string js_type;
601
+ bool as_number = field->options().GetExtension(jstype);
602
+ if (field->type() == google::protobuf::FieldDescriptor::TYPE_DOUBLE) {
603
+ js_type = "DOUBLE";
604
+ default_value << field->default_value_double();
605
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_FLOAT) {
606
+ js_type = "FLOAT";
607
+ default_value << field->default_value_float();
608
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_INT64) {
609
+ js_type = "INT64";
610
+ if (as_number) {
611
+ default_value << field->default_value_int64();
612
+ } else {
613
+ default_value << "'" << field->default_value_int64() << "'";
614
+ }
615
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_UINT64) {
616
+ js_type = "UINT64";
617
+ if (as_number) {
618
+ default_value << field->default_value_uint64();
619
+ } else {
620
+ default_value << "'" << field->default_value_uint64() << "'";
621
+ }
622
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_INT32) {
623
+ js_type = "INT32";
624
+ default_value << field->default_value_uint32();
625
+ } else if (
626
+ field->type() == google::protobuf::FieldDescriptor::TYPE_FIXED64) {
627
+ js_type = "FIXED64";
628
+ if (as_number) {
629
+ default_value << field->default_value_uint64();
630
+ } else {
631
+ default_value << "'" << field->default_value_uint64() << "'";
632
+ }
633
+ } else if (
634
+ field->type() == google::protobuf::FieldDescriptor::TYPE_FIXED32) {
635
+ js_type = "FIXED32";
636
+ default_value << field->default_value_uint32();
637
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) {
638
+ js_type = "BOOL";
639
+ default_value << field->default_value_bool();
640
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
641
+ js_type = "STRING";
642
+ default_value << "'" << field->default_value_string() << "'";
643
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_GROUP) {
644
+ js_type = "GROUP";
645
+ } else if (
646
+ field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
647
+ js_type = "MESSAGE";
648
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES) {
649
+ js_type = "BYTES";
650
+ default_value << "'" << field->default_value_string() << "'";
651
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_UINT32) {
652
+ js_type = "UINT32";
653
+ default_value << field->default_value_uint32();
654
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_ENUM) {
655
+ js_type = "ENUM";
656
+
657
+ default_value << JsFullName(field->enum_type()->file(),
658
+ field->enum_type()->full_name() + "." +
659
+ field->default_value_enum()->name());
660
+ } else if (
661
+ field->type() == google::protobuf::FieldDescriptor::TYPE_SFIXED32) {
662
+ js_type = "SFIXED32";
663
+ default_value << field->default_value_int32();
664
+ } else if (
665
+ field->type() == google::protobuf::FieldDescriptor::TYPE_SFIXED64) {
666
+ js_type = "SFIXED64";
667
+ if (as_number) {
668
+ default_value << field->default_value_int64();
669
+ } else {
670
+ default_value << "'" << field->default_value_int64() << "'";
671
+ }
672
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_SINT32) {
673
+ js_type = "SINT32";
674
+ default_value << field->default_value_int32();
675
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_SINT64) {
676
+ js_type = "SINT64";
677
+ if (as_number) {
678
+ default_value << field->default_value_int64();
679
+ } else {
680
+ default_value << "'" << field->default_value_int64() << "'";
681
+ }
682
+ }
683
+
684
+ std::string js_object;
685
+ if (field->type() == google::protobuf::FieldDescriptor::TYPE_BOOL) {
686
+ js_object = "Boolean";
687
+ } else if (
688
+ field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES ||
689
+ field->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
690
+ ((field->type() == google::protobuf::FieldDescriptor::TYPE_INT64 ||
691
+ field->type() == google::protobuf::FieldDescriptor::TYPE_UINT64 ||
692
+ field->type() == google::protobuf::FieldDescriptor::TYPE_SINT64 ||
693
+ field->type() == google::protobuf::FieldDescriptor::TYPE_FIXED64 ||
694
+ field->type() == google::protobuf::FieldDescriptor::TYPE_SFIXED64) &&
695
+ !as_number)) {
696
+ js_object = "String";
697
+ } else if (
698
+ field->type() == google::protobuf::FieldDescriptor::TYPE_GROUP ||
699
+ field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
700
+ js_object = JsFullName(field->message_type()->file(),
701
+ field->message_type()->full_name());
702
+ } else if (field->type() == google::protobuf::FieldDescriptor::TYPE_ENUM) {
703
+ js_object = JsFullName(field->enum_type()->file(),
704
+ field->enum_type()->full_name());
705
+ } else {
706
+ js_object = "Number";
707
+ }
708
+
709
+ printer->Print("$number$: {\n",
710
+ "number", number.str());
711
+ printer->Indent();
712
+ printer->Print("name: '$name$',\n",
713
+ "name", field->name());
714
+ if (field->is_repeated()) {
715
+ printer->Print("repeated: true,\n");
716
+ }
717
+ printer->Print("fieldType: goog.proto2.Message.FieldType.$js_type$,\n",
718
+ "js_type", js_type);
719
+ if (field->has_default_value() ||
720
+ field->type() == google::protobuf::FieldDescriptor::TYPE_ENUM) {
721
+ printer->Print("defaultValue: $default$,\n",
722
+ "default", default_value.str());
723
+ }
724
+ printer->Print("type: $type$\n",
725
+ "type", js_object);
726
+ printer->Outdent();
727
+ printer->Print("}");
728
+ }
729
+
730
+ } // namespace js
731
+ } // namespace protobuf
732
+ } // namespace sg