aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ulas Kirazci <ulas@google.com>2013-03-14 16:44:33 -0700
committerGravatar Ulas Kirazci <ulas@google.com>2013-04-01 14:55:45 -0700
commit2337023fd9686b61f73f91588583685abf7d5773 (patch)
tree851d3eb1e4c9fa04a475446d3762cb32e03abeab
parentc991c16e92fb3ddb7d072f37665cf1ad25b9c4bc (diff)
Nano protobufs.
Like micro protobufs except: - No setter/getter/hazzer functions. - Has state is not available. Outputs all fields != their default. - CodedInputStream can only take byte[] (not InputStream). - Repeated fields are in arrays, not ArrayList or Vector. - Unset messages/groups are null, not "defaultInstance()". - Required fields are always serialized. To use: - Link libprotobuf-java-2.3.0-nano runtime. - Use LOCAL_PROTOC_OPTIMIZE_TYPE := nano Change-Id: I7429015b3c5f7f38b7be01eb2d4927f7a9999c80
-rw-r--r--Android.mk32
-rw-r--r--java/README.txt51
-rw-r--r--java/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java624
-rw-r--r--java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java910
-rw-r--r--java/src/main/java/com/google/protobuf/nano/InternalNano.java113
-rw-r--r--java/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java93
-rw-r--r--java/src/main/java/com/google/protobuf/nano/MessageNano.java128
-rw-r--r--java/src/main/java/com/google/protobuf/nano/WireFormatNano.java138
-rw-r--r--java/src/test/java/com/google/protobuf/NanoTest.java2104
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.cc96
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.h87
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc266
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.h94
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.cc102
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h98
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_file.cc251
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_file.h94
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc170
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.h72
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc404
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.h132
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc372
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.h92
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc216
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h95
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_params.h123
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc493
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h94
-rw-r--r--src/google/protobuf/unittest_import_nano.proto49
-rw-r--r--src/google/protobuf/unittest_nano.proto171
-rw-r--r--src/google/protobuf/unittest_recursive_nano.proto47
-rw-r--r--src/google/protobuf/unittest_simple_nano.proto52
-rw-r--r--src/google/protobuf/unittest_stringutf8_nano.proto41
33 files changed, 7904 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
index 889764dd..dd489223 100644
--- a/Android.mk
+++ b/Android.mk
@@ -106,6 +106,15 @@ COMPILER_SRC_FILES := \
src/google/protobuf/compiler/javamicro/javamicro_message.cc \
src/google/protobuf/compiler/javamicro/javamicro_message_field.cc \
src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc \
+ src/google/protobuf/compiler/javanano/javanano_enum.cc \
+ src/google/protobuf/compiler/javanano/javanano_enum_field.cc \
+ src/google/protobuf/compiler/javanano/javanano_field.cc \
+ src/google/protobuf/compiler/javanano/javanano_file.cc \
+ src/google/protobuf/compiler/javanano/javanano_generator.cc \
+ src/google/protobuf/compiler/javanano/javanano_helpers.cc \
+ src/google/protobuf/compiler/javanano/javanano_message.cc \
+ src/google/protobuf/compiler/javanano/javanano_message_field.cc \
+ src/google/protobuf/compiler/javanano/javanano_primitive_field.cc \
src/google/protobuf/compiler/python/python_generator.cc \
src/google/protobuf/io/coded_stream.cc \
src/google/protobuf/io/gzip_stream.cc \
@@ -121,6 +130,29 @@ COMPILER_SRC_FILES := \
src/google/protobuf/stubs/strutil.cc \
src/google/protobuf/stubs/substitute.cc
+# Java nano library (for device-side users)
+# =======================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libprotobuf-java-2.3.0-nano
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := 8
+
+LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Java nano library (for host-side users)
+# =======================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := host-libprotobuf-java-2.3.0-nano
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
# Java micro library (for device-side users)
# =======================================================
include $(CLEAR_VARS)
diff --git a/java/README.txt b/java/README.txt
index 8972792d..82c1ed53 100644
--- a/java/README.txt
+++ b/java/README.txt
@@ -260,6 +260,57 @@ This could be compiled using:
With the result will be com/example/TestMessages.java
+Nano version
+============================
+
+Nano is even smaller than micro, especially in the number of generated
+functions. It is like micro except:
+
+- No setter/getter/hazzer functions.
+- Has state is not available. Outputs all fields not equal to their
+ default. (See important implications below.)
+- CodedInputStreamMicro is renamed to CodedInputByteBufferNano and can
+ only take byte[] (not InputStream).
+- Similar rename from CodedOutputStreamMicro to
+ CodedOutputByteBufferNano.
+- Repeated fields are in arrays, not ArrayList or Vector.
+- Unset messages/groups are null, not an immutable empty default
+ instance.
+- Required fields are always serialized.
+- toByteArray(...) and mergeFrom(...) are now static functions of
+ MessageNano.
+- "bytes" are of java type byte[].
+
+IMPORTANT: If you have fields with defaults
+
+How fields with defaults are serialized has changed. Because we don't
+keep "has" state, any field equal to its default is assumed to be not
+set and therefore is not serialized. Consider the situation where we
+change the default value of a field. Senders compiled against an older
+version of the proto continue to match against the old default, and
+don't send values to the receiver even though the receiver assumes the
+new default value. Therefore, think carefully about the implications
+of changing the default value.
+
+IMPORTANT: If you have "bytes" fields with non-empty defaults
+
+Because the byte buffer is now of mutable type byte[], the default
+static final cannot be exposed through a public field. Each time a
+message's constructor or clear() function is called, the default value
+(kept in a private byte[]) is cloned. This causes a small memory
+penalty. This is not a problem if the field has no default or is an
+empty default.
+
+
+To use nano protobufs:
+
+- Link with the generated jar file
+ <protobuf-root>java/target/protobuf-java-2.3.0-nano.jar.
+- Invoke with --javanano_out, e.g.:
+
+../src/protoc '--javanano_out=java_package=src/test/proto/simple-data.proto|my_package,java_outer_classname=src/test/proto/simple-data.proto|OuterName:.' src/test/proto/simple-data.proto
+
+
Usage
=====
diff --git a/java/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/java/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
new file mode 100644
index 00000000..ed387882
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
@@ -0,0 +1,624 @@
+// 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.io.IOException;
+
+/**
+ * Reads and decodes protocol message fields.
+ *
+ * This class contains two kinds of methods: methods that read specific
+ * protocol message constructs and field types (e.g. {@link #readTag()} and
+ * {@link #readInt32()}) and methods that read low-level values (e.g.
+ * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading
+ * encoded protocol messages, you should use the former methods, but if you are
+ * reading some other format of your own design, use the latter.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class CodedInputByteBufferNano {
+ /**
+ * Create a new CodedInputStream wrapping the given byte array.
+ */
+ public static CodedInputByteBufferNano newInstance(final byte[] buf) {
+ return newInstance(buf, 0, buf.length);
+ }
+
+ /**
+ * Create a new CodedInputStream wrapping the given byte array slice.
+ */
+ public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off,
+ final int len) {
+ return new CodedInputByteBufferNano(buf, off, len);
+ }
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Attempt to read a field tag, returning zero if we have reached EOF.
+ * Protocol message parsers use this to read tags, since a protocol message
+ * may legally end wherever a tag occurs, and zero is not a valid tag number.
+ */
+ public int readTag() throws IOException {
+ if (isAtEnd()) {
+ lastTag = 0;
+ return 0;
+ }
+
+ lastTag = readRawVarint32();
+ if (lastTag == 0) {
+ // If we actually read zero, that's not a valid tag.
+ throw InvalidProtocolBufferNanoException.invalidTag();
+ }
+ return lastTag;
+ }
+
+ /**
+ * Verifies that the last call to readTag() returned the given tag value.
+ * This is used to verify that a nested group ended with the correct
+ * end tag.
+ *
+ * @throws InvalidProtocolBufferNanoException {@code value} does not match the
+ * last tag.
+ */
+ public void checkLastTagWas(final int value)
+ throws InvalidProtocolBufferNanoException {
+ if (lastTag != value) {
+ throw InvalidProtocolBufferNanoException.invalidEndTag();
+ }
+ }
+
+ /**
+ * Reads and discards a single field, given its tag value.
+ *
+ * @return {@code false} if the tag is an endgroup tag, in which case
+ * nothing is skipped. Otherwise, returns {@code true}.
+ */
+ public boolean skipField(final int tag) throws IOException {
+ switch (WireFormatNano.getTagWireType(tag)) {
+ case WireFormatNano.WIRETYPE_VARINT:
+ readInt32();
+ return true;
+ case WireFormatNano.WIRETYPE_FIXED64:
+ readRawLittleEndian64();
+ return true;
+ case WireFormatNano.WIRETYPE_LENGTH_DELIMITED:
+ skipRawBytes(readRawVarint32());
+ return true;
+ case WireFormatNano.WIRETYPE_START_GROUP:
+ skipMessage();
+ checkLastTagWas(
+ WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag),
+ WireFormatNano.WIRETYPE_END_GROUP));
+ return true;
+ case WireFormatNano.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormatNano.WIRETYPE_FIXED32:
+ readRawLittleEndian32();
+ return true;
+ default:
+ throw InvalidProtocolBufferNanoException.invalidWireType();
+ }
+ }
+
+ /**
+ * Reads and discards an entire message. This will read either until EOF
+ * or until an endgroup tag, whichever comes first.
+ */
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag)) {
+ return;
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ /** Read a {@code double} field value from the stream. */
+ public double readDouble() throws IOException {
+ return Double.longBitsToDouble(readRawLittleEndian64());
+ }
+
+ /** Read a {@code float} field value from the stream. */
+ public float readFloat() throws IOException {
+ return Float.intBitsToFloat(readRawLittleEndian32());
+ }
+
+ /** Read a {@code uint64} field value from the stream. */
+ public long readUInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ /** Read an {@code int64} field value from the stream. */
+ public long readInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ /** Read an {@code int32} field value from the stream. */
+ public int readInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ /** Read a {@code fixed64} field value from the stream. */
+ public long readFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ /** Read a {@code fixed32} field value from the stream. */
+ public int readFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ /** Read a {@code bool} field value from the stream. */
+ public boolean readBool() throws IOException {
+ return readRawVarint32() != 0;
+ }
+
+ /** Read a {@code string} field value from the stream. */
+ public String readString() throws IOException {
+ final int size = readRawVarint32();
+ if (size <= (bufferSize - bufferPos) && size > 0) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final String result = new String(buffer, bufferPos, size, "UTF-8");
+ bufferPos += size;
+ return result;
+ } else {
+ // Slow path: Build a byte array first then copy it.
+ return new String(readRawBytes(size), "UTF-8");
+ }
+ }
+
+ /** Read a {@code group} field value from the stream. */
+ public void readGroup(final MessageNano msg, final int fieldNumber)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ msg.mergeFrom(this);
+ checkLastTagWas(
+ WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ }
+
+ public void readMessage(final MessageNano msg)
+ throws IOException {
+ final int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferNanoException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ msg.mergeFrom(this);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ }
+
+ /** Read a {@code bytes} field value from the stream. */
+ public byte[] readBytes() throws IOException {
+ final int size = readRawVarint32();
+ if (size <= (bufferSize - bufferPos) && size > 0) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final byte[] result = new byte[size];
+ System.arraycopy(buffer, bufferPos, result, 0, size);
+ bufferPos += size;
+ return result;
+ } else {
+ // Slow path: Build a byte array first then copy it.
+ return readRawBytes(size);
+ }
+ }
+
+ /** Read a {@code uint32} field value from the stream. */
+ public int readUInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ /**
+ * Read an enum field value from the stream. Caller is responsible
+ * for converting the numeric value to an actual enum.
+ */
+ public int readEnum() throws IOException {
+ return readRawVarint32();
+ }
+
+ /** Read an {@code sfixed32} field value from the stream. */
+ public int readSFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ /** Read an {@code sfixed64} field value from the stream. */
+ public long readSFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ /** Read an {@code sint32} field value from the stream. */
+ public int readSInt32() throws IOException {
+ return decodeZigZag32(readRawVarint32());
+ }
+
+ /** Read an {@code sint64} field value from the stream. */
+ public long readSInt64() throws IOException {
+ return decodeZigZag64(readRawVarint64());
+ }
+
+ // =================================================================
+
+ /**
+ * Read a raw Varint from the stream. If larger than 32 bits, discard the
+ * upper bits.
+ */
+ public int readRawVarint32() throws IOException {
+ byte tmp = readRawByte();
+ if (tmp >= 0) {
+ return tmp;
+ }
+ int result = tmp & 0x7f;
+ if ((tmp = readRawByte()) >= 0) {
+ result |= tmp << 7;
+ } else {
+ result |= (tmp & 0x7f) << 7;
+ if ((tmp = readRawByte()) >= 0) {
+ result |= tmp << 14;
+ } else {
+ result |= (tmp & 0x7f) << 14;
+ if ((tmp = readRawByte()) >= 0) {
+ result |= tmp << 21;
+ } else {
+ result |= (tmp & 0x7f) << 21;
+ result |= (tmp = readRawByte()) << 28;
+ if (tmp < 0) {
+ // Discard upper 32 bits.
+ for (int i = 0; i < 5; i++) {
+ if (readRawByte() >= 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferNanoException.malformedVarint();
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /** Read a raw Varint from the stream. */
+ public long readRawVarint64() throws IOException {
+ int shift = 0;
+ long result = 0;
+ while (shift < 64) {
+ final byte b = readRawByte();
+ result |= (long)(b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ shift += 7;
+ }
+ throw InvalidProtocolBufferNanoException.malformedVarint();
+ }
+
+ /** Read a 32-bit little-endian integer from the stream. */
+ public int readRawLittleEndian32() throws IOException {
+ final byte b1 = readRawByte();
+ final byte b2 = readRawByte();
+ final byte b3 = readRawByte();
+ final byte b4 = readRawByte();
+ return ((b1 & 0xff) ) |
+ ((b2 & 0xff) << 8) |
+ ((b3 & 0xff) << 16) |
+ ((b4 & 0xff) << 24);
+ }
+
+ /** Read a 64-bit little-endian integer from the stream. */
+ public long readRawLittleEndian64() throws IOException {
+ final byte b1 = readRawByte();
+ final byte b2 = readRawByte();
+ final byte b3 = readRawByte();
+ final byte b4 = readRawByte();
+ final byte b5 = readRawByte();
+ final byte b6 = readRawByte();
+ final byte b7 = readRawByte();
+ final byte b8 = readRawByte();
+ return (((long)b1 & 0xff) ) |
+ (((long)b2 & 0xff) << 8) |
+ (((long)b3 & 0xff) << 16) |
+ (((long)b4 & 0xff) << 24) |
+ (((long)b5 & 0xff) << 32) |
+ (((long)b6 & 0xff) << 40) |
+ (((long)b7 & 0xff) << 48) |
+ (((long)b8 & 0xff) << 56);
+ }
+
+ /**
+ * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
+ * into values that can be efficiently encoded with varint. (Otherwise,
+ * negative values must be sign-extended to 64 bits to be varint encoded,
+ * thus always taking 10 bytes on the wire.)
+ *
+ * @param n An unsigned 32-bit integer, stored in a signed int because
+ * Java has no explicit unsigned support.
+ * @return A signed 32-bit integer.
+ */
+ public static int decodeZigZag32(final int n) {
+ return (n >>> 1) ^ -(n & 1);
+ }
+
+ /**
+ * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
+ * into values that can be efficiently encoded with varint. (Otherwise,
+ * negative values must be sign-extended to 64 bits to be varint encoded,
+ * thus always taking 10 bytes on the wire.)
+ *
+ * @param n An unsigned 64-bit integer, stored in a signed int because
+ * Java has no explicit unsigned support.
+ * @return A signed 64-bit integer.
+ */
+ public static long decodeZigZag64(final long n) {
+ return (n >>> 1) ^ -(n & 1);
+ }
+
+ // -----------------------------------------------------------------
+
+ private final byte[] buffer;
+ private int bufferStart;
+ private int bufferSize;
+ private int bufferSizeAfterLimit;
+ private int bufferPos;
+ private int lastTag;
+
+ /** The absolute position of the end of the current message. */
+ private int currentLimit = Integer.MAX_VALUE;
+
+ /** See setRecursionLimit() */
+ private int recursionDepth;
+ private int recursionLimit = DEFAULT_RECURSION_LIMIT;
+
+ /** See setSizeLimit() */
+ private int sizeLimit = DEFAULT_SIZE_LIMIT;
+
+ private static final int DEFAULT_RECURSION_LIMIT = 64;
+ private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
+
+ private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) {
+ this.buffer = buffer;
+ bufferStart = off;
+ bufferSize = off + len;
+ bufferPos = off;
+ }
+
+ /**
+ * Set the maximum message recursion depth. In order to prevent malicious
+ * messages from causing stack overflows, {@code CodedInputStream} limits
+ * how deeply messages may be nested. The default limit is 64.
+ *
+ * @return the old limit.
+ */
+ public int setRecursionLimit(final int limit) {
+ if (limit < 0) {
+ throw new IllegalArgumentException(
+ "Recursion limit cannot be negative: " + limit);
+ }
+ final int oldLimit = recursionLimit;
+ recursionLimit = limit;
+ return oldLimit;
+ }
+
+ /**
+ * Set the maximum message size. In order to prevent malicious
+ * messages from exhausting memory or causing integer overflows,
+ * {@code CodedInputStream} limits how large a message may be.
+ * The default limit is 64MB. You should set this limit as small
+ * as you can without harming your app's functionality. Note that
+ * size limits only apply when reading from an {@code InputStream}, not
+ * when constructed around a raw byte array.
+ * <p>
+ * If you want to read several messages from a single CodedInputStream, you
+ * could call {@link #resetSizeCounter()} after each one to avoid hitting the
+ * size limit.
+ *
+ * @return the old limit.
+ */
+ public int setSizeLimit(final int limit) {
+ if (limit < 0) {
+ throw new IllegalArgumentException(
+ "Size limit cannot be negative: " + limit);
+ }
+ final int oldLimit = sizeLimit;
+ sizeLimit = limit;
+ return oldLimit;
+ }
+
+ /**
+ * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
+ */
+ public void resetSizeCounter() {
+ }
+
+ /**
+ * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This
+ * is called when descending into a length-delimited embedded message.
+ *
+ * @return the old limit.
+ */
+ public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException {
+ if (byteLimit < 0) {
+ throw InvalidProtocolBufferNanoException.negativeSize();
+ }
+ byteLimit += bufferPos;
+ final int oldLimit = currentLimit;
+ if (byteLimit > oldLimit) {
+ throw InvalidProtocolBufferNanoException.truncatedMessage();
+ }
+ currentLimit = byteLimit;
+
+ recomputeBufferSizeAfterLimit();
+
+ return oldLimit;
+ }
+
+ private void recomputeBufferSizeAfterLimit() {
+ bufferSize += bufferSizeAfterLimit;
+ final int bufferEnd = bufferSize;
+ if (bufferEnd > currentLimit) {
+ // Limit is in current buffer.
+ bufferSizeAfterLimit = bufferEnd - currentLimit;
+ bufferSize -= bufferSizeAfterLimit;
+ } else {
+ bufferSizeAfterLimit = 0;
+ }
+ }
+
+ /**
+ * Discards the current limit, returning to the previous limit.
+ *
+ * @param oldLimit The old limit, as returned by {@code pushLimit}.
+ */
+ public void popLimit(final int oldLimit) {
+ currentLimit = oldLimit;
+ recomputeBufferSizeAfterLimit();
+ }
+
+ /**
+ * Returns the number of bytes to be read before the current limit.
+ * If no limit is set, returns -1.
+ */
+ public int getBytesUntilLimit() {
+ if (currentLimit == Integer.MAX_VALUE) {
+ return -1;
+ }
+
+ final int currentAbsolutePosition = bufferPos;
+ return currentLimit - currentAbsolutePosition;
+ }
+
+ /**
+ * Returns true if the stream has reached the end of the input. This is the
+ * case if either the end of the underlying input source has been reached or
+ * if the stream has reached a limit created using {@link #pushLimit(int)}.
+ */
+ public boolean isAtEnd() {
+ return bufferPos == bufferSize;
+ }
+
+ /**
+ * Get current position in buffer relative to beginning offset.
+ */
+ public int getPosition() {
+ return bufferPos - bufferStart;
+ }
+
+ /**
+ * Rewind to previous position. Cannot go forward.
+ */
+ public void rewindToPosition(int position) {
+ if (position > bufferPos - bufferStart) {
+ throw new IllegalArgumentException(
+ "Position " + position + " is beyond current " + (bufferPos - bufferStart));
+ }
+ if (position < 0) {
+ throw new IllegalArgumentException("Bad position " + position);
+ }
+ bufferPos = bufferStart + position;
+ }
+
+ /**
+ * Read one byte from the input.
+ *
+ * @throws InvalidProtocolBufferNanoException The end of the stream or the current
+ * limit was reached.
+ */
+ public byte readRawByte() throws IOException {
+ if (bufferPos == bufferSize) {
+ throw InvalidProtocolBufferNanoException.truncatedMessage();
+ }
+ return buffer[bufferPos++];
+ }
+
+ /**
+ * Read a fixed size of bytes from the input.
+ *
+ * @throws InvalidProtocolBufferNanoException The end of the stream or the current
+ * limit was reached.
+ */
+ public byte[] readRawBytes(final int size) throws IOException {
+ if (size < 0) {
+ throw InvalidProtocolBufferNanoException.negativeSize();
+ }
+
+ if (bufferPos + size > currentLimit) {
+ // Read to the end of the stream anyway.
+ skipRawBytes(currentLimit - bufferPos);
+ // Then fail.
+ throw InvalidProtocolBufferNanoException.truncatedMessage();
+ }
+
+ if (size <= bufferSize - bufferPos) {
+ // We have all the bytes we need already.
+ final byte[] bytes = new byte[size];
+ System.arraycopy(buffer, bufferPos, bytes, 0, size);
+ bufferPos += size;
+ return bytes;
+ } else {
+ throw InvalidProtocolBufferNanoException.truncatedMessage();
+ }
+ }
+
+ /**
+ * Reads and discards {@code size} bytes.
+ *
+ * @throws InvalidProtocolBufferNanoException The end of the stream or the current
+ * limit was reached.
+ */
+ public void skipRawBytes(final int size) throws IOException {
+ if (size < 0) {
+ throw InvalidProtocolBufferNanoException.negativeSize();
+ }
+
+ if (bufferPos + size > currentLimit) {
+ // Read to the end of the stream anyway.
+ skipRawBytes(currentLimit - bufferPos);
+ // Then fail.
+ throw InvalidProtocolBufferNanoException.truncatedMessage();
+ }
+
+ if (size <= bufferSize - bufferPos) {
+ // We have all the bytes we need already.
+ bufferPos += size;
+ } else {
+ throw InvalidProtocolBufferNanoException.truncatedMessage();
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
new file mode 100644
index 00000000..769bb19c
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
@@ -0,0 +1,910 @@
+// 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.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Encodes and writes protocol message fields.
+ *
+ * <p>This class contains two kinds of methods: methods that write specific
+ * protocol message constructs and field types (e.g. {@link #writeTag} and
+ * {@link #writeInt32}) and methods that write low-level values (e.g.
+ * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are
+ * writing encoded protocol messages, you should use the former methods, but if
+ * you are writing some other format of your own design, use the latter.
+ *
+ * <p>This class is totally unsynchronized.
+ *
+ * @author kneton@google.com Kenton Varda
+ */
+public final class CodedOutputByteBufferNano {
+ private final byte[] buffer;
+ private final int limit;
+ private int position;
+
+ private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
+ final int length) {
+ this.buffer = buffer;
+ position = offset;
+ limit = offset + length;
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} that writes directly to the given
+ * byte array. If more bytes are written than fit in the array,
+ * {@link OutOfSpaceException} will be thrown. Writing directly to a flat
+ * array is faster than writing to an {@code OutputStream}.
+ */
+ public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) {
+ return newInstance(flatArray, 0, flatArray.length);
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} that writes directly to the given
+ * byte array slice. If more bytes are written than fit in the slice,
+ * {@link OutOfSpaceException} will be thrown. Writing directly to a flat
+ * array is faster than writing to an {@code OutputStream}.
+ */
+ public static CodedOutputByteBufferNano newInstance(final byte[] flatArray,
+ final int offset,
+ final int length) {
+ return new CodedOutputByteBufferNano(flatArray, offset, length);
+ }
+
+ // -----------------------------------------------------------------
+
+ /** Write a {@code double} field, including tag, to the stream. */
+ public void writeDouble(final int fieldNumber, final double value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
+ writeDoubleNoTag(value);
+ }
+
+ /** Write a {@code float} field, including tag, to the stream. */
+ public void writeFloat(final int fieldNumber, final float value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
+ writeFloatNoTag(value);
+ }
+
+ /** Write a {@code uint64} field, including tag, to the stream. */
+ public void writeUInt64(final int fieldNumber, final long value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeUInt64NoTag(value);
+ }
+
+ /** Write an {@code int64} field, including tag, to the stream. */
+ public void writeInt64(final int fieldNumber, final long value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeInt64NoTag(value);
+ }
+
+ /** Write an {@code int32} field, including tag, to the stream. */
+ public void writeInt32(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeInt32NoTag(value);
+ }
+
+ /** Write a {@code fixed64} field, including tag, to the stream. */
+ public void writeFixed64(final int fieldNumber, final long value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
+ writeFixed64NoTag(value);
+ }
+
+ /** Write a {@code fixed32} field, including tag, to the stream. */
+ public void writeFixed32(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
+ writeFixed32NoTag(value);
+ }
+
+ /** Write a {@code bool} field, including tag, to the stream. */
+ public void writeBool(final int fieldNumber, final boolean value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeBoolNoTag(value);
+ }
+
+ /** Write a {@code string} field, including tag, to the stream. */
+ public void writeString(final int fieldNumber, final String value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ /** Write a {@code group} field, including tag, to the stream. */
+ public void writeGroup(final int fieldNumber, final MessageNano value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP);
+ writeGroupNoTag(value);
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
+ }
+
+ /** Write an embedded message field, including tag, to the stream. */
+ public void writeMessage(final int fieldNumber, final MessageNano value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ /** Write a {@code bytes} field, including tag, to the stream. */
+ public void writeBytes(final int fieldNumber, final byte[] value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ /** Write a {@code byte} field, including tag, to the stream. */
+ public void writeByteArray(final int fieldNumber, final byte[] value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value);
+ }
+
+
+ /** Write a {@code uint32} field, including tag, to the stream. */
+ public void writeUInt32(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeUInt32NoTag(value);
+ }
+
+ /**
+ * Write an enum field, including tag, to the stream. Caller is responsible
+ * for converting the enum value to its numeric value.
+ */
+ public void writeEnum(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeEnumNoTag(value);
+ }
+
+ /** Write an {@code sfixed32} field, including tag, to the stream. */
+ public void writeSFixed32(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
+ writeSFixed32NoTag(value);
+ }
+
+ /** Write an {@code sfixed64} field, including tag, to the stream. */
+ public void writeSFixed64(final int fieldNumber, final long value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
+ writeSFixed64NoTag(value);
+ }
+
+ /** Write an {@code sint32} field, including tag, to the stream. */
+ public void writeSInt32(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeSInt32NoTag(value);
+ }
+
+ /** Write an {@code sint64} field, including tag, to the stream. */
+ public void writeSInt64(final int fieldNumber, final long value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
+ writeSInt64NoTag(value);
+ }
+
+ /**
+ * Write a MessageSet extension field to the stream. For historical reasons,
+ * the wire format differs from normal fields.
+ */
+// public void writeMessageSetExtension(final int fieldNumber,
+// final MessageMicro value)
+// throws IOException {
+// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
+// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
+// writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
+// }
+
+ /**
+ * Write an unparsed MessageSet extension field to the stream. For
+ * historical reasons, the wire format differs from normal fields.
+ */
+// public void writeRawMessageSetExtension(final int fieldNumber,
+// final ByteStringMicro value)
+// throws IOException {
+// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
+// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
+// writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
+// }
+
+ // -----------------------------------------------------------------
+
+ /** Write a {@code double} field to the stream. */
+ public void writeDoubleNoTag(final double value) throws IOException {
+ writeRawLittleEndian64(Double.doubleToLongBits(value));
+ }
+
+ /** Write a {@code float} field to the stream. */
+ public void writeFloatNoTag(final float value) throws IOException {
+ writeRawLittleEndian32(Float.floatToIntBits(value));
+ }
+
+ /** Write a {@code uint64} field to the stream. */
+ public void writeUInt64NoTag(final long value) throws IOException {
+ writeRawVarint64(value);
+ }
+
+ /** Write an {@code int64} field to the stream. */
+ public void writeInt64NoTag(final long value) throws IOException {
+ writeRawVarint64(value);
+ }
+
+ /** Write an {@code int32} field to the stream. */
+ public void writeInt32NoTag(final int value) throws IOException {
+ if (value >= 0) {
+ writeRawVarint32(value);
+ } else {
+ // Must sign-extend.
+ writeRawVarint64(value);
+ }
+ }
+
+ /** Write a {@code fixed64} field to the stream. */
+ public void writeFixed64NoTag(final long value) throws IOException {
+ writeRawLittleEndian64(value);
+ }
+
+ /** Write a {@code fixed32} field to the stream. */
+ public void writeFixed32NoTag(final int value) throws IOException {
+ writeRawLittleEndian32(value);
+ }
+
+ /** Write a {@code bool} field to the stream. */
+ public void writeBoolNoTag(final boolean value) throws IOException {
+ writeRawByte(value ? 1 : 0);
+ }
+
+ /** Write a {@code string} field to the stream. */
+ public void writeStringNoTag(final String value) throws IOException {
+ // Unfortunately there does not appear to be any way to tell Java to encode
+ // UTF-8 directly into our buffer, so we have to let it create its own byte
+ // array and then copy.
+ final byte[] bytes = value.getBytes("UTF-8");
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** Write a {@code group} field to the stream. */
+ public void writeGroupNoTag(final MessageNano value) throws IOException {
+ value.writeTo(this);
+ }
+
+ /** Write an embedded message field to the stream. */
+ public void writeMessageNoTag(final MessageNano value) throws IOException {
+ writeRawVarint32(value.getCachedSize());
+ value.writeTo(this);
+ }
+
+ /** Write a {@code bytes} field to the stream. */
+ public void writeBytesNoTag(final byte[] value) throws IOException {
+ writeRawVarint32(value.length);
+ writeRawBytes(value);
+ }
+
+ /** Write a {@code byte[]} field to the stream. */
+ public void writeByteArrayNoTag(final byte [] value) throws IOException {
+ writeRawVarint32(value.length);
+ writeRawBytes(value);
+ }
+
+ /** Write a {@code uint32} field to the stream. */
+ public void writeUInt32NoTag(final int value) throws IOException {
+ writeRawVarint32(value);
+ }
+
+ /**
+ * Write an enum field to the stream. Caller is responsible
+ * for converting the enum value to its numeric value.
+ */
+ public void writeEnumNoTag(final int value) throws IOException {
+ writeRawVarint32(value);
+ }
+
+ /** Write an {@code sfixed32} field to the stream. */
+ public void writeSFixed32NoTag(final int value) throws IOException {
+ writeRawLittleEndian32(value);
+ }
+
+ /** Write an {@code sfixed64} field to the stream. */
+ public void writeSFixed64NoTag(final long value) throws IOException {
+ writeRawLittleEndian64(value);
+ }
+
+ /** Write an {@code sint32} field to the stream. */
+ public void writeSInt32NoTag(final int value) throws IOException {
+ writeRawVarint32(encodeZigZag32(value));
+ }
+
+ /** Write an {@code sint64} field to the stream. */
+ public void writeSInt64NoTag(final long value) throws IOException {
+ writeRawVarint64(encodeZigZag64(value));
+ }
+
+ // =================================================================
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code double} field, including tag.
+ */
+ public static int computeDoubleSize(final int fieldNumber,
+ final double value) {
+ return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code float} field, including tag.
+ */
+ public static int computeFloatSize(final int fieldNumber, final float value) {
+ return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint64} field, including tag.
+ */
+ public static int computeUInt64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int64} field, including tag.
+ */
+ public static int computeInt64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int32} field, including tag.
+ */
+ public static int computeInt32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed64} field, including tag.
+ */
+ public static int computeFixed64Size(final int fieldNumber,
+ final long value) {
+ return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed32} field, including tag.
+ */
+ public static int computeFixed32Size(final int fieldNumber,
+ final int value) {
+ return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bool} field, including tag.
+ */
+ public static int computeBoolSize(final int fieldNumber,
+ final boolean value) {
+ return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code string} field, including tag.
+ */
+ public static int computeStringSize(final int fieldNumber,
+ final String value) {
+ return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field, including tag.
+ */
+ public static int computeGroupSize(final int fieldNumber,
+ final MessageNano value) {
+ return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * embedded message field, including tag.
+ */
+ public static int computeMessageSize(final int fieldNumber,
+ final MessageNano value) {
+ return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field, including tag.
+ */
+ public static int computeBytesSize(final int fieldNumber,
+ final byte[] value) {
+ return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code byte[]} field, including tag.
+ */
+ public static int computeByteArraySize(final int fieldNumber,
+ final byte[] value) {
+ return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint32} field, including tag.
+ */
+ public static int computeUInt32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * enum field, including tag. Caller is responsible for converting the
+ * enum value to its numeric value.
+ */
+ public static int computeEnumSize(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed32} field, including tag.
+ */
+ public static int computeSFixed32Size(final int fieldNumber,
+ final int value) {
+ return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed64} field, including tag.
+ */
+ public static int computeSFixed64Size(final int fieldNumber,
+ final long value) {
+ return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint32} field, including tag.
+ */
+ public static int computeSInt32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint64} field, including tag.
+ */
+ public static int computeSInt64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * MessageSet extension to the stream. For historical reasons,
+ * the wire format differs from normal fields.
+ */
+// public static int computeMessageSetExtensionSize(
+// final int fieldNumber, final MessageMicro value) {
+// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
+// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
+// computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+// }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * unparsed MessageSet extension field to the stream. For
+ * historical reasons, the wire format differs from normal fields.
+ */
+// public static int computeRawMessageSetExtensionSize(
+// final int fieldNumber, final ByteStringMicro value) {
+// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
+// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
+// computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
+// }
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code double} field, including tag.
+ */
+ public static int computeDoubleSizeNoTag(final double value) {
+ return LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code float} field, including tag.
+ */
+ public static int computeFloatSizeNoTag(final float value) {
+ return LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint64} field, including tag.
+ */
+ public static int computeUInt64SizeNoTag(final long value) {
+ return computeRawVarint64Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int64} field, including tag.
+ */
+ public static int computeInt64SizeNoTag(final long value) {
+ return computeRawVarint64Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int32} field, including tag.
+ */
+ public static int computeInt32SizeNoTag(final int value) {
+ if (value >= 0) {
+ return computeRawVarint32Size(value);
+ } else {
+ // Must sign-extend.
+ return 10;
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed64} field.
+ */
+ public static int computeFixed64SizeNoTag(final long value) {
+ return LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed32} field.
+ */
+ public static int computeFixed32SizeNoTag(final int value) {
+ return LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bool} field.
+ */
+ public static int computeBoolSizeNoTag(final boolean value) {
+ return 1;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code string} field.
+ */
+ public static int computeStringSizeNoTag(final String value) {
+ try {
+ final byte[] bytes = value.getBytes("UTF-8");
+ return computeRawVarint32Size(bytes.length) +
+ bytes.length;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported.");
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field.
+ */
+ public static int computeGroupSizeNoTag(final MessageNano value) {
+ return value.getSerializedSize();
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an embedded
+ * message field.
+ */
+ public static int computeMessageSizeNoTag(final MessageNano value) {
+ final int size = value.getSerializedSize();
+ return computeRawVarint32Size(size) + size;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field.
+ */
+ public static int computeBytesSizeNoTag(final byte[] value) {
+ return computeRawVarint32Size(value.length) + value.length;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code byte[]} field.
+ */
+ public static int computeByteArraySizeNoTag(final byte[] value) {
+ return computeRawVarint32Size(value.length) + value.length;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint32} field.
+ */
+ public static int computeUInt32SizeNoTag(final int value) {
+ return computeRawVarint32Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an enum field.
+ * Caller is responsible for converting the enum value to its numeric value.
+ */
+ public static int computeEnumSizeNoTag(final int value) {
+ return computeRawVarint32Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed32} field.
+ */
+ public static int computeSFixed32SizeNoTag(final int value) {
+ return LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed64} field.
+ */
+ public static int computeSFixed64SizeNoTag(final long value) {
+ return LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint32} field.
+ */
+ public static int computeSInt32SizeNoTag(final int value) {
+ return computeRawVarint32Size(encodeZigZag32(value));
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint64} field.
+ */
+ public static int computeSInt64SizeNoTag(final long value) {
+ return computeRawVarint64Size(encodeZigZag64(value));
+ }
+
+ // =================================================================
+
+ /**
+ * If writing to a flat array, return the space left in the array.
+ * Otherwise, throws {@code UnsupportedOperationException}.
+ */
+ public int spaceLeft() {
+ return limit - position;
+ }
+
+ /**
+ * Verifies that {@link #spaceLeft()} returns zero. It's common to create
+ * a byte array that is exactly big enough to hold a message, then write to
+ * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()}
+ * after writing verifies that the message was actually as big as expected,
+ * which can help catch bugs.
+ */
+ public void checkNoSpaceLeft() {
+ if (spaceLeft() != 0) {
+ throw new IllegalStateException(
+ "Did not write as much data as expected.");
+ }
+ }
+
+ /**
+ * If you create a CodedOutputStream around a simple flat array, you must
+ * not attempt to write more bytes than the array has space. Otherwise,
+ * this exception will be thrown.
+ */
+ public static class OutOfSpaceException extends IOException {
+ private static final long serialVersionUID = -6947486886997889499L;
+
+ OutOfSpaceException(int position, int limit) {
+ super("CodedOutputStream was writing to a flat byte array and ran " +
+ "out of space (pos " + position + " limit " + limit + ").");
+ }
+ }
+
+ /** Write a single byte. */
+ public void writeRawByte(final byte value) throws IOException {
+ if (position == limit) {
+ // We're writing to a single buffer.
+ throw new OutOfSpaceException(position, limit);
+ }
+
+ buffer[position++] = value;
+ }
+
+ /** Write a single byte, represented by an integer value. */
+ public void writeRawByte(final int value) throws IOException {
+ writeRawByte((byte) value);
+ }
+
+ /** Write an array of bytes. */
+ public void writeRawBytes(final byte[] value) throws IOException {
+ writeRawBytes(value, 0, value.length);
+ }
+
+ /** Write part of an array of bytes. */
+ public void writeRawBytes(final byte[] value, int offset, int length)
+ throws IOException {
+ if (limit - position >= length) {
+ // We have room in the current buffer.
+ System.arraycopy(value, offset, buffer, position, length);
+ position += length;
+ } else {
+ // We're writing to a single buffer.
+ throw new OutOfSpaceException(position, limit);
+ }
+ }
+
+ /** Encode and write a tag. */
+ public void writeTag(final int fieldNumber, final int wireType)
+ throws IOException {
+ writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType));
+ }
+
+ /** Compute the number of bytes that would be needed to encode a tag. */
+ public static int computeTagSize(final int fieldNumber) {
+ return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0));
+ }
+
+ /**
+ * Encode and write a varint. {@code value} is treated as
+ * unsigned, so it won't be sign-extended if negative.
+ */
+ public void writeRawVarint32(int value) throws IOException {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ writeRawByte(value);
+ return;
+ } else {
+ writeRawByte((value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a varint.
+ * {@code value} is treated as unsigned, so it won't be sign-extended if
+ * negative.
+ */
+ public static int computeRawVarint32Size(final int value) {
+ if ((value & (0xffffffff << 7)) == 0) return 1;
+ if ((value & (0xffffffff << 14)) == 0) return 2;
+ if ((value & (0xffffffff << 21)) == 0) return 3;
+ if ((value & (0xffffffff << 28)) == 0) return 4;
+ return 5;
+ }
+
+ /** Encode and write a varint. */
+ public void writeRawVarint64(long value) throws IOException {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ writeRawByte((int)value);
+ return;
+ } else {
+ writeRawByte(((int)value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ }
+
+ /** Compute the number of bytes that would be needed to encode a varint. */
+ public static int computeRawVarint64Size(final long value) {
+ if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
+ if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
+ if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
+ if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
+ if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
+ if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
+ if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
+ if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
+ if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
+ return 10;
+ }
+
+ /** Write a little-endian 32-bit integer. */
+ public void writeRawLittleEndian32(final int value) throws IOException {
+ writeRawByte((value ) & 0xFF);
+ writeRawByte((value >> 8) & 0xFF);
+ writeRawByte((value >> 16) & 0xFF);
+ writeRawByte((value >> 24) & 0xFF);
+ }
+
+ public static final int LITTLE_ENDIAN_32_SIZE = 4;
+
+ /** Write a little-endian 64-bit integer. */
+ public void writeRawLittleEndian64(final long value) throws IOException {
+ writeRawByte((int)(value ) & 0xFF);
+ writeRawByte((int)(value >> 8) & 0xFF);
+ writeRawByte((int)(value >> 16) & 0xFF);
+ writeRawByte((int)(value >> 24) & 0xFF);
+ writeRawByte((int)(value >> 32) & 0xFF);
+ writeRawByte((int)(value >> 40) & 0xFF);
+ writeRawByte((int)(value >> 48) & 0xFF);
+ writeRawByte((int)(value >> 56) & 0xFF);
+ }
+
+ public static final int LITTLE_ENDIAN_64_SIZE = 8;
+
+ /**
+ * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
+ * into values that can be efficiently encoded with varint. (Otherwise,
+ * negative values must be sign-extended to 64 bits to be varint encoded,
+ * thus always taking 10 bytes on the wire.)
+ *
+ * @param n A signed 32-bit integer.
+ * @return An unsigned 32-bit integer, stored in a signed int because
+ * Java has no explicit unsigned support.
+ */
+ public static int encodeZigZag32(final int n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 31);
+ }
+
+ /**
+ * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
+ * into values that can be efficiently encoded with varint. (Otherwise,
+ * negative values must be sign-extended to 64 bits to be varint encoded,
+ * thus always taking 10 bytes on the wire.)
+ *
+ * @param n A signed 64-bit integer.
+ * @return An unsigned 64-bit integer, stored in a signed int because
+ * Java has no explicit unsigned support.
+ */
+ public static long encodeZigZag64(final long n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 63);
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/nano/InternalNano.java b/java/src/main/java/com/google/protobuf/nano/InternalNano.java
new file mode 100644
index 00000000..49309516
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -0,0 +1,113 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.io.UnsupportedEncodingException;
+
+/**
+ * The classes contained within are used internally by the Protocol Buffer
+ * library and generated message implementations. They are public only because
+ * those generated messages do not reside in the {@code protobuf} package.
+ * Others should not use this class directly.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class InternalNano {
+ /**
+ * Helper called by generated code to construct default values for string
+ * fields.
+ * <p>
+ * The protocol compiler does not actually contain a UTF-8 decoder -- it
+ * just pushes UTF-8-encoded text around without touching it. The one place
+ * where this presents a problem is when generating Java string literals.
+ * Unicode characters in the string literal would normally need to be encoded
+ * using a Unicode escape sequence, which would require decoding them.
+ * To get around this, protoc instead embeds the UTF-8 bytes into the
+ * generated code and leaves it to the runtime library to decode them.
+ * <p>
+ * It gets worse, though. If protoc just generated a byte array, like:
+ * new byte[] {0x12, 0x34, 0x56, 0x78}
+ * Java actually generates *code* which allocates an array and then fills
+ * in each value. This is much less efficient than just embedding the bytes
+ * directly into the bytecode. To get around this, we need another
+ * work-around. String literals are embedded directly, so protoc actually
+ * generates a string literal corresponding to the bytes. The easiest way
+ * to do this is to use the ISO-8859-1 character set, which corresponds to
+ * the first 256 characters of the Unicode range. Protoc can then use
+ * good old CEscape to generate the string.
+ * <p>
+ * So we have a string literal which represents a set of bytes which
+ * represents another string. This function -- stringDefaultValue --
+ * converts from the generated string to the string we actually want. The
+ * generated code calls this automatically.
+ */
+ public static final String stringDefaultValue(String bytes) {
+ try {
+ return new String(bytes.getBytes("ISO-8859-1"), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // This should never happen since all JVMs are required to implement
+ // both of the above character sets.
+ throw new IllegalStateException(
+ "Java VM does not support a standard character set.", e);
+ }
+ }
+
+ /**
+ * Helper called by generated code to construct default values for bytes
+ * fields.
+ * <p>
+ * This is a lot like {@link #stringDefaultValue}, but for bytes fields.
+ * In this case we only need the second of the two hacks -- allowing us to
+ * embed raw bytes as a string literal with ISO-8859-1 encoding.
+ */
+ public static final byte[] bytesDefaultValue(String bytes) {
+ try {
+ return bytes.getBytes("ISO-8859-1");
+ } catch (UnsupportedEncodingException e) {
+ // This should never happen since all JVMs are required to implement
+ // ISO-8859-1.
+ throw new IllegalStateException(
+ "Java VM does not support a standard character set.", e);
+ }
+ }
+
+ /**
+ * Helper function to convert a string into UTF-8 while turning the
+ * UnsupportedEncodingException to a RuntimeException.
+ */
+ public static final byte[] copyFromUtf8(final String text) {
+ try {
+ return text.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported?");
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java b/java/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java
new file mode 100644
index 00000000..ff0af9df
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java
@@ -0,0 +1,93 @@
+// 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.io.IOException;
+
+/**
+ * Thrown when a protocol message being parsed is invalid in some way,
+ * e.g. it contains a malformed varint or a negative byte length.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class InvalidProtocolBufferNanoException extends IOException {
+ private static final long serialVersionUID = -1616151763072450476L;
+
+ public InvalidProtocolBufferNanoException(final String description) {
+ super(description);
+ }
+
+ static InvalidProtocolBufferNanoException truncatedMessage() {
+ return new InvalidProtocolBufferNanoException(
+ "While parsing a protocol message, the input ended unexpectedly " +
+ "in the middle of a field. This could mean either than the " +
+ "input has been truncated or that an embedded message " +
+ "misreported its own length.");
+ }
+
+ static InvalidProtocolBufferNanoException negativeSize() {
+ return new InvalidProtocolBufferNanoException(
+ "CodedInputStream encountered an embedded string or message " +
+ "which claimed to have negative size.");
+ }
+
+ static InvalidProtocolBufferNanoException malformedVarint() {
+ return new InvalidProtocolBufferNanoException(
+ "CodedInputStream encountered a malformed varint.");
+ }
+
+ static InvalidProtocolBufferNanoException invalidTag() {
+ return new InvalidProtocolBufferNanoException(
+ "Protocol message contained an invalid tag (zero).");
+ }
+
+ static InvalidProtocolBufferNanoException invalidEndTag() {
+ return new InvalidProtocolBufferNanoException(
+ "Protocol message end-group tag did not match expected tag.");
+ }
+
+ static InvalidProtocolBufferNanoException invalidWireType() {
+ return new InvalidProtocolBufferNanoException(
+ "Protocol message tag had invalid wire type.");
+ }
+
+ static InvalidProtocolBufferNanoException recursionLimitExceeded() {
+ return new InvalidProtocolBufferNanoException(
+ "Protocol message had too many levels of nesting. May be malicious. " +
+ "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+ }
+
+ static InvalidProtocolBufferNanoException sizeLimitExceeded() {
+ return new InvalidProtocolBufferNanoException(
+ "Protocol message was too large. May be malicious. " +
+ "Use CodedInputStream.setSizeLimit() to increase the size limit.");
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/nano/MessageNano.java b/java/src/main/java/com/google/protobuf/nano/MessageNano.java
new file mode 100644
index 00000000..66080cc8
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/nano/MessageNano.java
@@ -0,0 +1,128 @@
+// 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.io.IOException;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * @author wink@google.com Wink Saville
+ */
+public abstract class MessageNano {
+ /**
+ * Get the number of bytes required to encode this message.
+ * Returns the cached size or calls getSerializedSize which
+ * sets the cached size. This is used internally when serializing
+ * 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();
+
+ /**
+ * 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();
+
+ /**
+ * Serializes the message and writes it to {@code output}. This does not
+ * flush or close the stream.
+ */
+ abstract public void writeTo(CodedOutputByteBufferNano output) throws java.io.IOException;
+
+ /**
+ * Parse {@code input} as a message of this type and merge it with the
+ * message being built.
+ */
+ abstract public MessageNano mergeFrom(final CodedInputByteBufferNano input) throws IOException;
+
+ /**
+ * Serialize to a byte array.
+ * @return byte array with the serialized data.
+ */
+ public static final byte[] toByteArray(MessageNano msg) {
+ final byte[] result = new byte[msg.getSerializedSize()];
+ toByteArray(msg, result, 0, result.length);
+ return result;
+ }
+
+ /**
+ * Serialize to a byte array starting at offset through length. The
+ * method getSerializedSize must have been called prior to calling
+ * this method so the proper length is know. If an attempt to
+ * write more than length bytes OutOfSpaceException will be thrown
+ * and if length bytes are not written then IllegalStateException
+ * is thrown.
+ * @return byte array with the serialized data.
+ */
+ public static final void toByteArray(MessageNano msg, byte [] data, int offset, int length) {
+ try {
+ final CodedOutputByteBufferNano output =
+ CodedOutputByteBufferNano.newInstance(data, offset, length);
+ msg.writeTo(output);
+ output.checkNoSpaceLeft();
+ } catch (IOException e) {
+ throw new RuntimeException("Serializing to a byte array threw an IOException "
+ + "(should never happen).");
+ }
+ }
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built.
+ */
+ public static final MessageNano mergeFrom(MessageNano msg, final byte[] data)
+ throws InvalidProtocolBufferNanoException {
+ return mergeFrom(msg, data, 0, data.length);
+ }
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built.
+ */
+ public static final MessageNano mergeFrom(MessageNano msg, final byte[] data, final int off,
+ final int len) throws InvalidProtocolBufferNanoException {
+ try {
+ final CodedInputByteBufferNano input =
+ CodedInputByteBufferNano.newInstance(data, off, len);
+ msg.mergeFrom(input);
+ input.checkLastTagWas(0);
+ return msg;
+ } catch (InvalidProtocolBufferNanoException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from a byte array threw an IOException (should "
+ + "never happen).");
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java b/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java
new file mode 100644
index 00000000..8fa36364
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/nano/WireFormatNano.java
@@ -0,0 +1,138 @@
+// 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.io.IOException;
+
+/**
+ * This class is used internally by the Protocol Buffer library and generated
+ * message implementations. It is public only because those generated messages
+ * do not reside in the {@code protobuf} package. Others should not use this
+ * class directly.
+ *
+ * This class contains constants and helper functions useful for dealing with
+ * the Protocol Buffer wire format.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class WireFormatNano {
+ // Do not allow instantiation.
+ private WireFormatNano() {}
+
+ static final int WIRETYPE_VARINT = 0;
+ static final int WIRETYPE_FIXED64 = 1;
+ static final int WIRETYPE_LENGTH_DELIMITED = 2;
+ static final int WIRETYPE_START_GROUP = 3;
+ static final int WIRETYPE_END_GROUP = 4;
+ static final int WIRETYPE_FIXED32 = 5;
+
+ static final int TAG_TYPE_BITS = 3;
+ static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
+
+ /** Given a tag value, determines the wire type (the lower 3 bits). */
+ static int getTagWireType(final int tag) {
+ return tag & TAG_TYPE_MASK;
+ }
+
+ /** Given a tag value, determines the field number (the upper 29 bits). */
+ public static int getTagFieldNumber(final int tag) {
+ return tag >>> TAG_TYPE_BITS;
+ }
+
+ /** Makes a tag value given a field number and wire type. */
+ static int makeTag(final int fieldNumber, final int wireType) {
+ return (fieldNumber << TAG_TYPE_BITS) | wireType;
+ }
+
+ // Field numbers for feilds in MessageSet wire format.
+ static final int MESSAGE_SET_ITEM = 1;
+ static final int MESSAGE_SET_TYPE_ID = 2;
+ static final int MESSAGE_SET_MESSAGE = 3;
+
+ // Tag numbers.
+ static final int MESSAGE_SET_ITEM_TAG =
+ makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
+ static final int MESSAGE_SET_ITEM_END_TAG =
+ makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
+ static final int MESSAGE_SET_TYPE_ID_TAG =
+ makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
+ static final int MESSAGE_SET_MESSAGE_TAG =
+ makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
+
+ public static final int EMPTY_INT_ARRAY[] = {};
+ public static final long EMPTY_LONG_ARRAY[] = {};
+ public static final float EMPTY_FLOAT_ARRAY[] = {};
+ public static final double EMPTY_DOUBLE_ARRAY[] = {};
+ public static final boolean EMPTY_BOOLEAN_ARRAY[] = {};
+ public static final String EMPTY_STRING_ARRAY[] = {};
+ public static final byte[] EMPTY_BYTES_ARRAY[] = {};
+ public static final byte[] EMPTY_BYTES = {};
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ public static boolean parseUnknownField(
+ final CodedInputByteBufferNano input,
+ final int tag) throws IOException {
+ return input.skipField(tag);
+ }
+
+ /**
+ * Computes the array length of a repeated field. We assume that in the common case repeated
+ * fields are contiguously serialized but we still correctly handle interspersed values of a
+ * repeated field (but with extra allocations).
+ *
+ * Rewinds to current input position before returning.
+ *
+ * @param input stream input, pointing to the byte after the first tag
+ * @param tag repeated field tag just read
+ * @return length of array
+ * @throws IOException
+ */
+ public static final int getRepeatedFieldArrayLength(
+ final CodedInputByteBufferNano input,
+ final int tag) throws IOException {
+ int arrayLength = 1;
+ int startPos = input.getPosition();
+ input.skipField(tag);
+ while (input.getBytesUntilLimit() > 0) {
+ int thisTag = input.readTag();
+ if (thisTag != tag) {
+ break;
+ }
+ input.skipField(tag);
+ arrayLength++;
+ }
+ input.rewindToPosition(startPos);
+ return arrayLength;
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java
new file mode 100644
index 00000000..85389d1f
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/NanoTest.java
@@ -0,0 +1,2104 @@
+// 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;
+
+import com.google.protobuf.nano.InternalNano;
+import com.google.protobuf.nano.MessageNano;
+import com.google.protobuf.nano.NanoOuterClass;
+import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
+import com.google.protobuf.nano.RecursiveMessageNano;
+import com.google.protobuf.nano.SimpleMessageNano;
+import com.google.protobuf.nano.UnittestImportNano;
+import com.google.protobuf.nano.CodedInputByteBufferNano;
+
+import junit.framework.TestCase;
+
+/**
+ * Test nano runtime.
+ *
+ * @author ulas@google.com Ulas Kirazci
+ */
+public class NanoTest extends TestCase {
+ public void setUp() throws Exception {
+ }
+
+ public void testSimpleMessageNano() throws Exception {
+ SimpleMessageNano msg = new SimpleMessageNano();
+ assertEquals(123, msg.d);
+ assertEquals(null, msg.nestedMsg);
+ assertEquals(SimpleMessageNano.BAZ, msg.defaultNestedEnum);
+
+ msg.d = 456;
+ assertEquals(456, msg.d);
+
+ SimpleMessageNano.NestedMessage nestedMsg = new SimpleMessageNano.NestedMessage();
+ nestedMsg.bb = 2;
+ assertEquals(2, nestedMsg.bb);
+ msg.nestedMsg = nestedMsg;
+ assertEquals(2, msg.nestedMsg.bb);
+
+ msg.defaultNestedEnum = SimpleMessageNano.BAR;
+ assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
+
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ SimpleMessageNano newMsg = SimpleMessageNano.parseFrom(result);
+ assertEquals(456, newMsg.d);
+ assertEquals(2, msg.nestedMsg.bb);
+ assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
+ }
+
+ public void testRecursiveMessageNano() throws Exception {
+ RecursiveMessageNano msg = new RecursiveMessageNano();
+ assertTrue(msg.repeatedRecursiveMessageNano.length == 0);
+
+ RecursiveMessageNano msg1 = new RecursiveMessageNano();
+ msg1.id = 1;
+ assertEquals(1, msg1.id);
+ RecursiveMessageNano msg2 = new RecursiveMessageNano();
+ msg2.id = 2;
+ RecursiveMessageNano msg3 = new RecursiveMessageNano();
+ msg3.id = 3;
+
+ RecursiveMessageNano.NestedMessage nestedMsg = new RecursiveMessageNano.NestedMessage();
+ nestedMsg.a = msg1;
+ assertEquals(1, nestedMsg.a.id);
+
+ msg.id = 0;
+ msg.nestedMessage = nestedMsg;
+ msg.optionalRecursiveMessageNano = msg2;
+ msg.repeatedRecursiveMessageNano = new RecursiveMessageNano[] { msg3 };
+
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 16);
+ assertEquals(result.length, msgSerializedSize);
+
+ RecursiveMessageNano newMsg = RecursiveMessageNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedRecursiveMessageNano.length);
+
+ assertEquals(0, newMsg.id);
+ assertEquals(1, newMsg.nestedMessage.a.id);
+ assertEquals(2, newMsg.optionalRecursiveMessageNano.id);
+ assertEquals(3, newMsg.repeatedRecursiveMessageNano[0].id);
+ }
+
+ public void testNanoRequiredInt32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.id = 123;
+ assertEquals(123, msg.id);
+ msg.clear().id = 456;
+ assertEquals(456, msg.id);
+ msg.clear();
+
+ msg.id = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.id);
+ }
+
+ public void testNanoOptionalInt32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalInt32 = 123;
+ assertEquals(123, msg.optionalInt32);
+ msg.clear()
+ .optionalInt32 = 456;
+ assertEquals(456, msg.optionalInt32);
+ msg.clear();
+
+ msg.optionalInt32 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalInt32);
+ }
+
+ public void testNanoOptionalInt64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalInt64 = 123;
+ assertEquals(123, msg.optionalInt64);
+ msg.clear()
+ .optionalInt64 = 456;
+ assertEquals(456, msg.optionalInt64);
+ msg.clear();
+ assertEquals(0, msg.optionalInt64);
+
+ msg.optionalInt64 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalInt64);
+ }
+
+ public void testNanoOptionalUint32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalUint32 = 123;
+ assertEquals(123, msg.optionalUint32);
+ msg.clear()
+ .optionalUint32 = 456;
+ assertEquals(456, msg.optionalUint32);
+ msg.clear();
+ assertEquals(0, msg.optionalUint32);
+
+ msg.optionalUint32 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalUint32);
+ }
+
+ public void testNanoOptionalUint64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalUint64 = 123;
+ assertEquals(123, msg.optionalUint64);
+ msg.clear()
+ .optionalUint64 = 456;
+ assertEquals(456, msg.optionalUint64);
+ msg.clear();
+ assertEquals(0, msg.optionalUint64);
+
+ msg.optionalUint64 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalUint64);
+ }
+
+ public void testNanoOptionalSint32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalSint32 = 123;
+ assertEquals(123, msg.optionalSint32);
+ msg.clear()
+ .optionalSint32 = 456;
+ assertEquals(456, msg.optionalSint32);
+ msg.clear();
+ assertEquals(0, msg.optionalSint32);
+
+ msg.optionalSint32 = -123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(-123, newMsg.optionalSint32);
+ }
+
+ public void testNanoOptionalSint64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalSint64 = 123;
+ assertEquals(123, msg.optionalSint64);
+ msg.clear()
+ .optionalSint64 = 456;
+ assertEquals(456, msg.optionalSint64);
+ msg.clear();
+ assertEquals(0, msg.optionalSint64);
+
+ msg.optionalSint64 = -123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(-123, newMsg.optionalSint64);
+ }
+
+ public void testNanoOptionalFixed32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalFixed32 = 123;
+ assertEquals(123, msg.optionalFixed32);
+ msg.clear()
+ .optionalFixed32 = 456;
+ assertEquals(456, msg.optionalFixed32);
+ msg.clear();
+ assertEquals(0, msg.optionalFixed32);
+
+ msg.optionalFixed32 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalFixed32);
+ }
+
+ public void testNanoOptionalFixed64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalFixed64 = 123;
+ assertEquals(123, msg.optionalFixed64);
+ msg.clear()
+ .optionalFixed64 = 456;
+ assertEquals(456, msg.optionalFixed64);
+ msg.clear();
+ assertEquals(0, msg.optionalFixed64);
+
+ msg.optionalFixed64 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 12);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalFixed64);
+ }
+
+ public void testNanoOptionalSfixed32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalSfixed32 = 123;
+ assertEquals(123, msg.optionalSfixed32);
+ msg.clear()
+ .optionalSfixed32 = 456;
+ assertEquals(456, msg.optionalSfixed32);
+ msg.clear();
+ assertEquals(0, msg.optionalSfixed32);
+
+ msg.optionalSfixed32 = 123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(123, newMsg.optionalSfixed32);
+ }
+
+ public void testNanoOptionalSfixed64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalSfixed64 = 123;
+ assertEquals(123, msg.optionalSfixed64);
+ msg.clear()
+ .optionalSfixed64 = 456;
+ assertEquals(456, msg.optionalSfixed64);
+ msg.clear();
+ assertEquals(0, msg.optionalSfixed64);
+
+ msg.optionalSfixed64 = -123;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 12);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(-123, newMsg.optionalSfixed64);
+ }
+
+ public void testNanoOptionalFloat() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalFloat = 123f;
+ assertTrue(123.0f == msg.optionalFloat);
+ msg.clear()
+ .optionalFloat = 456.0f;
+ assertTrue(456.0f == msg.optionalFloat);
+ msg.clear();
+ assertTrue(0.0f == msg.optionalFloat);
+
+ msg.optionalFloat = -123.456f;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(-123.456f == newMsg.optionalFloat);
+ }
+
+ public void testNanoOptionalDouble() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalDouble = 123;
+ assertTrue(123.0 == msg.optionalDouble);
+ msg.clear()
+ .optionalDouble = 456.0;
+ assertTrue(456.0 == msg.optionalDouble);
+ msg.clear();
+ assertTrue(0.0 == msg.optionalDouble);
+
+ msg.optionalDouble = -123.456;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 12);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(-123.456 == newMsg.optionalDouble);
+ }
+
+ public void testNanoOptionalBool() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalBool = true;
+ assertTrue(msg.optionalBool);
+ msg.clear()
+ .optionalBool = true;
+ assertTrue(msg.optionalBool);
+ msg.clear();
+ assertFalse(msg.optionalBool);
+
+ msg.optionalBool = true;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalBool);
+ }
+
+ public void testNanoOptionalString() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalString = "hello";
+ assertEquals("hello", msg.optionalString);
+ msg.clear();
+ assertTrue(msg.optionalString.isEmpty());
+ msg.clear()
+ .optionalString = "hello2";
+ assertEquals("hello2", msg.optionalString);
+ msg.clear();
+ assertTrue(msg.optionalString.isEmpty());
+
+ msg.optionalString = "bye";
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalString != null);
+ assertEquals("bye", newMsg.optionalString);
+ }
+
+ public void testNanoOptionalBytes() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertFalse(msg.optionalBytes.length > 0);
+ msg.optionalBytes = InternalNano.copyFromUtf8("hello");
+ assertTrue(msg.optionalBytes.length > 0);
+ assertEquals("hello", new String(msg.optionalBytes, "UTF-8"));
+ msg.clear();
+ assertFalse(msg.optionalBytes.length > 0);
+ msg.clear()
+ .optionalBytes = InternalNano.copyFromUtf8("hello");
+ assertTrue(msg.optionalBytes.length > 0);
+ msg.clear();
+ assertFalse(msg.optionalBytes.length > 0);
+
+ msg.optionalBytes = InternalNano.copyFromUtf8("bye");
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalBytes.length > 0);
+ assertEquals("bye", new String(newMsg.optionalBytes, "UTF-8"));
+ }
+
+ public void testNanoOptionalGroup() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ TestAllTypesNano.OptionalGroup grp = new TestAllTypesNano.OptionalGroup();
+ grp.a = 1;
+ assertFalse(msg.optionalGroup != null);
+ msg.optionalGroup = grp;
+ assertTrue(msg.optionalGroup != null);
+ assertEquals(1, msg.optionalGroup.a);
+ msg.clear();
+ assertFalse(msg.optionalGroup != null);
+ msg.clear()
+ .optionalGroup = new TestAllTypesNano.OptionalGroup();
+ msg.optionalGroup.a = 2;
+ assertTrue(msg.optionalGroup != null);
+ msg.clear();
+ assertFalse(msg.optionalGroup != null);
+
+ msg.optionalGroup = grp;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalGroup != null);
+ assertEquals(1, newMsg.optionalGroup.a);
+ }
+
+ public void testNanoOptionalNestedMessage() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ TestAllTypesNano.NestedMessage nestedMsg = new TestAllTypesNano.NestedMessage();
+ nestedMsg.bb = 1;
+ assertFalse(msg.optionalNestedMessage != null);
+ msg.optionalNestedMessage = nestedMsg;
+ assertTrue(msg.optionalNestedMessage != null);
+ assertEquals(1, msg.optionalNestedMessage.bb);
+ msg.clear();
+ assertFalse(msg.optionalNestedMessage != null);
+ msg.clear()
+ .optionalNestedMessage = new TestAllTypesNano.NestedMessage();
+ msg.optionalNestedMessage.bb = 2;
+ assertTrue(msg.optionalNestedMessage != null);
+ msg.clear();
+ assertFalse(msg.optionalNestedMessage != null);
+
+ msg.optionalNestedMessage = nestedMsg;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalNestedMessage != null);
+ assertEquals(1, newMsg.optionalNestedMessage.bb);
+ }
+
+ public void testNanoOptionalForeignMessage() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ NanoOuterClass.ForeignMessageNano nestedMsg = new NanoOuterClass.ForeignMessageNano();
+ nestedMsg.c = 1;
+ assertFalse(msg.optionalForeignMessage != null);
+ msg.optionalForeignMessage = nestedMsg;
+ assertTrue(msg.optionalForeignMessage != null);
+ assertEquals(1, msg.optionalForeignMessage.c);
+ msg.clear();
+ assertFalse(msg.optionalForeignMessage != null);
+ msg.clear()
+ .optionalForeignMessage = new NanoOuterClass.ForeignMessageNano();
+ msg.optionalForeignMessage.c = 2;
+ assertTrue(msg.optionalForeignMessage != null);
+ msg.clear();
+ assertFalse(msg.optionalForeignMessage != null);
+
+ msg.optionalForeignMessage = nestedMsg;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalForeignMessage != null);
+ assertEquals(1, newMsg.optionalForeignMessage.c);
+ }
+
+ public void testNanoOptionalImportMessage() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ UnittestImportNano.ImportMessageNano nestedMsg = new UnittestImportNano.ImportMessageNano();
+ nestedMsg.d = 1;
+ assertFalse(msg.optionalImportMessage != null);
+ msg.optionalImportMessage = nestedMsg;
+ assertTrue(msg.optionalImportMessage != null);
+ assertEquals(1, msg.optionalImportMessage.d);
+ msg.clear();
+ assertFalse(msg.optionalImportMessage != null);
+ msg.clear()
+ .optionalImportMessage = new UnittestImportNano.ImportMessageNano();
+ msg.optionalImportMessage.d = 2;
+ assertTrue(msg.optionalImportMessage != null);
+ msg.clear();
+ assertFalse(msg.optionalImportMessage != null);
+
+ msg.optionalImportMessage = nestedMsg;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalImportMessage != null);
+ assertEquals(1, newMsg.optionalImportMessage.d);
+ }
+
+ public void testNanoOptionalNestedEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalNestedEnum = TestAllTypesNano.BAR;
+ assertEquals(TestAllTypesNano.BAR, msg.optionalNestedEnum);
+ msg.clear()
+ .optionalNestedEnum = TestAllTypesNano.BAZ;
+ assertEquals(TestAllTypesNano.BAZ, msg.optionalNestedEnum);
+ msg.clear();
+ assertEquals(TestAllTypesNano.FOO, msg.optionalNestedEnum);
+
+ msg.optionalNestedEnum = TestAllTypesNano.BAR;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(TestAllTypesNano.BAR, newMsg.optionalNestedEnum);
+ }
+
+ public void testNanoOptionalForeignEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAR;
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.optionalForeignEnum);
+ msg.clear()
+ .optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAZ;
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAZ, msg.optionalForeignEnum);
+ msg.clear();
+ assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.optionalForeignEnum);
+
+ msg.optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAR;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, newMsg.optionalForeignEnum);
+ }
+
+ public void testNanoOptionalImportEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAR;
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.optionalImportEnum);
+ msg.clear()
+ .optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAZ;
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAZ, msg.optionalImportEnum);
+ msg.clear();
+ assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.optionalImportEnum);
+
+ msg.optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAR;
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAR, newMsg.optionalImportEnum);
+ }
+
+ public void testNanoOptionalStringPiece() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalStringPiece = "hello";
+ assertEquals("hello", msg.optionalStringPiece);
+ msg.clear();
+ assertTrue(msg.optionalStringPiece.isEmpty());
+ msg.clear()
+ .optionalStringPiece = "hello2";
+ assertEquals("hello2", msg.optionalStringPiece);
+ msg.clear();
+ assertTrue(msg.optionalStringPiece.isEmpty());
+
+ msg.optionalStringPiece = "bye";
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalStringPiece != null);
+ assertEquals("bye", newMsg.optionalStringPiece);
+ }
+
+ public void testNanoOptionalCord() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.optionalCord = "hello";
+ assertEquals("hello", msg.optionalCord);
+ msg.clear();
+ assertTrue(msg.optionalCord.isEmpty());
+ msg.clear()
+ .optionalCord = "hello2";
+ assertEquals("hello2", msg.optionalCord);
+ msg.clear();
+ assertTrue(msg.optionalCord.isEmpty());
+
+ msg.optionalCord = "bye";
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertTrue(newMsg.optionalCord != null);
+ assertEquals("bye", newMsg.optionalCord);
+ }
+
+ public void testNanoRepeatedInt32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedInt32.length);
+ msg.repeatedInt32 = new int[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedInt32[1]);
+ assertEquals(456, msg.repeatedInt32[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedInt32.length);
+ msg.clear()
+ .repeatedInt32 = new int[] { 456 };
+ assertEquals(1, msg.repeatedInt32.length);
+ assertEquals(456, msg.repeatedInt32[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedInt32.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedInt32 = new int[] { 123 };
+ assertEquals(1, msg.repeatedInt32.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedInt32.length);
+ assertEquals(123, newMsg.repeatedInt32[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedInt32 = new int[] { 123, 456 };
+ assertEquals(2, msg.repeatedInt32.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedInt32.length);
+ assertEquals(123, newMsg.repeatedInt32[0]);
+ assertEquals(456, newMsg.repeatedInt32[1]);
+ }
+
+ public void testNanoRepeatedInt64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedInt64.length);
+ msg.repeatedInt64 = new long[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedInt64[1]);
+ assertEquals(456, msg.repeatedInt64[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedInt64.length);
+ msg.clear()
+ .repeatedInt64 = new long[] { 456 };
+ assertEquals(1, msg.repeatedInt64.length);
+ assertEquals(456, msg.repeatedInt64[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedInt64.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedInt64 = new long[] { 123 };
+ assertEquals(1, msg.repeatedInt64.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedInt64.length);
+ assertEquals(123, newMsg.repeatedInt64[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedInt64 = new long[] { 123, 456 };
+ assertEquals(2, msg.repeatedInt64.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedInt64.length);
+ assertEquals(123, newMsg.repeatedInt64[0]);
+ assertEquals(456, newMsg.repeatedInt64[1]);
+ }
+
+ public void testNanoRepeatedUint32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedUint32.length);
+ msg.repeatedUint32 = new int[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedUint32[1]);
+ assertEquals(456, msg.repeatedUint32[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedUint32.length);
+ msg.clear()
+ .repeatedUint32 = new int[] { 456 };
+ assertEquals(1, msg.repeatedUint32.length);
+ assertEquals(456, msg.repeatedUint32[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedUint32.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedUint32 = new int[] { 123 };
+ assertEquals(1, msg.repeatedUint32.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedUint32.length);
+ assertEquals(123, newMsg.repeatedUint32[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedUint32 = new int[] { 123, 456 };
+ assertEquals(2, msg.repeatedUint32.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedUint32.length);
+ assertEquals(123, newMsg.repeatedUint32[0]);
+ assertEquals(456, newMsg.repeatedUint32[1]);
+ }
+
+ public void testNanoRepeatedUint64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedUint64.length);
+ msg.repeatedUint64 = new long[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedUint64[1]);
+ assertEquals(456, msg.repeatedUint64[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedUint64.length);
+ msg.clear()
+ .repeatedUint64 = new long[] { 456 };
+ assertEquals(1, msg.repeatedUint64.length);
+ assertEquals(456, msg.repeatedUint64[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedUint64.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedUint64 = new long[] { 123 };
+ assertEquals(1, msg.repeatedUint64.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedUint64.length);
+ assertEquals(123, newMsg.repeatedUint64[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedUint64 = new long[] { 123, 456 };
+ assertEquals(2, msg.repeatedUint64.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedUint64.length);
+ assertEquals(123, newMsg.repeatedUint64[0]);
+ assertEquals(456, newMsg.repeatedUint64[1]);
+ }
+
+ public void testNanoRepeatedSint32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedSint32.length);
+ msg.repeatedSint32 = new int[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedSint32[1]);
+ assertEquals(456, msg.repeatedSint32[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSint32.length);
+ msg.clear()
+ .repeatedSint32 = new int[] { 456 };
+ assertEquals(1, msg.repeatedSint32.length);
+ assertEquals(456, msg.repeatedSint32[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSint32.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedSint32 = new int[] { 123 };
+ assertEquals(1, msg.repeatedSint32.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedSint32.length);
+ assertEquals(123, newMsg.repeatedSint32[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedSint32 = new int[] { 123, 456 };
+ assertEquals(2, msg.repeatedSint32.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 11);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedSint32.length);
+ assertEquals(123, newMsg.repeatedSint32[0]);
+ assertEquals(456, newMsg.repeatedSint32[1]);
+ }
+
+ public void testNanoRepeatedSint64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedSint64.length);
+ msg.repeatedSint64 = new long[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedSint64[1]);
+ assertEquals(456, msg.repeatedSint64[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSint64.length);
+ msg.clear()
+ .repeatedSint64 = new long[] { 456 };
+ assertEquals(1, msg.repeatedSint64.length);
+ assertEquals(456, msg.repeatedSint64[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSint64.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedSint64 = new long[] { 123 };
+ assertEquals(1, msg.repeatedSint64.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedSint64.length);
+ assertEquals(123, newMsg.repeatedSint64[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedSint64 = new long[] { 123, 456 };
+ assertEquals(2, msg.repeatedSint64.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 11);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedSint64.length);
+ assertEquals(123, newMsg.repeatedSint64[0]);
+ assertEquals(456, newMsg.repeatedSint64[1]);
+ }
+
+ public void testNanoRepeatedFixed32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedFixed32.length);
+ msg.repeatedFixed32 = new int[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedFixed32[1]);
+ assertEquals(456, msg.repeatedFixed32[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedFixed32.length);
+ msg.clear()
+ .repeatedFixed32 = new int[] { 456 };
+ assertEquals(1, msg.repeatedFixed32.length);
+ assertEquals(456, msg.repeatedFixed32[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedFixed32.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedFixed32 = new int[] { 123 };
+ assertEquals(1, msg.repeatedFixed32.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedFixed32.length);
+ assertEquals(123, newMsg.repeatedFixed32[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedFixed32 = new int[] { 123, 456 };
+ assertEquals(2, msg.repeatedFixed32.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 15);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedFixed32.length);
+ assertEquals(123, newMsg.repeatedFixed32[0]);
+ assertEquals(456, newMsg.repeatedFixed32[1]);
+ }
+
+ public void testNanoRepeatedFixed64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedFixed64.length);
+ msg.repeatedFixed64 = new long[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedFixed64[1]);
+ assertEquals(456, msg.repeatedFixed64[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedFixed64.length);
+ msg.clear()
+ .repeatedFixed64 = new long[] { 456 };
+ assertEquals(1, msg.repeatedFixed64.length);
+ assertEquals(456, msg.repeatedFixed64[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedFixed64.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedFixed64 = new long[] { 123 };
+ assertEquals(1, msg.repeatedFixed64.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 13);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedFixed64.length);
+ assertEquals(123, newMsg.repeatedFixed64[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedFixed64 = new long[] { 123, 456 };
+ assertEquals(2, msg.repeatedFixed64.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 23);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedFixed64.length);
+ assertEquals(123, newMsg.repeatedFixed64[0]);
+ assertEquals(456, newMsg.repeatedFixed64[1]);
+ }
+
+ public void testNanoRepeatedSfixed32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedSfixed32.length);
+ msg.repeatedSfixed32 = new int[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedSfixed32[1]);
+ assertEquals(456, msg.repeatedSfixed32[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSfixed32.length);
+ msg.clear()
+ .repeatedSfixed32 = new int[] { 456 };
+ assertEquals(1, msg.repeatedSfixed32.length);
+ assertEquals(456, msg.repeatedSfixed32[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSfixed32.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedSfixed32 = new int[] { 123 };
+ assertEquals(1, msg.repeatedSfixed32.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedSfixed32.length);
+ assertEquals(123, newMsg.repeatedSfixed32[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedSfixed32 = new int[] { 123, 456 };
+ assertEquals(2, msg.repeatedSfixed32.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 15);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedSfixed32.length);
+ assertEquals(123, newMsg.repeatedSfixed32[0]);
+ assertEquals(456, newMsg.repeatedSfixed32[1]);
+ }
+
+ public void testNanoRepeatedSfixed64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedSfixed64.length);
+ msg.repeatedSfixed64 = new long[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedSfixed64[1]);
+ assertEquals(456, msg.repeatedSfixed64[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSfixed64.length);
+ msg.clear()
+ .repeatedSfixed64 = new long[] { 456 };
+ assertEquals(1, msg.repeatedSfixed64.length);
+ assertEquals(456, msg.repeatedSfixed64[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedSfixed64.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedSfixed64 = new long[] { 123 };
+ assertEquals(1, msg.repeatedSfixed64.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 13);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedSfixed64.length);
+ assertEquals(123, newMsg.repeatedSfixed64[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedSfixed64 = new long[] { 123, 456 };
+ assertEquals(2, msg.repeatedSfixed64.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 23);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedSfixed64.length);
+ assertEquals(123, newMsg.repeatedSfixed64[0]);
+ assertEquals(456, newMsg.repeatedSfixed64[1]);
+ }
+
+ public void testNanoRepeatedFloat() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedFloat.length);
+ msg.repeatedFloat = new float[] { 123f, 789f, 456f };
+ assertEquals(789f, msg.repeatedFloat[1]);
+ assertEquals(456f, msg.repeatedFloat[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedFloat.length);
+ msg.clear()
+ .repeatedFloat = new float[] { 456f };
+ assertEquals(1, msg.repeatedFloat.length);
+ assertEquals(456f, msg.repeatedFloat[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedFloat.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedFloat = new float[] { 123f };
+ assertEquals(1, msg.repeatedFloat.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedFloat.length);
+ assertEquals(123f, newMsg.repeatedFloat[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedFloat = new float[] { 123f, 456f };
+ assertEquals(2, msg.repeatedFloat.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 15);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedFloat.length);
+ assertEquals(123f, newMsg.repeatedFloat[0]);
+ assertEquals(456f, newMsg.repeatedFloat[1]);
+ }
+
+ public void testNanoRepeatedDouble() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedDouble.length);
+ msg.repeatedDouble = new double[] { 123.0, 789.0, 456.0 };
+ assertEquals(789.0, msg.repeatedDouble[1]);
+ assertEquals(456.0, msg.repeatedDouble[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedDouble.length);
+ msg.clear()
+ .repeatedDouble = new double[] { 456.0 };
+ assertEquals(1, msg.repeatedDouble.length);
+ assertEquals(456.0, msg.repeatedDouble[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedDouble.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedDouble = new double[] { 123.0 };
+ assertEquals(1, msg.repeatedDouble.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 13);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedDouble.length);
+ assertEquals(123.0, newMsg.repeatedDouble[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedDouble = new double[] { 123.0, 456.0 };
+ assertEquals(2, msg.repeatedDouble.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 23);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedDouble.length);
+ assertEquals(123.0, newMsg.repeatedDouble[0]);
+ assertEquals(456.0, newMsg.repeatedDouble[1]);
+ }
+
+ public void testNanoRepeatedBool() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedBool.length);
+ msg.repeatedBool = new boolean[] { false, true, false };
+ assertTrue(msg.repeatedBool[1]);
+ assertFalse(msg.repeatedBool[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedBool.length);
+ msg.clear()
+ .repeatedBool = new boolean[] { true };
+ assertEquals(1, msg.repeatedBool.length);
+ assertTrue(msg.repeatedBool[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedBool.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedBool = new boolean[] { false };
+ assertEquals(1, msg.repeatedBool.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedBool.length);
+ assertFalse(newMsg.repeatedBool[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedBool = new boolean[] { true, false };
+ assertEquals(2, msg.repeatedBool.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedBool.length);
+ assertTrue(newMsg.repeatedBool[0]);
+ assertFalse(newMsg.repeatedBool[1]);
+ }
+
+ public void testNanoRepeatedString() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedString.length);
+ msg.repeatedString = new String[] { "hello", "bye", "boo" };
+ assertEquals("bye", msg.repeatedString[1]);
+ assertEquals("boo", msg.repeatedString[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedString.length);
+ msg.clear()
+ .repeatedString = new String[] { "boo" };
+ assertEquals(1, msg.repeatedString.length);
+ assertEquals("boo", msg.repeatedString[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedString.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedString = new String[] { "" };
+ assertEquals(1, msg.repeatedString.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedString.length);
+ assertTrue(newMsg.repeatedString[0].isEmpty());
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedString = new String[] { "hello", "world" };
+ assertEquals(2, msg.repeatedString.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 19);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedString.length);
+ assertEquals("hello", newMsg.repeatedString[0]);
+ assertEquals("world", newMsg.repeatedString[1]);
+ }
+
+ public void testNanoRepeatedBytes() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedBytes.length);
+ msg.repeatedBytes = new byte[][] {
+ InternalNano.copyFromUtf8("hello"),
+ InternalNano.copyFromUtf8("bye"),
+ InternalNano.copyFromUtf8("boo")
+ };
+ assertEquals("bye", new String(msg.repeatedBytes[1], "UTF-8"));
+ assertEquals("boo", new String(msg.repeatedBytes[2], "UTF-8"));
+ msg.clear();
+ assertEquals(0, msg.repeatedBytes.length);
+ msg.clear()
+ .repeatedBytes = new byte[][] { InternalNano.copyFromUtf8("boo") };
+ assertEquals(1, msg.repeatedBytes.length);
+ assertEquals("boo", new String(msg.repeatedBytes[0], "UTF-8"));
+ msg.clear();
+ assertEquals(0, msg.repeatedBytes.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedBytes = new byte[][] { InternalNano.copyFromUtf8("") };
+ assertEquals(1, msg.repeatedBytes.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedBytes.length);
+ assertTrue(newMsg.repeatedBytes[0].length == 0);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedBytes = new byte[][] {
+ InternalNano.copyFromUtf8("hello"),
+ InternalNano.copyFromUtf8("world")
+ };
+ assertEquals(2, msg.repeatedBytes.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 19);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedBytes.length);
+ assertEquals("hello", new String(newMsg.repeatedBytes[0], "UTF-8"));
+ assertEquals("world", new String(newMsg.repeatedBytes[1], "UTF-8"));
+ }
+
+ public void testNanoRepeatedGroup() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ TestAllTypesNano.RepeatedGroup group0 =
+ new TestAllTypesNano.RepeatedGroup();
+ group0.a = 0;
+ TestAllTypesNano.RepeatedGroup group1 =
+ new TestAllTypesNano.RepeatedGroup();
+ group1.a = 1;
+ TestAllTypesNano.RepeatedGroup group2 =
+ new TestAllTypesNano.RepeatedGroup();
+ group2.a = 2;
+
+ msg.repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0, group1, group2 };
+ assertEquals(3, msg.repeatedGroup.length);
+ assertEquals(0, msg.repeatedGroup[0].a);
+ assertEquals(1, msg.repeatedGroup[1].a);
+ assertEquals(2, msg.repeatedGroup[2].a);
+ msg.clear();
+ assertEquals(0, msg.repeatedGroup.length);
+ msg.clear()
+ .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group1 };
+ assertEquals(1, msg.repeatedGroup.length);
+ assertEquals(1, msg.repeatedGroup[0].a);
+ msg.clear();
+ assertEquals(0, msg.repeatedGroup.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0 };
+ assertEquals(1, msg.repeatedGroup.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedGroup.length);
+ assertEquals(0, newMsg.repeatedGroup[0].a);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0, group1 };
+ assertEquals(2, msg.repeatedGroup.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 14);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedGroup.length);
+ assertEquals(0, newMsg.repeatedGroup[0].a);
+ assertEquals(1, newMsg.repeatedGroup[1].a);
+ }
+
+ public void testNanoRepeatedNestedMessage() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ TestAllTypesNano.NestedMessage nestedMsg0 =
+ new TestAllTypesNano.NestedMessage();
+ nestedMsg0.bb = 0;
+ TestAllTypesNano.NestedMessage nestedMsg1 =
+ new TestAllTypesNano.NestedMessage();
+ nestedMsg1.bb = 1;
+ TestAllTypesNano.NestedMessage nestedMsg2 =
+ new TestAllTypesNano.NestedMessage();
+ nestedMsg2.bb = 2;
+
+ msg.repeatedNestedMessage =
+ new TestAllTypesNano.NestedMessage[] { nestedMsg0, nestedMsg1, nestedMsg2 };
+ assertEquals(3, msg.repeatedNestedMessage.length);
+ assertEquals(0, msg.repeatedNestedMessage[0].bb);
+ assertEquals(1, msg.repeatedNestedMessage[1].bb);
+ assertEquals(2, msg.repeatedNestedMessage[2].bb);
+ msg.clear();
+ assertEquals(0, msg.repeatedNestedMessage.length);
+ msg.clear()
+ .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg1 };
+ assertEquals(1, msg.repeatedNestedMessage.length);
+ assertEquals(1, msg.repeatedNestedMessage[0].bb);
+ msg.clear();
+ assertEquals(0, msg.repeatedNestedMessage.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0 };
+ assertEquals(1, msg.repeatedNestedMessage.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedNestedMessage.length);
+ assertEquals(0, newMsg.repeatedNestedMessage[0].bb);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0, nestedMsg1 };
+ assertEquals(2, msg.repeatedNestedMessage.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 11);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedNestedMessage.length);
+ assertEquals(0, newMsg.repeatedNestedMessage[0].bb);
+ assertEquals(1, newMsg.repeatedNestedMessage[1].bb);
+ }
+
+ public void testNanoRepeatedForeignMessage() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ NanoOuterClass.ForeignMessageNano foreignMsg0 =
+ new NanoOuterClass.ForeignMessageNano();
+ foreignMsg0.c = 0;
+ NanoOuterClass.ForeignMessageNano foreignMsg1 =
+ new NanoOuterClass.ForeignMessageNano();
+ foreignMsg1.c = 1;
+ NanoOuterClass.ForeignMessageNano foreignMsg2 =
+ new NanoOuterClass.ForeignMessageNano();
+ foreignMsg2.c = 2;
+
+ msg.repeatedForeignMessage =
+ new NanoOuterClass.ForeignMessageNano[] { foreignMsg0, foreignMsg1, foreignMsg2 };
+ assertEquals(3, msg.repeatedForeignMessage.length);
+ assertEquals(0, msg.repeatedForeignMessage[0].c);
+ assertEquals(1, msg.repeatedForeignMessage[1].c);
+ assertEquals(2, msg.repeatedForeignMessage[2].c);
+ msg.clear();
+ assertEquals(0, msg.repeatedForeignMessage.length);
+ msg.clear()
+ .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg1 };
+ assertEquals(1, msg.repeatedForeignMessage.length);
+ assertEquals(1, msg.repeatedForeignMessage[0].c);
+ msg.clear();
+ assertEquals(0, msg.repeatedForeignMessage.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg0 };
+ assertEquals(1, msg.repeatedForeignMessage.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedForeignMessage.length);
+ assertEquals(0, newMsg.repeatedForeignMessage[0].c);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg0, foreignMsg1 };
+ assertEquals(2, msg.repeatedForeignMessage.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 11);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedForeignMessage.length);
+ assertEquals(0, newMsg.repeatedForeignMessage[0].c);
+ assertEquals(1, newMsg.repeatedForeignMessage[1].c);
+ }
+
+ public void testNanoRepeatedImportMessage() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ UnittestImportNano.ImportMessageNano foreignMsg0 =
+ new UnittestImportNano.ImportMessageNano();
+ foreignMsg0.d = 0;
+ UnittestImportNano.ImportMessageNano foreignMsg1 =
+ new UnittestImportNano.ImportMessageNano();
+ foreignMsg1.d = 1;
+ UnittestImportNano.ImportMessageNano foreignMsg2 =
+ new UnittestImportNano.ImportMessageNano();
+ foreignMsg2.d = 2;
+
+ msg.repeatedImportMessage =
+ new UnittestImportNano.ImportMessageNano[] { foreignMsg0, foreignMsg1, foreignMsg2 };
+ assertEquals(3, msg.repeatedImportMessage.length);
+ assertEquals(0, msg.repeatedImportMessage[0].d);
+ assertEquals(1, msg.repeatedImportMessage[1].d);
+ assertEquals(2, msg.repeatedImportMessage[2].d);
+ msg.clear();
+ assertEquals(0, msg.repeatedImportMessage.length);
+ msg.clear()
+ .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg1 };
+ assertEquals(1, msg.repeatedImportMessage.length);
+ assertEquals(1, msg.repeatedImportMessage[0].d);
+ msg.clear();
+ assertEquals(0, msg.repeatedImportMessage.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg0 };
+ assertEquals(1, msg.repeatedImportMessage.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedImportMessage.length);
+ assertEquals(0, newMsg.repeatedImportMessage[0].d);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg0, foreignMsg1 };
+ assertEquals(2, msg.repeatedImportMessage.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 11);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedImportMessage.length);
+ assertEquals(0, newMsg.repeatedImportMessage[0].d);
+ assertEquals(1, newMsg.repeatedImportMessage[1].d);
+ }
+
+ public void testNanoRepeatedNestedEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.repeatedNestedEnum = new int[] {
+ TestAllTypesNano.FOO,
+ TestAllTypesNano.BAR,
+ TestAllTypesNano.BAZ
+ };
+ assertEquals(3, msg.repeatedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]);
+ assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[1]);
+ assertEquals(TestAllTypesNano.BAZ, msg.repeatedNestedEnum[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedNestedEnum.length);
+ msg.clear()
+ .repeatedNestedEnum = new int[] { TestAllTypesNano.BAR };
+ assertEquals(1, msg.repeatedNestedEnum.length);
+ assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedNestedEnum.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedNestedEnum = new int[] { TestAllTypesNano.FOO };
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedNestedEnum = new int[] { TestAllTypesNano.FOO, TestAllTypesNano.BAR };
+ assertEquals(2, msg.repeatedNestedEnum.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]);
+ assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[1]);
+ }
+
+ public void testNanoRepeatedForeignEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.repeatedForeignEnum = new int[] {
+ NanoOuterClass.FOREIGN_NANO_FOO,
+ NanoOuterClass.FOREIGN_NANO_BAR,
+ NanoOuterClass.FOREIGN_NANO_BAZ
+ };
+ assertEquals(3, msg.repeatedForeignEnum.length);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[1]);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAZ, msg.repeatedForeignEnum[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedForeignEnum.length);
+ msg.clear()
+ .repeatedForeignEnum = new int[] { NanoOuterClass.FOREIGN_NANO_BAR };
+ assertEquals(1, msg.repeatedForeignEnum.length);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedForeignEnum.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedForeignEnum = new int[] { NanoOuterClass.FOREIGN_NANO_FOO };
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedForeignEnum.length);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedForeignEnum = new int[] {
+ NanoOuterClass.FOREIGN_NANO_FOO,
+ NanoOuterClass.FOREIGN_NANO_BAR
+ };
+ assertEquals(2, msg.repeatedForeignEnum.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedForeignEnum.length);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[1]);
+ }
+
+ public void testNanoRepeatedImportEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.repeatedImportEnum = new int[] {
+ UnittestImportNano.IMPORT_NANO_FOO,
+ UnittestImportNano.IMPORT_NANO_BAR,
+ UnittestImportNano.IMPORT_NANO_BAZ
+ };
+ assertEquals(3, msg.repeatedImportEnum.length);
+ assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]);
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[1]);
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAZ, msg.repeatedImportEnum[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedImportEnum.length);
+ msg.clear()
+ .repeatedImportEnum = new int[] { UnittestImportNano.IMPORT_NANO_BAR };
+ assertEquals(1, msg.repeatedImportEnum.length);
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedImportEnum.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedImportEnum = new int[] { UnittestImportNano.IMPORT_NANO_FOO };
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedImportEnum.length);
+ assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedImportEnum = new int[] {
+ UnittestImportNano.IMPORT_NANO_FOO,
+ UnittestImportNano.IMPORT_NANO_BAR
+ };
+ assertEquals(2, msg.repeatedImportEnum.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedImportEnum.length);
+ assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]);
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[1]);
+ }
+
+ public void testNanoRepeatedStringPiece() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedStringPiece.length);
+ msg.repeatedStringPiece = new String[] { "hello", "bye", "boo" };
+ assertEquals("bye", msg.repeatedStringPiece[1]);
+ assertEquals("boo", msg.repeatedStringPiece[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedStringPiece.length);
+ msg.clear()
+ .repeatedStringPiece = new String[] { "boo" };
+ assertEquals(1, msg.repeatedStringPiece.length);
+ assertEquals("boo", msg.repeatedStringPiece[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedStringPiece.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedStringPiece = new String[] { "" };
+ assertEquals(1, msg.repeatedStringPiece.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedStringPiece.length);
+ assertTrue(newMsg.repeatedStringPiece[0].isEmpty());
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedStringPiece = new String[] { "hello", "world" };
+ assertEquals(2, msg.repeatedStringPiece.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 19);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedStringPiece.length);
+ assertEquals("hello", newMsg.repeatedStringPiece[0]);
+ assertEquals("world", newMsg.repeatedStringPiece[1]);
+ }
+
+ public void testNanoRepeatedCord() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedCord.length);
+ msg.repeatedCord = new String[] { "hello", "bye", "boo" };
+ assertEquals("bye", msg.repeatedCord[1]);
+ assertEquals("boo", msg.repeatedCord[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedCord.length);
+ msg.clear()
+ .repeatedCord = new String[] { "boo" };
+ assertEquals(1, msg.repeatedCord.length);
+ assertEquals("boo", msg.repeatedCord[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedCord.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedCord = new String[] { "" };
+ assertEquals(1, msg.repeatedCord.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedCord.length);
+ assertTrue(newMsg.repeatedCord[0].isEmpty());
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedCord = new String[] { "hello", "world" };
+ assertEquals(2, msg.repeatedCord.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 19);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedCord.length);
+ assertEquals("hello", newMsg.repeatedCord[0]);
+ assertEquals("world", newMsg.repeatedCord[1]);
+ }
+
+ public void testNanoRepeatedPackedInt32() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedPackedInt32.length);
+ msg.repeatedPackedInt32 = new int[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedPackedInt32[1]);
+ assertEquals(456, msg.repeatedPackedInt32[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedPackedInt32.length);
+ msg.clear()
+ .repeatedPackedInt32 = new int[] { 456 };
+ assertEquals(1, msg.repeatedPackedInt32.length);
+ assertEquals(456, msg.repeatedPackedInt32[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedPackedInt32.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedPackedInt32 = new int[] { 123 };
+ assertEquals(1, msg.repeatedPackedInt32.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedPackedInt32.length);
+ assertEquals(123, newMsg.repeatedPackedInt32[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedPackedInt32 = new int[] { 123, 456 };
+ assertEquals(2, msg.repeatedPackedInt32.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedPackedInt32.length);
+ assertEquals(123, newMsg.repeatedPackedInt32[0]);
+ assertEquals(456, newMsg.repeatedPackedInt32[1]);
+ }
+
+ public void testNanoRepeatedPackedSfixed64() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ assertEquals(0, msg.repeatedPackedSfixed64.length);
+ msg.repeatedPackedSfixed64 = new long[] { 123, 789, 456 };
+ assertEquals(789, msg.repeatedPackedSfixed64[1]);
+ assertEquals(456, msg.repeatedPackedSfixed64[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedPackedSfixed64.length);
+ msg.clear()
+ .repeatedPackedSfixed64 = new long[] { 456 };
+ assertEquals(1, msg.repeatedPackedSfixed64.length);
+ assertEquals(456, msg.repeatedPackedSfixed64[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedPackedSfixed64.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedPackedSfixed64 = new long[] { 123 };
+ assertEquals(1, msg.repeatedPackedSfixed64.length);
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 14);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedPackedSfixed64.length);
+ assertEquals(123, newMsg.repeatedPackedSfixed64[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedPackedSfixed64 = new long[] { 123, 456 };
+ assertEquals(2, msg.repeatedPackedSfixed64.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 22);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedPackedSfixed64.length);
+ assertEquals(123, newMsg.repeatedPackedSfixed64[0]);
+ assertEquals(456, newMsg.repeatedPackedSfixed64[1]);
+ }
+
+ public void testNanoRepeatedPackedNestedEnum() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.repeatedPackedNestedEnum = new int[] {
+ TestAllTypesNano.FOO,
+ TestAllTypesNano.BAR,
+ TestAllTypesNano.BAZ
+ };
+ assertEquals(3, msg.repeatedPackedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]);
+ assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]);
+ assertEquals(TestAllTypesNano.BAZ, msg.repeatedPackedNestedEnum[2]);
+ msg.clear();
+ assertEquals(0, msg.repeatedPackedNestedEnum.length);
+ msg.clear()
+ .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.BAR };
+ assertEquals(1, msg.repeatedPackedNestedEnum.length);
+ assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[0]);
+ msg.clear();
+ assertEquals(0, msg.repeatedPackedNestedEnum.length);
+
+ // Test 1 entry
+ msg.clear()
+ .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.FOO };
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(1, newMsg.repeatedPackedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]);
+
+ // Test 2 entries
+ msg.clear()
+ .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.FOO, TestAllTypesNano.BAR };
+ assertEquals(2, msg.repeatedPackedNestedEnum.length);
+ result = MessageNano.toByteArray(msg);
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(2, newMsg.repeatedPackedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]);
+ assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]);
+ }
+
+ public void testNanoRepeatedInt32ReMerge() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.repeatedInt32 = new int[] { 234 };
+ byte [] result1 = MessageNano.toByteArray(msg);
+
+ msg.clear().optionalInt32 = 789;
+ byte [] result2 = MessageNano.toByteArray(msg);
+
+ msg.clear().repeatedInt32 = new int[] { 123, 456 };
+ byte [] result3 = MessageNano.toByteArray(msg);
+
+ // Concatenate the three serializations and read as one message.
+ byte [] result = new byte[result1.length + result2.length + result3.length];
+ System.arraycopy(result1, 0, result, 0, result1.length);
+ System.arraycopy(result2, 0, result, result1.length, result2.length);
+ System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(789, newMsg.optionalInt32);
+ assertEquals(3, newMsg.repeatedInt32.length);
+ assertEquals(234, newMsg.repeatedInt32[0]);
+ assertEquals(123, newMsg.repeatedInt32[1]);
+ assertEquals(456, newMsg.repeatedInt32[2]);
+ }
+
+ public void testNanoRepeatedNestedEnumReMerge() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ msg.repeatedNestedEnum = new int[] { TestAllTypesNano.FOO };
+ byte [] result1 = MessageNano.toByteArray(msg);
+
+ msg.clear().optionalInt32 = 789;
+ byte [] result2 = MessageNano.toByteArray(msg);
+
+ msg.clear().repeatedNestedEnum = new int[] { TestAllTypesNano.BAR, TestAllTypesNano.FOO };
+ byte [] result3 = MessageNano.toByteArray(msg);
+
+ // Concatenate the three serializations and read as one message.
+ byte [] result = new byte[result1.length + result2.length + result3.length];
+ System.arraycopy(result1, 0, result, 0, result1.length);
+ System.arraycopy(result2, 0, result, result1.length, result2.length);
+ System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(789, newMsg.optionalInt32);
+ assertEquals(3, newMsg.repeatedNestedEnum.length);
+ assertEquals(TestAllTypesNano.FOO, newMsg.repeatedNestedEnum[0]);
+ assertEquals(TestAllTypesNano.BAR, newMsg.repeatedNestedEnum[1]);
+ assertEquals(TestAllTypesNano.FOO, newMsg.repeatedNestedEnum[2]);
+ }
+
+ public void testNanoRepeatedNestedMessageReMerge() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ TestAllTypesNano.NestedMessage nestedMsg0 =
+ new TestAllTypesNano.NestedMessage();
+ nestedMsg0.bb = 0;
+ TestAllTypesNano.NestedMessage nestedMsg1 =
+ new TestAllTypesNano.NestedMessage();
+ nestedMsg1.bb = 1;
+ TestAllTypesNano.NestedMessage nestedMsg2 =
+ new TestAllTypesNano.NestedMessage();
+ nestedMsg2.bb = 2;
+
+ msg.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0 };
+ byte [] result1 = MessageNano.toByteArray(msg);
+
+ msg.clear().optionalInt32 = 789;
+ byte [] result2 = MessageNano.toByteArray(msg);
+
+ msg.clear().repeatedNestedMessage =
+ new TestAllTypesNano.NestedMessage[] { nestedMsg1, nestedMsg2 };
+ byte [] result3 = MessageNano.toByteArray(msg);
+
+ // Concatenate the three serializations and read as one message.
+ byte [] result = new byte[result1.length + result2.length + result3.length];
+ System.arraycopy(result1, 0, result, 0, result1.length);
+ System.arraycopy(result2, 0, result, result1.length, result2.length);
+ System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length);
+
+ TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result);
+ assertEquals(789, newMsg.optionalInt32);
+ assertEquals(3, newMsg.repeatedNestedMessage.length);
+ assertEquals(nestedMsg0.bb, newMsg.repeatedNestedMessage[0].bb);
+ assertEquals(nestedMsg1.bb, newMsg.repeatedNestedMessage[1].bb);
+ assertEquals(nestedMsg2.bb, newMsg.repeatedNestedMessage[2].bb);
+ }
+
+ public void testNanoDefaults() throws Exception {
+ TestAllTypesNano msg = new TestAllTypesNano();
+ for (int i = 0; i < 2; i++) {
+ assertEquals(41, msg.defaultInt32);
+ assertEquals(42, msg.defaultInt64);
+ assertEquals(43, msg.defaultUint32);
+ assertEquals(44, msg.defaultUint64);
+ assertEquals(-45, msg.defaultSint32);
+ assertEquals(46, msg.defaultSint64);
+ assertEquals(47, msg.defaultFixed32);
+ assertEquals(48, msg.defaultFixed64);
+ assertEquals(49, msg.defaultSfixed32);
+ assertEquals(-50, msg.defaultSfixed64);
+ assertTrue(51.5f == msg.defaultFloat);
+ assertTrue(52.0e3 == msg.defaultDouble);
+ assertEquals(true, msg.defaultBool);
+ assertEquals("hello", msg.defaultString);
+ assertEquals("world", new String(msg.defaultBytes, "UTF-8"));
+ assertEquals("dünya", msg.defaultStringNonascii);
+ assertEquals("dünyab", new String(msg.defaultBytesNonascii, "UTF-8"));
+ assertEquals(TestAllTypesNano.BAR, msg.defaultNestedEnum);
+ assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.defaultForeignEnum);
+ assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.defaultImportEnum);
+
+ // Default values are not output, except for required fields.
+ byte [] result = MessageNano.toByteArray(msg);
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ msg.clear();
+ }
+ }
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * exactly up to a limit, this should not break things.
+ */
+ public void testSkipRawBytesBug() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2 };
+ CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(rawBytes);
+
+ int limit = input.pushLimit(1);
+ input.skipRawBytes(1);
+ input.popLimit(limit);
+ assertEquals(2, input.readRawByte());
+ }
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * past the end of a buffer with a limit that has been set past the end of
+ * that buffer, this should not break things.
+ */
+ public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
+ CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(rawBytes);
+
+ int limit = input.pushLimit(4);
+ // In order to expose the bug we need to read at least one byte to prime the
+ // buffer inside the CodedInputStream.
+ assertEquals(1, input.readRawByte());
+ // Skip to the end of the limit.
+ input.skipRawBytes(3);
+ assertTrue(input.isAtEnd());
+ input.popLimit(limit);
+ assertEquals(5, input.readRawByte());
+ }
+}
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
new file mode 100644
index 00000000..5abd46e9
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -0,0 +1,96 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params)
+ : params_(params), descriptor_(descriptor) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ canonical_values_.push_back(value);
+ } else {
+ Alias alias;
+ alias.value = value;
+ alias.canonical_value = canonical_value;
+ aliases_.push_back(alias);
+ }
+ }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::Generate(io::Printer* printer) {
+ printer->Print("// enum $classname$\n", "classname", descriptor_->name());
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ map<string, string> vars;
+ vars["name"] = canonical_values_[i]->name();
+ vars["canonical_value"] = SimpleItoa(canonical_values_[i]->number());
+ printer->Print(vars,
+ "public static final int $name$ = $canonical_value$;\n");
+ }
+
+ // -----------------------------------------------------------------
+
+ for (int i = 0; i < aliases_.size(); i++) {
+ map<string, string> vars;
+ vars["name"] = aliases_[i].value->name();
+ vars["canonical_name"] = aliases_[i].canonical_value->name();
+ printer->Print(vars,
+ "public static final int $name$ = $canonical_name$;\n");
+ }
+
+ printer->Print("\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.h b/src/google/protobuf/compiler/javanano/javanano_enum.h
new file mode 100644
index 00000000..d6f463ec
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.h
@@ -0,0 +1,87 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class EnumGenerator {
+ public:
+ explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params);
+ ~EnumGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const Params& params_;
+ const EnumDescriptor* descriptor_;
+
+ // The proto language allows multiple enum constants to have the same numeric
+ // value. Java, however, does not allow multiple enum constants to be
+ // considered equivalent. We treat the first defined constant for any
+ // given numeric value as "canonical" and the rest as aliases of that
+ // canonical value.
+ vector<const EnumValueDescriptor*> canonical_values_;
+
+ struct Alias {
+ const EnumValueDescriptor* value;
+ const EnumValueDescriptor* canonical_value;
+ };
+ vector<Alias> aliases_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
new file mode 100644
index 00000000..68020db1
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -0,0 +1,266 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
+// repeat code between this and the other field types.
+void SetEnumVariables(const Params& params,
+ const FieldDescriptor* descriptor, map<string, string>* variables) {
+ (*variables)["name"] =
+ UnderscoresToCamelCase(descriptor);
+ (*variables)["capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(descriptor);
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["type"] = "int";
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ (*variables)["message_name"] = descriptor->containing_type()->name();
+}
+
+} // namespace
+
+// ===================================================================
+
+EnumFieldGenerator::
+EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetEnumVariables(params, descriptor, &variables_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "public int $name$ = $default$;\n");
+}
+
+void EnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$ = other.$name$;\n");
+}
+
+void EnumFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ " $name$ = input.readInt32();\n");
+}
+
+void EnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->is_required()) {
+ printer->Print(variables_,
+ "output.writeInt32($number$, $name$);\n");
+ } else {
+ printer->Print(variables_,
+ "if ($name$ != $default$) {\n"
+ " output.writeInt32($number$, $name$);\n"
+ "}\n");
+ }
+}
+
+void EnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ if (descriptor_->is_required()) {
+ printer->Print(variables_,
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32Size($number$, $name$);\n");
+ } else {
+ printer->Print(variables_,
+ "if ($name$ != $default$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32Size($number$, $name$);\n"
+ "}\n");
+ }
+}
+
+string EnumFieldGenerator::GetBoxedType() const {
+ return ClassName(params_, descriptor_->enum_type());
+}
+
+// ===================================================================
+
+RepeatedEnumFieldGenerator::
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetEnumVariables(params, descriptor, &variables_);
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "public int[] $name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.$name$.length > 0) {\n"
+ " int[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n"
+ " java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n"
+ " result.$name$ = merged;\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ // First, figure out the length of the array, then parse.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "// First pass to compute array length.\n"
+ "int arrayLength = 0;\n"
+ "int startPos = input.getPosition();\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " input.readInt32();\n"
+ " arrayLength++;\n"
+ "}\n"
+ "input.rewindToPosition(startPos);\n"
+ "$name$ = new $type$[arrayLength];\n"
+ "for (int i = 0; i < arrayLength; i++) {\n"
+ " $name$[i] = input.readInt32();\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+ } else {
+ printer->Print(variables_,
+ "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n"
+ "int i = $name$.length;\n"
+ "$name$ = java.util.Arrays.copyOf($name$, $name$.length + arrayLength);\n"
+ "for (; i < $name$.length - 1; i++) {\n"
+ " $name$[i] = input.readInt32();\n"
+ " input.readTag();\n"
+ "}\n"
+ "// Last one without readTag.\n"
+ "$name$[i] = input.readInt32();\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($name$.length > 0) {\n");
+ printer->Indent();
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "output.writeRawVarint32($tag$);\n"
+ "output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "for (int element : $name$) {\n"
+ " output.writeRawVarint32(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int element : $name$) {\n"
+ " output.writeInt32($number$, element);\n"
+ "}\n");
+ }
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($name$.length > 0) {\n");
+ printer->Indent();
+
+ printer->Print(variables_,
+ "int dataSize = 0;\n"
+ "for (int element : $name$) {\n"
+ " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32SizeNoTag(element);\n"
+ "}\n");
+
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ // cache the data size for packed fields.
+ printer->Print(variables_,
+ "size += $tag_size$;\n"
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeRawVarint32Size(dataSize);\n"
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * $name$.length;\n");
+ }
+
+ printer->Outdent();
+
+ // set cached size to 0 for empty packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "} else {\n"
+ " $name$MemoizedSerializedSize = 0;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "}\n");
+ }
+}
+
+string RepeatedEnumFieldGenerator::GetBoxedType() const {
+ return ClassName(params_, descriptor_->enum_type());
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
new file mode 100644
index 00000000..8985b0f0
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class EnumFieldGenerator : public FieldGenerator {
+ public:
+ explicit EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ ~EnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public FieldGenerator {
+ public:
+ explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ ~RepeatedEnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
new file mode 100644
index 00000000..ea25786c
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -0,0 +1,102 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
+#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/compiler/javanano/javanano_message_field.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+FieldGenerator::~FieldGenerator() {}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params &params)
+ : descriptor_(descriptor),
+ field_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
+ extension_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+
+ // Construct all the FieldGenerators.
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ field_generators_[i].reset(MakeGenerator(descriptor->field(i), params));
+ }
+ for (int i = 0; i < descriptor->extension_count(); i++) {
+ extension_generators_[i].reset(MakeGenerator(descriptor->extension(i), params));
+ }
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, const Params &params) {
+ if (field->is_repeated()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ return new RepeatedMessageFieldGenerator(field, params);
+ case JAVATYPE_ENUM:
+ return new RepeatedEnumFieldGenerator(field, params);
+ default:
+ return new RepeatedPrimitiveFieldGenerator(field, params);
+ }
+ } else {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ return new MessageFieldGenerator(field, params);
+ case JAVATYPE_ENUM:
+ return new EnumFieldGenerator(field, params);
+ default:
+ return new PrimitiveFieldGenerator(field, params);
+ }
+ }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+ return *field_generators_[field->index()];
+}
+
+const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
+ return *extension_generators_[index];
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
new file mode 100644
index 00000000..a0bf909a
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class FieldGenerator {
+ public:
+ //FieldGenerator() {}
+ FieldGenerator(const Params& params) : params_(params) {}
+ virtual ~FieldGenerator();
+
+ virtual void GenerateMembers(io::Printer* printer) const = 0;
+ virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+
+ virtual string GetBoxedType() const = 0;
+
+ protected:
+ const Params& params_;
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+ explicit FieldGeneratorMap(const Descriptor* descriptor, const Params &params);
+ ~FieldGeneratorMap();
+
+ const FieldGenerator& get(const FieldDescriptor* field) const;
+ const FieldGenerator& get_extension(int index) const;
+
+ private:
+ const Descriptor* descriptor_;
+ scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+ scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
+
+ static FieldGenerator* MakeGenerator(const FieldDescriptor* field, const Params &params);
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc
new file mode 100644
index 00000000..2f42fa0e
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_file.cc
@@ -0,0 +1,251 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/javanano/javanano_file.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_message.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+namespace {
+
+// Recursively searches the given message to see if it contains any extensions.
+bool UsesExtensions(const Message& message) {
+ const Reflection* reflection = message.GetReflection();
+
+ // We conservatively assume that unknown fields are extensions.
+ if (reflection->GetUnknownFields(message).field_count() > 0) return true;
+
+ vector<const FieldDescriptor*> fields;
+ reflection->ListFields(message, &fields);
+
+ for (int i = 0; i < fields.size(); i++) {
+ if (fields[i]->is_extension()) return true;
+
+ if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (fields[i]->is_repeated()) {
+ int size = reflection->FieldSize(message, fields[i]);
+ for (int j = 0; j < size; j++) {
+ const Message& sub_message =
+ reflection->GetRepeatedMessage(message, fields[i], j);
+ if (UsesExtensions(sub_message)) return true;
+ }
+ } else {
+ const Message& sub_message = reflection->GetMessage(message, fields[i]);
+ if (UsesExtensions(sub_message)) return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+} // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params)
+ : file_(file),
+ params_(params),
+ java_package_(FileJavaPackage(params, file)),
+ classname_(FileClassName(params, file)) {}
+
+FileGenerator::~FileGenerator() {}
+
+bool FileGenerator::Validate(string* error) {
+ // Check for extensions
+ FileDescriptorProto file_proto;
+ file_->CopyTo(&file_proto);
+ if (UsesExtensions(file_proto)) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME does not support extensions\"");
+ return false;
+ }
+
+ // If there is no outer class name then there must be only
+ // message and no enums defined in the file scope.
+ if (!params_.has_java_outer_classname(file_->name())) {
+ if (file_->message_type_count() != 1) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME may only have 1 message if there is no 'option java_outer_classname'\"");
+ return false;
+ }
+
+ if (file_->enum_type_count() != 0) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME must have an 'option java_outer_classname' if file scope enums are present\"");
+ return false;
+ }
+ }
+
+ // Check that no class name matches the file's class name. This is a common
+ // problem that leads to Java compile errors that can be hard to understand.
+ // It's especially bad when using the java_multiple_files, since we would
+ // end up overwriting the outer class with one of the inner ones.
+ int found_fileName = 0;
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ if (file_->enum_type(i)->name() == classname_) {
+ found_fileName += 1;
+ }
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (file_->message_type(i)->name() == classname_) {
+ found_fileName += 1;
+ }
+ }
+ if (file_->service_count() != 0) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME does not support services\"");
+ return false;
+ }
+
+ if (found_fileName > 1) {
+ error->assign(file_->name());
+ error->append(
+ ": Cannot generate Java output because there is more than one class name, \"");
+ error->append(classname_);
+ error->append(
+ "\", matches the name of one of the types declared inside it. "
+ "Please either rename the type or use the java_outer_classname "
+ "option to specify a different outer class name for the .proto file."
+ " -- FIX THIS MESSAGE");
+ return false;
+ }
+ return true;
+}
+
+void FileGenerator::Generate(io::Printer* printer) {
+ // We don't import anything because we refer to all classes by their
+ // fully-qualified names in the generated source.
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "\n");
+ if (!java_package_.empty()) {
+ printer->Print(
+ "package $package$;\n"
+ "\n",
+ "package", java_package_);
+ }
+
+ if (params_.has_java_outer_classname(file_->name())) {
+ printer->Print(
+ "public final class $classname$ {\n"
+ " private $classname$() {}\n",
+ "classname", classname_);
+ printer->Indent();
+ }
+
+ // -----------------------------------------------------------------
+
+ if (!params_.java_multiple_files()) {
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator(file_->enum_type(i), params_).Generate(printer);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator(file_->message_type(i), params_).Generate(printer);
+ }
+ }
+
+ // Static variables.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
+ }
+
+ if (params_.has_java_outer_classname(file_->name())) {
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+}
+
+template<typename GeneratorClass, typename DescriptorClass>
+static void GenerateSibling(const string& package_dir,
+ const string& java_package,
+ const DescriptorClass* descriptor,
+ OutputDirectory* output_directory,
+ vector<string>* file_list,
+ const Params& params) {
+ string filename = package_dir + descriptor->name() + ".java";
+ file_list->push_back(filename);
+
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(filename));
+ io::Printer printer(output.get(), '$');
+
+ printer.Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "\n");
+ if (!java_package.empty()) {
+ printer.Print(
+ "package $package$;\n"
+ "\n",
+ "package", java_package);
+ }
+
+ GeneratorClass(descriptor, params).Generate(&printer);
+}
+
+void FileGenerator::GenerateSiblings(const string& package_dir,
+ OutputDirectory* output_directory,
+ vector<string>* file_list) {
+ if (params_.java_multiple_files()) {
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ GenerateSibling<EnumGenerator>(package_dir, java_package_,
+ file_->enum_type(i),
+ output_directory, file_list, params_);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ GenerateSibling<MessageGenerator>(package_dir, java_package_,
+ file_->message_type(i),
+ output_directory, file_list, params_);
+ }
+ }
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h
new file mode 100644
index 00000000..94727211
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_file.h
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+
+namespace google {
+namespace protobuf {
+ class FileDescriptor; // descriptor.h
+ namespace io {
+ class Printer; // printer.h
+ }
+ namespace compiler {
+ class OutputDirectory; // code_generator.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class FileGenerator {
+ public:
+ explicit FileGenerator(const FileDescriptor* file, const Params& params);
+ ~FileGenerator();
+
+ // Checks for problems that would otherwise lead to cryptic compile errors.
+ // Returns true if there are no problems, or writes an error description to
+ // the given string and returns false otherwise.
+ bool Validate(string* error);
+
+ void Generate(io::Printer* printer);
+
+ // If we aren't putting everything into one file, this will write all the
+ // files other than the outer file (i.e. one for each message, enum, and
+ // service type).
+ void GenerateSiblings(const string& package_dir,
+ OutputDirectory* output_directory,
+ vector<string>* file_list);
+
+ const string& java_package() { return java_package_; }
+ const string& classname() { return classname_; }
+
+ private:
+ const FileDescriptor* file_;
+ const Params& params_;
+ string java_package_;
+ string classname_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
new file mode 100644
index 00000000..554f6d4d
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -0,0 +1,170 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_generator.h>
+#include <google/protobuf/compiler/javanano/javanano_file.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+void UpdateParamsRecursively(Params& params,
+ const FileDescriptor* file) {
+ // Add any parameters for this file
+ if (file->options().has_java_outer_classname()) {
+ params.set_java_outer_classname(
+ file->name(), file->options().java_outer_classname());
+ }
+ if (file->options().has_java_package()) {
+ params.set_java_package(
+ file->name(), file->options().java_package());
+ }
+
+ // Loop through all dependent files recursively
+ // adding dep
+ for (int i = 0; i < file->dependency_count(); i++) {
+ UpdateParamsRecursively(params, file->dependency(i));
+ }
+}
+
+JavaNanoGenerator::JavaNanoGenerator() {}
+JavaNanoGenerator::~JavaNanoGenerator() {}
+
+bool JavaNanoGenerator::Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ vector<pair<string, string> > options;
+
+ ParseGeneratorParameter(parameter, &options);
+
+ // -----------------------------------------------------------------
+ // parse generator options
+
+ // Name a file where we will write a list of generated file names, one
+ // per line.
+ string output_list_file;
+ Params params(file->name());
+
+ // Get options from the proto file
+ if (file->options().has_java_multiple_files()) {
+ params.set_java_multiple_files(file->options().java_multiple_files());
+ }
+
+ // Update per file params
+ UpdateParamsRecursively(params, file);
+
+ // Replace any existing options with ones from command line
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "output_list_file") {
+ output_list_file = options[i].second;
+ } else if (options[i].first == "java_package") {
+ vector<string> parts;
+ SplitStringUsing(options[i].second, "|", &parts);
+ if (parts.size() != 2) {
+ *error = "Bad java_package, expecting filename|PackageName found '"
+ + options[i].second + "'";
+ return false;
+ }
+ params.set_java_package(parts[0], parts[1]);
+ } else if (options[i].first == "java_outer_classname") {
+ vector<string> parts;
+ SplitStringUsing(options[i].second, "|", &parts);
+ if (parts.size() != 2) {
+ *error = "Bad java_outer_classname, "
+ "expecting filename|ClassName found '"
+ + options[i].second + "'";
+ return false;
+ }
+ params.set_java_outer_classname(parts[0], parts[1]);
+ } else if (options[i].first == "java_multiple_files") {
+ params.set_java_multiple_files(options[i].second == "true");
+ } else {
+ *error = "Ignore unknown javanano generator option: " + options[i].first;
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ FileGenerator file_generator(file, params);
+ if (!file_generator.Validate(error)) {
+ return false;
+ }
+
+ string package_dir =
+ StringReplace(file_generator.java_package(), ".", "/", true);
+ if (!package_dir.empty()) package_dir += "/";
+
+ vector<string> all_files;
+
+ string java_filename = package_dir;
+ java_filename += file_generator.classname();
+ java_filename += ".java";
+ all_files.push_back(java_filename);
+
+ // Generate main java file.
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(java_filename));
+ io::Printer printer(output.get(), '$');
+ file_generator.Generate(&printer);
+
+ // Generate sibling files.
+ file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
+
+ // Generate output list if requested.
+ if (!output_list_file.empty()) {
+ // Generate output list. This is just a simple text file placed in a
+ // deterministic location which lists the .java files being generated.
+ scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
+ output_directory->Open(output_list_file));
+ io::Printer srclist_printer(srclist_raw_output.get(), '$');
+ for (int i = 0; i < all_files.size(); i++) {
+ srclist_printer.Print("$filename$\n", "filename", all_files[i]);
+ }
+ }
+
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.h b/src/google/protobuf/compiler/javanano/javanano_generator.h
new file mode 100644
index 00000000..0c1e3a41
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Generates Java nano code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NANO_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_NANO_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// CodeGenerator implementation which generates Java nano code. If you create your
+// own protocol compiler binary and you want it to support Java output for the
+// nano runtime, you can do so by registering an instance of this CodeGenerator with
+// the CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator {
+ public:
+ JavaNanoGenerator();
+ ~JavaNanoGenerator();
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NANO_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
new file mode 100644
index 00000000..78395567
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -0,0 +1,404 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <vector>
+
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+const char kThickSeparator[] =
+ "// ===================================================================\n";
+const char kThinSeparator[] =
+ "// -------------------------------------------------------------------\n";
+
+namespace {
+
+const char* kDefaultPackage = "";
+
+const string& FieldName(const FieldDescriptor* field) {
+ // Groups are hacky: The name of the field is just the lower-cased name
+ // of the group type. In Java, though, we would like to retain the original
+ // capitalization of the type name.
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ return field->message_type()->name();
+ } else {
+ return field->name();
+ }
+}
+
+string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
+ string result;
+ // Note: I distrust ctype.h due to locales.
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ if (cap_next_letter) {
+ result += input[i] + ('A' - 'a');
+ } else {
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('A' <= input[i] && input[i] <= 'Z') {
+ if (i == 0 && !cap_next_letter) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result += input[i] + ('a' - 'A');
+ } else {
+ // Capital letters after the first are left as-is.
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('0' <= input[i] && input[i] <= '9') {
+ result += input[i];
+ cap_next_letter = true;
+ } else {
+ cap_next_letter = true;
+ }
+ }
+ return result;
+}
+
+} // namespace
+
+string UnderscoresToCamelCase(const FieldDescriptor* field) {
+ return UnderscoresToCamelCaseImpl(FieldName(field), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
+ return UnderscoresToCamelCaseImpl(FieldName(field), true);
+}
+
+string UnderscoresToCamelCase(const MethodDescriptor* method) {
+ return UnderscoresToCamelCaseImpl(method->name(), false);
+}
+
+string StripProto(const string& filename) {
+ if (HasSuffixString(filename, ".protodevel")) {
+ return StripSuffixString(filename, ".protodevel");
+ } else {
+ return StripSuffixString(filename, ".proto");
+ }
+}
+
+string FileClassName(const Params& params, const FileDescriptor* file) {
+ string name;
+
+ if (params.has_java_outer_classname(file->name())) {
+ name = params.java_outer_classname(file->name());
+ } else {
+ if ((file->message_type_count() == 1)
+ || (file->enum_type_count() == 0)) {
+ // If no outer calls and only one message then
+ // use the message name as the file name
+ name = file->message_type(0)->name();
+ } else {
+ // Use the filename it self with underscores removed
+ // and a CamelCase style name.
+ string basename;
+ string::size_type last_slash = file->name().find_last_of('/');
+ if (last_slash == string::npos) {
+ basename = file->name();
+ } else {
+ basename = file->name().substr(last_slash + 1);
+ }
+ name = UnderscoresToCamelCaseImpl(StripProto(basename), true);
+ }
+ }
+
+ return name;
+}
+
+string FileJavaPackage(const Params& params, const FileDescriptor* file) {
+ if (params.has_java_package(file->name())) {
+ return params.java_package(file->name());
+ } else {
+ string result = kDefaultPackage;
+ if (!file->package().empty()) {
+ if (!result.empty()) result += '.';
+ result += file->package();
+ }
+ return result;
+ }
+}
+
+string ToJavaName(const Params& params, const string& full_name,
+ const FileDescriptor* file) {
+ string result;
+ if (params.java_multiple_files()) {
+ result = FileJavaPackage(params, file);
+ } else {
+ result = ClassName(params, file);
+ }
+ if (file->package().empty()) {
+ result += '.';
+ result += full_name;
+ } else {
+ // Strip the proto package from full_name since we've replaced it with
+ // the Java package. If there isn't an outer classname then strip it too.
+ int sizeToSkipPackageName = file->package().size();
+ int sizeToSkipOutClassName;
+ if (params.has_java_outer_classname(file->name())) {
+ sizeToSkipOutClassName = 0;
+ } else {
+ sizeToSkipOutClassName =
+ full_name.find_first_of('.', sizeToSkipPackageName + 1);
+ }
+ int sizeToSkip = sizeToSkipOutClassName > 0 ?
+ sizeToSkipOutClassName : sizeToSkipPackageName;
+ string class_name = full_name.substr(sizeToSkip + 1);
+ if (class_name == FileClassName(params, file)) {
+ // Done class_name is already present.
+ } else {
+ result += '.';
+ result += class_name;
+ }
+ }
+ return result;
+}
+
+string ClassName(const Params& params, const FileDescriptor* descriptor) {
+ string result = FileJavaPackage(params, descriptor);
+ if (!result.empty()) result += '.';
+ result += FileClassName(params, descriptor);
+ return result;
+}
+
+string ClassName(const Params& params, const EnumDescriptor* descriptor) {
+ string result;
+ const FileDescriptor* file = descriptor->file();
+ const string file_name = file->name();
+ const string full_name = descriptor->full_name();
+
+ // Remove enum class name as we use int's for enums
+ string base_name = full_name.substr(0, full_name.find_last_of('.'));
+
+ if (!file->package().empty()) {
+ if (file->package() == base_name.substr(0, file->package().size())) {
+ // Remove package name leaving just the parent class of the enum
+ int offset = file->package().size();
+ if (base_name.size() > offset) {
+ // Remove period between package and class name if there is a classname
+ offset += 1;
+ }
+ base_name = base_name.substr(offset);
+ } else {
+ GOOGLE_LOG(FATAL) << "Expected package name to start an enum";
+ }
+ }
+
+ // Construct the path name from the package and outer class
+
+ // Add the java package name if it exsits
+ if (params.has_java_package(file_name)) {
+ result += params.java_package(file_name);
+ }
+
+ // Add the outer classname if it exists
+ if (params.has_java_outer_classname(file_name)) {
+ if (!result.empty()) {
+ result += ".";
+ }
+ result += params.java_outer_classname(file_name);
+ }
+
+ // Create the full class name from the base and path
+ if (!base_name.empty()) {
+ if (!result.empty()) {
+ result += ".";
+ }
+ result += base_name;
+ }
+ return result;
+}
+
+string FieldConstantName(const FieldDescriptor *field) {
+ string name = field->name() + "_FIELD_NUMBER";
+ UpperString(&name);
+ return name;
+}
+
+string FieldDefaultConstantName(const FieldDescriptor *field) {
+ string name = field->name() + "_DEFAULT";
+ UpperString(&name);
+ return name;
+}
+
+JavaType GetJavaType(FieldDescriptor::Type field_type) {
+ switch (field_type) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ return JAVATYPE_INT;
+
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ return JAVATYPE_LONG;
+
+ case FieldDescriptor::TYPE_FLOAT:
+ return JAVATYPE_FLOAT;
+
+ case FieldDescriptor::TYPE_DOUBLE:
+ return JAVATYPE_DOUBLE;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return JAVATYPE_BOOLEAN;
+
+ case FieldDescriptor::TYPE_STRING:
+ return JAVATYPE_STRING;
+
+ case FieldDescriptor::TYPE_BYTES:
+ return JAVATYPE_BYTES;
+
+ case FieldDescriptor::TYPE_ENUM:
+ return JAVATYPE_ENUM;
+
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ return JAVATYPE_MESSAGE;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return JAVATYPE_INT;
+}
+
+const char* BoxedPrimitiveTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return "java.lang.Integer";
+ case JAVATYPE_LONG : return "java.lang.Long";
+ case JAVATYPE_FLOAT : return "java.lang.Float";
+ case JAVATYPE_DOUBLE : return "java.lang.Double";
+ case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
+ case JAVATYPE_STRING : return "java.lang.String";
+ case JAVATYPE_BYTES : return "byte[]";
+ case JAVATYPE_ENUM : return "java.lang.Integer";
+ case JAVATYPE_MESSAGE: return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+string EmptyArrayName(const Params& params, const FieldDescriptor* field) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_INT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+ case JAVATYPE_LONG : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY";
+ case JAVATYPE_FLOAT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY";
+ case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY";
+ case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY";
+ case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY";
+ case JAVATYPE_BYTES : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY";
+ case JAVATYPE_ENUM : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+ case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY";
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+string DefaultValue(const Params& params, const FieldDescriptor* field) {
+ if (field->label() == FieldDescriptor::LABEL_REPEATED) {
+ return EmptyArrayName(params, field);
+ }
+
+ // Switch on cpp_type since we need to know which default_value_* method
+ // of FieldDescriptor to call.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return SimpleItoa(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ // Need to print as a signed int since Java has no unsigned.
+ return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
+ case FieldDescriptor::CPPTYPE_INT64:
+ return SimpleItoa(field->default_value_int64()) + "L";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
+ "L";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return SimpleDtoa(field->default_value_double()) + "D";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return SimpleFtoa(field->default_value_float()) + "F";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "true" : "false";
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (!field->default_value_string().empty()) {
+ // Point it to the static final in the generated code.
+ return FieldDefaultConstantName(field);
+ } else {
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES";
+ } else {
+ return "\"\"";
+ }
+ }
+
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return ClassName(params, field->enum_type()) + "." +
+ field->default_value_enum()->name();
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "null";
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
new file mode 100644
index 00000000..04e0c2e9
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -0,0 +1,132 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
+
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// Commonly-used separator comments. Thick is a line of '=', thin is a line
+// of '-'.
+extern const char kThickSeparator[];
+extern const char kThinSeparator[];
+
+// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
+// "fooBarBaz" or "FooBarBaz", respectively.
+string UnderscoresToCamelCase(const FieldDescriptor* field);
+string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
+
+// Similar, but for method names. (Typically, this merely has the effect
+// of lower-casing the first letter of the name.)
+string UnderscoresToCamelCase(const MethodDescriptor* method);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+string StripProto(const string& filename);
+
+// Gets the unqualified class name for the file. Each .proto file becomes a
+// single Java class, with all its contents nested in that class.
+string FileClassName(const Params& params, const FileDescriptor* file);
+
+// Returns the file's Java package name.
+string FileJavaPackage(const Params& params, const FileDescriptor* file);
+
+// Converts the given fully-qualified name in the proto namespace to its
+// fully-qualified name in the Java namespace, given that it is in the given
+// file.
+string ToJavaName(const Params& params, const string& full_name,
+ const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+inline string ClassName(const Params& params, const Descriptor* descriptor) {
+ return ToJavaName(params, descriptor->full_name(), descriptor->file());
+}
+string ClassName(const Params& params, const EnumDescriptor* descriptor);
+inline string ClassName(const Params& params,
+ const ServiceDescriptor* descriptor) {
+ return ToJavaName(params, descriptor->full_name(), descriptor->file());
+}
+inline string ExtensionIdentifierName(const Params& params,
+ const FieldDescriptor* descriptor) {
+ return ToJavaName(params, descriptor->full_name(), descriptor->file());
+}
+string ClassName(const Params& params, const FileDescriptor* descriptor);
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+string FieldConstantName(const FieldDescriptor *field);
+
+string FieldDefaultConstantName(const FieldDescriptor *field);
+
+enum JavaType {
+ JAVATYPE_INT,
+ JAVATYPE_LONG,
+ JAVATYPE_FLOAT,
+ JAVATYPE_DOUBLE,
+ JAVATYPE_BOOLEAN,
+ JAVATYPE_STRING,
+ JAVATYPE_BYTES,
+ JAVATYPE_ENUM,
+ JAVATYPE_MESSAGE
+};
+
+JavaType GetJavaType(FieldDescriptor::Type field_type);
+
+inline JavaType GetJavaType(const FieldDescriptor* field) {
+ return GetJavaType(field->type());
+}
+
+// Get the fully-qualified class name for a boxed primitive type, e.g.
+// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
+// types.
+const char* BoxedPrimitiveTypeName(JavaType type);
+
+string EmptyArrayName(const Params& params, const FieldDescriptor* field);
+
+string DefaultValue(const Params& params, const FieldDescriptor* field);
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
new file mode 100644
index 00000000..f8a4fe78
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -0,0 +1,372 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/javanano/javanano_message.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
+ // Print the field's proto-syntax definition as a comment. We don't want to
+ // print group bodies so we cut off after the first line.
+ string def = field->DebugString();
+ printer->Print("// $def$\n",
+ "def", def.substr(0, def.find_first_of('\n')));
+}
+
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor*[descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByNumber());
+ return fields;
+}
+
+// Get an identifier that uniquely identifies this type within the file.
+// This is used to declare static variables related to this type at the
+// outermost file scope.
+string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
+ return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
+}
+
+} // namespace
+
+// ===================================================================
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
+ : params_(params),
+ descriptor_(descriptor),
+ field_generators_(descriptor, params) {
+}
+
+MessageGenerator::~MessageGenerator() {}
+
+void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
+ // Generate static members for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ MessageGenerator(descriptor_->nested_type(i), params_)
+ .GenerateStaticVariables(printer);
+ }
+}
+
+void MessageGenerator::GenerateStaticVariableInitializers(
+ io::Printer* printer) {
+ // Generate static member initializers for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ MessageGenerator(descriptor_->nested_type(i), params_)
+ .GenerateStaticVariableInitializers(printer);
+ }
+
+ if (descriptor_->extension_count() != 0) {
+ GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n";
+ }
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+ bool is_own_file =
+ params_.java_multiple_files() || ((descriptor_->containing_type() == NULL)
+ && !params_.has_java_outer_classname(descriptor_->file()->name()));
+
+#if 0
+ GOOGLE_LOG(INFO) << "is_own_file=" << is_own_file;
+ GOOGLE_LOG(INFO) << "containing_type()=" << ((descriptor_->containing_type() == NULL) ? "NULL" : "not null");
+ GOOGLE_LOG(INFO) << "java_multiple_files()=" << params_.java_multiple_files();
+ GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name());
+#endif
+
+ if ((descriptor_->extension_count() != 0)
+ || (descriptor_->extension_range_count() != 0)) {
+ GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n";
+ }
+
+ // Note: Fields (which will be emitted in the loop, below) may have the same names as fields in
+ // the inner or outer class. This causes Java warnings, but is not fatal, so we suppress those
+ // warnings here in the class declaration.
+ printer->Print(
+ "@SuppressWarnings(\"hiding\")\n"
+ "public $modifiers$ final class $classname$ extends\n"
+ " com.google.protobuf.nano.MessageNano {\n",
+ "modifiers", is_own_file ? "" : "static",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Print(
+ "public static final $classname$ EMPTY_ARRAY[] = {};\n"
+ "public $classname$() {}\n"
+ "\n",
+ "classname", descriptor_->name());
+
+ // Nested types and extensions
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
+ }
+
+ // Fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ PrintFieldComment(printer, descriptor_->field(i));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ GenerateClear(printer);
+ GenerateMessageSerializationMethods(printer);
+ GenerateMergeFromMethods(printer);
+ GenerateParseFromMethods(printer);
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+// ===================================================================
+
+void MessageGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ if (descriptor_->extension_range_count() != 0) {
+ GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n";
+ }
+
+ // writeTo only throws an exception if it contains one or more fields to write
+ if (descriptor_->field_count() > 0) {
+ printer->Print(
+ "@Override\n"
+ "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
+ " throws java.io.IOException {\n");
+ } else {
+ printer->Print(
+ "@Override\n"
+ "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output) {\n");
+ }
+ printer->Indent();
+
+ // Output the fields in sorted order
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ GenerateSerializeOneField(printer, sorted_fields[i]);
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n"
+ "private int cachedSize = -1;\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();
+
+ 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"
+ "\n");
+}
+
+void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print(
+ "@Override\n"
+ "public $classname$ mergeFrom(\n"
+ " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
+ " throws java.io.IOException {\n",
+ "classname", descriptor_->name());
+
+ printer->Indent();
+
+ printer->Print(
+ "while (true) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "int tag = input.readTag();\n"
+ "switch (tag) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "case 0:\n" // zero signals EOF / limit reached
+ " return this;\n"
+ "default: {\n"
+ " if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
+ " return this;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ uint32 tag = WireFormatLite::MakeTag(field->number(),
+ WireFormat::WireTypeForField(field));
+
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ " }\n" // while (true)
+ "}\n"
+ "\n");
+}
+
+void MessageGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+ bool is_own_file =
+ descriptor_->containing_type() == NULL;
+
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ printer->Print(
+ "public $static$ $classname$ parseFrom(byte[] data)\n"
+ " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
+ " return ($classname$) com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
+ "}\n"
+ "\n"
+ "public $static$ $classname$ parseFrom(\n"
+ " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
+ " throws java.io.IOException {\n"
+ " return new $classname$().mergeFrom(input);\n"
+ "}\n"
+ "\n",
+ "static", (is_own_file ? "static" : ""),
+ "classname", descriptor_->name());
+}
+
+void MessageGenerator::GenerateSerializeOneField(
+ io::Printer* printer, const FieldDescriptor* field) {
+ field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void MessageGenerator::GenerateClear(io::Printer* printer) {
+ printer->Print(
+ "public final $classname$ clear() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ // Call clear for all of the fields.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ if (field->type() == FieldDescriptor::TYPE_BYTES &&
+ !field->default_value_string().empty()) {
+ // Need to clone the default value because it is of a mutable
+ // type.
+ printer->Print(
+ "$name$ = $default$.clone();\n",
+ "name", UnderscoresToCamelCase(field),
+ "default", DefaultValue(params_, field));
+ } else {
+ printer->Print(
+ "$name$ = $default$;\n",
+ "name", UnderscoresToCamelCase(field),
+ "default", DefaultValue(params_, field));
+ }
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " cachedSize = -1;\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h
new file mode 100644
index 00000000..d59ec9f0
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message.h
@@ -0,0 +1,92 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MessageGenerator {
+ public:
+ explicit MessageGenerator(const Descriptor* descriptor, const Params& params);
+ ~MessageGenerator();
+
+ // All static variables have to be declared at the top-level of the file
+ // so that we can control initialization order, which is important for
+ // DescriptorProto bootstrapping to work.
+ void GenerateStaticVariables(io::Printer* printer);
+
+ // Output code which initializes the static variables generated by
+ // GenerateStaticVariables().
+ void GenerateStaticVariableInitializers(io::Printer* printer);
+
+ // Generate the class itself.
+ void Generate(io::Printer* printer);
+
+ private:
+ void GenerateMessageSerializationMethods(io::Printer* printer);
+ void GenerateMergeFromMethods(io::Printer* printer);
+ void GenerateParseFromMethods(io::Printer* printer);
+ void GenerateSerializeOneField(io::Printer* printer,
+ const FieldDescriptor* field);
+
+ void GenerateClear(io::Printer* printer);
+
+ const Params& params_;
+ const Descriptor* descriptor_;
+ FieldGeneratorMap field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
new file mode 100644
index 00000000..6d89bd52
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -0,0 +1,216 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_message_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
+// repeat code between this and the other field types.
+void SetMessageVariables(const Params& params,
+ const FieldDescriptor* descriptor, map<string, string>* variables) {
+ (*variables)["name"] =
+ UnderscoresToCamelCase(descriptor);
+ (*variables)["capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(descriptor);
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["type"] = ClassName(params, descriptor->message_type());
+ (*variables)["group_or_message"] =
+ (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
+ "Group" : "Message";
+ (*variables)["message_name"] = descriptor->containing_type()->name();
+ //(*variables)["message_type"] = descriptor->message_type()->name();
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+}
+
+} // namespace
+
+// ===================================================================
+
+MessageFieldGenerator::
+MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMessageVariables(params, descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "public $type$ $name$ = null;\n");
+}
+
+void MessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.$name$ != null) {\n"
+ " merge$capitalized_name$(other.$name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "input.readGroup($name$, $number$);\n");
+ } else {
+ printer->Print(variables_,
+ "input.readMessage($name$);\n");
+ }
+}
+
+void MessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($name$ != null) {\n"
+ " output.write$group_or_message$($number$, $name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($name$ != null) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$group_or_message$Size($number$, $name$);\n"
+ "}\n");
+}
+
+string MessageFieldGenerator::GetBoxedType() const {
+ return ClassName(params_, descriptor_->message_type());
+}
+
+// ===================================================================
+
+RepeatedMessageFieldGenerator::
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMessageVariables(params, descriptor, &variables_);
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "public $type$[] $name$ = $type$.EMPTY_ARRAY;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.$name$.length > 0) {\n"
+ " $type$[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n"
+ " java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n"
+ " result.$name$ = merged;\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ // First, figure out the length of the array, then parse.
+ printer->Print(variables_,
+ "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n"
+ "int i = $name$.length;\n"
+ "$name$ = java.util.Arrays.copyOf($name$, i + arrayLength);\n"
+ "for (; i < $name$.length - 1; i++) {\n"
+ " $name$[i] = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ " input.readGroup($name$[i], $number$);\n");
+ } else {
+ printer->Print(variables_,
+ " input.readMessage($name$[i]);\n");
+ }
+
+ printer->Print(variables_,
+ " input.readTag();\n"
+ "}\n"
+ "// Last one without readTag.\n"
+ "$name$[i] = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "input.readGroup($name$[i], $number$);\n");
+ } else {
+ printer->Print(variables_,
+ "input.readMessage($name$[i]);\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for ($type$ element : $name$) {\n"
+ " output.write$group_or_message$($number$, element);\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for ($type$ element : $name$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$group_or_message$Size($number$, element);\n"
+ "}\n");
+}
+
+string RepeatedMessageFieldGenerator::GetBoxedType() const {
+ return ClassName(params_, descriptor_->message_type());
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
new file mode 100644
index 00000000..5fb00617
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MessageFieldGenerator : public FieldGenerator {
+ public:
+ explicit MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ ~MessageFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public FieldGenerator {
+ public:
+ explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params);
+ ~RepeatedMessageFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
new file mode 100644
index 00000000..f6192eae
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2010 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.
+
+// Author: wink@google.com (Wink Saville)
+
+#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
+#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
+
+#include <map>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// Parameters for used by the generators
+class Params {
+ public:
+ typedef map<string, string> NameMap;
+ private:
+ string empty_;
+ string base_name_;
+ bool java_multiple_files_;
+ NameMap java_packages_;
+ NameMap java_outer_classnames_;
+
+ public:
+ Params(const string & base_name) :
+ empty_(""),
+ base_name_(base_name),
+ java_multiple_files_(false) {
+ }
+
+ const string& base_name() const {
+ return base_name_;
+ }
+
+ bool has_java_package(const string& file_name) const {
+ return java_packages_.find(file_name)
+ != java_packages_.end();
+ }
+ void set_java_package(const string& file_name,
+ const string& java_package) {
+ java_packages_[file_name] = java_package;
+ }
+ const string& java_package(const string& file_name) const {
+ NameMap::const_iterator itr;
+
+ itr = java_packages_.find(file_name);
+ if (itr == java_packages_.end()) {
+ return empty_;
+ } else {
+ return itr->second;
+ }
+ }
+ const NameMap& java_packages() {
+ return java_packages_;
+ }
+
+ bool has_java_outer_classname(const string& file_name) const {
+ return java_outer_classnames_.find(file_name)
+ != java_outer_classnames_.end();
+ }
+ void set_java_outer_classname(const string& file_name,
+ const string& java_outer_classname) {
+ java_outer_classnames_[file_name] = java_outer_classname;
+ }
+ const string& java_outer_classname(const string& file_name) const {
+ NameMap::const_iterator itr;
+
+ itr = java_outer_classnames_.find(file_name);
+ if (itr == java_outer_classnames_.end()) {
+ return empty_;
+ } else {
+ return itr->second;
+ }
+ }
+ const NameMap& java_outer_classnames() {
+ return java_outer_classnames_;
+ }
+
+ void set_java_multiple_files(bool value) {
+ java_multiple_files_ = value;
+ }
+ bool java_multiple_files() const {
+ return java_multiple_files_;
+ }
+
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
new file mode 100644
index 00000000..041d22ff
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -0,0 +1,493 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* PrimitiveTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return "int";
+ case JAVATYPE_LONG : return "long";
+ case JAVATYPE_FLOAT : return "float";
+ case JAVATYPE_DOUBLE : return "double";
+ case JAVATYPE_BOOLEAN: return "boolean";
+ case JAVATYPE_STRING : return "java.lang.String";
+ case JAVATYPE_BYTES : return "byte[]";
+ case JAVATYPE_ENUM : return NULL;
+ case JAVATYPE_MESSAGE: return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+bool IsReferenceType(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return false;
+ case JAVATYPE_LONG : return false;
+ case JAVATYPE_FLOAT : return false;
+ case JAVATYPE_DOUBLE : return false;
+ case JAVATYPE_BOOLEAN: return false;
+ case JAVATYPE_STRING : return true;
+ case JAVATYPE_BYTES : return true;
+ case JAVATYPE_ENUM : return false;
+ case JAVATYPE_MESSAGE: return true;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
+bool IsArrayType(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return false;
+ case JAVATYPE_LONG : return false;
+ case JAVATYPE_FLOAT : return false;
+ case JAVATYPE_DOUBLE : return false;
+ case JAVATYPE_BOOLEAN: return false;
+ case JAVATYPE_STRING : return false;
+ case JAVATYPE_BYTES : return true;
+ case JAVATYPE_ENUM : return false;
+ case JAVATYPE_MESSAGE: return false;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
+const char* GetCapitalizedType(const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32 : return "Int32" ;
+ case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
+ case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
+ case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
+ case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
+ case FieldDescriptor::TYPE_INT64 : return "Int64" ;
+ case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
+ case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
+ case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
+ case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
+ case FieldDescriptor::TYPE_FLOAT : return "Float" ;
+ case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
+ case FieldDescriptor::TYPE_BOOL : return "Bool" ;
+ case FieldDescriptor::TYPE_STRING : return "String" ;
+ case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
+ case FieldDescriptor::TYPE_ENUM : return "Enum" ;
+ case FieldDescriptor::TYPE_GROUP : return "Group" ;
+ case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32 : return -1;
+ case FieldDescriptor::TYPE_INT64 : return -1;
+ case FieldDescriptor::TYPE_UINT32 : return -1;
+ case FieldDescriptor::TYPE_UINT64 : return -1;
+ case FieldDescriptor::TYPE_SINT32 : return -1;
+ case FieldDescriptor::TYPE_SINT64 : return -1;
+ case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
+ case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
+ case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
+ case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
+ case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
+ case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
+
+ case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
+ case FieldDescriptor::TYPE_ENUM : return -1;
+
+ case FieldDescriptor::TYPE_STRING : return -1;
+ case FieldDescriptor::TYPE_BYTES : return -1;
+ case FieldDescriptor::TYPE_GROUP : return -1;
+ case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1;
+}
+
+// Return true if the type is a that has variable length
+// for instance String's.
+bool IsVariableLenType(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return false;
+ case JAVATYPE_LONG : return false;
+ case JAVATYPE_FLOAT : return false;
+ case JAVATYPE_DOUBLE : return false;
+ case JAVATYPE_BOOLEAN: return false;
+ case JAVATYPE_STRING : return true;
+ case JAVATYPE_BYTES : return true;
+ case JAVATYPE_ENUM : return false;
+ case JAVATYPE_MESSAGE: return true;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
+bool AllAscii(const string& text) {
+ for (int i = 0; i < text.size(); i++) {
+ if ((text[i] & 0x80) != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
+ map<string, string>* variables) {
+ (*variables)["name"] =
+ UnderscoresToCamelCase(descriptor);
+ (*variables)["capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(descriptor);
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
+ // For C++-string types (string and bytes), we might need to have
+ // the generated code do the unicode decoding (see comments in
+ // InternalNano.java for gory details.). We would like to do this
+ // once into a "private static final" field and re-use that from
+ // then on.
+ if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ !descriptor->default_value_string().empty()) {
+ string default_value;
+ if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+ default_value = strings::Substitute(
+ "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
+ CEscape(descriptor->default_value_string()));
+ } else {
+ if (AllAscii(descriptor->default_value_string())) {
+ // All chars are ASCII. In this case CEscape() works fine.
+ default_value = "\"" + CEscape(descriptor->default_value_string()) + "\"";
+ } else {
+ default_value = strings::Substitute(
+ "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
+ CEscape(descriptor->default_value_string()));
+ }
+ }
+ (*variables)["default_constant_value"] = default_value;
+ }
+ (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ if (IsReferenceType(GetJavaType(descriptor))) {
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+ } else {
+ (*variables)["null_check"] = "";
+ }
+ int fixed_size = FixedSize(descriptor->type());
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+ }
+ (*variables)["message_name"] = descriptor->containing_type()->name();
+ (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
+}
+} // namespace
+
+// ===================================================================
+
+PrimitiveFieldGenerator::
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+void PrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ if (variables_.find("default_constant_value") != variables_.end()) {
+ // Those primitive types that need a saved default.
+ printer->Print(variables_,
+ "private static final $type$ $default_constant$ = $default_constant_value$;\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
+ printer->Print(variables_,
+ "public $type$ $name$ = $default$.clone();\n");
+ } else {
+ printer->Print(variables_,
+ "public $type$ $name$ = $default$;\n");
+ }
+ } else {
+ printer->Print(variables_,
+ "public $type$ $name$ = $default$;\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$ = other.$name$;\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = input.read$capitalized_type$();\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->is_required()) {
+ printer->Print(variables_,
+ "output.write$capitalized_type$($number$, $name$);\n");
+ } else {
+ if (IsArrayType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "if (!java.util.Arrays.equals($name$, $default$)) {\n");
+ } else if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "if (!$name$.equals($default$)) {\n");
+ } else {
+ printer->Print(variables_,
+ "if ($name$ != $default$) {\n");
+ }
+
+ printer->Print(variables_,
+ " output.write$capitalized_type$($number$, $name$);\n"
+ "}\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ if (descriptor_->is_required()) {
+ printer->Print(variables_,
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size($number$, $name$);\n");
+ } else {
+ if (IsArrayType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "if (!java.util.Arrays.equals($name$, $default$)) {\n");
+ } else if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "if (!$name$.equals($default$)) {\n");
+ } else {
+ printer->Print(variables_,
+ "if ($name$ != $default$) {\n");
+ }
+
+ printer->Print(variables_,
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size($number$, $name$);\n"
+ "}\n");
+ }
+}
+
+string PrimitiveFieldGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "public $type$[] $name$ = $default$;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.$name$.length > 0) {\n"
+ " $type$[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n"
+ " java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n"
+ " result.$name$ = merged;\n"
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ // First, figure out the length of the array, then parse.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "// First pass to compute array length.\n"
+ "int arrayLength = 0;\n"
+ "int startPos = input.getPosition();\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " input.read$capitalized_type$();\n"
+ " arrayLength++;\n"
+ "}\n"
+ "input.rewindToPosition(startPos);\n"
+ "$name$ = new $type$[arrayLength];\n"
+ "for (int i = 0; i < arrayLength; i++) {\n"
+ " $name$[i] = input.read$capitalized_type$();\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+ } else {
+ printer->Print(variables_,
+ "int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n"
+ "int i = $name$.length;\n"
+ "$name$ = java.util.Arrays.copyOf($name$, $name$.length + arrayLength);\n"
+ "for (; i < $name$.length - 1; i++) {\n"
+ " $name$[i] = input.read$capitalized_type$();\n"
+ " input.readTag();\n"
+ "}\n"
+ "// Last one without readTag.\n"
+ "$name$[i] = input.read$capitalized_type$();\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if ($name$.length > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n");
+ printer->Print(variables_,
+ "for ($type$ element : $name$) {\n"
+ " output.write$capitalized_type$NoTag(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : $name$) {\n"
+ " output.write$capitalized_type$($number$, element);\n"
+ "}\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($name$.length > 0) {\n");
+ printer->Indent();
+
+ if (FixedSize(descriptor_->type()) == -1) {
+ printer->Print(variables_,
+ "int dataSize = 0;\n"
+ "for ($type$ element : $name$) {\n"
+ " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$SizeNoTag(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "int dataSize = $fixed_size$ * $name$.length;\n");
+ }
+
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ // cache the data size for packed fields.
+ printer->Print(variables_,
+ "size += $tag_size$;\n"
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeRawVarint32Size(dataSize);\n"
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * $name$.length;\n");
+ }
+
+ printer->Outdent();
+
+ // set cached size to 0 for empty packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "} else {\n"
+ " $name$MemoizedSerializedSize = 0;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "}\n");
+ }
+}
+
+string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
new file mode 100644
index 00000000..7c14e4c2
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class PrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params &params);
+ ~PrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ ~RepeatedPrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
diff --git a/src/google/protobuf/unittest_import_nano.proto b/src/google/protobuf/unittest_import_nano.proto
new file mode 100644
index 00000000..7813715b
--- /dev/null
+++ b/src/google/protobuf/unittest_import_nano.proto
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest_import.proto but with optimize_for = NANO_RUNTIME.
+
+package protobuf_unittest_import;
+
+// java_package and java_outer_classname are specified on the command line.
+//option java_package = "com.google.protobuf.nano";
+//option java_outer_classname = "UnittestImportNano";
+
+message ImportMessageNano {
+ optional int32 d = 1;
+}
+
+enum ImportEnumNano {
+ IMPORT_NANO_FOO = 7;
+ IMPORT_NANO_BAR = 8;
+ IMPORT_NANO_BAZ = 9;
+}
diff --git a/src/google/protobuf/unittest_nano.proto b/src/google/protobuf/unittest_nano.proto
new file mode 100644
index 00000000..c689ac0e
--- /dev/null
+++ b/src/google/protobuf/unittest_nano.proto
@@ -0,0 +1,171 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: wink@google.com (Wink Saville)
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest_import_nano.proto";
+
+option java_package = "com.google.protobuf.nano";
+option java_outer_classname = "NanoOuterClass";
+
+// Same as TestAllTypes but with the nano runtime.
+message TestAllTypesNano {
+
+ message NestedMessage {
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessageNano optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessageNano
+ optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnumNano optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnumNano optional_import_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessageNano repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessageNano
+ repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnumNano repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnumNano repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ // Repeated packed
+ repeated int32 repeated_packed_int32 = 87 [packed=true];
+ repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true];
+
+ repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true];
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional int64 default_int64 = 62 [default = 42 ];
+ optional uint32 default_uint32 = 63 [default = 43 ];
+ optional uint64 default_uint64 = 64 [default = 44 ];
+ optional sint32 default_sint32 = 65 [default = -45 ];
+ optional sint64 default_sint64 = 66 [default = 46 ];
+ optional fixed32 default_fixed32 = 67 [default = 47 ];
+ optional fixed64 default_fixed64 = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32 = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64 = 70 [default = -50 ];
+ optional float default_float = 71 [default = 51.5 ];
+ optional double default_double = 72 [default = 52e3 ];
+ optional bool default_bool = 73 [default = true ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional string default_string_nonascii = 76 [default = "dünya"];
+ optional bytes default_bytes_nonascii = 77 [default = "dünyab"];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR];
+ optional ForeignEnumNano default_foreign_enum = 82
+ [default = FOREIGN_NANO_BAR];
+ optional protobuf_unittest_import.ImportEnumNano
+ default_import_enum = 83 [default = IMPORT_NANO_BAR];
+
+ optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+ optional string default_cord = 85 [ctype=CORD,default="123"];
+
+ required int32 id = 86;
+}
+
+message ForeignMessageNano {
+ optional int32 c = 1;
+}
+
+enum ForeignEnumNano {
+ FOREIGN_NANO_FOO = 4;
+ FOREIGN_NANO_BAR = 5;
+ FOREIGN_NANO_BAZ = 6;
+}
+
+// Test that deprecated fields work. We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedNano {
+ optional int32 deprecated_field = 1 [deprecated = true];
+}
diff --git a/src/google/protobuf/unittest_recursive_nano.proto b/src/google/protobuf/unittest_recursive_nano.proto
new file mode 100644
index 00000000..a62613ed
--- /dev/null
+++ b/src/google/protobuf/unittest_recursive_nano.proto
@@ -0,0 +1,47 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: wink@google.com (Wink Saville)
+//
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.nano";
+
+message RecursiveMessageNano {
+ message NestedMessage {
+ optional RecursiveMessageNano a = 1;
+ }
+
+ required int32 id = 1;
+ optional NestedMessage nested_message = 2;
+ optional RecursiveMessageNano optional_recursive_message_nano = 3;
+ repeated RecursiveMessageNano repeated_recursive_message_nano = 4;
+}
diff --git a/src/google/protobuf/unittest_simple_nano.proto b/src/google/protobuf/unittest_simple_nano.proto
new file mode 100644
index 00000000..287e962f
--- /dev/null
+++ b/src/google/protobuf/unittest_simple_nano.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: wink@google.com (Wink Saville)
+//
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.nano";
+
+message SimpleMessageNano {
+ message NestedMessage {
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ optional int32 d = 1 [default = 123];
+ optional NestedMessage nested_msg = 2;
+ optional NestedEnum default_nested_enum = 3 [default = BAZ];
+}
diff --git a/src/google/protobuf/unittest_stringutf8_nano.proto b/src/google/protobuf/unittest_stringutf8_nano.proto
new file mode 100644
index 00000000..da624b0e
--- /dev/null
+++ b/src/google/protobuf/unittest_stringutf8_nano.proto
@@ -0,0 +1,41 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
+// Author: wink@google.com (Wink Saville)
+//
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.nano";
+
+message StringUtf8 {
+ optional string id = 1;
+ repeated string rs = 2;
+}