diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java index 3cf98162fe..0e03ebd14e 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteString.java +++ b/java/core/src/main/java/com/google/protobuf/ByteString.java @@ -1143,7 +1143,7 @@ public abstract class ByteString implements Iterable, Serializable { synchronized (this) { // Copy the information we need into local variables so as to hold // the lock for as short a time as possible. - cachedFlushBuffers = flushedBuffers.toArray(new ByteString[flushedBuffers.size()]); + cachedFlushBuffers = flushedBuffers.toArray(new ByteString[0]); cachedBuffer = buffer; cachedBufferPos = bufferPos; } diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java index de0ee11b7e..26cc5bb759 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -36,7 +36,6 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; - import java.io.IOException; import java.io.InputStream; import java.io.ObjectStreamException; @@ -51,25 +50,23 @@ import java.util.Map; import java.util.TreeMap; /** - * All generated protocol message classes extend this class. This class - * implements most of the Message and Builder interfaces using Java reflection. - * Users can ignore this class and pretend that generated messages implement - * the Message interface directly. + * All generated protocol message classes extend this class. This class implements most of the + * Message and Builder interfaces using Java reflection. Users can ignore this class and pretend + * that generated messages implement the Message interface directly. * * @author kenton@google.com Kenton Varda */ -public abstract class GeneratedMessage extends AbstractMessage - implements Serializable { +public abstract class GeneratedMessage extends AbstractMessage implements Serializable { private static final long serialVersionUID = 1L; /** - * For testing. Allows a test to disable the optimization that avoids using - * field builders for nested messages until they are requested. By disabling - * this optimization, existing tests can be reused to test the field builders. + * For testing. Allows a test to disable the optimization that avoids using field builders for + * nested messages until they are requested. By disabling this optimization, existing tests can be + * reused to test the field builders. */ protected static boolean alwaysUseFieldBuilders = false; - /** For use by generated code only. */ + /** For use by generated code only. */ protected UnknownFieldSet unknownFields; protected GeneratedMessage() { @@ -82,24 +79,22 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public Parser getParserForType() { - throw new UnsupportedOperationException( - "This is supposed to be overridden by subclasses."); + throw new UnsupportedOperationException("This is supposed to be overridden by subclasses."); } - /** - * For testing. Allows a test to disable the optimization that avoids using - * field builders for nested messages until they are requested. By disabling - * this optimization, existing tests can be reused to test the field builders. - * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. - */ + /** + * For testing. Allows a test to disable the optimization that avoids using field builders for + * nested messages until they are requested. By disabling this optimization, existing tests can be + * reused to test the field builders. See {@link RepeatedFieldBuilder} and {@link + * SingleFieldBuilder}. + */ static void enableAlwaysUseFieldBuildersForTesting() { alwaysUseFieldBuilders = true; } /** - * Get the FieldAccessorTable for this type. We can't have the message - * class pass this in to the constructor because of bootstrapping trouble - * with DescriptorProtos. + * Get the FieldAccessorTable for this type. We can't have the message class pass this in to the + * constructor because of bootstrapping trouble with DescriptorProtos. */ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); @@ -109,16 +104,14 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Internal helper to return a modifiable map containing all the fields. - * The returned Map is modifialbe so that the caller can add additional - * extension fields to implement {@link #getAllFields()}. + * Internal helper to return a modifiable map containing all the fields. The returned Map is + * modifialbe so that the caller can add additional extension fields to implement {@link + * #getAllFields()}. * * @param getBytesForString whether to generate ByteString for string fields */ - private Map getAllFieldsMutable( - boolean getBytesForString) { - final TreeMap result = - new TreeMap(); + private Map getAllFieldsMutable(boolean getBytesForString) { + final TreeMap result = new TreeMap(); final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; final List fields = descriptor.getFields(); @@ -174,8 +167,8 @@ public abstract class GeneratedMessage extends AbstractMessage // Check that embedded messages are initialized. if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (field.isRepeated()) { - @SuppressWarnings("unchecked") final - List messageList = (List) getField(field); + @SuppressWarnings("unchecked") + final List messageList = (List) getField(field); for (final Message element : messageList) { if (!element.isInitialized()) { return false; @@ -194,23 +187,19 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public Map getAllFields() { - return Collections.unmodifiableMap( - getAllFieldsMutable(/* getBytesForString = */ false)); + return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ false)); } /** - * Returns a collection of all the fields in this message which are set - * and their corresponding values. A singular ("required" or "optional") - * field is set iff hasField() returns true for that field. A "repeated" - * field is set iff getRepeatedFieldCount() is greater than zero. The - * values are exactly what would be returned by calling - * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map - * is guaranteed to be a sorted map, so iterating over it will return fields - * in order by field number. + * Returns a collection of all the fields in this message which are set and their corresponding + * values. A singular ("required" or "optional") field is set iff hasField() returns true for that + * field. A "repeated" field is set iff getRepeatedFieldCount() is greater than zero. The values + * are exactly what would be returned by calling {@link #getFieldRaw(Descriptors.FieldDescriptor)} + * for each field. The map is guaranteed to be a sorted map, so iterating over it will return + * fields in order by field number. */ Map getAllFieldsRaw() { - return Collections.unmodifiableMap( - getAllFieldsMutable(/* getBytesForString = */ true)); + return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ true)); } @Override @@ -234,12 +223,11 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Obtains the value of the given field, or the default value if it is - * not set. For primitive fields, the boxed primitive value is returned. - * For enum fields, the EnumValueDescriptor for the value is returned. For - * embedded message fields, the sub-message is returned. For repeated - * fields, a java.util.List is returned. For present string fields, a - * ByteString is returned representing the bytes that the field contains. + * Obtains the value of the given field, or the default value if it is not set. For primitive + * fields, the boxed primitive value is returned. For enum fields, the EnumValueDescriptor for the + * value is returned. For embedded message fields, the sub-message is returned. For repeated + * fields, a java.util.List is returned. For present string fields, a ByteString is returned + * representing the bytes that the field contains. */ Object getFieldRaw(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).getRaw(this); @@ -247,31 +235,30 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public int getRepeatedFieldCount(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field) - .getRepeatedCount(this); + return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this); } @Override public Object getRepeatedField(final FieldDescriptor field, final int index) { - return internalGetFieldAccessorTable().getField(field) - .getRepeated(this, index); + return internalGetFieldAccessorTable().getField(field).getRepeated(this, index); } @Override public UnknownFieldSet getUnknownFields() { - throw new UnsupportedOperationException( - "This is supposed to be overridden by subclasses."); + throw new UnsupportedOperationException("This is supposed to be overridden by subclasses."); } /** * Called by subclasses to parse an unknown field. + * * @return {@code true} unless the tag is an end-group tag. */ protected boolean parseUnknownField( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, - int tag) throws IOException { + int tag) + throws IOException { return unknownFields.mergeFieldFrom(tag, input); } @@ -284,8 +271,8 @@ public abstract class GeneratedMessage extends AbstractMessage } } - protected static M parseWithIOException(Parser parser, InputStream input, - ExtensionRegistryLite extensions) throws IOException { + protected static M parseWithIOException( + Parser parser, InputStream input, ExtensionRegistryLite extensions) throws IOException { try { return parser.parseFrom(input, extensions); } catch (InvalidProtocolBufferException e) { @@ -293,8 +280,8 @@ public abstract class GeneratedMessage extends AbstractMessage } } - protected static M parseWithIOException(Parser parser, - CodedInputStream input) throws IOException { + protected static M parseWithIOException( + Parser parser, CodedInputStream input) throws IOException { try { return parser.parseFrom(input); } catch (InvalidProtocolBufferException e) { @@ -302,8 +289,9 @@ public abstract class GeneratedMessage extends AbstractMessage } } - protected static M parseWithIOException(Parser parser, - CodedInputStream input, ExtensionRegistryLite extensions) throws IOException { + protected static M parseWithIOException( + Parser parser, CodedInputStream input, ExtensionRegistryLite extensions) + throws IOException { try { return parser.parseFrom(input, extensions); } catch (InvalidProtocolBufferException e) { @@ -311,8 +299,8 @@ public abstract class GeneratedMessage extends AbstractMessage } } - protected static M parseDelimitedWithIOException(Parser parser, - InputStream input) throws IOException { + protected static M parseDelimitedWithIOException( + Parser parser, InputStream input) throws IOException { try { return parser.parseDelimitedFrom(input); } catch (InvalidProtocolBufferException e) { @@ -320,8 +308,8 @@ public abstract class GeneratedMessage extends AbstractMessage } } - protected static M parseDelimitedWithIOException(Parser parser, - InputStream input, ExtensionRegistryLite extensions) throws IOException { + protected static M parseDelimitedWithIOException( + Parser parser, InputStream input, ExtensionRegistryLite extensions) throws IOException { try { return parser.parseDelimitedFrom(input, extensions); } catch (InvalidProtocolBufferException e) { @@ -341,46 +329,38 @@ public abstract class GeneratedMessage extends AbstractMessage return size; } - memoizedSize = MessageReflection.getSerializedSize( - this, getAllFieldsRaw()); + memoizedSize = MessageReflection.getSerializedSize(this, getAllFieldsRaw()); return memoizedSize; } - - - /** - * Used by parsing constructors in generated classes. - */ + /** Used by parsing constructors in generated classes. */ protected void makeExtensionsImmutable() { // Noop for messages without extensions. } /** - * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this - * interface to AbstractMessage in order to versioning GeneratedMessage but - * this move breaks binary compatibility for AppEngine. After AppEngine is - * fixed we can exclude this from google3. + * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this interface to + * AbstractMessage in order to versioning GeneratedMessage but this move breaks binary + * compatibility for AppEngine. After AppEngine is fixed we can exclude this from google3. */ protected interface BuilderParent extends AbstractMessage.BuilderParent {} - /** - * TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent. - */ + /** TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent. */ protected abstract Message.Builder newBuilderForType(BuilderParent parent); @Override protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) { - return newBuilderForType(new BuilderParent() { - @Override - public void markDirty() { - parent.markDirty(); - } - }); + return newBuilderForType( + new BuilderParent() { + @Override + public void markDirty() { + parent.markDirty(); + } + }); } - @SuppressWarnings("unchecked") - public abstract static class Builder > + public abstract static class Builder> extends AbstractMessage.Builder { private BuilderParent builderParent; @@ -391,8 +371,7 @@ public abstract class GeneratedMessage extends AbstractMessage // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. private boolean isClean; - private UnknownFieldSet unknownFields = - UnknownFieldSet.getDefaultInstance(); + private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance(); protected Builder() { this(null); @@ -407,9 +386,7 @@ public abstract class GeneratedMessage extends AbstractMessage builderParent = null; } - /** - * Called by the subclass when a message is built. - */ + /** Called by the subclass when a message is built. */ protected void onBuilt() { if (builderParent != null) { markClean(); @@ -417,8 +394,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Called by the subclass or a builder to notify us that a message was - * built and may be cached and therefore invalidations are needed. + * Called by the subclass or a builder to notify us that a message was built and may be cached + * and therefore invalidations are needed. */ @Override protected void markClean() { @@ -436,15 +413,14 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public BuilderType clone() { - BuilderType builder = - (BuilderType) getDefaultInstanceForType().newBuilderForType(); + BuilderType builder = (BuilderType) getDefaultInstanceForType().newBuilderForType(); builder.mergeFrom(buildPartial()); return builder; } /** - * Called by the initialization and clear code paths to allow subclasses to - * reset any of their builtin fields back to the initial values. + * Called by the initialization and clear code paths to allow subclasses to reset any of their + * builtin fields back to the initial values. */ @Override public BuilderType clear() { @@ -454,9 +430,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Get the FieldAccessorTable for this type. We can't have the message - * class pass this in to the constructor because of bootstrapping trouble - * with DescriptorProtos. + * Get the FieldAccessorTable for this type. We can't have the message class pass this in to the + * constructor because of bootstrapping trouble with DescriptorProtos. */ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); @@ -472,8 +447,7 @@ public abstract class GeneratedMessage extends AbstractMessage /** Internal helper which returns a mutable map. */ private Map getAllFieldsMutable() { - final TreeMap result = - new TreeMap(); + final TreeMap result = new TreeMap(); final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; final List fields = descriptor.getFields(); @@ -525,8 +499,7 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) { - return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder( - this, index); + return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(this, index); } @Override @@ -576,21 +549,18 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public int getRepeatedFieldCount(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field) - .getRepeatedCount(this); + return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this); } @Override public Object getRepeatedField(final FieldDescriptor field, final int index) { - return internalGetFieldAccessorTable().getField(field) - .getRepeated(this, index); + return internalGetFieldAccessorTable().getField(field).getRepeated(this, index); } @Override public BuilderType setRepeatedField( final FieldDescriptor field, final int index, final Object value) { - internalGetFieldAccessorTable().getField(field) - .setRepeated(this, index, value); + internalGetFieldAccessorTable().getField(field).setRepeated(this, index, value); return (BuilderType) this; } @@ -608,12 +578,9 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public BuilderType mergeUnknownFields( - final UnknownFieldSet unknownFields) { + public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { this.unknownFields = - UnknownFieldSet.newBuilder(this.unknownFields) - .mergeFrom(unknownFields) - .build(); + UnknownFieldSet.newBuilder(this.unknownFields).mergeFrom(unknownFields).build(); onChanged(); return (BuilderType) this; } @@ -630,16 +597,15 @@ public abstract class GeneratedMessage extends AbstractMessage // Check that embedded messages are initialized. if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (field.isRepeated()) { - @SuppressWarnings("unchecked") final - List messageList = (List) getField(field); + @SuppressWarnings("unchecked") + final List messageList = (List) getField(field); for (final Message element : messageList) { if (!element.isInitialized()) { return false; } } } else { - if (hasField(field) && - !((Message) getField(field)).isInitialized()) { + if (hasField(field) && !((Message) getField(field)).isInitialized()) { return false; } } @@ -655,20 +621,21 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Called by subclasses to parse an unknown field. + * * @return {@code true} unless the tag is an end-group tag. */ protected boolean parseUnknownField( final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, - final int tag) throws IOException { + final int tag) + throws IOException { return unknownFields.mergeFieldFrom(tag, input); } /** - * Implementation of {@link BuilderParent} for giving to our children. This - * small inner class makes it so we don't publicly expose the BuilderParent - * methods. + * Implementation of {@link BuilderParent} for giving to our children. This small inner class + * makes it so we don't publicly expose the BuilderParent methods. */ private class BuilderParentImpl implements BuilderParent { @@ -680,6 +647,7 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Gets the {@link BuilderParent} for giving to our children. + * * @return The builder parent for our children. */ protected BuilderParent getParentForChildren() { @@ -690,8 +658,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Called when a the builder or one of its nested children has changed - * and any parent should be notified of its invalidation. + * Called when a the builder or one of its nested children has changed and any parent should be + * notified of its invalidation. */ protected final void onChanged() { if (isClean && builderParent != null) { @@ -703,22 +671,19 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Gets the map field with the given field number. This method should be - * overridden in the generated message class if the message contains map - * fields. + * Gets the map field with the given field number. This method should be overridden in the + * generated message class if the message contains map fields. * - * Unlike other field types, reflection support for map fields can't be - * implemented based on generated public API because we need to access a - * map field as a list in reflection API but the generated API only allows - * us to access it as a map. This method returns the underlying map field - * directly and thus enables us to access the map field as a list. + *

Unlike other field types, reflection support for map fields can't be implemented based on + * generated public API because we need to access a map field as a list in reflection API but + * the generated API only allows us to access it as a map. This method returns the underlying + * map field directly and thus enables us to access the map field as a list. */ @SuppressWarnings({"unused", "rawtypes"}) protected MapField internalGetMapField(int fieldNumber) { // Note that we can't use descriptor names here because this method will // be called when descriptor is being initialized. - throw new RuntimeException( - "No map fields found in " + getClass().getName()); + throw new RuntimeException("No map fields found in " + getClass().getName()); } /** Like {@link #internalGetMapField} but return a mutable version. */ @@ -726,76 +691,57 @@ public abstract class GeneratedMessage extends AbstractMessage protected MapField internalGetMutableMapField(int fieldNumber) { // Note that we can't use descriptor names here because this method will // be called when descriptor is being initialized. - throw new RuntimeException( - "No map fields found in " + getClass().getName()); + throw new RuntimeException("No map fields found in " + getClass().getName()); } } // ================================================================= // Extensions-related stuff - public interface ExtendableMessageOrBuilder< - MessageType extends ExtendableMessage> extends MessageOrBuilder { + public interface ExtendableMessageOrBuilder + extends MessageOrBuilder { // Re-define for return type covariance. @Override Message getDefaultInstanceForType(); /** Check if a singular extension is present. */ - boolean hasExtension( - ExtensionLite extension); + boolean hasExtension(ExtensionLite extension); /** Get the number of elements in a repeated extension. */ - int getExtensionCount( - ExtensionLite> extension); + int getExtensionCount(ExtensionLite> extension); /** Get the value of an extension. */ - Type getExtension( - ExtensionLite extension); + Type getExtension(ExtensionLite extension); /** Get one element of a repeated extension. */ - Type getExtension( - ExtensionLite> extension, - int index); + Type getExtension(ExtensionLite> extension, int index); /** Check if a singular extension is present. */ - boolean hasExtension( - Extension extension); + boolean hasExtension(Extension extension); /** Check if a singular extension is present. */ - boolean hasExtension( - GeneratedExtension extension); + boolean hasExtension(GeneratedExtension extension); /** Get the number of elements in a repeated extension. */ - int getExtensionCount( - Extension> extension); + int getExtensionCount(Extension> extension); /** Get the number of elements in a repeated extension. */ - int getExtensionCount( - GeneratedExtension> extension); + int getExtensionCount(GeneratedExtension> extension); /** Get the value of an extension. */ - Type getExtension( - Extension extension); + Type getExtension(Extension extension); /** Get the value of an extension. */ - Type getExtension( - GeneratedExtension extension); + Type getExtension(GeneratedExtension extension); /** Get one element of a repeated extension. */ - Type getExtension( - Extension> extension, - int index); + Type getExtension(Extension> extension, int index); /** Get one element of a repeated extension. */ - Type getExtension( - GeneratedExtension> extension, - int index); + Type getExtension(GeneratedExtension> extension, int index); } /** - * Generated message classes for message types that contain extension ranges - * subclass this. + * Generated message classes for message types that contain extension ranges subclass this. * - *

This class implements type-safe accessors for extensions. They - * implement all the same operations that you can do with normal fields -- - * e.g. "has", "get", and "getCount" -- but for extensions. The extensions - * are identified using instances of the class {@link GeneratedExtension}; - * the protocol compiler generates a static instance of this class for every - * extension in its input. Through the magic of generics, all is made - * type-safe. + *

This class implements type-safe accessors for extensions. They implement all the same + * operations that you can do with normal fields -- e.g. "has", "get", and "getCount" -- but for + * extensions. The extensions are identified using instances of the class {@link + * GeneratedExtension}; the protocol compiler generates a static instance of this class for every + * extension in its input. Through the magic of generics, all is made type-safe. * *

For example, imagine you have the {@code .proto} file: * @@ -820,10 +766,8 @@ public abstract class GeneratedMessage extends AbstractMessage * *

See also {@link ExtendableBuilder}. */ - public abstract static class ExtendableMessage< - MessageType extends ExtendableMessage> - extends GeneratedMessage - implements ExtendableMessageOrBuilder { + public abstract static class ExtendableMessage + extends GeneratedMessage implements ExtendableMessageOrBuilder { private static final long serialVersionUID = 1L; @@ -833,22 +777,20 @@ public abstract class GeneratedMessage extends AbstractMessage this.extensions = FieldSet.newFieldSet(); } - protected ExtendableMessage( - ExtendableBuilder builder) { + protected ExtendableMessage(ExtendableBuilder builder) { super(builder); this.extensions = builder.buildExtensions(); } - private void verifyExtensionContainingType( - final Extension extension) { - if (extension.getDescriptor().getContainingType() != - getDescriptorForType()) { + private void verifyExtensionContainingType(final Extension extension) { + if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( - "Extension is for type \"" + - extension.getDescriptor().getContainingType().getFullName() + - "\" which does not match message type \"" + - getDescriptorForType().getFullName() + "\"."); + "Extension is for type \"" + + extension.getDescriptor().getContainingType().getFullName() + + "\" which does not match message type \"" + + getDescriptorForType().getFullName() + + "\"."); } } @@ -886,12 +828,10 @@ public abstract class GeneratedMessage extends AbstractMessage if (value == null) { if (descriptor.isRepeated()) { return (Type) Collections.emptyList(); - } else if (descriptor.getJavaType() == - FieldDescriptor.JavaType.MESSAGE) { + } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { return (Type) extension.getMessageDefaultInstance(); } else { - return (Type) extension.fromReflectionType( - descriptor.getDefaultValue()); + return (Type) extension.fromReflectionType(descriptor.getDefaultValue()); } } else { return (Type) extension.fromReflectionType(value); @@ -907,8 +847,8 @@ public abstract class GeneratedMessage extends AbstractMessage verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - return (Type) extension.singularFromReflectionType( - extensions.getRepeatedField(descriptor, index)); + return (Type) + extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); } /** Check if a singular extension is present. */ @@ -924,8 +864,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the number of elements in a repeated extension. */ @Override - public final int getExtensionCount( - final Extension> extension) { + public final int getExtensionCount(final Extension> extension) { return getExtensionCount((ExtensionLite>) extension); } /** Get the number of elements in a repeated extension. */ @@ -941,8 +880,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the value of an extension. */ @Override - public final Type getExtension( - final GeneratedExtension extension) { + public final Type getExtension(final GeneratedExtension extension) { return getExtension((ExtensionLite) extension); } /** Get one element of a repeated extension. */ @@ -973,33 +911,33 @@ public abstract class GeneratedMessage extends AbstractMessage CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, - int tag) throws IOException { + int tag) + throws IOException { return MessageReflection.mergeFieldFrom( - input, unknownFields, extensionRegistry, getDescriptorForType(), - new MessageReflection.ExtensionAdapter(extensions), tag); + input, + unknownFields, + extensionRegistry, + getDescriptorForType(), + new MessageReflection.ExtensionAdapter(extensions), + tag); } - - /** - * Used by parsing constructors in generated classes. - */ + /** Used by parsing constructors in generated classes. */ @Override protected void makeExtensionsImmutable() { extensions.makeImmutable(); } /** - * Used by subclasses to serialize extensions. Extension ranges may be - * interleaved with field numbers, but we must write them in canonical - * (sorted by field number) order. ExtensionWriter helps us write - * individual ranges of extensions at once. + * Used by subclasses to serialize extensions. Extension ranges may be interleaved with field + * numbers, but we must write them in canonical (sorted by field number) order. ExtensionWriter + * helps us write individual ranges of extensions at once. */ protected class ExtensionWriter { // Imagine how much simpler this code would be if Java iterators had // a way to get the next element without advancing the iterator. - private final Iterator> iter = - extensions.iterator(); + private final Iterator> iter = extensions.iterator(); private Map.Entry next; private final boolean messageSetWireFormat; @@ -1010,19 +948,18 @@ public abstract class GeneratedMessage extends AbstractMessage this.messageSetWireFormat = messageSetWireFormat; } - public void writeUntil(final int end, final CodedOutputStream output) - throws IOException { + public void writeUntil(final int end, final CodedOutputStream output) throws IOException { while (next != null && next.getKey().getNumber() < end) { FieldDescriptor descriptor = next.getKey(); - if (messageSetWireFormat && descriptor.getLiteJavaType() == - WireFormat.JavaType.MESSAGE && - !descriptor.isRepeated()) { + if (messageSetWireFormat + && descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE + && !descriptor.isRepeated()) { if (next instanceof LazyField.LazyEntry) { - output.writeRawMessageSetExtension(descriptor.getNumber(), + output.writeRawMessageSetExtension( + descriptor.getNumber(), ((LazyField.LazyEntry) next).getField().toByteString()); } else { - output.writeMessageSetExtension(descriptor.getNumber(), - (Message) next.getValue()); + output.writeMessageSetExtension(descriptor.getNumber(), (Message) next.getValue()); } } else { // TODO(xiangl): Taken care of following code, it may cause @@ -1046,6 +983,7 @@ public abstract class GeneratedMessage extends AbstractMessage protected ExtensionWriter newExtensionWriter() { return new ExtensionWriter(false); } + protected ExtensionWriter newMessageSetExtensionWriter() { return new ExtensionWriter(true); } @@ -1054,6 +992,7 @@ public abstract class GeneratedMessage extends AbstractMessage protected int extensionsSerializedSize() { return extensions.getSerializedSize(); } + protected int extensionsSerializedSizeAsMessageSet() { return extensions.getMessageSetSerializedSize(); } @@ -1125,8 +1064,7 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public Object getRepeatedField(final FieldDescriptor field, - final int index) { + public Object getRepeatedField(final FieldDescriptor field, final int index) { if (field.isExtension()) { verifyContainingType(field); return extensions.getRepeatedField(field, index); @@ -1137,23 +1075,19 @@ public abstract class GeneratedMessage extends AbstractMessage private void verifyContainingType(final FieldDescriptor field) { if (field.getContainingType() != getDescriptorForType()) { - throw new IllegalArgumentException( - "FieldDescriptor does not match message type."); + throw new IllegalArgumentException("FieldDescriptor does not match message type."); } } } /** - * Generated message builders for message types that contain extension ranges - * subclass this. + * Generated message builders for message types that contain extension ranges subclass this. * - *

This class implements type-safe accessors for extensions. They - * implement all the same operations that you can do with normal fields -- - * e.g. "get", "set", and "add" -- but for extensions. The extensions are - * identified using instances of the class {@link GeneratedExtension}; the - * protocol compiler generates a static instance of this class for every - * extension in its input. Through the magic of generics, all is made - * type-safe. + *

This class implements type-safe accessors for extensions. They implement all the same + * operations that you can do with normal fields -- e.g. "get", "set", and "add" -- but for + * extensions. The extensions are identified using instances of the class {@link + * GeneratedExtension}; the protocol compiler generates a static instance of this class for every + * extension in its input. Through the magic of generics, all is made type-safe. * *

For example, imagine you have the {@code .proto} file: * @@ -1182,17 +1116,15 @@ public abstract class GeneratedMessage extends AbstractMessage */ @SuppressWarnings("unchecked") public abstract static class ExtendableBuilder< - MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder> - extends Builder - implements ExtendableMessageOrBuilder { + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends Builder implements ExtendableMessageOrBuilder { private FieldSet extensions = FieldSet.emptySet(); protected ExtendableBuilder() {} - protected ExtendableBuilder( - BuilderParent parent) { + protected ExtendableBuilder(BuilderParent parent) { super(parent); } @@ -1221,16 +1153,15 @@ public abstract class GeneratedMessage extends AbstractMessage } } - private void verifyExtensionContainingType( - final Extension extension) { - if (extension.getDescriptor().getContainingType() != - getDescriptorForType()) { + private void verifyExtensionContainingType(final Extension extension) { + if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( - "Extension is for type \"" + - extension.getDescriptor().getContainingType().getFullName() + - "\" which does not match message type \"" + - getDescriptorForType().getFullName() + "\"."); + "Extension is for type \"" + + extension.getDescriptor().getContainingType().getFullName() + + "\" which does not match message type \"" + + getDescriptorForType().getFullName() + + "\"."); } } @@ -1265,12 +1196,10 @@ public abstract class GeneratedMessage extends AbstractMessage if (value == null) { if (descriptor.isRepeated()) { return (Type) Collections.emptyList(); - } else if (descriptor.getJavaType() == - FieldDescriptor.JavaType.MESSAGE) { + } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { return (Type) extension.getMessageDefaultInstance(); } else { - return (Type) extension.fromReflectionType( - descriptor.getDefaultValue()); + return (Type) extension.fromReflectionType(descriptor.getDefaultValue()); } } else { return (Type) extension.fromReflectionType(value); @@ -1285,14 +1214,13 @@ public abstract class GeneratedMessage extends AbstractMessage verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - return (Type) extension.singularFromReflectionType( - extensions.getRepeatedField(descriptor, index)); + return (Type) + extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); } /** Set the value of an extension. */ public final BuilderType setExtension( - final ExtensionLite extensionLite, - final Type value) { + final ExtensionLite extensionLite, final Type value) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1306,30 +1234,27 @@ public abstract class GeneratedMessage extends AbstractMessage /** Set the value of one element of a repeated extension. */ public final BuilderType setExtension( final ExtensionLite> extensionLite, - final int index, final Type value) { + final int index, + final Type value) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); - extensions.setRepeatedField( - descriptor, index, - extension.singularToReflectionType(value)); + extensions.setRepeatedField(descriptor, index, extension.singularToReflectionType(value)); onChanged(); return (BuilderType) this; } /** Append a value to a repeated extension. */ public final BuilderType addExtension( - final ExtensionLite> extensionLite, - final Type value) { + final ExtensionLite> extensionLite, final Type value) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); - extensions.addRepeatedField( - descriptor, extension.singularToReflectionType(value)); + extensions.addRepeatedField(descriptor, extension.singularToReflectionType(value)); onChanged(); return (BuilderType) this; } @@ -1359,8 +1284,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the number of elements in a repeated extension. */ @Override - public final int getExtensionCount( - final Extension> extension) { + public final int getExtensionCount(final Extension> extension) { return getExtensionCount((ExtensionLite>) extension); } /** Get the number of elements in a repeated extension. */ @@ -1376,8 +1300,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Get the value of an extension. */ @Override - public final Type getExtension( - final GeneratedExtension extension) { + public final Type getExtension(final GeneratedExtension extension) { return getExtension((ExtensionLite) extension); } /** Get the value of an extension. */ @@ -1404,14 +1327,14 @@ public abstract class GeneratedMessage extends AbstractMessage } /** Set the value of one element of a repeated extension. */ public final BuilderType setExtension( - final Extension> extension, - final int index, final Type value) { + final Extension> extension, final int index, final Type value) { return setExtension((ExtensionLite>) extension, index, value); } /** Set the value of one element of a repeated extension. */ public BuilderType setExtension( final GeneratedExtension> extension, - final int index, final Type value) { + final int index, + final Type value) { return setExtension((ExtensionLite>) extension, index, value); } /** Append a value to a repeated extension. */ @@ -1425,13 +1348,11 @@ public abstract class GeneratedMessage extends AbstractMessage return addExtension((ExtensionLite>) extension, value); } /** Clear an extension. */ - public final BuilderType clearExtension( - final Extension extension) { + public final BuilderType clearExtension(final Extension extension) { return clearExtension((ExtensionLite) extension); } /** Clear an extension. */ - public BuilderType clearExtension( - final GeneratedExtension extension) { + public BuilderType clearExtension(final GeneratedExtension extension) { return clearExtension((ExtensionLite) extension); } @@ -1441,8 +1362,7 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Called by the build code path to create a copy of the extensions for - * building the message. + * Called by the build code path to create a copy of the extensions for building the message. */ private FieldSet buildExtensions() { extensions.makeImmutable(); @@ -1456,6 +1376,7 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Called by subclasses to parse an unknown field or an extension. + * * @return {@code true} unless the tag is an end-group tag. */ @Override @@ -1463,10 +1384,15 @@ public abstract class GeneratedMessage extends AbstractMessage final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, - final int tag) throws IOException { + final int tag) + throws IOException { return MessageReflection.mergeFieldFrom( - input, unknownFields, extensionRegistry, getDescriptorForType(), - new MessageReflection.BuilderAdapter(this), tag); + input, + unknownFields, + extensionRegistry, + getDescriptorForType(), + new MessageReflection.BuilderAdapter(this), + tag); } // --------------------------------------------------------------- @@ -1511,8 +1437,7 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public Object getRepeatedField(final FieldDescriptor field, - final int index) { + public Object getRepeatedField(final FieldDescriptor field, final int index) { if (field.isExtension()) { verifyContainingType(field); return extensions.getRepeatedField(field, index); @@ -1532,8 +1457,7 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public BuilderType setField(final FieldDescriptor field, - final Object value) { + public BuilderType setField(final FieldDescriptor field, final Object value) { if (field.isExtension()) { verifyContainingType(field); ensureExtensionsIsMutable(); @@ -1559,8 +1483,8 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public BuilderType setRepeatedField(final FieldDescriptor field, - final int index, final Object value) { + public BuilderType setRepeatedField( + final FieldDescriptor field, final int index, final Object value) { if (field.isExtension()) { verifyContainingType(field); ensureExtensionsIsMutable(); @@ -1573,8 +1497,7 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public BuilderType addRepeatedField(final FieldDescriptor field, - final Object value) { + public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) { if (field.isExtension()) { verifyContainingType(field); ensureExtensionsIsMutable(); @@ -1594,8 +1517,7 @@ public abstract class GeneratedMessage extends AbstractMessage private void verifyContainingType(final FieldDescriptor field) { if (field.getContainingType() != getDescriptorForType()) { - throw new IllegalArgumentException( - "FieldDescriptor does not match message type."); + throw new IllegalArgumentException("FieldDescriptor does not match message type."); } } } @@ -1603,8 +1525,8 @@ public abstract class GeneratedMessage extends AbstractMessage // ----------------------------------------------------------------- /** - * Gets the descriptor for an extension. The implementation depends on whether - * the extension is scoped in the top level of a file or scoped in a Message. + * Gets the descriptor for an extension. The implementation depends on whether the extension is + * scoped in the top level of a file or scoped in a Message. */ static interface ExtensionDescriptorRetriever { FieldDescriptor getDescriptor(); @@ -1612,11 +1534,11 @@ public abstract class GeneratedMessage extends AbstractMessage /** For use by generated code only. */ public static - GeneratedExtension - newMessageScopedGeneratedExtension(final Message scope, - final int descriptorIndex, - final Class singularType, - final Message defaultInstance) { + GeneratedExtension newMessageScopedGeneratedExtension( + final Message scope, + final int descriptorIndex, + final Class singularType, + final Message defaultInstance) { // For extensions scoped within a Message, we use the Message to resolve // the outer class's descriptor, from which the extension descriptor is // obtained. @@ -1634,22 +1556,21 @@ public abstract class GeneratedMessage extends AbstractMessage /** For use by generated code only. */ public static - GeneratedExtension - newFileScopedGeneratedExtension(final Class singularType, - final Message defaultInstance) { + GeneratedExtension newFileScopedGeneratedExtension( + final Class singularType, final Message defaultInstance) { // For extensions scoped within a file, we rely on the outer class's // static initializer to call internalInit() on the extension when the // descriptor is available. return new GeneratedExtension( - null, // ExtensionDescriptorRetriever is initialized in internalInit(); + null, // ExtensionDescriptorRetriever is initialized in internalInit(); singularType, defaultInstance, Extension.ExtensionType.IMMUTABLE); } - private abstract static class CachedDescriptorRetriever - implements ExtensionDescriptorRetriever { + private abstract static class CachedDescriptorRetriever implements ExtensionDescriptorRetriever { private volatile FieldDescriptor descriptor; + protected abstract FieldDescriptor loadDescriptor(); @Override @@ -1668,15 +1589,16 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Used in proto1 generated code only. * - * After enabling bridge, we can define proto2 extensions (the extended type - * is a proto2 mutable message) in a proto1 .proto file. For these extensions - * we should generate proto2 GeneratedExtensions. + *

After enabling bridge, we can define proto2 extensions (the extended type is a proto2 + * mutable message) in a proto1 .proto file. For these extensions we should generate proto2 + * GeneratedExtensions. */ public static - GeneratedExtension - newMessageScopedGeneratedExtension( - final Message scope, final String name, - final Class singularType, final Message defaultInstance) { + GeneratedExtension newMessageScopedGeneratedExtension( + final Message scope, + final String name, + final Class singularType, + final Message defaultInstance) { // For extensions scoped within a Message, we use the Message to resolve // the outer class's descriptor, from which the extension descriptor is // obtained. @@ -1695,15 +1617,16 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Used in proto1 generated code only. * - * After enabling bridge, we can define proto2 extensions (the extended type - * is a proto2 mutable message) in a proto1 .proto file. For these extensions - * we should generate proto2 GeneratedExtensions. + *

After enabling bridge, we can define proto2 extensions (the extended type is a proto2 + * mutable message) in a proto1 .proto file. For these extensions we should generate proto2 + * GeneratedExtensions. */ public static - GeneratedExtension - newFileScopedGeneratedExtension( - final Class singularType, final Message defaultInstance, - final String descriptorOuterClass, final String extensionName) { + GeneratedExtension newFileScopedGeneratedExtension( + final Class singularType, + final Message defaultInstance, + final String descriptorOuterClass, + final String extensionName) { // For extensions scoped within a file, we load the descriptor outer // class and rely on it to get the FileDescriptor which then can be // used to obtain the extension's FieldDescriptor. @@ -1730,8 +1653,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Type used to represent generated extensions. The protocol compiler - * generates a static singleton instance of this class for each extension. + * Type used to represent generated extensions. The protocol compiler generates a static singleton + * instance of this class for each extension. * *

For example, imagine you have the {@code .proto} file: * @@ -1747,16 +1670,14 @@ public abstract class GeneratedMessage extends AbstractMessage * } * * - *

Then, {@code MyProto.Foo.bar} has type - * {@code GeneratedExtension}. + *

Then, {@code MyProto.Foo.bar} has type {@code GeneratedExtension}. * - *

In general, users should ignore the details of this type, and simply use - * these static singletons as parameters to the extension accessors defined - * in {@link ExtendableMessage} and {@link ExtendableBuilder}. + *

In general, users should ignore the details of this type, and simply use these static + * singletons as parameters to the extension accessors defined in {@link ExtendableMessage} and + * {@link ExtendableBuilder}. */ - public static class GeneratedExtension< - ContainingType extends Message, Type> extends - Extension { + public static class GeneratedExtension + extends Extension { // TODO(kenton): Find ways to avoid using Java reflection within this // class. Also try to avoid suppressing unchecked warnings. @@ -1772,12 +1693,13 @@ public abstract class GeneratedMessage extends AbstractMessage // In the case of non-nested extensions, we initialize the // ExtensionDescriptorRetriever to null and rely on the outer class's static // initializer to call internalInit() after the descriptor has been parsed. - GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever, + GeneratedExtension( + ExtensionDescriptorRetriever descriptorRetriever, Class singularType, Message messageDefaultInstance, ExtensionType extensionType) { - if (Message.class.isAssignableFrom(singularType) && - !singularType.isInstance(messageDefaultInstance)) { + if (Message.class.isAssignableFrom(singularType) + && !singularType.isInstance(messageDefaultInstance)) { throw new IllegalArgumentException( "Bad messageDefaultInstance for " + singularType.getName()); } @@ -1786,10 +1708,8 @@ public abstract class GeneratedMessage extends AbstractMessage this.messageDefaultInstance = messageDefaultInstance; if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) { - this.enumValueOf = getMethodOrDie(singularType, "valueOf", - EnumValueDescriptor.class); - this.enumGetValueDescriptor = - getMethodOrDie(singularType, "getValueDescriptor"); + this.enumValueOf = getMethodOrDie(singularType, "valueOf", EnumValueDescriptor.class); + this.enumGetValueDescriptor = getMethodOrDie(singularType, "getValueDescriptor"); } else { this.enumValueOf = null; this.enumGetValueDescriptor = null; @@ -1821,15 +1741,14 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public FieldDescriptor getDescriptor() { if (descriptorRetriever == null) { - throw new IllegalStateException( - "getDescriptor() called before internalInit()"); + throw new IllegalStateException("getDescriptor() called before internalInit()"); } return descriptorRetriever.getDescriptor(); } /** - * If the extension is an embedded message or group, returns the default - * instance of the message. + * If the extension is an embedded message or group, returns the default instance of the + * message. */ @Override public Message getMessageDefaultInstance() { @@ -1842,18 +1761,17 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Convert from the type used by the reflection accessors to the type used - * by native accessors. E.g., for enums, the reflection accessors use - * EnumValueDescriptors but the native accessors use the generated enum - * type. + * Convert from the type used by the reflection accessors to the type used by native accessors. + * E.g., for enums, the reflection accessors use EnumValueDescriptors but the native accessors + * use the generated enum type. */ @Override @SuppressWarnings("unchecked") protected Object fromReflectionType(final Object value) { FieldDescriptor descriptor = getDescriptor(); if (descriptor.isRepeated()) { - if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || - descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { + if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE + || descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { // Must convert the whole list. final List result = new ArrayList(); for (final Object element : (List) value) { @@ -1869,8 +1787,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Like {@link #fromReflectionType(Object)}, but if the type is a repeated - * type, this converts a single element. + * Like {@link #fromReflectionType(Object)}, but if the type is a repeated type, this converts a + * single element. */ @Override protected Object singularFromReflectionType(final Object value) { @@ -1880,8 +1798,7 @@ public abstract class GeneratedMessage extends AbstractMessage if (singularType.isInstance(value)) { return value; } else { - return messageDefaultInstance.newBuilderForType() - .mergeFrom((Message) value).build(); + return messageDefaultInstance.newBuilderForType().mergeFrom((Message) value).build(); } case ENUM: return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); @@ -1891,10 +1808,9 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Convert from the type used by the native accessors to the type used - * by reflection accessors. E.g., for enums, the reflection accessors use - * EnumValueDescriptors but the native accessors use the generated enum - * type. + * Convert from the type used by the native accessors to the type used by reflection accessors. + * E.g., for enums, the reflection accessors use EnumValueDescriptors but the native accessors + * use the generated enum type. */ @Override @SuppressWarnings("unchecked") @@ -1917,8 +1833,8 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Like {@link #toReflectionType(Object)}, but if the type is a repeated - * type, this converts a single element. + * Like {@link #toReflectionType(Object)}, but if the type is a repeated type, this converts a + * single element. */ @Override protected Object singularToReflectionType(final Object value) { @@ -1955,8 +1871,7 @@ public abstract class GeneratedMessage extends AbstractMessage if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { return (Type) messageDefaultInstance; } - return (Type) singularFromReflectionType( - getDescriptor().getDefaultValue()); + return (Type) singularFromReflectionType(getDescriptor().getDefaultValue()); } } @@ -1970,8 +1885,8 @@ public abstract class GeneratedMessage extends AbstractMessage return clazz.getMethod(name, params); } catch (NoSuchMethodException e) { throw new RuntimeException( - "Generated message class \"" + clazz.getName() + - "\" missing method \"" + name + "\".", e); + "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".", + e); } } @@ -1982,8 +1897,7 @@ public abstract class GeneratedMessage extends AbstractMessage return method.invoke(object, params); } catch (IllegalAccessException e) { throw new RuntimeException( - "Couldn't use Java reflection to implement protocol message " + - "reflection.", e); + "Couldn't use Java reflection to implement protocol message " + "reflection.", e); } catch (InvocationTargetException e) { final Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { @@ -1992,45 +1906,42 @@ public abstract class GeneratedMessage extends AbstractMessage throw (Error) cause; } else { throw new RuntimeException( - "Unexpected exception thrown by generated accessor method.", cause); + "Unexpected exception thrown by generated accessor method.", cause); } } } /** - * Gets the map field with the given field number. This method should be - * overridden in the generated message class if the message contains map - * fields. + * Gets the map field with the given field number. This method should be overridden in the + * generated message class if the message contains map fields. * - * Unlike other field types, reflection support for map fields can't be - * implemented based on generated public API because we need to access a - * map field as a list in reflection API but the generated API only allows - * us to access it as a map. This method returns the underlying map field - * directly and thus enables us to access the map field as a list. + *

Unlike other field types, reflection support for map fields can't be implemented based on + * generated public API because we need to access a map field as a list in reflection API but the + * generated API only allows us to access it as a map. This method returns the underlying map + * field directly and thus enables us to access the map field as a list. */ @SuppressWarnings({"rawtypes", "unused"}) protected MapField internalGetMapField(int fieldNumber) { // Note that we can't use descriptor names here because this method will // be called when descriptor is being initialized. - throw new RuntimeException( - "No map fields found in " + getClass().getName()); + throw new RuntimeException("No map fields found in " + getClass().getName()); } /** - * Users should ignore this class. This class provides the implementation - * with access to the fields of a message object using Java reflection. + * Users should ignore this class. This class provides the implementation with access to the + * fields of a message object using Java reflection. */ public static final class FieldAccessorTable { /** - * Construct a FieldAccessorTable for a particular message class. Only - * one FieldAccessorTable should ever be constructed per class. + * Construct a FieldAccessorTable for a particular message class. Only one FieldAccessorTable + * should ever be constructed per class. * - * @param descriptor The type's descriptor. - * @param camelCaseNames The camelcase names of all fields in the message. - * These are used to derive the accessor method names. - * @param messageClass The message type. - * @param builderClass The builder type. + * @param descriptor The type's descriptor. + * @param camelCaseNames The camelcase names of all fields in the message. These are used to + * derive the accessor method names. + * @param messageClass The message type. + * @param builderClass The builder type. */ public FieldAccessorTable( final Descriptor descriptor, @@ -2042,12 +1953,10 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Construct a FieldAccessorTable for a particular message class without - * initializing FieldAccessors. + * Construct a FieldAccessorTable for a particular message class without initializing + * FieldAccessors. */ - public FieldAccessorTable( - final Descriptor descriptor, - final String[] camelCaseNames) { + public FieldAccessorTable(final Descriptor descriptor, final String[] camelCaseNames) { this.descriptor = descriptor; this.camelCaseNames = camelCaseNames; fields = new FieldAccessor[descriptor.getFields().size()]; @@ -2063,16 +1972,19 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Ensures the field accessors are initialized. This method is thread-safe. * - * @param messageClass The message type. - * @param builderClass The builder type. + * @param messageClass The message type. + * @param builderClass The builder type. * @return this */ public FieldAccessorTable ensureFieldAccessorsInitialized( - Class messageClass, - Class builderClass) { - if (initialized) { return this; } + Class messageClass, Class builderClass) { + if (initialized) { + return this; + } synchronized (this) { - if (initialized) { return this; } + if (initialized) { + return this; + } int fieldsSize = fields.length; for (int i = 0; i < fieldsSize; i++) { FieldDescriptor field = descriptor.getFields().get(i); @@ -2084,45 +1996,63 @@ public abstract class GeneratedMessage extends AbstractMessage if (field.isRepeated()) { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (field.isMapField() && isMapFieldEnabled(field)) { - fields[i] = new MapFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + fields[i] = + new MapFieldAccessor(field, camelCaseNames[i], messageClass, builderClass); } else { - fields[i] = new RepeatedMessageFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + fields[i] = + new RepeatedMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); } } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { - fields[i] = new RepeatedEnumFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + fields[i] = + new RepeatedEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); } else { - fields[i] = new RepeatedFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass); + fields[i] = + new RepeatedFieldAccessor(field, camelCaseNames[i], messageClass, builderClass); } } else { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - fields[i] = new SingularMessageFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass, - containingOneofCamelCaseName); + fields[i] = + new SingularMessageFieldAccessor( + field, + camelCaseNames[i], + messageClass, + builderClass, + containingOneofCamelCaseName); } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { - fields[i] = new SingularEnumFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass, - containingOneofCamelCaseName); + fields[i] = + new SingularEnumFieldAccessor( + field, + camelCaseNames[i], + messageClass, + builderClass, + containingOneofCamelCaseName); } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) { - fields[i] = new SingularStringFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass, - containingOneofCamelCaseName); + fields[i] = + new SingularStringFieldAccessor( + field, + camelCaseNames[i], + messageClass, + builderClass, + containingOneofCamelCaseName); } else { - fields[i] = new SingularFieldAccessor( - field, camelCaseNames[i], messageClass, builderClass, - containingOneofCamelCaseName); + fields[i] = + new SingularFieldAccessor( + field, + camelCaseNames[i], + messageClass, + builderClass, + containingOneofCamelCaseName); } } } int oneofsSize = oneofs.length; for (int i = 0; i < oneofsSize; i++) { - oneofs[i] = new OneofAccessor( - descriptor, camelCaseNames[i + fieldsSize], - messageClass, builderClass); + oneofs[i] = + new OneofAccessor( + descriptor, camelCaseNames[i + fieldsSize], messageClass, builderClass); } initialized = true; camelCaseNames = null; @@ -2139,13 +2069,11 @@ public abstract class GeneratedMessage extends AbstractMessage /** Get the FieldAccessor for a particular field. */ private FieldAccessor getField(final FieldDescriptor field) { if (field.getContainingType() != descriptor) { - throw new IllegalArgumentException( - "FieldDescriptor does not match message type."); + throw new IllegalArgumentException("FieldDescriptor does not match message type."); } else if (field.isExtension()) { // If this type had extensions, it would subclass ExtendableMessage, // which overrides the reflection interface to handle extensions. - throw new IllegalArgumentException( - "This type does not have extensions."); + throw new IllegalArgumentException("This type does not have extensions."); } return fields[field.getIndex()]; } @@ -2153,51 +2081,65 @@ public abstract class GeneratedMessage extends AbstractMessage /** Get the OneofAccessor for a particular oneof. */ private OneofAccessor getOneof(final OneofDescriptor oneof) { if (oneof.getContainingType() != descriptor) { - throw new IllegalArgumentException( - "OneofDescriptor does not match message type."); + throw new IllegalArgumentException("OneofDescriptor does not match message type."); } return oneofs[oneof.getIndex()]; } /** - * Abstract interface that provides access to a single field. This is - * implemented differently depending on the field type and cardinality. + * Abstract interface that provides access to a single field. This is implemented differently + * depending on the field type and cardinality. */ private interface FieldAccessor { Object get(GeneratedMessage message); + Object get(GeneratedMessage.Builder builder); + Object getRaw(GeneratedMessage message); + Object getRaw(GeneratedMessage.Builder builder); + void set(Builder builder, Object value); + Object getRepeated(GeneratedMessage message, int index); + Object getRepeated(GeneratedMessage.Builder builder, int index); + Object getRepeatedRaw(GeneratedMessage message, int index); + Object getRepeatedRaw(GeneratedMessage.Builder builder, int index); - void setRepeated(Builder builder, - int index, Object value); + + void setRepeated(Builder builder, int index, Object value); + void addRepeated(Builder builder, Object value); + boolean has(GeneratedMessage message); + boolean has(GeneratedMessage.Builder builder); + int getRepeatedCount(GeneratedMessage message); + int getRepeatedCount(GeneratedMessage.Builder builder); + void clear(Builder builder); + Message.Builder newBuilder(); + Message.Builder getBuilder(GeneratedMessage.Builder builder); - Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, - int index); + + Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index); } /** OneofAccessor provides access to a single oneof. */ private static class OneofAccessor { OneofAccessor( - final Descriptor descriptor, final String camelCaseName, + final Descriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass) { this.descriptor = descriptor; - caseMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); - caseMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); + caseMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); + caseMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); } @@ -2249,27 +2191,32 @@ public abstract class GeneratedMessage extends AbstractMessage private static class SingularFieldAccessor implements FieldAccessor { SingularFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass, final String containingOneofCamelCaseName) { field = descriptor; isOneofField = descriptor.getContainingOneof() != null; - hasHasMethod = supportFieldPresence(descriptor.getFile()) - || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); + hasHasMethod = + supportFieldPresence(descriptor.getFile()) + || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); type = getMethod.getReturnType(); setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); - hasMethod = - hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; + hasMethod = hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; hasMethodBuilder = hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); - caseMethod = isOneofField ? getMethodOrDie( - messageClass, "get" + containingOneofCamelCaseName + "Case") : null; - caseMethodBuilder = isOneofField ? getMethodOrDie( - builderClass, "get" + containingOneofCamelCaseName + "Case") : null; + caseMethod = + isOneofField + ? getMethodOrDie(messageClass, "get" + containingOneofCamelCaseName + "Case") + : null; + caseMethodBuilder = + isOneofField + ? getMethodOrDie(builderClass, "get" + containingOneofCamelCaseName + "Case") + : null; } // Note: We use Java reflection to call public methods rather than @@ -2300,52 +2247,59 @@ public abstract class GeneratedMessage extends AbstractMessage public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } + @Override public Object get(GeneratedMessage.Builder builder) { return invokeOrDie(getMethodBuilder, builder); } + @Override public Object getRaw(final GeneratedMessage message) { return get(message); } + @Override public Object getRaw(GeneratedMessage.Builder builder) { return get(builder); } + @Override public void set(final Builder builder, final Object value) { invokeOrDie(setMethod, builder, value); } + @Override public Object getRepeated(final GeneratedMessage message, final int index) { - throw new UnsupportedOperationException( - "getRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } + @Override public Object getRepeatedRaw(final GeneratedMessage message, final int index) { throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); + "getRepeatedFieldRaw() called on a singular field."); } + @Override public Object getRepeated(GeneratedMessage.Builder builder, int index) { - throw new UnsupportedOperationException( - "getRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } + @Override public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); + "getRepeatedFieldRaw() called on a singular field."); } + @Override public void setRepeated(final Builder builder, final int index, final Object value) { - throw new UnsupportedOperationException( - "setRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("setRepeatedField() called on a singular field."); } + @Override public void addRepeated(final Builder builder, final Object value) { - throw new UnsupportedOperationException( - "addRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("addRepeatedField() called on a singular field."); } + @Override public boolean has(final GeneratedMessage message) { if (!hasHasMethod) { @@ -2356,6 +2310,7 @@ public abstract class GeneratedMessage extends AbstractMessage } return (Boolean) invokeOrDie(hasMethod, message); } + @Override public boolean has(GeneratedMessage.Builder builder) { if (!hasHasMethod) { @@ -2366,34 +2321,39 @@ public abstract class GeneratedMessage extends AbstractMessage } return (Boolean) invokeOrDie(hasMethodBuilder, builder); } + @Override public int getRepeatedCount(final GeneratedMessage message) { throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); + "getRepeatedFieldSize() called on a singular field."); } + @Override public int getRepeatedCount(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); + "getRepeatedFieldSize() called on a singular field."); } + @Override public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } + @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + "newBuilderForField() called on a non-Message type."); } + @Override public Message.Builder getBuilder(GeneratedMessage.Builder builder) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } + @Override public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); + "getRepeatedFieldBuilder() called on a non-Message type."); } } @@ -2410,27 +2370,20 @@ public abstract class GeneratedMessage extends AbstractMessage protected final Method clearMethod; RepeatedFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass) { - getMethod = getMethodOrDie(messageClass, - "get" + camelCaseName + "List"); - getMethodBuilder = getMethodOrDie(builderClass, - "get" + camelCaseName + "List"); - getRepeatedMethod = - getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List"); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List"); + getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); getRepeatedMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); type = getRepeatedMethod.getReturnType(); - setRepeatedMethod = - getMethodOrDie(builderClass, "set" + camelCaseName, - Integer.TYPE, type); - addRepeatedMethod = - getMethodOrDie(builderClass, "add" + camelCaseName, type); - getCountMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); - getCountMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); + setRepeatedMethod = getMethodOrDie(builderClass, "set" + camelCaseName, Integer.TYPE, type); + addRepeatedMethod = getMethodOrDie(builderClass, "add" + camelCaseName, type); + getCountMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); + getCountMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); } @@ -2439,18 +2392,22 @@ public abstract class GeneratedMessage extends AbstractMessage public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } + @Override public Object get(GeneratedMessage.Builder builder) { return invokeOrDie(getMethodBuilder, builder); } + @Override public Object getRaw(final GeneratedMessage message) { return get(message); } + @Override public Object getRaw(GeneratedMessage.Builder builder) { return get(builder); } + @Override public void set(final Builder builder, final Object value) { // Add all the elements individually. This serves two purposes: @@ -2462,81 +2419,91 @@ public abstract class GeneratedMessage extends AbstractMessage addRepeated(builder, element); } } + @Override public Object getRepeated(final GeneratedMessage message, final int index) { return invokeOrDie(getRepeatedMethod, message, index); } + @Override public Object getRepeated(GeneratedMessage.Builder builder, int index) { return invokeOrDie(getRepeatedMethodBuilder, builder, index); } + @Override public Object getRepeatedRaw(GeneratedMessage message, int index) { return getRepeated(message, index); } + @Override public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { return getRepeated(builder, index); } + @Override public void setRepeated(final Builder builder, final int index, final Object value) { invokeOrDie(setRepeatedMethod, builder, index, value); } + @Override public void addRepeated(final Builder builder, final Object value) { invokeOrDie(addRepeatedMethod, builder, value); } + @Override public boolean has(final GeneratedMessage message) { - throw new UnsupportedOperationException( - "hasField() called on a repeated field."); + throw new UnsupportedOperationException("hasField() called on a repeated field."); } + @Override public boolean has(GeneratedMessage.Builder builder) { - throw new UnsupportedOperationException( - "hasField() called on a repeated field."); + throw new UnsupportedOperationException("hasField() called on a repeated field."); } + @Override public int getRepeatedCount(final GeneratedMessage message) { return (Integer) invokeOrDie(getCountMethod, message); } + @Override public int getRepeatedCount(GeneratedMessage.Builder builder) { return (Integer) invokeOrDie(getCountMethodBuilder, builder); } + @Override public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } + @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + "newBuilderForField() called on a non-Message type."); } + @Override public Message.Builder getBuilder(GeneratedMessage.Builder builder) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } + @Override public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); + "getRepeatedFieldBuilder() called on a non-Message type."); } } private static class MapFieldAccessor implements FieldAccessor { MapFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass) { field = descriptor; - Method getDefaultInstanceMethod = - getMethodOrDie(messageClass, "getDefaultInstance"); - MapField defaultMapField = getMapField( - (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null)); - mapEntryMessageDefaultInstance = - defaultMapField.getMapEntryMessageDefaultInstance(); + Method getDefaultInstanceMethod = getMethodOrDie(messageClass, "getDefaultInstance"); + MapField defaultMapField = + getMapField((GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null)); + mapEntryMessageDefaultInstance = defaultMapField.getMapEntryMessageDefaultInstance(); } private final FieldDescriptor field; @@ -2550,10 +2517,8 @@ public abstract class GeneratedMessage extends AbstractMessage return (MapField) builder.internalGetMapField(field.getNumber()); } - private MapField getMutableMapField( - GeneratedMessage.Builder builder) { - return (MapField) builder.internalGetMutableMapField( - field.getNumber()); + private MapField getMutableMapField(GeneratedMessage.Builder builder) { + return (MapField) builder.internalGetMutableMapField(field.getNumber()); } @Override @@ -2626,14 +2591,12 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public boolean has(GeneratedMessage message) { - throw new UnsupportedOperationException( - "hasField() is not supported for repeated fields."); + throw new UnsupportedOperationException("hasField() is not supported for repeated fields."); } @Override public boolean has(Builder builder) { - throw new UnsupportedOperationException( - "hasField() is not supported for repeated fields."); + throw new UnsupportedOperationException("hasField() is not supported for repeated fields."); } @Override @@ -2658,23 +2621,21 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public com.google.protobuf.Message.Builder getBuilder(Builder builder) { - throw new UnsupportedOperationException( - "Nested builder not supported for map fields."); + throw new UnsupportedOperationException("Nested builder not supported for map fields."); } @Override public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) { - throw new UnsupportedOperationException( - "Nested builder not supported for map fields."); + throw new UnsupportedOperationException("Nested builder not supported for map fields."); } } // --------------------------------------------------------------- - private static final class SingularEnumFieldAccessor - extends SingularFieldAccessor { + private static final class SingularEnumFieldAccessor extends SingularFieldAccessor { SingularEnumFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass, final String containingOneofCamelCaseName) { @@ -2682,19 +2643,14 @@ public abstract class GeneratedMessage extends AbstractMessage enumDescriptor = descriptor.getEnumType(); - valueOfMethod = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - getValueDescriptorMethod = - getMethodOrDie(type, "getValueDescriptor"); + valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); + getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); if (supportUnknownEnumValue) { - getValueMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Value"); - getValueMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Value"); - setValueMethod = - getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class); + getValueMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Value"); + getValueMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Value"); + setValueMethod = getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class); } } @@ -2729,28 +2685,25 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public void set(final Builder builder, final Object value) { if (supportUnknownEnumValue) { - invokeOrDie(setValueMethod, builder, - ((EnumValueDescriptor) value).getNumber()); + invokeOrDie(setValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); return; } super.set(builder, invokeOrDie(valueOfMethod, null, value)); } } - private static final class RepeatedEnumFieldAccessor - extends RepeatedFieldAccessor { + private static final class RepeatedEnumFieldAccessor extends RepeatedFieldAccessor { RepeatedEnumFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); enumDescriptor = descriptor.getEnumType(); - valueOfMethod = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - getValueDescriptorMethod = - getMethodOrDie(type, "getValueDescriptor"); + valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); + getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); if (supportUnknownEnumValue) { @@ -2764,6 +2717,7 @@ public abstract class GeneratedMessage extends AbstractMessage getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class); } } + private EnumDescriptor enumDescriptor; private final Method valueOfMethod; @@ -2798,41 +2752,37 @@ public abstract class GeneratedMessage extends AbstractMessage } @Override - public Object getRepeated(final GeneratedMessage message, - final int index) { + public Object getRepeated(final GeneratedMessage message, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); } - return invokeOrDie(getValueDescriptorMethod, - super.getRepeated(message, index)); + return invokeOrDie(getValueDescriptorMethod, super.getRepeated(message, index)); } + @Override - public Object getRepeated(final GeneratedMessage.Builder builder, - final int index) { + public Object getRepeated(final GeneratedMessage.Builder builder, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); } - return invokeOrDie(getValueDescriptorMethod, - super.getRepeated(builder, index)); + return invokeOrDie(getValueDescriptorMethod, super.getRepeated(builder, index)); } + @Override - public void setRepeated(final Builder builder, - final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { if (supportUnknownEnumValue) { - invokeOrDie(setRepeatedValueMethod, builder, index, - ((EnumValueDescriptor) value).getNumber()); + invokeOrDie( + setRepeatedValueMethod, builder, index, ((EnumValueDescriptor) value).getNumber()); return; } - super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, - value)); + super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value)); } + @Override public void addRepeated(final Builder builder, final Object value) { if (supportUnknownEnumValue) { - invokeOrDie(addRepeatedValueMethod, builder, - ((EnumValueDescriptor) value).getNumber()); + invokeOrDie(addRepeatedValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); return; } super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); @@ -2844,29 +2794,25 @@ public abstract class GeneratedMessage extends AbstractMessage /** * Field accessor for string fields. * - *

This class makes getFooBytes() and setFooBytes() available for - * reflection API so that reflection based serialize/parse functions can - * access the raw bytes of the field to preserve non-UTF8 bytes in the - * string. + *

This class makes getFooBytes() and setFooBytes() available for reflection API so that + * reflection based serialize/parse functions can access the raw bytes of the field to preserve + * non-UTF8 bytes in the string. * - *

This ensures the serialize/parse round-trip safety, which is important - * for servers which forward messages. + *

This ensures the serialize/parse round-trip safety, which is important for servers which + * forward messages. */ - private static final class SingularStringFieldAccessor - extends SingularFieldAccessor { + private static final class SingularStringFieldAccessor extends SingularFieldAccessor { SingularStringFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass, final String containingOneofCamelCaseName) { - super(descriptor, camelCaseName, messageClass, builderClass, - containingOneofCamelCaseName); - getBytesMethod = getMethodOrDie(messageClass, - "get" + camelCaseName + "Bytes"); - getBytesMethodBuilder = getMethodOrDie(builderClass, - "get" + camelCaseName + "Bytes"); - setBytesMethodBuilder = getMethodOrDie(builderClass, - "set" + camelCaseName + "Bytes", ByteString.class); + super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); + getBytesMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Bytes"); + getBytesMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Bytes"); + setBytesMethodBuilder = + getMethodOrDie(builderClass, "set" + camelCaseName + "Bytes", ByteString.class); } private final Method getBytesMethod; @@ -2895,19 +2841,17 @@ public abstract class GeneratedMessage extends AbstractMessage // --------------------------------------------------------------- - private static final class SingularMessageFieldAccessor - extends SingularFieldAccessor { + private static final class SingularMessageFieldAccessor extends SingularFieldAccessor { SingularMessageFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass, final String containingOneofCamelCaseName) { - super(descriptor, camelCaseName, messageClass, builderClass, - containingOneofCamelCaseName); + super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); newBuilderMethod = getMethodOrDie(type, "newBuilder"); - getBuilderMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Builder"); + getBuilderMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Builder"); } private final Method newBuilderMethod; @@ -2922,7 +2866,8 @@ public abstract class GeneratedMessage extends AbstractMessage // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).buildPartial(); + .mergeFrom((Message) value) + .buildPartial(); } } @@ -2930,27 +2875,29 @@ public abstract class GeneratedMessage extends AbstractMessage public void set(final Builder builder, final Object value) { super.set(builder, coerceType(value)); } + @Override public Message.Builder newBuilder() { return (Message.Builder) invokeOrDie(newBuilderMethod, null); } + @Override public Message.Builder getBuilder(GeneratedMessage.Builder builder) { return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder); } } - private static final class RepeatedMessageFieldAccessor - extends RepeatedFieldAccessor { + private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAccessor { RepeatedMessageFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); newBuilderMethod = getMethodOrDie(type, "newBuilder"); - getBuilderMethodBuilder = getMethodOrDie(builderClass, - "get" + camelCaseName + "Builder", Integer.TYPE); + getBuilderMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName + "Builder", Integer.TYPE); } private final Method newBuilderMethod; @@ -2965,36 +2912,39 @@ public abstract class GeneratedMessage extends AbstractMessage // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).build(); + .mergeFrom((Message) value) + .build(); } } @Override - public void setRepeated(final Builder builder, - final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { super.setRepeated(builder, index, coerceType(value)); } + @Override public void addRepeated(final Builder builder, final Object value) { super.addRepeated(builder, coerceType(value)); } + @Override public Message.Builder newBuilder() { return (Message.Builder) invokeOrDie(newBuilderMethod, null); } + @Override public Message.Builder getRepeatedBuilder( final GeneratedMessage.Builder builder, final int index) { - return (Message.Builder) invokeOrDie( - getBuilderMethodBuilder, builder, index); + return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder, index); } } } /** - * Replaces this object in the output stream with a serialized form. - * Part of Java's serialization magic. Generated sub-classes must override - * this method by calling {@code return super.writeReplace();} + * Replaces this object in the output stream with a serialized form. Part of Java's serialization + * magic. Generated sub-classes must override this method by calling {@code return + * super.writeReplace();} + * * @return a SerializedForm of this message */ protected Object writeReplace() throws ObjectStreamException { @@ -3002,12 +2952,10 @@ public abstract class GeneratedMessage extends AbstractMessage } /** - * Checks that the {@link Extension} is non-Lite and returns it as a - * {@link GeneratedExtension}. + * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}. */ private static , T> - Extension checkNotLite( - ExtensionLite extension) { + Extension checkNotLite(ExtensionLite extension) { if (extension.isLite()) { throw new IllegalArgumentException("Expected non-lite extension."); } @@ -3040,8 +2988,8 @@ public abstract class GeneratedMessage extends AbstractMessage } } - protected static void writeStringNoTag( - CodedOutputStream output, final Object value) throws IOException { + protected static void writeStringNoTag(CodedOutputStream output, final Object value) + throws IOException { if (value instanceof String) { output.writeStringNoTag((String) value); } else { diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java index 16521e1bdd..be6f97de75 100644 --- a/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java +++ b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java @@ -43,7 +43,7 @@ import java.nio.ByteBuffer; * ByteString} can lead to unexpected and undesirable consequences in your application, and will * likely be difficult to debug. Proceed with caution! * - *

This can have a number of significant side affects that have spooky-action-at-a-distance-like + *

This can have a number of significant side effects that have spooky-action-at-a-distance-like * behavior. In particular, if the bytes value changes out from under a Protocol Buffer: * *

    diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java index 9f36494a71..55e3079f93 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java @@ -101,9 +101,8 @@ public final class FieldMaskUtil { /** * Constructs a FieldMask for a list of field paths in a certain type. * - * @throws IllegalArgumentException if any of the field path is not valid. + * @throws IllegalArgumentException if any of the field path is not valid */ - // TODO(xiaofeng): Consider renaming fromStrings() public static FieldMask fromStringList(Class type, Iterable paths) { return fromStringList(Internal.getDefaultInstance(type).getDescriptorForType(), paths); } diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 8c43e476f9..1a0a51ce34 100644 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -124,7 +124,7 @@ class DescriptorTest(unittest.TestCase): method_descriptor = service_descriptor.FindMethodByName('Foo') self.assertEqual(method_descriptor.name, 'Foo') with self.assertRaises(KeyError): - service_descriptor.FindMethodByName('MethodDoesNotExist') + service_descriptor.FindMethodByName('MethodDoesNotExist') def testEnumValueName(self): self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), diff --git a/src/Makefile.am b/src/Makefile.am index ece3974ad1..9875b1c575 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -177,6 +177,7 @@ nobase_include_HEADERS = \ google/protobuf/util/field_comparator.h \ google/protobuf/util/field_mask_util.h \ google/protobuf/util/json_util.h \ + google/protobuf/util/zero_copy_sink.h \ google/protobuf/util/message_differencer.h \ google/protobuf/util/time_util.h \ google/protobuf/util/type_resolver.h \ @@ -311,6 +312,7 @@ libprotobuf_la_SOURCES = \ google/protobuf/util/internal/utility.cc \ google/protobuf/util/internal/utility.h \ google/protobuf/util/json_util.cc \ + google/protobuf/util/zero_copy_sink.cc \ google/protobuf/util/message_differencer.cc \ google/protobuf/util/time_util.cc \ google/protobuf/util/type_resolver_util.cc \ @@ -829,6 +831,7 @@ protobuf_test_SOURCES = \ google/protobuf/util/internal/protostream_objectwriter_test.cc \ google/protobuf/util/internal/type_info_test_helper.cc \ google/protobuf/util/json_util_test.cc \ + google/protobuf/util/zero_copy_sink_test.cc \ google/protobuf/util/message_differencer_unittest.cc \ google/protobuf/util/time_util_test.cc \ google/protobuf/util/type_resolver_util_test.cc \ diff --git a/src/file_lists.cmake b/src/file_lists.cmake index c849a6236e..32f10b2705 100644 --- a/src/file_lists.cmake +++ b/src/file_lists.cmake @@ -92,6 +92,7 @@ set(libprotobuf_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/util/zero_copy_sink.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.cc @@ -213,6 +214,7 @@ set(libprotobuf_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.h ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver.h ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/util/zero_copy_sink.h ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.h ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.h ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.h @@ -843,6 +845,7 @@ set(util_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util_test.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/util/zero_copy_sink_test.cc ) # //src/google/protobuf/util:test_proto_srcs diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 99be4a3c5e..90136930c9 100644 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -134,14 +134,6 @@ SerialArena::Memory SerialArena::Free(Deallocator deallocator) { return mem; } -PROTOBUF_NOINLINE -std::pair -SerialArena::AllocateAlignedWithCleanupFallback( - size_t n, const AllocationPolicy* policy) { - AllocateNewBlock(n + kCleanupSize, policy); - return AllocateFromExistingWithCleanupFallback(n); -} - PROTOBUF_NOINLINE void* SerialArena::AllocateAlignedFallback(size_t n, const AllocationPolicy* policy) { @@ -161,7 +153,12 @@ void* SerialArena::AllocateAlignedWithCleanupFallback( PROTOBUF_NOINLINE void SerialArena::AddCleanupFallback(void* elem, void (*destructor)(void*), const AllocationPolicy* policy) { +<<<<<<< HEAD AllocateNewBlock(0, policy); +======= + size_t required = cleanup::Size(destructor); + AllocateNewBlock(required, policy); +>>>>>>> 87d285c785cd1a4334e3e21e5d468a9bc3e85f62 AddCleanupFromExisting(elem, destructor); } @@ -466,15 +463,16 @@ uint64_t ThreadSafeArena::Reset() { return space_allocated; } -std::pair -ThreadSafeArena::AllocateAlignedWithCleanup(size_t n, - const std::type_info* type) { +void* ThreadSafeArena::AllocateAlignedWithCleanup(size_t n, size_t align, + void (*destructor)(void*), + const std::type_info* type) { SerialArena* arena; if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() && GetSerialArenaFast(&arena))) { - return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get()); + return arena->AllocateAlignedWithCleanup(n, align, destructor, + alloc_policy_.get()); } else { - return AllocateAlignedWithCleanupFallback(n, type); + return AllocateAlignedWithCleanupFallback(n, align, destructor, type); } } @@ -501,18 +499,19 @@ void* ThreadSafeArena::AllocateAlignedFallback(size_t n, } PROTOBUF_NOINLINE -std::pair -ThreadSafeArena::AllocateAlignedWithCleanupFallback( - size_t n, const std::type_info* type) { +void* ThreadSafeArena::AllocateAlignedWithCleanupFallback( + size_t n, size_t align, void (*destructor)(void*), + const std::type_info* type) { if (alloc_policy_.should_record_allocs()) { - alloc_policy_.RecordAlloc(type, n); + alloc_policy_.RecordAlloc(type, internal::AlignUpTo(n, align)); SerialArena* arena; if (GetSerialArenaFast(&arena)) { - return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get()); + return arena->AllocateAlignedWithCleanup(n, align, destructor, + alloc_policy_.get()); } } return GetSerialArenaFallback(&thread_cache()) - ->AllocateAlignedWithCleanup(n, alloc_policy_.get()); + ->AllocateAlignedWithCleanup(n, align, destructor, alloc_policy_.get()); } uint64_t ThreadSafeArena::SpaceAllocated() const { @@ -584,9 +583,10 @@ void* Arena::AllocateAlignedWithHookForArray(size_t n, } PROTOBUF_FUNC_ALIGN(32) -std::pair -Arena::AllocateAlignedWithCleanup(size_t n, const std::type_info* type) { - return impl_.AllocateAlignedWithCleanup(n, type); +void* Arena::AllocateAlignedWithCleanup(size_t n, size_t align, + void (*destructor)(void*), + const std::type_info* type) { + return impl_.AllocateAlignedWithCleanup(n, align, destructor, type); } } // namespace protobuf diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 0f9f81366f..b629780822 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -90,21 +90,10 @@ class RepeatedPtrFieldBase; // defined in repeated_ptr_field.h template class GenericTypeHandler; // defined in repeated_field.h -inline PROTOBUF_ALWAYS_INLINE -void* AlignTo(void* ptr, size_t align) { - return reinterpret_cast( - (reinterpret_cast(ptr) + align - 1) & (~align + 1)); -} - -// Templated cleanup methods. -template -void arena_destruct_object(void* object) { - reinterpret_cast(object)->~T(); -} - template struct ObjectDestructor { - constexpr static void (*destructor)(void*) = &arena_destruct_object; + constexpr static void (*destructor)(void*) = + &internal::cleanup::arena_destruct_object; }; template @@ -368,9 +357,12 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // sizes of the underlying blocks. uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); } // Returns the total space used by the arena. Similar to SpaceAllocated but - // does not include free space and block overhead. The total space returned - // may not include space used by other threads executing concurrently with - // the call to this method. + // does not include free space and block overhead. This is a best-effort + // estimate and may inaccurately calculate space used by other threads + // executing concurrently with the call to this method. These inaccuracies + // are due to race conditions, and are bounded but unpredictable. Stale data + // can lead to underestimates of the space used, and race conditions can lead + // to overestimates (up to the current block size). uint64_t SpaceUsed() const { return impl_.SpaceUsed(); } // Frees all storage allocated by this arena after calling destructors @@ -395,7 +387,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { template PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) { if (object != NULL) { - impl_.AddCleanup(object, &internal::arena_destruct_object); + impl_.AddCleanup(object, &internal::cleanup::arena_destruct_object); } } @@ -420,7 +412,18 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { template class InternalHelper { private: - struct Rank1 {}; + // A SFINAE friendly trait that probes for `U` but always evalues to + // `Arena*`. + template + using EnableIfArena = + typename std::enable_if::value, Arena*>::type; + + // Rather than use SFINAE that must fully cover the space of options in a + // mutually exclusive fashion, we use implicit conversions to base classes + // to force an explicit ranking for our preferences. The lowest ranked + // version that compiles will be accepted. + struct Rank2 {}; + struct Rank1 : Rank2 {}; struct Rank0 : Rank1 {}; static Arena* GetOwningArena(const T* p) { @@ -429,7 +432,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { template static auto GetOwningArena(Rank0, const U* p) - -> decltype(p->GetOwningArena()) { + -> EnableIfArenaGetOwningArena())> { return p->GetOwningArena(); } @@ -440,35 +443,31 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { static void InternalSwap(T* a, T* b) { a->InternalSwap(b); } - static Arena* GetArenaForAllocationInternal( - const T* p, std::true_type /*is_derived_from*/) { - return p->GetArenaForAllocation(); + static Arena* GetArenaForAllocation(const T* p) { + return GetArenaForAllocation(Rank0{}, p); } - static Arena* GetArenaForAllocationInternal( - const T* p, std::false_type /*is_derived_from*/) { - return GetArenaForAllocationForNonMessage( - p, typename is_arena_constructable::type()); + static Arena* GetArena(const T* p) { + // Rather than replicate probing for `GetArena` with fallback to nullptr, + // we borrow the implementation of `GetArenaForAllocation` but skip + // `Rank0` which probes for `GetArenaForAllocation`. + return GetArenaForAllocation(Rank1{}, p); } - static Arena* GetArenaForAllocationForNonMessage( - const T* p, std::true_type /*is_arena_constructible*/) { - return p->GetArena(); - } - - static Arena* GetArenaForAllocationForNonMessage( - const T* p, std::false_type /*is_arena_constructible*/) { - return GetArenaForAllocationForNonMessageNonArenaConstructible( - p, typename has_get_arena::type()); + template + static auto GetArenaForAllocation(Rank0, const U* p) + -> EnableIfArenaGetArenaForAllocation())> { + return p->GetArenaForAllocation(); } - static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible( - const T* p, std::true_type /*has_get_arena*/) { + template + static auto GetArenaForAllocation(Rank1, const U* p) + -> EnableIfArenaGetArena())> { return p->GetArena(); } - static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible( - const T* /* p */, std::false_type /*has_get_arena*/) { + template + static Arena* GetArenaForAllocation(Rank2, const U* p) { return nullptr; } @@ -494,18 +493,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { sizeof(char)> is_arena_constructable; - template () - .GetArena())>::value, - int>::type = 0> - static char HasGetArena(decltype(&U::GetArena)); - template - static double HasGetArena(...); - - typedef std::integral_constant(nullptr)) == - sizeof(char)> - has_get_arena; template static T* Construct(void* ptr, Args&&... args) { @@ -516,8 +503,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { return new T(nullptr); } - static Arena* GetArena(const T* p) { return p->GetArena(); } - friend class Arena; friend class TestUtil::ReflectionTester; }; @@ -533,8 +518,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // For internal use only. template static Arena* InternalGetArenaForAllocation(const T* p) { - return InternalHelper::GetArenaForAllocationInternal( - p, std::is_convertible()); + return InternalHelper::GetArenaForAllocation(p); } // Creates message-owned arena. For internal use only. @@ -566,9 +550,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { private: internal::ThreadSafeArena impl_; - template - struct has_get_arena : InternalHelper::has_get_arena {}; - // Constructor solely used by message-owned arena. inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {} @@ -620,18 +601,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { if (destructor == nullptr) { return AllocateAlignedWithHook(size, align, type); } else { - if (align <= 8) { - auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type); - res.second->elem = res.first; - res.second->cleanup = destructor; - return res.first; - } else { - auto res = AllocateAlignedWithCleanup(size + align - 8, type); - auto ptr = internal::AlignTo(res.first, align); - res.second->elem = ptr; - res.second->cleanup = destructor; - return ptr; - } + return AllocateAlignedWithCleanup(size, align, destructor, type); } } @@ -774,26 +744,10 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // Implementation for GetArena(). Only message objects with // InternalArenaConstructable_ tags can be associated with an arena, and such // objects must implement a GetArena() method. - template ::value, int>::type = 0> + template PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { return InternalHelper::GetArena(value); } - template ::value && - has_get_arena::value, - int>::type = 0> - PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { - return value->GetArena(); - } - template ::value && - !has_get_arena::value, - int>::type = 0> - PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { - (void)value; - return nullptr; - } void* AllocateAlignedWithHookForArray(size_t n, size_t align, const std::type_info* type) { @@ -828,8 +782,9 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { void* AllocateAlignedNoHook(size_t n); void* AllocateAlignedWithHook(size_t n, const std::type_info* type); void* AllocateAlignedWithHookForArray(size_t n, const std::type_info* type); - std::pair - AllocateAlignedWithCleanup(size_t n, const std::type_info* type); + void* AllocateAlignedWithCleanup(size_t n, size_t align, + void (*destructor)(void*), + const std::type_info* type); template friend class internal::GenericTypeHandler; diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h index 76727688b5..2b71b3c7f1 100644 --- a/src/google/protobuf/arena_impl.h +++ b/src/google/protobuf/arena_impl.h @@ -35,12 +35,14 @@ #include #include +#include #include #include #include #include + #ifdef ADDRESS_SANITIZER #include #endif // ADDRESS_SANITIZER @@ -62,11 +64,148 @@ enum { kCacheAlignment = 64 }; enum { kCacheAlignment = alignof(max_align_t) }; // do the best we can #endif -inline constexpr size_t AlignUpTo8(size_t n) { +inline PROTOBUF_ALWAYS_INLINE constexpr size_t AlignUpTo8(size_t n) { // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.) return (n + 7) & static_cast(-8); } +inline PROTOBUF_ALWAYS_INLINE constexpr size_t AlignUpTo(size_t n, size_t a) { + // We are wasting space by over allocating align - 8 bytes. Compared to a + // dedicated function that takes current alignment in consideration. Such a + // scheme would only waste (align - 8)/2 bytes on average, but requires a + // dedicated function in the outline arena allocation functions. Possibly + // re-evaluate tradeoffs later. + return a <= 8 ? AlignUpTo8(n) : n + a - 8; +} + +inline PROTOBUF_ALWAYS_INLINE void* AlignTo(void* p, size_t a) { + if (a <= 8) { + return p; + } else { + auto u = reinterpret_cast(p); + return reinterpret_cast((u + a - 1) & (~a + 1)); + } +} + +namespace cleanup { + +template +void arena_destruct_object(void* object) { + reinterpret_cast(object)->~T(); +} + +enum class Tag : uintptr_t { + kDynamic = 0, // {void* elem, void (*destructor)(void*)} + kString = 1, // std::string* | kString +}; + +constexpr bool EnableSpecializedTags() { + return alignof(std::string) >= 8 + ; +} + +// All node types must start with a `uintptr_t` that stores `Tag` in its low +// two bits. +struct DynamicNode { + uintptr_t elem; + void (*destructor)(void*); +}; + +struct StringNode { + uintptr_t elem; +}; + + +inline PROTOBUF_ALWAYS_INLINE void CreateNode(Tag tag, void* pos, + const void* elem, + void (*destructor)(void*)) { + if (EnableSpecializedTags()) { + switch (tag) { + case Tag::kString: { + StringNode n = {reinterpret_cast(elem) | + static_cast(Tag::kString)}; + memcpy(pos, &n, sizeof(n)); + return; + } + default: + break; + } + } + DynamicNode n = {reinterpret_cast(elem), destructor}; + memcpy(pos, &n, sizeof(n)); +} + +inline PROTOBUF_ALWAYS_INLINE void PrefetchNode(const void* elem_address) { + (void)elem_address; +} + +inline PROTOBUF_ALWAYS_INLINE void DestroyNode(Tag tag, const void* pos) { + if (EnableSpecializedTags()) { + switch (tag) { + case Tag::kString: { + StringNode n; + memcpy(&n, pos, sizeof(n)); + auto* s = reinterpret_cast(n.elem & ~0x7ULL); + // Some compilers don't like fully qualified explicit dtor calls, + // so use an alias to avoid having to type `::`. + using string_type = std::string; + s->~string_type(); + return; + } + default: + break; + } + } + DynamicNode n; + memcpy(&n, pos, sizeof(n)); + n.destructor(reinterpret_cast(n.elem)); +} + +inline PROTOBUF_ALWAYS_INLINE Tag Type(void (*destructor)(void*)) { + if (EnableSpecializedTags()) { + if (destructor == &arena_destruct_object) { + return Tag::kString; + } + } + return Tag::kDynamic; +} + +inline PROTOBUF_ALWAYS_INLINE Tag Type(void* raw) { + if (!EnableSpecializedTags()) return Tag::kDynamic; + + uintptr_t elem; + memcpy(&elem, raw, sizeof(elem)); + switch (static_cast(elem & 0x7ULL)) { + case Tag::kDynamic: + return Tag::kDynamic; + case Tag::kString: + return Tag::kString; + default: + GOOGLE_LOG(FATAL) << "Corrupted cleanup tag: " << (elem & 0x7ULL); + return Tag::kDynamic; + } +} + +inline PROTOBUF_ALWAYS_INLINE size_t Size(Tag tag) { + if (!EnableSpecializedTags()) return sizeof(DynamicNode); + + switch (tag) { + case Tag::kDynamic: + return sizeof(DynamicNode); + case Tag::kString: + return sizeof(StringNode); + default: + GOOGLE_LOG(FATAL) << "Corrupted cleanup tag: " << static_cast(tag); + return sizeof(DynamicNode); + } +} + +inline PROTOBUF_ALWAYS_INLINE size_t Size(void (*destructor)(void*)) { + return destructor == nullptr ? 0 : Size(Type(destructor)); +} + +} // namespace cleanup + using LifecycleIdAtomic = uint64_t; // MetricsCollector collects stats for a particular arena. @@ -198,7 +337,7 @@ enum class AllocationClient { kDefault, kArray }; // This class manages // 1) Arena bump allocation + owning memory blocks. // 2) Maintaining a cleanup list. -// It delagetes the actual memory allocation back to ThreadSafeArena, which +// It delegates the actual memory allocation back to ThreadSafeArena, which // contains the information on block growth policy and backing memory allocation // used. class PROTOBUF_EXPORT SerialArena { @@ -208,13 +347,6 @@ class PROTOBUF_EXPORT SerialArena { size_t size; }; - // Node contains the ptr of the object to be cleaned up and the associated - // cleanup function ptr. - struct CleanupNode { - void* elem; // Pointer to the object to be cleaned up. - void (*cleanup)(void*); // Function pointer to the destructor or deleter. - }; - void CleanupList(); uint64_t SpaceAllocated() const { return space_allocated_.load(std::memory_order_relaxed); @@ -222,7 +354,7 @@ class PROTOBUF_EXPORT SerialArena { uint64_t SpaceUsed() const; bool HasSpace(size_t n) const { - return n <= static_cast(limit_ - ptr_); + return n <= static_cast(limit_ - ptr()); } // See comments on `cached_blocks_` member for details. @@ -254,7 +386,7 @@ class PROTOBUF_EXPORT SerialArena { template void* AllocateAligned(size_t n, const AllocationPolicy* policy) { GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. - GOOGLE_DCHECK_GE(limit_, ptr_); + GOOGLE_DCHECK_GE(limit_, ptr()); if (alloc_client == AllocationClient::kArray) { if (void* res = TryAllocateFromCachedBlock(n)) { @@ -270,11 +402,11 @@ class PROTOBUF_EXPORT SerialArena { private: void* AllocateFromExisting(size_t n) { - void* ret = ptr_; - ptr_ += n; #ifdef ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(ret, n); + ASAN_UNPOISON_MEMORY_REGION(ptr(), n); #endif // ADDRESS_SANITIZER + void* ret = ptr(); + set_ptr(static_cast(ret) + n); return ret; } @@ -303,7 +435,16 @@ class PROTOBUF_EXPORT SerialArena { std::copy(cached_blocks_, cached_blocks_ + cached_block_length_, new_list); + +#ifdef ADDRESS_SANITIZER + // We need to unpoison this memory before filling it in case it has been + // poisoned by another santizer client. + ASAN_UNPOISON_MEMORY_REGION( + new_list + cached_block_length_, + (new_size - cached_block_length_) * sizeof(CachedBlock*)); +#endif std::fill(new_list + cached_block_length_, new_list + new_size, nullptr); + cached_blocks_ = new_list; // Make the size fit in uint8_t. This is the power of two, so we don't // need anything larger. @@ -326,42 +467,61 @@ class PROTOBUF_EXPORT SerialArena { // Allocate space if the current region provides enough space. bool MaybeAllocateAligned(size_t n, void** out) { GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. - GOOGLE_DCHECK_GE(limit_, ptr_); + GOOGLE_DCHECK_GE(limit_, ptr()); if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false; *out = AllocateFromExisting(n); return true; } - std::pair AllocateAlignedWithCleanup( - size_t n, const AllocationPolicy* policy) { - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. - if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) { - return AllocateAlignedWithCleanupFallback(n, policy); + PROTOBUF_ALWAYS_INLINE + void* AllocateAlignedWithCleanup(size_t n, size_t align, + void (*destructor)(void*), + const AllocationPolicy* policy) { + size_t required = AlignUpTo(n, align) + cleanup::Size(destructor); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(required))) { + return AllocateAlignedWithCleanupFallback(n, align, destructor, policy); } - return AllocateFromExistingWithCleanupFallback(n); + return AllocateFromExistingWithCleanupFallback(n, align, destructor); + } + + PROTOBUF_ALWAYS_INLINE + void AddCleanup(void* elem, void (*destructor)(void*), + const AllocationPolicy* policy) { + size_t required = cleanup::Size(destructor); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(required))) { + return AddCleanupFallback(elem, destructor, policy); + } + AddCleanupFromExisting(elem, destructor); } private: - std::pair AllocateFromExistingWithCleanupFallback( - size_t n) { - void* ret = ptr_; - ptr_ += n; - limit_ -= kCleanupSize; + void* AllocateFromExistingWithCleanupFallback(size_t n, size_t align, + void (*destructor)(void*)) { + n = AlignUpTo(n, align); #ifdef ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(ret, n); - ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize); + ASAN_UNPOISON_MEMORY_REGION(ptr_, n); #endif // ADDRESS_SANITIZER - return CreatePair(ret, reinterpret_cast(limit_)); + void* ret = internal::AlignTo(ptr_, align); + ptr_ += n; + GOOGLE_DCHECK_GE(limit_, ptr_); + AddCleanupFromExisting(ret, destructor); + return ret; } - public: - void AddCleanup(void* elem, void (*cleanup)(void*), - const AllocationPolicy* policy) { - auto res = AllocateAlignedWithCleanup(0, policy); - res.second->elem = elem; - res.second->cleanup = cleanup; + PROTOBUF_ALWAYS_INLINE + void AddCleanupFromExisting(void* elem, void (*destructor)(void*)) { + cleanup::Tag tag = cleanup::Type(destructor); + size_t n = cleanup::Size(tag); + +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(limit_ - n, n); +#endif // ADDRESS_SANITIZER + limit_ -= n; + GOOGLE_DCHECK_GE(limit_, ptr_); + cleanup::CreateNode(tag, limit_, elem, destructor); } + public: void* owner() const { return owner_; } SerialArena* next() const { return next_; } void set_next(SerialArena* next) { next_ = next; } @@ -381,29 +541,45 @@ class PROTOBUF_EXPORT SerialArena { // Blocks are variable length malloc-ed objects. The following structure // describes the common header for all blocks. struct Block { - Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {} + Block(Block* next, size_t size) + : next(next), cleanup_nodes(nullptr), relaxed_size(size) {} char* Pointer(size_t n) { - GOOGLE_DCHECK(n <= size); + GOOGLE_DCHECK(n <= size()); return reinterpret_cast(this) + n; } + size_t size() const { return relaxed_size.load(std::memory_order_relaxed); } + Block* const next; - const size_t size; - CleanupNode* start; + void* cleanup_nodes; + + private: + const std::atomic relaxed_size; // data follows }; void* owner_; // &ThreadCache of this thread; - Block* head_; // Head of linked list of blocks. + std::atomic head_; // Head of linked list of blocks. SerialArena* next_; // Next SerialArena in this linked list. - size_t space_used_ = 0; // Necessary for metrics. + std::atomic space_used_{0}; // Necessary for metrics. std::atomic space_allocated_; // Next pointer to allocate from. Always 8-byte aligned. Points inside // head_ (and head_->pos will always be non-canonical). We keep these // here to reduce indirection. - char* ptr_; + std::atomic ptr_; + + // Helper getters/setters to handle relaxed operations on atomic variables. + Block* head() { return head_.load(std::memory_order_relaxed); } + const Block* head() const { return head_.load(std::memory_order_relaxed); } + void set_head(Block* head) { + return head_.store(head, std::memory_order_relaxed); + } + char* ptr() { return ptr_.load(std::memory_order_relaxed); } + const char* ptr() const { return ptr_.load(std::memory_order_relaxed); } + void set_ptr(char* ptr) { return ptr_.store(ptr, std::memory_order_relaxed); } + // Limiting address up to which memory can be allocated from the head block. char* limit_; // For holding sampling information. The pointer is owned by the @@ -427,17 +603,15 @@ class PROTOBUF_EXPORT SerialArena { // Constructor is private as only New() should be used. inline SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats); void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy); - std::pair AllocateAlignedWithCleanupFallback( - size_t n, const AllocationPolicy* policy); + void* AllocateAlignedWithCleanupFallback(size_t n, size_t align, + void (*destructor)(void*), + const AllocationPolicy* policy); + void AddCleanupFallback(void* elem, void (*destructor)(void*), + const AllocationPolicy* policy); void AllocateNewBlock(size_t n, const AllocationPolicy* policy); - std::pair CreatePair(void* ptr, CleanupNode* node) { - return {ptr, node}; - } - public: static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block)); - static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode)); }; // Tag type used to invoke the constructor of message-owned arena. @@ -469,6 +643,13 @@ class PROTOBUF_EXPORT ThreadSafeArena { InitializeWithPolicy(mem, size, policy); } + // All protos have pointers back to the arena hence Arena must have + // pointer stability. + ThreadSafeArena(const ThreadSafeArena&) = delete; + ThreadSafeArena& operator=(const ThreadSafeArena&) = delete; + ThreadSafeArena(ThreadSafeArena&&) = delete; + ThreadSafeArena& operator=(ThreadSafeArena&&) = delete; + // Destructor deletes all owned heap allocated objects, and destructs objects // that have non-trivial destructors, except for proto2 message objects whose // destructors can be skipped. Also, frees all blocks except the initial block @@ -506,14 +687,15 @@ class PROTOBUF_EXPORT ThreadSafeArena { PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) { SerialArena* arena; if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() && - GetSerialArenaFromThreadCache(&arena))) { + GetSerialArenaFast(&arena))) { return arena->MaybeAllocateAligned(n, out); } return false; } - std::pair AllocateAlignedWithCleanup( - size_t n, const std::type_info* type); + void* AllocateAlignedWithCleanup(size_t n, size_t align, + void (*destructor)(void*), + const std::type_info* type); // Add object pointer and cleanup function pointer to the list. void AddCleanup(void* elem, void (*cleanup)(void*)); @@ -524,6 +706,8 @@ class PROTOBUF_EXPORT ThreadSafeArena { } private: + static uint64_t GetNextLifeCycleId(); + // Unique for each arena. Changes on Reset(). uint64_t tag_and_id_ = 0; // The LSB of tag_and_id_ indicates if the arena is message-owned. @@ -535,14 +719,14 @@ class PROTOBUF_EXPORT ThreadSafeArena { "SerialArena needs to be trivially destructible."); // Pointer to a linked list of SerialArena. std::atomic threads_; - std::atomic hint_; // Fast thread-local block access const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); } void InitializeFrom(void* mem, size_t size); void InitializeWithPolicy(void* mem, size_t size, AllocationPolicy policy); void* AllocateAlignedFallback(size_t n, const std::type_info* type); - std::pair - AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type); + void* AllocateAlignedWithCleanupFallback(size_t n, size_t align, + void (*destructor)(void*), + const std::type_info* type); void Init(); void SetInitialBlock(void* mem, size_t size); @@ -550,36 +734,14 @@ class PROTOBUF_EXPORT ThreadSafeArena { // Delete or Destruct all objects owned by the arena. void CleanupList(); - inline uint64_t LifeCycleId() const { - return tag_and_id_ & ~kMessageOwnedArena; - } - inline void CacheSerialArena(SerialArena* serial) { - thread_cache().last_serial_arena = serial; - thread_cache().last_lifecycle_id_seen = tag_and_id_; - // TODO(haberman): evaluate whether we would gain efficiency by getting rid - // of hint_. It's the only write we do to ThreadSafeArena in the allocation - // path, which will dirty the cache line. - - hint_.store(serial, std::memory_order_release); - } - - PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) { - if (GetSerialArenaFromThreadCache(arena)) return true; - - // Check whether we own the last accessed SerialArena on this arena. This - // fast path optimizes the case where a single thread uses multiple arenas. - ThreadCache* tc = &thread_cache(); - SerialArena* serial = hint_.load(std::memory_order_acquire); - if (PROTOBUF_PREDICT_TRUE(serial != nullptr && serial->owner() == tc)) { - *arena = serial; - return true; + if (!IsMessageOwned()) { + thread_cache().last_serial_arena = serial; + thread_cache().last_lifecycle_id_seen = tag_and_id_; } - return false; } - PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache( - SerialArena** arena) { + PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) { // If this thread already owns a block in this arena then try to use that. // This fast path optimizes the case where multiple threads allocate from // the same arena. @@ -659,12 +821,6 @@ class PROTOBUF_EXPORT ThreadSafeArena { ThreadSafeArenaStatsHandle arena_stats_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena); - // All protos have pointers back to the arena hence Arena must have - // pointer stability. - ThreadSafeArena(ThreadSafeArena&&) = delete; - ThreadSafeArena& operator=(ThreadSafeArena&&) = delete; - public: // kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 // to protect the invariant that pos is always at a multiple of 8. diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc index 65da0d3d4d..03b1438b44 100644 --- a/src/google/protobuf/arenastring.cc +++ b/src/google/protobuf/arenastring.cc @@ -125,8 +125,7 @@ void ArenaStringPtr::Set(ConstStringParam value, Arena* arena) { } else { #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING if (arena == nullptr) { - GOOGLE_DCHECK(tagged_ptr_.IsAllocated()); - auto* old = tagged_ptr_.Get(); + auto* old = tagged_ptr_.GetIfAllocated(); tagged_ptr_ = CreateString(value); delete old; } else { diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 5e9a2c4185..a688bcfb06 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1276,6 +1276,7 @@ bool CommandLineInterface::ParseInputFiles( } parsed_files->push_back(parsed_file); + // Enforce --disallow_services. if (disallow_services_ && parsed_file->service_count() > 0) { std::cerr << parsed_file->name() diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index e8425508b1..8064b397f8 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -398,7 +398,7 @@ class PROTOC_EXPORT CommandLineInterface { // True if we should treat warnings as errors that fail the compilation. bool fatal_warnings_ = false; - std::vector > + std::vector> proto_path_; // Search path for proto files. std::vector input_files_; // Names of the input proto files. diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc index 90d20848b3..cf4f14e8bf 100644 --- a/src/google/protobuf/compiler/cpp/field.cc +++ b/src/google/protobuf/compiler/cpp/field.cc @@ -330,6 +330,7 @@ void FieldGenerator::GenerateCopyConstructorCode(io::Printer* printer) const { } } + void SetCommonOneofFieldVariables( const FieldDescriptor* descriptor, std::map* variables) { diff --git a/src/google/protobuf/compiler/cpp/field.h b/src/google/protobuf/compiler/cpp/field.h index 3fcbda371c..3903e79862 100644 --- a/src/google/protobuf/compiler/cpp/field.h +++ b/src/google/protobuf/compiler/cpp/field.h @@ -208,6 +208,7 @@ class FieldGenerator { virtual bool IsInlined() const { return false; } + virtual ArenaDtorNeeds NeedsArenaDestructor() const { return ArenaDtorNeeds::kNone; } diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc index 4b7c5c9d91..2eb20cf057 100644 --- a/src/google/protobuf/compiler/cpp/helpers.cc +++ b/src/google/protobuf/compiler/cpp/helpers.cc @@ -76,7 +76,8 @@ std::string DotsToColons(const std::string& name) { return StringReplace(name, ".", "::", true); } -static const char* const kKeywordList[] = { // +static const char* const kKeywordList[] = { + // "NULL", "alignas", "alignof", @@ -159,7 +160,21 @@ static const char* const kKeywordList[] = { // "wchar_t", "while", "xor", - "xor_eq"}; + "xor_eq", +#ifdef PROTOBUF_FUTURE_CPP20_KEYWORDS // C++20 keywords. + "char8_t", + "char16_t", + "char32_t", + "concept", + "consteval", + "constinit", + "co_await", + "co_return", + "co_yield", + "requires", +#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES +}; + static std::unordered_set* MakeKeywordsMap() { auto* result = new std::unordered_set(); @@ -509,6 +524,7 @@ std::string FieldName(const FieldDescriptor* field) { return result; } + std::string FieldMemberName(const FieldDescriptor* field, bool split) { StringPiece prefix = IsMapEntryMessage(field->containing_type()) ? "" : "_impl_."; @@ -856,6 +872,7 @@ std::string SafeFunctionName(const Descriptor* descriptor, return function_name; } + bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options) { (void)descriptor; diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index af463d58ac..72fde8308a 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -790,38 +790,41 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { std::map vars; SetCommonFieldVariables(field, &vars, options_); + format.AddMap(vars); - if (field->is_repeated()) { - format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field, - !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); - if (!IsFieldStripped(field, options_)) { - format( - "private:\n" - "int ${1$_internal_$name$_size$}$() const;\n" - "public:\n", - field); - } - } else if (HasHasMethod(field)) { - format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field, - !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); - if (!IsFieldStripped(field, options_)) { + if (field->is_repeated()) { format( - "private:\n" - "bool _internal_has_$name$() const;\n" - "public:\n"); - } - } else if (HasPrivateHasMethod(field)) { - if (!IsFieldStripped(field, options_)) { + "$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field, + !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); + if (!IsFieldStripped(field, options_)) { + format( + "private:\n" + "int ${1$_internal_$name$_size$}$() const;\n" + "public:\n", + field); + } + } else if (HasHasMethod(field)) { format( - "private:\n" - "bool ${1$_internal_has_$name$$}$() const;\n" - "public:\n", - field); + "$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field, + !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); + if (!IsFieldStripped(field, options_)) { + format( + "private:\n" + "bool _internal_has_$name$() const;\n" + "public:\n"); + } + } else if (HasPrivateHasMethod(field)) { + if (!IsFieldStripped(field, options_)) { + format( + "private:\n" + "bool ${1$_internal_has_$name$$}$() const;\n" + "public:\n", + field); + } } - } - format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field, - !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}"); + format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field, + !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}"); // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); @@ -1235,37 +1238,36 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { Formatter::SaveState saver(&format); format.AddMap(vars); - - // Generate has_$name$() or $name$_size(). - if (field->is_repeated()) { - if (IsFieldStripped(field, options_)) { - format( - "inline int $classname$::$name$_size() const { " - "__builtin_trap(); }\n"); + // Generate has_$name$() or $name$_size(). + if (field->is_repeated()) { + if (IsFieldStripped(field, options_)) { + format( + "inline int $classname$::$name$_size() const { " + "__builtin_trap(); }\n"); + } else { + format( + "inline int $classname$::_internal_$name$_size() const {\n" + " return $field$$1$.size();\n" + "}\n" + "inline int $classname$::$name$_size() const {\n" + "$annotate_size$" + " return _internal_$name$_size();\n" + "}\n", + IsImplicitWeakField(field, options_, scc_analyzer_) && + field->message_type() + ? ".weak" + : ""); + } + } else if (field->real_containing_oneof()) { + format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); + format.Set("oneof_name", field->containing_oneof()->name()); + format.Set("oneof_index", + StrCat(field->containing_oneof()->index())); + GenerateOneofMemberHasBits(field, format); } else { - format( - "inline int $classname$::_internal_$name$_size() const {\n" - " return $field$$1$.size();\n" - "}\n" - "inline int $classname$::$name$_size() const {\n" - "$annotate_size$" - " return _internal_$name$_size();\n" - "}\n", - IsImplicitWeakField(field, options_, scc_analyzer_) && - field->message_type() - ? ".weak" - : ""); + // Singular field. + GenerateSingularFieldHasBits(field, format); } - } else if (field->real_containing_oneof()) { - format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); - format.Set("oneof_name", field->containing_oneof()->name()); - format.Set("oneof_index", - StrCat(field->containing_oneof()->index())); - GenerateOneofMemberHasBits(field, format); - } else { - // Singular field. - GenerateSingularFieldHasBits(field, format); - } if (!IsCrossFileMaybeMap(field)) { GenerateFieldClear(field, true, format); diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 5bd37d147b..f220fad8be 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -634,14 +634,17 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { root_location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::OTHER); - if (require_syntax_identifier_ || LookingAt("syntax")) { + if (require_syntax_identifier_ || LookingAt("syntax") + ) { if (!ParseSyntaxIdentifier(root_location)) { // Don't attempt to parse the file if we didn't recognize the syntax // identifier. return false; } // Store the syntax into the file. - if (file != nullptr) file->set_syntax(syntax_identifier_); + if (file != nullptr) { + file->set_syntax(syntax_identifier_); + } } else if (!stop_after_syntax_identifier_) { GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: " << file->name() << ". Please use 'syntax = \"proto2\";' " @@ -678,9 +681,10 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { LocationRecorder syntax_location(parent, FileDescriptorProto::kSyntaxFieldNumber); - DO(Consume( - "syntax", - "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'.")); + DO(Consume("syntax", + "File must begin with a syntax statement, e.g. 'syntax = " + "\"proto2\";'.")); + DO(Consume("=")); io::Tokenizer::Token syntax_token = input_->current(); std::string syntax; @@ -688,7 +692,6 @@ bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { DO(ConsumeEndOfDeclaration(";", &syntax_location)); syntax_identifier_ = syntax; - if (syntax != "proto2" && syntax != "proto3" && !stop_after_syntax_identifier_) { AddError(syntax_token.line, syntax_token.column, diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 2d681d957f..55ed7acb6f 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -264,6 +264,7 @@ TEST_F(ParserTest, WarnIfFieldNameContainsNumberImmediatelyFollowUnderscore) { "song_name_1.") != std::string::npos); } + // =================================================================== typedef ParserTest ParseMessageTest; diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 5f3427dc72..139e6f892f 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -2562,7 +2562,9 @@ void FileDescriptor::CopyTo(FileDescriptorProto* proto) const { proto->set_name(name()); if (!package().empty()) proto->set_package(package()); // TODO(liujisi): Also populate when syntax="proto2". - if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax())); + if (syntax() == SYNTAX_PROTO3 + ) proto->set_syntax(SyntaxName(syntax())); + for (int i = 0; i < dependency_count(); i++) { proto->add_dependency(dependency(i)->name()); @@ -4982,7 +4984,8 @@ static void PlanAllocationSize(const FileDescriptorProto& proto, internal::FlatAllocator& alloc) { alloc.PlanArray(1); alloc.PlanArray(1); - alloc.PlanArray(2); // name + package + alloc.PlanArray(2 + ); // name + package if (proto.has_options()) alloc.PlanArray(1); if (proto.has_source_code_info()) alloc.PlanArray(1); diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 1b8728ec63..685e9235d8 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -54,6 +54,9 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ #define GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#include + +#include #include #include @@ -1702,7 +1705,7 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor); }; -PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FileDescriptor, 144); +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FileDescriptor, 152); // =================================================================== diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index c77c83c1e9..2dfece5b61 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -48,6 +48,7 @@ PROTOBUF_CONSTEXPR FileDescriptorProto::FileDescriptorProto( , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} , /*decltype(_impl_.package_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} , /*decltype(_impl_.syntax_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.edition_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} , /*decltype(_impl_.options_)*/nullptr , /*decltype(_impl_.source_code_info_)*/nullptr} {} struct FileDescriptorProtoDefaultTypeInternal { @@ -540,6 +541,7 @@ const uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PRO PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.options_), PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.source_code_info_), PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.syntax_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.edition_), 0, 1, ~0u, @@ -549,9 +551,10 @@ const uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PRO ~0u, ~0u, ~0u, - 3, 4, + 5, 2, + 3, PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _internal_metadata_), ~0u, // no _extensions_ @@ -977,32 +980,32 @@ const uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PRO }; static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet)}, - { 9, 29, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto)}, - { 41, 52, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)}, - { 55, 65, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)}, - { 67, 85, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto)}, - { 95, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)}, - { 104, 123, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)}, - { 134, 144, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)}, - { 146, 156, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)}, - { 158, 171, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)}, - { 176, 187, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)}, - { 190, 201, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)}, - { 204, 218, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)}, - { 224, 253, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileOptions)}, - { 274, 287, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MessageOptions)}, - { 292, 308, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldOptions)}, - { 316, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofOptions)}, - { 325, 336, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumOptions)}, - { 339, 349, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueOptions)}, - { 351, 361, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceOptions)}, - { 363, 374, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodOptions)}, - { 377, 387, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)}, - { 389, 404, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption)}, - { 411, 424, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)}, - { 429, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo)}, - { 438, 450, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)}, - { 454, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)}, + { 9, 30, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto)}, + { 43, 54, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)}, + { 57, 67, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)}, + { 69, 87, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto)}, + { 97, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)}, + { 106, 125, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)}, + { 136, 146, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)}, + { 148, 158, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)}, + { 160, 173, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)}, + { 178, 189, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)}, + { 192, 203, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)}, + { 206, 220, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)}, + { 226, 255, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileOptions)}, + { 276, 289, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MessageOptions)}, + { 294, 310, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldOptions)}, + { 318, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofOptions)}, + { 327, 338, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumOptions)}, + { 341, 351, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueOptions)}, + { 353, 363, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceOptions)}, + { 365, 376, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodOptions)}, + { 379, 389, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)}, + { 391, 406, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption)}, + { 413, 426, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)}, + { 431, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo)}, + { 440, 452, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)}, + { 456, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)}, }; static const ::_pb::Message* const file_default_instances[] = { @@ -1039,7 +1042,7 @@ const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PR "\n google/protobuf/descriptor.proto\022\017goog" "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" - "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" + "roto\"\354\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" @@ -1051,147 +1054,148 @@ const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PR "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001" - "(\t\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005" - "field\030\002 \003(\0132%.google.protobuf.FieldDescr" - "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p" - "rotobuf.FieldDescriptorProto\0225\n\013nested_t" - "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr" - "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf" - ".EnumDescriptorProto\022H\n\017extension_range\030" - "\005 \003(\0132/.google.protobuf.DescriptorProto." - "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo" - "gle.protobuf.OneofDescriptorProto\0220\n\007opt" - "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti" - "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro" - "tobuf.DescriptorProto.ReservedRange\022\025\n\rr" - "eserved_name\030\n \003(\t\032e\n\016ExtensionRange\022\r\n\005" - "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003 \001(" - "\0132&.google.protobuf.ExtensionRangeOption" - "s\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end" - "\030\002 \001(\005\"g\n\025ExtensionRangeOptions\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\325\005\n\024Fiel" - "dDescriptorProto\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." - "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016" - "2*.google.protobuf.FieldDescriptorProto." - "Type\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\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(" - "\0132\035.google.protobuf.FieldOptions\022\027\n\017prot" - "o3_optional\030\021 \001(\010\"\266\002\n\004Type\022\017\n\013TYPE_DOUBL" - "E\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013T" - "YPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIX" - "ED64\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_GROUP\020\n\022\020\n\014TYPE" - "_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT3" - "2\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\013TYP" - "E_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022" - "\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"" - "T\n\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\022.\n" - "\007options\030\002 \001(\0132\035.google.protobuf.OneofOp" - "tions\"\244\002\n\023EnumDescriptorProto\022\014\n\004name\030\001 " - "\001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.Enu" - "mValueDescriptorProto\022-\n\007options\030\003 \001(\0132\034" - ".google.protobuf.EnumOptions\022N\n\016reserved" - "_range\030\004 \003(\01326.google.protobuf.EnumDescr" - "iptorProto.EnumReservedRange\022\025\n\rreserved" - "_name\030\005 \003(\t\032/\n\021EnumReservedRange\022\r\n\005star" - "t\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n\030EnumValueDescrip" - "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222" - "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa" - "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n" - "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro" - "tobuf.MethodDescriptorProto\0220\n\007options\030\003" - " \001(\0132\037.google.protobuf.ServiceOptions\"\301\001" - "\n\025MethodDescriptorProto\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\007options\030\004 \001(\0132\036.google.protobuf.Method" - "Options\022\037\n\020client_streaming\030\005 \001(\010:\005false" - "\022\037\n\020server_streaming\030\006 \001(\010:\005false\"\245\006\n\013Fi" - "leOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_" - "outer_classname\030\010 \001(\t\022\"\n\023java_multiple_f" - "iles\030\n \001(\010:\005false\022)\n\035java_generate_equal" - "s_and_hash\030\024 \001(\010B\002\030\001\022%\n\026java_string_chec" - "k_utf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(" - "\0162).google.protobuf.FileOptions.Optimize" - "Mode:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_ge" - "neric_services\030\020 \001(\010:\005false\022$\n\025java_gene" - "ric_services\030\021 \001(\010:\005false\022\"\n\023py_generic_" - "services\030\022 \001(\010:\005false\022#\n\024php_generic_ser" - "vices\030* \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005" - "false\022\036\n\020cc_enable_arenas\030\037 \001(\010:\004true\022\031\n" - "\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_names" - "pace\030% \001(\t\022\024\n\014swift_prefix\030\' \001(\t\022\030\n\020php_" - "class_prefix\030( \001(\t\022\025\n\rphp_namespace\030) \001(" - "\t\022\036\n\026php_metadata_namespace\030, \001(\t\022\024\n\014rub" - "y_package\030- \001(\t\022C\n\024uninterpreted_option\030" - "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" - "tion\":\n\014OptimizeMode\022\t\n\005SPEED\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\002J\004\010&\020" - "\'\"\204\002\n\016MessageOptions\022&\n\027message_set_wire" - "_format\030\001 \001(\010:\005false\022.\n\037no_standard_desc" - "riptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecat" - "ed\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024un" - "interpreted_option\030\347\007 \003(\0132$.google.proto" - "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005" - "J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020\n\"\276\003\n\014FieldOption" - "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field" - "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n" - "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt" - "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa" - "lse\022\036\n\017unverified_lazy\030\017 \001(\010:\005false\022\031\n\nd" - "eprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fa" - "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo" - "gle.protobuf.UninterpretedOption\"/\n\005CTyp" - "e\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_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014One" - "ofOptions\022C\n\024uninterpreted_option\030\347\007 \003(\013" - "2$.google.protobuf.UninterpretedOption*\t" - "\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptions\022\023\n\013allow_alias" - "\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"" - "}\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" + "(\t\022\017\n\007edition\030\r \001(\t\"\251\005\n\017DescriptorProto\022" + "\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.pr" + "otobuf.FieldDescriptorProto\0228\n\textension" + "\030\006 \003(\0132%.google.protobuf.FieldDescriptor" + "Proto\0225\n\013nested_type\030\003 \003(\0132 .google.prot" + "obuf.DescriptorProto\0227\n\tenum_type\030\004 \003(\0132" + "$.google.protobuf.EnumDescriptorProto\022H\n" + "\017extension_range\030\005 \003(\0132/.google.protobuf" + ".DescriptorProto.ExtensionRange\0229\n\noneof" + "_decl\030\010 \003(\0132%.google.protobuf.OneofDescr" + "iptorProto\0220\n\007options\030\007 \001(\0132\037.google.pro" + "tobuf.MessageOptions\022F\n\016reserved_range\030\t" + " \003(\0132..google.protobuf.DescriptorProto.R" + "eservedRange\022\025\n\rreserved_name\030\n \003(\t\032e\n\016E" + "xtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(" + "\005\0227\n\007options\030\003 \001(\0132&.google.protobuf.Ext" + "ensionRangeOptions\032+\n\rReservedRange\022\r\n\005s" + "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"g\n\025ExtensionRang" + "eOptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "$.google.protobuf.UninterpretedOption*\t\010" + "\350\007\020\200\200\200\200\002\"\325\005\n\024FieldDescriptorProto\022\014\n\004nam" + "e\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+" + ".google.protobuf.FieldDescriptorProto.La" + "bel\0228\n\004type\030\005 \001(\0162*.google.protobuf.Fiel" + "dDescriptorProto.Type\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\021\n\tjson_name\030\n \001(" + "\t\022.\n\007options\030\010 \001(\0132\035.google.protobuf.Fie" + "ldOptions\022\027\n\017proto3_optional\030\021 \001(\010\"\266\002\n\004T" + "ype\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\n" + "TYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_IN" + "T32\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\nTYP" + "E_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTE" + "S\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rT" + "YPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYP" + "E_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016" + "LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016" + "LABEL_REPEATED\020\003\"T\n\024OneofDescriptorProto" + "\022\014\n\004name\030\001 \001(\t\022.\n\007options\030\002 \001(\0132\035.google" + ".protobuf.OneofOptions\"\244\002\n\023EnumDescripto" + "rProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).go" + "ogle.protobuf.EnumValueDescriptorProto\022-" + "\n\007options\030\003 \001(\0132\034.google.protobuf.EnumOp" + "tions\022N\n\016reserved_range\030\004 \003(\01326.google.p" + "rotobuf.EnumDescriptorProto.EnumReserved" + "Range\022\025\n\rreserved_name\030\005 \003(\t\032/\n\021EnumRese" + "rvedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n" + "\030EnumValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022" + "\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.googl" + "e.protobuf.EnumValueOptions\"\220\001\n\026ServiceD" + "escriptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002" + " \003(\0132&.google.protobuf.MethodDescriptorP" + "roto\0220\n\007options\030\003 \001(\0132\037.google.protobuf." + "ServiceOptions\"\301\001\n\025MethodDescriptorProto" + "\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013ou" + "tput_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.googl" + "e.protobuf.MethodOptions\022\037\n\020client_strea" + "ming\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 " + "\001(\010:\005false\"\245\006\n\013FileOptions\022\024\n\014java_packa" + "ge\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\035ja" + "va_generate_equals_and_hash\030\024 \001(\010B\002\030\001\022%\n" + "\026java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014" + "optimize_for\030\t \001(\0162).google.protobuf.Fil" + "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa" + "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f" + "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal" + "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022#" + "\n\024php_generic_services\030* \001(\010:\005false\022\031\n\nd" + "eprecated\030\027 \001(\010:\005false\022\036\n\020cc_enable_aren" + "as\030\037 \001(\010:\004true\022\031\n\021objc_class_prefix\030$ \001(" + "\t\022\030\n\020csharp_namespace\030% \001(\t\022\024\n\014swift_pre" + "fix\030\' \001(\t\022\030\n\020php_class_prefix\030( \001(\t\022\025\n\rp" + "hp_namespace\030) \001(\t\022\036\n\026php_metadata_names" + "pace\030, \001(\t\022\024\n\014ruby_package\030- \001(\t\022C\n\024unin" + "terpreted_option\030\347\007 \003(\0132$.google.protobu" + "f.UninterpretedOption\":\n\014OptimizeMode\022\t\n" + "\005SPEED\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\002J\004\010&\020\'\"\204\002\n\016MessageOptions\022&\n" + "\027message_set_wire_format\030\001 \001(\010:\005false\022.\n" + "\037no_standard_descriptor_accessor\030\002 \001(\010:\005" + "false\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$.google.protobuf.UninterpretedOption" - "*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n\ndepreca" - "ted\030! \001(\010:\005false\022_\n\021idempotency_level\030\" " - "\001(\0162/.google.protobuf.MethodOptions.Idem" - "potencyLevel:\023IDEMPOTENCY_UNKNOWN\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption\"P\n\020IdempotencyLev" - "el\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_E" - "FFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023" - "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog" - "le.protobuf.UninterpretedOption.NamePart" - "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i" - "nt_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_value" - "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP" - "art\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.Locat" - "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" - "an\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_det" - "ached_comments\030\006 \003(\t\"\247\001\n\021GeneratedCodeIn" - "fo\022A\n\nannotation\030\001 \003(\0132-.google.protobuf" - ".GeneratedCodeInfo.Annotation\032O\n\nAnnotat" - "ion\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001" - "(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~\n\023com.go" - "ogle.protobufB\020DescriptorProtosH\001Z-googl" - "e.golang.org/protobuf/types/descriptorpb" - "\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Reflection" + "*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020" + "\n\"\276\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.goog" + "le.protobuf.FieldOptions.CType:\006STRING\022\016" + "\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.google." + "protobuf.FieldOptions.JSType:\tJS_NORMAL\022" + "\023\n\004lazy\030\005 \001(\010:\005false\022\036\n\017unverified_lazy\030" + "\017 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" + "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption\"/\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_NORMA" + "L\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200" + "\200\200\200\002J\004\010\004\020\005\"^\n\014OneofOptions\022C\n\024uninterpre" + "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" + "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptio" + "ns\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 " + "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(" + "\0132$.google.protobuf.UninterpretedOption*" + "\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"}\n\020EnumValueOptions\022\031\n\n" + "deprecated\030\001 \001(\010:\005false\022C\n\024uninterpreted" + "_option\030\347\007 \003(\0132$.google.protobuf.Uninter" + "pretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOption" + "s\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterp" + "reted_option\030\347\007 \003(\0132$.google.protobuf.Un" + "interpretedOption*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodO" + "ptions\022\031\n\ndeprecated\030! \001(\010:\005false\022_\n\021ide" + "mpotency_level\030\" \001(\0162/.google.protobuf.M" + "ethodOptions.IdempotencyLevel:\023IDEMPOTEN" + "CY_UNKNOWN\022C\n\024uninterpreted_option\030\347\007 \003(" + "\0132$.google.protobuf.UninterpretedOption\"" + "P\n\020IdempotencyLevel\022\027\n\023IDEMPOTENCY_UNKNO" + "WN\020\000\022\023\n\017NO_SIDE_EFFECTS\020\001\022\016\n\nIDEMPOTENT\020" + "\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022;\n\004" + "name\030\002 \003(\0132-.google.protobuf.Uninterpret" + "edOption.NamePart\022\030\n\020identifier_value\030\003 " + "\001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022negat" + "ive_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_val" + "ue\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\016SourceCodeInfo" + "\022:\n\010location\030\001 \003(\0132(.google.protobuf.Sou" + "rceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004pat" + "h\030\001 \003(\005B\002\020\001\022\020\n\004span\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_detached_comments\030\006 \003(\t\"\247\001" + "\n\021GeneratedCodeInfo\022A\n\nannotation\030\001 \003(\0132" + "-.google.protobuf.GeneratedCodeInfo.Anno" + "tation\032O\n\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023" + "\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003en" + "d\030\004 \001(\005B~\n\023com.google.protobufB\020Descript" + "orProtosH\001Z-google.golang.org/protobuf/t" + "ypes/descriptorpb\370\001\001\242\002\003GPB\252\002\032Google.Prot" + "obuf.Reflection" ; static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = { - false, false, 6078, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, + false, false, 6095, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, nullptr, 0, 27, schemas, file_default_instances, TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets, @@ -1576,15 +1580,18 @@ class FileDescriptorProto::_Internal { } static const ::PROTOBUF_NAMESPACE_ID::FileOptions& options(const FileDescriptorProto* msg); static void set_has_options(HasBits* has_bits) { - (*has_bits)[0] |= 8u; + (*has_bits)[0] |= 16u; } static const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info(const FileDescriptorProto* msg); static void set_has_source_code_info(HasBits* has_bits) { - (*has_bits)[0] |= 16u; + (*has_bits)[0] |= 32u; } static void set_has_syntax(HasBits* has_bits) { (*has_bits)[0] |= 4u; } + static void set_has_edition(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } }; const ::PROTOBUF_NAMESPACE_ID::FileOptions& @@ -1617,6 +1624,7 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) , decltype(_impl_.name_){} , decltype(_impl_.package_){} , decltype(_impl_.syntax_){} + , decltype(_impl_.edition_){} , decltype(_impl_.options_){nullptr} , decltype(_impl_.source_code_info_){nullptr}}; @@ -1645,6 +1653,14 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) _this->_impl_.syntax_.Set(from._internal_syntax(), _this->GetArenaForAllocation()); } + _impl_.edition_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.edition_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_edition()) { + _this->_impl_.edition_.Set(from._internal_edition(), + _this->GetArenaForAllocation()); + } if (from._internal_has_options()) { _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::FileOptions(*from._impl_.options_); } @@ -1671,6 +1687,7 @@ inline void FileDescriptorProto::SharedCtor( , decltype(_impl_.name_){} , decltype(_impl_.package_){} , decltype(_impl_.syntax_){} + , decltype(_impl_.edition_){} , decltype(_impl_.options_){nullptr} , decltype(_impl_.source_code_info_){nullptr} }; @@ -1686,6 +1703,10 @@ inline void FileDescriptorProto::SharedCtor( #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING _impl_.syntax_.Set("", GetArenaForAllocation()); #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.edition_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.edition_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } FileDescriptorProto::~FileDescriptorProto() { @@ -1709,6 +1730,7 @@ inline void FileDescriptorProto::SharedDtor() { _impl_.name_.Destroy(); _impl_.package_.Destroy(); _impl_.syntax_.Destroy(); + _impl_.edition_.Destroy(); if (this != internal_default_instance()) delete _impl_.options_; if (this != internal_default_instance()) delete _impl_.source_code_info_; } @@ -1731,7 +1753,7 @@ void FileDescriptorProto::Clear() { _impl_.public_dependency_.Clear(); _impl_.weak_dependency_.Clear(); cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x0000003fu) { if (cached_has_bits & 0x00000001u) { _impl_.name_.ClearNonDefaultToEmpty(); } @@ -1742,10 +1764,13 @@ void FileDescriptorProto::Clear() { _impl_.syntax_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000008u) { + _impl_.edition_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000010u) { GOOGLE_DCHECK(_impl_.options_ != nullptr); _impl_.options_->Clear(); } - if (cached_has_bits & 0x00000010u) { + if (cached_has_bits & 0x00000020u) { GOOGLE_DCHECK(_impl_.source_code_info_ != nullptr); _impl_.source_code_info_->Clear(); } @@ -1914,6 +1939,18 @@ const char* FileDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseCo } else goto handle_unusual; continue; + // optional string edition = 13; + case 13: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 106)) { + auto str = _internal_mutable_edition(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.edition"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; default: goto handle_unusual; } // switch @@ -2008,14 +2045,14 @@ uint8_t* FileDescriptorProto::_InternalSerialize( } // optional .google.protobuf.FileOptions options = 8; - if (cached_has_bits & 0x00000008u) { + if (cached_has_bits & 0x00000010u) { target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: InternalWriteMessage(8, _Internal::options(this), _Internal::options(this).GetCachedSize(), target, stream); } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - if (cached_has_bits & 0x00000010u) { + if (cached_has_bits & 0x00000020u) { target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: InternalWriteMessage(9, _Internal::source_code_info(this), _Internal::source_code_info(this).GetCachedSize(), target, stream); @@ -2043,6 +2080,16 @@ uint8_t* FileDescriptorProto::_InternalSerialize( 12, this->_internal_syntax(), target); } + // optional string edition = 13; + if (cached_has_bits & 0x00000008u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_edition().data(), static_cast(this->_internal_edition().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.edition"); + target = stream->WriteStringMaybeAliased( + 13, this->_internal_edition(), target); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); @@ -2114,7 +2161,7 @@ size_t FileDescriptorProto::ByteSizeLong() const { } cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x0000003fu) { // optional string name = 1; if (cached_has_bits & 0x00000001u) { total_size += 1 + @@ -2136,15 +2183,22 @@ size_t FileDescriptorProto::ByteSizeLong() const { this->_internal_syntax()); } - // optional .google.protobuf.FileOptions options = 8; + // optional string edition = 13; if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_edition()); + } + + // optional .google.protobuf.FileOptions options = 8; + if (cached_has_bits & 0x00000010u) { total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( *_impl_.options_); } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - if (cached_has_bits & 0x00000010u) { + if (cached_has_bits & 0x00000020u) { total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( *_impl_.source_code_info_); @@ -2177,7 +2231,7 @@ void FileDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, co _this->_impl_.public_dependency_.MergeFrom(from._impl_.public_dependency_); _this->_impl_.weak_dependency_.MergeFrom(from._impl_.weak_dependency_); cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x0000003fu) { if (cached_has_bits & 0x00000001u) { _this->_internal_set_name(from._internal_name()); } @@ -2188,10 +2242,13 @@ void FileDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, co _this->_internal_set_syntax(from._internal_syntax()); } if (cached_has_bits & 0x00000008u) { + _this->_internal_set_edition(from._internal_edition()); + } + if (cached_has_bits & 0x00000010u) { _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::FileOptions::MergeFrom( from._internal_options()); } - if (cached_has_bits & 0x00000010u) { + if (cached_has_bits & 0x00000020u) { _this->_internal_mutable_source_code_info()->::PROTOBUF_NAMESPACE_ID::SourceCodeInfo::MergeFrom( from._internal_source_code_info()); } @@ -2246,6 +2303,10 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { &_impl_.syntax_, lhs_arena, &other->_impl_.syntax_, rhs_arena ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.edition_, lhs_arena, + &other->_impl_.edition_, rhs_arena + ); ::PROTOBUF_NAMESPACE_ID::internal::memswap< PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.source_code_info_) + sizeof(FileDescriptorProto::_impl_.source_code_info_) diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index f1204e5ccc..9c5d5e1756 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -622,6 +622,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : kNameFieldNumber = 1, kPackageFieldNumber = 2, kSyntaxFieldNumber = 12, + kEditionFieldNumber = 13, kOptionsFieldNumber = 8, kSourceCodeInfoFieldNumber = 9, }; @@ -819,6 +820,24 @@ class PROTOBUF_EXPORT FileDescriptorProto final : std::string* _internal_mutable_syntax(); public: + // optional string edition = 13; + bool has_edition() const; + private: + bool _internal_has_edition() const; + public: + void clear_edition(); + const std::string& edition() const; + template + void set_edition(ArgT0&& arg0, ArgT... args); + std::string* mutable_edition(); + PROTOBUF_NODISCARD std::string* release_edition(); + void set_allocated_edition(std::string* edition); + private: + const std::string& _internal_edition() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_edition(const std::string& value); + std::string* _internal_mutable_edition(); + public: + // optional .google.protobuf.FileOptions options = 8; bool has_options() const; private: @@ -875,6 +894,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr package_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr syntax_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr edition_; ::PROTOBUF_NAMESPACE_ID::FileOptions* options_; ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info_; }; @@ -9042,7 +9062,7 @@ FileDescriptorProto::extension() const { // optional .google.protobuf.FileOptions options = 8; inline bool FileDescriptorProto::_internal_has_options() const { - bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); return value; } @@ -9051,7 +9071,7 @@ inline bool FileDescriptorProto::has_options() const { } inline void FileDescriptorProto::clear_options() { if (_impl_.options_ != nullptr) _impl_.options_->Clear(); - _impl_._has_bits_[0] &= ~0x00000008u; + _impl_._has_bits_[0] &= ~0x00000010u; } inline const ::PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::_internal_options() const { const ::PROTOBUF_NAMESPACE_ID::FileOptions* p = _impl_.options_; @@ -9069,14 +9089,14 @@ inline void FileDescriptorProto::unsafe_arena_set_allocated_options( } _impl_.options_ = options; if (options) { - _impl_._has_bits_[0] |= 0x00000008u; + _impl_._has_bits_[0] |= 0x00000010u; } else { - _impl_._has_bits_[0] &= ~0x00000008u; + _impl_._has_bits_[0] &= ~0x00000010u; } // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.options) } inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::release_options() { - _impl_._has_bits_[0] &= ~0x00000008u; + _impl_._has_bits_[0] &= ~0x00000010u; ::PROTOBUF_NAMESPACE_ID::FileOptions* temp = _impl_.options_; _impl_.options_ = nullptr; #ifdef PROTOBUF_FORCE_COPY_IN_RELEASE @@ -9092,13 +9112,13 @@ inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::release_option } inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options) - _impl_._has_bits_[0] &= ~0x00000008u; + _impl_._has_bits_[0] &= ~0x00000010u; ::PROTOBUF_NAMESPACE_ID::FileOptions* temp = _impl_.options_; _impl_.options_ = nullptr; return temp; } inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::_internal_mutable_options() { - _impl_._has_bits_[0] |= 0x00000008u; + _impl_._has_bits_[0] |= 0x00000010u; if (_impl_.options_ == nullptr) { auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileOptions>(GetArenaForAllocation()); _impl_.options_ = p; @@ -9122,9 +9142,9 @@ inline void FileDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID:: options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( message_arena, options, submessage_arena); } - _impl_._has_bits_[0] |= 0x00000008u; + _impl_._has_bits_[0] |= 0x00000010u; } else { - _impl_._has_bits_[0] &= ~0x00000008u; + _impl_._has_bits_[0] &= ~0x00000010u; } _impl_.options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) @@ -9132,7 +9152,7 @@ inline void FileDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID:: // optional .google.protobuf.SourceCodeInfo source_code_info = 9; inline bool FileDescriptorProto::_internal_has_source_code_info() const { - bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0; PROTOBUF_ASSUME(!value || _impl_.source_code_info_ != nullptr); return value; } @@ -9141,7 +9161,7 @@ inline bool FileDescriptorProto::has_source_code_info() const { } inline void FileDescriptorProto::clear_source_code_info() { if (_impl_.source_code_info_ != nullptr) _impl_.source_code_info_->Clear(); - _impl_._has_bits_[0] &= ~0x00000010u; + _impl_._has_bits_[0] &= ~0x00000020u; } inline const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::_internal_source_code_info() const { const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* p = _impl_.source_code_info_; @@ -9159,14 +9179,14 @@ inline void FileDescriptorProto::unsafe_arena_set_allocated_source_code_info( } _impl_.source_code_info_ = source_code_info; if (source_code_info) { - _impl_._has_bits_[0] |= 0x00000010u; + _impl_._has_bits_[0] |= 0x00000020u; } else { - _impl_._has_bits_[0] &= ~0x00000010u; + _impl_._has_bits_[0] &= ~0x00000020u; } // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) } inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { - _impl_._has_bits_[0] &= ~0x00000010u; + _impl_._has_bits_[0] &= ~0x00000020u; ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = _impl_.source_code_info_; _impl_.source_code_info_ = nullptr; #ifdef PROTOBUF_FORCE_COPY_IN_RELEASE @@ -9182,13 +9202,13 @@ inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::release_sou } inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info) - _impl_._has_bits_[0] &= ~0x00000010u; + _impl_._has_bits_[0] &= ~0x00000020u; ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = _impl_.source_code_info_; _impl_.source_code_info_ = nullptr; return temp; } inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::_internal_mutable_source_code_info() { - _impl_._has_bits_[0] |= 0x00000010u; + _impl_._has_bits_[0] |= 0x00000020u; if (_impl_.source_code_info_ == nullptr) { auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(GetArenaForAllocation()); _impl_.source_code_info_ = p; @@ -9212,9 +9232,9 @@ inline void FileDescriptorProto::set_allocated_source_code_info(::PROTOBUF_NAMES source_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( message_arena, source_code_info, submessage_arena); } - _impl_._has_bits_[0] |= 0x00000010u; + _impl_._has_bits_[0] |= 0x00000020u; } else { - _impl_._has_bits_[0] &= ~0x00000010u; + _impl_._has_bits_[0] &= ~0x00000020u; } _impl_.source_code_info_ = source_code_info; // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) @@ -9286,6 +9306,72 @@ inline void FileDescriptorProto::set_allocated_syntax(std::string* syntax) { // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) } +// optional string edition = 13; +inline bool FileDescriptorProto::_internal_has_edition() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool FileDescriptorProto::has_edition() const { + return _internal_has_edition(); +} +inline void FileDescriptorProto::clear_edition() { + _impl_.edition_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline const std::string& FileDescriptorProto::edition() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.edition) + return _internal_edition(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void FileDescriptorProto::set_edition(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.edition_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.edition) +} +inline std::string* FileDescriptorProto::mutable_edition() { + std::string* _s = _internal_mutable_edition(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.edition) + return _s; +} +inline const std::string& FileDescriptorProto::_internal_edition() const { + return _impl_.edition_.Get(); +} +inline void FileDescriptorProto::_internal_set_edition(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.edition_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::_internal_mutable_edition() { + _impl_._has_bits_[0] |= 0x00000008u; + return _impl_.edition_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::release_edition() { + // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.edition) + if (!_internal_has_edition()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000008u; + auto* p = _impl_.edition_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.edition_.Set("", GetArenaForAllocation()); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileDescriptorProto::set_allocated_edition(std::string* edition) { + if (edition != nullptr) { + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + _impl_.edition_.SetAllocated(edition, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.edition_.IsDefault()) { + _impl_.edition_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.edition) +} + // ------------------------------------------------------------------- // DescriptorProto_ExtensionRange diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 5b4d06b41c..5404b14190 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -86,8 +86,13 @@ message FileDescriptorProto { optional SourceCodeInfo source_code_info = 9; // The syntax of the proto file. - // The supported values are "proto2" and "proto3". + // The supported values are "proto2", "proto3", and "editions". + // + // If `edition` is present, this value must be "editions". optional string syntax = 12; + + // The edition of the proto file, which is an opaque string. + optional string edition = 13; } // Describes a message type. diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index aefec99081..7d19cf5d52 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -395,7 +395,19 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { } } } +#ifndef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG return total_size; +#else + // Use both `this` and `dummy` to generate the seed so that the scale factor + // is both per-object and non-predictable, but consistent across multiple + // calls in the same binary. + static bool dummy; + uintptr_t seed = + reinterpret_cast(&dummy) ^ reinterpret_cast(this); + // Fuzz the size by +/- 50%. + double scale = (static_cast(seed % 10000) / 10000) + 0.5; + return total_size * scale; +#endif } namespace { diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 1e0c9cbff3..7042a13342 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -298,6 +298,10 @@ class PROTOBUF_EXPORT Message : public MessageLite { // using reflection (rather than the generated code implementation for // ByteSize()). Like ByteSize(), its CPU time is linear in the number of // fields defined for the proto. + // + // Note: The precise value of this method should never be depended on, and can + // change substantially due to internal details. In debug builds, this will + // include a random fuzz factor to prevent these dependencies. virtual size_t SpaceUsedLong() const; PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead") diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index 6f7ad7ca3a..c694a8b7c6 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -189,6 +189,13 @@ // Used to remove the manipulation of cleared elements in RepeatedPtrField. // Owner: mkruskal@ #define PROTOBUF_FUTURE_REMOVE_CLEARED_API 1 +<<<<<<< HEAD +======= + +// Used to escape C++20 keywords. +// Owner: mkruskal@ +#define PROTOBUF_FUTURE_CPP20_KEYWORDS 1 +>>>>>>> 87d285c785cd1a4334e3e21e5d468a9bc3e85f62 #else #define PROTOBUF_FUTURE_FINAL #endif @@ -545,6 +552,10 @@ #error PROTOBUF_FORCE_RESET_IN_CLEAR was previously defined #endif +#ifdef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG +#error PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG was previously defined +#endif + // Force copy the default string to a string field so that non-optimized builds // have harder-to-rely-on address stability. #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc index cc7ccd05fe..2c43d2cf6a 100644 --- a/src/google/protobuf/port_undef.inc +++ b/src/google/protobuf/port_undef.inc @@ -73,6 +73,7 @@ #undef PROTOBUF_FORCE_COPY_IN_SWAP #undef PROTOBUF_FORCE_COPY_IN_MOVE #undef PROTOBUF_FORCE_RESET_IN_CLEAR +#undef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG #undef PROTOBUF_FORCE_COPY_DEFAULT_STRING #undef PROTOBUF_NAMESPACE_OPEN #undef PROTOBUF_NAMESPACE_CLOSE diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 8e9b398360..d452f6e72b 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -503,10 +503,9 @@ int CEscapeInternal(const char* src, int src_len, char* dest, (last_hex_escape && isxdigit(*src)))) { // need space for 4 letter escape and the trailing '\0' to // be written by snprintf. - if (dest_len - used < 5) - return -1; + if (dest_len - used < 5) return -1; snprintf(dest + used, 5, (use_hex ? "\\x%02x" : "\\%03o"), - static_cast(*src)); + static_cast(*src)); is_hex_escape = use_hex; used += 4; } else { diff --git a/src/google/protobuf/test_messages_proto2.proto b/src/google/protobuf/test_messages_proto2.proto index c7b9c487a7..b04d8bb475 100644 --- a/src/google/protobuf/test_messages_proto2.proto +++ b/src/google/protobuf/test_messages_proto2.proto @@ -295,3 +295,9 @@ message EnumOnlyProto2 { message OneStringProto2 { optional string data = 1; } + +message ProtoWithKeywords { + optional int32 inline = 1; + optional string concept = 2; + repeated string requires = 3; +} diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc index c39c10d87b..c15f3f10ae 100644 --- a/src/google/protobuf/util/json_util.cc +++ b/src/google/protobuf/util/json_util.cc @@ -45,6 +45,7 @@ #include #include #include +#include #include // clang-format off @@ -54,35 +55,7 @@ namespace google { namespace protobuf { namespace util { - -namespace internal { -ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() { - if (buffer_size_ > 0) { - stream_->BackUp(buffer_size_); - } -} - -void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { - while (true) { - if (len <= buffer_size_) { // NOLINT - memcpy(buffer_, bytes, len); - buffer_ = static_cast(buffer_) + len; - buffer_size_ -= len; - return; - } - if (buffer_size_ > 0) { - memcpy(buffer_, bytes, buffer_size_); - bytes += buffer_size_; - len -= buffer_size_; - } - if (!stream_->Next(&buffer_, &buffer_size_)) { - // There isn't a way for ByteSink to report errors. - buffer_size_ = 0; - return; - } - } -} -} // namespace internal +using ::google::protobuf::util::zc_sink_internal::ZeroCopyStreamByteSink; util::Status BinaryToJsonStream(TypeResolver* resolver, const std::string& type_url, @@ -181,7 +154,7 @@ util::Status JsonToBinaryStream(TypeResolver* resolver, const JsonParseOptions& options) { google::protobuf::Type type; RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); - internal::ZeroCopyStreamByteSink sink(binary_output); + ZeroCopyStreamByteSink sink(binary_output); StatusErrorListener listener; converter::ProtoStreamObjectWriter::Options proto_writer_options; proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields; diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h index 0f1c4d8b5f..4f4594e2f9 100644 --- a/src/google/protobuf/util/json_util.h +++ b/src/google/protobuf/util/json_util.h @@ -175,26 +175,6 @@ inline util::Status JsonToBinaryString(TypeResolver* resolver, return JsonToBinaryString(resolver, type_url, json_input, binary_output, JsonParseOptions()); } - -namespace internal { -// Internal helper class. Put in the header so we can write unit-tests for it. -class PROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { - public: - explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) - : stream_(stream), buffer_(nullptr), buffer_size_(0) {} - ~ZeroCopyStreamByteSink() override; - - void Append(const char* bytes, size_t len) override; - - private: - io::ZeroCopyOutputStream* stream_; - void* buffer_; - int buffer_size_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); -}; -} // namespace internal - } // namespace util } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/util/zero_copy_sink.cc b/src/google/protobuf/util/zero_copy_sink.cc new file mode 100644 index 0000000000..2b24f11238 --- /dev/null +++ b/src/google/protobuf/util/zero_copy_sink.cc @@ -0,0 +1,60 @@ +// 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. + +#include + +namespace google { +namespace protobuf { +namespace util { +namespace zc_sink_internal { +void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { + while (true) { + if (len <= buffer_size_) { // NOLINT + memcpy(buffer_, bytes, len); + buffer_ = static_cast(buffer_) + len; + buffer_size_ -= len; + return; + } + if (buffer_size_ > 0) { + memcpy(buffer_, bytes, buffer_size_); + bytes += buffer_size_; + len -= buffer_size_; + } + if (!stream_->Next(&buffer_, &buffer_size_)) { + // There isn't a way for ByteSink to report errors. + buffer_size_ = 0; + return; + } + } +} +} // namespace zc_sink_internal +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/zero_copy_sink.h b/src/google/protobuf/util/zero_copy_sink.h new file mode 100644 index 0000000000..f2fd9d7867 --- /dev/null +++ b/src/google/protobuf/util/zero_copy_sink.h @@ -0,0 +1,74 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_ZERO_COPY_SINK_H__ +#define GOOGLE_PROTOBUF_UTIL_ZERO_COPY_SINK_H__ + +#include + +#include +#include +#include + +// Must be included last. +#include + +namespace google { +namespace protobuf { +namespace util { +namespace zc_sink_internal { +// Internal helper class. Put in the header so we can write unit-tests for it. +class PROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { + public: + explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) + : stream_(stream) {} + + ~ZeroCopyStreamByteSink() override { + if (buffer_size_ > 0) { + stream_->BackUp(buffer_size_); + } + } + + void Append(const char* bytes, size_t len) override; + + private: + io::ZeroCopyOutputStream* stream_; + void* buffer_ = nullptr; + int buffer_size_ = 0; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); +}; +} // namespace zc_sink_internal +} // namespace util +} // namespace protobuf +} // namespace google + +#include +#endif // GOOGLE_PROTOBUF_UTIL_ZERO_COPY_SINK_H__ diff --git a/src/google/protobuf/util/zero_copy_sink_test.cc b/src/google/protobuf/util/zero_copy_sink_test.cc new file mode 100644 index 0000000000..9eed0fe160 --- /dev/null +++ b/src/google/protobuf/util/zero_copy_sink_test.cc @@ -0,0 +1,226 @@ +// 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. + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace zc_sink_internal { +namespace { + +class ChunkedString { + public: + explicit ChunkedString(StringPiece data, size_t skipped_patterns) + : data_(data), skipped_patterns_(skipped_patterns) {} + + // Returns the next chunk; empty if out of chunks. + StringPiece NextChunk() { + if (pattern_bit_idx_ == data_.size()) { + return ""; + } + size_t start = pattern_bit_idx_; + do { + ++pattern_bit_idx_; + } while (pattern_bit_idx_ < data_.size() && + (pattern_ >> pattern_bit_idx_ & 1) == 0); + size_t end = pattern_bit_idx_; + return data_.substr(start, end - start); + } + + // Resets the stream and runs the next pattern of splits. + bool NextPattern() { + pattern_ += skipped_patterns_; + if (pattern_ >= (1 << data_.size())) { + return false; + } + pattern_bit_idx_ = 0; + return true; + } + + // prints out the pattern as a sequence of quoted strings. + std::string PatternAsQuotedString() { + std::string out; + size_t start = 0; + for (size_t i = 0; i <= data_.size(); ++i) { + if (i == data_.size() || (pattern_ >> start & 1) != 0) { + if (!out.empty()) { + StrAppend(&out, " "); + } + StrAppend( + &out, "\"", + strings::CHexEscape(std::string{data_.substr(start, i - start)}), + "\""); + start = i; + } + } + return out; + } + + private: + StringPiece data_; + size_t skipped_patterns_; + // pattern_ is a bitset indicating at which indices we insert a seam. + uint64_t pattern_ = 0; + size_t pattern_bit_idx_ = 0; +}; + +class PatternedOutputStream : public io::ZeroCopyOutputStream { + public: + explicit PatternedOutputStream(ChunkedString data) : data_(data) {} + + bool Next(void** buffer, int* length) override { + StringPiece segment; + if (!back_up_.empty()) { + segment = back_up_.back(); + back_up_.pop_back(); + } else { + segment_ = data_.NextChunk(); + segment = segment_; + } + + if (segment_.empty()) { + return false; + } + + // TODO(b/234159981): This is only ever constructed in test code, and only + // from non-const bytes, so this is a valid cast. We need to do this since + // OSS proto does not yet have absl::Span; once we take a full Abseil + // dependency we should use that here instead. + *buffer = const_cast(segment.data()); + *length = static_cast(segment.size()); + byte_count_ += static_cast(segment.size()); + return true; + } + + void BackUp(int length) override { + GOOGLE_CHECK(length <= static_cast(segment_.size())); + + size_t backup = segment_.size() - static_cast(length); + back_up_.push_back(segment_.substr(backup)); + segment_ = segment_.substr(0, backup); + byte_count_ -= static_cast(length); + } + + int64_t ByteCount() const override { return byte_count_; } + + private: + ChunkedString data_; + StringPiece segment_; + + std::vector back_up_; + int64_t byte_count_ = 0; +}; + +class ZeroCopyStreamByteSinkTest : public testing::Test { + protected: + std::array output_{}; + StringPiece output_view_{output_.data(), output_.size()}; + ChunkedString output_chunks_{output_view_, 7}; +}; + +TEST_F(ZeroCopyStreamByteSinkTest, WriteExact) { + do { + SCOPED_TRACE(output_chunks_.PatternAsQuotedString()); + ChunkedString input("0123456789", 1); + + do { + SCOPED_TRACE(input.PatternAsQuotedString()); + output_ = {}; + PatternedOutputStream output_stream(output_chunks_); + ZeroCopyStreamByteSink byte_sink(&output_stream); + SCOPED_TRACE(input.PatternAsQuotedString()); + StringPiece chunk; + while (!(chunk = input.NextChunk()).empty()) { + byte_sink.Append(chunk.data(), chunk.size()); + } + } while (input.NextPattern()); + + ASSERT_EQ(output_view_, "0123456789"); + } while (output_chunks_.NextPattern()); +} + +TEST_F(ZeroCopyStreamByteSinkTest, WriteShort) { + do { + SCOPED_TRACE(output_chunks_.PatternAsQuotedString()); + ChunkedString input("012345678", 1); + + do { + SCOPED_TRACE(input.PatternAsQuotedString()); + output_ = {}; + PatternedOutputStream output_stream(output_chunks_); + ZeroCopyStreamByteSink byte_sink(&output_stream); + SCOPED_TRACE(input.PatternAsQuotedString()); + StringPiece chunk; + while (!(chunk = input.NextChunk()).empty()) { + byte_sink.Append(chunk.data(), chunk.size()); + } + } while (input.NextPattern()); + + ASSERT_EQ(output_view_, StringPiece("012345678\0", 10)); + } while (output_chunks_.NextPattern()); +} + +TEST_F(ZeroCopyStreamByteSinkTest, WriteLong) { + do { + SCOPED_TRACE(output_chunks_.PatternAsQuotedString()); + ChunkedString input("0123456789A", 1); + + do { + SCOPED_TRACE(input.PatternAsQuotedString()); + output_ = {}; + PatternedOutputStream output_stream(output_chunks_); + ZeroCopyStreamByteSink byte_sink(&output_stream); + SCOPED_TRACE(input.PatternAsQuotedString()); + StringPiece chunk; + while (!(chunk = input.NextChunk()).empty()) { + byte_sink.Append(chunk.data(), chunk.size()); + } + } while (input.NextPattern()); + + ASSERT_EQ(output_view_, "0123456789"); + } while (output_chunks_.NextPattern()); +} +} // namespace +} // namespace zc_sink_internal +} // namespace util +} // namespace protobuf +} // namespace google