1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <algorithm> 36#include <google/protobuf/stubs/hash.h> 37#include <google/protobuf/compiler/javanano/javanano_message.h> 38#include <google/protobuf/compiler/javanano/javanano_enum.h> 39#include <google/protobuf/compiler/javanano/javanano_extension.h> 40#include <google/protobuf/compiler/javanano/javanano_helpers.h> 41#include <google/protobuf/stubs/strutil.h> 42#include <google/protobuf/io/printer.h> 43#include <google/protobuf/io/coded_stream.h> 44#include <google/protobuf/wire_format.h> 45#include <google/protobuf/descriptor.pb.h> 46 47namespace google { 48namespace protobuf { 49namespace compiler { 50namespace javanano { 51 52using internal::WireFormat; 53using internal::WireFormatLite; 54 55namespace { 56 57struct FieldOrderingByNumber { 58 inline bool operator()(const FieldDescriptor* a, 59 const FieldDescriptor* b) const { 60 return a->number() < b->number(); 61 } 62}; 63 64// Sort the fields of the given Descriptor by number into a new[]'d array 65// and return it. 66const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { 67 const FieldDescriptor** fields = 68 new const FieldDescriptor*[descriptor->field_count()]; 69 for (int i = 0; i < descriptor->field_count(); i++) { 70 fields[i] = descriptor->field(i); 71 } 72 sort(fields, fields + descriptor->field_count(), 73 FieldOrderingByNumber()); 74 return fields; 75} 76 77} // namespace 78 79// =================================================================== 80 81MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params) 82 : params_(params), 83 descriptor_(descriptor), 84 field_generators_(descriptor, params) { 85} 86 87MessageGenerator::~MessageGenerator() {} 88 89void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { 90 // Generate static members for all nested types. 91 for (int i = 0; i < descriptor_->nested_type_count(); i++) { 92 // TODO(kenton): Reuse MessageGenerator objects? 93 if (IsMapEntry(descriptor_->nested_type(i))) continue; 94 MessageGenerator(descriptor_->nested_type(i), params_) 95 .GenerateStaticVariables(printer); 96 } 97} 98 99void MessageGenerator::GenerateStaticVariableInitializers( 100 io::Printer* printer) { 101 // Generate static member initializers for all nested types. 102 for (int i = 0; i < descriptor_->nested_type_count(); i++) { 103 // TODO(kenton): Reuse MessageGenerator objects? 104 if (IsMapEntry(descriptor_->nested_type(i))) continue; 105 MessageGenerator(descriptor_->nested_type(i), params_) 106 .GenerateStaticVariableInitializers(printer); 107 } 108} 109 110void MessageGenerator::Generate(io::Printer* printer) { 111 if (!params_.store_unknown_fields() && 112 (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) { 113 GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the " 114 "'store_unknown_fields' generator option is 'true'\n"; 115 } 116 117 const string& file_name = descriptor_->file()->name(); 118 bool is_own_file = 119 params_.java_multiple_files(file_name) 120 && descriptor_->containing_type() == NULL; 121 122 if (is_own_file) { 123 // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below) 124 // may have the same names as constants in the nested classes. This causes Java warnings, but 125 // is not fatal, so we suppress those warnings here in the top-most class declaration. 126 printer->Print( 127 "\n" 128 "@SuppressWarnings(\"hiding\")\n" 129 "public final class $classname$ extends\n", 130 "classname", descriptor_->name()); 131 } else { 132 printer->Print( 133 "\n" 134 "public static final class $classname$ extends\n", 135 "classname", descriptor_->name()); 136 } 137 if (params_.store_unknown_fields() && params_.parcelable_messages()) { 138 printer->Print( 139 " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>", 140 "classname", descriptor_->name()); 141 } else if (params_.store_unknown_fields()) { 142 printer->Print( 143 " com.google.protobuf.nano.ExtendableMessageNano<$classname$>", 144 "classname", descriptor_->name()); 145 } else if (params_.parcelable_messages()) { 146 printer->Print( 147 " com.google.protobuf.nano.android.ParcelableMessageNano"); 148 } else { 149 printer->Print( 150 " com.google.protobuf.nano.MessageNano"); 151 } 152 if (params_.generate_clone()) { 153 printer->Print(" implements java.lang.Cloneable {\n"); 154 } else { 155 printer->Print(" {\n"); 156 } 157 printer->Indent(); 158 159 if (params_.parcelable_messages()) { 160 printer->Print( 161 "\n" 162 "// Used by Parcelable\n" 163 "@SuppressWarnings({\"unused\"})\n" 164 "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n" 165 " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n" 166 " $classname$>($classname$.class);\n", 167 "classname", descriptor_->name()); 168 } 169 170 // Nested types and extensions 171 for (int i = 0; i < descriptor_->extension_count(); i++) { 172 ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); 173 } 174 175 for (int i = 0; i < descriptor_->enum_type_count(); i++) { 176 EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer); 177 } 178 179 for (int i = 0; i < descriptor_->nested_type_count(); i++) { 180 if (IsMapEntry(descriptor_->nested_type(i))) continue; 181 MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); 182 } 183 184 // oneof 185 map<string, string> vars; 186 vars["message_name"] = descriptor_->name(); 187 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { 188 const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); 189 vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc); 190 vars["oneof_capitalized_name"] = 191 UnderscoresToCapitalizedCamelCase(oneof_desc); 192 vars["oneof_index"] = SimpleItoa(oneof_desc->index()); 193 // Oneof Constants 194 for (int j = 0; j < oneof_desc->field_count(); j++) { 195 const FieldDescriptor* field = oneof_desc->field(j); 196 vars["number"] = SimpleItoa(field->number()); 197 vars["cap_field_name"] = ToUpper(field->name()); 198 printer->Print(vars, 199 "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n"); 200 } 201 // oneofCase_ and oneof_ 202 printer->Print(vars, 203 "private int $oneof_name$Case_ = 0;\n" 204 "private java.lang.Object $oneof_name$_;\n"); 205 printer->Print(vars, 206 "public int get$oneof_capitalized_name$Case() {\n" 207 " return this.$oneof_name$Case_;\n" 208 "}\n"); 209 // Oneof clear 210 printer->Print(vars, 211 "public $message_name$ clear$oneof_capitalized_name$() {\n" 212 " this.$oneof_name$Case_ = 0;\n" 213 " this.$oneof_name$_ = null;\n" 214 " return this;\n" 215 "}\n"); 216 } 217 218 // Lazy initialization of otherwise static final fields can help prevent the 219 // class initializer from being generated. We want to prevent it because it 220 // stops ProGuard from inlining any methods in this class into call sites and 221 // therefore reducing the method count. However, extensions are best kept as 222 // public static final fields with initializers, so with their existence we 223 // won't bother with lazy initialization. 224 bool lazy_init = descriptor_->extension_count() == 0; 225 226 // Empty array 227 if (lazy_init) { 228 printer->Print( 229 "\n" 230 "private static volatile $classname$[] _emptyArray;\n" 231 "public static $classname$[] emptyArray() {\n" 232 " // Lazily initializes the empty array\n" 233 " if (_emptyArray == null) {\n" 234 " synchronized (\n" 235 " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n" 236 " if (_emptyArray == null) {\n" 237 " _emptyArray = new $classname$[0];\n" 238 " }\n" 239 " }\n" 240 " }\n" 241 " return _emptyArray;\n" 242 "}\n", 243 "classname", descriptor_->name()); 244 } else { 245 printer->Print( 246 "\n" 247 "private static final $classname$[] EMPTY_ARRAY = {};\n" 248 "public static $classname$[] emptyArray() {\n" 249 " return EMPTY_ARRAY;\n" 250 "}\n", 251 "classname", descriptor_->name()); 252 } 253 254 // Integers for bit fields 255 int totalInts = (field_generators_.total_bits() + 31) / 32; 256 if (totalInts > 0) { 257 printer->Print("\n"); 258 for (int i = 0; i < totalInts; i++) { 259 printer->Print("private int $bit_field_name$;\n", 260 "bit_field_name", GetBitFieldName(i)); 261 } 262 } 263 264 // Fields and maybe their default values 265 for (int i = 0; i < descriptor_->field_count(); i++) { 266 printer->Print("\n"); 267 PrintFieldComment(printer, descriptor_->field(i)); 268 field_generators_.get(descriptor_->field(i)).GenerateMembers( 269 printer, lazy_init); 270 } 271 272 // Constructor, with lazy init code if needed 273 if (lazy_init && field_generators_.saved_defaults_needed()) { 274 printer->Print( 275 "\n" 276 "private static volatile boolean _classInitialized;\n" 277 "\n" 278 "public $classname$() {\n" 279 " // Lazily initializes the field defaults\n" 280 " if (!_classInitialized) {\n" 281 " synchronized (\n" 282 " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n" 283 " if (!_classInitialized) {\n", 284 "classname", descriptor_->name()); 285 printer->Indent(); 286 printer->Indent(); 287 printer->Indent(); 288 printer->Indent(); 289 for (int i = 0; i < descriptor_->field_count(); i++) { 290 field_generators_.get(descriptor_->field(i)) 291 .GenerateInitSavedDefaultCode(printer); 292 } 293 printer->Outdent(); 294 printer->Outdent(); 295 printer->Outdent(); 296 printer->Outdent(); 297 printer->Print( 298 " _classInitialized = true;\n" 299 " }\n" 300 " }\n" 301 " }\n"); 302 if (params_.generate_clear()) { 303 printer->Print(" clear();\n"); 304 } 305 printer->Print("}\n"); 306 } else { 307 printer->Print( 308 "\n" 309 "public $classname$() {\n", 310 "classname", descriptor_->name()); 311 if (params_.generate_clear()) { 312 printer->Print(" clear();\n"); 313 } else { 314 printer->Indent(); 315 GenerateFieldInitializers(printer); 316 printer->Outdent(); 317 } 318 printer->Print("}\n"); 319 } 320 321 // Other methods in this class 322 323 GenerateClear(printer); 324 325 if (params_.generate_clone()) { 326 GenerateClone(printer); 327 } 328 329 if (params_.generate_equals()) { 330 GenerateEquals(printer); 331 GenerateHashCode(printer); 332 } 333 334 GenerateMessageSerializationMethods(printer); 335 GenerateMergeFromMethods(printer); 336 GenerateParseFromMethods(printer); 337 338 printer->Outdent(); 339 printer->Print("}\n"); 340} 341 342// =================================================================== 343 344void MessageGenerator:: 345GenerateMessageSerializationMethods(io::Printer* printer) { 346 // Rely on the parent implementations of writeTo() and getSerializedSize() 347 // if there are no fields to serialize in this message. 348 if (descriptor_->field_count() == 0) { 349 return; 350 } 351 352 scoped_array<const FieldDescriptor*> sorted_fields( 353 SortFieldsByNumber(descriptor_)); 354 355 printer->Print( 356 "\n" 357 "@Override\n" 358 "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n" 359 " throws java.io.IOException {\n"); 360 printer->Indent(); 361 362 // Output the fields in sorted order 363 for (int i = 0; i < descriptor_->field_count(); i++) { 364 GenerateSerializeOneField(printer, sorted_fields[i]); 365 } 366 367 // The parent implementation will write any unknown fields if necessary. 368 printer->Print( 369 "super.writeTo(output);\n"); 370 371 printer->Outdent(); 372 printer->Print("}\n"); 373 374 // The parent implementation will get the serialized size for unknown 375 // fields if necessary. 376 printer->Print( 377 "\n" 378 "@Override\n" 379 "protected int computeSerializedSize() {\n" 380 " int size = super.computeSerializedSize();\n"); 381 printer->Indent(); 382 383 for (int i = 0; i < descriptor_->field_count(); i++) { 384 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); 385 } 386 387 printer->Outdent(); 388 printer->Print( 389 " return size;\n" 390 "}\n"); 391} 392 393void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { 394 scoped_array<const FieldDescriptor*> sorted_fields( 395 SortFieldsByNumber(descriptor_)); 396 397 printer->Print( 398 "\n" 399 "@Override\n" 400 "public $classname$ mergeFrom(\n" 401 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" 402 " throws java.io.IOException {\n", 403 "classname", descriptor_->name()); 404 405 printer->Indent(); 406 if (HasMapField(descriptor_)) { 407 printer->Print( 408 "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n" 409 " com.google.protobuf.nano.MapFactories.getMapFactory();\n"); 410 } 411 412 printer->Print( 413 "while (true) {\n"); 414 printer->Indent(); 415 416 printer->Print( 417 "int tag = input.readTag();\n" 418 "switch (tag) {\n"); 419 printer->Indent(); 420 421 printer->Print( 422 "case 0:\n" // zero signals EOF / limit reached 423 " return this;\n" 424 "default: {\n"); 425 426 printer->Indent(); 427 if (params_.store_unknown_fields()) { 428 printer->Print( 429 "if (!storeUnknownField(input, tag)) {\n" 430 " return this;\n" 431 "}\n"); 432 } else { 433 printer->Print( 434 "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n" 435 " return this;\n" // it's an endgroup tag 436 "}\n"); 437 } 438 printer->Print("break;\n"); 439 printer->Outdent(); 440 printer->Print("}\n"); 441 442 for (int i = 0; i < descriptor_->field_count(); i++) { 443 const FieldDescriptor* field = sorted_fields[i]; 444 uint32 tag = WireFormatLite::MakeTag(field->number(), 445 WireFormat::WireTypeForFieldType(field->type())); 446 447 printer->Print( 448 "case $tag$: {\n", 449 "tag", SimpleItoa(tag)); 450 printer->Indent(); 451 452 field_generators_.get(field).GenerateMergingCode(printer); 453 454 printer->Outdent(); 455 printer->Print( 456 " break;\n" 457 "}\n"); 458 459 if (field->is_packable()) { 460 // To make packed = true wire compatible, we generate parsing code from a 461 // packed version of this field regardless of field->options().packed(). 462 uint32 packed_tag = WireFormatLite::MakeTag(field->number(), 463 WireFormatLite::WIRETYPE_LENGTH_DELIMITED); 464 printer->Print( 465 "case $tag$: {\n", 466 "tag", SimpleItoa(packed_tag)); 467 printer->Indent(); 468 469 field_generators_.get(field).GenerateMergingCodeFromPacked(printer); 470 471 printer->Outdent(); 472 printer->Print( 473 " break;\n" 474 "}\n"); 475 } 476 } 477 478 printer->Outdent(); 479 printer->Outdent(); 480 printer->Outdent(); 481 printer->Print( 482 " }\n" // switch (tag) 483 " }\n" // while (true) 484 "}\n"); 485} 486 487void MessageGenerator:: 488GenerateParseFromMethods(io::Printer* printer) { 489 // Note: These are separate from GenerateMessageSerializationMethods() 490 // because they need to be generated even for messages that are optimized 491 // for code size. 492 printer->Print( 493 "\n" 494 "public static $classname$ parseFrom(byte[] data)\n" 495 " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n" 496 " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n" 497 "}\n" 498 "\n" 499 "public static $classname$ parseFrom(\n" 500 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" 501 " throws java.io.IOException {\n" 502 " return new $classname$().mergeFrom(input);\n" 503 "}\n", 504 "classname", descriptor_->name()); 505} 506 507void MessageGenerator::GenerateSerializeOneField( 508 io::Printer* printer, const FieldDescriptor* field) { 509 field_generators_.get(field).GenerateSerializationCode(printer); 510} 511 512void MessageGenerator::GenerateClear(io::Printer* printer) { 513 if (!params_.generate_clear()) { 514 return; 515 } 516 printer->Print( 517 "\n" 518 "public $classname$ clear() {\n", 519 "classname", descriptor_->name()); 520 printer->Indent(); 521 522 GenerateFieldInitializers(printer); 523 524 printer->Outdent(); 525 printer->Print( 526 " return this;\n" 527 "}\n"); 528} 529 530void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { 531 // Clear bit fields. 532 int totalInts = (field_generators_.total_bits() + 31) / 32; 533 for (int i = 0; i < totalInts; i++) { 534 printer->Print("$bit_field_name$ = 0;\n", 535 "bit_field_name", GetBitFieldName(i)); 536 } 537 538 // Call clear for all of the fields. 539 for (int i = 0; i < descriptor_->field_count(); i++) { 540 const FieldDescriptor* field = descriptor_->field(i); 541 field_generators_.get(field).GenerateClearCode(printer); 542 } 543 544 // Clear oneofs. 545 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { 546 printer->Print( 547 "clear$oneof_capitalized_name$();\n", 548 "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase( 549 descriptor_->oneof_decl(i))); 550 } 551 552 // Clear unknown fields. 553 if (params_.store_unknown_fields()) { 554 printer->Print("unknownFieldData = null;\n"); 555 } 556 printer->Print("cachedSize = -1;\n"); 557} 558 559void MessageGenerator::GenerateClone(io::Printer* printer) { 560 printer->Print( 561 "@Override\n" 562 "public $classname$ clone() {\n", 563 "classname", descriptor_->name()); 564 printer->Indent(); 565 566 printer->Print( 567 "$classname$ cloned;\n" 568 "try {\n" 569 " cloned = ($classname$) super.clone();\n" 570 "} catch (java.lang.CloneNotSupportedException e) {\n" 571 " throw new java.lang.AssertionError(e);\n" 572 "}\n", 573 "classname", descriptor_->name()); 574 575 for (int i = 0; i < descriptor_->field_count(); i++) { 576 field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer); 577 } 578 579 printer->Outdent(); 580 printer->Print( 581 " return cloned;\n" 582 "}\n" 583 "\n"); 584} 585 586void MessageGenerator::GenerateEquals(io::Printer* printer) { 587 // Don't override if there are no fields. We could generate an 588 // equals method that compares types, but often empty messages 589 // are used as namespaces. 590 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { 591 return; 592 } 593 594 printer->Print( 595 "\n" 596 "@Override\n" 597 "public boolean equals(Object o) {\n"); 598 printer->Indent(); 599 printer->Print( 600 "if (o == this) {\n" 601 " return true;\n" 602 "}\n" 603 "if (!(o instanceof $classname$)) {\n" 604 " return false;\n" 605 "}\n" 606 "$classname$ other = ($classname$) o;\n", 607 "classname", descriptor_->name()); 608 609 // Checking oneof case before checking each oneof field. 610 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { 611 const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); 612 printer->Print( 613 "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n" 614 " return false;\n" 615 "}\n", 616 "oneof_name", UnderscoresToCamelCase(oneof_desc)); 617 } 618 619 for (int i = 0; i < descriptor_->field_count(); i++) { 620 const FieldDescriptor* field = descriptor_->field(i); 621 field_generators_.get(field).GenerateEqualsCode(printer); 622 } 623 624 if (params_.store_unknown_fields()) { 625 printer->Print( 626 "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" 627 " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n" 628 "} else {\n" 629 " return unknownFieldData.equals(other.unknownFieldData);\n" 630 "}"); 631 } else { 632 printer->Print( 633 "return true;\n"); 634 } 635 636 printer->Outdent(); 637 printer->Print("}\n"); 638} 639 640void MessageGenerator::GenerateHashCode(io::Printer* printer) { 641 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { 642 return; 643 } 644 645 printer->Print( 646 "\n" 647 "@Override\n" 648 "public int hashCode() {\n"); 649 printer->Indent(); 650 651 printer->Print("int result = 17;\n"); 652 printer->Print("result = 31 * result + getClass().getName().hashCode();\n"); 653 for (int i = 0; i < descriptor_->field_count(); i++) { 654 const FieldDescriptor* field = descriptor_->field(i); 655 field_generators_.get(field).GenerateHashCodeCode(printer); 656 } 657 658 if (params_.store_unknown_fields()) { 659 printer->Print( 660 "result = 31 * result + \n" 661 " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n" 662 " unknownFieldData.hashCode());\n"); 663 } 664 665 printer->Print("return result;\n"); 666 667 printer->Outdent(); 668 printer->Print("}\n"); 669} 670 671// =================================================================== 672 673} // namespace javanano 674} // namespace compiler 675} // namespace protobuf 676} // namespace google 677