| 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");
|
| + }
|
| + }
|
| +}
|
|
|