Index: third_party/protobuf/java/src/main/java/com/google/protobuf/LazyFieldLite.java |
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyFieldLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyFieldLite.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..eea1fe3cdde1b3f395abb6664033f9207b2b13db |
--- /dev/null |
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyFieldLite.java |
@@ -0,0 +1,339 @@ |
+// 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. |
+ |
+package com.google.protobuf; |
+ |
+/** |
+ * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores |
+ * the message in a ByteString initially and then parse it on-demand. |
+ * |
+ * LazyField is thread-compatible e.g. concurrent read are safe, however, |
+ * synchronizations are needed under read/write situations. |
+ * |
+ * This class is internal implementation detail, so you don't need to use it directly. |
+ * |
+ * @author xiangl@google.com (Xiang Li) |
+ */ |
+public class LazyFieldLite { |
+ private static final ExtensionRegistryLite EMPTY_REGISTRY = |
+ ExtensionRegistryLite.getEmptyRegistry(); |
+ |
+ /** |
+ * A delayed-parsed version of the bytes. When this is non-null then {@code extensionRegistry } is |
+ * also non-null and {@code value} and {@code memoizedBytes} are null. |
+ */ |
+ private ByteString delayedBytes; |
+ |
+ /** |
+ * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It |
+ * is only guaranteed to be non-null if this message was initialized using bytes and an |
+ * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has |
+ * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}. |
+ */ |
+ private ExtensionRegistryLite extensionRegistry; |
+ |
+ /** |
+ * The parsed value. When this is non-null then {@code delayedBytes} will be null. |
+ */ |
+ protected volatile MessageLite value; |
+ |
+ /** |
+ * The memoized bytes for {@code value}. Will be null when {@code value} is null. |
+ */ |
+ private volatile ByteString memoizedBytes; |
+ |
+ /** |
+ * Constructs a LazyFieldLite with bytes that will be parsed lazily. |
+ */ |
+ public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) { |
+ checkArguments(extensionRegistry, bytes); |
+ this.extensionRegistry = extensionRegistry; |
+ this.delayedBytes = bytes; |
+ } |
+ |
+ /** |
+ * Constructs a LazyFieldLite with no contents, and no ability to parse extensions. |
+ */ |
+ public LazyFieldLite() { |
+ } |
+ |
+ /** |
+ * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse |
+ * the extensions in the value as it has no ExtensionRegistry. |
+ */ |
+ public static LazyFieldLite fromValue(MessageLite value) { |
+ LazyFieldLite lf = new LazyFieldLite(); |
+ lf.setValue(value); |
+ return lf; |
+ } |
+ |
+ /** |
+ * Determines whether this LazyFieldLite instance represents the default instance of this type. |
+ */ |
+ public boolean containsDefaultInstance() { |
+ return memoizedBytes == ByteString.EMPTY |
+ || value == null && (delayedBytes == null || delayedBytes == ByteString.EMPTY); |
+ } |
+ |
+ /** |
+ * Clears the value state of this instance. |
+ * |
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed |
+ * under read/write situations. |
+ */ |
+ public void clear() { |
+ // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another |
+ // value, but there is no guarantee that it will contain all extensions that were directly set |
+ // on the values that need to be merged. |
+ delayedBytes = null; |
+ value = null; |
+ memoizedBytes = null; |
+ } |
+ |
+ /** |
+ * Overrides the contents of this LazyField. |
+ * |
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed |
+ * under read/write situations. |
+ */ |
+ public void set(LazyFieldLite other) { |
+ this.delayedBytes = other.delayedBytes; |
+ this.value = other.value; |
+ this.memoizedBytes = other.memoizedBytes; |
+ // If the other LazyFieldLite was created by directly setting the value rather than first by |
+ // parsing, then it will not have an extensionRegistry. In this case we hold on to the existing |
+ // extensionRegistry, which has no guarantees that it has all the extensions that will be |
+ // directly set on the value. |
+ if (other.extensionRegistry != null) { |
+ this.extensionRegistry = other.extensionRegistry; |
+ } |
+ } |
+ |
+ /** |
+ * Returns message instance. It may do some thread-safe delayed parsing of bytes. |
+ * |
+ * @param defaultInstance its message's default instance. It's also used to get parser for the |
+ * message type. |
+ */ |
+ public MessageLite getValue(MessageLite defaultInstance) { |
+ ensureInitialized(defaultInstance); |
+ return value; |
+ } |
+ |
+ /** |
+ * Sets the value of the instance and returns the old value without delay parsing anything. |
+ * |
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed |
+ * under read/write situations. |
+ */ |
+ public MessageLite setValue(MessageLite value) { |
+ MessageLite originalValue = this.value; |
+ this.delayedBytes = null; |
+ this.memoizedBytes = null; |
+ this.value = value; |
+ return originalValue; |
+ } |
+ |
+ /** |
+ * Merges another instance's contents. In some cases may drop some extensions if both fields |
+ * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this |
+ * field will copy over that {@code ExtensionRegistry}. |
+ * |
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed |
+ * under read/write situations. |
+ */ |
+ public void merge(LazyFieldLite other) { |
+ if (other.containsDefaultInstance()) { |
+ return; |
+ } |
+ |
+ if (this.containsDefaultInstance()) { |
+ set(other); |
+ return; |
+ } |
+ |
+ // If the other field has an extension registry but this does not, copy over the other extension |
+ // registry. |
+ if (this.extensionRegistry == null) { |
+ this.extensionRegistry = other.extensionRegistry; |
+ } |
+ |
+ // In the case that both of them are not parsed we simply concatenate the bytes to save time. In |
+ // the (probably rare) case that they have different extension registries there is a chance that |
+ // some of the extensions may be dropped, but the tradeoff of making this operation fast seems |
+ // to outway the benefits of combining the extension registries, which is not normally done for |
+ // lite protos anyways. |
+ if (this.delayedBytes != null && other.delayedBytes != null) { |
+ this.delayedBytes = this.delayedBytes.concat(other.delayedBytes); |
+ return; |
+ } |
+ |
+ // At least one is parsed and both contain data. We won't drop any extensions here directly, but |
+ // in the case that the extension registries are not the same then we might in the future if we |
+ // need to serialze and parse a message again. |
+ if (this.value == null && other.value != null) { |
+ setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry)); |
+ return; |
+ } else if (this.value != null && other.value == null) { |
+ setValue(mergeValueAndBytes(this.value, other.delayedBytes, other.extensionRegistry)); |
+ return; |
+ } |
+ |
+ // At this point we have two fully parsed messages. We can't merge directly from one to the |
+ // other because only generated builder code contains methods to mergeFrom another parsed |
+ // message. We have to serialize one instance and then merge the bytes into the other. This may |
+ // drop extensions from one of the messages if one of the values had an extension set on it |
+ // directly. |
+ // |
+ // To mitigate this we prefer serializing a message that has an extension registry, and |
+ // therefore a chance that all extensions set on it are in that registry. |
+ // |
+ // NOTE: The check for other.extensionRegistry not being null must come first because at this |
+ // point in time if other.extensionRegistry is not null then this.extensionRegistry will not be |
+ // null either. |
+ if (other.extensionRegistry != null) { |
+ setValue(mergeValueAndBytes(this.value, other.toByteString(), other.extensionRegistry)); |
+ return; |
+ } else if (this.extensionRegistry != null) { |
+ setValue(mergeValueAndBytes(other.value, this.toByteString(), this.extensionRegistry)); |
+ return; |
+ } else { |
+ // All extensions from the other message will be dropped because we have no registry. |
+ setValue(mergeValueAndBytes(this.value, other.toByteString(), EMPTY_REGISTRY)); |
+ return; |
+ } |
+ } |
+ |
+ private static MessageLite mergeValueAndBytes( |
+ MessageLite value, ByteString otherBytes, ExtensionRegistryLite extensionRegistry) { |
+ try { |
+ return value.toBuilder().mergeFrom(otherBytes, extensionRegistry).build(); |
+ } catch (InvalidProtocolBufferException e) { |
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto |
+ // was invalid. |
+ return value; |
+ } |
+ } |
+ |
+ /** |
+ * Sets this field with bytes to delay-parse. |
+ */ |
+ public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) { |
+ checkArguments(extensionRegistry, bytes); |
+ this.delayedBytes = bytes; |
+ this.extensionRegistry = extensionRegistry; |
+ this.value = null; |
+ this.memoizedBytes = null; |
+ } |
+ |
+ /** |
+ * Due to the optional field can be duplicated at the end of serialized |
+ * bytes, which will make the serialized size changed after LazyField |
+ * parsed. Be careful when using this method. |
+ */ |
+ public int getSerializedSize() { |
+ if (delayedBytes != null) { |
+ return delayedBytes.size(); |
+ } else if (memoizedBytes != null) { |
+ return memoizedBytes.size(); |
+ } else if (value != null) { |
+ return value.getSerializedSize(); |
+ } else { |
+ return 0; |
+ } |
+ } |
+ |
+ /** |
+ * Returns a BytesString for this field in a thread-safe way. |
+ */ |
+ public ByteString toByteString() { |
+ if (delayedBytes != null) { |
+ return delayedBytes; |
+ } |
+ if (memoizedBytes != null) { |
+ return memoizedBytes; |
+ } |
+ synchronized (this) { |
+ if (memoizedBytes != null) { |
+ return memoizedBytes; |
+ } |
+ if (value == null) { |
+ memoizedBytes = ByteString.EMPTY; |
+ } else { |
+ memoizedBytes = value.toByteString(); |
+ } |
+ return memoizedBytes; |
+ } |
+ } |
+ |
+ /** |
+ * Might lazily parse the bytes that were previously passed in. Is thread-safe. |
+ */ |
+ protected void ensureInitialized(MessageLite defaultInstance) { |
+ if (value != null) { |
+ return; |
+ } |
+ synchronized (this) { |
+ if (value != null) { |
+ return; |
+ } |
+ try { |
+ if (delayedBytes != null) { |
+ // The extensionRegistry shouldn't be null here since we have delayedBytes. |
+ MessageLite parsedValue = defaultInstance.getParserForType() |
+ .parseFrom(delayedBytes, extensionRegistry); |
+ this.value = parsedValue; |
+ this.memoizedBytes = delayedBytes; |
+ this.delayedBytes = null; |
+ } else { |
+ this.value = defaultInstance; |
+ this.memoizedBytes = ByteString.EMPTY; |
+ this.delayedBytes = null; |
+ } |
+ } catch (InvalidProtocolBufferException e) { |
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto |
+ // was invalid. |
+ this.value = defaultInstance; |
+ this.memoizedBytes = ByteString.EMPTY; |
+ this.delayedBytes = null; |
+ } |
+ } |
+ } |
+ |
+ |
+ private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) { |
+ if (extensionRegistry == null) { |
+ throw new NullPointerException("found null ExtensionRegistry"); |
+ } |
+ if (bytes == null) { |
+ throw new NullPointerException("found null ByteString"); |
+ } |
+ } |
+} |