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/javamicro/javamicro_primitive_field.cc \
|
||||||
src/google/protobuf/compiler/javanano/javanano_enum.cc \
|
src/google/protobuf/compiler/javanano/javanano_enum.cc \
|
||||||
src/google/protobuf/compiler/javanano/javanano_enum_field.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_field.cc \
|
||||||
src/google/protobuf/compiler/javanano/javanano_file.cc \
|
src/google/protobuf/compiler/javanano/javanano_file.cc \
|
||||||
src/google/protobuf/compiler/javanano/javanano_generator.cc \
|
src/google/protobuf/compiler/javanano/javanano_generator.cc \
|
||||||
|
@ -540,6 +540,23 @@ public final class CodedInputByteBufferNano {
|
|||||||
return bufferPos - bufferStart;
|
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.
|
* 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();
|
output.checkNoSpaceLeft();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Serializing to a byte array threw an IOException "
|
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;
|
package com.google.protobuf.nano;
|
||||||
|
|
||||||
import java.io.IOException;
|
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
|
* 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 = {};
|
public static final byte[] EMPTY_BYTES = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by subclasses to parse an unknown field.
|
* Parses an unknown field. This implementation skips the field.
|
||||||
* @return {@code true} unless the tag is an end-group tag.
|
*
|
||||||
|
* <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(
|
public static boolean parseUnknownField(
|
||||||
final CodedInputByteBufferNano input,
|
final CodedInputByteBufferNano input,
|
||||||
@ -106,6 +113,30 @@ public final class WireFormatNano {
|
|||||||
return input.skipField(tag);
|
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
|
* 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
|
* fields are contiguously serialized but we still correctly handle interspersed values of a
|
||||||
@ -135,4 +166,194 @@ public final class WireFormatNano {
|
|||||||
input.rewindToPosition(startPos);
|
input.rewindToPosition(startPos);
|
||||||
return arrayLength;
|
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;
|
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.InternalNano;
|
||||||
import com.google.protobuf.nano.MessageNano;
|
import com.google.protobuf.nano.MessageNano;
|
||||||
import com.google.protobuf.nano.NanoOuterClass;
|
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.RecursiveMessageNano;
|
||||||
import com.google.protobuf.nano.SimpleMessageNano;
|
import com.google.protobuf.nano.SimpleMessageNano;
|
||||||
import com.google.protobuf.nano.UnittestImportNano;
|
import com.google.protobuf.nano.UnittestImportNano;
|
||||||
import com.google.protobuf.nano.CodedInputByteBufferNano;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test nano runtime.
|
* Test nano runtime.
|
||||||
*
|
*
|
||||||
@ -2155,4 +2160,93 @@ public class NanoTest extends TestCase {
|
|||||||
assertTrue(protoPrint.contains(" default_int32: 41"));
|
assertTrue(protoPrint.contains(" default_int32: 41"));
|
||||||
assertTrue(protoPrint.contains(" default_string: \"hello\""));
|
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_file.h>
|
||||||
#include <google/protobuf/compiler/javanano/javanano_enum.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_helpers.h>
|
||||||
#include <google/protobuf/compiler/javanano/javanano_message.h>
|
#include <google/protobuf/compiler/javanano/javanano_message.h>
|
||||||
#include <google/protobuf/compiler/code_generator.h>
|
#include <google/protobuf/compiler/code_generator.h>
|
||||||
@ -94,10 +95,11 @@ bool FileGenerator::Validate(string* error) {
|
|||||||
// Check for extensions
|
// Check for extensions
|
||||||
FileDescriptorProto file_proto;
|
FileDescriptorProto file_proto;
|
||||||
file_->CopyTo(&file_proto);
|
file_->CopyTo(&file_proto);
|
||||||
if (UsesExtensions(file_proto)) {
|
if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) {
|
||||||
error->assign(file_->name());
|
error->assign(file_->name());
|
||||||
error->append(
|
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;
|
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()) {
|
if (!params_.java_multiple_files()) {
|
||||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
EnumGenerator(file_->enum_type(i), params_).Generate(printer);
|
EnumGenerator(file_->enum_type(i), params_).Generate(printer);
|
||||||
|
@ -115,6 +115,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
params.set_java_outer_classname(parts[0], parts[1]);
|
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") {
|
} else if (options[i].first == "java_multiple_files") {
|
||||||
params.set_java_multiple_files(options[i].second == "true");
|
params.set_java_multiple_files(options[i].second == "true");
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <google/protobuf/stubs/hash.h>
|
#include <google/protobuf/stubs/hash.h>
|
||||||
#include <google/protobuf/compiler/javanano/javanano_message.h>
|
#include <google/protobuf/compiler/javanano/javanano_message.h>
|
||||||
#include <google/protobuf/compiler/javanano/javanano_enum.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_helpers.h>
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
@ -117,10 +118,6 @@ void MessageGenerator::GenerateStaticVariableInitializers(
|
|||||||
MessageGenerator(descriptor_->nested_type(i), params_)
|
MessageGenerator(descriptor_->nested_type(i), params_)
|
||||||
.GenerateStaticVariableInitializers(printer);
|
.GenerateStaticVariableInitializers(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor_->extension_count() != 0) {
|
|
||||||
GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageGenerator::Generate(io::Printer* printer) {
|
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());
|
GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((descriptor_->extension_count() != 0)
|
if (!params_.store_unknown_fields() &&
|
||||||
|| (descriptor_->extension_range_count() != 0)) {
|
(descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
|
||||||
GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n";
|
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
|
// 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",
|
"\n",
|
||||||
"classname", descriptor_->name());
|
"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
|
// 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++) {
|
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
||||||
EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
|
EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
|
||||||
}
|
}
|
||||||
@ -173,6 +181,24 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GenerateClear(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);
|
GenerateMessageSerializationMethods(printer);
|
||||||
GenerateMergeFromMethods(printer);
|
GenerateMergeFromMethods(printer);
|
||||||
GenerateParseFromMethods(printer);
|
GenerateParseFromMethods(printer);
|
||||||
@ -188,12 +214,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
|||||||
scoped_array<const FieldDescriptor*> sorted_fields(
|
scoped_array<const FieldDescriptor*> sorted_fields(
|
||||||
SortFieldsByNumber(descriptor_));
|
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
|
// 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(
|
printer->Print(
|
||||||
"@Override\n"
|
"@Override\n"
|
||||||
"public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\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
|
// Output the fields in sorted order
|
||||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
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();
|
printer->Outdent();
|
||||||
@ -233,6 +262,11 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
|||||||
field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(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->Outdent();
|
||||||
printer->Print(
|
printer->Print(
|
||||||
" cachedSize = size;\n"
|
" cachedSize = size;\n"
|
||||||
@ -266,12 +300,28 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
|
|||||||
printer->Print(
|
printer->Print(
|
||||||
"case 0:\n" // zero signals EOF / limit reached
|
"case 0:\n" // zero signals EOF / limit reached
|
||||||
" return this;\n"
|
" return this;\n"
|
||||||
"default: {\n"
|
"default: {\n");
|
||||||
" if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
|
|
||||||
" return this;\n" // it's an endgroup tag
|
printer->Indent();
|
||||||
" }\n"
|
if (params_.store_unknown_fields()) {
|
||||||
" break;\n"
|
printer->Print(
|
||||||
"}\n");
|
"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++) {
|
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||||
const FieldDescriptor* field = sorted_fields[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->Outdent();
|
||||||
printer->Print(
|
printer->Print(
|
||||||
" cachedSize = -1;\n"
|
" cachedSize = -1;\n"
|
||||||
|
@ -49,6 +49,7 @@ class Params {
|
|||||||
string empty_;
|
string empty_;
|
||||||
string base_name_;
|
string base_name_;
|
||||||
bool java_multiple_files_;
|
bool java_multiple_files_;
|
||||||
|
bool store_unknown_fields_;
|
||||||
NameMap java_packages_;
|
NameMap java_packages_;
|
||||||
NameMap java_outer_classnames_;
|
NameMap java_outer_classnames_;
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ class Params {
|
|||||||
Params(const string & base_name) :
|
Params(const string & base_name) :
|
||||||
empty_(""),
|
empty_(""),
|
||||||
base_name_(base_name),
|
base_name_(base_name),
|
||||||
|
store_unknown_fields_(false),
|
||||||
java_multiple_files_(false) {
|
java_multiple_files_(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +109,13 @@ class Params {
|
|||||||
return java_outer_classnames_;
|
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) {
|
void set_java_multiple_files(bool value) {
|
||||||
java_multiple_files_ = 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