diff options
author | Jisi Liu <jisi.liu@gmail.com> | 2017-10-18 12:22:18 -0700 |
---|---|---|
committer | Jisi Liu <jisi.liu@gmail.com> | 2017-10-18 12:22:18 -0700 |
commit | 1a7a7fca804afa1cf67f8be5e71092898ba40334 (patch) | |
tree | 04b3da27c71c607510f34a12cf7856a1b94181ae /java | |
parent | c4f59dcc5c13debc572154c8f636b8a9361aacde (diff) |
Merge from google internal
Diffstat (limited to 'java')
9 files changed, 91 insertions, 48 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java index 065fa1a9..908764df 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java @@ -380,6 +380,10 @@ public abstract class AbstractMessage @Override public BuilderType mergeFrom(final Message other) { + return mergeFrom(other, other.getAllFields()); + } + + BuilderType mergeFrom(final Message other, Map<FieldDescriptor, Object> allFields) { if (other.getDescriptorForType() != getDescriptorForType()) { throw new IllegalArgumentException( "mergeFrom(Message) can only merge messages of the same type."); @@ -394,8 +398,7 @@ public abstract class AbstractMessage // TODO(kenton): Provide a function somewhere called makeDeepCopy() // which allows people to make secure deep copies of messages. - for (final Map.Entry<FieldDescriptor, Object> entry : - other.getAllFields().entrySet()) { + for (final Map.Entry<FieldDescriptor, Object> entry : allFields.entrySet()) { final FieldDescriptor field = entry.getKey(); if (field.isRepeated()) { for (final Object element : (List)entry.getValue()) { diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java index 511501d4..e08a993b 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -413,8 +413,7 @@ public abstract class CodedInputStream { private boolean explicitDiscardUnknownFields = false; - /** TODO(liujisi): flip the default.*/ - private static volatile boolean proto3DiscardUnknownFieldsDefault = true; + private static volatile boolean proto3DiscardUnknownFieldsDefault = false; static void setProto3DiscardUnknownsByDefaultForTest() { proto3DiscardUnknownFieldsDefault = true; diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 99864964..09084646 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -31,7 +31,6 @@ package com.google.protobuf; import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream; -import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException; import com.google.protobuf.Internal.BooleanList; import com.google.protobuf.Internal.DoubleList; import com.google.protobuf.Internal.EnumLiteMap; @@ -52,6 +51,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Lite version of {@link GeneratedMessage}. @@ -62,6 +62,12 @@ public abstract class GeneratedMessageLite< MessageType extends GeneratedMessageLite<MessageType, BuilderType>, BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> extends AbstractMessageLite<MessageType, BuilderType> { + // BEGIN REGULAR + static final boolean ENABLE_EXPERIMENTAL_RUNTIME_AT_BUILD_TIME = false; + // END REGULAR + // BEGIN EXPERIMENTAL + // static final boolean ENABLE_EXPERIMENTAL_RUNTIME_AT_BUILD_TIME = true; + // END EXPERIMENTAL /** For use by generated code only. Lazily initialized to reduce allocations. */ protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance(); @@ -110,12 +116,19 @@ public abstract class GeneratedMessageLite< if (memoizedHashCode != 0) { return memoizedHashCode; } + // BEGIN EXPERIMENTAL + // memoizedHashCode = Protobuf.getInstance().schemaFor(this).hashCode(this); + // return memoizedHashCode; + // END EXPERIMENTAL + // BEGIN REGULAR HashCodeVisitor visitor = new HashCodeVisitor(); visit(visitor, (MessageType) this); memoizedHashCode = visitor.hashCode; return memoizedHashCode; + // END REGULAR } + // BEGIN REGULAR @SuppressWarnings("unchecked") // Guaranteed by runtime int hashCode(HashCodeVisitor visitor) { if (memoizedHashCode == 0) { @@ -127,6 +140,7 @@ public abstract class GeneratedMessageLite< } return memoizedHashCode; } + // END REGULAR @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime @Override @@ -139,18 +153,22 @@ public abstract class GeneratedMessageLite< return false; } + // BEGIN EXPERIMENTAL + // return Protobuf.getInstance().schemaFor(this).equals(this, (MessageType) other); + // END EXPERIMENTAL + // BEGIN REGULAR try { visit(EqualsVisitor.INSTANCE, (MessageType) other); - } catch (NotEqualsException e) { + } catch (EqualsVisitor.NotEqualsException e) { return false; } return true; + // END REGULAR } - /** - * Same as {@link #equals(Object)} but throws {@code NotEqualsException}. - */ + // BEGIN REGULAR + /** Same as {@link #equals(Object)} but throws {@code NotEqualsException}. */ @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime boolean equals(EqualsVisitor visitor, MessageLite other) { if (this == other) { @@ -164,14 +182,13 @@ public abstract class GeneratedMessageLite< visit(visitor, (MessageType) other); return true; } + // END REGULAR // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as // mutable during the parsing constructor and immutable after. This allows us to avoid // any unnecessary intermediary allocations while reducing the generated code size. - /** - * Lazily initializes unknown fields. - */ + /** Lazily initializes unknown fields. */ private final void ensureUnknownFieldsInitialized() { if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { unknownFields = UnknownFieldSetLite.newInstance(); @@ -218,6 +235,20 @@ public abstract class GeneratedMessageLite< unknownFields.makeImmutable(); } + protected final < + MessageType extends GeneratedMessageLite<MessageType, BuilderType>, + BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> + BuilderType createBuilder() { + return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); + } + + protected final < + MessageType extends GeneratedMessageLite<MessageType, BuilderType>, + BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> + BuilderType createBuilder(MessageType prototype) { + return ((BuilderType) createBuilder()).mergeFrom(prototype); + } + @Override public final boolean isInitialized() { return isInitialized((MessageType) this, Boolean.TRUE); @@ -238,11 +269,13 @@ public abstract class GeneratedMessageLite< * For use by generated code only. */ public static enum MethodToInvoke { - // Rely on/modify instance state IS_INITIALIZED, + // BEGIN REGULAR + VISIT, + // END REGULAR + // Rely on/modify instance state GET_MEMOIZED_IS_INITIALIZED, SET_MEMOIZED_IS_INITIALIZED, - VISIT, MERGE_FROM_STREAM, MAKE_IMMUTABLE, @@ -299,10 +332,13 @@ public abstract class GeneratedMessageLite< return dynamicMethod(method, null, null); } + // BEGIN REGULAR void visit(Visitor visitor, MessageType other) { dynamicMethod(MethodToInvoke.VISIT, visitor, other); unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields); } + // END REGULAR + /** @@ -399,7 +435,12 @@ public abstract class GeneratedMessageLite< } private void mergeFromInstance(MessageType dest, MessageType src) { + // BEGIN EXPERIMENTAL + // Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src); + // END EXPERIMENTAL + // BEGIN REGULAR dest.visit(MergeFromVisitor.INSTANCE, src); + // END REGULAR } @Override @@ -477,11 +518,13 @@ public abstract class GeneratedMessageLite< extensions.mergeFrom(((ExtendableMessage) other).extensions); } + // BEGIN REGULAR @Override final void visit(Visitor visitor, MessageType other) { super.visit(visitor, other); extensions = visitor.visitExtensions(extensions, other.extensions); } + // END REGULAR /** * Parse an unknown field or an extension. For use by generated code only. @@ -494,7 +537,8 @@ public abstract class GeneratedMessageLite< MessageType defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry, - int tag) throws IOException { + int tag) + throws IOException { int fieldNumber = WireFormat.getTagFieldNumber(tag); // TODO(dweis): How much bytecode would be saved by not requiring the generated code to @@ -1716,6 +1760,7 @@ public abstract class GeneratedMessageLite< return message; } + // BEGIN REGULAR /** * An abstract visitor that the generated code calls into that we use to implement various * features. Fields that are not members of oneofs are always visited. Members of a oneof are only @@ -2401,4 +2446,5 @@ public abstract class GeneratedMessageLite< return mine; } } + // END REGULAR } diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java index 592869a1..4acd8f2f 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java @@ -358,6 +358,10 @@ public abstract class GeneratedMessageV3 extends AbstractMessage throw e.unwrapIOException(); } } + + protected static boolean canUseUnsafe() { + return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations(); + } @Override public void writeTo(final CodedOutputStream output) throws IOException { @@ -655,6 +659,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage .build()); } + @Override public boolean isInitialized() { for (final FieldDescriptor field : getDescriptorForType().getFields()) { @@ -2853,3 +2858,4 @@ public abstract class GeneratedMessageV3 extends AbstractMessage } } } + diff --git a/java/core/src/main/java/com/google/protobuf/Message.java b/java/core/src/main/java/com/google/protobuf/Message.java index 94590fb9..0770d417 100644 --- a/java/core/src/main/java/com/google/protobuf/Message.java +++ b/java/core/src/main/java/com/google/protobuf/Message.java @@ -125,7 +125,7 @@ public interface Message extends MessageLite, MessageOrBuilder { * it is merged into the corresponding sub-message of this message * using the same merging rules.<br> * * For repeated fields, the elements in {@code other} are concatenated - * with the elements in this message. + * with the elements in this message.<br> * * For oneof groups, if the other message has one of the fields set, * the group of this message is cleared and replaced by the field * of the other message, so that the oneof constraint is preserved. diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java index ff686a0c..42da5bb3 100644 --- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java +++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java @@ -404,34 +404,4 @@ public class FieldPresenceTest extends TestCase { assertTrue(builder.buildPartial().isInitialized()); } - - // Test that unknown fields are dropped. - public void testUnknownFields() throws Exception { - TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.setOptionalInt32(1234); - builder.addRepeatedInt32(5678); - TestAllTypes message = builder.build(); - ByteString data = message.toByteString(); - - TestOptionalFieldsOnly optionalOnlyMessage = - TestOptionalFieldsOnly.parseFrom(data); - // UnknownFieldSet should be empty. - assertEquals( - 0, optionalOnlyMessage.getUnknownFields().toByteString().size()); - assertEquals(1234, optionalOnlyMessage.getOptionalInt32()); - message = TestAllTypes.parseFrom(optionalOnlyMessage.toByteString()); - assertEquals(1234, message.getOptionalInt32()); - // The repeated field is discarded because it's unknown to the optional-only - // message. - assertEquals(0, message.getRepeatedInt32Count()); - - DynamicMessage dynamicOptionalOnlyMessage = - DynamicMessage.getDefaultInstance( - TestOptionalFieldsOnly.getDescriptor()) - .getParserForType().parseFrom(data); - assertEquals( - 0, dynamicOptionalOnlyMessage.getUnknownFields().toByteString().size()); - assertEquals(optionalOnlyMessage.toByteString(), - dynamicOptionalOnlyMessage.toByteString()); - } } diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java index ba4d539d..40b44538 100644 --- a/java/core/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LiteTest.java @@ -1453,6 +1453,15 @@ public class LiteTest extends TestCase { UnittestLite.optionalFixed32ExtensionLite)); } + public void testBuilderMergeFromNull() throws Exception { + try { + TestAllTypesLite.newBuilder().mergeFrom((TestAllTypesLite) null); + fail("Expected exception"); + } catch (NullPointerException e) { + // Pass. + } + } + // Builder.mergeFrom() should keep existing extensions. public void testBuilderMergeFromWithExtensions() throws Exception { TestAllExtensionsLite message = diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java index b192b53e..e017b987 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java @@ -34,7 +34,6 @@ import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.FieldMask; import com.google.protobuf.Message; - import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; @@ -244,6 +243,11 @@ final class FieldMaskTree { + "singluar message field and cannot have sub-fields."); continue; } + if (!source.hasField(field) && !destination.hasField(field)) { + // If the message field is not present in both source and destination, skip recursing + // so we don't create unneccessary empty messages. + continue; + } String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey(); merge( entry.getValue(), diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java index 3ee0fc6e..853b6151 100644 --- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java @@ -33,7 +33,6 @@ package com.google.protobuf.util; import protobuf_unittest.UnittestProto.NestedTestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; - import junit.framework.TestCase; public class FieldMaskTreeTest extends TestCase { @@ -222,6 +221,13 @@ public class FieldMaskTreeTest extends TestCase { new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options); assertEquals(false, builder.hasPayload()); + // Skip a message field if they are unset in both source and target. + builder = NestedTestAllTypes.newBuilder(); + new FieldMaskTree() + .addFieldPath("payload.optional_int32") + .merge(clearedSource, builder, options); + assertEquals(false, builder.hasPayload()); + // Change to replace message fields. options.setReplaceMessageFields(true); builder = NestedTestAllTypes.newBuilder(); |