Home | History | Annotate | Download | only in javanano
      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 (at) google.com (Kenton Varda)
     32 //  Based on original Protocol Buffers design by
     33 //  Sanjay Ghemawat, Jeff Dean, and others.
     34 
     35 #include <map>
     36 #include <string>
     37 
     38 #include <google/protobuf/compiler/javanano/javanano_enum_field.h>
     39 #include <google/protobuf/stubs/common.h>
     40 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
     41 #include <google/protobuf/io/printer.h>
     42 #include <google/protobuf/wire_format.h>
     43 #include <google/protobuf/stubs/strutil.h>
     44 
     45 namespace google {
     46 namespace protobuf {
     47 namespace compiler {
     48 namespace javanano {
     49 
     50 namespace {
     51 
     52 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
     53 //   repeat code between this and the other field types.
     54 void SetEnumVariables(const Params& params,
     55     const FieldDescriptor* descriptor, map<string, string>* variables) {
     56   (*variables)["name"] =
     57     RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
     58   (*variables)["capitalized_name"] =
     59     RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
     60   (*variables)["number"] = SimpleItoa(descriptor->number());
     61   if (params.use_reference_types_for_primitives()
     62       && !params.reftypes_primitive_enums()
     63       && !descriptor->is_repeated()) {
     64     (*variables)["type"] = "java.lang.Integer";
     65     (*variables)["default"] = "null";
     66   } else {
     67     (*variables)["type"] = "int";
     68     (*variables)["default"] = DefaultValue(params, descriptor);
     69   }
     70   (*variables)["repeated_default"] =
     71       "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
     72   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
     73   (*variables)["tag_size"] = SimpleItoa(
     74       internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
     75   (*variables)["non_packed_tag"] = SimpleItoa(
     76       internal::WireFormatLite::MakeTag(descriptor->number(),
     77           internal::WireFormat::WireTypeForFieldType(descriptor->type())));
     78   (*variables)["message_name"] = descriptor->containing_type()->name();
     79   const EnumDescriptor* enum_type = descriptor->enum_type();
     80   (*variables)["message_type_intdef"] = "@"
     81       + ToJavaName(params, enum_type->name(), true,
     82           enum_type->containing_type(), enum_type->file());
     83 }
     84 
     85 void LoadEnumValues(const Params& params,
     86     const EnumDescriptor* enum_descriptor, vector<string>* canonical_values) {
     87   string enum_class_name = ClassName(params, enum_descriptor);
     88   for (int i = 0; i < enum_descriptor->value_count(); i++) {
     89     const EnumValueDescriptor* value = enum_descriptor->value(i);
     90     const EnumValueDescriptor* canonical_value =
     91         enum_descriptor->FindValueByNumber(value->number());
     92     if (value == canonical_value) {
     93       canonical_values->push_back(
     94           enum_class_name + "." + RenameJavaKeywords(value->name()));
     95     }
     96   }
     97 }
     98 
     99 void PrintCaseLabels(
    100     io::Printer* printer, const vector<string>& canonical_values) {
    101   for (int i = 0; i < canonical_values.size(); i++) {
    102     printer->Print(
    103       "  case $value$:\n",
    104       "value", canonical_values[i]);
    105   }
    106 }
    107 
    108 }  // namespace
    109 
    110 // ===================================================================
    111 
    112 EnumFieldGenerator::
    113 EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
    114   : FieldGenerator(params), descriptor_(descriptor) {
    115   SetEnumVariables(params, descriptor, &variables_);
    116   LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
    117 }
    118 
    119 EnumFieldGenerator::~EnumFieldGenerator() {}
    120 
    121 void EnumFieldGenerator::
    122 GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
    123   if (params_.generate_intdefs()) {
    124     printer->Print(variables_, "$message_type_intdef$\n");
    125   }
    126   printer->Print(variables_, "public $type$ $name$;\n");
    127 
    128   if (params_.generate_has()) {
    129     printer->Print(variables_,
    130       "public boolean has$capitalized_name$;\n");
    131   }
    132 }
    133 
    134 void EnumFieldGenerator::
    135 GenerateClearCode(io::Printer* printer) const {
    136   printer->Print(variables_,
    137     "$name$ = $default$;\n");
    138 
    139   if (params_.generate_has()) {
    140     printer->Print(variables_,
    141       "has$capitalized_name$ = false;\n");
    142   }
    143 }
    144 
    145 void EnumFieldGenerator::
    146 GenerateMergingCode(io::Printer* printer) const {
    147   if (params_.store_unknown_fields()) {
    148     printer->Print("int initialPos = input.getPosition();\n");
    149   }
    150   printer->Print(variables_,
    151     "int value = input.readInt32();\n"
    152     "switch (value) {\n");
    153   PrintCaseLabels(printer, canonical_values_);
    154   printer->Print(variables_,
    155     "    this.$name$ = value;\n");
    156   if (params_.generate_has()) {
    157     printer->Print(variables_,
    158       "    has$capitalized_name$ = true;\n");
    159   }
    160   printer->Print(
    161     "    break;\n");
    162   if (params_.store_unknown_fields()) {
    163     // If storing unknown fields, store invalid values there.
    164     // This is consistent with full protobuf, but note that if a client writes
    165     // a new value to this field, both will be serialized on the wire, and
    166     // other clients which are aware of unknown fields will see the previous
    167     // value, not the new one.
    168     printer->Print(
    169       "  default:\n"
    170       "    input.rewindToPosition(initialPos);\n"
    171       "    storeUnknownField(input, tag);\n"
    172       "    break;\n");
    173   }
    174   printer->Print("}\n");
    175 }
    176 
    177 void EnumFieldGenerator::
    178 GenerateSerializationCode(io::Printer* printer) const {
    179   if (descriptor_->is_required() && !params_.generate_has()) {
    180     // Always serialize a required field if we don't have the 'has' signal.
    181     printer->Print(variables_,
    182       "output.writeInt32($number$, this.$name$);\n");
    183   } else {
    184     if (params_.generate_has()) {
    185       printer->Print(variables_,
    186         "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
    187     } else {
    188       printer->Print(variables_,
    189         "if (this.$name$ != $default$) {\n");
    190     }
    191     printer->Print(variables_,
    192       "  output.writeInt32($number$, this.$name$);\n"
    193       "}\n");
    194   }
    195 }
    196 
    197 void EnumFieldGenerator::
    198 GenerateSerializedSizeCode(io::Printer* printer) const {
    199   if (descriptor_->is_required() && !params_.generate_has()) {
    200     printer->Print(variables_,
    201       "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    202       "  .computeInt32Size($number$, this.$name$);\n");
    203   } else {
    204     if (params_.generate_has()) {
    205       printer->Print(variables_,
    206         "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
    207     } else {
    208       printer->Print(variables_,
    209         "if (this.$name$ != $default$) {\n");
    210     }
    211     printer->Print(variables_,
    212       "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    213       "    .computeInt32Size($number$, this.$name$);\n"
    214       "}\n");
    215   }
    216 }
    217 
    218 void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const {
    219   if (params_.use_reference_types_for_primitives()
    220         && !params_.reftypes_primitive_enums()) {
    221     printer->Print(variables_,
    222       "if (this.$name$ == null) {\n"
    223       "  if (other.$name$ != null) {\n"
    224       "    return false;\n"
    225       "  }\n"
    226       "} else if (!this.$name$.equals(other.$name$)) {\n"
    227       "  return false;"
    228       "}\n");
    229   } else {
    230     // We define equality as serialized form equality. If generate_has(),
    231     // then if the field value equals the default value in both messages,
    232     // but one's 'has' field is set and the other's is not, the serialized
    233     // forms are different and we should return false.
    234     printer->Print(variables_,
    235       "if (this.$name$ != other.$name$");
    236     if (params_.generate_has()) {
    237       printer->Print(variables_,
    238         "\n"
    239         "    || (this.$name$ == $default$\n"
    240         "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    241     }
    242     printer->Print(") {\n"
    243       "  return false;\n"
    244       "}\n");
    245   }
    246 }
    247 
    248 void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const {
    249   printer->Print(
    250     "result = 31 * result + ");
    251   if (params_.use_reference_types_for_primitives()
    252         && !params_.reftypes_primitive_enums()) {
    253     printer->Print(variables_,
    254       "(this.$name$ == null ? 0 : this.$name$)");
    255   } else {
    256     printer->Print(variables_,
    257       "this.$name$");
    258   }
    259   printer->Print(";\n");
    260 }
    261 
    262 // ===================================================================
    263 
    264 AccessorEnumFieldGenerator::
    265 AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
    266     const Params& params, int has_bit_index)
    267   : FieldGenerator(params), descriptor_(descriptor) {
    268   SetEnumVariables(params, descriptor, &variables_);
    269   LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
    270   SetBitOperationVariables("has", has_bit_index, &variables_);
    271 }
    272 
    273 AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
    274 
    275 void AccessorEnumFieldGenerator::
    276 GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
    277   printer->Print(variables_, "private int $name$_;\n");
    278   if (params_.generate_intdefs()) {
    279     printer->Print(variables_, "$message_type_intdef$\n");
    280   }
    281   printer->Print(variables_,
    282     "public int get$capitalized_name$() {\n"
    283     "  return $name$_;\n"
    284     "}\n"
    285     "public $message_name$ set$capitalized_name$(");
    286   if (params_.generate_intdefs()) {
    287     printer->Print(variables_,
    288       "\n"
    289       "    $message_type_intdef$ ");
    290   }
    291   printer->Print(variables_,
    292     "int value) {\n"
    293     "  $name$_ = value;\n"
    294     "  $set_has$;\n"
    295     "  return this;\n"
    296     "}\n"
    297     "public boolean has$capitalized_name$() {\n"
    298     "  return $get_has$;\n"
    299     "}\n"
    300     "public $message_name$ clear$capitalized_name$() {\n"
    301     "  $name$_ = $default$;\n"
    302     "  $clear_has$;\n"
    303     "  return this;\n"
    304     "}\n");
    305 }
    306 
    307 void AccessorEnumFieldGenerator::
    308 GenerateClearCode(io::Printer* printer) const {
    309   printer->Print(variables_,
    310     "$name$_ = $default$;\n");
    311 }
    312 
    313 void AccessorEnumFieldGenerator::
    314 GenerateMergingCode(io::Printer* printer) const {
    315   if (params_.store_unknown_fields()) {
    316     printer->Print("int initialPos = input.getPosition();\n");
    317   }
    318   printer->Print(variables_,
    319     "int value = input.readInt32();\n"
    320     "switch (value) {\n");
    321   PrintCaseLabels(printer, canonical_values_);
    322   printer->Print(variables_,
    323     "    $name$_ = value;\n"
    324     "    $set_has$;\n"
    325     "    break;\n");
    326   if (params_.store_unknown_fields()) {
    327     // If storing unknown fields, store invalid values there.
    328     // This is consistent with full protobuf, but note that if a client writes
    329     // a new value to this field, both will be serialized on the wire, and
    330     // other clients which are aware of unknown fields will see the previous
    331     // value, not the new one.
    332     printer->Print(
    333       "  default:\n"
    334       "    input.rewindToPosition(initialPos);\n"
    335       "    storeUnknownField(input, tag);\n"
    336       "    break;\n");
    337   }
    338   printer->Print("}\n");
    339 }
    340 
    341 void AccessorEnumFieldGenerator::
    342 GenerateSerializationCode(io::Printer* printer) const {
    343   printer->Print(variables_,
    344     "if ($get_has$) {\n"
    345     "  output.writeInt32($number$, $name$_);\n"
    346     "}\n");
    347 }
    348 
    349 void AccessorEnumFieldGenerator::
    350 GenerateSerializedSizeCode(io::Printer* printer) const {
    351   printer->Print(variables_,
    352     "if ($get_has$) {\n"
    353     "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    354     "    .computeInt32Size($number$, $name$_);\n"
    355     "}\n");
    356 }
    357 
    358 void AccessorEnumFieldGenerator::
    359 GenerateEqualsCode(io::Printer* printer) const {
    360   printer->Print(variables_,
    361     "if ($different_has$\n"
    362     "    || $name$_ != other.$name$_) {\n"
    363     "  return false;\n"
    364     "}\n");
    365 }
    366 
    367 void AccessorEnumFieldGenerator::
    368 GenerateHashCodeCode(io::Printer* printer) const {
    369   printer->Print(variables_,
    370     "result = 31 * result + $name$_;\n");
    371 }
    372 
    373 // ===================================================================
    374 
    375 RepeatedEnumFieldGenerator::
    376 RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
    377   : FieldGenerator(params), descriptor_(descriptor) {
    378   SetEnumVariables(params, descriptor, &variables_);
    379   LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
    380 }
    381 
    382 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
    383 
    384 void RepeatedEnumFieldGenerator::
    385 GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
    386   printer->Print(variables_,
    387     "public $type$[] $name$;\n");
    388 }
    389 
    390 void RepeatedEnumFieldGenerator::
    391 GenerateClearCode(io::Printer* printer) const {
    392   printer->Print(variables_,
    393     "$name$ = $repeated_default$;\n");
    394 }
    395 
    396 void RepeatedEnumFieldGenerator::
    397 GenerateMergingCode(io::Printer* printer) const {
    398   // First, figure out the maximum length of the array, then parse,
    399   // and finally copy the valid values to the field.
    400   printer->Print(variables_,
    401     "int length = com.google.protobuf.nano.WireFormatNano\n"
    402     "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
    403     "int[] validValues = new int[length];\n"
    404     "int validCount = 0;\n"
    405     "for (int i = 0; i < length; i++) {\n"
    406     "  if (i != 0) { // tag for first value already consumed.\n"
    407     "    input.readTag();\n"
    408     "  }\n");
    409   if (params_.store_unknown_fields()) {
    410     printer->Print("  int initialPos = input.getPosition();\n");
    411   }
    412   printer->Print(
    413     "  int value = input.readInt32();\n"
    414     "  switch (value) {\n");
    415   printer->Indent();
    416   PrintCaseLabels(printer, canonical_values_);
    417   printer->Outdent();
    418   printer->Print(variables_,
    419     "      validValues[validCount++] = value;\n"
    420     "      break;\n");
    421   if (params_.store_unknown_fields()) {
    422     // If storing unknown fields, store invalid values there.
    423     // This is consistent with full protobuf. Note that this can lead to very
    424     // strange behaviors if a value is serialized and reread, e.g. changes in
    425     // value ordering.
    426     printer->Print(
    427       "    default:\n"
    428       "      input.rewindToPosition(initialPos);\n"
    429       "      storeUnknownField(input, tag);\n"
    430       "      break;\n");
    431   }
    432   printer->Print(variables_,
    433     "  }\n"
    434     "}\n"
    435     "if (validCount != 0) {\n"
    436     "  int i = this.$name$ == null ? 0 : this.$name$.length;\n"
    437     "  if (i == 0 && validCount == validValues.length) {\n"
    438     "    this.$name$ = validValues;\n"
    439     "  } else {\n"
    440     "    int[] newArray = new int[i + validCount];\n"
    441     "    if (i != 0) {\n"
    442     "      java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    443     "    }\n"
    444     "    java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n"
    445     "    this.$name$ = newArray;\n"
    446     "  }\n"
    447     "}\n");
    448 }
    449 
    450 void RepeatedEnumFieldGenerator::
    451 GenerateMergingCodeFromPacked(io::Printer* printer) const {
    452   printer->Print(variables_,
    453     "int bytes = input.readRawVarint32();\n"
    454     "int limit = input.pushLimit(bytes);\n"
    455     "// First pass to compute array length.\n"
    456     "int arrayLength = 0;\n"
    457     "int startPos = input.getPosition();\n"
    458     "while (input.getBytesUntilLimit() > 0) {\n"
    459     "  switch (input.readInt32()) {\n");
    460   printer->Indent();
    461   PrintCaseLabels(printer, canonical_values_);
    462   printer->Outdent();
    463   printer->Print(variables_,
    464     "      arrayLength++;\n"
    465     "      break;\n"
    466     "  }\n"
    467     "}\n"
    468     "if (arrayLength != 0) {\n"
    469     "  input.rewindToPosition(startPos);\n"
    470     "  int i = this.$name$ == null ? 0 : this.$name$.length;\n"
    471     "  int[] newArray = new int[i + arrayLength];\n"
    472     "  if (i != 0) {\n"
    473     "    java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    474     "  }\n"
    475     "  while (input.getBytesUntilLimit() > 0) {\n");
    476   if (params_.store_unknown_fields()) {
    477     printer->Print("    int initialPos = input.getPosition();\n");
    478   }
    479   printer->Print(variables_,
    480     "    int value = input.readInt32();\n"
    481     "    switch (value) {\n");
    482   printer->Indent();
    483   printer->Indent();
    484   PrintCaseLabels(printer, canonical_values_);
    485   printer->Outdent();
    486   printer->Outdent();
    487   printer->Print(variables_,
    488     "        newArray[i++] = value;\n"
    489     "        break;\n");
    490   if (params_.store_unknown_fields()) {
    491     // If storing unknown fields, store invalid values there.
    492     // This is consistent with full protobuf. Note that this can lead to very
    493     // strange behaviors if a value is serialized and reread, e.g. changes in
    494     // value ordering.
    495     printer->Print(variables_,
    496       "      default:\n"
    497       "        input.rewindToPosition(initialPos);\n"
    498       "        storeUnknownField(input, $non_packed_tag$);\n"
    499       "        break;\n");
    500   }
    501   printer->Print(variables_,
    502     "    }\n"
    503     "  }\n"
    504     "  this.$name$ = newArray;\n"
    505     "}\n"
    506     "input.popLimit(limit);\n");
    507 }
    508 
    509 void RepeatedEnumFieldGenerator::
    510 GenerateRepeatedDataSizeCode(io::Printer* printer) const {
    511   // Creates a variable dataSize and puts the serialized size in there.
    512   printer->Print(variables_,
    513     "int dataSize = 0;\n"
    514     "for (int i = 0; i < this.$name$.length; i++) {\n"
    515     "  int element = this.$name$[i];\n"
    516     "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    517     "      .computeInt32SizeNoTag(element);\n"
    518     "}\n");
    519 }
    520 
    521 void RepeatedEnumFieldGenerator::
    522 GenerateSerializationCode(io::Printer* printer) const {
    523   printer->Print(variables_,
    524     "if (this.$name$ != null && this.$name$.length > 0) {\n");
    525   printer->Indent();
    526 
    527   if (descriptor_->options().packed()) {
    528     GenerateRepeatedDataSizeCode(printer);
    529     printer->Print(variables_,
    530       "output.writeRawVarint32($tag$);\n"
    531       "output.writeRawVarint32(dataSize);\n"
    532       "for (int i = 0; i < this.$name$.length; i++) {\n"
    533       "  output.writeRawVarint32(this.$name$[i]);\n"
    534       "}\n");
    535   } else {
    536     printer->Print(variables_,
    537       "for (int i = 0; i < this.$name$.length; i++) {\n"
    538       "  output.writeInt32($number$, this.$name$[i]);\n"
    539       "}\n");
    540   }
    541 
    542   printer->Outdent();
    543   printer->Print(variables_,
    544     "}\n");
    545 }
    546 
    547 void RepeatedEnumFieldGenerator::
    548 GenerateSerializedSizeCode(io::Printer* printer) const {
    549   printer->Print(variables_,
    550     "if (this.$name$ != null && this.$name$.length > 0) {\n");
    551   printer->Indent();
    552 
    553   GenerateRepeatedDataSizeCode(printer);
    554 
    555   printer->Print(
    556     "size += dataSize;\n");
    557   if (descriptor_->options().packed()) {
    558     printer->Print(variables_,
    559       "size += $tag_size$;\n"
    560       "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    561       "    .computeRawVarint32Size(dataSize);\n");
    562   } else {
    563     printer->Print(variables_,
    564       "size += $tag_size$ * this.$name$.length;\n");
    565   }
    566 
    567   printer->Outdent();
    568 
    569   printer->Print(
    570     "}\n");
    571 }
    572 
    573 void RepeatedEnumFieldGenerator::
    574 GenerateFixClonedCode(io::Printer* printer) const {
    575   printer->Print(variables_,
    576     "if (this.$name$ != null && this.$name$.length > 0) {\n"
    577     "  cloned.$name$ = this.$name$.clone();\n"
    578     "}\n");
    579 }
    580 
    581 void RepeatedEnumFieldGenerator::
    582 GenerateEqualsCode(io::Printer* printer) const {
    583   printer->Print(variables_,
    584     "if (!com.google.protobuf.nano.InternalNano.equals(\n"
    585     "    this.$name$, other.$name$)) {\n"
    586     "  return false;\n"
    587     "}\n");
    588 }
    589 
    590 void RepeatedEnumFieldGenerator::
    591 GenerateHashCodeCode(io::Printer* printer) const {
    592   printer->Print(variables_,
    593     "result = 31 * result\n"
    594     "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
    595 }
    596 
    597 }  // namespace javanano
    598 }  // namespace compiler
    599 }  // namespace protobuf
    600 }  // namespace google
    601