Merge "Update MessageNano#toString() to return mostly valid TextFormat."
diff --git a/Android.mk b/Android.mk
index 56419db..c977d3c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -16,6 +16,8 @@
 
 LOCAL_PATH := $(call my-dir)
 
+IGNORED_WARNINGS := -Wno-sign-compare -Wno-unused-parameter -Wno-sign-promo
+
 CC_LITE_SRC_FILES := \
     src/google/protobuf/stubs/common.cc                              \
     src/google/protobuf/stubs/once.cc                                \
@@ -227,7 +229,7 @@
 #
 #LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE)
 
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI
+LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
 
 # These are the minimum versions and don't need to be update.
 ifeq ($(TARGET_ARCH),arm)
@@ -293,7 +295,7 @@
 #
 #LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE)
 
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI
+LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
 
 # These are the minimum versions and don't need to be update.
 ifeq ($(TARGET_ARCH),arm)
@@ -319,7 +321,7 @@
     external/zlib \
     $(LOCAL_PATH)/src
 
-LOCAL_CFLAGS := -frtti
+LOCAL_CFLAGS := -frtti $(IGNORED_WARNINGS)
 LOCAL_SDK_VERSION := 14
 LOCAL_NDK_STL_VARIANT := gnustl_static
 
@@ -349,6 +351,8 @@
 LOCAL_STATIC_LIBRARIES += libz
 LOCAL_LDLIBS := -lpthread
 
+LOCAL_CFLAGS := $(IGNORED_WARNINGS)
+
 include $(BUILD_HOST_EXECUTABLE)
 
 # To test java proto params build rules.
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 0000000..066774d
--- /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> 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> T getExtension(Extension<T> extension) {
+        return WireFormatNano.getExtension(extension, unknownFieldData);
+    }
+
+    /**
+     * Sets the value of the specified extension of this message.
+     */
+    public <T> void setExtension(Extension<T> extension, T value) {
+        if (unknownFieldData == null) {
+            unknownFieldData = new ArrayList<UnknownFieldData>();
+        }
+        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 0885cdb..0cf8416 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 @@
  * @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 @@
      * 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 4e9fe0a..bdc51c4 100644
--- a/src/google/protobuf/compiler/javanano/javanano_file.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_file.cc
@@ -177,9 +177,7 @@
   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 63f8955..901870f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -139,16 +139,21 @@
     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 @@
     "}\n",
     "classname", descriptor_->name());
 
-  if (params_.store_unknown_fields()) {
-    printer->Print(
-        "\n"
-        "private java.util.List<com.google.protobuf.nano.UnknownFieldData>\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 @@
     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> T getExtension(com.google.protobuf.nano.Extension<T> extension) {\n"
-      "  return com.google.protobuf.nano.WireFormatNano.getExtension(\n"
-      "      extension, unknownFieldData);\n"
-      "}\n"
-      "\n"
-      "public <T> void setExtension(com.google.protobuf.nano.Extension<T> extension, T value) {\n"
-      "  if (unknownFieldData == null) {\n"
-      "    unknownFieldData =\n"
-      "        new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n"
-      "  }\n"
-      "  com.google.protobuf.nano.WireFormatNano.setExtension(\n"
-      "      extension, value, unknownFieldData);\n"
-      "}\n");
-  }
   GenerateMessageSerializationMethods(printer);
   GenerateMergeFromMethods(printer);
   GenerateParseFromMethods(printer);
@@ -265,38 +244,28 @@
   }
 
   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);
-  }
-
-  if (params_.store_unknown_fields()) {
+  // Rely on the parent implementation of getSerializedSize if there are no fields to
+  // serialize in this MessageNano.
+  if (descriptor_->field_count() != 0) {
     printer->Print(
-      "size += com.google.protobuf.nano.WireFormatNano.computeWireSize(unknownFieldData);\n");
-  }
+      "\n"
+      "@Override\n"
+      "public int getSerializedSize() {\n"
+      "  int size = super.getSerializedSize();\n");
+    printer->Indent();
 
-  printer->Outdent();
-  printer->Print(
-    "  cachedSize = size;\n"
-    "  return size;\n"
-    "}\n");
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "  cachedSize = size;\n"
+      "  return size;\n"
+      "}\n");
+  }
 }
 
 void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index dcbb0d4..e5f6161 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -521,7 +521,7 @@
   bool ReadStringFallback(string* buffer, int size);
 
   // Return the size of the buffer.
-  int BufferSize() const;
+  uint32 BufferSize() const;
 
   static const int kDefaultTotalBytesLimit = 64 << 20;  // 64MB
 
@@ -1031,7 +1031,7 @@
   return extension_factory_;
 }
 
-inline int CodedInputStream::BufferSize() const {
+inline uint32 CodedInputStream::BufferSize() const {
   return buffer_end_ - buffer_;
 }
 
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index d7b2c30..3f0d7f8 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -222,7 +222,7 @@
 }
 
 template <typename CType, enum WireFormatLite::FieldType DeclaredType>
-inline bool WireFormatLite::ReadRepeatedPrimitive(int tag_size,
+inline bool WireFormatLite::ReadRepeatedPrimitive(int, // tag_size, unused
                                                uint32 tag,
                                                io::CodedInputStream* input,
                                                RepeatedField<CType>* values) {