diff --git a/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java new file mode 100644 index 0000000000..066774d5bf --- /dev/null +++ b/java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2013 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf.nano; + +import java.util.ArrayList; +import java.util.List; + +/** + * Base class of those Protocol Buffer messages that need to store unknown fields, + * such as extensions. + */ +public abstract class ExtendableMessageNano extends MessageNano { + /** + * A container for fields unknown to the message, including extensions. Extension fields can + * can be accessed through the {@link getExtension()} and {@link setExtension()} methods. + */ + protected List unknownFieldData; + + @Override + public int getSerializedSize() { + int size = WireFormatNano.computeWireSize(unknownFieldData); + cachedSize = size; + return size; + } + + /** + * Gets the value stored in the specified extension of this message. + */ + public T getExtension(Extension extension) { + return WireFormatNano.getExtension(extension, unknownFieldData); + } + + /** + * Sets the value of the specified extension of this message. + */ + public void setExtension(Extension extension, T value) { + if (unknownFieldData == null) { + unknownFieldData = new ArrayList(); + } + WireFormatNano.setExtension(extension, value, unknownFieldData); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/google/protobuf/nano/MessageNano.java b/java/src/main/java/com/google/protobuf/nano/MessageNano.java index 8d4ec39e77..7eff153cb4 100644 --- a/java/src/main/java/com/google/protobuf/nano/MessageNano.java +++ b/java/src/main/java/com/google/protobuf/nano/MessageNano.java @@ -38,6 +38,8 @@ import java.io.IOException; * @author wink@google.com Wink Saville */ public abstract class MessageNano { + protected int cachedSize = -1; + /** * Get the number of bytes required to encode this message. * Returns the cached size or calls getSerializedSize which @@ -45,14 +47,24 @@ public abstract class MessageNano { * so the size is only computed once. If a member is modified * then this could be stale call getSerializedSize if in doubt. */ - abstract public int getCachedSize(); + public int getCachedSize() { + if (cachedSize < 0) { + // getSerializedSize sets cachedSize + getSerializedSize(); + } + return cachedSize; + } /** * Computes the number of bytes required to encode this message. * The size is cached and the cached result can be retrieved * using getCachedSize(). */ - abstract public int getSerializedSize(); + public int getSerializedSize() { + // This is overridden if the generated message has serialized fields. + cachedSize = 0; + return 0; + } /** * Serializes the message and writes it to {@code output}. This does not diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc index 4e9fe0a88f..bdc51c4e73 100644 --- a/src/google/protobuf/compiler/javanano/javanano_file.cc +++ b/src/google/protobuf/compiler/javanano/javanano_file.cc @@ -177,9 +177,7 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print( "\n" "@SuppressWarnings(\"hiding\")\n" - "public final class $classname$ {\n" - " \n" - " private $classname$() {}\n", + "public interface $classname$ {\n", "classname", classname_); printer->Indent(); diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 63f895531e..901870f186 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -139,16 +139,21 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( "\n" "@SuppressWarnings(\"hiding\")\n" - "public final class $classname$ extends\n" - " com.google.protobuf.nano.MessageNano {\n", + "public final class $classname$ extends\n", "classname", descriptor_->name()); } else { printer->Print( "\n" - "public static final class $classname$ extends\n" - " com.google.protobuf.nano.MessageNano {\n", + "public static final class $classname$ extends\n", "classname", descriptor_->name()); } + if (params_.store_unknown_fields()) { + printer->Print( + " com.google.protobuf.nano.ExtendableMessageNano {\n"); + } else { + printer->Print( + " com.google.protobuf.nano.MessageNano {\n"); + } printer->Indent(); printer->Print( "\n" @@ -159,13 +164,6 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n", "classname", descriptor_->name()); - if (params_.store_unknown_fields()) { - printer->Print( - "\n" - "private java.util.List\n" - " unknownFieldData;\n"); - } - // Nested types and extensions for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); @@ -203,25 +201,6 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateHashCode(printer); } - // If we have an extension range, generate accessors for extensions. - if (params_.store_unknown_fields() - && descriptor_->extension_range_count() > 0) { - printer->Print( - "\n" - "public T getExtension(com.google.protobuf.nano.Extension extension) {\n" - " return com.google.protobuf.nano.WireFormatNano.getExtension(\n" - " extension, unknownFieldData);\n" - "}\n" - "\n" - "public void setExtension(com.google.protobuf.nano.Extension extension, T value) {\n" - " if (unknownFieldData == null) {\n" - " unknownFieldData =\n" - " new java.util.ArrayList();\n" - " }\n" - " com.google.protobuf.nano.WireFormatNano.setExtension(\n" - " extension, value, unknownFieldData);\n" - "}\n"); - } GenerateMessageSerializationMethods(printer); GenerateMergeFromMethods(printer); GenerateParseFromMethods(printer); @@ -265,38 +244,28 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } printer->Outdent(); - printer->Print( - "}\n" - "\n" - "private int cachedSize;\n" - "@Override\n" - "public int getCachedSize() {\n" - " if (cachedSize < 0) {\n" - " // getSerializedSize sets cachedSize\n" - " getSerializedSize();\n" - " }\n" - " return cachedSize;\n" - "}\n" - "\n" - "@Override\n" - "public int getSerializedSize() {\n" - " int size = 0;\n"); - printer->Indent(); + printer->Print("}\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); - } + // Rely on the parent implementation of getSerializedSize if there are no fields to + // serialize in this MessageNano. + if (descriptor_->field_count() != 0) { + printer->Print( + "\n" + "@Override\n" + "public int getSerializedSize() {\n" + " int size = super.getSerializedSize();\n"); + printer->Indent(); - if (params_.store_unknown_fields()) { + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); + } + + printer->Outdent(); printer->Print( - "size += com.google.protobuf.nano.WireFormatNano.computeWireSize(unknownFieldData);\n"); + " cachedSize = size;\n" + " return size;\n" + "}\n"); } - - printer->Outdent(); - printer->Print( - " cachedSize = size;\n" - " return size;\n" - "}\n"); } void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {