Down-integrate from google internal.

This commit is contained in:
Jisi Liu 2015-10-05 11:59:43 -07:00
parent 0087da9d47
commit 46e8ff63cb
112 changed files with 3564 additions and 964 deletions

View File

@ -505,6 +505,7 @@ python_EXTRA_DIST= \
python/google/protobuf/internal/factory_test1.proto \
python/google/protobuf/internal/factory_test2.proto \
python/google/protobuf/internal/generator_test.py \
python/google/protobuf/internal/json_format_test.py \
python/google/protobuf/internal/message_factory_test.py \
python/google/protobuf/internal/message_listener.py \
python/google/protobuf/internal/message_set_extensions.proto \
@ -560,6 +561,7 @@ python_EXTRA_DIST= \
python/google/protobuf/descriptor.py \
python/google/protobuf/descriptor_database.py \
python/google/protobuf/descriptor_pool.py \
python/google/protobuf/json_format.py \
python/google/protobuf/message.py \
python/google/protobuf/message_factory.py \
python/google/protobuf/proto_builder.py \

View File

@ -1,32 +1,32 @@
# Only test one combination: "Visual Studio 12 + Win64 + Debug + DLL". We can
# test more combinations but AppVeyor just takes too long to finish (each
# combination takes ~15mins).
platform:
- Win64
configuration:
- Debug
environment:
matrix:
- language: cpp
BUILD_DLL: ON
- language: csharp
install:
- ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
- 7z x gmock-1.7.0.zip
- rename gmock-1.7.0 gmock
before_build:
- if %platform%==Win32 set generator=Visual Studio 12
- if %platform%==Win64 set generator=Visual Studio 12 Win64
- if %platform%==Win32 set vcplatform=Win32
- if %platform%==Win64 set vcplatform=x64
build_script:
- CALL appveyor.bat
skip_commits:
message: /.*\[skip appveyor\].*/
# Only test one combination: "Visual Studio 12 + Win64 + Debug + DLL". We can
# test more combinations but AppVeyor just takes too long to finish (each
# combination takes ~15mins).
platform:
- Win64
configuration:
- Debug
environment:
matrix:
- language: cpp
BUILD_DLL: ON
- language: csharp
install:
- ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
- 7z x gmock-1.7.0.zip
- rename gmock-1.7.0 gmock
before_build:
- if %platform%==Win32 set generator=Visual Studio 12
- if %platform%==Win64 set generator=Visual Studio 12 Win64
- if %platform%==Win32 set vcplatform=Win32
- if %platform%==Win64 set vcplatform=x64
build_script:
- CALL appveyor.bat
skip_commits:
message: /.*\[skip appveyor\].*/

View File

@ -62,9 +62,8 @@ public abstract class GeneratedMessageLite<
private static final long serialVersionUID = 1L;
/** For use by generated code only. */
protected UnknownFieldSetLite unknownFields =
UnknownFieldSetLite.getDefaultInstance();
/** For use by generated code only. Lazily initialized to reduce allocations. */
protected UnknownFieldSetLite unknownFields = null;
/** For use by generated code only. */
protected int memoizedSerializedSize = -1;
@ -84,19 +83,56 @@ public abstract class GeneratedMessageLite<
return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
}
// The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
// mutable during the parsing constructor and immutable after. This allows us to avoid
// any unnecessary intermediary allocations while reducing the generated code size.
/**
* Called by subclasses to parse an unknown field. For use by generated code
* only.
* Lazily initializes unknown fields.
*/
private final void ensureUnknownFieldsInitialized() {
if (unknownFields == null) {
unknownFields = UnknownFieldSetLite.newInstance();
}
}
/**
* Called by subclasses to parse an unknown field. For use by generated code only.
*
* @return {@code true} unless the tag is an end-group tag.
*/
protected static boolean parseUnknownField(
CodedInputStream input,
UnknownFieldSetLite.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
protected boolean parseUnknownField(int tag, CodedInputStream input) throws IOException {
ensureUnknownFieldsInitialized();
return unknownFields.mergeFieldFrom(tag, input);
}
/**
* Called by subclasses to parse an unknown field. For use by generated code only.
*/
protected void mergeVarintField(int tag, int value) {
ensureUnknownFieldsInitialized();
unknownFields.mergeVarintField(tag, value);
}
/**
* Called by subclasses to parse an unknown field. For use by generated code only.
*/
protected void mergeLengthDelimitedField(int fieldNumber, ByteString value) {
ensureUnknownFieldsInitialized();
unknownFields.mergeLengthDelimitedField(fieldNumber, value);
}
/**
* Called by subclasses to complete parsing. For use by generated code only.
*/
protected void doneParsing() {
if (unknownFields == null) {
unknownFields = UnknownFieldSetLite.getDefaultInstance();
} else {
unknownFields.makeImmutable();
}
}
public final boolean isInitialized() {
return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
}
@ -171,7 +207,7 @@ public abstract class GeneratedMessageLite<
* <p>For use by generated code only.
*/
protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) {
this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields);
this.unknownFields = UnknownFieldSetLite.mutableCopyOf(this.unknownFields, unknownFields);
}
@SuppressWarnings("unchecked")
@ -225,7 +261,13 @@ public abstract class GeneratedMessageLite<
//@Override (Java 1.6 override semantics, but we must support 1.5)
public MessageType buildPartial() {
if (isBuilt) {
return instance;
}
instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
instance.unknownFields.makeImmutable();
isBuilt = true;
return instance;
}
@ -249,18 +291,6 @@ public abstract class GeneratedMessageLite<
public MessageType getDefaultInstanceForType() {
return defaultInstance;
}
/**
* Called by subclasses to parse an unknown field.
* @return {@code true} unless the tag is an end-group tag.
*/
protected boolean parseUnknownField(
CodedInputStream input,
UnknownFieldSetLite.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
return unknownFields.mergeFieldFrom(tag, input);
}
public BuilderType mergeFrom(
com.google.protobuf.CodedInputStream input,
@ -334,6 +364,130 @@ public abstract class GeneratedMessageLite<
extensions.mergeFrom(((ExtendableMessage) other).extensions);
}
/**
* Parse an unknown field or an extension. For use by generated code only.
*
* <p>For use by generated code only.
*
* @return {@code true} unless the tag is an end-group tag.
*/
protected <MessageType extends MessageLite> boolean parseUnknownField(
MessageType defaultInstance,
CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
int wireType = WireFormat.getTagWireType(tag);
int fieldNumber = WireFormat.getTagFieldNumber(tag);
// TODO(dweis): How much bytecode would be saved by not requiring the generated code to
// provide the default instance?
GeneratedExtension<MessageType, ?> extension = extensionRegistry.findLiteExtensionByNumber(
defaultInstance, fieldNumber);
boolean unknown = false;
boolean packed = false;
if (extension == null) {
unknown = true; // Unknown field.
} else if (wireType == FieldSet.getWireFormatForFieldType(
extension.descriptor.getLiteType(),
false /* isPacked */)) {
packed = false; // Normal, unpacked value.
} else if (extension.descriptor.isRepeated &&
extension.descriptor.type.isPackable() &&
wireType == FieldSet.getWireFormatForFieldType(
extension.descriptor.getLiteType(),
true /* isPacked */)) {
packed = true; // Packed value.
} else {
unknown = true; // Wrong wire type.
}
if (unknown) { // Unknown field or wrong wire type. Skip.
return parseUnknownField(tag, input);
}
if (packed) {
int length = input.readRawVarint32();
int limit = input.pushLimit(length);
if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
while (input.getBytesUntilLimit() > 0) {
int rawValue = input.readEnum();
Object value =
extension.descriptor.getEnumType().findValueByNumber(rawValue);
if (value == null) {
// If the number isn't recognized as a valid value for this
// enum, drop it (don't even add it to unknownFields).
return true;
}
extensions.addRepeatedField(extension.descriptor,
extension.singularToFieldSetType(value));
}
} else {
while (input.getBytesUntilLimit() > 0) {
Object value =
FieldSet.readPrimitiveField(input,
extension.descriptor.getLiteType(),
/*checkUtf8=*/ false);
extensions.addRepeatedField(extension.descriptor, value);
}
}
input.popLimit(limit);
} else {
Object value;
switch (extension.descriptor.getLiteJavaType()) {
case MESSAGE: {
MessageLite.Builder subBuilder = null;
if (!extension.descriptor.isRepeated()) {
MessageLite existingValue =
(MessageLite) extensions.getField(extension.descriptor);
if (existingValue != null) {
subBuilder = existingValue.toBuilder();
}
}
if (subBuilder == null) {
subBuilder = extension.getMessageDefaultInstance()
.newBuilderForType();
}
if (extension.descriptor.getLiteType() ==
WireFormat.FieldType.GROUP) {
input.readGroup(extension.getNumber(),
subBuilder, extensionRegistry);
} else {
input.readMessage(subBuilder, extensionRegistry);
}
value = subBuilder.build();
break;
}
case ENUM:
int rawValue = input.readEnum();
value = extension.descriptor.getEnumType()
.findValueByNumber(rawValue);
// If the number isn't recognized as a valid value for this enum,
// write it to unknown fields object.
if (value == null) {
mergeVarintField(fieldNumber, rawValue);
return true;
}
break;
default:
value = FieldSet.readPrimitiveField(input,
extension.descriptor.getLiteType(),
/*checkUtf8=*/ false);
break;
}
if (extension.descriptor.isRepeated()) {
extensions.addRepeatedField(extension.descriptor,
extension.singularToFieldSetType(value));
} else {
extensions.setField(extension.descriptor,
extension.singularToFieldSetType(value));
}
}
return true;
}
private void verifyExtensionContainingType(
final GeneratedExtension<MessageType, ?> extension) {
if (extension.getContainingTypeDefaultInstance() !=
@ -404,11 +558,10 @@ public abstract class GeneratedMessageLite<
}
/**
* Used by parsing constructors in generated classes.
*/
protected static void makeExtensionsImmutable(
FieldSet<ExtensionDescriptor> extensions) {
@Override
protected final void doneParsing() {
super.doneParsing();
extensions.makeImmutable();
}
@ -619,131 +772,6 @@ public abstract class GeneratedMessageLite<
}
}
//-----------------------------------------------------------------
/**
* Parse an unknown field or an extension. For use by generated code only.
* @return {@code true} unless the tag is an end-group tag.
*/
protected static <MessageType extends MessageLite>
boolean parseUnknownField(
FieldSet<ExtensionDescriptor> extensions,
MessageType defaultInstance,
CodedInputStream input,
UnknownFieldSetLite.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
int wireType = WireFormat.getTagWireType(tag);
int fieldNumber = WireFormat.getTagFieldNumber(tag);
GeneratedExtension<MessageType, ?> extension =
extensionRegistry.findLiteExtensionByNumber(
defaultInstance, fieldNumber);
boolean unknown = false;
boolean packed = false;
if (extension == null) {
unknown = true; // Unknown field.
} else if (wireType == FieldSet.getWireFormatForFieldType(
extension.descriptor.getLiteType(),
false /* isPacked */)) {
packed = false; // Normal, unpacked value.
} else if (extension.descriptor.isRepeated &&
extension.descriptor.type.isPackable() &&
wireType == FieldSet.getWireFormatForFieldType(
extension.descriptor.getLiteType(),
true /* isPacked */)) {
packed = true; // Packed value.
} else {
unknown = true; // Wrong wire type.
}
if (unknown) { // Unknown field or wrong wire type. Skip.
return unknownFields.mergeFieldFrom(tag, input);
}
if (packed) {
int length = input.readRawVarint32();
int limit = input.pushLimit(length);
if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
while (input.getBytesUntilLimit() > 0) {
int rawValue = input.readEnum();
Object value =
extension.descriptor.getEnumType().findValueByNumber(rawValue);
if (value == null) {
// If the number isn't recognized as a valid value for this
// enum, drop it (don't even add it to unknownFields).
return true;
}
extensions.addRepeatedField(extension.descriptor,
extension.singularToFieldSetType(value));
}
} else {
while (input.getBytesUntilLimit() > 0) {
Object value =
FieldSet.readPrimitiveField(input,
extension.descriptor.getLiteType(),
/*checkUtf8=*/ false);
extensions.addRepeatedField(extension.descriptor, value);
}
}
input.popLimit(limit);
} else {
Object value;
switch (extension.descriptor.getLiteJavaType()) {
case MESSAGE: {
MessageLite.Builder subBuilder = null;
if (!extension.descriptor.isRepeated()) {
MessageLite existingValue =
(MessageLite) extensions.getField(extension.descriptor);
if (existingValue != null) {
subBuilder = existingValue.toBuilder();
}
}
if (subBuilder == null) {
subBuilder = extension.getMessageDefaultInstance()
.newBuilderForType();
}
if (extension.descriptor.getLiteType() ==
WireFormat.FieldType.GROUP) {
input.readGroup(extension.getNumber(),
subBuilder, extensionRegistry);
} else {
input.readMessage(subBuilder, extensionRegistry);
}
value = subBuilder.build();
break;
}
case ENUM:
int rawValue = input.readEnum();
value = extension.descriptor.getEnumType()
.findValueByNumber(rawValue);
// If the number isn't recognized as a valid value for this enum,
// write it to unknown fields object.
if (value == null) {
unknownFields.mergeVarintField(fieldNumber, rawValue);
return true;
}
break;
default:
value = FieldSet.readPrimitiveField(input,
extension.descriptor.getLiteType(),
/*checkUtf8=*/ false);
break;
}
if (extension.descriptor.isRepeated()) {
extensions.addRepeatedField(extension.descriptor,
extension.singularToFieldSetType(value));
} else {
extensions.setField(extension.descriptor,
extension.singularToFieldSetType(value));
}
}
return true;
}
// -----------------------------------------------------------------
/** For use by generated code only. */
@ -893,7 +921,7 @@ public abstract class GeneratedMessageLite<
extends ExtensionLite<ContainingType, Type> {
/**
* Create a new isntance with the given parameters.
* Create a new instance with the given parameters.
*
* The last parameter {@code singularType} is only needed for enum types.
* We store integer values for enum types in a {@link ExtendableMessage}
@ -905,7 +933,7 @@ public abstract class GeneratedMessageLite<
final Type defaultValue,
final MessageLite messageDefaultInstance,
final ExtensionDescriptor descriptor,
Class singularType) {
final Class singularType) {
// Defensive checks to verify the correct initialization order of
// GeneratedExtensions and their related GeneratedMessages.
if (containingTypeDefaultInstance == null) {
@ -921,24 +949,12 @@ public abstract class GeneratedMessageLite<
this.defaultValue = defaultValue;
this.messageDefaultInstance = messageDefaultInstance;
this.descriptor = descriptor;
// Use Java reflection to invoke the static method {@code valueOf} of
// enum types in order to convert integers to concrete enum objects.
this.singularType = singularType;
if (Internal.EnumLite.class.isAssignableFrom(singularType)) {
this.enumValueOf = getMethodOrDie(
singularType, "valueOf", int.class);
} else {
this.enumValueOf = null;
}
}
final ContainingType containingTypeDefaultInstance;
final Type defaultValue;
final MessageLite messageDefaultInstance;
final ExtensionDescriptor descriptor;
final Class singularType;
final Method enumValueOf;
/**
* Default instance of the type being extended, used to identify that type.
@ -980,7 +996,7 @@ public abstract class GeneratedMessageLite<
Object singularFromFieldSetType(final Object value) {
if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
return invokeOrDie(enumValueOf, null, (Integer) value);
return descriptor.enumTypeMap.findValueByNumber((Integer) value);
} else {
return value;
}

View File

@ -118,6 +118,21 @@ public final class TextFormat {
}
}
/**
* Generates a human readable form of the field, useful for debugging
* and other purposes, with no newline characters.
*/
public static String shortDebugString(final FieldDescriptor field,
final Object value) {
try {
final StringBuilder sb = new StringBuilder();
SINGLE_LINE_PRINTER.printField(field, value, new TextGenerator(sb));
return sb.toString().trim();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* Generates a human readable form of the unknown fields, useful for debugging
* and other purposes, with no newline characters.

View File

@ -45,12 +45,13 @@ import java.util.Arrays;
* @author dweis@google.com (Daniel Weis)
*/
public final class UnknownFieldSetLite {
private static final int[] EMPTY_INT_ARRAY = new int[0];
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
// Arbitrarily chosen.
// TODO(dweis): Tune this number?
private static final int MIN_CAPACITY = 8;
private static final UnknownFieldSetLite DEFAULT_INSTANCE =
new UnknownFieldSetLite(0, EMPTY_INT_ARRAY, EMPTY_OBJECT_ARRAY);
new UnknownFieldSetLite(0, new int[0], new Object[0], false /* isMutable */);
/**
* Get an empty {@code UnknownFieldSetLite}.
@ -62,25 +63,32 @@ public final class UnknownFieldSetLite {
}
/**
* Create a new {@link Builder}.
* Returns an empty {@code UnknownFieldSetLite.Builder}.
*
* <p>For use by generated code only.
*/
public static Builder newBuilder() {
return new Builder();
}
/**
* Returns a new mutable instance.
*/
static UnknownFieldSetLite newInstance() {
return new UnknownFieldSetLite();
}
/**
* Returns an {@code UnknownFieldSetLite} that is the composite of {@code first} and
* Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and
* {@code second}.
*/
static UnknownFieldSetLite concat(UnknownFieldSetLite first, UnknownFieldSetLite second) {
static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownFieldSetLite second) {
int count = first.count + second.count;
int[] tags = Arrays.copyOf(first.tags, count);
System.arraycopy(second.tags, 0, tags, first.count, second.count);
Object[] objects = Arrays.copyOf(first.objects, count);
System.arraycopy(second.objects, 0, objects, first.count, second.count);
return new UnknownFieldSetLite(count, tags, objects);
return new UnknownFieldSetLite(count, tags, objects, true /* isMutable */);
}
/**
@ -102,14 +110,45 @@ public final class UnknownFieldSetLite {
* The lazily computed serialized size of the set.
*/
private int memoizedSerializedSize = -1;
/**
* Indicates that this object is mutable.
*/
private boolean isMutable;
/**
* Constructs a mutable {@code UnknownFieldSetLite}.
*/
private UnknownFieldSetLite() {
this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], true /* isMutable */);
}
/**
* Constructs the {@code UnknownFieldSetLite}.
*/
private UnknownFieldSetLite(int count, int[] tags, Object[] objects) {
private UnknownFieldSetLite(int count, int[] tags, Object[] objects, boolean isMutable) {
this.count = count;
this.tags = tags;
this.objects = objects;
this.isMutable = isMutable;
}
/**
* Marks this object as immutable.
*
* <p>Future calls to methods that attempt to modify this object will throw.
*/
public void makeImmutable() {
this.isMutable = false;
}
/**
* Throws an {@link UnsupportedOperationException} if immutable.
*/
void checkMutable() {
if (!isMutable) {
throw new UnsupportedOperationException();
}
}
/**
@ -223,6 +262,114 @@ public final class UnknownFieldSetLite {
return hashCode;
}
private void storeField(int tag, Object value) {
ensureCapacity();
tags[count] = tag;
objects[count] = value;
count++;
}
/**
* Ensures that our arrays are long enough to store more metadata.
*/
private void ensureCapacity() {
if (count == tags.length) {
int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
int newLength = count + increment;
tags = Arrays.copyOf(tags, newLength);
objects = Arrays.copyOf(objects, newLength);
}
}
/**
* Parse a single field from {@code input} and merge it into this set.
*
* <p>For use by generated code only.
*
* @param tag The field's tag number, which was already parsed.
* @return {@code false} if the tag is an end group tag.
*/
boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException {
checkMutable();
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
storeField(tag, input.readInt64());
return true;
case WireFormat.WIRETYPE_FIXED32:
storeField(tag, input.readFixed32());
return true;
case WireFormat.WIRETYPE_FIXED64:
storeField(tag, input.readFixed64());
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
storeField(tag, input.readBytes());
return true;
case WireFormat.WIRETYPE_START_GROUP:
final UnknownFieldSetLite subFieldSet = new UnknownFieldSetLite();
subFieldSet.mergeFrom(input);
input.checkLastTagWas(
WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
storeField(tag, subFieldSet);
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
/**
* Convenience method for merging a new field containing a single varint
* value. This is used in particular when an unknown enum value is
* encountered.
*
* <p>For use by generated code only.
*/
UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) {
checkMutable();
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
return this;
}
/**
* Convenience method for merging a length-delimited field.
*
* <p>For use by generated code only.
*/
UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) {
checkMutable();
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
return this;
}
/**
* Parse an entire message from {@code input} and merge its fields into
* this set.
*/
private UnknownFieldSetLite mergeFrom(final CodedInputStream input) throws IOException {
// Ensures initialization in mergeFieldFrom.
while (true) {
final int tag = input.readTag();
if (tag == 0 || !mergeFieldFrom(tag, input)) {
break;
}
}
return this;
}
/**
* Builder for {@link UnknownFieldSetLite}s.
*
@ -230,53 +377,26 @@ public final class UnknownFieldSetLite {
*
* <p>For use by generated code only.
*/
// TODO(dweis): Update the mutable API to no longer need this builder and delete.
public static final class Builder {
// Arbitrarily chosen.
// TODO(dweis): Tune this number?
private static final int MIN_CAPACITY = 8;
private int count = 0;
private int[] tags = EMPTY_INT_ARRAY;
private Object[] objects = EMPTY_OBJECT_ARRAY;
private boolean built;
/**
* Constructs a {@code Builder}.
*/
private Builder() {}
private UnknownFieldSetLite set;
private Builder() {
this.set = null;
}
/**
* Ensures internal state is initialized for use.
*/
private void ensureNotBuilt() {
if (built) {
throw new IllegalStateException("Do not reuse UnknownFieldSetLite Builders.");
if (set == null) {
set = new UnknownFieldSetLite();
}
}
private void storeField(int tag, Object value) {
ensureCapacity();
tags[count] = tag;
objects[count] = value;
count++;
set.checkMutable();
}
/**
* Ensures that our arrays are long enough to store more metadata.
*/
private void ensureCapacity() {
if (count == tags.length) {
int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
int newLength = count + increment;
tags = Arrays.copyOf(tags, newLength);
objects = Arrays.copyOf(objects, newLength);
}
}
/**
* Parse a single field from {@code input} and merge it into this set.
*
@ -285,36 +405,9 @@ public final class UnknownFieldSetLite {
* @param tag The field's tag number, which was already parsed.
* @return {@code false} if the tag is an end group tag.
*/
public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
throws IOException {
boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException {
ensureNotBuilt();
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
storeField(tag, input.readInt64());
return true;
case WireFormat.WIRETYPE_FIXED32:
storeField(tag, input.readFixed32());
return true;
case WireFormat.WIRETYPE_FIXED64:
storeField(tag, input.readFixed64());
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
storeField(tag, input.readBytes());
return true;
case WireFormat.WIRETYPE_START_GROUP:
final Builder subBuilder = newBuilder();
subBuilder.mergeFrom(input);
input.checkLastTagWas(
WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
storeField(tag, subBuilder.build());
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
return set.mergeFieldFrom(tag, input);
}
/**
@ -324,71 +417,42 @@ public final class UnknownFieldSetLite {
*
* <p>For use by generated code only.
*/
public Builder mergeVarintField(int fieldNumber, int value) {
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
Builder mergeVarintField(int fieldNumber, int value) {
ensureNotBuilt();
storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
set.mergeVarintField(fieldNumber, value);
return this;
}
/**
* Convenience method for merging a length-delimited field.
*
* <p>For use by generated code only.
*/
public Builder mergeLengthDelimitedField(
final int fieldNumber, final ByteString value) {
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
ensureNotBuilt();
storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
public Builder mergeLengthDelimitedField(final int fieldNumber, final ByteString value) {
ensureNotBuilt();
set.mergeLengthDelimitedField(fieldNumber, value);
return this;
}
/**
* Parse an entire message from {@code input} and merge its fields into
* this set.
*/
private Builder mergeFrom(final CodedInputStream input) throws IOException {
// Ensures initialization in mergeFieldFrom.
while (true) {
final int tag = input.readTag();
if (tag == 0 || !mergeFieldFrom(tag, input)) {
break;
}
}
return this;
}
/**
* Build the {@link UnknownFieldSetLite} and return it.
*
* <p>Once {@code build()} has been called, the {@code Builder} will no
* longer be usable. Calling any method after {@code build()} will result
* in undefined behavior and can cause a {@code IllegalStateException} to be
* thrown.
* in undefined behavior and can cause an
* {@code UnsupportedOperationException} to be thrown.
*
* <p>For use by generated code only.
*/
public UnknownFieldSetLite build() {
if (built) {
throw new IllegalStateException("Do not reuse UnknownFieldSetLite Builders.");
}
built = true;
if (count == 0) {
if (set == null) {
return DEFAULT_INSTANCE;
}
set.checkMutable();
set.makeImmutable();
return new UnknownFieldSetLite(count, tags, objects);
return set;
}
}
}

View File

@ -360,8 +360,8 @@ final class Utf8 {
static class UnpairedSurrogateException extends IllegalArgumentException {
private UnpairedSurrogateException(int index) {
super("Unpaired surrogate at index " + index);
private UnpairedSurrogateException(int index, int length) {
super("Unpaired surrogate at index " + index + " of " + length);
}
}
@ -417,7 +417,7 @@ final class Utf8 {
// Check that we have a well-formed surrogate pair.
int cp = Character.codePointAt(sequence, i);
if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
throw new UnpairedSurrogateException(i);
throw new UnpairedSurrogateException(i, utf16Length);
}
i++;
}
@ -457,7 +457,7 @@ final class Utf8 {
final char low;
if (i + 1 == sequence.length()
|| !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
throw new UnpairedSurrogateException((i - 1));
throw new UnpairedSurrogateException((i - 1), utf16Length);
}
int codePoint = Character.toCodePoint(c, low);
bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
@ -470,7 +470,7 @@ final class Utf8 {
if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
&& (i + 1 == sequence.length()
|| !Character.isSurrogatePair(c, sequence.charAt(i + 1)))) {
throw new UnpairedSurrogateException(i);
throw new UnpairedSurrogateException(i, utf16Length);
}
throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
}

View File

@ -46,6 +46,7 @@ import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Descriptors.ServiceDescriptor;
import com.google.protobuf.test.UnittestImport;
import com.google.protobuf.test.UnittestImport.ImportEnum;
import com.google.protobuf.test.UnittestImport.ImportEnumForMap;
import protobuf_unittest.TestCustomOptions;
import protobuf_unittest.UnittestCustomOptions;
import protobuf_unittest.UnittestProto;
@ -115,7 +116,8 @@ public class DescriptorsTest extends TestCase {
assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
assertNull(file.findEnumTypeByName("NoSuchType"));
assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
assertEquals(Arrays.asList(ImportEnum.getDescriptor()),
assertEquals(Arrays.asList(ImportEnum.getDescriptor(),
ImportEnumForMap.getDescriptor()),
UnittestImport.getDescriptor().getEnumTypes());
for (int i = 0; i < file.getEnumTypes().size(); i++) {
assertEquals(i, file.getEnumTypes().get(i).getIndex());

View File

@ -830,6 +830,22 @@ public class TextFormatTest extends TestCase {
.build()));
}
public void testShortDebugString_field() {
final FieldDescriptor dataField =
OneString.getDescriptor().findFieldByName("data");
assertEquals(
"data: \"test data\"",
TextFormat.shortDebugString(dataField, "test data"));
final FieldDescriptor optionalField =
TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
final Object value = NestedMessage.newBuilder().setBb(42).build();
assertEquals(
"optional_nested_message { bb: 42 }",
TextFormat.shortDebugString(optionalField, value));
}
public void testShortDebugString_unknown() {
assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
+ " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"

View File

@ -30,6 +30,8 @@
package com.google.protobuf;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestAllTypesLite;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
@ -52,7 +54,40 @@ public class UnknownFieldSetLiteTest extends TestCase {
UnknownFieldSetLite.newBuilder()
.build());
}
public void testBuilderReuse() throws IOException {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.mergeVarintField(10, 2);
builder.build();
try {
builder.build();
fail();
} catch (UnsupportedOperationException e) {
// Expected.
}
try {
builder.mergeFieldFrom(0, CodedInputStream.newInstance(new byte[0]));
fail();
} catch (UnsupportedOperationException e) {
// Expected.
}
try {
builder.mergeVarintField(5, 1);
fail();
} catch (UnsupportedOperationException e) {
// Expected.
}
}
public void testBuilderReuse_empty() {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.build();
builder.build();
}
public void testDefaultInstance() {
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
@ -67,10 +102,10 @@ public class UnknownFieldSetLiteTest extends TestCase {
CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.mergeFieldFrom(input.readTag(), input);
UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
instance.mergeFieldFrom(input.readTag(), input);
assertEquals(foo.toByteString(), toByteString(builder.build()));
assertEquals(foo.toByteString(), toByteString(instance));
}
public void testSerializedSize() throws IOException {
@ -80,18 +115,18 @@ public class UnknownFieldSetLiteTest extends TestCase {
CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.mergeFieldFrom(input.readTag(), input);
UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
instance.mergeFieldFrom(input.readTag(), input);
assertEquals(foo.toByteString().size(), builder.build().getSerializedSize());
assertEquals(foo.toByteString().size(), instance.getSerializedSize());
}
public void testMergeVarintField() throws IOException {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.mergeVarintField(10, 2);
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
unknownFields.mergeVarintField(10, 2);
CodedInputStream input =
CodedInputStream.newInstance(toByteString(builder.build()).toByteArray());
CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
int tag = input.readTag();
assertEquals(10, WireFormat.getTagFieldNumber(tag));
@ -101,11 +136,11 @@ public class UnknownFieldSetLiteTest extends TestCase {
}
public void testMergeVarintField_negative() throws IOException {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
UnknownFieldSetLite builder = UnknownFieldSetLite.newInstance();
builder.mergeVarintField(10, -6);
CodedInputStream input =
CodedInputStream.newInstance(toByteString(builder.build()).toByteArray());
CodedInputStream.newInstance(toByteString(builder).toByteArray());
int tag = input.readTag();
assertEquals(10, WireFormat.getTagFieldNumber(tag));
@ -115,13 +150,11 @@ public class UnknownFieldSetLiteTest extends TestCase {
}
public void testEqualsAndHashCode() {
UnknownFieldSetLite.Builder builder1 = UnknownFieldSetLite.newBuilder();
builder1.mergeVarintField(10, 2);
UnknownFieldSetLite unknownFields1 = builder1.build();
UnknownFieldSetLite unknownFields1 = UnknownFieldSetLite.newInstance();
unknownFields1.mergeVarintField(10, 2);
UnknownFieldSetLite.Builder builder2 = UnknownFieldSetLite.newBuilder();
builder2.mergeVarintField(10, 2);
UnknownFieldSetLite unknownFields2 = builder2.build();
UnknownFieldSetLite unknownFields2 = UnknownFieldSetLite.newInstance();
unknownFields2.mergeVarintField(10, 2);
assertEquals(unknownFields1, unknownFields2);
assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode());
@ -129,12 +162,11 @@ public class UnknownFieldSetLiteTest extends TestCase {
assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode());
}
public void testConcat() throws IOException {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.mergeVarintField(10, 2);
UnknownFieldSetLite unknownFields = builder.build();
unknownFields = UnknownFieldSetLite.concat(unknownFields, unknownFields);
public void testMutableCopyOf() throws IOException {
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
unknownFields.mergeVarintField(10, 2);
unknownFields = UnknownFieldSetLite.mutableCopyOf(unknownFields, unknownFields);
unknownFields.checkMutable();
CodedInputStream input =
CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
@ -151,53 +183,15 @@ public class UnknownFieldSetLiteTest extends TestCase {
assertTrue(input.isAtEnd());
}
public void testConcat_empty() {
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.concat(
public void testMutableCopyOf_empty() {
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.mutableCopyOf(
UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance());
unknownFields.checkMutable();
assertEquals(0, unknownFields.getSerializedSize());
assertEquals(ByteString.EMPTY, toByteString(unknownFields));
}
public void testBuilderReuse() throws IOException {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.mergeVarintField(10, 2);
builder.build();
try {
builder.build();
fail();
} catch (IllegalStateException e) {
// Expected.
}
try {
builder.mergeFieldFrom(0, CodedInputStream.newInstance(new byte[0]));
fail();
} catch (IllegalStateException e) {
// Expected.
}
try {
builder.mergeVarintField(5, 1);
fail();
} catch (IllegalStateException e) {
// Expected.
}
}
public void testBuilderReuse_empty() {
UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
builder.build();
try {
builder.build();
fail();
} catch (IllegalStateException e) {
// Expected.
}
}
public void testRoundTrips() throws InvalidProtocolBufferException {
Foo foo = Foo.newBuilder()
.setValue(1)
@ -301,6 +295,64 @@ public class UnknownFieldSetLiteTest extends TestCase {
// Expected.
}
}
public void testMakeImmutable() throws Exception {
UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
unknownFields.makeImmutable();
try {
unknownFields.mergeVarintField(1, 1);
fail();
} catch (UnsupportedOperationException expected) {}
try {
unknownFields.mergeLengthDelimitedField(2, ByteString.copyFromUtf8("hello"));
fail();
} catch (UnsupportedOperationException expected) {}
try {
unknownFields.mergeFieldFrom(1, CodedInputStream.newInstance(new byte[0]));
fail();
} catch (UnsupportedOperationException expected) {}
}
public void testEndToEnd() throws Exception {
TestAllTypesLite testAllTypes = TestAllTypesLite.getDefaultInstance();
try {
testAllTypes.unknownFields.checkMutable();
fail();
} catch (UnsupportedOperationException expected) {}
testAllTypes = TestAllTypesLite.parseFrom(new byte[0]);
try {
testAllTypes.unknownFields.checkMutable();
fail();
} catch (UnsupportedOperationException expected) {}
testAllTypes = TestAllTypesLite.newBuilder().build();
try {
testAllTypes.unknownFields.checkMutable();
fail();
} catch (UnsupportedOperationException expected) {}
testAllTypes = TestAllTypesLite.newBuilder()
.setDefaultBool(true)
.build();
try {
testAllTypes.unknownFields.checkMutable();
fail();
} catch (UnsupportedOperationException expected) {}
TestAllExtensionsLite testAllExtensions = TestAllExtensionsLite.newBuilder()
.mergeFrom(TestAllExtensionsLite.newBuilder()
.setExtension(UnittestLite.optionalInt32ExtensionLite, 2)
.build().toByteArray())
.build();
try {
testAllExtensions.unknownFields.checkMutable();
fail();
} catch (UnsupportedOperationException expected) {}
}
private ByteString toByteString(UnknownFieldSetLite unknownFields) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

View File

@ -140,11 +140,11 @@ message TestConflictingFieldNames {
optional bytes bytes_field_count = 14;
optional TestMessage message_field_count = 15;
repeated int32 Int32Field = 21;
repeated TestEnum EnumField = 22;
repeated string StringField = 23;
repeated bytes BytesField = 24;
repeated TestMessage MessageField = 25;
repeated int32 Int32Field = 21; // NO_PROTO3
repeated TestEnum EnumField = 22; // NO_PROTO3
repeated string StringField = 23; // NO_PROTO3
repeated bytes BytesField = 24; // NO_PROTO3
repeated TestMessage MessageField = 25; // NO_PROTO3
// This field conflicts with "int32_field" as they both generate
// the method getInt32FieldList().

View File

@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.0.0-beta-1</version>
<version>3.0.0-alpha-4-pre</version>
<packaging>bundle</packaging>
<name>Protocol Buffer Java API</name>
<description>
@ -36,7 +36,7 @@
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0-beta-1</version>
<version>3.0.0-alpha-4-pre</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -123,7 +123,7 @@
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf.util</Bundle-SymbolicName>
<Export-Package>com.google.protobuf.util;version=3.0.0-beta-1</Export-Package>
<Export-Package>com.google.protobuf.util;version=3.0.0-alpha-3</Export-Package>
</instructions>
</configuration>
</plugin>

View File

@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2007 Google Inc. All Rights Reserved.
"""Descriptors essentially contain exactly the information found in a .proto
file, in types that make this information accessible in Python.
"""
@ -40,7 +38,6 @@ import six
from google.protobuf.internal import api_implementation
_USE_C_DESCRIPTORS = False
if api_implementation.Type() == 'cpp':
# Used by MakeDescriptor in cpp mode
@ -221,6 +218,9 @@ class Descriptor(_NestedDescriptorBase):
fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor
objects as in |fields|, but indexed by "name" attribute in each
FieldDescriptor.
fields_by_camelcase_name: (dict str -> FieldDescriptor) Same
FieldDescriptor objects as in |fields|, but indexed by
"camelcase_name" attribute in each FieldDescriptor.
nested_types: (list of Descriptors) Descriptor references
for all protocol message types nested within this one.
@ -292,6 +292,7 @@ class Descriptor(_NestedDescriptorBase):
field.containing_type = self
self.fields_by_number = dict((f.number, f) for f in fields)
self.fields_by_name = dict((f.name, f) for f in fields)
self._fields_by_camelcase_name = None
self.nested_types = nested_types
for nested_type in nested_types:
@ -317,6 +318,13 @@ class Descriptor(_NestedDescriptorBase):
oneof.containing_type = self
self.syntax = syntax or "proto2"
@property
def fields_by_camelcase_name(self):
if self._fields_by_camelcase_name is None:
self._fields_by_camelcase_name = dict(
(f.camelcase_name, f) for f in self.fields)
return self._fields_by_camelcase_name
def EnumValueName(self, enum, value):
"""Returns the string name of an enum value.
@ -365,6 +373,7 @@ class FieldDescriptor(DescriptorBase):
name: (str) Name of this field, exactly as it appears in .proto.
full_name: (str) Name of this field, including containing scope. This is
particularly relevant for extensions.
camelcase_name: (str) Camelcase name of this field.
index: (int) Dense, 0-indexed index giving the order that this
field textually appears within its message in the .proto file.
number: (int) Tag number declared for this field in the .proto file.
@ -509,6 +518,7 @@ class FieldDescriptor(DescriptorBase):
super(FieldDescriptor, self).__init__(options, 'FieldOptions')
self.name = name
self.full_name = full_name
self._camelcase_name = None
self.index = index
self.number = number
self.type = type
@ -530,6 +540,12 @@ class FieldDescriptor(DescriptorBase):
else:
self._cdescriptor = None
@property
def camelcase_name(self):
if self._camelcase_name is None:
self._camelcase_name = _ToCamelCase(self.name)
return self._camelcase_name
@staticmethod
def ProtoTypeToCppProtoType(proto_type):
"""Converts from a Python proto type to a C++ Proto Type.
@ -822,6 +838,27 @@ def _ParseOptions(message, string):
return message
def _ToCamelCase(name):
"""Converts name to camel-case and returns it."""
capitalize_next = False
result = []
for c in name:
if c == '_':
if result:
capitalize_next = True
elif capitalize_next:
result.append(c.upper())
capitalize_next = False
else:
result += c
# Lower-case the first letter.
if result and result[0].isupper():
result[0] = result[0].lower()
return ''.join(result)
def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
syntax=None):
"""Make a protobuf Descriptor given a DescriptorProto protobuf.

View File

@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2009 Google Inc. All Rights Reserved.
"""Code for decoding protocol buffer primitives.
This code is very similar to encoder.py -- read the docs for that module first.

View File

@ -34,10 +34,7 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import descriptor_pb2
from google.protobuf.internal import factory_test2_pb2
from google.protobuf import descriptor_database

View File

@ -35,11 +35,8 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
import os
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2
from google.protobuf.internal import api_implementation
@ -47,6 +44,7 @@ from google.protobuf.internal import descriptor_pool_test1_pb2
from google.protobuf.internal import descriptor_pool_test2_pb2
from google.protobuf.internal import factory_test1_pb2
from google.protobuf.internal import factory_test2_pb2
from google.protobuf.internal import test_util
from google.protobuf import descriptor
from google.protobuf import descriptor_database
from google.protobuf import descriptor_pool

View File

@ -1,4 +1,4 @@
#! /usr/bin/python
#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
@ -36,20 +36,17 @@ __author__ = 'robinson@google.com (Will Robinson)'
import sys
import unittest
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2
from google.protobuf.internal import api_implementation
from google.protobuf.internal import test_util
from google.protobuf import descriptor
from google.protobuf import symbol_database
from google.protobuf import text_format
try:
import unittest2 as unittest
except ImportError:
import unittest
TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
name: 'TestEmptyMessage'
@ -394,7 +391,7 @@ class DescriptorTest(unittest.TestCase):
self.assertEqual(self.my_file.name, 'some/filename/some.proto')
self.assertEqual(self.my_file.package, 'protobuf_unittest')
@unittest.skipIf(
@test_util.skipIf(
api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
'Immutability of descriptors is only enforced in v2 implementation')
def testImmutableCppDescriptor(self):
@ -425,10 +422,12 @@ class GeneratedDescriptorTest(unittest.TestCase):
self.CheckDescriptorSequence(message_descriptor.fields)
self.CheckDescriptorMapping(message_descriptor.fields_by_name)
self.CheckDescriptorMapping(message_descriptor.fields_by_number)
self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name)
def CheckFieldDescriptor(self, field_descriptor):
# Basic properties
self.assertEqual(field_descriptor.name, 'optional_int32')
self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32')
self.assertEqual(field_descriptor.full_name,
'protobuf_unittest.TestAllTypes.optional_int32')
self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes')
@ -437,6 +436,10 @@ class GeneratedDescriptorTest(unittest.TestCase):
self.assertEqual(
field_descriptor.containing_type.fields_by_name['optional_int32'],
field_descriptor)
self.assertEqual(
field_descriptor.containing_type.fields_by_camelcase_name[
'optionalInt32'],
field_descriptor)
self.assertIn(field_descriptor, [field_descriptor])
self.assertIn(field_descriptor, {field_descriptor: None})
@ -481,6 +484,9 @@ class GeneratedDescriptorTest(unittest.TestCase):
self.CheckMessageDescriptor(message_descriptor)
field_descriptor = message_descriptor.fields_by_name['optional_int32']
self.CheckFieldDescriptor(field_descriptor)
field_descriptor = message_descriptor.fields_by_camelcase_name[
'optionalInt32']
self.CheckFieldDescriptor(field_descriptor)
def testCppDescriptorContainer(self):
# Check that the collection is still valid even if the parent disappeared.
@ -779,5 +785,20 @@ class MakeDescriptorTest(unittest.TestCase):
self.assertEqual(101,
options.Extensions[unittest_custom_options_pb2.msgopt].i)
def testCamelcaseName(self):
descriptor_proto = descriptor_pb2.DescriptorProto()
descriptor_proto.name = 'Bar'
names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar']
camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar']
for index in range(len(names)):
field = descriptor_proto.field.add()
field.number = index + 1
field.name = names[index]
result = descriptor.MakeDescriptor(descriptor_proto)
for index in range(len(camelcase_names)):
self.assertEqual(result.fields[index].camelcase_name,
camelcase_names[index])
if __name__ == '__main__':
unittest.main()

View File

@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2009 Google Inc. All Rights Reserved.
"""Code for encoding protocol message primitives.
Contains the logic for encoding every logical protocol field type

View File

@ -41,10 +41,7 @@ further ensures that we can use Python protocol message objects as we expect.
__author__ = 'robinson@google.com (Will Robinson)'
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf.internal import test_bad_identifiers_pb2
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2

View File

@ -0,0 +1,522 @@
#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
# https://developers.google.com/protocol-buffers/
#
# 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.
"""Test for google.protobuf.json_format."""
__author__ = 'jieluo@google.com (Jie Luo)'
import json
import math
import sys
import unittest
from google.protobuf import json_format
from google.protobuf.util import json_format_proto3_pb2
class JsonFormatBase(unittest.TestCase):
def FillAllFields(self, message):
message.int32_value = 20
message.int64_value = -20
message.uint32_value = 3120987654
message.uint64_value = 12345678900
message.float_value = float('-inf')
message.double_value = 3.1415
message.bool_value = True
message.string_value = 'foo'
message.bytes_value = b'bar'
message.message_value.value = 10
message.enum_value = json_format_proto3_pb2.BAR
# Repeated
message.repeated_int32_value.append(0x7FFFFFFF)
message.repeated_int32_value.append(-2147483648)
message.repeated_int64_value.append(9007199254740992)
message.repeated_int64_value.append(-9007199254740992)
message.repeated_uint32_value.append(0xFFFFFFF)
message.repeated_uint32_value.append(0x7FFFFFF)
message.repeated_uint64_value.append(9007199254740992)
message.repeated_uint64_value.append(9007199254740991)
message.repeated_float_value.append(0)
message.repeated_double_value.append(1E-15)
message.repeated_double_value.append(float('inf'))
message.repeated_bool_value.append(True)
message.repeated_bool_value.append(False)
message.repeated_string_value.append('Few symbols!#$,;')
message.repeated_string_value.append('bar')
message.repeated_bytes_value.append(b'foo')
message.repeated_bytes_value.append(b'bar')
message.repeated_message_value.add().value = 10
message.repeated_message_value.add().value = 11
message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
self.message = message
def CheckParseBack(self, message, parsed_message):
json_format.Parse(json_format.MessageToJson(message),
parsed_message)
self.assertEqual(message, parsed_message)
def CheckError(self, text, error_message):
message = json_format_proto3_pb2.TestMessage()
self.assertRaisesRegexp(
json_format.ParseError,
error_message,
json_format.Parse, text, message)
class JsonFormatTest(JsonFormatBase):
def testEmptyMessageToJson(self):
message = json_format_proto3_pb2.TestMessage()
self.assertEqual(json_format.MessageToJson(message),
'{}')
parsed_message = json_format_proto3_pb2.TestMessage()
self.CheckParseBack(message, parsed_message)
def testPartialMessageToJson(self):
message = json_format_proto3_pb2.TestMessage(
string_value='test',
repeated_int32_value=[89, 4])
self.assertEqual(json.loads(json_format.MessageToJson(message)),
json.loads('{"stringValue": "test", '
'"repeatedInt32Value": [89, 4]}'))
parsed_message = json_format_proto3_pb2.TestMessage()
self.CheckParseBack(message, parsed_message)
def testAllFieldsToJson(self):
message = json_format_proto3_pb2.TestMessage()
text = ('{"int32Value": 20, '
'"int64Value": "-20", '
'"uint32Value": 3120987654,'
'"uint64Value": "12345678900",'
'"floatValue": "-Infinity",'
'"doubleValue": 3.1415,'
'"boolValue": true,'
'"stringValue": "foo",'
'"bytesValue": "YmFy",'
'"messageValue": {"value": 10},'
'"enumValue": "BAR",'
'"repeatedInt32Value": [2147483647, -2147483648],'
'"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],'
'"repeatedUint32Value": [268435455, 134217727],'
'"repeatedUint64Value": ["9007199254740992", "9007199254740991"],'
'"repeatedFloatValue": [0],'
'"repeatedDoubleValue": [1e-15, "Infinity"],'
'"repeatedBoolValue": [true, false],'
'"repeatedStringValue": ["Few symbols!#$,;", "bar"],'
'"repeatedBytesValue": ["Zm9v", "YmFy"],'
'"repeatedMessageValue": [{"value": 10}, {"value": 11}],'
'"repeatedEnumValue": ["FOO", "BAR"]'
'}')
self.FillAllFields(message)
self.assertEqual(
json.loads(json_format.MessageToJson(message)),
json.loads(text))
parsed_message = json_format_proto3_pb2.TestMessage()
json_format.Parse(text, parsed_message)
self.assertEqual(message, parsed_message)
def testJsonEscapeString(self):
message = json_format_proto3_pb2.TestMessage()
if sys.version_info[0] < 3:
message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9'
else:
message.string_value = '&\n<\"\r>\b\t\f\\\001/'
message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8')
self.assertEqual(
json_format.MessageToJson(message),
'{\n "stringValue": '
'"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}')
parsed_message = json_format_proto3_pb2.TestMessage()
self.CheckParseBack(message, parsed_message)
text = u'{"int32Value": "\u0031"}'
json_format.Parse(text, message)
self.assertEqual(message.int32_value, 1)
def testAlwaysSeriliaze(self):
message = json_format_proto3_pb2.TestMessage(
string_value='foo')
self.assertEqual(
json.loads(json_format.MessageToJson(message, True)),
json.loads('{'
'"repeatedStringValue": [],'
'"stringValue": "foo",'
'"repeatedBoolValue": [],'
'"repeatedUint32Value": [],'
'"repeatedInt32Value": [],'
'"enumValue": "FOO",'
'"int32Value": 0,'
'"floatValue": 0,'
'"int64Value": "0",'
'"uint32Value": 0,'
'"repeatedBytesValue": [],'
'"repeatedUint64Value": [],'
'"repeatedDoubleValue": [],'
'"bytesValue": "",'
'"boolValue": false,'
'"repeatedEnumValue": [],'
'"uint64Value": "0",'
'"doubleValue": 0,'
'"repeatedFloatValue": [],'
'"repeatedInt64Value": [],'
'"repeatedMessageValue": []}'))
parsed_message = json_format_proto3_pb2.TestMessage()
self.CheckParseBack(message, parsed_message)
def testMapFields(self):
message = json_format_proto3_pb2.TestMap()
message.bool_map[True] = 1
message.bool_map[False] = 2
message.int32_map[1] = 2
message.int32_map[2] = 3
message.int64_map[1] = 2
message.int64_map[2] = 3
message.uint32_map[1] = 2
message.uint32_map[2] = 3
message.uint64_map[1] = 2
message.uint64_map[2] = 3
message.string_map['1'] = 2
message.string_map['null'] = 3
self.assertEqual(
json.loads(json_format.MessageToJson(message, True)),
json.loads('{'
'"boolMap": {"false": 2, "true": 1},'
'"int32Map": {"1": 2, "2": 3},'
'"int64Map": {"1": 2, "2": 3},'
'"uint32Map": {"1": 2, "2": 3},'
'"uint64Map": {"1": 2, "2": 3},'
'"stringMap": {"1": 2, "null": 3}'
'}'))
parsed_message = json_format_proto3_pb2.TestMap()
self.CheckParseBack(message, parsed_message)
def testOneofFields(self):
message = json_format_proto3_pb2.TestOneof()
# Always print does not affect oneof fields.
self.assertEqual(
json_format.MessageToJson(message, True),
'{}')
message.oneof_int32_value = 0
self.assertEqual(
json_format.MessageToJson(message, True),
'{\n'
' "oneofInt32Value": 0\n'
'}')
parsed_message = json_format_proto3_pb2.TestOneof()
self.CheckParseBack(message, parsed_message)
def testTimestampMessage(self):
message = json_format_proto3_pb2.TestTimestamp()
message.value.seconds = 0
message.value.nanos = 0
message.repeated_value.add().seconds = 20
message.repeated_value[0].nanos = 1
message.repeated_value.add().seconds = 0
message.repeated_value[1].nanos = 10000
message.repeated_value.add().seconds = 100000000
message.repeated_value[2].nanos = 0
# Maximum time
message.repeated_value.add().seconds = 253402300799
message.repeated_value[3].nanos = 999999999
# Minimum time
message.repeated_value.add().seconds = -62135596800
message.repeated_value[4].nanos = 0
self.assertEqual(
json.loads(json_format.MessageToJson(message, True)),
json.loads('{'
'"value": "1970-01-01T00:00:00Z",'
'"repeatedValue": ['
' "1970-01-01T00:00:20.000000001Z",'
' "1970-01-01T00:00:00.000010Z",'
' "1973-03-03T09:46:40Z",'
' "9999-12-31T23:59:59.999999999Z",'
' "0001-01-01T00:00:00Z"'
']'
'}'))
parsed_message = json_format_proto3_pb2.TestTimestamp()
self.CheckParseBack(message, parsed_message)
text = (r'{"value": "1972-01-01T01:00:00.01+08:00",'
r'"repeatedValue":['
r' "1972-01-01T01:00:00.01+08:30",'
r' "1972-01-01T01:00:00.01-01:23"]}')
json_format.Parse(text, parsed_message)
self.assertEqual(parsed_message.value.seconds, 63104400)
self.assertEqual(parsed_message.value.nanos, 10000000)
self.assertEqual(parsed_message.repeated_value[0].seconds, 63106200)
self.assertEqual(parsed_message.repeated_value[1].seconds, 63070620)
def testDurationMessage(self):
message = json_format_proto3_pb2.TestDuration()
message.value.seconds = 1
message.repeated_value.add().seconds = 0
message.repeated_value[0].nanos = 10
message.repeated_value.add().seconds = -1
message.repeated_value[1].nanos = -1000
message.repeated_value.add().seconds = 10
message.repeated_value[2].nanos = 11000000
message.repeated_value.add().seconds = -315576000000
message.repeated_value.add().seconds = 315576000000
self.assertEqual(
json.loads(json_format.MessageToJson(message, True)),
json.loads('{'
'"value": "1s",'
'"repeatedValue": ['
' "0.000000010s",'
' "-1.000001s",'
' "10.011s",'
' "-315576000000s",'
' "315576000000s"'
']'
'}'))
parsed_message = json_format_proto3_pb2.TestDuration()
self.CheckParseBack(message, parsed_message)
def testFieldMaskMessage(self):
message = json_format_proto3_pb2.TestFieldMask()
message.value.paths.append('foo.bar')
message.value.paths.append('bar')
self.assertEqual(
json_format.MessageToJson(message, True),
'{\n'
' "value": "foo.bar,bar"\n'
'}')
parsed_message = json_format_proto3_pb2.TestFieldMask()
self.CheckParseBack(message, parsed_message)
def testWrapperMessage(self):
message = json_format_proto3_pb2.TestWrapper()
message.bool_value.value = False
message.int32_value.value = 0
message.string_value.value = ''
message.bytes_value.value = b''
message.repeated_bool_value.add().value = True
message.repeated_bool_value.add().value = False
self.assertEqual(
json.loads(json_format.MessageToJson(message, True)),
json.loads('{\n'
' "int32Value": 0,'
' "boolValue": false,'
' "stringValue": "",'
' "bytesValue": "",'
' "repeatedBoolValue": [true, false],'
' "repeatedInt32Value": [],'
' "repeatedUint32Value": [],'
' "repeatedFloatValue": [],'
' "repeatedDoubleValue": [],'
' "repeatedBytesValue": [],'
' "repeatedInt64Value": [],'
' "repeatedUint64Value": [],'
' "repeatedStringValue": []'
'}'))
parsed_message = json_format_proto3_pb2.TestWrapper()
self.CheckParseBack(message, parsed_message)
def testParseNull(self):
message = json_format_proto3_pb2.TestMessage()
message.repeated_int32_value.append(1)
message.repeated_int32_value.append(2)
message.repeated_int32_value.append(3)
parsed_message = json_format_proto3_pb2.TestMessage()
self.FillAllFields(parsed_message)
json_format.Parse('{"int32Value": null, '
'"int64Value": null, '
'"uint32Value": null,'
'"uint64Value": null,'
'"floatValue": null,'
'"doubleValue": null,'
'"boolValue": null,'
'"stringValue": null,'
'"bytesValue": null,'
'"messageValue": null,'
'"enumValue": null,'
'"repeatedInt32Value": [1, 2, null, 3],'
'"repeatedInt64Value": null,'
'"repeatedUint32Value": null,'
'"repeatedUint64Value": null,'
'"repeatedFloatValue": null,'
'"repeatedDoubleValue": null,'
'"repeatedBoolValue": null,'
'"repeatedStringValue": null,'
'"repeatedBytesValue": null,'
'"repeatedMessageValue": null,'
'"repeatedEnumValue": null'
'}',
parsed_message)
self.assertEqual(message, parsed_message)
def testNanFloat(self):
message = json_format_proto3_pb2.TestMessage()
message.float_value = float('nan')
text = '{\n "floatValue": "NaN"\n}'
self.assertEqual(json_format.MessageToJson(message), text)
parsed_message = json_format_proto3_pb2.TestMessage()
json_format.Parse(text, parsed_message)
self.assertTrue(math.isnan(parsed_message.float_value))
def testParseEmptyText(self):
self.CheckError('',
r'Failed to load JSON: (Expecting value)|(No JSON)')
def testParseBadEnumValue(self):
self.CheckError(
'{"enumValue": 1}',
'Enum value must be a string literal with double quotes. '
'Type "proto3.EnumType" has no value named 1.')
self.CheckError(
'{"enumValue": "baz"}',
'Enum value must be a string literal with double quotes. '
'Type "proto3.EnumType" has no value named baz.')
def testParseBadIdentifer(self):
self.CheckError('{int32Value: 1}',
(r'Failed to load JSON: Expecting property name enclosed '
r'in double quotes: line 1'))
self.CheckError('{"unknownName": 1}',
'Message type "proto3.TestMessage" has no field named '
'"unknownName".')
def testDuplicateField(self):
self.CheckError('{"int32Value": 1,\n"int32Value":2}',
'Failed to load JSON: duplicate key int32Value')
def testInvalidBoolValue(self):
self.CheckError('{"boolValue": 1}',
'Failed to parse boolValue field: '
'Expected true or false without quotes.')
self.CheckError('{"boolValue": "true"}',
'Failed to parse boolValue field: '
'Expected true or false without quotes.')
def testInvalidIntegerValue(self):
message = json_format_proto3_pb2.TestMessage()
text = '{"int32Value": 0x12345}'
self.assertRaises(json_format.ParseError,
json_format.Parse, text, message)
self.CheckError('{"int32Value": 012345}',
(r'Failed to load JSON: Expecting \',\' delimiter: '
r'line 1'))
self.CheckError('{"int32Value": 1.0}',
'Failed to parse int32Value field: '
'Couldn\'t parse integer: 1.0')
self.CheckError('{"int32Value": " 1 "}',
'Failed to parse int32Value field: '
'Couldn\'t parse integer: " 1 "')
self.CheckError('{"int32Value": 12345678901234567890}',
'Failed to parse int32Value field: Value out of range: '
'12345678901234567890')
self.CheckError('{"int32Value": 1e5}',
'Failed to parse int32Value field: '
'Couldn\'t parse integer: 100000.0')
self.CheckError('{"uint32Value": -1}',
'Failed to parse uint32Value field: Value out of range: -1')
def testInvalidFloatValue(self):
self.CheckError('{"floatValue": "nan"}',
'Failed to parse floatValue field: Couldn\'t '
'parse float "nan", use "NaN" instead')
def testInvalidBytesValue(self):
self.CheckError('{"bytesValue": "AQI"}',
'Failed to parse bytesValue field: Incorrect padding')
self.CheckError('{"bytesValue": "AQI*"}',
'Failed to parse bytesValue field: Incorrect padding')
def testInvalidMap(self):
message = json_format_proto3_pb2.TestMap()
text = '{"int32Map": {"null": 2, "2": 3}}'
self.assertRaisesRegexp(
json_format.ParseError,
'Failed to parse int32Map field: Couldn\'t parse integer: "null"',
json_format.Parse, text, message)
text = '{"int32Map": {1: 2, "2": 3}}'
self.assertRaisesRegexp(
json_format.ParseError,
(r'Failed to load JSON: Expecting property name enclosed '
r'in double quotes: line 1'),
json_format.Parse, text, message)
text = r'{"stringMap": {"a": 3, "\u0061": 2}}'
self.assertRaisesRegexp(
json_format.ParseError,
'Failed to load JSON: duplicate key a',
json_format.Parse, text, message)
text = '{"boolMap": {"null": 1}}'
self.assertRaisesRegexp(
json_format.ParseError,
'Failed to parse boolMap field: Expect "true" or "false", not null.',
json_format.Parse, text, message)
def testInvalidTimestamp(self):
message = json_format_proto3_pb2.TestTimestamp()
text = '{"value": "10000-01-01T00:00:00.00Z"}'
self.assertRaisesRegexp(
json_format.ParseError,
'time data \'10000-01-01T00:00:00\' does not match'
' format \'%Y-%m-%dT%H:%M:%S\'',
json_format.Parse, text, message)
text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}'
self.assertRaisesRegexp(
json_format.ParseError,
'Failed to parse value field: Failed to parse Timestamp: '
'nanos 0123456789012 more than 9 fractional digits.',
json_format.Parse, text, message)
text = '{"value": "1972-01-01T01:00:00.01+08"}'
self.assertRaisesRegexp(
json_format.ParseError,
(r'Failed to parse value field: Invalid timezone offset value: \+08'),
json_format.Parse, text, message)
# Time smaller than minimum time.
text = '{"value": "0000-01-01T00:00:00Z"}'
self.assertRaisesRegexp(
json_format.ParseError,
'Failed to parse value field: year is out of range',
json_format.Parse, text, message)
# Time bigger than maxinum time.
message.value.seconds = 253402300800
self.assertRaisesRegexp(
json_format.SerializeToJsonError,
'Failed to serialize value field: year is out of range',
json_format.MessageToJson, message)
def testInvalidOneof(self):
message = json_format_proto3_pb2.TestOneof()
text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}'
self.assertRaisesRegexp(
json_format.ParseError,
'Message type "proto3.TestOneof"'
' should not have multiple "oneof_value" oneof fields.',
json_format.Parse, text, message)
if __name__ == '__main__':
unittest.main()

View File

@ -34,10 +34,7 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import descriptor_pb2
from google.protobuf.internal import factory_test1_pb2
from google.protobuf.internal import factory_test2_pb2
@ -45,7 +42,6 @@ from google.protobuf import descriptor_database
from google.protobuf import descriptor_pool
from google.protobuf import message_factory
class MessageFactoryTest(unittest.TestCase):
def setUp(self):

View File

@ -43,22 +43,16 @@ abstract interface.
__author__ = 'gps@google.com (Gregory P. Smith)'
import collections
import copy
import math
import operator
import pickle
import six
import sys
import six
if six.PY3:
long = int
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf.internal import _parameterized
from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_pb2
@ -68,6 +62,9 @@ from google.protobuf.internal import packed_field_test_pb2
from google.protobuf.internal import test_util
from google.protobuf import message
if six.PY3:
long = int
# Python pre-2.6 does not have isinf() or isnan() functions, so we have
# to provide our own.
def isnan(val):
@ -442,7 +439,7 @@ class MessageTest(unittest.TestCase):
message.repeated_nested_message.add().bb = 24
message.repeated_nested_message.add().bb = 10
message.repeated_nested_message.sort(key=lambda z: z.bb // 10)
self.assertEquals(
self.assertEqual(
[13, 11, 10, 21, 20, 24, 33],
[n.bb for n in message.repeated_nested_message])
@ -451,7 +448,7 @@ class MessageTest(unittest.TestCase):
pb = message.SerializeToString()
message.Clear()
message.MergeFromString(pb)
self.assertEquals(
self.assertEqual(
[13, 11, 10, 21, 20, 24, 33],
[n.bb for n in message.repeated_nested_message])
@ -914,7 +911,6 @@ class MessageTest(unittest.TestCase):
with self.assertRaises(pickle.PickleError) as _:
pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL)
def testSortEmptyRepeatedCompositeContainer(self, message_module):
"""Exercise a scenario that has led to segfaults in the past.
"""

View File

@ -50,3 +50,7 @@ message TestMissingEnumValues {
repeated NestedEnum repeated_nested_enum = 2;
repeated NestedEnum packed_nested_enum = 3 [packed = true];
}
message JustString {
required string dummy = 1;
}

View File

@ -34,14 +34,10 @@
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict #PY26
try:
import unittest2 as unittest #PY26
except ImportError:
import unittest
from ordereddict import OrderedDict #PY26
import collections
import unittest
from google.protobuf import descriptor_pb2
from google.protobuf import descriptor_pool
from google.protobuf import proto_builder

View File

@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2007 Google Inc. All Rights Reserved.
#
# This code is meant to work on Python 2.4 and above only.
#
# TODO(robinson): Helpers for verbose, common checks like seeing if a

View File

@ -38,14 +38,10 @@ pure-Python protocol compiler.
import copy
import gc
import operator
import struct
try:
import unittest2 as unittest
except ImportError:
import unittest
import six
import struct
import unittest
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
@ -1627,7 +1623,7 @@ class ReflectionTest(unittest.TestCase):
self.assertFalse(proto.IsInitialized(errors))
self.assertEqual(errors, ['a', 'b', 'c'])
@unittest.skipIf(
@test_util.skipIf(
api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
'Errors are only available from the most recent C++ implementation.')
def testFileDescriptorErrors(self):
@ -1799,7 +1795,6 @@ class ReflectionTest(unittest.TestCase):
# Just check the default value.
self.assertEqual(57, msg.inner.value)
# Since we had so many tests for protocol buffer equality, we broke these out
# into separate TestCase classes.
@ -2827,7 +2822,7 @@ class OptionsTest(unittest.TestCase):
class ClassAPITest(unittest.TestCase):
@unittest.skipIf(
@test_util.skipIf(
api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
'C++ implementation requires a call to MakeDescriptor()')
def testMakeClassWithNestedDescriptor(self):

View File

@ -34,10 +34,7 @@
__author__ = 'petar@google.com (Petar Petrov)'
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import unittest_pb2
from google.protobuf import service_reflection
from google.protobuf import service

View File

@ -32,27 +32,29 @@
"""Tests for google.protobuf.symbol_database."""
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import unittest_pb2
from google.protobuf import descriptor
from google.protobuf import symbol_database
class SymbolDatabaseTest(unittest.TestCase):
def _Database(self):
db = symbol_database.SymbolDatabase()
# Register representative types from unittest_pb2.
db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR)
db.RegisterMessage(unittest_pb2.TestAllTypes)
db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage)
db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup)
db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup)
db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR)
db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR)
return db
# TODO(b/17734095): Remove this difference when the C++ implementation
# supports multiple databases.
if descriptor._USE_C_DESCRIPTORS:
return symbol_database.Default()
else:
db = symbol_database.SymbolDatabase()
# Register representative types from unittest_pb2.
db.RegisterFileDescriptor(unittest_pb2.DESCRIPTOR)
db.RegisterMessage(unittest_pb2.TestAllTypes)
db.RegisterMessage(unittest_pb2.TestAllTypes.NestedMessage)
db.RegisterMessage(unittest_pb2.TestAllTypes.OptionalGroup)
db.RegisterMessage(unittest_pb2.TestAllTypes.RepeatedGroup)
db.RegisterEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR)
db.RegisterEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR)
return db
def testGetPrototype(self):
instance = self._Database().GetPrototype(

View File

@ -38,6 +38,13 @@ __author__ = 'robinson@google.com (Will Robinson)'
import os.path
import sys
# PY2.6 compatible skipIf
if sys.version_info < (2, 7):
from unittest2 import skipIf
else:
from unittest import skipIf
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2

View File

@ -32,10 +32,7 @@
"""Tests for google.protobuf.text_encoding."""
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import text_encoding
TEST_VALUES = [

View File

@ -34,14 +34,12 @@
__author__ = 'kenton@google.com (Kenton Varda)'
import re
import six
import string
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf.internal import _parameterized
from google.protobuf import map_unittest_pb2
@ -389,7 +387,7 @@ class TextFormatTest(TextFormatBase):
# Ideally the schemas would be made more similar so these tests could pass.
class OnlyWorksWithProto2RightNowTests(TextFormatBase):
def testPrintAllFieldsPointy(self, message_module):
def testPrintAllFieldsPointy(self):
message = unittest_pb2.TestAllTypes()
test_util.SetAllFields(message)
self.CompareToGoldenFile(

View File

@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2008 Google Inc. All Rights Reserved.
"""Provides type checking routines.
This module defines type checking utilities in the forms of dictionaries:
@ -52,6 +50,7 @@ import six
if six.PY3:
long = int
from google.protobuf.internal import api_implementation
from google.protobuf.internal import decoder
from google.protobuf.internal import encoder
from google.protobuf.internal import wire_format

View File

@ -35,11 +35,7 @@
__author__ = 'bohdank@google.com (Bohdan Koval)'
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
@ -52,7 +48,7 @@ from google.protobuf.internal import type_checkers
def SkipIfCppImplementation(func):
return unittest.skipIf(
return test_util.skipIf(
api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
'C++ implementation does not expose unknown fields to Python')(func)
@ -262,6 +258,19 @@ class UnknownEnumValuesTest(unittest.TestCase):
decoder(value, 0, len(value), self.message, result_dict)
return result_dict[field_descriptor]
def testUnknownParseMismatchEnumValue(self):
just_string = missing_enum_values_pb2.JustString()
just_string.dummy = 'blah'
missing = missing_enum_values_pb2.TestEnumValues()
# The parse is invalid, storing the string proto into the set of
# unknown fields.
missing.ParseFromString(just_string.SerializeToString())
# Fetching the enum field shouldn't crash, instead returning the
# default value.
self.assertEqual(missing.optional_nested_enum, 0)
@SkipIfCppImplementation
def testUnknownEnumValue(self):
self.assertFalse(self.missing_message.HasField('optional_nested_enum'))

View File

@ -34,10 +34,7 @@
__author__ = 'robinson@google.com (Will Robinson)'
try:
import unittest2 as unittest
except ImportError:
import unittest
import unittest
from google.protobuf import message
from google.protobuf.internal import wire_format

View File

@ -0,0 +1,601 @@
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
# https://developers.google.com/protocol-buffers/
#
# 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.
"""Contains routines for printing protocol messages in JSON format."""
__author__ = 'jieluo@google.com (Jie Luo)'
import base64
from datetime import datetime
import json
import math
import re
from google.protobuf import descriptor
_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
_NUMBER = re.compile(u'[0-9+-][0-9e.+-]*')
_INTEGER = re.compile(u'[0-9+-]')
_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32,
descriptor.FieldDescriptor.CPPTYPE_UINT32,
descriptor.FieldDescriptor.CPPTYPE_INT64,
descriptor.FieldDescriptor.CPPTYPE_UINT64])
_INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64,
descriptor.FieldDescriptor.CPPTYPE_UINT64])
_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT,
descriptor.FieldDescriptor.CPPTYPE_DOUBLE])
if str is bytes:
_UNICODETYPE = unicode
else:
_UNICODETYPE = str
class SerializeToJsonError(Exception):
"""Thrown if serialization to JSON fails."""
class ParseError(Exception):
"""Thrown in case of parsing error."""
def MessageToJson(message, including_default_value_fields=False):
"""Converts protobuf message to JSON format.
Args:
message: The protocol buffers message instance to serialize.
including_default_value_fields: If True, singular primitive fields,
repeated fields, and map fields will always be serialized. If
False, only serialize non-empty fields. Singular message fields
and oneof fields are not affected by this option.
Returns:
A string containing the JSON formatted protocol buffer message.
"""
js = _MessageToJsonObject(message, including_default_value_fields)
return json.dumps(js, indent=2)
def _MessageToJsonObject(message, including_default_value_fields):
"""Converts message to an object according to Proto3 JSON Specification."""
message_descriptor = message.DESCRIPTOR
if _IsTimestampMessage(message_descriptor):
return _TimestampMessageToJsonObject(message)
if _IsDurationMessage(message_descriptor):
return _DurationMessageToJsonObject(message)
if _IsFieldMaskMessage(message_descriptor):
return _FieldMaskMessageToJsonObject(message)
if _IsWrapperMessage(message_descriptor):
return _WrapperMessageToJsonObject(message)
return _RegularMessageToJsonObject(message, including_default_value_fields)
def _IsMapEntry(field):
return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
field.message_type.has_options and
field.message_type.GetOptions().map_entry)
def _RegularMessageToJsonObject(message, including_default_value_fields):
"""Converts normal message according to Proto3 JSON Specification."""
js = {}
fields = message.ListFields()
try:
for field, value in fields:
name = field.camelcase_name
if _IsMapEntry(field):
# Convert a map field.
js_map = {}
for key in value:
js_map[key] = _ConvertFieldToJsonObject(
field.message_type.fields_by_name['value'],
value[key], including_default_value_fields)
js[name] = js_map
elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
# Convert a repeated field.
repeated = []
for element in value:
repeated.append(_ConvertFieldToJsonObject(
field, element, including_default_value_fields))
js[name] = repeated
else:
js[name] = _ConvertFieldToJsonObject(
field, value, including_default_value_fields)
# Serialize default value if including_default_value_fields is True.
if including_default_value_fields:
message_descriptor = message.DESCRIPTOR
for field in message_descriptor.fields:
# Singular message fields and oneof fields will not be affected.
if ((field.label != descriptor.FieldDescriptor.LABEL_REPEATED and
field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE) or
field.containing_oneof):
continue
name = field.camelcase_name
if name in js:
# Skip the field which has been serailized already.
continue
if _IsMapEntry(field):
js[name] = {}
elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
js[name] = []
else:
js[name] = _ConvertFieldToJsonObject(field, field.default_value)
except ValueError as e:
raise SerializeToJsonError(
'Failed to serialize {0} field: {1}'.format(field.name, e))
return js
def _ConvertFieldToJsonObject(
field, value, including_default_value_fields=False):
"""Converts field value according to Proto3 JSON Specification."""
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
return _MessageToJsonObject(value, including_default_value_fields)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
enum_value = field.enum_type.values_by_number.get(value, None)
if enum_value is not None:
return enum_value.name
else:
raise SerializeToJsonError('Enum field contains an integer value '
'which can not mapped to an enum value.')
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
# Use base64 Data encoding for bytes
return base64.b64encode(value).decode('utf-8')
else:
return value
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
if value:
return True
else:
return False
elif field.cpp_type in _INT64_TYPES:
return str(value)
elif field.cpp_type in _FLOAT_TYPES:
if math.isinf(value):
if value < 0.0:
return '-Infinity'
else:
return 'Infinity'
if math.isnan(value):
return 'NaN'
return value
def _IsTimestampMessage(message_descriptor):
return (message_descriptor.name == 'Timestamp' and
message_descriptor.file.name == 'google/protobuf/timestamp.proto')
def _TimestampMessageToJsonObject(message):
"""Converts Timestamp message according to Proto3 JSON Specification."""
nanos = message.nanos % 1e9
dt = datetime.utcfromtimestamp(
message.seconds + (message.nanos - nanos) / 1e9)
result = dt.isoformat()
if (nanos % 1e9) == 0:
# If there are 0 fractional digits, the fractional
# point '.' should be omitted when serializing.
return result + 'Z'
if (nanos % 1e6) == 0:
# Serialize 3 fractional digits.
return result + '.%03dZ' % (nanos / 1e6)
if (nanos % 1e3) == 0:
# Serialize 6 fractional digits.
return result + '.%06dZ' % (nanos / 1e3)
# Serialize 9 fractional digits.
return result + '.%09dZ' % nanos
def _IsDurationMessage(message_descriptor):
return (message_descriptor.name == 'Duration' and
message_descriptor.file.name == 'google/protobuf/duration.proto')
def _DurationMessageToJsonObject(message):
"""Converts Duration message according to Proto3 JSON Specification."""
if message.seconds < 0 or message.nanos < 0:
result = '-'
seconds = - message.seconds + int((0 - message.nanos) / 1e9)
nanos = (0 - message.nanos) % 1e9
else:
result = ''
seconds = message.seconds + int(message.nanos / 1e9)
nanos = message.nanos % 1e9
result += '%d' % seconds
if (nanos % 1e9) == 0:
# If there are 0 fractional digits, the fractional
# point '.' should be omitted when serializing.
return result + 's'
if (nanos % 1e6) == 0:
# Serialize 3 fractional digits.
return result + '.%03ds' % (nanos / 1e6)
if (nanos % 1e3) == 0:
# Serialize 6 fractional digits.
return result + '.%06ds' % (nanos / 1e3)
# Serialize 9 fractional digits.
return result + '.%09ds' % nanos
def _IsFieldMaskMessage(message_descriptor):
return (message_descriptor.name == 'FieldMask' and
message_descriptor.file.name == 'google/protobuf/field_mask.proto')
def _FieldMaskMessageToJsonObject(message):
"""Converts FieldMask message according to Proto3 JSON Specification."""
result = ''
first = True
for path in message.paths:
if not first:
result += ','
result += path
first = False
return result
def _IsWrapperMessage(message_descriptor):
return message_descriptor.file.name == 'google/protobuf/wrappers.proto'
def _WrapperMessageToJsonObject(message):
return _ConvertFieldToJsonObject(
message.DESCRIPTOR.fields_by_name['value'], message.value)
def _DuplicateChecker(js):
result = {}
for name, value in js:
if name in result:
raise ParseError('Failed to load JSON: duplicate key ' + name)
result[name] = value
return result
def Parse(text, message):
"""Parses a JSON representation of a protocol message into a message.
Args:
text: Message JSON representation.
message: A protocol beffer message to merge into.
Returns:
The same message passed as argument.
Raises::
ParseError: On JSON parsing problems.
"""
if not isinstance(text, _UNICODETYPE): text = text.decode('utf-8')
try:
js = json.loads(text, object_pairs_hook=_DuplicateChecker)
except ValueError as e:
raise ParseError('Failed to load JSON: ' + str(e))
_ConvertFieldValuePair(js, message)
return message
def _ConvertFieldValuePair(js, message):
"""Convert field value pairs into regular message.
Args:
js: A JSON object to convert the field value pairs.
message: A regular protocol message to record the data.
Raises:
ParseError: In case of problems converting.
"""
names = []
message_descriptor = message.DESCRIPTOR
for name in js:
try:
field = message_descriptor.fields_by_camelcase_name.get(name, None)
if not field:
raise ParseError(
'Message type "{0}" has no field named "{1}".'.format(
message_descriptor.full_name, name))
if name in names:
raise ParseError(
'Message type "{0}" should not have multiple "{1}" fields.'.format(
message.DESCRIPTOR.full_name, name))
names.append(name)
# Check no other oneof field is parsed.
if field.containing_oneof is not None:
oneof_name = field.containing_oneof.name
if oneof_name in names:
raise ParseError('Message type "{0}" should not have multiple "{1}" '
'oneof fields.'.format(
message.DESCRIPTOR.full_name, oneof_name))
names.append(oneof_name)
value = js[name]
if value is None:
message.ClearField(field.name)
continue
# Parse field value.
if _IsMapEntry(field):
message.ClearField(field.name)
_ConvertMapFieldValue(value, message, field)
elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
message.ClearField(field.name)
if not isinstance(value, list):
raise ParseError('repeated field {0} must be in [] which is '
'{1}'.format(name, value))
for item in value:
if item is None:
continue
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
sub_message = getattr(message, field.name).add()
_ConvertMessage(item, sub_message)
else:
getattr(message, field.name).append(
_ConvertScalarFieldValue(item, field))
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
sub_message = getattr(message, field.name)
_ConvertMessage(value, sub_message)
else:
setattr(message, field.name, _ConvertScalarFieldValue(value, field))
except ParseError as e:
if field and field.containing_oneof is None:
raise ParseError('Failed to parse {0} field: {1}'.format(name, e))
else:
raise ParseError(str(e))
except ValueError as e:
raise ParseError('Failed to parse {0} field: {1}'.format(name, e))
except TypeError as e:
raise ParseError('Failed to parse {0} field: {1}'.format(name, e))
def _ConvertMessage(value, message):
"""Convert a JSON object into a message.
Args:
value: A JSON object.
message: A WKT or regular protocol message to record the data.
Raises:
ParseError: In case of convert problems.
"""
message_descriptor = message.DESCRIPTOR
if _IsTimestampMessage(message_descriptor):
_ConvertTimestampMessage(value, message)
elif _IsDurationMessage(message_descriptor):
_ConvertDurationMessage(value, message)
elif _IsFieldMaskMessage(message_descriptor):
_ConvertFieldMaskMessage(value, message)
elif _IsWrapperMessage(message_descriptor):
_ConvertWrapperMessage(value, message)
else:
_ConvertFieldValuePair(value, message)
def _ConvertTimestampMessage(value, message):
"""Convert a JSON representation into Timestamp message."""
timezone_offset = value.find('Z')
if timezone_offset == -1:
timezone_offset = value.find('+')
if timezone_offset == -1:
timezone_offset = value.rfind('-')
if timezone_offset == -1:
raise ParseError(
'Failed to parse timestamp: missing valid timezone offset.')
time_value = value[0:timezone_offset]
# Parse datetime and nanos
point_position = time_value.find('.')
if point_position == -1:
second_value = time_value
nano_value = ''
else:
second_value = time_value[:point_position]
nano_value = time_value[point_position + 1:]
date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT)
seconds = (date_object - datetime(1970, 1, 1)).total_seconds()
if len(nano_value) > 9:
raise ParseError(
'Failed to parse Timestamp: nanos {0} more than '
'9 fractional digits.'.format(nano_value))
if nano_value:
nanos = round(float('0.' + nano_value) * 1e9)
else:
nanos = 0
# Parse timezone offsets
if value[timezone_offset] == 'Z':
if len(value) != timezone_offset + 1:
raise ParseError(
'Failed to parse timestamp: invalid trailing data {0}.'.format(value))
else:
timezone = value[timezone_offset:]
pos = timezone.find(':')
if pos == -1:
raise ParseError(
'Invalid timezone offset value: ' + timezone)
if timezone[0] == '+':
seconds += (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60
else:
seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60
# Set seconds and nanos
message.seconds = int(seconds)
message.nanos = int(nanos)
def _ConvertDurationMessage(value, message):
"""Convert a JSON representation into Duration message."""
if value[-1] != 's':
raise ParseError(
'Duration must end with letter "s": ' + value)
try:
duration = float(value[:-1])
except ValueError:
raise ParseError(
'Couldn\'t parse duration: ' + value)
message.seconds = int(duration)
message.nanos = int(round((duration - message.seconds) * 1e9))
def _ConvertFieldMaskMessage(value, message):
"""Convert a JSON representation into FieldMask message."""
for path in value.split(','):
message.paths.append(path)
def _ConvertWrapperMessage(value, message):
"""Convert a JSON representation into Wrapper message."""
field = message.DESCRIPTOR.fields_by_name['value']
setattr(message, 'value', _ConvertScalarFieldValue(value, field))
def _ConvertMapFieldValue(value, message, field):
"""Convert map field value for a message map field.
Args:
value: A JSON object to convert the map field value.
message: A protocol message to record the converted data.
field: The descriptor of the map field to be converted.
Raises:
ParseError: In case of convert problems.
"""
if not isinstance(value, dict):
raise ParseError(
'Map fieled {0} must be in {} which is {1}.'.format(field.name, value))
key_field = field.message_type.fields_by_name['key']
value_field = field.message_type.fields_by_name['value']
for key in value:
key_value = _ConvertScalarFieldValue(key, key_field, True)
if value_field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
_ConvertMessage(value[key], getattr(message, field.name)[key_value])
else:
getattr(message, field.name)[key_value] = _ConvertScalarFieldValue(
value[key], value_field)
def _ConvertScalarFieldValue(value, field, require_quote=False):
"""Convert a single scalar field value.
Args:
value: A scalar value to convert the scalar field value.
field: The descriptor of the field to convert.
require_quote: If True, '"' is required for the field value.
Returns:
The converted scalar field value
Raises:
ParseError: In case of convert problems.
"""
if field.cpp_type in _INT_TYPES:
return _ConvertInteger(value)
elif field.cpp_type in _FLOAT_TYPES:
return _ConvertFloat(value)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:
return _ConvertBool(value, require_quote)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
return base64.b64decode(value)
else:
return value
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
# Convert an enum value.
enum_value = field.enum_type.values_by_name.get(value, None)
if enum_value is None:
raise ParseError(
'Enum value must be a string literal with double quotes. '
'Type "{0}" has no value named {1}.'.format(
field.enum_type.full_name, value))
return enum_value.number
def _ConvertInteger(value):
"""Convert an integer.
Args:
value: A scalar value to convert.
Returns:
The integer value.
Raises:
ParseError: If an integer couldn't be consumed.
"""
if isinstance(value, float):
raise ParseError('Couldn\'t parse integer: {0}'.format(value))
if isinstance(value, _UNICODETYPE) and not _INTEGER.match(value):
raise ParseError('Couldn\'t parse integer: "{0}"'.format(value))
return int(value)
def _ConvertFloat(value):
"""Convert an floating point number."""
if value == 'nan':
raise ParseError('Couldn\'t parse float "nan", use "NaN" instead')
try:
# Assume Python compatible syntax.
return float(value)
except ValueError:
# Check alternative spellings.
if value == '-Infinity':
return float('-inf')
elif value == 'Infinity':
return float('inf')
elif value == 'NaN':
return float('nan')
else:
raise ParseError('Couldn\'t parse float: {0}'.format(value))
def _ConvertBool(value, require_quote):
"""Convert a boolean value.
Args:
value: A scalar value to convert.
require_quote: If True, '"' is required for the boolean value.
Returns:
The bool parsed.
Raises:
ParseError: If a boolean value couldn't be consumed.
"""
if require_quote:
if value == 'true':
return True
elif value == 'false':
return False
else:
raise ParseError('Expect "true" or "false", not {0}.'.format(value))
if not isinstance(value, bool):
raise ParseError('Expected true or false without quotes.')
return value

View File

@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2012 Google Inc. All Rights Reserved.
"""Provides a factory class for generating dynamic messages.
The easiest way to use this class is if you have access to the FileDescriptor

View File

@ -48,7 +48,7 @@ def _GetMessageFromFactory(factory, full_name):
factory: a MessageFactory instance.
full_name: str, the fully qualified name of the proto type.
Returns:
a class, for the type identified by full_name.
A class, for the type identified by full_name.
Raises:
KeyError, if the proto is not found in the factory's descriptor pool.
"""
@ -57,7 +57,7 @@ def _GetMessageFromFactory(factory, full_name):
return proto_cls
def MakeSimpleProtoClass(fields, full_name, pool=None):
def MakeSimpleProtoClass(fields, full_name=None, pool=None):
"""Create a Protobuf class whose fields are basic types.
Note: this doesn't validate field names!
@ -66,18 +66,20 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
fields: dict of {name: field_type} mappings for each field in the proto. If
this is an OrderedDict the order will be maintained, otherwise the
fields will be sorted by name.
full_name: str, the fully-qualified name of the proto type.
full_name: optional str, the fully-qualified name of the proto type.
pool: optional DescriptorPool instance.
Returns:
a class, the new protobuf class with a FileDescriptor.
"""
factory = message_factory.MessageFactory(pool=pool)
try:
proto_cls = _GetMessageFromFactory(factory, full_name)
return proto_cls
except KeyError:
# The factory's DescriptorPool doesn't know about this class yet.
pass
if full_name is not None:
try:
proto_cls = _GetMessageFromFactory(factory, full_name)
return proto_cls
except KeyError:
# The factory's DescriptorPool doesn't know about this class yet.
pass
# Get a list of (name, field_type) tuples from the fields dict. If fields was
# an OrderedDict we keep the order, but otherwise we sort the field to ensure
@ -94,6 +96,25 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
fields_hash.update(str(f_type).encode('utf-8'))
proto_file_name = fields_hash.hexdigest() + '.proto'
# If the proto is anonymous, use the same hash to name it.
if full_name is None:
full_name = ('net.proto2.python.public.proto_builder.AnonymousProto_' +
fields_hash.hexdigest())
try:
proto_cls = _GetMessageFromFactory(factory, full_name)
return proto_cls
except KeyError:
# The factory's DescriptorPool doesn't know about this class yet.
pass
# This is the first time we see this proto: add a new descriptor to the pool.
factory.pool.Add(
_MakeFileDescriptorProto(proto_file_name, full_name, field_items))
return _GetMessageFromFactory(factory, full_name)
def _MakeFileDescriptorProto(proto_file_name, full_name, field_items):
"""Populate FileDescriptorProto for MessageFactory's DescriptorPool."""
package, name = full_name.rsplit('.', 1)
file_proto = descriptor_pb2.FileDescriptorProto()
file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name)
@ -106,6 +127,4 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
field_proto.number = f_number
field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
field_proto.type = f_type
factory.pool.Add(file_proto)
return _GetMessageFromFactory(factory, full_name)
return file_proto

View File

@ -223,8 +223,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
options.SerializeToString(&serialized);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
input.SetExtensionRegistry(pool->pool,
GetDescriptorPool()->message_factory);
input.SetExtensionRegistry(pool->pool, pool->message_factory);
bool success = cmsg->message->MergePartialFromCodedStream(&input);
if (!success) {
PyErr_Format(PyExc_ValueError, "Error parsing Options message");
@ -414,8 +413,14 @@ static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
}
static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
// Retuns the canonical class for the given descriptor.
// This is the class that was registered with the primary descriptor pool
// which contains this descriptor.
// This might not be the one you expect! For example the returned object does
// not know about extensions defined in a custom pool.
PyObject* concrete_class(cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), _GetDescriptor(self)));
GetDescriptorPool_FromPool(_GetDescriptor(self)->file()->pool()),
_GetDescriptor(self)));
Py_XINCREF(concrete_class);
return concrete_class;
}
@ -424,6 +429,11 @@ static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {
return NewMessageFieldsByName(_GetDescriptor(self));
}
static PyObject* GetFieldsByCamelcaseName(PyBaseDescriptor* self,
void *closure) {
return NewMessageFieldsByCamelcaseName(_GetDescriptor(self));
}
static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) {
return NewMessageFieldsByNumber(_GetDescriptor(self));
}
@ -564,6 +574,8 @@ static PyGetSetDef Getters[] = {
{ "fields", (getter)GetFieldsSeq, NULL, "Fields sequence"},
{ "fields_by_name", (getter)GetFieldsByName, NULL, "Fields by name"},
{ "fields_by_camelcase_name", (getter)GetFieldsByCamelcaseName, NULL,
"Fields by camelCase name"},
{ "fields_by_number", (getter)GetFieldsByNumber, NULL, "Fields by number"},
{ "nested_types", (getter)GetNestedTypesSeq, NULL, "Nested types sequence"},
{ "nested_types_by_name", (getter)GetNestedTypesByName, NULL,
@ -662,6 +674,10 @@ static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
return PyString_FromCppString(_GetDescriptor(self)->name());
}
static PyObject* GetCamelcaseName(PyBaseDescriptor* self, void *closure) {
return PyString_FromCppString(_GetDescriptor(self)->camelcase_name());
}
static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->type());
}
@ -850,6 +866,7 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
static PyGetSetDef Getters[] = {
{ "full_name", (getter)GetFullName, NULL, "Full name"},
{ "name", (getter)GetName, NULL, "Unqualified name"},
{ "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"},
{ "type", (getter)GetType, NULL, "C++ Type"},
{ "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
{ "label", (getter)GetLabel, NULL, "Label"},
@ -1070,6 +1087,15 @@ PyObject* PyEnumDescriptor_FromDescriptor(
&PyEnumDescriptor_Type, enum_descriptor, NULL);
}
const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj) {
if (!PyObject_TypeCheck(obj, &PyEnumDescriptor_Type)) {
PyErr_SetString(PyExc_TypeError, "Not an EnumDescriptor");
return NULL;
}
return reinterpret_cast<const EnumDescriptor*>(
reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
}
namespace enumvalue_descriptor {
// Unchecked accessor to the C++ pointer.
@ -1359,6 +1385,15 @@ PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
return py_descriptor;
}
const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj) {
if (!PyObject_TypeCheck(obj, &PyFileDescriptor_Type)) {
PyErr_SetString(PyExc_TypeError, "Not a FileDescriptor");
return NULL;
}
return reinterpret_cast<const FileDescriptor*>(
reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
}
namespace oneof_descriptor {
// Unchecked accessor to the C++ pointer.

View File

@ -72,6 +72,8 @@ PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
// exception set.
const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj);
const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj);
const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj);
const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj);
// Returns the raw C++ pointer.
const void* PyDescriptor_AsVoidPtr(PyObject* obj);

View File

@ -79,9 +79,12 @@ struct PyContainer;
typedef int (*CountMethod)(PyContainer* self);
typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
const string& name);
typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
typedef const string& (*GetItemNameMethod)(const void* descriptor);
typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor);
typedef int (*GetItemNumberMethod)(const void* descriptor);
typedef int (*GetItemIndexMethod)(const void* descriptor);
@ -95,6 +98,9 @@ struct DescriptorContainerDef {
// Retrieve item by name (usually a call to some 'FindByName' method).
// Used by "by_name" mappings.
GetByNameMethod get_by_name_fn;
// Retrieve item by camelcase name (usually a call to some
// 'FindByCamelcaseName' method). Used by "by_camelcase_name" mappings.
GetByCamelcaseNameMethod get_by_camelcase_name_fn;
// Retrieve item by declared number (field tag, or enum value).
// Used by "by_number" mappings.
GetByNumberMethod get_by_number_fn;
@ -102,6 +108,9 @@ struct DescriptorContainerDef {
NewObjectFromItemMethod new_object_from_item_fn;
// Retrieve the name of an item. Used by iterators on "by_name" mappings.
GetItemNameMethod get_item_name_fn;
// Retrieve the camelcase name of an item. Used by iterators on
// "by_camelcase_name" mappings.
GetItemCamelcaseNameMethod get_item_camelcase_name_fn;
// Retrieve the number of an item. Used by iterators on "by_number" mappings.
GetItemNumberMethod get_item_number_fn;
// Retrieve the index of an item for the container type.
@ -125,6 +134,7 @@ struct PyContainer {
enum ContainerKind {
KIND_SEQUENCE,
KIND_BYNAME,
KIND_BYCAMELCASENAME,
KIND_BYNUMBER,
} kind;
};
@ -172,6 +182,23 @@ static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
self, string(name, name_size));
return true;
}
case PyContainer::KIND_BYCAMELCASENAME:
{
char* camelcase_name;
Py_ssize_t name_size;
if (PyString_AsStringAndSize(key, &camelcase_name, &name_size) < 0) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
// Not a string, cannot be in the container.
PyErr_Clear();
*item = NULL;
return true;
}
return false;
}
*item = self->container_def->get_by_camelcase_name_fn(
self, string(camelcase_name, name_size));
return true;
}
case PyContainer::KIND_BYNUMBER:
{
Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
@ -203,6 +230,12 @@ static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
const string& name(self->container_def->get_item_name_fn(item));
return PyString_FromStringAndSize(name.c_str(), name.size());
}
case PyContainer::KIND_BYCAMELCASENAME:
{
const string& name(
self->container_def->get_item_camelcase_name_fn(item));
return PyString_FromStringAndSize(name.c_str(), name.size());
}
case PyContainer::KIND_BYNUMBER:
{
int value = self->container_def->get_item_number_fn(item);
@ -276,6 +309,9 @@ static PyObject* ContainerRepr(PyContainer* self) {
case PyContainer::KIND_BYNAME:
kind = "mapping by name";
break;
case PyContainer::KIND_BYCAMELCASENAME:
kind = "mapping by camelCase name";
break;
case PyContainer::KIND_BYNUMBER:
kind = "mapping by number";
break;
@ -731,6 +767,18 @@ static PyObject* NewMappingByName(
return reinterpret_cast<PyObject*>(self);
}
static PyObject* NewMappingByCamelcaseName(
DescriptorContainerDef* container_def, const void* descriptor) {
PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
if (self == NULL) {
return NULL;
}
self->descriptor = descriptor;
self->container_def = container_def;
self->kind = PyContainer::KIND_BYCAMELCASENAME;
return reinterpret_cast<PyObject*>(self);
}
static PyObject* NewMappingByNumber(
DescriptorContainerDef* container_def, const void* descriptor) {
if (container_def->get_by_number_fn == NULL ||
@ -889,6 +937,11 @@ static ItemDescriptor GetByName(PyContainer* self, const string& name) {
return GetDescriptor(self)->FindFieldByName(name);
}
static ItemDescriptor GetByCamelcaseName(PyContainer* self,
const string& name) {
return GetDescriptor(self)->FindFieldByCamelcaseName(name);
}
static ItemDescriptor GetByNumber(PyContainer* self, int number) {
return GetDescriptor(self)->FindFieldByNumber(number);
}
@ -905,6 +958,10 @@ static const string& GetItemName(ItemDescriptor item) {
return item->name();
}
static const string& GetItemCamelcaseName(ItemDescriptor item) {
return item->camelcase_name();
}
static int GetItemNumber(ItemDescriptor item) {
return item->number();
}
@ -918,9 +975,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)GetByCamelcaseName,
(GetByNumberMethod)GetByNumber,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)GetItemCamelcaseName,
(GetItemNumberMethod)GetItemNumber,
(GetItemIndexMethod)GetItemIndex,
};
@ -931,6 +990,11 @@ PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
}
PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) {
return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef,
descriptor);
}
PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
}
@ -972,9 +1036,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1022,9 +1088,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1094,9 +1162,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)NULL,
};
@ -1140,9 +1210,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1190,9 +1262,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1258,9 +1332,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)GetByNumber,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)GetItemNumber,
(GetItemIndexMethod)GetItemIndex,
};
@ -1314,9 +1390,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)NULL,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)NULL,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1370,9 +1448,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1416,9 +1496,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1462,9 +1544,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)GetByName,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)GetItemName,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)GetItemIndex,
};
@ -1496,9 +1580,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)NULL,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)NULL,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)NULL,
};
@ -1530,9 +1616,11 @@ static DescriptorContainerDef ContainerDef = {
(CountMethod)Count,
(GetByIndexMethod)GetByIndex,
(GetByNameMethod)NULL,
(GetByCamelcaseNameMethod)NULL,
(GetByNumberMethod)NULL,
(NewObjectFromItemMethod)NewObjectFromItem,
(GetItemNameMethod)NULL,
(GetItemCamelcaseNameMethod)NULL,
(GetItemNumberMethod)NULL,
(GetItemIndexMethod)NULL,
};

