am 0a1429cc: Merge "Nano support for extensions and unknown fields."
* commit '0a1429cc5ee4865550bcdddfae681a30cef58a5a': Nano support for extensions and unknown fields.
This commit is contained in:
commit
50acfdac08
@ -108,6 +108,7 @@ COMPILER_SRC_FILES := \
|
||||
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_extension.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 \
|
||||
|
@ -540,6 +540,23 @@ public final class CodedInputByteBufferNano {
|
||||
return bufferPos - bufferStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a subset of data in the buffer. The returned array is not backed by the original
|
||||
* buffer array.
|
||||
*
|
||||
* @param offset the position (relative to the buffer start position) to start at.
|
||||
* @param length the number of bytes to retrieve.
|
||||
*/
|
||||
public byte[] getData(int offset, int length) {
|
||||
if (length == 0) {
|
||||
return WireFormatNano.EMPTY_BYTES;
|
||||
}
|
||||
byte[] copy = new byte[length];
|
||||
int start = bufferStart + offset;
|
||||
System.arraycopy(buffer, start, copy, 0, length);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind to previous position. Cannot go forward.
|
||||
*/
|
||||
|
114
java/src/main/java/com/google/protobuf/nano/Extension.java
Normal file
114
java/src/main/java/com/google/protobuf/nano/Extension.java
Normal file
@ -0,0 +1,114 @@
|
||||
// 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.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents an extension.
|
||||
*
|
||||
* @author bduff@google.com (Brian Duff)
|
||||
* @param <T> the type of the extension.
|
||||
*/
|
||||
public class Extension<T> {
|
||||
public final int fieldNumber;
|
||||
public boolean isRepeatedField;
|
||||
public Class<T> fieldType;
|
||||
public Class<T> listType;
|
||||
|
||||
private Extension(int fieldNumber, TypeLiteral<T> type) {
|
||||
this.fieldNumber = fieldNumber;
|
||||
isRepeatedField = type.isList();
|
||||
fieldType = type.getTargetClass();
|
||||
listType = isRepeatedField ? type.getListType() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code Extension} for the specified {@code fieldNumber} and
|
||||
* {@code type}.
|
||||
*/
|
||||
public static <T> Extension<T> create(int fieldNumber, TypeLiteral<T> type) {
|
||||
return new Extension<T>(fieldNumber, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code Extension} for the specified {@code fieldNumber} and
|
||||
* {@code type}. This version is used for repeated fields.
|
||||
*/
|
||||
public static <T> Extension<List<T>> createRepeated(int fieldNumber, TypeLiteral<List<T>> type) {
|
||||
return new Extension<List<T>>(fieldNumber, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a generic type literal. We can't typesafely reference a
|
||||
* Class<List<Foo>>.class in Java, so we use this instead.
|
||||
* See: http://gafter.blogspot.com/2006/12/super-type-tokens.html
|
||||
*
|
||||
* <p>Somewhat specialized because we only ever have a Foo or a List<Foo>.
|
||||
*/
|
||||
public static abstract class TypeLiteral<T> {
|
||||
private final Type type;
|
||||
|
||||
protected TypeLiteral() {
|
||||
Type superclass = getClass().getGenericSuperclass();
|
||||
if (superclass instanceof Class) {
|
||||
throw new RuntimeException("Missing type parameter");
|
||||
}
|
||||
this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* If the generic type is a list, returns {@code true}.
|
||||
*/
|
||||
private boolean isList() {
|
||||
return type instanceof ParameterizedType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<T> getListType() {
|
||||
return (Class<T>) ((ParameterizedType) type).getRawType();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the generic type is a list, returns the type of element in the list. Otherwise,
|
||||
* returns the actual type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<T> getTargetClass() {
|
||||
if (isList()) {
|
||||
return (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
}
|
||||
return (Class<T>) type;
|
||||
}
|
||||
}
|
||||
}
|
@ -93,7 +93,7 @@ public abstract class MessageNano {
|
||||
output.checkNoSpaceLeft();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Serializing to a byte array threw an IOException "
|
||||
+ "(should never happen).");
|
||||
+ "(should never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Stores unknown fields. These might be extensions or fields that the generated API doesn't
|
||||
* know about yet.
|
||||
*
|
||||
* @author bduff@google.com (Brian Duff)
|
||||
*/
|
||||
public final class UnknownFieldData {
|
||||
final int tag;
|
||||
final byte[] bytes;
|
||||
|
||||
UnknownFieldData(int tag, byte[] bytes) {
|
||||
this.tag = tag;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
}
|
@ -31,6 +31,9 @@
|
||||
package com.google.protobuf.nano;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used internally by the Protocol Buffer library and generated
|
||||
@ -97,8 +100,12 @@ public final class WireFormatNano {
|
||||
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.
|
||||
* Parses an unknown field. This implementation skips the field.
|
||||
*
|
||||
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
|
||||
* option is off.
|
||||
*
|
||||
* @return {@literal true} unless the tag is an end-group tag.
|
||||
*/
|
||||
public static boolean parseUnknownField(
|
||||
final CodedInputByteBufferNano input,
|
||||
@ -106,6 +113,30 @@ public final class WireFormatNano {
|
||||
return input.skipField(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the binary data of an unknown field.
|
||||
*
|
||||
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
|
||||
* option is on.
|
||||
*
|
||||
* @param data a Collection in which to store the data.
|
||||
* @param input the input buffer.
|
||||
* @param tag the tag of the field.
|
||||
|
||||
* @return {@literal true} unless the tag is an end-group tag.
|
||||
*/
|
||||
public static boolean storeUnknownField(
|
||||
final List<UnknownFieldData> data,
|
||||
final CodedInputByteBufferNano input,
|
||||
final int tag) throws IOException {
|
||||
int startPos = input.getPosition();
|
||||
boolean skip = input.skipField(tag);
|
||||
int endPos = input.getPosition();
|
||||
byte[] bytes = input.getData(startPos, endPos - startPos);
|
||||
data.add(new UnknownFieldData(tag, bytes));
|
||||
return skip;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -135,4 +166,194 @@ public final class WireFormatNano {
|
||||
input.rewindToPosition(startPos);
|
||||
return arrayLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the value of an extension.
|
||||
*/
|
||||
public static <T> T getExtension(Extension<T> extension, List<UnknownFieldData> unknownFields) {
|
||||
if (unknownFields == null) {
|
||||
return null;
|
||||
}
|
||||
List<UnknownFieldData> dataForField = new ArrayList<UnknownFieldData>();
|
||||
for (UnknownFieldData data : unknownFields) {
|
||||
if (getTagFieldNumber(data.tag) == extension.fieldNumber) {
|
||||
dataForField.add(data);
|
||||
}
|
||||
}
|
||||
if (dataForField.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (extension.isRepeatedField) {
|
||||
List<Object> result = new ArrayList<Object>(dataForField.size());
|
||||
for (UnknownFieldData data : dataForField) {
|
||||
result.add(readData(extension.fieldType, data.bytes));
|
||||
}
|
||||
return extension.listType.cast(result);
|
||||
}
|
||||
|
||||
// Normal fields. Note that the protobuf docs require us to handle multiple instances
|
||||
// of the same field even for fields that are not repeated.
|
||||
UnknownFieldData lastData = dataForField.get(dataForField.size() - 1);
|
||||
return readData(extension.fieldType, lastData.bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads (extension) data of the specified type from the specified byte array.
|
||||
*
|
||||
* @throws IllegalArgumentException if an error occurs while reading the data.
|
||||
*/
|
||||
private static <T> T readData(Class<T> clazz, byte[] data) {
|
||||
if (data.length == 0) {
|
||||
return null;
|
||||
}
|
||||
CodedInputByteBufferNano buffer = CodedInputByteBufferNano.newInstance(data);
|
||||
try {
|
||||
if (clazz == String.class) {
|
||||
return clazz.cast(buffer.readString());
|
||||
} else if (clazz == Integer.class) {
|
||||
return clazz.cast(buffer.readInt32());
|
||||
} else if (clazz == Long.class) {
|
||||
return clazz.cast(buffer.readInt64());
|
||||
} else if (clazz == Boolean.class) {
|
||||
return clazz.cast(buffer.readBool());
|
||||
} else if (clazz == Float.class) {
|
||||
return clazz.cast(buffer.readFloat());
|
||||
} else if (clazz == Double.class) {
|
||||
return clazz.cast(buffer.readDouble());
|
||||
} else if (clazz == byte[].class) {
|
||||
return clazz.cast(buffer.readBytes());
|
||||
} else if (MessageNano.class.isAssignableFrom(clazz)) {
|
||||
try {
|
||||
MessageNano message = (MessageNano) clazz.newInstance();
|
||||
buffer.readMessage(message);
|
||||
return clazz.cast(message);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException("Error creating instance of class " + clazz, e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalArgumentException("Error creating instance of class " + clazz, e);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled extension field type: " + clazz);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException("Error reading extension field", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void setExtension(Extension<T> extension, T value,
|
||||
List<UnknownFieldData> unknownFields) {
|
||||
// First, remove all unknown fields with this tag.
|
||||
for (Iterator<UnknownFieldData> i = unknownFields.iterator(); i.hasNext();) {
|
||||
UnknownFieldData data = i.next();
|
||||
if (extension.fieldNumber == getTagFieldNumber(data.tag)) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
// Repeated field.
|
||||
if (value instanceof List) {
|
||||
for (Object item : (List<?>) value) {
|
||||
unknownFields.add(write(extension.fieldNumber, item));
|
||||
}
|
||||
} else {
|
||||
unknownFields.add(write(extension.fieldNumber, value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes extension data and returns an {@link UnknownFieldData} containing
|
||||
* bytes and a tag.
|
||||
*
|
||||
* @throws IllegalArgumentException if an error occurs while writing.
|
||||
*/
|
||||
private static UnknownFieldData write(int fieldNumber, Object object) {
|
||||
byte[] data;
|
||||
int tag;
|
||||
Class<?> clazz = object.getClass();
|
||||
try {
|
||||
if (clazz == String.class) {
|
||||
String str = (String) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeStringSizeNoTag(str)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeStringNoTag(str);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
|
||||
} else if (clazz == Integer.class) {
|
||||
Integer integer = (Integer) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeInt32SizeNoTag(integer)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeInt32NoTag(integer);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_VARINT);
|
||||
} else if (clazz == Long.class) {
|
||||
Long longValue = (Long) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeInt64SizeNoTag(longValue)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeInt64NoTag(longValue);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_VARINT);
|
||||
} else if (clazz == Boolean.class) {
|
||||
Boolean boolValue = (Boolean) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeBoolSizeNoTag(boolValue)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeBoolNoTag(boolValue);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_VARINT);
|
||||
} else if (clazz == Float.class) {
|
||||
Float floatValue = (Float) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeFloatSizeNoTag(floatValue)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeFloatNoTag(floatValue);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_FIXED32);
|
||||
} else if (clazz == Double.class) {
|
||||
Double doubleValue = (Double) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeDoubleSizeNoTag(doubleValue)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeDoubleNoTag(doubleValue);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_FIXED64);
|
||||
} else if (clazz == byte[].class) {
|
||||
byte[] byteArrayValue = (byte[]) object;
|
||||
data = new byte[CodedOutputByteBufferNano.computeByteArraySizeNoTag(byteArrayValue)];
|
||||
CodedOutputByteBufferNano.newInstance(data).writeByteArrayNoTag(byteArrayValue);
|
||||
tag = makeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
|
||||
} else if (MessageNano.class.isAssignableFrom(clazz)) {
|
||||
MessageNano messageValue = (MessageNano) object;
|
||||
|
||||
int messageSize = messageValue.getSerializedSize();
|
||||
int delimiterSize = CodedOutputByteBufferNano.computeRawVarint32Size(messageSize);
|
||||
data = new byte[messageSize + delimiterSize];
|
||||
CodedOutputByteBufferNano buffer = CodedOutputByteBufferNano.newInstance(data);
|
||||
buffer.writeRawVarint32(messageSize);
|
||||
buffer.writeRawBytes(MessageNano.toByteArray(messageValue));
|
||||
tag = makeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled extension field type: " + clazz);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
return new UnknownFieldData(tag, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of unknown field data, compute the wire size.
|
||||
*/
|
||||
public static int computeWireSize(List<UnknownFieldData> unknownFields) {
|
||||
if (unknownFields == null) {
|
||||
return 0;
|
||||
}
|
||||
int size = 0;
|
||||
for (UnknownFieldData unknownField : unknownFields) {
|
||||
size += CodedOutputByteBufferNano.computeRawVarint32Size(unknownField.tag);
|
||||
size += unknownField.bytes.length;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write unknown fields.
|
||||
*/
|
||||
public static void writeUnknownFields(List<UnknownFieldData> unknownFields,
|
||||
CodedOutputByteBufferNano outBuffer) throws IOException {
|
||||
if (unknownFields == null) {
|
||||
return;
|
||||
}
|
||||
for (UnknownFieldData data : unknownFields) {
|
||||
outBuffer.writeTag(getTagFieldNumber(data.tag), getTagWireType(data.tag));
|
||||
outBuffer.writeRawBytes(data.bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,9 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import com.google.protobuf.nano.CodedInputByteBufferNano;
|
||||
import com.google.protobuf.nano.Extensions;
|
||||
import com.google.protobuf.nano.Extensions.AnotherMessage;
|
||||
import com.google.protobuf.nano.InternalNano;
|
||||
import com.google.protobuf.nano.MessageNano;
|
||||
import com.google.protobuf.nano.NanoOuterClass;
|
||||
@ -37,10 +40,12 @@ 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test nano runtime.
|
||||
*
|
||||
@ -2155,4 +2160,93 @@ public class NanoTest extends TestCase {
|
||||
assertTrue(protoPrint.contains(" default_int32: 41"));
|
||||
assertTrue(protoPrint.contains(" default_string: \"hello\""));
|
||||
}
|
||||
|
||||
public void testExtensions() throws Exception {
|
||||
Extensions.ExtendableMessage message = new Extensions.ExtendableMessage();
|
||||
message.field = 5;
|
||||
message.setExtension(Extensions.someString, "Hello World!");
|
||||
message.setExtension(Extensions.someBool, true);
|
||||
message.setExtension(Extensions.someInt, 42);
|
||||
message.setExtension(Extensions.someLong, 124234234234L);
|
||||
message.setExtension(Extensions.someFloat, 42.0f);
|
||||
message.setExtension(Extensions.someDouble, 422222.0);
|
||||
message.setExtension(Extensions.someEnum, Extensions.FIRST_VALUE);
|
||||
AnotherMessage another = new AnotherMessage();
|
||||
another.string = "Foo";
|
||||
another.value = true;
|
||||
message.setExtension(Extensions.someMessage, another);
|
||||
|
||||
message.setExtension(Extensions.someRepeatedString, list("a", "bee", "seeya"));
|
||||
message.setExtension(Extensions.someRepeatedBool, list(true, false, true));
|
||||
message.setExtension(Extensions.someRepeatedInt, list(4, 8, 15, 16, 23, 42));
|
||||
message.setExtension(Extensions.someRepeatedLong, list(4L, 8L, 15L, 16L, 23L, 42L));
|
||||
message.setExtension(Extensions.someRepeatedFloat, list(1.0f, 3.0f));
|
||||
message.setExtension(Extensions.someRepeatedDouble, list(55.133, 3.14159));
|
||||
message.setExtension(Extensions.someRepeatedEnum, list(Extensions.FIRST_VALUE,
|
||||
Extensions.SECOND_VALUE));
|
||||
AnotherMessage second = new AnotherMessage();
|
||||
second.string = "Whee";
|
||||
second.value = false;
|
||||
message.setExtension(Extensions.someRepeatedMessage, list(another, second));
|
||||
|
||||
byte[] data = MessageNano.toByteArray(message);
|
||||
|
||||
Extensions.ExtendableMessage deserialized = Extensions.ExtendableMessage.parseFrom(data);
|
||||
assertEquals(5, deserialized.field);
|
||||
assertEquals("Hello World!", deserialized.getExtension(Extensions.someString));
|
||||
assertEquals(Boolean.TRUE, deserialized.getExtension(Extensions.someBool));
|
||||
assertEquals(Integer.valueOf(42), deserialized.getExtension(Extensions.someInt));
|
||||
assertEquals(Long.valueOf(124234234234L), deserialized.getExtension(Extensions.someLong));
|
||||
assertEquals(Float.valueOf(42.0f), deserialized.getExtension(Extensions.someFloat));
|
||||
assertEquals(Double.valueOf(422222.0), deserialized.getExtension(Extensions.someDouble));
|
||||
assertEquals(Integer.valueOf(Extensions.FIRST_VALUE),
|
||||
deserialized.getExtension(Extensions.someEnum));
|
||||
assertEquals(another.string, deserialized.getExtension(Extensions.someMessage).string);
|
||||
assertEquals(another.value, deserialized.getExtension(Extensions.someMessage).value);
|
||||
assertEquals(list("a", "bee", "seeya"), deserialized.getExtension(Extensions.someRepeatedString));
|
||||
assertEquals(list(true, false, true), deserialized.getExtension(Extensions.someRepeatedBool));
|
||||
assertEquals(list(4, 8, 15, 16, 23, 42), deserialized.getExtension(Extensions.someRepeatedInt));
|
||||
assertEquals(list(4L, 8L, 15L, 16L, 23L, 42L), deserialized.getExtension(Extensions.someRepeatedLong));
|
||||
assertEquals(list(1.0f, 3.0f), deserialized.getExtension(Extensions.someRepeatedFloat));
|
||||
assertEquals(list(55.133, 3.14159), deserialized.getExtension(Extensions.someRepeatedDouble));
|
||||
assertEquals(list(Extensions.FIRST_VALUE,
|
||||
Extensions.SECOND_VALUE), deserialized.getExtension(Extensions.someRepeatedEnum));
|
||||
assertEquals("Foo", deserialized.getExtension(Extensions.someRepeatedMessage).get(0).string);
|
||||
assertEquals(true, deserialized.getExtension(Extensions.someRepeatedMessage).get(0).value);
|
||||
assertEquals("Whee", deserialized.getExtension(Extensions.someRepeatedMessage).get(1).string);
|
||||
assertEquals(false, deserialized.getExtension(Extensions.someRepeatedMessage).get(1).value);
|
||||
}
|
||||
|
||||
public void testUnknownFields() throws Exception {
|
||||
// Check that we roundtrip (serialize and deserialize) unrecognized fields.
|
||||
AnotherMessage message = new AnotherMessage();
|
||||
message.string = "Hello World";
|
||||
message.value = false;
|
||||
|
||||
byte[] bytes = MessageNano.toByteArray(message);
|
||||
int extraFieldSize = CodedOutputStream.computeStringSize(1001, "This is an unknown field");
|
||||
byte[] newBytes = new byte[bytes.length + extraFieldSize];
|
||||
System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
|
||||
CodedOutputStream.newInstance(newBytes, bytes.length, extraFieldSize).writeString(1001,
|
||||
"This is an unknown field");
|
||||
|
||||
// Deserialize with an unknown field.
|
||||
AnotherMessage deserialized = AnotherMessage.parseFrom(newBytes);
|
||||
byte[] serialized = MessageNano.toByteArray(deserialized);
|
||||
|
||||
assertEquals(newBytes.length, serialized.length);
|
||||
|
||||
// Clear, and make sure it clears everything.
|
||||
deserialized.clear();
|
||||
assertEquals(0, MessageNano.toByteArray(deserialized).length);
|
||||
}
|
||||
|
||||
private <T> List<T> list(T first, T... remaining) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
list.add(first);
|
||||
for (T item : remaining) {
|
||||
list.add(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
96
src/google/protobuf/compiler/javanano/javanano_extension.cc
Normal file
96
src/google/protobuf/compiler/javanano/javanano_extension.cc
Normal file
@ -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: bduff@google.com (Brian Duff)
|
||||
|
||||
#include <google/protobuf/compiler/javanano/javanano_extension.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace javanano {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
void SetVariables(const FieldDescriptor* descriptor, const Params params,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] = UnderscoresToCamelCase(descriptor);
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["extends"] = ClassName(params, descriptor->containing_type());
|
||||
|
||||
string type;
|
||||
JavaType java_type = GetJavaType(descriptor->type());
|
||||
switch (java_type) {
|
||||
case JAVATYPE_ENUM:
|
||||
type = "java.lang.Integer";
|
||||
break;
|
||||
case JAVATYPE_MESSAGE:
|
||||
type = ClassName(params, descriptor->message_type());
|
||||
break;
|
||||
default:
|
||||
type = BoxedPrimitiveTypeName(java_type);
|
||||
break;
|
||||
}
|
||||
(*variables)["type"] = type;
|
||||
}
|
||||
|
||||
ExtensionGenerator::
|
||||
ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params)
|
||||
: params_(params), descriptor_(descriptor) {
|
||||
SetVariables(descriptor, params, &variables_);
|
||||
}
|
||||
|
||||
ExtensionGenerator::~ExtensionGenerator() {}
|
||||
|
||||
void ExtensionGenerator::Generate(io::Printer* printer) const {
|
||||
if (descriptor_->is_repeated()) {
|
||||
printer->Print(variables_,
|
||||
"// Extends $extends$\n"
|
||||
"public static final com.google.protobuf.nano.Extension<java.util.List<$type$>> $name$ = \n"
|
||||
" com.google.protobuf.nano.Extension.createRepeated($number$,\n"
|
||||
" new com.google.protobuf.nano.Extension.TypeLiteral<java.util.List<$type$>>(){});\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"// Extends $extends$\n"
|
||||
"public static final com.google.protobuf.nano.Extension<$type$> $name$ =\n"
|
||||
" com.google.protobuf.nano.Extension.create($number$,\n"
|
||||
" new com.google.protobuf.nano.Extension.TypeLiteral<$type$>(){});\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace javanano
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
74
src/google/protobuf/compiler/javanano/javanano_extension.h
Normal file
74
src/google/protobuf/compiler/javanano/javanano_extension.h
Normal file
@ -0,0 +1,74 @@
|
||||
// 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: bduff@google.com (Brian Duff)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H_
|
||||
#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_params.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace javanano {
|
||||
|
||||
class ExtensionGenerator {
|
||||
public:
|
||||
explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
|
||||
~ExtensionGenerator();
|
||||
|
||||
void Generate(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const Params& params_;
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
|
||||
};
|
||||
|
||||
} // namespace javanano
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H_
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <google/protobuf/compiler/javanano/javanano_file.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_enum.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_extension.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_message.h>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
@ -94,10 +95,11 @@ bool FileGenerator::Validate(string* error) {
|
||||
// Check for extensions
|
||||
FileDescriptorProto file_proto;
|
||||
file_->CopyTo(&file_proto);
|
||||
if (UsesExtensions(file_proto)) {
|
||||
if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) {
|
||||
error->assign(file_->name());
|
||||
error->append(
|
||||
": Java NANO_RUNTIME does not support extensions\"");
|
||||
": Java NANO_RUNTIME only supports extensions when the "
|
||||
"'store_unknown_fields' generator option is 'true'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -179,6 +181,11 @@ void FileGenerator::Generate(io::Printer* printer) {
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// Extensions.
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
ExtensionGenerator(file_->extension(i), params_).Generate(printer);
|
||||
}
|
||||
|
||||
if (!params_.java_multiple_files()) {
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
EnumGenerator(file_->enum_type(i), params_).Generate(printer);
|
||||
|
@ -115,6 +115,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
|
||||
return false;
|
||||
}
|
||||
params.set_java_outer_classname(parts[0], parts[1]);
|
||||
} else if (options[i].first == "store_unknown_fields") {
|
||||
params.set_store_unknown_fields(options[i].second == "true");
|
||||
} else if (options[i].first == "java_multiple_files") {
|
||||
params.set_java_multiple_files(options[i].second == "true");
|
||||
} else {
|
||||
|
@ -36,6 +36,7 @@
|
||||
#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_extension.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
@ -117,10 +118,6 @@ void MessageGenerator::GenerateStaticVariableInitializers(
|
||||
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) {
|
||||
@ -135,9 +132,10 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
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";
|
||||
if (!params_.store_unknown_fields() &&
|
||||
(descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
|
||||
GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
|
||||
"'store_unknown_fields' generator option is 'true'\n";
|
||||
}
|
||||
|
||||
// Note: Fields (which will be emitted in the loop, below) may have the same names as fields in
|
||||
@ -156,7 +154,17 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
"\n",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
if (params_.store_unknown_fields()) {
|
||||
printer->Print(
|
||||
"private java.util.List<com.google.protobuf.nano.UnknownFieldData>\n"
|
||||
" unknownFieldData;\n");
|
||||
}
|
||||
|
||||
// Nested types and extensions
|
||||
for (int i = 0; i < descriptor_->extension_count(); i++) {
|
||||
ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
|
||||
}
|
||||
|
||||
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
||||
EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
|
||||
}
|
||||
@ -173,6 +181,24 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
}
|
||||
|
||||
GenerateClear(printer);
|
||||
|
||||
// If we have an extension range, generate accessors for extensions.
|
||||
if (params_.store_unknown_fields()
|
||||
&& descriptor_->extension_range_count() > 0) {
|
||||
printer->Print(
|
||||
"public <T> T getExtension(com.google.protobuf.nano.Extension<T> extension) {\n"
|
||||
" return com.google.protobuf.nano.WireFormatNano.getExtension(\n"
|
||||
" extension, unknownFieldData);\n"
|
||||
"}\n\n"
|
||||
"public <T> void setExtension(com.google.protobuf.nano.Extension<T> extension, T value) {\n"
|
||||
" if (unknownFieldData == null) {\n"
|
||||
" unknownFieldData = \n"
|
||||
" new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n"
|
||||
" }\n"
|
||||
" com.google.protobuf.nano.WireFormatNano.setExtension(\n"
|
||||
" extension, value, unknownFieldData);\n"
|
||||
"}\n\n");
|
||||
}
|
||||
GenerateMessageSerializationMethods(printer);
|
||||
GenerateMergeFromMethods(printer);
|
||||
GenerateParseFromMethods(printer);
|
||||
@ -188,12 +214,8 @@ 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) {
|
||||
if (descriptor_->field_count() > 0 || params_.store_unknown_fields()) {
|
||||
printer->Print(
|
||||
"@Override\n"
|
||||
"public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
|
||||
@ -207,7 +229,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
||||
|
||||
// Output the fields in sorted order
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
GenerateSerializeOneField(printer, sorted_fields[i]);
|
||||
GenerateSerializeOneField(printer, sorted_fields[i]);
|
||||
}
|
||||
|
||||
// Write unknown fields.
|
||||
if (params_.store_unknown_fields()) {
|
||||
printer->Print(
|
||||
"com.google.protobuf.nano.WireFormatNano.writeUnknownFields(\n"
|
||||
" unknownFieldData, output);\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
@ -233,6 +262,11 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
||||
field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
|
||||
}
|
||||
|
||||
if (params_.store_unknown_fields()) {
|
||||
printer->Print(
|
||||
"size += com.google.protobuf.nano.WireFormatNano.computeWireSize(unknownFieldData);\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" cachedSize = size;\n"
|
||||
@ -266,12 +300,28 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
|
||||
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");
|
||||
"default: {\n");
|
||||
|
||||
printer->Indent();
|
||||
if (params_.store_unknown_fields()) {
|
||||
printer->Print(
|
||||
"if (unknownFieldData == null) {\n"
|
||||
" unknownFieldData = \n"
|
||||
" new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n"
|
||||
"}\n"
|
||||
"if (!com.google.protobuf.nano.WireFormatNano.storeUnknownField(unknownFieldData, \n"
|
||||
" input, tag)) {\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
|
||||
" return this;\n" // it's an endgroup tag
|
||||
"}\n");
|
||||
}
|
||||
printer->Print("break;\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor* field = sorted_fields[i];
|
||||
@ -356,6 +406,11 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
// Clear unknown fields.
|
||||
if (params_.store_unknown_fields()) {
|
||||
printer->Print("unknownFieldData = null;\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" cachedSize = -1;\n"
|
||||
|
@ -49,6 +49,7 @@ class Params {
|
||||
string empty_;
|
||||
string base_name_;
|
||||
bool java_multiple_files_;
|
||||
bool store_unknown_fields_;
|
||||
NameMap java_packages_;
|
||||
NameMap java_outer_classnames_;
|
||||
|
||||
@ -56,6 +57,7 @@ class Params {
|
||||
Params(const string & base_name) :
|
||||
empty_(""),
|
||||
base_name_(base_name),
|
||||
store_unknown_fields_(false),
|
||||
java_multiple_files_(false) {
|
||||
}
|
||||
|
||||
@ -107,6 +109,13 @@ class Params {
|
||||
return java_outer_classnames_;
|
||||
}
|
||||
|
||||
void set_store_unknown_fields(bool value) {
|
||||
store_unknown_fields_ = value;
|
||||
}
|
||||
bool store_unknown_fields() const {
|
||||
return store_unknown_fields_;
|
||||
}
|
||||
|
||||
void set_java_multiple_files(bool value) {
|
||||
java_multiple_files_ = value;
|
||||
}
|
||||
|
44
src/google/protobuf/unittest_extension_nano.proto
Normal file
44
src/google/protobuf/unittest_extension_nano.proto
Normal file
@ -0,0 +1,44 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option java_outer_classname = "Extensions";
|
||||
option java_package = "com.google.protobuf.nano";
|
||||
|
||||
message ExtendableMessage {
|
||||
optional int32 field = 1;
|
||||
extensions 10 to max;
|
||||
}
|
||||
|
||||
enum AnEnum {
|
||||
FIRST_VALUE = 1;
|
||||
SECOND_VALUE = 2;
|
||||
}
|
||||
|
||||
message AnotherMessage {
|
||||
optional string string = 1;
|
||||
optional bool value = 2;
|
||||
}
|
||||
|
||||
extend ExtendableMessage {
|
||||
optional string some_string = 10;
|
||||
optional int32 some_int = 11;
|
||||
optional int64 some_long = 12;
|
||||
optional float some_float = 13;
|
||||
optional double some_double = 14;
|
||||
optional bool some_bool = 15;
|
||||
optional AnEnum some_enum = 16;
|
||||
optional AnotherMessage some_message = 17;
|
||||
repeated string some_repeated_string = 18;
|
||||
repeated int32 some_repeated_int = 19;
|
||||
repeated int64 some_repeated_long = 20;
|
||||
repeated float some_repeated_float = 21;
|
||||
repeated double some_repeated_double = 22;
|
||||
repeated bool some_repeated_bool = 23;
|
||||
repeated AnEnum some_repeated_enum = 24;
|
||||
repeated AnotherMessage some_repeated_message = 25;
|
||||
}
|
||||
|
||||
message ContainerMessage {
|
||||
extend ExtendableMessage {
|
||||
optional bool another_thing = 100;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user