View File

@ -54,6 +54,7 @@ bool InitDescriptorMappingTypes();
namespace message_descriptor {
PyObject* NewMessageFieldsByName(const Descriptor* descriptor);
PyObject* NewMessageFieldsByCamelcaseName(const Descriptor* descriptor);
PyObject* NewMessageFieldsByNumber(const Descriptor* descriptor);
PyObject* NewMessageFieldsSeq(const Descriptor* descriptor);

View File

@ -108,6 +108,7 @@ static void Dealloc(PyDescriptorPool* self) {
Py_DECREF(it->second);
}
delete self->descriptor_options;
delete self->pool;
delete self->message_factory;
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@ -131,22 +132,9 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
}
// Add a message class to our database.
const Descriptor* RegisterMessageClass(
PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) {
ScopedPyObjectPtr full_message_name(
PyObject_GetAttrString(descriptor, "full_name"));
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(full_message_name, &name, &name_size) < 0) {
return NULL;
}
const Descriptor *message_descriptor =
self->pool->FindMessageTypeByName(string(name, name_size));
if (!message_descriptor) {
PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'",
name);
return NULL;
}
int RegisterMessageClass(PyDescriptorPool* self,
const Descriptor *message_descriptor,
PyObject *message_class) {
Py_INCREF(message_class);
typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
@ -156,7 +144,7 @@ const Descriptor* RegisterMessageClass(
Py_DECREF(ret.first->second);
ret.first->second = message_class;
}
return message_descriptor;
return 0;
}
// Retrieve the message class added to our database.
@ -260,6 +248,80 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
return PyOneofDescriptor_FromDescriptor(oneof_descriptor);
}
PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
return NULL;
}
const FileDescriptor* file_descriptor =
self->pool->FindFileContainingSymbol(string(name, name_size));
if (file_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name);
return NULL;
}
return PyFileDescriptor_FromDescriptor(file_descriptor);
}
// These functions should not exist -- the only valid way to create
// descriptors is to call Add() or AddSerializedFile().
// But these AddDescriptor() functions were created in Python and some people
// call them, so we support them for now for compatibility.
// However we do check that the existing descriptor already exists in the pool,
// which appears to always be true for existing calls -- but then why do people
// call a function that will just be a no-op?
// TODO(amauryfa): Need to investigate further.
PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
const FileDescriptor* file_descriptor =
PyFileDescriptor_AsDescriptor(descriptor);
if (!file_descriptor) {
return NULL;
}
if (file_descriptor !=
self->pool->FindFileByName(file_descriptor->name())) {
PyErr_Format(PyExc_ValueError,
"The file descriptor %s does not belong to this pool",
file_descriptor->name().c_str());
return NULL;
}
Py_RETURN_NONE;
}
PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
const Descriptor* message_descriptor =
PyMessageDescriptor_AsDescriptor(descriptor);
if (!message_descriptor) {
return NULL;
}
if (message_descriptor !=
self->pool->FindMessageTypeByName(message_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The message descriptor %s does not belong to this pool",
message_descriptor->full_name().c_str());
return NULL;
}
Py_RETURN_NONE;
}
PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
const EnumDescriptor* enum_descriptor =
PyEnumDescriptor_AsDescriptor(descriptor);
if (!enum_descriptor) {
return NULL;
}
if (enum_descriptor !=
self->pool->FindEnumTypeByName(enum_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The enum descriptor %s does not belong to this pool",
enum_descriptor->full_name().c_str());
return NULL;
}
Py_RETURN_NONE;
}
// The code below loads new Descriptors from a serialized FileDescriptorProto.
@ -341,6 +403,15 @@ static PyMethodDef Methods[] = {
{ "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O,
"Adds a serialized FileDescriptorProto to this pool." },
// TODO(amauryfa): Understand why the Python implementation differs from
// this one, ask users to use another API and deprecate these functions.
{ "AddFileDescriptor", (PyCFunction)AddFileDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddDescriptor", (PyCFunction)AddDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "FindFileByName", (PyCFunction)FindFileByName, METH_O,
"Searches for a file descriptor by its .proto name." },
{ "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O,
@ -353,6 +424,9 @@ static PyMethodDef Methods[] = {
"Searches for enum type descriptor by full name." },
{ "FindOneofByName", (PyCFunction)FindOneofByName, METH_O,
"Searches for oneof descriptor by full name." },
{ "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O,
"Gets the FileDescriptor containing the specified symbol." },
{NULL}
};
@ -420,7 +494,7 @@ bool InitDescriptorPool() {
return true;
}
PyDescriptorPool* GetDescriptorPool() {
PyDescriptorPool* GetDefaultDescriptorPool() {
return python_generated_pool;
}
@ -432,7 +506,7 @@ PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool) {
}
hash_map<const DescriptorPool*, PyDescriptorPool*>::iterator it =
descriptor_pool_map.find(pool);
if (it != descriptor_pool_map.end()) {
if (it == descriptor_pool_map.end()) {
PyErr_SetString(PyExc_KeyError, "Unknown descriptor pool");
return NULL;
}

View File

@ -89,12 +89,10 @@ const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
const string& name);
// Registers a new Python class for the given message descriptor.
// Returns the message Descriptor.
// On error, returns NULL with a Python exception set.
const Descriptor* RegisterMessageClass(
PyDescriptorPool* self, PyObject* message_class, PyObject* descriptor);
// The function below are also exposed as methods of the DescriptorPool type.
// On error, returns -1 with a Python exception set.
int RegisterMessageClass(PyDescriptorPool* self,
const Descriptor* message_descriptor,
PyObject* message_class);
// Retrieves the Python class registered with the given message descriptor.
//
@ -103,6 +101,8 @@ const Descriptor* RegisterMessageClass(
PyObject* GetMessageClass(PyDescriptorPool* self,
const Descriptor* message_descriptor);
// The functions below are also exposed as methods of the DescriptorPool type.
// Looks up a message by name. Returns a PyMessageDescriptor corresponding to
// the field on success, or NULL on failure.
//
@ -136,8 +136,9 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg);
} // namespace cdescriptor_pool
// Retrieve the global descriptor pool owned by the _message module.
// This is the one used by pb2.py generated modules.
// Returns a *borrowed* reference.
PyDescriptorPool* GetDescriptorPool();
PyDescriptorPool* GetDefaultDescriptorPool();
// Retrieve the python descriptor pool owning a C++ descriptor pool.
// Returns a *borrowed* reference.

View File

@ -123,7 +123,8 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyObject *message_class = cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), descriptor->message_type());
cmessage::GetDescriptorPoolForMessage(self->parent),
descriptor->message_type());
if (message_class == NULL) {
return NULL;
}

View File

@ -55,6 +55,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/extension_dict.h>
@ -107,8 +108,18 @@ struct PyMessageMeta {
// C++ descriptor of this message.
const Descriptor* message_descriptor;
// Owned reference, used to keep the pointer above alive.
PyObject* py_message_descriptor;
// The Python DescriptorPool used to create the class. It is needed to resolve
// fields descriptors, including extensions fields; its C++ MessageFactory is
// used to instantiate submessages.
// This can be different from DESCRIPTOR.file.pool, in the case of a custom
// DescriptorPool which defines new extensions.
// We own the reference, because it's important to keep the descriptors and
// factory alive.
PyDescriptorPool* py_descriptor_pool;
};
namespace message_meta {
@ -139,18 +150,10 @@ static bool AddFieldNumberToClass(
// Finalize the creation of the Message class.
// Called from its metaclass: GeneratedProtocolMessageType.__init__().
static int AddDescriptors(PyObject* cls, PyObject* descriptor) {
const Descriptor* message_descriptor =
cdescriptor_pool::RegisterMessageClass(
GetDescriptorPool(), cls, descriptor);
if (message_descriptor == NULL) {
return -1;
}
static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
// If there are extension_ranges, the message is "extendable", and extension
// classes will register themselves in this class.
if (message_descriptor->extension_range_count() > 0) {
if (descriptor->extension_range_count() > 0) {
ScopedPyObjectPtr by_name(PyDict_New());
if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
return -1;
@ -162,8 +165,8 @@ static int AddDescriptors(PyObject* cls, PyObject* descriptor) {
}
// For each field set: cls.<field>_FIELD_NUMBER = <number>
for (int i = 0; i < message_descriptor->field_count(); ++i) {
if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
for (int i = 0; i < descriptor->field_count(); ++i) {
if (!AddFieldNumberToClass(cls, descriptor->field(i))) {
return -1;
}
}
@ -173,8 +176,8 @@ static int AddDescriptors(PyObject* cls, PyObject* descriptor) {
// The enum descriptor we get from
// <messagedescriptor>.enum_types_by_name[name]
// which was built previously.
for (int i = 0; i < message_descriptor->enum_type_count(); ++i) {
const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
for (int i = 0; i < descriptor->enum_type_count(); ++i) {
const EnumDescriptor* enum_descriptor = descriptor->enum_type(i);
ScopedPyObjectPtr enum_type(
PyEnumDescriptor_FromDescriptor(enum_descriptor));
if (enum_type == NULL) {
@ -212,8 +215,8 @@ static int AddDescriptors(PyObject* cls, PyObject* descriptor) {
// Extension descriptors come from
// <message descriptor>.extensions_by_name[name]
// which was defined previously.
for (int i = 0; i < message_descriptor->extension_count(); ++i) {
const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
for (int i = 0; i < descriptor->extension_count(); ++i) {
const google::protobuf::FieldDescriptor* field = descriptor->extension(i);
ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
if (extension_field == NULL) {
return -1;
@ -258,14 +261,14 @@ static PyObject* New(PyTypeObject* type,
}
// Check dict['DESCRIPTOR']
PyObject* descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
if (descriptor == NULL) {
PyObject* py_descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
if (py_descriptor == NULL) {
PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
return NULL;
}
if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
if (!PyObject_TypeCheck(py_descriptor, &PyMessageDescriptor_Type)) {
PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
descriptor->ob_type->tp_name);
py_descriptor->ob_type->tp_name);
return NULL;
}
@ -291,14 +294,28 @@ static PyObject* New(PyTypeObject* type,
}
// Cache the descriptor, both as Python object and as C++ pointer.
const Descriptor* message_descriptor =
PyMessageDescriptor_AsDescriptor(descriptor);
if (message_descriptor == NULL) {
const Descriptor* descriptor =
PyMessageDescriptor_AsDescriptor(py_descriptor);
if (descriptor == NULL) {
return NULL;
}
Py_INCREF(py_descriptor);
newtype->py_message_descriptor = py_descriptor;
newtype->message_descriptor = descriptor;
// TODO(amauryfa): Don't always use the canonical pool of the descriptor,
// use the MessageFactory optionally passed in the class dict.
newtype->py_descriptor_pool = GetDescriptorPool_FromPool(
descriptor->file()->pool());
if (newtype->py_descriptor_pool == NULL) {
return NULL;
}
Py_INCREF(newtype->py_descriptor_pool);
// Add the message to the DescriptorPool.
if (cdescriptor_pool::RegisterMessageClass(newtype->py_descriptor_pool,
descriptor, result) < 0) {
return NULL;
}
Py_INCREF(descriptor);
newtype->py_message_descriptor = descriptor;
newtype->message_descriptor = message_descriptor;
// Continue with type initialization: add other descriptors, enum values...
if (AddDescriptors(result, descriptor) < 0) {
@ -309,6 +326,7 @@ static PyObject* New(PyTypeObject* type,
static void Dealloc(PyMessageMeta *self) {
Py_DECREF(self->py_message_descriptor);
Py_DECREF(self->py_descriptor_pool);
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@ -381,12 +399,20 @@ PyTypeObject PyMessageMeta_Type = {
message_meta::New, // tp_new
};
static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
static PyMessageMeta* CheckMessageClass(PyTypeObject* cls) {
if (!PyObject_TypeCheck(cls, &PyMessageMeta_Type)) {
PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name);
return NULL;
}
return reinterpret_cast<PyMessageMeta*>(cls)->message_descriptor;
return reinterpret_cast<PyMessageMeta*>(cls);
}
static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
PyMessageMeta* type = CheckMessageClass(cls);
if (type == NULL) {
return NULL;
}
return type->message_descriptor;
}
// Forward declarations
@ -723,6 +749,17 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
namespace cmessage {
PyDescriptorPool* GetDescriptorPoolForMessage(CMessage* message) {
// No need to check the type: the type of instances of CMessage is always
// an instance of PyMessageMeta. Let's prove it with a debug-only check.
GOOGLE_DCHECK(PyObject_TypeCheck(message, &CMessage_Type));
return reinterpret_cast<PyMessageMeta*>(Py_TYPE(message))->py_descriptor_pool;
}
MessageFactory* GetFactoryForMessage(CMessage* message) {
return GetDescriptorPoolForMessage(message)->message_factory;
}
static int MaybeReleaseOverlappingOneofField(
CMessage* cmessage,
const FieldDescriptor* field) {
@ -773,7 +810,7 @@ static Message* GetMutableMessage(
return NULL;
}
return reflection->MutableMessage(
parent_message, parent_field, GetDescriptorPool()->message_factory);
parent_message, parent_field, GetFactoryForMessage(parent));
}
struct FixupMessageReference : public ChildVisitor {
@ -814,10 +851,7 @@ int AssureWritable(CMessage* self) {
// If parent is NULL but we are trying to modify a read-only message, this
// is a reference to a constant default instance that needs to be replaced
// with a mutable top-level message.
const Message* prototype =
GetDescriptorPool()->message_factory->GetPrototype(
self->message->GetDescriptor());
self->message = prototype->New();
self->message = self->message->New();
self->owner.reset(self->message);
// Cascade the new owner to eventual children: even if this message is
// empty, some submessages or repeated containers might exist already.
@ -1190,15 +1224,19 @@ CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) {
// The __new__ method of Message classes.
// Creates a new C++ message and takes ownership.
static PyObject* New(PyTypeObject* type,
static PyObject* New(PyTypeObject* cls,
PyObject* unused_args, PyObject* unused_kwargs) {
PyMessageMeta* type = CheckMessageClass(cls);
if (type == NULL) {
return NULL;
}
// Retrieve the message descriptor and the default instance (=prototype).
const Descriptor* message_descriptor = GetMessageDescriptor(type);
const Descriptor* message_descriptor = type->message_descriptor;
if (message_descriptor == NULL) {
return NULL;
}
const Message* default_message =
GetDescriptorPool()->message_factory->GetPrototype(message_descriptor);
const Message* default_message = type->py_descriptor_pool->message_factory
->GetPrototype(message_descriptor);
if (default_message == NULL) {
PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
return NULL;
@ -1528,7 +1566,7 @@ int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
Message* ReleaseMessage(CMessage* self,
const Descriptor* descriptor,
const FieldDescriptor* field_descriptor) {
MessageFactory* message_factory = GetDescriptorPool()->message_factory;
MessageFactory* message_factory = GetFactoryForMessage(self);
Message* released_message = self->message->GetReflection()->ReleaseMessage(
self->message, field_descriptor, message_factory);
// ReleaseMessage will return NULL which differs from
@ -1883,8 +1921,8 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
AssureWritable(self);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(data), data_length);
input.SetExtensionRegistry(GetDescriptorPool()->pool,
GetDescriptorPool()->message_factory);
PyDescriptorPool* pool = GetDescriptorPoolForMessage(self);
input.SetExtensionRegistry(pool->pool, pool->message_factory);
bool success = self->message->MergePartialFromCodedStream(&input);
if (success) {
return PyInt_FromLong(input.CurrentPosition());
@ -1907,11 +1945,6 @@ static PyObject* ByteSize(CMessage* self, PyObject* args) {
static PyObject* RegisterExtension(PyObject* cls,
PyObject* extension_handle) {
ScopedPyObjectPtr message_descriptor(PyObject_GetAttr(cls, kDESCRIPTOR));
if (message_descriptor == NULL) {
return NULL;
}
const FieldDescriptor* descriptor =
GetExtensionDescriptor(extension_handle);
if (descriptor == NULL) {
@ -1920,13 +1953,6 @@ static PyObject* RegisterExtension(PyObject* cls,
const Descriptor* cmessage_descriptor = GetMessageDescriptor(
reinterpret_cast<PyTypeObject*>(cls));
if (cmessage_descriptor != descriptor->containing_type()) {
if (PyObject_SetAttrString(extension_handle, "containing_type",
message_descriptor) < 0) {
return NULL;
}
}
ScopedPyObjectPtr extensions_by_name(
PyObject_GetAttr(cls, k_extensions_by_name));
if (extensions_by_name == NULL) {
@ -2050,7 +2076,8 @@ static PyObject* ListFields(CMessage* self) {
// TODO(amauryfa): consider building the class on the fly!
if (fields[i]->message_type() != NULL &&
cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), fields[i]->message_type()) == NULL) {
GetDescriptorPoolForMessage(self),
fields[i]->message_type()) == NULL) {
PyErr_Clear();
continue;
}
@ -2207,7 +2234,9 @@ PyObject* InternalGetScalar(const Message* message,
message->GetReflection()->GetUnknownFields(*message);
for (int i = 0; i < unknown_field_set.field_count(); ++i) {
if (unknown_field_set.field(i).number() ==
field_descriptor->number()) {
field_descriptor->number() &&
unknown_field_set.field(i).type() ==
google::protobuf::UnknownField::TYPE_VARINT) {
result = PyInt_FromLong(unknown_field_set.field(i).varint());
break;
}
@ -2233,11 +2262,12 @@ PyObject* InternalGetScalar(const Message* message,
PyObject* InternalGetSubMessage(
CMessage* self, const FieldDescriptor* field_descriptor) {
const Reflection* reflection = self->message->GetReflection();
PyDescriptorPool* pool = GetDescriptorPoolForMessage(self);
const Message& sub_message = reflection->GetMessage(
*self->message, field_descriptor, GetDescriptorPool()->message_factory);
*self->message, field_descriptor, pool->message_factory);
PyObject *message_class = cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), field_descriptor->message_type());
pool, field_descriptor->message_type());
if (message_class == NULL) {
return NULL;
}
@ -2560,7 +2590,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
const FieldDescriptor* value_type = entry_type->FindFieldByName("value");
if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyObject* value_class = cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), value_type->message_type());
GetDescriptorPoolForMessage(self), value_type->message_type());
if (value_class == NULL) {
return NULL;
}
@ -2583,7 +2613,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
PyObject* py_container = NULL;
if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyObject *message_class = cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), field_descriptor->message_type());
GetDescriptorPoolForMessage(self), field_descriptor->message_type());
if (message_class == NULL) {
return NULL;
}
@ -2908,9 +2938,10 @@ bool InitProto2MessageModule(PyObject *m) {
// Expose the DescriptorPool used to hold all descriptors added from generated
// pb2.py files.
Py_INCREF(GetDescriptorPool()); // PyModule_AddObject steals a reference.
PyModule_AddObject(
m, "default_pool", reinterpret_cast<PyObject*>(GetDescriptorPool()));
// PyModule_AddObject steals a reference.
Py_INCREF(GetDefaultDescriptorPool());
PyModule_AddObject(m, "default_pool",
reinterpret_cast<PyObject*>(GetDefaultDescriptorPool()));
// This implementation provides full Descriptor types, we advertise it so that
// descriptor.py can use them in replacement of the Python classes.

View File

@ -49,12 +49,15 @@ class Message;
class Reflection;
class FieldDescriptor;
class Descriptor;
class DescriptorPool;
class MessageFactory;
using internal::shared_ptr;
namespace python {
struct ExtensionDict;
struct PyDescriptorPool;
typedef struct CMessage {
PyObject_HEAD;
@ -220,6 +223,16 @@ PyObject* FindInitializationErrors(CMessage* self);
int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner);
int AssureWritable(CMessage* self);
// Returns the "best" DescriptorPool for the given message.
// This is often equivalent to message.DESCRIPTOR.pool, but not always, when
// the message class was created from a MessageFactory using a custom pool which
// uses the generated pool as an underlay.
//
// The returned pool is suitable for finding fields and building submessages,
// even in the case of extensions.
PyDescriptorPool* GetDescriptorPoolForMessage(CMessage* message);
} // namespace cmessage

View File

@ -60,6 +60,7 @@ Example usage:
"""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool
@ -72,6 +73,31 @@ class SymbolDatabase(object):
buffer types used within a program.
"""
# pylint: disable=protected-access
if _descriptor._USE_C_DESCRIPTORS:
def __new__(cls):
raise TypeError("Instances of SymbolDatabase cannot be created")
@classmethod
def _CreateDefaultDatabase(cls):
self = object.__new__(cls) # Bypass the __new__ above.
# Don't call __init__() and initialize here.
self._symbols = {}
self._symbols_by_file = {}
# As of today all descriptors are registered and retrieved from
# _message.default_pool (see FileDescriptor.__new__), so it's not
# necessary to use another pool.
self.pool = _descriptor._message.default_pool
return self
# pylint: enable=protected-access
else:
@classmethod
def _CreateDefaultDatabase(cls):
return cls()
def __init__(self):
"""Constructor."""
@ -177,7 +203,7 @@ class SymbolDatabase(object):
result.update(self._symbols_by_file[f])
return result
_DEFAULT = SymbolDatabase()
_DEFAULT = SymbolDatabase._CreateDefaultDatabase()
def Default():

View File

@ -27,6 +27,7 @@
# 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.
"""Encoding related utilities."""
import re

View File

@ -28,9 +28,17 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright 2007 Google Inc. All Rights Reserved.
"""Contains routines for printing protocol messages in text format.
"""Contains routines for printing protocol messages in text format."""
Simple usage example:
# Create a proto object and serialize it to a text proto string.
message = my_proto_pb2.MyMessage(foo='bar')
text_proto = text_format.MessageToString(message)
# Parse a text proto string.
message = text_format.Parse(text_proto, my_proto_pb2.MyMessage())
"""
__author__ = 'kenton@google.com (Kenton Varda)'

View File

View File

@ -88,6 +88,15 @@ def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/unittest_mset_wire_format.proto", False)
generate_proto("../src/google/protobuf/unittest_no_generic_services.proto", False)
generate_proto("../src/google/protobuf/unittest_proto3_arena.proto", False)
# Move the well-known-types proto to required when they are no longer only
# required by json format tests.
generate_proto("../src/google/protobuf/timestamp.proto", False)
generate_proto("../src/google/protobuf/duration.proto", False)
generate_proto("../src/google/protobuf/wrappers.proto", False)
generate_proto("../src/google/protobuf/struct.proto", False)
generate_proto("../src/google/protobuf/any.proto", False)
generate_proto("../src/google/protobuf/field_mask.proto", False)
generate_proto("../src/google/protobuf/util/json_format_proto3.proto", False)
generate_proto("google/protobuf/internal/descriptor_pool_test1.proto", False)
generate_proto("google/protobuf/internal/descriptor_pool_test2.proto", False)
generate_proto("google/protobuf/internal/factory_test1.proto", False)

View File

@ -43,6 +43,7 @@ string GetTypeUrl(const Descriptor* message) {
const char kAnyFullTypeName[] = "google.protobuf.Any";
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
: type_url_(type_url), value_(value) {
@ -70,11 +71,17 @@ bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
}
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
const int prefix_len = strlen(kTypeGoogleApisComPrefix);
if (strncmp(type_url.c_str(), kTypeGoogleApisComPrefix, prefix_len) == 0) {
full_type_name->assign(type_url.data() + prefix_len,
type_url.size() - prefix_len);
return true;
static const char* prefix[] = {
kTypeGoogleApisComPrefix,
kTypeGoogleProdComPrefix
};
for (int i = 0; i < 2; i++) {
const int prefix_len = strlen(prefix[i]);
if (strncmp(type_url.c_str(), prefix[i], prefix_len) == 0) {
full_type_name->assign(type_url.data() + prefix_len,
type_url.size() - prefix_len);
return true;
}
}
return false;
}

View File

@ -70,6 +70,7 @@ class LIBPROTOBUF_EXPORT AnyMetadata {
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
// Get the proto type name from Any::type_url value. For example, passing
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in

View File

@ -38,17 +38,17 @@ namespace google {
namespace protobuf {
google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
#ifdef PROTOBUF_USE_DLLS
Arena::ThreadCache& Arena::thread_cache() {
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
return thread_cache_;
}
#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
Arena::ThreadCache& Arena::thread_cache() {
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
new internal::ThreadLocalStorage<ThreadCache>();
return *thread_cache_->Get();
}
#elif defined(PROTOBUF_USE_DLLS)
Arena::ThreadCache& Arena::thread_cache() {
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
return thread_cache_;
}
#else
GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
#endif

View File

@ -38,7 +38,16 @@
#if __cplusplus >= 201103L
#include <google/protobuf/stubs/type_traits.h>
#endif
#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
#include <exception>
#include <typeinfo>
namespace std {
using type_info = ::type_info;
}
#else
#include <typeinfo>
#endif
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
@ -533,15 +542,15 @@ class LIBPROTOBUF_EXPORT Arena {
static const size_t kHeaderSize = sizeof(Block);
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
#ifdef PROTOBUF_USE_DLLS
// Thread local variables cannot be exposed through DLL interface but we can
// wrap them in static functions.
static ThreadCache& thread_cache();
#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
// local storage class we implemented.
// iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
static ThreadCache& thread_cache();
#elif defined(PROTOBUF_USE_DLLS)
// Thread local variables cannot be exposed through DLL interface but we can
// wrap them in static functions.
static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
@ -581,11 +590,13 @@ class LIBPROTOBUF_EXPORT Arena {
template<typename U>
static double DestructorSkippable(...);
// The raw_skippable_value const bool variable is separated from the typedef
// line below as a work-around of an NVCC 7.0 (and earlier) compiler bug.
static const bool raw_skippable_value =
sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true;
// This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
typedef google::protobuf::internal::integral_constant<bool,
sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true>
type;
typedef google::protobuf::internal::integral_constant<bool, raw_skippable_value> type;
static const type value;
};

View File

@ -362,7 +362,7 @@ TEST(ArenaTest, ReleaseMessage) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->mutable_optional_nested_message()->set_bb(118);
scoped_ptr<TestAllTypes::NestedMessage> nested(
google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
arena_message->release_optional_nested_message());
EXPECT_EQ(118, nested->bb());
@ -383,7 +383,7 @@ TEST(ArenaTest, ReleaseString) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->set_optional_string("hello");
scoped_ptr<string> released_str(
google::protobuf::scoped_ptr<string> released_str(
arena_message->release_optional_string());
EXPECT_EQ("hello", *released_str);

View File

@ -63,13 +63,13 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace compiler {
// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
// which case tcmalloc will print warnings that fail the plugin tests.
#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
namespace google {
namespace protobuf {
namespace compiler {
#if defined(_WIN32)
#ifndef STDIN_FILENO
@ -1800,8 +1800,8 @@ TEST_F(EncodeDecodeTest, ProtoParseError) {
} // anonymous namespace
#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
} // namespace compiler
} // namespace protobuf
#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
} // namespace google

View File

@ -66,7 +66,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["wrapper"] = "EntryWrapper";
break;
case FieldDescriptor::CPPTYPE_ENUM:
(*variables)["val_cpp"] = ClassName(val->enum_type(), false);
(*variables)["val_cpp"] = ClassName(val->enum_type(), true);
(*variables)["wrapper"] = "EnumEntryWrapper";
break;
default:
@ -200,7 +200,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
case FieldDescriptor::CPPTYPE_ENUM:
printer->Print(variables_,
"(*mutable_$name$())[entry->key()] =\n"
" static_cast<$val_cpp$>(*entry->mutable_value());\n");
" static_cast< $val_cpp$ >(*entry->mutable_value());\n");
break;
default:
printer->Print(variables_,
@ -215,7 +215,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" DO_(entry->ParseFromString(data));\n"
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
" (*mutable_$name$())[entry->key()] =\n"
" static_cast<$val_cpp$>(*entry->mutable_value());\n"
" static_cast< $val_cpp$ >(*entry->mutable_value());\n"
" } else {\n");
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(variables_,

View File

@ -350,7 +350,7 @@ void CollectMapInfo(const Descriptor* descriptor,
(*variables)["val"] = FieldMessageTypeName(val);
break;
case FieldDescriptor::CPPTYPE_ENUM:
(*variables)["val"] = ClassName(val->enum_type(), false);
(*variables)["val"] = ClassName(val->enum_type(), true);
break;
default:
(*variables)["val"] = PrimitiveTypeName(val->cpp_type());

View File

@ -299,7 +299,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
" unknownFields.mergeVarintField($number$, rawValue);\n");
" super.mergeVarintField($number$, rawValue);\n");
}
printer->Print(variables_,
"} else {\n"
@ -492,7 +492,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
" unknownFields.mergeVarintField($number$, rawValue);\n");
" super.mergeVarintField($number$, rawValue);\n");
}
printer->Print(variables_,
"} else {\n"
@ -850,7 +850,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
" unknownFields.mergeVarintField($number$, rawValue);\n");
" super.mergeVarintField($number$, rawValue);\n");
}
printer->Print(variables_,
"} else {\n"

View File

@ -405,7 +405,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(
variables_,
"if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
" unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
" super.mergeLengthDelimitedField($number$, bytes);\n"
"} else {\n"
" $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
"}\n");

View File

@ -1029,12 +1029,6 @@ GenerateParsingConstructor(io::Printer* printer) {
"bit_field_name", GetBitFieldName(i));
}
if (PreserveUnknownFields(descriptor_)) {
printer->Print(
"com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
" com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
}
printer->Print(
"try {\n");
printer->Indent();
@ -1056,13 +1050,10 @@ GenerateParsingConstructor(io::Printer* printer) {
if (PreserveUnknownFields(descriptor_)) {
if (descriptor_->extension_range_count() > 0) {
// Lite runtime directly invokes parseUnknownField to reduce method
// counts.
printer->Print(
"default: {\n"
" if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
" input, unknownFields,\n"
" extensionRegistry, tag)) {\n"
" if (!parseUnknownField(getDefaultInstanceForType(),\n"
" input, extensionRegistry, tag)) {\n"
" done = true;\n" // it's an endgroup tag
" }\n"
" break;\n"
@ -1070,8 +1061,7 @@ GenerateParsingConstructor(io::Printer* printer) {
} else {
printer->Print(
"default: {\n"
" if (!parseUnknownField(input, unknownFields,\n"
" extensionRegistry, tag)) {\n"
" if (!parseUnknownField(tag, input)) {\n"
" done = true;\n" // it's an endgroup tag
" }\n"
" break;\n"
@ -1146,16 +1136,8 @@ GenerateParsingConstructor(io::Printer* printer) {
field_generators_.get(field).GenerateParsingDoneCode(printer);
}
if (PreserveUnknownFields(descriptor_)) {
// Make unknown fields immutable.
printer->Print("this.unknownFields = unknownFields.build();\n");
}
if (descriptor_->extension_range_count() > 0) {
// Make extensions immutable.
printer->Print(
"makeExtensionsImmutable(extensions);\n");
}
printer->Print(
"doneParsing();\n");
printer->Outdent();
printer->Outdent();

View File

@ -993,6 +993,9 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
// We intentionally pass field_location rather than location here, since
// the default value is not actually an option.
DO(ParseDefaultAssignment(field, field_location, containing_file));
} else if (LookingAt("json_name")) {
// Like default value, this "json_name" is not an actual option.
DO(ParseJsonName(field, field_location, containing_file));
} else {
DO(ParseOption(field->mutable_options(), location,
containing_file, OPTION_ASSIGNMENT));
@ -1140,6 +1143,28 @@ bool Parser::ParseDefaultAssignment(
return true;
}
bool Parser::ParseJsonName(
FieldDescriptorProto* field,
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file) {
if (field->has_json_name()) {
AddError("Already set option \"json_name\".");
field->clear_json_name();
}
DO(Consume("json_name"));
DO(Consume("="));
LocationRecorder location(field_location,
FieldDescriptorProto::kJsonNameFieldNumber);
location.RecordLegacyLocation(
field, DescriptorPool::ErrorCollector::OPTION_VALUE);
DO(ConsumeString(field->mutable_json_name(),
"Expected string for JSON name."));
return true;
}
bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
const LocationRecorder& part_location,
const FileDescriptorProto* containing_file) {

View File

@ -439,6 +439,10 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file);
bool ParseJsonName(FieldDescriptorProto* field,
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file);
enum OptionStyle {
OPTION_ASSIGNMENT, // just "name = value"
OPTION_STATEMENT // "option name = value;"

View File

@ -452,6 +452,20 @@ TEST_F(ParseMessageTest, FieldDefaults) {
#undef ETC
}
TEST_F(ParseMessageTest, FieldJsonName) {
ExpectParsesTo(
"message TestMessage {\n"
" optional string foo = 1 [json_name = \"@type\"];\n"
"}\n",
"message_type {"
" name: \"TestMessage\""
" field {\n"
" name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
" json_name: \"@type\"\n"
" }\n"
"}\n");
}
TEST_F(ParseMessageTest, FieldOptions) {
ExpectParsesTo(
"message TestMessage {\n"
@ -1126,6 +1140,22 @@ TEST_F(ParseErrorTest, DefaultValueTooLarge) {
"6:36: Integer out of range.\n");
}
TEST_F(ParseErrorTest, JsonNameNotString) {
ExpectHasErrors(
"message TestMessage {\n"
" optional string foo = 1 [json_name=1];\n"
"}\n",
"1:37: Expected string for JSON name.\n");
}
TEST_F(ParseErrorTest, DuplicateJsonName) {
ExpectHasErrors(
"message TestMessage {\n"
" optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n"
"}\n",
"1:41: Already set option \"json_name\".\n");
}
TEST_F(ParseErrorTest, EnumValueOutOfRange) {
ExpectHasErrors(
"enum TestEnum {\n"

View File

@ -28,6 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//#PY25 compatible generated code for GAE.
// Copyright 2007 Google Inc. All Rights Reserved.
// Author: robinson@google.com (Will Robinson)
//
@ -166,6 +167,7 @@ void PrintTopBoilerplate(
printer->Print(
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"# source: $filename$\n"
"\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25
"\n",
"filename", file->name());
if (HasTopLevelEnums(file)) {
@ -257,9 +259,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
case FieldDescriptor::CPPTYPE_ENUM:
return SimpleItoa(field.default_value_enum()->number());
case FieldDescriptor::CPPTYPE_STRING:
return "b\"" + CEscape(field.default_value_string()) +
(field.type() != FieldDescriptor::TYPE_STRING ? "\"" :
"\".decode('utf-8')");
//##!PY25 return "b\"" + CEscape(field.default_value_string()) +
//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" :
//##!PY25 "\".decode('utf-8')");
return "_b(\"" + CEscape(field.default_value_string()) + //##PY25
(field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25
"\").decode('utf-8')"); //##PY25
case FieldDescriptor::CPPTYPE_MESSAGE:
return "None";
}
@ -385,7 +390,8 @@ void Generator::PrintFileDescriptor() const {
printer_->Print(m, file_descriptor_template);
printer_->Indent();
printer_->Print(
"serialized_pb=b'$value$'\n",
//##!PY25 "serialized_pb=b'$value$'\n",
"serialized_pb=_b('$value$')\n", //##PY25
"value", strings::CHexEscape(file_descriptor_serialized_));
if (file_->dependency_count() != 0) {
printer_->Print(",\ndependencies=[");
@ -1029,8 +1035,10 @@ string Generator::OptionsValue(
return "None";
} else {
string full_class_name = "descriptor_pb2." + class_name;
return "_descriptor._ParseOptions(" + full_class_name + "(), b'"
+ CEscape(serialized_options)+ "')";
//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'"
//##!PY25 + CEscape(serialized_options)+ "')";
return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25
+ CEscape(serialized_options)+ "'))"; //##PY25
}
}

View File

@ -34,6 +34,10 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <set>
#include <string>
#include <vector>
@ -1726,6 +1730,20 @@ void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
}
}
void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
if (message_type_count() != proto->message_type_size() ||
extension_count() != proto->extension_size()) {
GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
return;
}
for (int i = 0; i < message_type_count(); i++) {
message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
}
for (int i = 0; i < extension_count(); i++) {
extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
}
}
void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
if (source_code_info_ &&
source_code_info_ != &SourceCodeInfo::default_instance()) {
@ -1770,9 +1788,30 @@ void Descriptor::CopyTo(DescriptorProto* proto) const {
}
}
void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
if (field_count() != proto->field_size() ||
nested_type_count() != proto->nested_type_size() ||
extension_count() != proto->extension_size()) {
GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
return;
}
for (int i = 0; i < field_count(); i++) {
field(i)->CopyJsonNameTo(proto->mutable_field(i));
}
for (int i = 0; i < nested_type_count(); i++) {
nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
}
for (int i = 0; i < extension_count(); i++) {
extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
}
}
void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
proto->set_name(name());
proto->set_number(number());
if (has_json_name_) {
proto->set_json_name(json_name());
}
// Some compilers do not allow static_cast directly between two enum types,
// so we must cast to int first.
@ -1819,6 +1858,10 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
}
}
void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
proto->set_json_name(json_name());
}
void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
proto->set_name(name());
}
@ -4136,6 +4179,14 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
tables_->AllocateString(ToCamelCase(proto.name(),
/* lower_first = */ true));
if (proto.has_json_name()) {
result->has_json_name_ = true;
result->json_name_ = tables_->AllocateString(proto.json_name());
} else {
result->has_json_name_ = false;
result->json_name_ = result->camelcase_name_;
}
// Some compilers do not allow static_cast directly between two enum types,
// so we must cast to int first.
result->type_ = static_cast<FieldDescriptor::Type>(
@ -5040,6 +5091,20 @@ void DescriptorBuilder::ValidateProto3(
}
}
static string ToLowercaseWithoutUnderscores(const string& name) {
string result;
for (int i = 0; i < name.size(); ++i) {
if (name[i] != '_') {
if (name[i] >= 'A' && name[i] <= 'Z') {
result.push_back(name[i] - 'A' + 'a');
} else {
result.push_back(name[i]);
}
}
}
return result;
}
void DescriptorBuilder::ValidateProto3Message(
Descriptor* message, const DescriptorProto& proto) {
for (int i = 0; i < message->nested_type_count(); ++i) {
@ -5067,6 +5132,25 @@ void DescriptorBuilder::ValidateProto3Message(
DescriptorPool::ErrorCollector::OTHER,
"MessageSet is not supported in proto3.");
}
// In proto3, we reject field names if they conflict in camelCase.
// Note that we currently enforce a stricter rule: Field names must be
// unique after being converted to lowercase with underscores removed.
map<string, const FieldDescriptor*> name_to_field;
for (int i = 0; i < message->field_count(); ++i) {
string lowercase_name = ToLowercaseWithoutUnderscores(
message->field(i)->name());
if (name_to_field.find(lowercase_name) != name_to_field.end()) {
AddError(message->full_name(), proto,
DescriptorPool::ErrorCollector::OTHER,
"The JSON camcel-case name of field \"" +
message->field(i)->name() + "\" conflicts with field \"" +
name_to_field[lowercase_name]->name() + "\". This is not " +
"allowed in proto3.");
} else {
name_to_field[lowercase_name] = message->field(i);
}
}
}
void DescriptorBuilder::ValidateProto3Field(
@ -5602,7 +5686,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
// First set the value on the UnknownFieldSet corresponding to the
// innermost message.
scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
google::protobuf::scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
if (!SetOptionValue(field, unknown_fields.get())) {
return false; // SetOptionValue() already added the error.
}
@ -5612,7 +5696,8 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
for (vector<const FieldDescriptor*>::reverse_iterator iter =
intermediate_fields.rbegin();
iter != intermediate_fields.rend(); ++iter) {
scoped_ptr<UnknownFieldSet> parent_unknown_fields(new UnknownFieldSet());
google::protobuf::scoped_ptr<UnknownFieldSet> parent_unknown_fields(
new UnknownFieldSet());
switch ((*iter)->type()) {
case FieldDescriptor::TYPE_MESSAGE: {
io::StringOutputStream outstr(
@ -5998,7 +6083,7 @@ bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
}
const Descriptor* type = option_field->message_type();
scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
google::protobuf::scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
GOOGLE_CHECK(dynamic.get() != NULL)
<< "Could not create an instance of " << option_field->DebugString();

View File

@ -54,6 +54,10 @@
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
#define GOOGLE_PROTOBUF_DESCRIPTOR_H__
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <set>
#include <string>
#include <vector>
@ -111,8 +115,17 @@ class UnknownField;
// Defined in generated_message_reflection.h.
namespace internal {
class GeneratedMessageReflection;
}
class GeneratedMessageReflection;
} // namespace internal
// Defined in command_line_interface.cc
namespace compiler {
class CommandLineInterface;
} // namespace compiler
namespace descriptor_unittest {
class DescriptorTest;
} // namespace descriptor_unittest
// NB, all indices are zero-based.
struct SourceLocation {
@ -343,6 +356,12 @@ class LIBPROTOBUF_EXPORT Descriptor {
private:
typedef MessageOptions OptionsType;
// Allows tests to test CopyTo(proto, true).
friend class ::google::protobuf::descriptor_unittest::DescriptorTest;
// Fill the json_name field of FieldDescriptorProto.
void CopyJsonNameTo(DescriptorProto* proto) const;
// Internal version of DebugString; controls the level of indenting for
// correct depth. Takes |options| to control debug-string options, and
// |include_opening_clause| to indicate whether the "message ... " part of the
@ -484,6 +503,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const string& name() const; // Name of this field within the message.
const string& full_name() const; // Fully-qualified name of the field.
const string& json_name() const; // JSON name of this field.
const FileDescriptor* file() const;// File in which this field was defined.
bool is_extension() const; // Is this an extension field?
int number() const; // Declared tag number.
@ -624,6 +644,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
private:
typedef FieldOptions OptionsType;
// Fill the json_name field of FieldDescriptorProto.
void CopyJsonNameTo(FieldDescriptorProto* proto) const;
// See Descriptor::DebugString().
enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL };
void DebugString(int depth, PrintLabelFlag print_label_flag,
@ -645,6 +668,12 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const string* full_name_;
const string* lowercase_name_;
const string* camelcase_name_;
// Whether the user has specified the json_name field option in the .proto
// file.
bool has_json_name_;
// If has_json_name_ is true, it's the value specified by the user.
// Otherwise, it has the same value as lowercase_name_.
const string* json_name_;
const FileDescriptor* file_;
int number_;
Type type_;
@ -1202,6 +1231,9 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// Write the source code information of this FileDescriptor into the given
// FileDescriptorProto. See CopyTo() above.
void CopySourceCodeInfoTo(FileDescriptorProto* proto) const;
// Fill the json_name field of FieldDescriptorProto for all fields. Can only
// be called after CopyTo().
void CopyJsonNameTo(FileDescriptorProto* proto) const;
// See Descriptor::DebugString().
string DebugString() const;
@ -1559,7 +1591,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// This class contains a lot of hash maps with complicated types that
// we'd like to keep out of the header.
class Tables;
scoped_ptr<Tables> tables_;
google::protobuf::scoped_ptr<Tables> tables_;
bool enforce_dependencies_;
bool allow_unknown_;
@ -1618,6 +1650,7 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, json_name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, lowercase_name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, camelcase_name)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*)

View File

@ -200,7 +200,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_),
-1);
FieldDescriptorProto_descriptor_ = file->message_type(3);
static const int FieldDescriptorProto_offsets_[9] = {
static const int FieldDescriptorProto_offsets_[10] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_),
@ -209,6 +209,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, oneof_index_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, json_name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_),
};
FieldDescriptorProto_reflection_ =
@ -663,101 +664,101 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
"eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005"
"start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang"
"e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024FieldD"
"e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\274\005\n\024FieldD"
"escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003"
" \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi"
"eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*"
".google.protobuf.FieldDescriptorProto.Ty"
"pe\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022"
"\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030\t "
"\001(\005\022.\n\007options\030\010 \001(\0132\035.google.protobuf.F"
"ieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n"
"\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UI"
"NT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006"
"\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYP"
"E_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSA"
"GE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n"
"\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_"
"SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT"
"64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LAB"
"EL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n\024One"
"ofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023Enum"
"DescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002"
" \003(\0132).google.protobuf.EnumValueDescript"
"orProto\022-\n\007options\030\003 \001(\0132\034.google.protob"
"uf.EnumOptions\"l\n\030EnumValueDescriptorPro"
"to\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007opti"
"ons\030\003 \001(\0132!.google.protobuf.EnumValueOpt"
"ions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004name\030"
"\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.protobuf."
"MethodDescriptorProto\0220\n\007options\030\003 \001(\0132\037"
".google.protobuf.ServiceOptions\"\301\001\n\025Meth"
"odDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput"
"_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007opti"
"ons\030\004 \001(\0132\036.google.protobuf.MethodOption"
"s\022\037\n\020client_streaming\030\005 \001(\010:\005false\022\037\n\020se"
"rver_streaming\030\006 \001(\010:\005false\"\252\005\n\013FileOpti"
"ons\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_outer_"
"classname\030\010 \001(\t\022\"\n\023java_multiple_files\030\n"
" \001(\010:\005false\022,\n\035java_generate_equals_and_"
"hash\030\024 \001(\010:\005false\022%\n\026java_string_check_u"
"tf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(\0162)"
".google.protobuf.FileOptions.OptimizeMod"
"e:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_gener"
"ic_services\030\020 \001(\010:\005false\022$\n\025java_generic"
"_services\030\021 \001(\010:\005false\022\"\n\023py_generic_ser"
"vices\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005"
"false\022\037\n\020cc_enable_arenas\030\037 \001(\010:\005false\022\031"
"\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_name"
"space\030% \001(\t\022\'\n\037javanano_use_deprecated_p"
"ackage\030& \001(\010\022C\n\024uninterpreted_option\030\347\007 "
"\003(\0132$.google.protobuf.UninterpretedOptio"
"n\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZ"
"E\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016Mes"
"sageOptions\022&\n\027message_set_wire_format\030\001"
" \001(\010:\005false\022.\n\037no_standard_descriptor_ac"
"cessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:"
"\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpret"
"ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
"erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptio"
"ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
"dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?"
"\n\006jstype\030\006 \001(\0162$.google.protobuf.FieldOp"
"tions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005f"
"alse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030"
"\n \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 "
"\003(\0132$.google.protobuf.UninterpretedOptio"
"n\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRI"
"NG_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJ"
"S_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n"
"\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndep"
"recated\030\003 \001(\010:\005false\022C\n\024uninterpreted_op"
"tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
"tedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions"
"\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpr"
"eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
"nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOp"
"tions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unin"
"terpreted_option\030\347\007 \003(\0132$.google.protobu"
"f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMeth"
"odOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024"
"uninterpreted_option\030\347\007 \003(\0132$.google.pro"
"tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n"
"\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goo"
"gle.protobuf.UninterpretedOption.NamePar"
"t\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_"
"int_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 "
"\001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_valu"
"e\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010Name"
"Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030"
"\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003"
"(\0132(.google.protobuf.SourceCodeInfo.Loca"
"tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s"
"pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022"
"\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de"
"tached_comments\030\006 \003(\tB;\n\023com.google.prot"
"obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G"
"PB", 4962);
"\001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(\0132"
"\035.google.protobuf.FieldOptions\"\266\002\n\004Type\022"
"\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE"
"_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020"
"\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n"
"\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GR"
"OUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022"
"\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_"
"SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SI"
"NT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABE"
"L_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABE"
"L_REPEATED\020\003\"$\n\024OneofDescriptorProto\022\014\n\004"
"name\030\001 \001(\t\"\214\001\n\023EnumDescriptorProto\022\014\n\004na"
"me\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google.protobu"
"f.EnumValueDescriptorProto\022-\n\007options\030\003 "
"\001(\0132\034.google.protobuf.EnumOptions\"l\n\030Enu"
"mValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006n"
"umber\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.pr"
"otobuf.EnumValueOptions\"\220\001\n\026ServiceDescr"
"iptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\013"
"2&.google.protobuf.MethodDescriptorProto"
"\0220\n\007options\030\003 \001(\0132\037.google.protobuf.Serv"
"iceOptions\"\301\001\n\025MethodDescriptorProto\022\014\n\004"
"name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output"
"_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
"otobuf.MethodOptions\022\037\n\020client_streaming"
"\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010:"
"\005false\"\252\005\n\013FileOptions\022\024\n\014java_package\030\001"
" \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
"va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
"enerate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026"
"java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014o"
"ptimize_for\030\t \001(\0162).google.protobuf.File"
"Options.OptimizeMode:\005SPEED\022\022\n\ngo_packag"
"e\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fa"
"lse\022$\n\025java_generic_services\030\021 \001(\010:\005fals"
"e\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n"
"\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_ar"
"enas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030$"
" \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022\'\n\037javana"
"no_use_deprecated_package\030& \001(\010\022C\n\024unint"
"erpreted_option\030\347\007 \003(\0132$.google.protobuf"
".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005"
"SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003"
"*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027messag"
"e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
"ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031"
"\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007"
" \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
"ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
"\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.g"
"oogle.protobuf.FieldOptions.CType:\006STRIN"
"G\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.goog"
"le.protobuf.FieldOptions.JSType:\tJS_NORM"
"AL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 "
"\001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024unint"
"erpreted_option\030\347\007 \003(\0132$.google.protobuf"
".UninterpretedOption\"/\n\005CType\022\n\n\006STRING\020"
"\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSType\022"
"\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NUMB"
"ER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow"
"_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
"C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
"protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:"
"\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
"google.protobuf.UninterpretedOption*\t\010\350\007"
"\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!"
" \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
"(\0132$.google.protobuf.UninterpretedOption"
"*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecat"
"ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
"\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
"tion*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022"
";\n\004name\030\002 \003(\0132-.google.protobuf.Uninterp"
"retedOption.NamePart\022\030\n\020identifier_value"
"\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022ne"
"gative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006"
" \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_"
"value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002"
"(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeI"
"nfo\022:\n\010location\030\001 \003(\0132(.google.protobuf."
"SourceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004"
"path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead"
"ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030"
"\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t"
"B;\n\023com.google.protobufB\020DescriptorProto"
"sH\001Z\ndescriptor\242\002\003GPB", 4981);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@ -4109,6 +4110,7 @@ const int FieldDescriptorProto::kTypeNameFieldNumber;
const int FieldDescriptorProto::kExtendeeFieldNumber;
const int FieldDescriptorProto::kDefaultValueFieldNumber;
const int FieldDescriptorProto::kOneofIndexFieldNumber;
const int FieldDescriptorProto::kJsonNameFieldNumber;
const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
@ -4141,6 +4143,7 @@ void FieldDescriptorProto::SharedCtor() {
extendee_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
oneof_index_ = 0;
json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@ -4155,6 +4158,7 @@ void FieldDescriptorProto::SharedDtor() {
type_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
extendee_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
default_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
delete options_;
}
@ -4204,8 +4208,13 @@ void FieldDescriptorProto::Clear() {
}
oneof_index_ = 0;
}
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
if (_has_bits_[8 / 32] & 768u) {
if (has_json_name()) {
json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
@ -4369,6 +4378,23 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(82)) goto parse_json_name;
break;
}
// optional string json_name = 10;
case 10: {
if (tag == 82) {
parse_json_name:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_json_name()));
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->json_name().data(), this->json_name().length(),
::google::protobuf::internal::WireFormat::PARSE,
"google.protobuf.FieldDescriptorProto.json_name");
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
@ -4466,6 +4492,16 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output);
}
// optional string json_name = 10;
if (has_json_name()) {
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->json_name().data(), this->json_name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
"google.protobuf.FieldDescriptorProto.json_name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
10, this->json_name(), output);
}
if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@ -4549,6 +4585,17 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target);
}
// optional string json_name = 10;
if (has_json_name()) {
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->json_name().data(), this->json_name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
"google.protobuf.FieldDescriptorProto.json_name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
10, this->json_name(), target);
}
if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@ -4616,13 +4663,22 @@ int FieldDescriptorProto::ByteSize() const {
}
}
// optional .google.protobuf.FieldOptions options = 8;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
*this->options_);
}
if (_has_bits_[8 / 32] & 768u) {
// optional string json_name = 10;
if (has_json_name()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->json_name());
}
// optional .google.protobuf.FieldOptions options = 8;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
*this->options_);
}
}
if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@ -4679,6 +4735,10 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
}
}
if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
if (from.has_json_name()) {
set_has_json_name();
json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_);
}
if (from.has_options()) {
mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options());
}
@ -4721,6 +4781,7 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
extendee_.Swap(&other->extendee_);
default_value_.Swap(&other->default_value_);
std::swap(oneof_index_, other->oneof_index_);
json_name_.Swap(&other->json_name_);
std::swap(options_, other->options_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
@ -5048,16 +5109,69 @@ void FieldDescriptorProto::clear_oneof_index() {
// @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
}
// optional .google.protobuf.FieldOptions options = 8;
bool FieldDescriptorProto::has_options() const {
// optional string json_name = 10;
bool FieldDescriptorProto::has_json_name() const {
return (_has_bits_[0] & 0x00000100u) != 0;
}
void FieldDescriptorProto::set_has_options() {
void FieldDescriptorProto::set_has_json_name() {
_has_bits_[0] |= 0x00000100u;
}
void FieldDescriptorProto::clear_has_options() {
void FieldDescriptorProto::clear_has_json_name() {
_has_bits_[0] &= ~0x00000100u;
}
void FieldDescriptorProto::clear_json_name() {
json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_json_name();
}
const ::std::string& FieldDescriptorProto::json_name() const {
// @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
void FieldDescriptorProto::set_json_name(const ::std::string& value) {
set_has_json_name();
json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
}
void FieldDescriptorProto::set_json_name(const char* value) {
set_has_json_name();
json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
}
void FieldDescriptorProto::set_json_name(const char* value, size_t size) {
set_has_json_name();
json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
}
::std::string* FieldDescriptorProto::mutable_json_name() {
set_has_json_name();
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FieldDescriptorProto::release_json_name() {
clear_has_json_name();
return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) {
if (json_name != NULL) {
set_has_json_name();
} else {
clear_has_json_name();
}
json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
}
// optional .google.protobuf.FieldOptions options = 8;
bool FieldDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000200u) != 0;
}
void FieldDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000200u;
}
void FieldDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000200u;
}
void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
clear_has_options();

View File

@ -1133,6 +1133,18 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
::google::protobuf::int32 oneof_index() const;
void set_oneof_index(::google::protobuf::int32 value);
// optional string json_name = 10;
bool has_json_name() const;
void clear_json_name();
static const int kJsonNameFieldNumber = 10;
const ::std::string& json_name() const;
void set_json_name(const ::std::string& value);
void set_json_name(const char* value);
void set_json_name(const char* value, size_t size);
::std::string* mutable_json_name();
::std::string* release_json_name();
void set_allocated_json_name(::std::string* json_name);
// optional .google.protobuf.FieldOptions options = 8;
bool has_options() const;
void clear_options();
@ -1160,6 +1172,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline void clear_has_default_value();
inline void set_has_oneof_index();
inline void clear_has_oneof_index();
inline void set_has_json_name();
inline void clear_has_json_name();
inline void set_has_options();
inline void clear_has_options();
@ -1174,6 +1188,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
int type_;
::google::protobuf::int32 oneof_index_;
::google::protobuf::internal::ArenaStringPtr default_value_;
::google::protobuf::internal::ArenaStringPtr json_name_;
::google::protobuf::FieldOptions* options_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
@ -4678,16 +4693,69 @@ inline void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 valu
// @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
}
// optional .google.protobuf.FieldOptions options = 8;
inline bool FieldDescriptorProto::has_options() const {
// optional string json_name = 10;
inline bool FieldDescriptorProto::has_json_name() const {
return (_has_bits_[0] & 0x00000100u) != 0;
}
inline void FieldDescriptorProto::set_has_options() {
inline void FieldDescriptorProto::set_has_json_name() {
_has_bits_[0] |= 0x00000100u;
}
inline void FieldDescriptorProto::clear_has_options() {
inline void FieldDescriptorProto::clear_has_json_name() {
_has_bits_[0] &= ~0x00000100u;
}
inline void FieldDescriptorProto::clear_json_name() {
json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_json_name();
}
inline const ::std::string& FieldDescriptorProto::json_name() const {
// @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
return json_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FieldDescriptorProto::set_json_name(const ::std::string& value) {
set_has_json_name();
json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
}
inline void FieldDescriptorProto::set_json_name(const char* value) {
set_has_json_name();
json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
}
inline void FieldDescriptorProto::set_json_name(const char* value, size_t size) {
set_has_json_name();
json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
}
inline ::std::string* FieldDescriptorProto::mutable_json_name() {
set_has_json_name();
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name)
return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FieldDescriptorProto::release_json_name() {
clear_has_json_name();
return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) {
if (json_name != NULL) {
set_has_json_name();
} else {
clear_has_json_name();
}
json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name);
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name)
}
// optional .google.protobuf.FieldOptions options = 8;
inline bool FieldDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void FieldDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000200u;
}
inline void FieldDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000200u;
}
inline void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
clear_has_options();

View File

@ -191,6 +191,12 @@ message FieldDescriptorProto {
// list. This field is a member of that oneof.
optional int32 oneof_index = 9;
// JSON name of this field. The value is set by protocol compiler. If the
// user has set a "json_name" option on this field, that option's value
// will be used. Otherwise, it's deduced from the field's name by converting
// it to camelCase.
optional string json_name = 10;
optional FieldOptions options = 8;
}

View File

@ -35,6 +35,10 @@
// This file makes extensive use of RFC 3092. :)
#include <algorithm>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/descriptor.h>
@ -177,7 +181,7 @@ class DescriptorDatabaseTest
EXPECT_FALSE(test_case_->AddToDatabase(file_proto));
}
scoped_ptr<DescriptorDatabaseTestCase> test_case_;
google::protobuf::scoped_ptr<DescriptorDatabaseTestCase> test_case_;
DescriptorDatabase* database_;
};

View File

@ -34,6 +34,10 @@
//
// This file makes extensive use of RFC 3092. :)
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <vector>
#include <google/protobuf/compiler/importer.h>
@ -461,6 +465,16 @@ class DescriptorTest : public testing::Test {
// map<int32, int32> map_int32_int32 = 1;
// }
//
// // in "json.proto"
// message TestMessage4 {
// optional int32 field_name1 = 1;
// optional int32 fieldName2 = 2;
// optional int32 FieldName3 = 3;
// optional int32 _field_name4 = 4;
// optional int32 FIELD_NAME5 = 5;
// optional int32 field_name6 = 6 [json_name = "@type"];
// }
//
// We cheat and use TestForeign as the type for qux rather than create
// an actual nested type.
//
@ -526,6 +540,30 @@ class DescriptorTest : public testing::Test {
FieldDescriptorProto::TYPE_MESSAGE)
->set_type_name("MapInt32Int32Entry");
FileDescriptorProto json_file;
json_file.set_name("json.proto");
json_file.set_syntax("proto3");
DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4");
AddField(message4, "field_name1", 1,
FieldDescriptorProto::LABEL_OPTIONAL,
FieldDescriptorProto::TYPE_INT32);
AddField(message4, "fieldName2", 2,
FieldDescriptorProto::LABEL_OPTIONAL,
FieldDescriptorProto::TYPE_INT32);
AddField(message4, "FieldName3", 3,
FieldDescriptorProto::LABEL_OPTIONAL,
FieldDescriptorProto::TYPE_INT32);
AddField(message4, "_field_name4", 4,
FieldDescriptorProto::LABEL_OPTIONAL,
FieldDescriptorProto::TYPE_INT32);
AddField(message4, "FIELD_NAME5", 5,
FieldDescriptorProto::LABEL_OPTIONAL,
FieldDescriptorProto::TYPE_INT32);
AddField(message4, "field_name6", 6,
FieldDescriptorProto::LABEL_OPTIONAL,
FieldDescriptorProto::TYPE_INT32)
->set_json_name("@type");
// Build the descriptors and get the pointers.
foo_file_ = pool_.BuildFile(foo_file);
ASSERT_TRUE(foo_file_ != NULL);
@ -536,6 +574,9 @@ class DescriptorTest : public testing::Test {
map_file_ = pool_.BuildFile(map_file);
ASSERT_TRUE(map_file_ != NULL);
json_file_ = pool_.BuildFile(json_file);
ASSERT_TRUE(json_file_ != NULL);
ASSERT_EQ(1, foo_file_->enum_type_count());
enum_ = foo_file_->enum_type(0);
@ -562,6 +603,14 @@ class DescriptorTest : public testing::Test {
ASSERT_EQ(1, message3_->field_count());
map_ = message3_->field(0);
ASSERT_EQ(1, json_file_->message_type_count());
message4_ = json_file_->message_type(0);
}
void CopyWithJsonName(const Descriptor* message, DescriptorProto* proto) {
message->CopyTo(proto);
message->CopyJsonNameTo(proto);
}
DescriptorPool pool_;
@ -569,10 +618,12 @@ class DescriptorTest : public testing::Test {
const FileDescriptor* foo_file_;
const FileDescriptor* bar_file_;
const FileDescriptor* map_file_;
const FileDescriptor* json_file_;
const Descriptor* message_;
const Descriptor* message2_;
const Descriptor* message3_;
const Descriptor* message4_;
const Descriptor* foreign_;
const EnumDescriptor* enum_;
@ -664,6 +715,35 @@ TEST_F(DescriptorTest, FieldFullName) {
EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
}
TEST_F(DescriptorTest, FieldJsonName) {
EXPECT_EQ("fieldName1", message4_->field(0)->json_name());
EXPECT_EQ("fieldName2", message4_->field(1)->json_name());
EXPECT_EQ("fieldName3", message4_->field(2)->json_name());
EXPECT_EQ("fieldName4", message4_->field(3)->json_name());
EXPECT_EQ("fIELDNAME5", message4_->field(4)->json_name());
EXPECT_EQ("@type", message4_->field(5)->json_name());
DescriptorProto proto;
message4_->CopyTo(&proto);
ASSERT_EQ(6, proto.field_size());
EXPECT_FALSE(proto.field(0).has_json_name());
EXPECT_FALSE(proto.field(1).has_json_name());
EXPECT_FALSE(proto.field(2).has_json_name());
EXPECT_FALSE(proto.field(3).has_json_name());
EXPECT_FALSE(proto.field(4).has_json_name());
EXPECT_EQ("@type", proto.field(5).json_name());
proto.Clear();
CopyWithJsonName(message4_, &proto);
ASSERT_EQ(6, proto.field_size());
EXPECT_EQ("fieldName1", proto.field(0).json_name());
EXPECT_EQ("fieldName2", proto.field(1).json_name());
EXPECT_EQ("fieldName3", proto.field(2).json_name());
EXPECT_EQ("fieldName4", proto.field(3).json_name());
EXPECT_EQ("fIELDNAME5", proto.field(4).json_name());
EXPECT_EQ("@type", proto.field(5).json_name());
}
TEST_F(DescriptorTest, FieldFile) {
EXPECT_EQ(foo_file_, foo_->file());
EXPECT_EQ(foo_file_, bar_->file());
@ -1900,7 +1980,7 @@ class MiscTest : public testing::Test {
return field != NULL ? field->enum_type() : NULL;
}
scoped_ptr<DescriptorPool> pool_;
google::protobuf::scoped_ptr<DescriptorPool> pool_;
};
TEST_F(MiscTest, TypeNames) {
@ -2330,7 +2410,7 @@ class AllowUnknownDependenciesTest
const FieldDescriptor* qux_field_;
SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode.
scoped_ptr<DescriptorPool> pool_;
google::protobuf::scoped_ptr<DescriptorPool> pool_;
};
TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
@ -5681,6 +5761,32 @@ TEST_F(ValidationErrorTest, ValidateProto3Extension) {
"defining options.\n");
}
// Test that field names that may conflict in JSON is not allowed by protoc.
TEST_F(ValidationErrorTest, ValidateProto3JsonName) {
// The comparison is case-insensitive.
BuildFileWithErrors(
"name: 'foo.proto' "
"syntax: 'proto3' "
"message_type {"
" name: 'Foo'"
" field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
" field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
"}",
"foo.proto: Foo: OTHER: The JSON camcel-case name of field \"Name\" "
"conflicts with field \"name\". This is not allowed in proto3.\n");
// Underscores are ignored.
BuildFileWithErrors(
"name: 'foo.proto' "
"syntax: 'proto3' "
"message_type {"
" name: 'Foo'"
" field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
" field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
"}",
"foo.proto: Foo: OTHER: The JSON camcel-case name of field \"_a__b_\" "
"conflicts with field \"ab\". This is not allowed in proto3.\n");
}
// ===================================================================
// DescriptorDatabase

View File

@ -64,6 +64,10 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
@ -229,8 +233,8 @@ class DynamicMessage : public Message {
// Warning: The order in which the following pointers are defined is
// important (the prototype must be deleted *before* the offsets).
scoped_array<int> offsets;
scoped_ptr<const GeneratedMessageReflection> reflection;
google::protobuf::scoped_array<int> offsets;
google::protobuf::scoped_ptr<const GeneratedMessageReflection> reflection;
// Don't use a scoped_ptr to hold the prototype: the destructor for
// DynamicMessage needs to know whether it is the prototype, and does so by
// looking back at this field. This would assume details about the

View File

@ -40,6 +40,11 @@
// reflection_ops_unittest, cover the rest of the functionality used by
// DynamicMessage.
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
@ -144,7 +149,7 @@ TEST_F(DynamicMessageTest, IndependentOffsets) {
// Check that all fields have independent offsets by setting each
// one to a unique value then checking that they all still have those
// unique values (i.e. they don't stomp each other).
scoped_ptr<Message> message(prototype_->New());
google::protobuf::scoped_ptr<Message> message(prototype_->New());
TestUtil::ReflectionTester reflection_tester(descriptor_);
reflection_tester.SetAllFieldsViaReflection(message.get());
@ -153,7 +158,7 @@ TEST_F(DynamicMessageTest, IndependentOffsets) {
TEST_F(DynamicMessageTest, Extensions) {
// Check that extensions work.
scoped_ptr<Message> message(extensions_prototype_->New());
google::protobuf::scoped_ptr<Message> message(extensions_prototype_->New());
TestUtil::ReflectionTester reflection_tester(extensions_descriptor_);
reflection_tester.SetAllFieldsViaReflection(message.get());
@ -162,7 +167,7 @@ TEST_F(DynamicMessageTest, Extensions) {
TEST_F(DynamicMessageTest, PackedFields) {
// Check that packed fields work properly.
scoped_ptr<Message> message(packed_prototype_->New());
google::protobuf::scoped_ptr<Message> message(packed_prototype_->New());
TestUtil::ReflectionTester reflection_tester(packed_descriptor_);
reflection_tester.SetPackedFieldsViaReflection(message.get());
@ -171,7 +176,7 @@ TEST_F(DynamicMessageTest, PackedFields) {
TEST_F(DynamicMessageTest, Oneof) {
// Check that oneof fields work properly.
scoped_ptr<Message> message(oneof_prototype_->New());
google::protobuf::scoped_ptr<Message> message(oneof_prototype_->New());
// Check default values.
const Descriptor* descriptor = message->GetDescriptor();
@ -232,7 +237,7 @@ TEST_F(DynamicMessageTest, SpaceUsed) {
// Since we share the implementation with generated messages, we don't need
// to test very much here. Just make sure it appears to be working.
scoped_ptr<Message> message(prototype_->New());
google::protobuf::scoped_ptr<Message> message(prototype_->New());
TestUtil::ReflectionTester reflection_tester(descriptor_);
int initial_space_used = message->SpaceUsed();

View File

@ -34,6 +34,7 @@
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>
@ -594,20 +595,21 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
ClearExtension(number);
return;
}
::google::protobuf::Arena* message_arena = message->GetArena();
Extension* extension;
if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
extension->is_lazy = false;
if (message->GetArena() == arena_) {
if (message_arena == arena_) {
extension->message_value = message;
} else if (message_arena == NULL) {
extension->message_value = message;
arena_->Own(message); // not NULL because not equal to message_arena
} else {
extension->message_value = message->New(arena_);
extension->message_value->CheckTypeAndMergeFrom(*message);
if (message->GetArena() == NULL) {
delete message;
}
}
} else {
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
@ -617,14 +619,14 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
if (arena_ == NULL) {
delete extension->message_value;
}
if (message->GetArena() == arena_) {
if (message_arena == arena_) {
extension->message_value = message;
} else if (message_arena == NULL) {
extension->message_value = message;
arena_->Own(message); // not NULL because not equal to message_arena
} else {
extension->message_value = message->New(arena_);
extension->message_value->CheckTypeAndMergeFrom(*message);
if (message->GetArena() == NULL) {
delete message;
}
}
}
}

View File

@ -724,8 +724,7 @@ class RepeatedPrimitiveTypeTraits {
static const RepeatedFieldType* GetDefaultRepeatedField();
};
LIBPROTOBUF_EXPORT extern ProtobufOnceType
repeated_primitive_generic_type_traits_once_init_;
extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits {
private:
@ -766,7 +765,7 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
} \
template<> inline const RepeatedField<TYPE>* \
RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \
GoogleOnceInit( \
::google::protobuf::GoogleOnceInit( \
&repeated_primitive_generic_type_traits_once_init_, \
&RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \
return RepeatedPrimitiveGenericTypeTraits:: \
@ -822,8 +821,7 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
}
};
LIBPROTOBUF_EXPORT extern ProtobufOnceType
repeated_string_type_traits_once_init_;
extern ProtobufOnceType repeated_string_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
public:
@ -868,7 +866,7 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
}
static const RepeatedFieldType* GetDefaultRepeatedField() {
GoogleOnceInit(&repeated_string_type_traits_once_init_,
::google::protobuf::GoogleOnceInit(&repeated_string_type_traits_once_init_,
&InitializeDefaultRepeatedFields);
return default_repeated_field_;
}
@ -1034,8 +1032,7 @@ class RepeatedMessageTypeTraits {
static const RepeatedFieldType* GetDefaultRepeatedField();
};
LIBPROTOBUF_EXPORT extern ProtobufOnceType
repeated_message_generic_type_traits_once_init_;
extern ProtobufOnceType repeated_message_generic_type_traits_once_init_;
// This class exists only to hold a generic default empty repeated field for all
// message-type repeated field extensions.
@ -1052,7 +1049,7 @@ class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits {
template<typename Type> inline
const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
GoogleOnceInit(
::google::protobuf::GoogleOnceInit(
&repeated_message_generic_type_traits_once_init_,
&RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields);
return reinterpret_cast<const RepeatedFieldType*>(

View File

@ -360,9 +360,8 @@ TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) {
unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
message->SetAllocatedExtension(unittest::optional_foreign_message_extension,
foreign_message);
// foreign_message is copied underneath, as foreign_message is on heap
// and extension_set is on an arena.
EXPECT_NE(foreign_message,
// foreign_message is now owned by the arena.
EXPECT_EQ(foreign_message,
message->MutableExtension(
unittest::optional_foreign_message_extension));

View File

@ -43,6 +43,11 @@
// rather than generated accessors.
#include <google/protobuf/generated_message_reflection.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/descriptor.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
@ -354,7 +359,7 @@ TEST(GeneratedMessageReflectionTest, ReleaseLast) {
ASSERT_EQ(2, message.repeated_foreign_message_size());
const protobuf_unittest::ForeignMessage* expected =
message.mutable_repeated_foreign_message(1);
scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
google::protobuf::scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
&message, descriptor->FindFieldByName("repeated_foreign_message")));
EXPECT_EQ(expected, released.get());
}
@ -377,9 +382,9 @@ TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) {
unittest::repeated_foreign_message_extension));
const protobuf_unittest::ForeignMessage* expected = message.MutableExtension(
unittest::repeated_foreign_message_extension, 1);
scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
google::protobuf::scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
&message, descriptor->file()->FindExtensionByName(
"repeated_foreign_message_extension")));
"repeated_foreign_message_extension")));
EXPECT_EQ(expected, released.get());
}

View File

@ -63,7 +63,6 @@ void InitEmptyString() {
int StringSpaceUsedExcludingSelf(const string& str) {
const void* start = &str;
const void* end = &str + 1;
if (start <= str.data() && str.data() < end) {
// The string's data is stored inside the string object itself.
return 0;
@ -73,6 +72,7 @@ int StringSpaceUsedExcludingSelf(const string& str) {
}
} // namespace internal
} // namespace protobuf
} // namespace google

View File

@ -34,6 +34,10 @@
//
// This file contains tests and benchmarks.
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <vector>
#include <google/protobuf/io/coded_stream.h>
@ -679,7 +683,7 @@ TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
}
TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) {
scoped_array<uint8> buffer(new uint8[8]);
google::protobuf::scoped_array<uint8> buffer(new uint8[8]);
CodedInputStream coded_input(buffer.get(), 8);
string str;
EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));

View File

@ -44,6 +44,10 @@
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
@ -235,7 +239,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream
// Data is read into this buffer. It may be NULL if no buffer is currently
// in use. Otherwise, it points to an array of size buffer_size_.
scoped_array<uint8> buffer_;
google::protobuf::scoped_array<uint8> buffer_;
const int buffer_size_;
// Number of valid bytes currently in the buffer (i.e. the size last
@ -324,7 +328,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
// Data is written from this buffer. It may be NULL if no buffer is
// currently in use. Otherwise, it points to an array of size buffer_size_.
scoped_array<uint8> buffer_;
google::protobuf::scoped_array<uint8> buffer_;
const int buffer_size_;
// Number of valid bytes currently in the buffer (i.e. the size last

View File

@ -57,6 +57,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <sstream>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@ -197,7 +201,7 @@ void IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) {
}
void IoTest::ReadString(ZeroCopyInputStream* input, const string& str) {
scoped_array<char> buffer(new char[str.size() + 1]);
google::protobuf::scoped_array<char> buffer(new char[str.size() + 1]);
buffer[str.size()] = '\0';
EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size());
EXPECT_STREQ(str.c_str(), buffer.get());

View File

@ -155,7 +155,8 @@ void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
this_iter->key_.SetType(that_iter.key_.type());
// MapValueRef::type() fails when containing data is null. However, if
// this_iter points to MapEnd, data can be null.
this_iter->value_.SetType((FieldDescriptor::CppType)that_iter.value_.type_);
this_iter->value_.SetType(
static_cast<FieldDescriptor::CppType>(that_iter.value_.type_));
SetMapIteratorValue(this_iter);
}

View File

@ -31,6 +31,8 @@
syntax = "proto2";
import "google/protobuf/unittest_import.proto";
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
@ -58,3 +60,7 @@ message TestEnumMapPlusExtra {
map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
}
message TestImportEnumMap {
map<int32, protobuf_unittest_import.ImportEnumForMap> import_enum_amp = 1;
}

View File

@ -2154,7 +2154,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
// Check that all fields have independent offsets by setting each
// one to a unique value then checking that they all still have those
// unique values (i.e. they don't stomp each other).
scoped_ptr<Message> message(map_prototype_->New());
google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
MapReflectionTester reflection_tester(map_descriptor_);
reflection_tester.SetMapFieldsViaReflection(message.get());
@ -2163,7 +2163,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) {
// Check that map fields work properly.
scoped_ptr<Message> message(map_prototype_->New());
google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
// Check set functions.
MapReflectionTester reflection_tester(map_descriptor_);
@ -2177,7 +2177,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
// Since we share the implementation with generated messages, we don't need
// to test very much here. Just make sure it appears to be working.
scoped_ptr<Message> message(map_prototype_->New());
google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
MapReflectionTester reflection_tester(map_descriptor_);
int initial_space_used = message->SpaceUsed();

View File

@ -55,7 +55,6 @@
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/singleton.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/port.h>
namespace google {
namespace protobuf {

View File

@ -971,7 +971,7 @@ class LIBPROTOBUF_EXPORT Reflection {
return false;
}
// Returns a MaIterator referring to the first element in the map field.
// Returns a MapIterator referring to the first element in the map field.
// If the map field is empty, this function returns the same as
// reflection::MapEnd. Mutation to the field may invalidate the iterator.
virtual MapIterator MapBegin(

View File

@ -649,7 +649,7 @@ inline const Message& GenericTypeHandler<Message>::default_instance() {
// StringTypeHandler is exported. So, we factor out StringTypeHandlerBase,
// export that, then make StringTypeHandler be a subclass which is NOT
// exported.
// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite
// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite
// library, this can be cleaned up.
class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
public:

View File

@ -149,6 +149,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/hash.h>
namespace google {
namespace protobuf {
@ -437,4 +438,16 @@ extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
} // namespace protobuf
} // namespace google
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
template<> struct hash<StringPiece> {
size_t operator()(const StringPiece& s) const {
size_t result = 0;
for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {
result = 5 * result + *str;
}
return result;
}
};
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
#endif // STRINGS_STRINGPIECE_H_

View File

@ -30,6 +30,7 @@
#include <google/protobuf/stubs/stringpiece.h>
#include <iterator>
#include <hash_set>
#include <map>
#include <string>
#include <utility>
@ -745,6 +746,23 @@ TEST(StringPiece, Comparisons2) {
EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz"));
}
TEST(StringPiece, HashFunction) {
hash_set<StringPiece> set;
set.insert(StringPiece("hello"));
EXPECT_EQ(1, set.size());
// Insert a StringPiece of the same value again and should NOT increment
// size of the set.
set.insert(StringPiece("hello"));
EXPECT_EQ(1, set.size());
// Insert a StringPiece with different value and check that size of the set
// has been increment by one.
set.insert(StringPiece("world"));
EXPECT_EQ(2, set.size());
}
TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
EXPECT_EQ("hello", string("hello"));
EXPECT_LT("hello", string("world"));

View File

@ -377,8 +377,8 @@ class TextFormat::Parser::ParserImpl {
if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
&any_value_field) &&
TryConsume("[")) {
string full_type_name;
DO(ConsumeAnyTypeUrl(&full_type_name));
string full_type_name, prefix;
DO(ConsumeAnyTypeUrl(&full_type_name, &prefix));
DO(Consume("]"));
string serialized_value;
DO(ConsumeAnyValue(full_type_name,
@ -386,7 +386,7 @@ class TextFormat::Parser::ParserImpl {
&serialized_value));
reflection->SetString(
message, any_type_url_field,
string(internal::kTypeGoogleApisComPrefix) + full_type_name);
string(prefix + full_type_name));
reflection->SetString(message, any_value_field, serialized_value);
return true;
// Fall through.
@ -981,7 +981,8 @@ class TextFormat::Parser::ParserImpl {
}
// Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name"
bool ConsumeAnyTypeUrl(string* full_type_name) {
// or "type.googleprod.com/full.type.Name"
bool ConsumeAnyTypeUrl(string* full_type_name, string* prefix) {
// TODO(saito) Extend Consume() to consume multiple tokens at once, so that
// this code can be written as just DO(Consume(kGoogleApisTypePrefix)).
string url1, url2, url3;
@ -993,10 +994,12 @@ class TextFormat::Parser::ParserImpl {
DO(Consume("/"));
DO(ConsumeFullTypeName(full_type_name));
const string prefix = url1 + "." + url2 + "." + url3 + "/";
if (prefix != internal::kTypeGoogleApisComPrefix) {
*prefix = url1 + "." + url2 + "." + url3 + "/";
if (*prefix != internal::kTypeGoogleApisComPrefix &&
*prefix != internal::kTypeGoogleProdComPrefix) {
ReportError("TextFormat::Parser for Any supports only "
"type.googleapi.com, but found \"" + prefix + "\"");
"type.googleapis.com and type.googleprod.com, "
"but found \"" + *prefix + "\"");
return false;
}
return true;

View File

@ -37,6 +37,10 @@
#include <math.h>
#include <stdlib.h>
#include <limits>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@ -931,7 +935,7 @@ class TextFormatParserTest : public testing::Test {
protected:
void ExpectFailure(const string& input, const string& message, int line,
int col) {
scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
google::protobuf::scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
ExpectFailure(input, message, line, col, proto.get());
}
@ -992,7 +996,7 @@ class TextFormatParserTest : public testing::Test {
};
TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
google::protobuf::scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
const Descriptor* d = message->GetDescriptor();
string stringData =
@ -1057,7 +1061,7 @@ TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
}
TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
google::protobuf::scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
const Descriptor* d = message->GetDescriptor();
#define EXPECT_FIELD(name, value, valuestring) \

View File

@ -64,3 +64,10 @@ enum ImportEnum {
IMPORT_BAZ = 9;
}
// To use an enum in a map, it must has the first value as 0.
enum ImportEnumForMap {
UNKNOWN = 0;
FOO = 1;
BAR = 2;
}

View File

@ -0,0 +1,218 @@
#ifndef NET_PROTO2_UTIL_CONVERTER_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H_
#define NET_PROTO2_UTIL_CONVERTER_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H_
#include <memory>
#include <stack>
#include <vector>
#include "base/macros.h"
#include "net/proto2/util/converter/internal/type_info.h"
#include "net/proto2/util/converter/public/datapiece.h"
#include "net/proto2/util/converter/public/object_writer.h"
#include "net/proto2/util/converter/public/utility.h"
#include "net/proto2/util/public/type_resolver.h"
#include "strings/stringpiece.h"
namespace proto2 {
namespace util {
namespace converter {
// An ObjectWriter that renders non-repeated primitive fields of proto messages
// with their default values. DefaultValueObjectWriter holds objects, lists and
// fields it receives in a tree structure and writes them out to another
// ObjectWriter when EndObject() is called on the root object. It also writes
// out all non-repeated primitive fields that haven't been explicitly rendered
// with their default values (0 for numbers, "" for strings, etc).
class DefaultValueObjectWriter : public ObjectWriter {
public:
#ifndef PROTO2_OPENSOURCE
DefaultValueObjectWriter(const TypeInfo& typeinfo,
const google::protobuf::Type& type,
ObjectWriter* ow);
#endif // !PROTO2_OPENSOURCE
DefaultValueObjectWriter(TypeResolver* type_resolver,
const google::protobuf::Type& type,
ObjectWriter* ow);
virtual ~DefaultValueObjectWriter();
// ObjectWriter methods.
virtual DefaultValueObjectWriter* StartObject(StringPiece name);
virtual DefaultValueObjectWriter* EndObject();
virtual DefaultValueObjectWriter* StartList(StringPiece name);
virtual DefaultValueObjectWriter* EndList();
virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value);
virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value);
virtual DefaultValueObjectWriter* RenderUint32(StringPiece name,
uint32 value);
virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value);
virtual DefaultValueObjectWriter* RenderUint64(StringPiece name,
uint64 value);
virtual DefaultValueObjectWriter* RenderDouble(StringPiece name,
double value);
virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value);
virtual DefaultValueObjectWriter* RenderString(StringPiece name,
StringPiece value);
#ifdef PROTO2_OPENSOURCE
virtual DefaultValueObjectWriter* RenderBytes(StringPiece name,
StringPiece value);
#else // PROTO2_OPENSOURCE
virtual DefaultValueObjectWriter* RenderCord(StringPiece name,
const Cord& value);
#endif // !PROTO2_OPENSOURCE
virtual DefaultValueObjectWriter* RenderNull(StringPiece name);
virtual DefaultValueObjectWriter* DisableCaseNormalizationForNextKey();
private:
enum NodeKind {
PRIMITIVE = 0,
OBJECT = 1,
LIST = 2,
MAP = 3,
};
// "Node" represents a node in the tree that holds the input of
// DefaultValueObjectWriter.
class Node {
public:
Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
const DataPiece& data, bool is_placeholder);
virtual ~Node() {
for (int i = 0; i < children_.size(); ++i) {
delete children_[i];
}
}
// Adds a child to this node. Takes ownership of this child.
void AddChild(Node* child) { children_.push_back(child); }
// Finds the child given its name.
Node* FindChild(StringPiece name);
// Populates children of this Node based on its type. If there are already
// children created, they will be merged to the result. Caller should pass
// in TypeInfo for looking up types of the children.
void PopulateChildren(const TypeInfo* typeinfo);
// If this node is a leaf (has data), writes the current node to the
// ObjectWriter; if not, then recursively writes the children to the
// ObjectWriter.
void WriteTo(ObjectWriter* ow);
// Accessors
const string& name() const { return name_; }
const google::protobuf::Type* type() { return type_; }
void set_type(const google::protobuf::Type* type) { type_ = type; }
NodeKind kind() { return kind_; }
int number_of_children() { return children_.size(); }
void set_data(const DataPiece& data) { data_ = data; }
void set_disable_normalize(bool disable_normalize) {
disable_normalize_ = disable_normalize;
}
bool is_any() { return is_any_; }
void set_is_any(bool is_any) { is_any_ = is_any; }
void set_is_placeholder(bool is_placeholder) {
is_placeholder_ = is_placeholder;
}
private:
// Returns the Value Type of a map given the Type of the map entry and a
// TypeInfo instance.
const google::protobuf::Type* GetMapValueType(
const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
// Calls WriteTo() on every child in children_.
void WriteChildren(ObjectWriter* ow);
// The name of this node.
string name_;
// google::protobuf::Type of this node. Owned by TypeInfo.
const google::protobuf::Type* type_;
// The kind of this node.
NodeKind kind_;
// Whether to disable case normalization of the name.
bool disable_normalize_;
// Whether this is a node for "Any".
bool is_any_;
// The data of this node when it is a leaf node.
DataPiece data_;
// Children of this node.
std::vector<Node*> children_;
// Whether this node is a placeholder for an object or list automatically
// generated when creating the parent node. Should be set to false after
// the parent node's StartObject()/StartList() method is called with this
// node's name.
bool is_placeholder_;
};
// Populates children of "node" if it is an "any" Node and its real type has
// been given.
void MaybePopulateChildrenOfAny(Node* node);
// Writes the root_ node to ow_ and resets the root_ and current_ pointer to
// nullptr.
void WriteRoot();
// Creates a DataPiece containing the default value of the type of the field.
static DataPiece CreateDefaultDataPieceForField(
const google::protobuf::Field& field);
// Returns disable_normalize_ and reset it to false.
bool GetAndResetDisableNormalize() {
return disable_normalize_ ? (disable_normalize_ = false, true) : false;
}
// Adds or replaces the data_ of a primitive child node.
void RenderDataPiece(StringPiece name, const DataPiece& data);
// Type information for all the types used in the descriptor. Used to find
// google::protobuf::Type of nested messages/enums.
const TypeInfo* typeinfo_;
// Whether the TypeInfo object is owned by this class.
bool own_typeinfo_;
// google::protobuf::Type of the root message type.
const google::protobuf::Type& type_;
// Holds copies of strings passed to RenderString.
vector<string*> string_values_;
// Whether to disable case normalization of the next node.
bool disable_normalize_;
// The current Node. Owned by its parents.
Node* current_;
// The root Node.
std::unique_ptr<Node> root_;
// The stack to hold the path of Nodes from current_ to root_;
std::stack<Node*> stack_;
ObjectWriter* ow_;
DISALLOW_COPY_AND_ASSIGN(DefaultValueObjectWriter);
};
} // namespace converter
} // namespace util
} // namespace proto2
#endif // NET_PROTO2_UTIL_CONVERTER_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H_

View File

@ -34,8 +34,8 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/mathutil.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/mathutil.h>
namespace google {
namespace protobuf {

View File

@ -43,7 +43,7 @@ string FieldMaskUtil::ToString(const FieldMask& mask) {
return Join(mask.paths(), ",");
}
void FieldMaskUtil::FromString(const string& str, FieldMask* out) {
void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
out->Clear();
vector<string> paths = Split(str, ",");
for (int i = 0; i < paths.size(); ++i) {
@ -53,7 +53,7 @@ void FieldMaskUtil::FromString(const string& str, FieldMask* out) {
}
bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
const string& path) {
StringPiece path) {
vector<string> parts = Split(path, ".");
for (int i = 0; i < parts.size(); ++i) {
const string& field_name = parts[i];
@ -386,15 +386,15 @@ void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2,
intersection.MergeToFieldMask(out);
}
bool FieldMaskUtil::IsPathInFieldMask(const string& path,
const FieldMask& mask) {
bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, const FieldMask& mask) {
for (int i = 0; i < mask.paths_size(); ++i) {
const string& mask_path = mask.paths(i);
if (path == mask_path) {
return true;
} else if (mask_path.length() < path.length()) {
// Also check whether mask.paths(i) is a prefix of path.
if (path.compare(0, mask_path.length() + 1, mask_path + ".") == 0) {
if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") ==
0) {
return true;
}
}

View File

@ -35,6 +35,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/field_mask.pb.h>
#include <google/protobuf/stubs/stringpiece.h>
namespace google {
namespace protobuf {
@ -47,11 +48,11 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
// Converts FieldMask to/from string, formatted according to proto3 JSON
// spec for FieldMask (e.g., "foo,bar,baz.quz").
static string ToString(const FieldMask& mask);
static void FromString(const string& str, FieldMask* out);
static void FromString(StringPiece str, FieldMask* out);
// Checks whether the given path is valid for type T.
template <typename T>
static bool IsValidPath(const string& path) {
static bool IsValidPath(StringPiece path) {
return InternalIsValidPath(T::descriptor(), path);
}
@ -67,7 +68,7 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
// Adds a path to FieldMask after checking whether the given path is valid.
// This method check-fails if the path is not a valid path for type T.
template <typename T>
static void AddPathToFieldMask(const string& path, FieldMask* mask) {
static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
GOOGLE_CHECK(IsValidPath<T>(path));
mask->add_paths(path);
}
@ -96,7 +97,7 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
// Returns true if path is covered by the given FieldMask. Note that path
// "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
static bool IsPathInFieldMask(const string& path, const FieldMask& mask);
static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask);
class MergeOptions;
// Merges fields specified in a FieldMask into another message.
@ -105,7 +106,7 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
private:
static bool InternalIsValidPath(const Descriptor* descriptor,
const string& path);
StringPiece path);
static void InternalGetFieldMaskForAllFields(const Descriptor* descriptor,
FieldMask* out);

View File

@ -110,7 +110,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// "Node" represents a node in the tree that holds the input of
// DefaultValueObjectWriter.
class Node {
class LIBPROTOBUF_EXPORT Node {
public:
Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
const DataPiece& data, bool is_placeholder);

View File

@ -37,8 +37,8 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/internal/json_escaping.h>
#include <google/protobuf/stubs/mathlimits.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/mathlimits.h>
namespace google {
namespace protobuf {
@ -116,7 +116,7 @@ JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
double value) {
if (google::protobuf::MathLimits<double>::IsFinite(value)) {
if (MathLimits<double>::IsFinite(value)) {
return RenderSimple(name, SimpleDtoa(value));
}
@ -126,7 +126,7 @@ JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
float value) {
if (google::protobuf::MathLimits<float>::IsFinite(value)) {
if (MathLimits<float>::IsFinite(value)) {
return RenderSimple(name, SimpleFtoa(value));
}

View File

@ -47,7 +47,6 @@
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/status_macros.h>
@ -140,6 +139,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
const uint32 end_tag,
bool include_start_and_end,
ObjectWriter* ow) const {
const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
if (type_renderer != NULL) {
return (*type_renderer)(this, type, name, ow);
@ -332,10 +332,9 @@ Status ProtoStreamObjectSource::RenderDuration(
if (seconds < 0) {
if (nanos > 0) {
return Status(util::error::INTERNAL,
StrCat(
"Duration nanos is non-negative, but seconds is "
"negative for field: ",
field_name));
StrCat("Duration nanos is non-negative, but seconds is "
"negative for field: ",
field_name));
}
sign = "-";
seconds = -seconds;
@ -648,6 +647,7 @@ Status ProtoStreamObjectSource::RenderFieldMask(
return Status::OK;
}
hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
ProtoStreamObjectSource::renderers_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_);
@ -670,13 +670,16 @@ void ProtoStreamObjectSource::InitRendererMap() {
&ProtoStreamObjectSource::RenderInt32;
(*renderers_)["google.protobuf.UInt32Value"] =
&ProtoStreamObjectSource::RenderUInt32;
(*renderers_)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool;
(*renderers_)["google.protobuf.BoolValue"] =
&ProtoStreamObjectSource::RenderBool;
(*renderers_)["google.protobuf.StringValue"] =
&ProtoStreamObjectSource::RenderString;
(*renderers_)["google.protobuf.BytesValue"] =
&ProtoStreamObjectSource::RenderBytes;
(*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
(*renderers_)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct;
(*renderers_)["google.protobuf.Any"] =
&ProtoStreamObjectSource::RenderAny;
(*renderers_)["google.protobuf.Struct"] =
&ProtoStreamObjectSource::RenderStruct;
(*renderers_)["google.protobuf.Value"] =
&ProtoStreamObjectSource::RenderStructValue;
(*renderers_)["google.protobuf.ListValue"] =
@ -835,6 +838,7 @@ Status ProtoStreamObjectSource::RenderField(
StrCat("Invalid configuration. Could not find the type: ",
field->type_url()));
}
RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
if (!stream_->ConsumedEntireMessage()) {
return Status(util::error::INVALID_ARGUMENT,
@ -988,7 +992,7 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
uint32 nanos = 0;
uint32 tag = 0;
int64 signed_seconds = 0;
int64 signed_nanos = 0;
int32 signed_nanos = 0;
for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
const google::protobuf::Field* field = FindAndVerifyField(type, tag);

Some files were not shown because too many files have changed in this diff Show More