aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/protobuf/3.2.0/java/util/src/main/java/com/google
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/protobuf/3.2.0/java/util/src/main/java/com/google')
-rw-r--r--third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Durations.java302
-rw-r--r--third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java287
-rw-r--r--third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java342
-rw-r--r--third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java1751
-rw-r--r--third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java400
-rw-r--r--third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Timestamps.java396
6 files changed, 0 insertions, 3478 deletions
diff --git a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Durations.java b/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Durations.java
deleted file mode 100644
index 46b2182865..0000000000
--- a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Durations.java
+++ /dev/null
@@ -1,302 +0,0 @@
-// 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.util;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.math.IntMath.checkedAdd;
-import static com.google.common.math.IntMath.checkedSubtract;
-import static com.google.common.math.LongMath.checkedAdd;
-import static com.google.common.math.LongMath.checkedMultiply;
-import static com.google.common.math.LongMath.checkedSubtract;
-import static com.google.protobuf.util.Timestamps.MICROS_PER_SECOND;
-import static com.google.protobuf.util.Timestamps.MILLIS_PER_SECOND;
-import static com.google.protobuf.util.Timestamps.NANOS_PER_MICROSECOND;
-import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND;
-import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND;
-
-import com.google.protobuf.Duration;
-import java.text.ParseException;
-import java.util.Comparator;
-
-/**
- * Utilities to help create/manipulate {@code protobuf/duration.proto}. All operations throw an
- * {@link IllegalArgumentException} if the input(s) are not {@linkplain #isValid(Duration) valid}.
- */
-public final class Durations {
- static final long DURATION_SECONDS_MIN = -315576000000L;
- static final long DURATION_SECONDS_MAX = 315576000000L;
-
- /** A constant holding the minimum valid {@link Duration}, approximately {@code -10,000} years. */
- public static final Duration MIN_VALUE =
- Duration.newBuilder().setSeconds(DURATION_SECONDS_MIN).setNanos(-999999999).build();
-
- /** A constant holding the maximum valid {@link Duration}, approximately {@code +10,000} years. */
- public static final Duration MAX_VALUE =
- Duration.newBuilder().setSeconds(DURATION_SECONDS_MAX).setNanos(999999999).build();
-
- private Durations() {}
-
- private static final Comparator<Duration> COMPARATOR =
- new Comparator<Duration>() {
- @Override
- public int compare(Duration d1, Duration d2) {
- checkValid(d1);
- checkValid(d2);
- int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
- return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
- }
- };
-
- /**
- * Returns a {@link Comparator} for {@link Duration}s which sorts in increasing chronological
- * order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}).
- */
- public static Comparator<Duration> comparator() {
- return COMPARATOR;
- }
-
- /**
- * Returns true if the given {@link Duration} is valid. The {@code seconds} value must be in the
- * range [-315,576,000,000, +315,576,000,000]. The {@code nanos} value must be in the range
- * [-999,999,999, +999,999,999].
- *
- * <p><b>Note:</b> Durations less than one second are represented with a 0 {@code seconds} field
- * and a positive or negative {@code nanos} field. For durations of one second or more, a non-zero
- * value for the {@code nanos} field must be of the same sign as the {@code seconds} field.
- */
- public static boolean isValid(Duration duration) {
- return isValid(duration.getSeconds(), duration.getNanos());
- }
-
- /**
- * Returns true if the given number of seconds and nanos is a valid {@link Duration}. The {@code
- * seconds} value must be in the range [-315,576,000,000, +315,576,000,000]. The {@code nanos}
- * value must be in the range [-999,999,999, +999,999,999].
- *
- * <p><b>Note:</b> Durations less than one second are represented with a 0 {@code seconds} field
- * and a positive or negative {@code nanos} field. For durations of one second or more, a non-zero
- * value for the {@code nanos} field must be of the same sign as the {@code seconds} field.
- */
- public static boolean isValid(long seconds, int nanos) {
- if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
- return false;
- }
- if (nanos < -999999999L || nanos >= NANOS_PER_SECOND) {
- return false;
- }
- if (seconds < 0 || nanos < 0) {
- if (seconds > 0 || nanos > 0) {
- return false;
- }
- }
- return true;
- }
-
- /** Throws an {@link IllegalArgumentException} if the given {@link Duration} is not valid. */
- public static Duration checkValid(Duration duration) {
- long seconds = duration.getSeconds();
- int nanos = duration.getNanos();
- checkArgument(
- isValid(seconds, nanos),
- "Duration is not valid. See proto definition for valid values. "
- + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. "
- + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. "
- + "Nanos must have the same sign as seconds",
- seconds,
- nanos);
- return duration;
- }
-
- /**
- * Convert Duration to string format. The string format will contains 3, 6, or 9 fractional digits
- * depending on the precision required to represent the exact Duration value. For example: "1s",
- * "1.010s", "1.000000100s", "-3.100s" The range that can be represented by Duration is from
- * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
- *
- * @return The string representation of the given duration.
- * @throws IllegalArgumentException if the given duration is not in the valid range.
- */
- public static String toString(Duration duration) {
- checkValid(duration);
-
- long seconds = duration.getSeconds();
- int nanos = duration.getNanos();
-
- StringBuilder result = new StringBuilder();
- if (seconds < 0 || nanos < 0) {
- result.append("-");
- seconds = -seconds;
- nanos = -nanos;
- }
- result.append(seconds);
- if (nanos != 0) {
- result.append(".");
- result.append(Timestamps.formatNanos(nanos));
- }
- result.append("s");
- return result.toString();
- }
-
- /**
- * Parse from a string to produce a duration.
- *
- * @return A Duration parsed from the string.
- * @throws ParseException if parsing fails.
- */
- public static Duration parse(String value) throws ParseException {
- // Must ended with "s".
- if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
- throw new ParseException("Invalid duration string: " + value, 0);
- }
- boolean negative = false;
- if (value.charAt(0) == '-') {
- negative = true;
- value = value.substring(1);
- }
- String secondValue = value.substring(0, value.length() - 1);
- String nanoValue = "";
- int pointPosition = secondValue.indexOf('.');
- if (pointPosition != -1) {
- nanoValue = secondValue.substring(pointPosition + 1);
- secondValue = secondValue.substring(0, pointPosition);
- }
- long seconds = Long.parseLong(secondValue);
- int nanos = nanoValue.isEmpty() ? 0 : Timestamps.parseNanos(nanoValue);
- if (seconds < 0) {
- throw new ParseException("Invalid duration string: " + value, 0);
- }
- if (negative) {
- seconds = -seconds;
- nanos = -nanos;
- }
- try {
- return normalizedDuration(seconds, nanos);
- } catch (IllegalArgumentException e) {
- throw new ParseException("Duration value is out of range.", 0);
- }
- }
-
- /** Create a Duration from the number of seconds. */
- public static Duration fromSeconds(long seconds) {
- return normalizedDuration(seconds, 0);
- }
-
- /**
- * Convert a Duration to the number of seconds. The result will be rounded towards 0 to the
- * nearest second. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
- */
- public static long toSeconds(Duration duration) {
- return checkValid(duration).getSeconds();
- }
-
- /** Create a Duration from the number of milliseconds. */
- public static Duration fromMillis(long milliseconds) {
- return normalizedDuration(
- milliseconds / MILLIS_PER_SECOND,
- (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
- }
-
- /**
- * Convert a Duration to the number of milliseconds. The result will be rounded towards 0 to the
- * nearest millisecond. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
- */
- public static long toMillis(Duration duration) {
- checkValid(duration);
- return checkedAdd(
- checkedMultiply(duration.getSeconds(), MILLIS_PER_SECOND),
- duration.getNanos() / NANOS_PER_MILLISECOND);
- }
-
- /** Create a Duration from the number of microseconds. */
- public static Duration fromMicros(long microseconds) {
- return normalizedDuration(
- microseconds / MICROS_PER_SECOND,
- (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
- }
-
- /**
- * Convert a Duration to the number of microseconds. The result will be rounded towards 0 to the
- * nearest microseconds. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
- */
- public static long toMicros(Duration duration) {
- checkValid(duration);
- return checkedAdd(
- checkedMultiply(duration.getSeconds(), MICROS_PER_SECOND),
- duration.getNanos() / NANOS_PER_MICROSECOND);
- }
-
- /** Create a Duration from the number of nanoseconds. */
- public static Duration fromNanos(long nanoseconds) {
- return normalizedDuration(
- nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
- }
-
- /** Convert a Duration to the number of nanoseconds. */
- public static long toNanos(Duration duration) {
- checkValid(duration);
- return checkedAdd(
- checkedMultiply(duration.getSeconds(), NANOS_PER_SECOND), duration.getNanos());
- }
-
- /** Add two durations. */
- public static Duration add(Duration d1, Duration d2) {
- checkValid(d1);
- checkValid(d2);
- return normalizedDuration(
- checkedAdd(d1.getSeconds(), d2.getSeconds()), checkedAdd(d1.getNanos(), d2.getNanos()));
- }
-
- /** Subtract a duration from another. */
- public static Duration subtract(Duration d1, Duration d2) {
- checkValid(d1);
- checkValid(d2);
- return normalizedDuration(
- checkedSubtract(d1.getSeconds(), d2.getSeconds()),
- checkedSubtract(d1.getNanos(), d2.getNanos()));
- }
-
- static Duration normalizedDuration(long seconds, int nanos) {
- if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
- seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND);
- nanos %= NANOS_PER_SECOND;
- }
- if (seconds > 0 && nanos < 0) {
- nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding)
- seconds--; // no overflow since seconds is positive (and we're decrementing)
- }
- if (seconds < 0 && nanos > 0) {
- nanos -= NANOS_PER_SECOND; // no overflow since nanos is positive (and we're subtracting)
- seconds++; // no overflow since seconds is negative (and we're incrementing)
- }
- Duration duration = Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
- return checkValid(duration);
- }
-}
diff --git a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
deleted file mode 100644
index b192b53edf..0000000000
--- a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
+++ /dev/null
@@ -1,287 +0,0 @@
-// 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.util;
-
-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;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.logging.Logger;
-
-/**
- * A tree representation of a FieldMask. Each leaf node in this tree represent
- * a field path in the FieldMask.
- *
- * <p>For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be:
- * <pre>
- * [root] -+- foo -+- bar
- * | |
- * | +- baz
- * |
- * +- bar --- baz
- * </pre>
- *
- * <p>By representing FieldMasks with this tree structure we can easily convert
- * a FieldMask to a canonical form, merge two FieldMasks, calculate the
- * intersection to two FieldMasks and traverse all fields specified by the
- * FieldMask in a message tree.
- */
-final class FieldMaskTree {
- private static final Logger logger = Logger.getLogger(FieldMaskTree.class.getName());
-
- private static final String FIELD_PATH_SEPARATOR_REGEX = "\\.";
-
- private static final class Node {
- final SortedMap<String, Node> children = new TreeMap<String, Node>();
- }
-
- private final Node root = new Node();
-
- /**
- * Creates an empty FieldMaskTree.
- */
- FieldMaskTree() {}
-
- /**
- * Creates a FieldMaskTree for a given FieldMask.
- */
- FieldMaskTree(FieldMask mask) {
- mergeFromFieldMask(mask);
- }
-
- @Override
- public String toString() {
- return FieldMaskUtil.toString(toFieldMask());
- }
-
- /**
- * Adds a field path to the tree. In a FieldMask, every field path matches the
- * specified field as well as all its sub-fields. For example, a field path
- * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding
- * a field path to the tree, redundant sub-paths will be removed. That is,
- * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
- * exists, which will turn the tree node for "foo.bar" to a leaf node.
- * Likewise, if the field path to add is a sub-path of an existing leaf node,
- * nothing will be changed in the tree.
- */
- FieldMaskTree addFieldPath(String path) {
- String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
- if (parts.length == 0) {
- return this;
- }
- Node node = root;
- boolean createNewBranch = false;
- // Find the matching node in the tree.
- for (String part : parts) {
- // Check whether the path matches an existing leaf node.
- if (!createNewBranch && node != root && node.children.isEmpty()) {
- // The path to add is a sub-path of an existing leaf node.
- return this;
- }
- if (node.children.containsKey(part)) {
- node = node.children.get(part);
- } else {
- createNewBranch = true;
- Node tmp = new Node();
- node.children.put(part, tmp);
- node = tmp;
- }
- }
- // Turn the matching node into a leaf node (i.e., remove sub-paths).
- node.children.clear();
- return this;
- }
-
- /**
- * Merges all field paths in a FieldMask into this tree.
- */
- FieldMaskTree mergeFromFieldMask(FieldMask mask) {
- for (String path : mask.getPathsList()) {
- addFieldPath(path);
- }
- return this;
- }
-
- /**
- * Converts this tree to a FieldMask.
- */
- FieldMask toFieldMask() {
- if (root.children.isEmpty()) {
- return FieldMask.getDefaultInstance();
- }
- List<String> paths = new ArrayList<String>();
- getFieldPaths(root, "", paths);
- return FieldMask.newBuilder().addAllPaths(paths).build();
- }
-
- /**
- * Gathers all field paths in a sub-tree.
- */
- private void getFieldPaths(Node node, String path, List<String> paths) {
- if (node.children.isEmpty()) {
- paths.add(path);
- return;
- }
- for (Entry<String, Node> entry : node.children.entrySet()) {
- String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
- getFieldPaths(entry.getValue(), childPath, paths);
- }
- }
-
- /**
- * Adds the intersection of this tree with the given {@code path} to {@code output}.
- */
- void intersectFieldPath(String path, FieldMaskTree output) {
- if (root.children.isEmpty()) {
- return;
- }
- String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
- if (parts.length == 0) {
- return;
- }
- Node node = root;
- for (String part : parts) {
- if (node != root && node.children.isEmpty()) {
- // The given path is a sub-path of an existing leaf node in the tree.
- output.addFieldPath(path);
- return;
- }
- if (node.children.containsKey(part)) {
- node = node.children.get(part);
- } else {
- return;
- }
- }
- // We found a matching node for the path. All leaf children of this matching
- // node is in the intersection.
- List<String> paths = new ArrayList<String>();
- getFieldPaths(node, path, paths);
- for (String value : paths) {
- output.addFieldPath(value);
- }
- }
-
- /**
- * Merges all fields specified by this FieldMaskTree from {@code source} to {@code destination}.
- */
- void merge(Message source, Message.Builder destination, FieldMaskUtil.MergeOptions options) {
- if (source.getDescriptorForType() != destination.getDescriptorForType()) {
- throw new IllegalArgumentException("Cannot merge messages of different types.");
- }
- if (root.children.isEmpty()) {
- return;
- }
- merge(root, "", source, destination, options);
- }
-
- /**
- * Merges all fields specified by a sub-tree from {@code source} to {@code destination}.
- */
- private void merge(
- Node node,
- String path,
- Message source,
- Message.Builder destination,
- FieldMaskUtil.MergeOptions options) {
- if (source.getDescriptorForType() != destination.getDescriptorForType()) {
- throw new IllegalArgumentException(
- String.format(
- "source (%s) and destination (%s) descriptor must be equal",
- source.getDescriptorForType(), destination.getDescriptorForType()));
- }
-
- Descriptor descriptor = source.getDescriptorForType();
- for (Entry<String, Node> entry : node.children.entrySet()) {
- FieldDescriptor field = descriptor.findFieldByName(entry.getKey());
- if (field == null) {
- logger.warning(
- "Cannot find field \""
- + entry.getKey()
- + "\" in message type "
- + descriptor.getFullName());
- continue;
- }
- if (!entry.getValue().children.isEmpty()) {
- if (field.isRepeated() || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
- logger.warning(
- "Field \""
- + field.getFullName()
- + "\" is not a "
- + "singluar message field and cannot have sub-fields.");
- continue;
- }
- String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
- merge(
- entry.getValue(),
- childPath,
- (Message) source.getField(field),
- destination.getFieldBuilder(field),
- options);
- continue;
- }
- if (field.isRepeated()) {
- if (options.replaceRepeatedFields()) {
- destination.setField(field, source.getField(field));
- } else {
- for (Object element : (List) source.getField(field)) {
- destination.addRepeatedField(field, element);
- }
- }
- } else {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (options.replaceMessageFields()) {
- if (!source.hasField(field)) {
- destination.clearField(field);
- } else {
- destination.setField(field, source.getField(field));
- }
- } else {
- if (source.hasField(field)) {
- destination.getFieldBuilder(field).mergeFrom((Message) source.getField(field));
- }
- }
- } else {
- if (source.hasField(field) || !options.replacePrimitiveFields()) {
- destination.setField(field, source.getField(field));
- } else {
- destination.clearField(field);
- }
- }
- }
- }
- }
-}
diff --git a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
deleted file mode 100644
index 21d11b2ce7..0000000000
--- a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
+++ /dev/null
@@ -1,342 +0,0 @@
-// 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.util;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Joiner;
-import com.google.common.base.Splitter;
-import com.google.common.primitives.Ints;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.FieldMask;
-import com.google.protobuf.Internal;
-import com.google.protobuf.Message;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Utility helper functions to work with {@link com.google.protobuf.FieldMask}.
- */
-public class FieldMaskUtil {
- private static final String FIELD_PATH_SEPARATOR = ",";
- private static final String FIELD_PATH_SEPARATOR_REGEX = ",";
- private static final String FIELD_SEPARATOR_REGEX = "\\.";
-
- private FieldMaskUtil() {}
-
- /**
- * Converts a FieldMask to a string.
- */
- public static String toString(FieldMask fieldMask) {
- // TODO(xiaofeng): Consider using com.google.common.base.Joiner here instead.
- StringBuilder result = new StringBuilder();
- boolean first = true;
- for (String value : fieldMask.getPathsList()) {
- if (value.isEmpty()) {
- // Ignore empty paths.
- continue;
- }
- if (first) {
- first = false;
- } else {
- result.append(FIELD_PATH_SEPARATOR);
- }
- result.append(value);
- }
- return result.toString();
- }
-
- /**
- * Parses from a string to a FieldMask.
- */
- public static FieldMask fromString(String value) {
- // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
- return fromStringList(null, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
- }
-
- /**
- * Parses from a string to a FieldMask and validates all field paths.
- *
- * @throws IllegalArgumentException if any of the field path is invalid.
- */
- public static FieldMask fromString(Class<? extends Message> type, String value) {
- // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
- return fromStringList(type, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
- }
-
- /**
- * Constructs a FieldMask for a list of field paths in a certain type.
- *
- * @throws IllegalArgumentException if any of the field path is not valid.
- */
- // TODO(xiaofeng): Consider renaming fromStrings()
- public static FieldMask fromStringList(Class<? extends Message> type, Iterable<String> paths) {
- FieldMask.Builder builder = FieldMask.newBuilder();
- for (String path : paths) {
- if (path.isEmpty()) {
- // Ignore empty field paths.
- continue;
- }
- if (type != null && !isValid(type, path)) {
- throw new IllegalArgumentException(path + " is not a valid path for " + type);
- }
- builder.addPaths(path);
- }
- return builder.build();
- }
-
- /**
- * Constructs a FieldMask from the passed field numbers.
- *
- * @throws IllegalArgumentException if any of the fields are invalid for the message.
- */
- public static FieldMask fromFieldNumbers(Class<? extends Message> type, int... fieldNumbers) {
- return fromFieldNumbers(type, Ints.asList(fieldNumbers));
- }
-
- /**
- * Constructs a FieldMask from the passed field numbers.
- *
- * @throws IllegalArgumentException if any of the fields are invalid for the message.
- */
- public static FieldMask fromFieldNumbers(
- Class<? extends Message> type, Iterable<Integer> fieldNumbers) {
- Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
-
- FieldMask.Builder builder = FieldMask.newBuilder();
- for (Integer fieldNumber : fieldNumbers) {
- FieldDescriptor field = descriptor.findFieldByNumber(fieldNumber);
- checkArgument(
- field != null,
- String.format("%s is not a valid field number for %s.", fieldNumber, type));
- builder.addPaths(field.getName());
- }
- return builder.build();
- }
-
- /**
- * Converts a field mask to a Proto3 JSON string, that is converting from snake case to camel
- * case and joining all paths into one string with commas.
- */
- public static String toJsonString(FieldMask fieldMask) {
- List<String> paths = new ArrayList<String>(fieldMask.getPathsCount());
- for (String path : fieldMask.getPathsList()) {
- if (path.isEmpty()) {
- continue;
- }
- paths.add(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, path));
- }
- return Joiner.on(FIELD_PATH_SEPARATOR).join(paths);
- }
-
- /**
- * Converts a field mask from a Proto3 JSON string, that is splitting the paths along commas and
- * converting from camel case to snake case.
- */
- public static FieldMask fromJsonString(String value) {
- Iterable<String> paths = Splitter.on(FIELD_PATH_SEPARATOR).split(value);
- FieldMask.Builder builder = FieldMask.newBuilder();
- for (String path : paths) {
- if (path.isEmpty()) {
- continue;
- }
- builder.addPaths(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, path));
- }
- return builder.build();
- }
-
- /**
- * Checks whether paths in a given fields mask are valid.
- */
- public static boolean isValid(Class<? extends Message> type, FieldMask fieldMask) {
- Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
-
- return isValid(descriptor, fieldMask);
- }
-
- /**
- * Checks whether paths in a given fields mask are valid.
- */
- public static boolean isValid(Descriptor descriptor, FieldMask fieldMask) {
- for (String path : fieldMask.getPathsList()) {
- if (!isValid(descriptor, path)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks whether a given field path is valid.
- */
- public static boolean isValid(Class<? extends Message> type, String path) {
- Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
-
- return isValid(descriptor, path);
- }
-
- /**
- * Checks whether paths in a given fields mask are valid.
- */
- public static boolean isValid(Descriptor descriptor, String path) {
- String[] parts = path.split(FIELD_SEPARATOR_REGEX);
- if (parts.length == 0) {
- return false;
- }
- for (String name : parts) {
- if (descriptor == null) {
- return false;
- }
- FieldDescriptor field = descriptor.findFieldByName(name);
- if (field == null) {
- return false;
- }
- if (!field.isRepeated() && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- descriptor = field.getMessageType();
- } else {
- descriptor = null;
- }
- }
- return true;
- }
-
- /**
- * Converts a FieldMask to its canonical form. In the canonical form of a
- * FieldMask, all field paths are sorted alphabetically and redundant field
- * paths are moved.
- */
- public static FieldMask normalize(FieldMask mask) {
- return new FieldMaskTree(mask).toFieldMask();
- }
-
- /**
- * Creates a union of two or more FieldMasks.
- */
- public static FieldMask union(
- FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) {
- FieldMaskTree maskTree = new FieldMaskTree(firstMask).mergeFromFieldMask(secondMask);
- for (FieldMask mask : otherMasks) {
- maskTree.mergeFromFieldMask(mask);
- }
- return maskTree.toFieldMask();
- }
-
- /**
- * Calculates the intersection of two FieldMasks.
- */
- public static FieldMask intersection(FieldMask mask1, FieldMask mask2) {
- FieldMaskTree tree = new FieldMaskTree(mask1);
- FieldMaskTree result = new FieldMaskTree();
- for (String path : mask2.getPathsList()) {
- tree.intersectFieldPath(path, result);
- }
- return result.toFieldMask();
- }
-
- /**
- * Options to customize merging behavior.
- */
- public static final class MergeOptions {
- private boolean replaceMessageFields = false;
- private boolean replaceRepeatedFields = false;
- // TODO(b/28277137): change the default behavior to always replace primitive fields after
- // fixing all failing TAP tests.
- private boolean replacePrimitiveFields = false;
-
- /**
- * Whether to replace message fields (i.e., discard existing content in
- * destination message fields) when merging.
- * Default behavior is to merge the source message field into the
- * destination message field.
- */
- public boolean replaceMessageFields() {
- return replaceMessageFields;
- }
-
- /**
- * Whether to replace repeated fields (i.e., discard existing content in
- * destination repeated fields) when merging.
- * Default behavior is to append elements from source repeated field to the
- * destination repeated field.
- */
- public boolean replaceRepeatedFields() {
- return replaceRepeatedFields;
- }
-
- /**
- * Whether to replace primitive (non-repeated and non-message) fields in
- * destination message fields with the source primitive fields (i.e., if the
- * field is set in the source, the value is copied to the
- * destination; if the field is unset in the source, the field is cleared
- * from the destination) when merging.
- *
- * <p>Default behavior is to always set the value of the source primitive
- * field to the destination primitive field, and if the source field is
- * unset, the default value of the source field is copied to the
- * destination.
- */
- public boolean replacePrimitiveFields() {
- return replacePrimitiveFields;
- }
-
- public void setReplaceMessageFields(boolean value) {
- replaceMessageFields = value;
- }
-
- public void setReplaceRepeatedFields(boolean value) {
- replaceRepeatedFields = value;
- }
-
- public void setReplacePrimitiveFields(boolean value) {
- replacePrimitiveFields = value;
- }
- }
-
- /**
- * Merges fields specified by a FieldMask from one message to another with the
- * specified merge options.
- */
- public static void merge(
- FieldMask mask, Message source, Message.Builder destination, MergeOptions options) {
- new FieldMaskTree(mask).merge(source, destination, options);
- }
-
- /**
- * Merges fields specified by a FieldMask from one message to another.
- */
- public static void merge(FieldMask mask, Message source, Message.Builder destination) {
- merge(mask, source, destination, new MergeOptions());
- }
-}
diff --git a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
deleted file mode 100644
index ac712c9429..0000000000
--- a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
+++ /dev/null
@@ -1,1751 +0,0 @@
-// 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.util;
-
-import com.google.common.io.BaseEncoding;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.stream.JsonReader;
-import com.google.protobuf.Any;
-import com.google.protobuf.BoolValue;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.BytesValue;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.EnumDescriptor;
-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 com.google.protobuf.DoubleValue;
-import com.google.protobuf.Duration;
-import com.google.protobuf.DynamicMessage;
-import com.google.protobuf.FieldMask;
-import com.google.protobuf.FloatValue;
-import com.google.protobuf.Int32Value;
-import com.google.protobuf.Int64Value;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.ListValue;
-import com.google.protobuf.Message;
-import com.google.protobuf.MessageOrBuilder;
-import com.google.protobuf.NullValue;
-import com.google.protobuf.StringValue;
-import com.google.protobuf.Struct;
-import com.google.protobuf.Timestamp;
-import com.google.protobuf.UInt32Value;
-import com.google.protobuf.UInt64Value;
-import com.google.protobuf.Value;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.text.ParseException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.logging.Logger;
-
-/**
- * Utility classes to convert protobuf messages to/from JSON format. The JSON
- * format follows Proto3 JSON specification and only proto3 features are
- * supported. Proto2 only features (e.g., extensions and unknown fields) will
- * be discarded in the conversion. That is, when converting proto2 messages
- * to JSON format, extensions and unknown fields will be treated as if they
- * do not exist. This applies to proto2 messages embedded in proto3 messages
- * as well.
- */
-public class JsonFormat {
- private static final Logger logger = Logger.getLogger(JsonFormat.class.getName());
-
- private JsonFormat() {}
-
- /**
- * Creates a {@link Printer} with default configurations.
- */
- public static Printer printer() {
- return new Printer(TypeRegistry.getEmptyTypeRegistry(), false, false, false);
- }
-
- /**
- * A Printer converts protobuf message to JSON format.
- */
- public static class Printer {
- private final TypeRegistry registry;
- private final boolean includingDefaultValueFields;
- private final boolean preservingProtoFieldNames;
- private final boolean omittingInsignificantWhitespace;
-
- private Printer(
- TypeRegistry registry,
- boolean includingDefaultValueFields,
- boolean preservingProtoFieldNames,
- boolean omittingInsignificantWhitespace) {
- this.registry = registry;
- this.includingDefaultValueFields = includingDefaultValueFields;
- this.preservingProtoFieldNames = preservingProtoFieldNames;
- this.omittingInsignificantWhitespace = omittingInsignificantWhitespace;
- }
-
- /**
- * Creates a new {@link Printer} using the given registry. The new Printer
- * clones all other configurations from the current {@link Printer}.
- *
- * @throws IllegalArgumentException if a registry is already set.
- */
- public Printer usingTypeRegistry(TypeRegistry registry) {
- if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
- throw new IllegalArgumentException("Only one registry is allowed.");
- }
- return new Printer(
- registry,
- includingDefaultValueFields,
- preservingProtoFieldNames,
- omittingInsignificantWhitespace);
- }
-
- /**
- * Creates a new {@link Printer} that will also print fields set to their
- * defaults. Empty repeated fields and map fields will be printed as well.
- * The new Printer clones all other configurations from the current
- * {@link Printer}.
- */
- public Printer includingDefaultValueFields() {
- return new Printer(
- registry, true, preservingProtoFieldNames, omittingInsignificantWhitespace);
- }
-
- /**
- * Creates a new {@link Printer} that is configured to use the original proto
- * field names as defined in the .proto file rather than converting them to
- * lowerCamelCase. The new Printer clones all other configurations from the
- * current {@link Printer}.
- */
- public Printer preservingProtoFieldNames() {
- return new Printer(
- registry, includingDefaultValueFields, true, omittingInsignificantWhitespace);
- }
-
-
- /**
- * Create a new {@link Printer} that will omit all insignificant whitespace
- * in the JSON output. This new Printer clones all other configurations from the
- * current Printer. Insignificant whitespace is defined by the JSON spec as whitespace
- * that appear between JSON structural elements:
- * <pre>
- * ws = *(
- * %x20 / ; Space
- * %x09 / ; Horizontal tab
- * %x0A / ; Line feed or New line
- * %x0D ) ; Carriage return
- * </pre>
- * See <a href="https://tools.ietf.org/html/rfc7159">https://tools.ietf.org/html/rfc7159</a>
- * current {@link Printer}.
- */
- public Printer omittingInsignificantWhitespace() {
- return new Printer(registry, includingDefaultValueFields, preservingProtoFieldNames, true);
- }
-
- /**
- * Converts a protobuf message to JSON format.
- *
- * @throws InvalidProtocolBufferException if the message contains Any types
- * that can't be resolved.
- * @throws IOException if writing to the output fails.
- */
- public void appendTo(MessageOrBuilder message, Appendable output) throws IOException {
- // TODO(xiaofeng): Investigate the allocation overhead and optimize for
- // mobile.
- new PrinterImpl(
- registry,
- includingDefaultValueFields,
- preservingProtoFieldNames,
- output,
- omittingInsignificantWhitespace)
- .print(message);
- }
-
- /**
- * Converts a protobuf message to JSON format. Throws exceptions if there
- * are unknown Any types in the message.
- */
- public String print(MessageOrBuilder message) throws InvalidProtocolBufferException {
- try {
- StringBuilder builder = new StringBuilder();
- appendTo(message, builder);
- return builder.toString();
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- // Unexpected IOException.
- throw new IllegalStateException(e);
- }
- }
- }
-
- /**
- * Creates a {@link Parser} with default configuration.
- */
- public static Parser parser() {
- return new Parser(TypeRegistry.getEmptyTypeRegistry(), false, Parser.DEFAULT_RECURSION_LIMIT);
- }
-
- /**
- * A Parser parses JSON to protobuf message.
- */
- public static class Parser {
- private final TypeRegistry registry;
- private final boolean ignoringUnknownFields;
- private final int recursionLimit;
-
- // The default parsing recursion limit is aligned with the proto binary parser.
- private static final int DEFAULT_RECURSION_LIMIT = 100;
-
- private Parser(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
- this.registry = registry;
- this.ignoringUnknownFields = ignoreUnknownFields;
- this.recursionLimit = recursionLimit;
- }
-
- /**
- * Creates a new {@link Parser} using the given registry. The new Parser
- * clones all other configurations from this Parser.
- *
- * @throws IllegalArgumentException if a registry is already set.
- */
- public Parser usingTypeRegistry(TypeRegistry registry) {
- if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
- throw new IllegalArgumentException("Only one registry is allowed.");
- }
- return new Parser(registry, ignoringUnknownFields, recursionLimit);
- }
-
- /**
- * Creates a new {@link Parser} configured to not throw an exception when an unknown field is
- * encountered. The new Parser clones all other configurations from this Parser.
- */
- public Parser ignoringUnknownFields() {
- return new Parser(this.registry, true, recursionLimit);
- }
-
- /**
- * Parses from JSON into a protobuf message.
- *
- * @throws InvalidProtocolBufferException if the input is not valid JSON
- * format or there are unknown fields in the input.
- */
- public void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException {
- // TODO(xiaofeng): Investigate the allocation overhead and optimize for
- // mobile.
- new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
- }
-
- /**
- * Parses from JSON into a protobuf message.
- *
- * @throws InvalidProtocolBufferException if the input is not valid JSON
- * format or there are unknown fields in the input.
- * @throws IOException if reading from the input throws.
- */
- public void merge(Reader json, Message.Builder builder) throws IOException {
- // TODO(xiaofeng): Investigate the allocation overhead and optimize for
- // mobile.
- new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
- }
-
- // For testing only.
- Parser usingRecursionLimit(int recursionLimit) {
- return new Parser(registry, ignoringUnknownFields, recursionLimit);
- }
- }
-
- /**
- * A TypeRegistry is used to resolve Any messages in the JSON conversion.
- * You must provide a TypeRegistry containing all message types used in
- * Any message fields, or the JSON conversion will fail because data
- * in Any message fields is unrecognizable. You don't need to supply a
- * TypeRegistry if you don't use Any message fields.
- */
- public static class TypeRegistry {
- private static class EmptyTypeRegistryHolder {
- private static final TypeRegistry EMPTY =
- new TypeRegistry(Collections.<String, Descriptor>emptyMap());
- }
-
- public static TypeRegistry getEmptyTypeRegistry() {
- return EmptyTypeRegistryHolder.EMPTY;
- }
-
- public static Builder newBuilder() {
- return new Builder();
- }
-
- /**
- * Find a type by its full name. Returns null if it cannot be found in
- * this {@link TypeRegistry}.
- */
- public Descriptor find(String name) {
- return types.get(name);
- }
-
- private final Map<String, Descriptor> types;
-
- private TypeRegistry(Map<String, Descriptor> types) {
- this.types = types;
- }
-
- /**
- * A Builder is used to build {@link TypeRegistry}.
- */
- public static class Builder {
- private Builder() {}
-
- /**
- * Adds a message type and all types defined in the same .proto file as
- * well as all transitively imported .proto files to this {@link Builder}.
- */
- public Builder add(Descriptor messageType) {
- if (types == null) {
- throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
- }
- addFile(messageType.getFile());
- return this;
- }
-
- /**
- * Adds message types and all types defined in the same .proto file as
- * well as all transitively imported .proto files to this {@link Builder}.
- */
- public Builder add(Iterable<Descriptor> messageTypes) {
- if (types == null) {
- throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
- }
- for (Descriptor type : messageTypes) {
- addFile(type.getFile());
- }
- return this;
- }
-
- /**
- * Builds a {@link TypeRegistry}. This method can only be called once for
- * one Builder.
- */
- public TypeRegistry build() {
- TypeRegistry result = new TypeRegistry(types);
- // Make sure the built {@link TypeRegistry} is immutable.
- types = null;
- return result;
- }
-
- private void addFile(FileDescriptor file) {
- // Skip the file if it's already added.
- if (!files.add(file.getFullName())) {
- return;
- }
- for (FileDescriptor dependency : file.getDependencies()) {
- addFile(dependency);
- }
- for (Descriptor message : file.getMessageTypes()) {
- addMessage(message);
- }
- }
-
- private void addMessage(Descriptor message) {
- for (Descriptor nestedType : message.getNestedTypes()) {
- addMessage(nestedType);
- }
-
- if (types.containsKey(message.getFullName())) {
- logger.warning("Type " + message.getFullName() + " is added multiple times.");
- return;
- }
-
- types.put(message.getFullName(), message);
- }
-
- private final Set<String> files = new HashSet<String>();
- private Map<String, Descriptor> types = new HashMap<String, Descriptor>();
- }
- }
-
- /**
- * An interface for json formatting that can be used in
- * combination with the omittingInsignificantWhitespace() method
- */
- interface TextGenerator {
- void indent();
-
- void outdent();
-
- void print(final CharSequence text) throws IOException;
- }
-
- /**
- * Format the json without indentation
- */
- private static final class CompactTextGenerator implements TextGenerator {
- private final Appendable output;
-
- private CompactTextGenerator(final Appendable output) {
- this.output = output;
- }
-
- /**
- * ignored by compact printer
- */
- public void indent() {}
-
- /**
- * ignored by compact printer
- */
- public void outdent() {}
-
- /**
- * Print text to the output stream.
- */
- public void print(final CharSequence text) throws IOException {
- output.append(text);
- }
- }
- /**
- * A TextGenerator adds indentation when writing formatted text.
- */
- private static final class PrettyTextGenerator implements TextGenerator {
- private final Appendable output;
- private final StringBuilder indent = new StringBuilder();
- private boolean atStartOfLine = true;
-
- private PrettyTextGenerator(final Appendable output) {
- this.output = output;
- }
-
- /**
- * Indent text by two spaces. After calling Indent(), two spaces will be
- * inserted at the beginning of each line of text. Indent() may be called
- * multiple times to produce deeper indents.
- */
- public void indent() {
- indent.append(" ");
- }
-
- /**
- * Reduces the current indent level by two spaces, or crashes if the indent
- * level is zero.
- */
- public void outdent() {
- final int length = indent.length();
- if (length < 2) {
- throw new IllegalArgumentException(" Outdent() without matching Indent().");
- }
- indent.delete(length - 2, length);
- }
-
- /**
- * Print text to the output stream.
- */
- public void print(final CharSequence text) throws IOException {
- final int size = text.length();
- int pos = 0;
-
- for (int i = 0; i < size; i++) {
- if (text.charAt(i) == '\n') {
- write(text.subSequence(pos, i + 1));
- pos = i + 1;
- atStartOfLine = true;
- }
- }
- write(text.subSequence(pos, size));
- }
-
- private void write(final CharSequence data) throws IOException {
- if (data.length() == 0) {
- return;
- }
- if (atStartOfLine) {
- atStartOfLine = false;
- output.append(indent);
- }
- output.append(data);
- }
- }
-
- /**
- * A Printer converts protobuf messages to JSON format.
- */
- private static final class PrinterImpl {
- private final TypeRegistry registry;
- private final boolean includingDefaultValueFields;
- private final boolean preservingProtoFieldNames;
- private final TextGenerator generator;
- // We use Gson to help handle string escapes.
- private final Gson gson;
- private final CharSequence blankOrSpace;
- private final CharSequence blankOrNewLine;
-
- private static class GsonHolder {
- private static final Gson DEFAULT_GSON = new GsonBuilder().disableHtmlEscaping().create();
- }
-
- PrinterImpl(
- TypeRegistry registry,
- boolean includingDefaultValueFields,
- boolean preservingProtoFieldNames,
- Appendable jsonOutput,
- boolean omittingInsignificantWhitespace) {
- this.registry = registry;
- this.includingDefaultValueFields = includingDefaultValueFields;
- this.preservingProtoFieldNames = preservingProtoFieldNames;
- this.gson = GsonHolder.DEFAULT_GSON;
- // json format related properties, determined by printerType
- if (omittingInsignificantWhitespace) {
- this.generator = new CompactTextGenerator(jsonOutput);
- this.blankOrSpace = "";
- this.blankOrNewLine = "";
- } else {
- this.generator = new PrettyTextGenerator(jsonOutput);
- this.blankOrSpace = " ";
- this.blankOrNewLine = "\n";
- }
- }
-
- void print(MessageOrBuilder message) throws IOException {
- WellKnownTypePrinter specialPrinter =
- wellKnownTypePrinters.get(message.getDescriptorForType().getFullName());
- if (specialPrinter != null) {
- specialPrinter.print(this, message);
- return;
- }
- print(message, null);
- }
-
- private interface WellKnownTypePrinter {
- void print(PrinterImpl printer, MessageOrBuilder message) throws IOException;
- }
-
- private static final Map<String, WellKnownTypePrinter> wellKnownTypePrinters =
- buildWellKnownTypePrinters();
-
- private static Map<String, WellKnownTypePrinter> buildWellKnownTypePrinters() {
- Map<String, WellKnownTypePrinter> printers = new HashMap<String, WellKnownTypePrinter>();
- // Special-case Any.
- printers.put(
- Any.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printAny(message);
- }
- });
- // Special-case wrapper types.
- WellKnownTypePrinter wrappersPrinter =
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printWrapper(message);
- }
- };
- printers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
- printers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
- // Special-case Timestamp.
- printers.put(
- Timestamp.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printTimestamp(message);
- }
- });
- // Special-case Duration.
- printers.put(
- Duration.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printDuration(message);
- }
- });
- // Special-case FieldMask.
- printers.put(
- FieldMask.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printFieldMask(message);
- }
- });
- // Special-case Struct.
- printers.put(
- Struct.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printStruct(message);
- }
- });
- // Special-case Value.
- printers.put(
- Value.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printValue(message);
- }
- });
- // Special-case ListValue.
- printers.put(
- ListValue.getDescriptor().getFullName(),
- new WellKnownTypePrinter() {
- @Override
- public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
- printer.printListValue(message);
- }
- });
- return printers;
- }
-
- /** Prints google.protobuf.Any */
- private void printAny(MessageOrBuilder message) throws IOException {
- if (Any.getDefaultInstance().equals(message)) {
- generator.print("{}");
- return;
- }
- Descriptor descriptor = message.getDescriptorForType();
- FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
- FieldDescriptor valueField = descriptor.findFieldByName("value");
- // Validates type of the message. Note that we can't just cast the message
- // to com.google.protobuf.Any because it might be a DynamicMessage.
- if (typeUrlField == null
- || valueField == null
- || typeUrlField.getType() != FieldDescriptor.Type.STRING
- || valueField.getType() != FieldDescriptor.Type.BYTES) {
- throw new InvalidProtocolBufferException("Invalid Any type.");
- }
- String typeUrl = (String) message.getField(typeUrlField);
- String typeName = getTypeName(typeUrl);
- Descriptor type = registry.find(typeName);
- if (type == null) {
- throw new InvalidProtocolBufferException("Cannot find type for url: " + typeUrl);
- }
- ByteString content = (ByteString) message.getField(valueField);
- Message contentMessage =
- DynamicMessage.getDefaultInstance(type).getParserForType().parseFrom(content);
- WellKnownTypePrinter printer = wellKnownTypePrinters.get(typeName);
- if (printer != null) {
- // If the type is one of the well-known types, we use a special
- // formatting.
- generator.print("{" + blankOrNewLine);
- generator.indent();
- generator.print("\"@type\":" + blankOrSpace + gson.toJson(typeUrl) + "," + blankOrNewLine);
- generator.print("\"value\":" + blankOrSpace);
- printer.print(this, contentMessage);
- generator.print(blankOrNewLine);
- generator.outdent();
- generator.print("}");
- } else {
- // Print the content message instead (with a "@type" field added).
- print(contentMessage, typeUrl);
- }
- }
-
- /** Prints wrapper types (e.g., google.protobuf.Int32Value) */
- private void printWrapper(MessageOrBuilder message) throws IOException {
- Descriptor descriptor = message.getDescriptorForType();
- FieldDescriptor valueField = descriptor.findFieldByName("value");
- if (valueField == null) {
- throw new InvalidProtocolBufferException("Invalid Wrapper type.");
- }
- // When formatting wrapper types, we just print its value field instead of
- // the whole message.
- printSingleFieldValue(valueField, message.getField(valueField));
- }
-
- private ByteString toByteString(MessageOrBuilder message) {
- if (message instanceof Message) {
- return ((Message) message).toByteString();
- } else {
- return ((Message.Builder) message).build().toByteString();
- }
- }
-
- /** Prints google.protobuf.Timestamp */
- private void printTimestamp(MessageOrBuilder message) throws IOException {
- Timestamp value = Timestamp.parseFrom(toByteString(message));
- generator.print("\"" + Timestamps.toString(value) + "\"");
- }
-
- /** Prints google.protobuf.Duration */
- private void printDuration(MessageOrBuilder message) throws IOException {
- Duration value = Duration.parseFrom(toByteString(message));
- generator.print("\"" + Durations.toString(value) + "\"");
- }
-
- /** Prints google.protobuf.FieldMask */
- private void printFieldMask(MessageOrBuilder message) throws IOException {
- FieldMask value = FieldMask.parseFrom(toByteString(message));
- generator.print("\"" + FieldMaskUtil.toJsonString(value) + "\"");
- }
-
- /** Prints google.protobuf.Struct */
- private void printStruct(MessageOrBuilder message) throws IOException {
- Descriptor descriptor = message.getDescriptorForType();
- FieldDescriptor field = descriptor.findFieldByName("fields");
- if (field == null) {
- throw new InvalidProtocolBufferException("Invalid Struct type.");
- }
- // Struct is formatted as a map object.
- printMapFieldValue(field, message.getField(field));
- }
-
- /** Prints google.protobuf.Value */
- private void printValue(MessageOrBuilder message) throws IOException {
- // For a Value message, only the value of the field is formatted.
- Map<FieldDescriptor, Object> fields = message.getAllFields();
- if (fields.isEmpty()) {
- // No value set.
- generator.print("null");
- return;
- }
- // A Value message can only have at most one field set (it only contains
- // an oneof).
- if (fields.size() != 1) {
- throw new InvalidProtocolBufferException("Invalid Value type.");
- }
- for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
- printSingleFieldValue(entry.getKey(), entry.getValue());
- }
- }
-
- /** Prints google.protobuf.ListValue */
- private void printListValue(MessageOrBuilder message) throws IOException {
- Descriptor descriptor = message.getDescriptorForType();
- FieldDescriptor field = descriptor.findFieldByName("values");
- if (field == null) {
- throw new InvalidProtocolBufferException("Invalid ListValue type.");
- }
- printRepeatedFieldValue(field, message.getField(field));
- }
-
- /** Prints a regular message with an optional type URL. */
- private void print(MessageOrBuilder message, String typeUrl) throws IOException {
- generator.print("{" + blankOrNewLine);
- generator.indent();
-
- boolean printedField = false;
- if (typeUrl != null) {
- generator.print("\"@type\":" + blankOrSpace + gson.toJson(typeUrl));
- printedField = true;
- }
- Map<FieldDescriptor, Object> fieldsToPrint = null;
- if (includingDefaultValueFields) {
- fieldsToPrint = new TreeMap<FieldDescriptor, Object>();
- for (FieldDescriptor field : message.getDescriptorForType().getFields()) {
- if (field.isOptional()) {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
- && !message.hasField(field)){
- // Always skip empty optional message fields. If not we will recurse indefinitely if
- // a message has itself as a sub-field.
- continue;
- }
- OneofDescriptor oneof = field.getContainingOneof();
- if (oneof != null && !message.hasField(field)) {
- // Skip all oneof fields except the one that is actually set
- continue;
- }
- }
- fieldsToPrint.put(field, message.getField(field));
- }
- } else {
- fieldsToPrint = message.getAllFields();
- }
- for (Map.Entry<FieldDescriptor, Object> field : fieldsToPrint.entrySet()) {
- if (printedField) {
- // Add line-endings for the previous field.
- generator.print("," + blankOrNewLine);
- } else {
- printedField = true;
- }
- printField(field.getKey(), field.getValue());
- }
-
- // Add line-endings for the last field.
- if (printedField) {
- generator.print(blankOrNewLine);
- }
- generator.outdent();
- generator.print("}");
- }
-
- private void printField(FieldDescriptor field, Object value) throws IOException {
- if (preservingProtoFieldNames) {
- generator.print("\"" + field.getName() + "\":" + blankOrSpace);
- } else {
- generator.print("\"" + field.getJsonName() + "\":" + blankOrSpace);
- }
- if (field.isMapField()) {
- printMapFieldValue(field, value);
- } else if (field.isRepeated()) {
- printRepeatedFieldValue(field, value);
- } else {
- printSingleFieldValue(field, value);
- }
- }
-
- @SuppressWarnings("rawtypes")
- private void printRepeatedFieldValue(FieldDescriptor field, Object value) throws IOException {
- generator.print("[");
- boolean printedElement = false;
- for (Object element : (List) value) {
- if (printedElement) {
- generator.print("," + blankOrSpace);
- } else {
- printedElement = true;
- }
- printSingleFieldValue(field, element);
- }
- generator.print("]");
- }
-
- @SuppressWarnings("rawtypes")
- private void printMapFieldValue(FieldDescriptor field, Object value) throws IOException {
- Descriptor type = field.getMessageType();
- FieldDescriptor keyField = type.findFieldByName("key");
- FieldDescriptor valueField = type.findFieldByName("value");
- if (keyField == null || valueField == null) {
- throw new InvalidProtocolBufferException("Invalid map field.");
- }
- generator.print("{" + blankOrNewLine);
- generator.indent();
- boolean printedElement = false;
- for (Object element : (List) value) {
- Message entry = (Message) element;
- Object entryKey = entry.getField(keyField);
- Object entryValue = entry.getField(valueField);
- if (printedElement) {
- generator.print("," + blankOrNewLine);
- } else {
- printedElement = true;
- }
- // Key fields are always double-quoted.
- printSingleFieldValue(keyField, entryKey, true);
- generator.print(":" + blankOrSpace);
- printSingleFieldValue(valueField, entryValue);
- }
- if (printedElement) {
- generator.print(blankOrNewLine);
- }
- generator.outdent();
- generator.print("}");
- }
-
- private void printSingleFieldValue(FieldDescriptor field, Object value) throws IOException {
- printSingleFieldValue(field, value, false);
- }
-
- /**
- * Prints a field's value in JSON format.
- *
- * @param alwaysWithQuotes whether to always add double-quotes to primitive
- * types.
- */
- private void printSingleFieldValue(
- final FieldDescriptor field, final Object value, boolean alwaysWithQuotes)
- throws IOException {
- switch (field.getType()) {
- case INT32:
- case SINT32:
- case SFIXED32:
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- generator.print(((Integer) value).toString());
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- break;
-
- case INT64:
- case SINT64:
- case SFIXED64:
- generator.print("\"" + ((Long) value).toString() + "\"");
- break;
-
- case BOOL:
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- if (((Boolean) value).booleanValue()) {
- generator.print("true");
- } else {
- generator.print("false");
- }
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- break;
-
- case FLOAT:
- Float floatValue = (Float) value;
- if (floatValue.isNaN()) {
- generator.print("\"NaN\"");
- } else if (floatValue.isInfinite()) {
- if (floatValue < 0) {
- generator.print("\"-Infinity\"");
- } else {
- generator.print("\"Infinity\"");
- }
- } else {
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- generator.print(floatValue.toString());
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- }
- break;
-
- case DOUBLE:
- Double doubleValue = (Double) value;
- if (doubleValue.isNaN()) {
- generator.print("\"NaN\"");
- } else if (doubleValue.isInfinite()) {
- if (doubleValue < 0) {
- generator.print("\"-Infinity\"");
- } else {
- generator.print("\"Infinity\"");
- }
- } else {
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- generator.print(doubleValue.toString());
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- }
- break;
-
- case UINT32:
- case FIXED32:
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- generator.print(unsignedToString((Integer) value));
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- break;
-
- case UINT64:
- case FIXED64:
- generator.print("\"" + unsignedToString((Long) value) + "\"");
- break;
-
- case STRING:
- generator.print(gson.toJson(value));
- break;
-
- case BYTES:
- generator.print("\"");
- generator.print(BaseEncoding.base64().encode(((ByteString) value).toByteArray()));
- generator.print("\"");
- break;
-
- case ENUM:
- // Special-case google.protobuf.NullValue (it's an Enum).
- if (field.getEnumType().getFullName().equals("google.protobuf.NullValue")) {
- // No matter what value it contains, we always print it as "null".
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- generator.print("null");
- if (alwaysWithQuotes) {
- generator.print("\"");
- }
- } else {
- if (((EnumValueDescriptor) value).getIndex() == -1) {
- generator.print(String.valueOf(((EnumValueDescriptor) value).getNumber()));
- } else {
- generator.print("\"" + ((EnumValueDescriptor) value).getName() + "\"");
- }
- }
- break;
-
- case MESSAGE:
- case GROUP:
- print((Message) value);
- break;
- }
- }
- }
-
- /** Convert an unsigned 32-bit integer to a string. */
- private static String unsignedToString(final int value) {
- if (value >= 0) {
- return Integer.toString(value);
- } else {
- return Long.toString(value & 0x00000000FFFFFFFFL);
- }
- }
-
- /** Convert an unsigned 64-bit integer to a string. */
- private static String unsignedToString(final long value) {
- if (value >= 0) {
- return Long.toString(value);
- } else {
- // Pull off the most-significant bit so that BigInteger doesn't think
- // the number is negative, then set it again using setBit().
- return BigInteger.valueOf(value & Long.MAX_VALUE).setBit(Long.SIZE - 1).toString();
- }
- }
-
- private static String getTypeName(String typeUrl) throws InvalidProtocolBufferException {
- String[] parts = typeUrl.split("/");
- if (parts.length == 1) {
- throw new InvalidProtocolBufferException("Invalid type url found: " + typeUrl);
- }
- return parts[parts.length - 1];
- }
-
- private static class ParserImpl {
- private final TypeRegistry registry;
- private final JsonParser jsonParser;
- private final boolean ignoringUnknownFields;
- private final int recursionLimit;
- private int currentDepth;
-
- ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
- this.registry = registry;
- this.ignoringUnknownFields = ignoreUnknownFields;
- this.jsonParser = new JsonParser();
- this.recursionLimit = recursionLimit;
- this.currentDepth = 0;
- }
-
- void merge(Reader json, Message.Builder builder) throws IOException {
- JsonReader reader = new JsonReader(json);
- reader.setLenient(false);
- merge(jsonParser.parse(reader), builder);
- }
-
- void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException {
- try {
- JsonReader reader = new JsonReader(new StringReader(json));
- reader.setLenient(false);
- merge(jsonParser.parse(reader), builder);
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (Exception e) {
- // We convert all exceptions from JSON parsing to our own exceptions.
- throw new InvalidProtocolBufferException(e.getMessage());
- }
- }
-
- private interface WellKnownTypeParser {
- void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException;
- }
-
- private static final Map<String, WellKnownTypeParser> wellKnownTypeParsers =
- buildWellKnownTypeParsers();
-
- private static Map<String, WellKnownTypeParser> buildWellKnownTypeParsers() {
- Map<String, WellKnownTypeParser> parsers = new HashMap<String, WellKnownTypeParser>();
- // Special-case Any.
- parsers.put(
- Any.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeAny(json, builder);
- }
- });
- // Special-case wrapper types.
- WellKnownTypeParser wrappersPrinter =
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeWrapper(json, builder);
- }
- };
- parsers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
- parsers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
- // Special-case Timestamp.
- parsers.put(
- Timestamp.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeTimestamp(json, builder);
- }
- });
- // Special-case Duration.
- parsers.put(
- Duration.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeDuration(json, builder);
- }
- });
- // Special-case FieldMask.
- parsers.put(
- FieldMask.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeFieldMask(json, builder);
- }
- });
- // Special-case Struct.
- parsers.put(
- Struct.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeStruct(json, builder);
- }
- });
- // Special-case ListValue.
- parsers.put(
- ListValue.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeListValue(json, builder);
- }
- });
- // Special-case Value.
- parsers.put(
- Value.getDescriptor().getFullName(),
- new WellKnownTypeParser() {
- @Override
- public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- parser.mergeValue(json, builder);
- }
- });
- return parsers;
- }
-
- private void merge(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- WellKnownTypeParser specialParser =
- wellKnownTypeParsers.get(builder.getDescriptorForType().getFullName());
- if (specialParser != null) {
- specialParser.merge(this, json, builder);
- return;
- }
- mergeMessage(json, builder, false);
- }
-
- // Maps from camel-case field names to FieldDescriptor.
- private final Map<Descriptor, Map<String, FieldDescriptor>> fieldNameMaps =
- new HashMap<Descriptor, Map<String, FieldDescriptor>>();
-
- private Map<String, FieldDescriptor> getFieldNameMap(Descriptor descriptor) {
- if (!fieldNameMaps.containsKey(descriptor)) {
- Map<String, FieldDescriptor> fieldNameMap = new HashMap<String, FieldDescriptor>();
- for (FieldDescriptor field : descriptor.getFields()) {
- fieldNameMap.put(field.getName(), field);
- fieldNameMap.put(field.getJsonName(), field);
- }
- fieldNameMaps.put(descriptor, fieldNameMap);
- return fieldNameMap;
- }
- return fieldNameMaps.get(descriptor);
- }
-
- private void mergeMessage(JsonElement json, Message.Builder builder, boolean skipTypeUrl)
- throws InvalidProtocolBufferException {
- if (!(json instanceof JsonObject)) {
- throw new InvalidProtocolBufferException("Expect message object but got: " + json);
- }
- JsonObject object = (JsonObject) json;
- Map<String, FieldDescriptor> fieldNameMap = getFieldNameMap(builder.getDescriptorForType());
- for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
- if (skipTypeUrl && entry.getKey().equals("@type")) {
- continue;
- }
- FieldDescriptor field = fieldNameMap.get(entry.getKey());
- if (field == null) {
- if (ignoringUnknownFields) {
- continue;
- }
- throw new InvalidProtocolBufferException(
- "Cannot find field: "
- + entry.getKey()
- + " in message "
- + builder.getDescriptorForType().getFullName());
- }
- mergeField(field, entry.getValue(), builder);
- }
- }
-
- private void mergeAny(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- Descriptor descriptor = builder.getDescriptorForType();
- FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
- FieldDescriptor valueField = descriptor.findFieldByName("value");
- // Validates type of the message. Note that we can't just cast the message
- // to com.google.protobuf.Any because it might be a DynamicMessage.
- if (typeUrlField == null
- || valueField == null
- || typeUrlField.getType() != FieldDescriptor.Type.STRING
- || valueField.getType() != FieldDescriptor.Type.BYTES) {
- throw new InvalidProtocolBufferException("Invalid Any type.");
- }
-
- if (!(json instanceof JsonObject)) {
- throw new InvalidProtocolBufferException("Expect message object but got: " + json);
- }
- JsonObject object = (JsonObject) json;
- if (object.entrySet().isEmpty()) {
- return; // builder never modified, so it will end up building the default instance of Any
- }
- JsonElement typeUrlElement = object.get("@type");
- if (typeUrlElement == null) {
- throw new InvalidProtocolBufferException("Missing type url when parsing: " + json);
- }
- String typeUrl = typeUrlElement.getAsString();
- Descriptor contentType = registry.find(getTypeName(typeUrl));
- if (contentType == null) {
- throw new InvalidProtocolBufferException("Cannot resolve type: " + typeUrl);
- }
- builder.setField(typeUrlField, typeUrl);
- Message.Builder contentBuilder =
- DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
- WellKnownTypeParser specialParser = wellKnownTypeParsers.get(contentType.getFullName());
- if (specialParser != null) {
- JsonElement value = object.get("value");
- if (value != null) {
- specialParser.merge(this, value, contentBuilder);
- }
- } else {
- mergeMessage(json, contentBuilder, true);
- }
- builder.setField(valueField, contentBuilder.build().toByteString());
- }
-
- private void mergeFieldMask(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- FieldMask value = FieldMaskUtil.fromJsonString(json.getAsString());
- builder.mergeFrom(value.toByteString());
- }
-
- private void mergeTimestamp(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- try {
- Timestamp value = Timestamps.parse(json.getAsString());
- builder.mergeFrom(value.toByteString());
- } catch (ParseException e) {
- throw new InvalidProtocolBufferException("Failed to parse timestamp: " + json);
- }
- }
-
- private void mergeDuration(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- try {
- Duration value = Durations.parse(json.getAsString());
- builder.mergeFrom(value.toByteString());
- } catch (ParseException e) {
- throw new InvalidProtocolBufferException("Failed to parse duration: " + json);
- }
- }
-
- private void mergeStruct(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- Descriptor descriptor = builder.getDescriptorForType();
- FieldDescriptor field = descriptor.findFieldByName("fields");
- if (field == null) {
- throw new InvalidProtocolBufferException("Invalid Struct type.");
- }
- mergeMapField(field, json, builder);
- }
-
- private void mergeListValue(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- Descriptor descriptor = builder.getDescriptorForType();
- FieldDescriptor field = descriptor.findFieldByName("values");
- if (field == null) {
- throw new InvalidProtocolBufferException("Invalid ListValue type.");
- }
- mergeRepeatedField(field, json, builder);
- }
-
- private void mergeValue(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- Descriptor type = builder.getDescriptorForType();
- if (json instanceof JsonPrimitive) {
- JsonPrimitive primitive = (JsonPrimitive) json;
- if (primitive.isBoolean()) {
- builder.setField(type.findFieldByName("bool_value"), primitive.getAsBoolean());
- } else if (primitive.isNumber()) {
- builder.setField(type.findFieldByName("number_value"), primitive.getAsDouble());
- } else {
- builder.setField(type.findFieldByName("string_value"), primitive.getAsString());
- }
- } else if (json instanceof JsonObject) {
- FieldDescriptor field = type.findFieldByName("struct_value");
- Message.Builder structBuilder = builder.newBuilderForField(field);
- merge(json, structBuilder);
- builder.setField(field, structBuilder.build());
- } else if (json instanceof JsonArray) {
- FieldDescriptor field = type.findFieldByName("list_value");
- Message.Builder listBuilder = builder.newBuilderForField(field);
- merge(json, listBuilder);
- builder.setField(field, listBuilder.build());
- } else if (json instanceof JsonNull) {
- builder.setField(
- type.findFieldByName("null_value"), NullValue.NULL_VALUE.getValueDescriptor());
- } else {
- throw new IllegalStateException("Unexpected json data: " + json);
- }
- }
-
- private void mergeWrapper(JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- Descriptor type = builder.getDescriptorForType();
- FieldDescriptor field = type.findFieldByName("value");
- if (field == null) {
- throw new InvalidProtocolBufferException("Invalid wrapper type: " + type.getFullName());
- }
- builder.setField(field, parseFieldValue(field, json, builder));
- }
-
- private void mergeField(FieldDescriptor field, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- if (field.isRepeated()) {
- if (builder.getRepeatedFieldCount(field) > 0) {
- throw new InvalidProtocolBufferException(
- "Field " + field.getFullName() + " has already been set.");
- }
- } else {
- if (builder.hasField(field)) {
- throw new InvalidProtocolBufferException(
- "Field " + field.getFullName() + " has already been set.");
- }
- if (field.getContainingOneof() != null
- && builder.getOneofFieldDescriptor(field.getContainingOneof()) != null) {
- FieldDescriptor other = builder.getOneofFieldDescriptor(field.getContainingOneof());
- throw new InvalidProtocolBufferException(
- "Cannot set field "
- + field.getFullName()
- + " because another field "
- + other.getFullName()
- + " belonging to the same oneof has already been set ");
- }
- }
- if (field.isRepeated() && json instanceof JsonNull) {
- // We allow "null" as value for all field types and treat it as if the
- // field is not present.
- return;
- }
- if (field.isMapField()) {
- mergeMapField(field, json, builder);
- } else if (field.isRepeated()) {
- mergeRepeatedField(field, json, builder);
- } else {
- Object value = parseFieldValue(field, json, builder);
- if (value != null) {
- builder.setField(field, value);
- }
- }
- }
-
- private void mergeMapField(FieldDescriptor field, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- if (!(json instanceof JsonObject)) {
- throw new InvalidProtocolBufferException("Expect a map object but found: " + json);
- }
- Descriptor type = field.getMessageType();
- FieldDescriptor keyField = type.findFieldByName("key");
- FieldDescriptor valueField = type.findFieldByName("value");
- if (keyField == null || valueField == null) {
- throw new InvalidProtocolBufferException("Invalid map field: " + field.getFullName());
- }
- JsonObject object = (JsonObject) json;
- for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
- Message.Builder entryBuilder = builder.newBuilderForField(field);
- Object key = parseFieldValue(keyField, new JsonPrimitive(entry.getKey()), entryBuilder);
- Object value = parseFieldValue(valueField, entry.getValue(), entryBuilder);
- if (value == null) {
- throw new InvalidProtocolBufferException("Map value cannot be null.");
- }
- entryBuilder.setField(keyField, key);
- entryBuilder.setField(valueField, value);
- builder.addRepeatedField(field, entryBuilder.build());
- }
- }
-
- /**
- * Gets the default value for a field type. Note that we use proto3
- * language defaults and ignore any default values set through the
- * proto "default" option.
- */
- private Object getDefaultValue(FieldDescriptor field, Message.Builder builder) {
- switch (field.getType()) {
- case INT32:
- case SINT32:
- case SFIXED32:
- case UINT32:
- case FIXED32:
- return 0;
- case INT64:
- case SINT64:
- case SFIXED64:
- case UINT64:
- case FIXED64:
- return 0L;
- case FLOAT:
- return 0.0f;
- case DOUBLE:
- return 0.0;
- case BOOL:
- return false;
- case STRING:
- return "";
- case BYTES:
- return ByteString.EMPTY;
- case ENUM:
- return field.getEnumType().getValues().get(0);
- case MESSAGE:
- case GROUP:
- return builder.newBuilderForField(field).getDefaultInstanceForType();
- default:
- throw new IllegalStateException("Invalid field type: " + field.getType());
- }
- }
-
- private void mergeRepeatedField(
- FieldDescriptor field, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- if (!(json instanceof JsonArray)) {
- throw new InvalidProtocolBufferException("Expect an array but found: " + json);
- }
- JsonArray array = (JsonArray) json;
- for (int i = 0; i < array.size(); ++i) {
- Object value = parseFieldValue(field, array.get(i), builder);
- if (value == null) {
- throw new InvalidProtocolBufferException("Repeated field elements cannot be null");
- }
- builder.addRepeatedField(field, value);
- }
- }
-
- private int parseInt32(JsonElement json) throws InvalidProtocolBufferException {
- try {
- return Integer.parseInt(json.getAsString());
- } catch (Exception e) {
- // Fall through.
- }
- // JSON doesn't distinguish between integer values and floating point values so "1" and
- // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
- // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
- try {
- BigDecimal value = new BigDecimal(json.getAsString());
- return value.intValueExact();
- } catch (Exception e) {
- throw new InvalidProtocolBufferException("Not an int32 value: " + json);
- }
- }
-
- private long parseInt64(JsonElement json) throws InvalidProtocolBufferException {
- try {
- return Long.parseLong(json.getAsString());
- } catch (Exception e) {
- // Fall through.
- }
- // JSON doesn't distinguish between integer values and floating point values so "1" and
- // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
- // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
- try {
- BigDecimal value = new BigDecimal(json.getAsString());
- return value.longValueExact();
- } catch (Exception e) {
- throw new InvalidProtocolBufferException("Not an int32 value: " + json);
- }
- }
-
- private int parseUint32(JsonElement json) throws InvalidProtocolBufferException {
- try {
- long result = Long.parseLong(json.getAsString());
- if (result < 0 || result > 0xFFFFFFFFL) {
- throw new InvalidProtocolBufferException("Out of range uint32 value: " + json);
- }
- return (int) result;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (Exception e) {
- // Fall through.
- }
- // JSON doesn't distinguish between integer values and floating point values so "1" and
- // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
- // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
- try {
- BigDecimal decimalValue = new BigDecimal(json.getAsString());
- BigInteger value = decimalValue.toBigIntegerExact();
- if (value.signum() < 0 || value.compareTo(new BigInteger("FFFFFFFF", 16)) > 0) {
- throw new InvalidProtocolBufferException("Out of range uint32 value: " + json);
- }
- return value.intValue();
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (Exception e) {
- throw new InvalidProtocolBufferException("Not an uint32 value: " + json);
- }
- }
-
- private static final BigInteger MAX_UINT64 = new BigInteger("FFFFFFFFFFFFFFFF", 16);
-
- private long parseUint64(JsonElement json) throws InvalidProtocolBufferException {
- try {
- BigDecimal decimalValue = new BigDecimal(json.getAsString());
- BigInteger value = decimalValue.toBigIntegerExact();
- if (value.compareTo(BigInteger.ZERO) < 0 || value.compareTo(MAX_UINT64) > 0) {
- throw new InvalidProtocolBufferException("Out of range uint64 value: " + json);
- }
- return value.longValue();
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (Exception e) {
- throw new InvalidProtocolBufferException("Not an uint64 value: " + json);
- }
- }
-
- private boolean parseBool(JsonElement json) throws InvalidProtocolBufferException {
- if (json.getAsString().equals("true")) {
- return true;
- }
- if (json.getAsString().equals("false")) {
- return false;
- }
- throw new InvalidProtocolBufferException("Invalid bool value: " + json);
- }
-
- private static final double EPSILON = 1e-6;
-
- private float parseFloat(JsonElement json) throws InvalidProtocolBufferException {
- if (json.getAsString().equals("NaN")) {
- return Float.NaN;
- } else if (json.getAsString().equals("Infinity")) {
- return Float.POSITIVE_INFINITY;
- } else if (json.getAsString().equals("-Infinity")) {
- return Float.NEGATIVE_INFINITY;
- }
- try {
- // We don't use Float.parseFloat() here because that function simply
- // accepts all double values. Here we parse the value into a Double
- // and do explicit range check on it.
- double value = Double.parseDouble(json.getAsString());
- // When a float value is printed, the printed value might be a little
- // larger or smaller due to precision loss. Here we need to add a bit
- // of tolerance when checking whether the float value is in range.
- if (value > Float.MAX_VALUE * (1.0 + EPSILON)
- || value < -Float.MAX_VALUE * (1.0 + EPSILON)) {
- throw new InvalidProtocolBufferException("Out of range float value: " + json);
- }
- return (float) value;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (Exception e) {
- throw new InvalidProtocolBufferException("Not a float value: " + json);
- }
- }
-
- private static final BigDecimal MORE_THAN_ONE = new BigDecimal(String.valueOf(1.0 + EPSILON));
- // When a float value is printed, the printed value might be a little
- // larger or smaller due to precision loss. Here we need to add a bit
- // of tolerance when checking whether the float value is in range.
- private static final BigDecimal MAX_DOUBLE =
- new BigDecimal(String.valueOf(Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
- private static final BigDecimal MIN_DOUBLE =
- new BigDecimal(String.valueOf(-Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
-
- private double parseDouble(JsonElement json) throws InvalidProtocolBufferException {
- if (json.getAsString().equals("NaN")) {
- return Double.NaN;
- } else if (json.getAsString().equals("Infinity")) {
- return Double.POSITIVE_INFINITY;
- } else if (json.getAsString().equals("-Infinity")) {
- return Double.NEGATIVE_INFINITY;
- }
- try {
- // We don't use Double.parseDouble() here because that function simply
- // accepts all values. Here we parse the value into a BigDecimal and do
- // explicit range check on it.
- BigDecimal value = new BigDecimal(json.getAsString());
- if (value.compareTo(MAX_DOUBLE) > 0 || value.compareTo(MIN_DOUBLE) < 0) {
- throw new InvalidProtocolBufferException("Out of range double value: " + json);
- }
- return value.doubleValue();
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (Exception e) {
- throw new InvalidProtocolBufferException("Not an double value: " + json);
- }
- }
-
- private String parseString(JsonElement json) {
- return json.getAsString();
- }
-
- private ByteString parseBytes(JsonElement json) throws InvalidProtocolBufferException {
- return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
- }
-
- private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor, JsonElement json)
- throws InvalidProtocolBufferException {
- String value = json.getAsString();
- EnumValueDescriptor result = enumDescriptor.findValueByName(value);
- if (result == null) {
- // Try to interpret the value as a number.
- try {
- int numericValue = parseInt32(json);
- if (enumDescriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3) {
- result = enumDescriptor.findValueByNumberCreatingIfUnknown(numericValue);
- } else {
- result = enumDescriptor.findValueByNumber(numericValue);
- }
- } catch (InvalidProtocolBufferException e) {
- // Fall through. This exception is about invalid int32 value we get from parseInt32() but
- // that's not the exception we want the user to see. Since result == null, we will throw
- // an exception later.
- }
-
- if (result == null) {
- throw new InvalidProtocolBufferException(
- "Invalid enum value: " + value + " for enum type: " + enumDescriptor.getFullName());
- }
- }
- return result;
- }
-
- private Object parseFieldValue(FieldDescriptor field, JsonElement json, Message.Builder builder)
- throws InvalidProtocolBufferException {
- if (json instanceof JsonNull) {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
- && field.getMessageType().getFullName().equals(Value.getDescriptor().getFullName())) {
- // For every other type, "null" means absence, but for the special
- // Value message, it means the "null_value" field has been set.
- Value value = Value.newBuilder().setNullValueValue(0).build();
- return builder.newBuilderForField(field).mergeFrom(value.toByteString()).build();
- } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM
- && field.getEnumType().getFullName().equals(NullValue.getDescriptor().getFullName())) {
- // If the type of the field is a NullValue, then the value should be explicitly set.
- return field.getEnumType().findValueByNumber(0);
- }
- return null;
- }
- switch (field.getType()) {
- case INT32:
- case SINT32:
- case SFIXED32:
- return parseInt32(json);
-
- case INT64:
- case SINT64:
- case SFIXED64:
- return parseInt64(json);
-
- case BOOL:
- return parseBool(json);
-
- case FLOAT:
- return parseFloat(json);
-
- case DOUBLE:
- return parseDouble(json);
-
- case UINT32:
- case FIXED32:
- return parseUint32(json);
-
- case UINT64:
- case FIXED64:
- return parseUint64(json);
-
- case STRING:
- return parseString(json);
-
- case BYTES:
- return parseBytes(json);
-
- case ENUM:
- return parseEnum(field.getEnumType(), json);
-
- case MESSAGE:
- case GROUP:
- if (currentDepth >= recursionLimit) {
- throw new InvalidProtocolBufferException("Hit recursion limit.");
- }
- ++currentDepth;
- Message.Builder subBuilder = builder.newBuilderForField(field);
- merge(json, subBuilder);
- --currentDepth;
- return subBuilder.build();
-
- default:
- throw new InvalidProtocolBufferException("Invalid field type: " + field.getType());
- }
- }
- }
-}
diff --git a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java b/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
deleted file mode 100644
index 0475847349..0000000000
--- a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
+++ /dev/null
@@ -1,400 +0,0 @@
-// 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.util;
-
-import com.google.protobuf.Duration;
-import com.google.protobuf.Timestamp;
-
-import java.math.BigInteger;
-import java.text.ParseException;
-
-/**
- * Utilities to help create/manipulate Timestamp/Duration
- *
- * @deprecated Use {@link Durations} and {@link Timestamps} instead.
- */
-@Deprecated
-public final class TimeUtil {
- // Timestamp for "0001-01-01T00:00:00Z"
- public static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
-
- // Timestamp for "9999-12-31T23:59:59Z"
- public static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
- public static final long DURATION_SECONDS_MIN = -315576000000L;
- public static final long DURATION_SECONDS_MAX = 315576000000L;
-
- private static final long NANOS_PER_SECOND = 1000000000;
-
- private TimeUtil() {}
-
- /**
- * Convert Timestamp to RFC 3339 date string format. The output will always
- * be Z-normalized and uses 3, 6 or 9 fractional digits as required to
- * represent the exact value. Note that Timestamp can only represent time
- * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
- * https://www.ietf.org/rfc/rfc3339.txt
- *
- * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
- *
- * @return The string representation of the given timestamp.
- * @throws IllegalArgumentException if the given timestamp is not in the
- * valid range.
- * @deprecated Use {@link Timestamps#toString} instead.
- */
- @Deprecated
- public static String toString(Timestamp timestamp) {
- return Timestamps.toString(timestamp);
- }
-
- /**
- * Parse from RFC 3339 date string to Timestamp. This method accepts all
- * outputs of {@link #toString(Timestamp)} and it also accepts any fractional
- * digits (or none) and any offset as long as they fit into nano-seconds
- * precision.
- *
- * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
- *
- * @return A Timestamp parsed from the string.
- * @throws ParseException if parsing fails.
- * @deprecated Use {@link Timestamps#parse} instead.
- */
- @Deprecated
- public static Timestamp parseTimestamp(String value) throws ParseException {
- return Timestamps.parse(value);
- }
-
- /**
- * Convert Duration to string format. The string format will contains 3, 6,
- * or 9 fractional digits depending on the precision required to represent
- * the exact Duration value. For example: "1s", "1.010s", "1.000000100s",
- * "-3.100s" The range that can be represented by Duration is from
- * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
- *
- * @return The string representation of the given duration.
- * @throws IllegalArgumentException if the given duration is not in the valid
- * range.
- * @deprecated Use {@link Durations#toString} instead.
- */
- @Deprecated
- public static String toString(Duration duration) {
- return Durations.toString(duration);
- }
-
- /**
- * Parse from a string to produce a duration.
- *
- * @return A Duration parsed from the string.
- * @throws ParseException if parsing fails.
- * @deprecated Use {@link Durations#parse} instead.
- */
- @Deprecated
- public static Duration parseDuration(String value) throws ParseException {
- return Durations.parse(value);
- }
-
- /**
- * Create a Timestamp from the number of milliseconds elapsed from the epoch.
- *
- * @deprecated Use {@link Timestamps#fromMillis} instead.
- */
- @Deprecated
- public static Timestamp createTimestampFromMillis(long milliseconds) {
- return Timestamps.fromMillis(milliseconds);
- }
-
- /**
- * Create a Duration from the number of milliseconds.
- *
- * @deprecated Use {@link Durations#fromMillis} instead.
- */
- @Deprecated
- public static Duration createDurationFromMillis(long milliseconds) {
- return Durations.fromMillis(milliseconds);
- }
-
- /**
- * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
- *
- * <p>The result will be rounded down to the nearest millisecond. E.g., if the
- * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
- * to -1 millisecond.
- *
- * @deprecated Use {@link Timestamps#toMillis} instead.
- */
- @Deprecated
- public static long toMillis(Timestamp timestamp) {
- return Timestamps.toMillis(timestamp);
- }
-
- /**
- * Convert a Duration to the number of milliseconds.The result will be
- * rounded towards 0 to the nearest millisecond. E.g., if the duration
- * represents -1 nanosecond, it will be rounded to 0.
- *
- * @deprecated Use {@link Durations#toMillis} instead.
- */
- @Deprecated
- public static long toMillis(Duration duration) {
- return Durations.toMillis(duration);
- }
-
- /**
- * Create a Timestamp from the number of microseconds elapsed from the epoch.
- *
- * @deprecated Use {@link Timestamps#fromMicros} instead.
- */
- @Deprecated
- public static Timestamp createTimestampFromMicros(long microseconds) {
- return Timestamps.fromMicros(microseconds);
- }
-
- /**
- * Create a Duration from the number of microseconds.
- *
- * @deprecated Use {@link Durations#fromMicros} instead.
- */
- @Deprecated
- public static Duration createDurationFromMicros(long microseconds) {
- return Durations.fromMicros(microseconds);
- }
-
- /**
- * Convert a Timestamp to the number of microseconds elapsed from the epoch.
- *
- * <p>The result will be rounded down to the nearest microsecond. E.g., if the
- * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
- * to -1 millisecond.
- *
- * @deprecated Use {@link Timestamps#toMicros} instead.
- */
- @Deprecated
- public static long toMicros(Timestamp timestamp) {
- return Timestamps.toMicros(timestamp);
- }
-
- /**
- * Convert a Duration to the number of microseconds.The result will be
- * rounded towards 0 to the nearest microseconds. E.g., if the duration
- * represents -1 nanosecond, it will be rounded to 0.
- *
- * @deprecated Use {@link Durations#toMicros} instead.
- */
- @Deprecated
- public static long toMicros(Duration duration) {
- return Durations.toMicros(duration);
- }
-
- /**
- * Create a Timestamp from the number of nanoseconds elapsed from the epoch.
- *
- * @deprecated Use {@link Timestamps#fromNanos} instead.
- */
- @Deprecated
- public static Timestamp createTimestampFromNanos(long nanoseconds) {
- return Timestamps.fromNanos(nanoseconds);
- }
-
- /**
- * Create a Duration from the number of nanoseconds.
- *
- * @deprecated Use {@link Durations#fromNanos} instead.
- */
- @Deprecated
- public static Duration createDurationFromNanos(long nanoseconds) {
- return Durations.fromNanos(nanoseconds);
- }
-
- /**
- * Convert a Timestamp to the number of nanoseconds elapsed from the epoch.
- *
- * @deprecated Use {@link Timestamps#toNanos} instead.
- */
- @Deprecated
- public static long toNanos(Timestamp timestamp) {
- return Timestamps.toNanos(timestamp);
- }
-
- /**
- * Convert a Duration to the number of nanoseconds.
- *
- * @deprecated Use {@link Durations#toNanos} instead.
- */
- @Deprecated
- public static long toNanos(Duration duration) {
- return Durations.toNanos(duration);
- }
-
- /**
- * Get the current time.
- *
- * @deprecated Use {@code Timestamps.fromMillis(System.currentTimeMillis())} instead.
- */
- @Deprecated
- public static Timestamp getCurrentTime() {
- return Timestamps.fromMillis(System.currentTimeMillis());
- }
-
- /**
- * Get the epoch.
- *
- * @deprecated Use {@code Timestamps.fromMillis(0)} instead.
- */
- @Deprecated
- public static Timestamp getEpoch() {
- return Timestamp.getDefaultInstance();
- }
-
- /**
- * Calculate the difference between two timestamps.
- *
- * @deprecated Use {@link Timestamps#between} instead.
- */
- @Deprecated
- public static Duration distance(Timestamp from, Timestamp to) {
- return Timestamps.between(from, to);
- }
-
- /**
- * Add a duration to a timestamp.
- *
- * @deprecated Use {@link Timestamps#add} instead.
- */
- @Deprecated
- public static Timestamp add(Timestamp start, Duration length) {
- return Timestamps.add(start, length);
- }
-
- /**
- * Subtract a duration from a timestamp.
- *
- * @deprecated Use {@link Timestamps#subtract} instead.
- */
- @Deprecated
- public static Timestamp subtract(Timestamp start, Duration length) {
- return Timestamps.subtract(start, length);
- }
-
- /**
- * Add two durations.
- *
- * @deprecated Use {@link Durations#add} instead.
- */
- @Deprecated
- public static Duration add(Duration d1, Duration d2) {
- return Durations.add(d1, d2);
- }
-
- /**
- * Subtract a duration from another.
- *
- * @deprecated Use {@link Durations#subtract} instead.
- */
- @Deprecated
- public static Duration subtract(Duration d1, Duration d2) {
- return Durations.subtract(d1, d2);
- }
-
- // Multiplications and divisions.
-
- // TODO(kak): Delete this.
- public static Duration multiply(Duration duration, double times) {
- double result = duration.getSeconds() * times + duration.getNanos() * times / 1000000000.0;
- if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {
- throw new IllegalArgumentException("Result is out of valid range.");
- }
- long seconds = (long) result;
- int nanos = (int) ((result - seconds) * 1000000000);
- return normalizedDuration(seconds, nanos);
- }
-
- // TODO(kak): Delete this.
- public static Duration divide(Duration duration, double value) {
- return multiply(duration, 1.0 / value);
- }
-
- // TODO(kak): Delete this.
- public static Duration multiply(Duration duration, long times) {
- return createDurationFromBigInteger(toBigInteger(duration).multiply(toBigInteger(times)));
- }
-
- // TODO(kak): Delete this.
- public static Duration divide(Duration duration, long times) {
- return createDurationFromBigInteger(toBigInteger(duration).divide(toBigInteger(times)));
- }
-
- // TODO(kak): Delete this.
- public static long divide(Duration d1, Duration d2) {
- return toBigInteger(d1).divide(toBigInteger(d2)).longValue();
- }
-
- // TODO(kak): Delete this.
- public static Duration remainder(Duration d1, Duration d2) {
- return createDurationFromBigInteger(toBigInteger(d1).remainder(toBigInteger(d2)));
- }
-
- private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER =
- new BigInteger(String.valueOf(NANOS_PER_SECOND));
-
- private static BigInteger toBigInteger(Duration duration) {
- return toBigInteger(duration.getSeconds())
- .multiply(NANOS_PER_SECOND_BIG_INTEGER)
- .add(toBigInteger(duration.getNanos()));
- }
-
- private static BigInteger toBigInteger(long value) {
- return new BigInteger(String.valueOf(value));
- }
-
- private static Duration createDurationFromBigInteger(BigInteger value) {
- long seconds = value.divide(new BigInteger(String.valueOf(NANOS_PER_SECOND))).longValue();
- int nanos = value.remainder(new BigInteger(String.valueOf(NANOS_PER_SECOND))).intValue();
- return normalizedDuration(seconds, nanos);
- }
-
- private static Duration normalizedDuration(long seconds, int nanos) {
- if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
- seconds += nanos / NANOS_PER_SECOND;
- nanos %= NANOS_PER_SECOND;
- }
- if (seconds > 0 && nanos < 0) {
- nanos += NANOS_PER_SECOND;
- seconds -= 1;
- }
- if (seconds < 0 && nanos > 0) {
- nanos -= NANOS_PER_SECOND;
- seconds += 1;
- }
- if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
- throw new IllegalArgumentException("Duration is out of valid range.");
- }
- return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
- }
-}
diff --git a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
deleted file mode 100644
index 2160e4d57d..0000000000
--- a/third_party/protobuf/3.2.0/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
+++ /dev/null
@@ -1,396 +0,0 @@
-// 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.util;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.math.IntMath.checkedAdd;
-import static com.google.common.math.IntMath.checkedSubtract;
-import static com.google.common.math.LongMath.checkedAdd;
-import static com.google.common.math.LongMath.checkedMultiply;
-import static com.google.common.math.LongMath.checkedSubtract;
-
-import com.google.protobuf.Duration;
-import com.google.protobuf.Timestamp;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-
-/**
- * Utilities to help create/manipulate {@code protobuf/timestamp.proto}. All operations throw an
- * {@link IllegalArgumentException} if the input(s) are not {@linkplain #isValid(Timestamp) valid}.
- */
-public final class Timestamps {
-
- // Timestamp for "0001-01-01T00:00:00Z"
- static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
-
- // Timestamp for "9999-12-31T23:59:59Z"
- static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
-
- static final long NANOS_PER_SECOND = 1000000000;
- static final long NANOS_PER_MILLISECOND = 1000000;
- static final long NANOS_PER_MICROSECOND = 1000;
- static final long MILLIS_PER_SECOND = 1000;
- static final long MICROS_PER_SECOND = 1000000;
-
- /** A constant holding the minimum valid {@link Timestamp}, {@code 0001-01-01T00:00:00Z}. */
- public static final Timestamp MIN_VALUE =
- Timestamp.newBuilder().setSeconds(TIMESTAMP_SECONDS_MIN).setNanos(0).build();
-
- /**
- * A constant holding the maximum valid {@link Timestamp}, {@code 9999-12-31T23:59:59.999999999Z}.
- */
- public static final Timestamp MAX_VALUE =
- Timestamp.newBuilder().setSeconds(TIMESTAMP_SECONDS_MAX).setNanos(999999999).build();
-
- private static final ThreadLocal<SimpleDateFormat> timestampFormat =
- new ThreadLocal<SimpleDateFormat>() {
- @Override
- protected SimpleDateFormat initialValue() {
- return createTimestampFormat();
- }
- };
-
- private static SimpleDateFormat createTimestampFormat() {
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
- GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
- // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends
- // backwards to year one) for timestamp formating.
- calendar.setGregorianChange(new Date(Long.MIN_VALUE));
- sdf.setCalendar(calendar);
- return sdf;
- }
-
- private Timestamps() {}
-
- private static final Comparator<Timestamp> COMPARATOR =
- new Comparator<Timestamp>() {
- @Override
- public int compare(Timestamp t1, Timestamp t2) {
- checkValid(t1);
- checkValid(t2);
- int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
- return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
- }
- };
-
- /**
- * Returns a {@link Comparator} for {@link Timestamp}s which sorts in increasing chronological
- * order. Nulls and invalid {@link Timestamp}s are not allowed (see {@link #isValid}).
- */
- public static Comparator<Timestamp> comparator() {
- return COMPARATOR;
- }
-
- /**
- * Returns true if the given {@link Timestamp} is valid. The {@code seconds} value must be in the
- * range [-62,135,596,800, +253,402,300,799] (i.e., between 0001-01-01T00:00:00Z and
- * 9999-12-31T23:59:59Z). The {@code nanos} value must be in the range [0, +999,999,999].
- *
- * <p><b>Note:</b> Negative second values with fractional seconds must still have non-negative
- * nanos values that count forward in time.
- */
- public static boolean isValid(Timestamp timestamp) {
- return isValid(timestamp.getSeconds(), timestamp.getNanos());
- }
-
- /**
- * Returns true if the given number of seconds and nanos is a valid {@link Timestamp}. The {@code
- * seconds} value must be in the range [-62,135,596,800, +253,402,300,799] (i.e., between
- * 0001-01-01T00:00:00Z and 9999-12-31T23:59:59Z). The {@code nanos} value must be in the range
- * [0, +999,999,999].
- *
- * <p><b>Note:</b> Negative second values with fractional seconds must still have non-negative
- * nanos values that count forward in time.
- */
- public static boolean isValid(long seconds, int nanos) {
- if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) {
- return false;
- }
- if (nanos < 0 || nanos >= NANOS_PER_SECOND) {
- return false;
- }
- return true;
- }
-
- /** Throws an {@link IllegalArgumentException} if the given {@link Timestamp} is not valid. */
- public static Timestamp checkValid(Timestamp timestamp) {
- long seconds = timestamp.getSeconds();
- int nanos = timestamp.getNanos();
- checkArgument(
- isValid(seconds, nanos),
- "Timestamp is not valid. See proto definition for valid values. "
- + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. "
- + "Nanos (%s) must be in range [0, +999,999,999].",
- seconds,
- nanos);
- return timestamp;
- }
-
- /**
- * Convert Timestamp to RFC 3339 date string format. The output will always be Z-normalized and
- * uses 3, 6 or 9 fractional digits as required to represent the exact value. Note that Timestamp
- * can only represent time from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
- * https://www.ietf.org/rfc/rfc3339.txt
- *
- * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
- *
- * @return The string representation of the given timestamp.
- * @throws IllegalArgumentException if the given timestamp is not in the valid range.
- */
- public static String toString(Timestamp timestamp) {
- checkValid(timestamp);
-
- long seconds = timestamp.getSeconds();
- int nanos = timestamp.getNanos();
-
- StringBuilder result = new StringBuilder();
- // Format the seconds part.
- Date date = new Date(seconds * MILLIS_PER_SECOND);
- result.append(timestampFormat.get().format(date));
- // Format the nanos part.
- if (nanos != 0) {
- result.append(".");
- result.append(formatNanos(nanos));
- }
- result.append("Z");
- return result.toString();
- }
-
- /**
- * Parse from RFC 3339 date string to Timestamp. This method accepts all outputs of {@link
- * #toString(Timestamp)} and it also accepts any fractional digits (or none) and any offset as
- * long as they fit into nano-seconds precision.
- *
- * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
- *
- * @return A Timestamp parsed from the string.
- * @throws ParseException if parsing fails.
- */
- public static Timestamp parse(String value) throws ParseException {
- int dayOffset = value.indexOf('T');
- if (dayOffset == -1) {
- throw new ParseException("Failed to parse timestamp: invalid timestamp \"" + value + "\"", 0);
- }
- int timezoneOffsetPosition = value.indexOf('Z', dayOffset);
- if (timezoneOffsetPosition == -1) {
- timezoneOffsetPosition = value.indexOf('+', dayOffset);
- }
- if (timezoneOffsetPosition == -1) {
- timezoneOffsetPosition = value.indexOf('-', dayOffset);
- }
- if (timezoneOffsetPosition == -1) {
- throw new ParseException("Failed to parse timestamp: missing valid timezone offset.", 0);
- }
- // Parse seconds and nanos.
- String timeValue = value.substring(0, timezoneOffsetPosition);
- String secondValue = timeValue;
- String nanoValue = "";
- int pointPosition = timeValue.indexOf('.');
- if (pointPosition != -1) {
- secondValue = timeValue.substring(0, pointPosition);
- nanoValue = timeValue.substring(pointPosition + 1);
- }
- Date date = timestampFormat.get().parse(secondValue);
- long seconds = date.getTime() / MILLIS_PER_SECOND;
- int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
- // Parse timezone offsets.
- if (value.charAt(timezoneOffsetPosition) == 'Z') {
- if (value.length() != timezoneOffsetPosition + 1) {
- throw new ParseException(
- "Failed to parse timestamp: invalid trailing data \""
- + value.substring(timezoneOffsetPosition)
- + "\"",
- 0);
- }
- } else {
- String offsetValue = value.substring(timezoneOffsetPosition + 1);
- long offset = parseTimezoneOffset(offsetValue);
- if (value.charAt(timezoneOffsetPosition) == '+') {
- seconds -= offset;
- } else {
- seconds += offset;
- }
- }
- try {
- return normalizedTimestamp(seconds, nanos);
- } catch (IllegalArgumentException e) {
- throw new ParseException("Failed to parse timestamp: timestamp is out of range.", 0);
- }
- }
-
- /** Create a Timestamp from the number of seconds elapsed from the epoch. */
- public static Timestamp fromSeconds(long seconds) {
- return normalizedTimestamp(seconds, 0);
- }
-
- /**
- * Convert a Timestamp to the number of seconds elapsed from the epoch.
- *
- * <p>The result will be rounded down to the nearest second. E.g., if the timestamp represents
- * "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 second.
- */
- public static long toSeconds(Timestamp timestamp) {
- return checkValid(timestamp).getSeconds();
- }
-
- /** Create a Timestamp from the number of milliseconds elapsed from the epoch. */
- public static Timestamp fromMillis(long milliseconds) {
- return normalizedTimestamp(
- milliseconds / MILLIS_PER_SECOND,
- (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
- }
-
- /**
- * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
- *
- * <p>The result will be rounded down to the nearest millisecond. E.g., if the timestamp
- * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 millisecond.
- */
- public static long toMillis(Timestamp timestamp) {
- checkValid(timestamp);
- return checkedAdd(
- checkedMultiply(timestamp.getSeconds(), MILLIS_PER_SECOND),
- timestamp.getNanos() / NANOS_PER_MILLISECOND);
- }
-
- /** Create a Timestamp from the number of microseconds elapsed from the epoch. */
- public static Timestamp fromMicros(long microseconds) {
- return normalizedTimestamp(
- microseconds / MICROS_PER_SECOND,
- (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
- }
-
- /**
- * Convert a Timestamp to the number of microseconds elapsed from the epoch.
- *
- * <p>The result will be rounded down to the nearest microsecond. E.g., if the timestamp
- * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 millisecond.
- */
- public static long toMicros(Timestamp timestamp) {
- checkValid(timestamp);
- return checkedAdd(
- checkedMultiply(timestamp.getSeconds(), MICROS_PER_SECOND),
- timestamp.getNanos() / NANOS_PER_MICROSECOND);
- }
-
- /** Create a Timestamp from the number of nanoseconds elapsed from the epoch. */
- public static Timestamp fromNanos(long nanoseconds) {
- return normalizedTimestamp(
- nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
- }
-
- /** Convert a Timestamp to the number of nanoseconds elapsed from the epoch. */
- public static long toNanos(Timestamp timestamp) {
- checkValid(timestamp);
- return checkedAdd(
- checkedMultiply(timestamp.getSeconds(), NANOS_PER_SECOND), timestamp.getNanos());
- }
-
- /** Calculate the difference between two timestamps. */
- public static Duration between(Timestamp from, Timestamp to) {
- checkValid(from);
- checkValid(to);
- return Durations.normalizedDuration(
- checkedSubtract(to.getSeconds(), from.getSeconds()),
- checkedSubtract(to.getNanos(), from.getNanos()));
- }
-
- /** Add a duration to a timestamp. */
- public static Timestamp add(Timestamp start, Duration length) {
- checkValid(start);
- Durations.checkValid(length);
- return normalizedTimestamp(
- checkedAdd(start.getSeconds(), length.getSeconds()),
- checkedAdd(start.getNanos(), length.getNanos()));
- }
-
- /** Subtract a duration from a timestamp. */
- public static Timestamp subtract(Timestamp start, Duration length) {
- checkValid(start);
- Durations.checkValid(length);
- return normalizedTimestamp(
- checkedSubtract(start.getSeconds(), length.getSeconds()),
- checkedSubtract(start.getNanos(), length.getNanos()));
- }
-
- static Timestamp normalizedTimestamp(long seconds, int nanos) {
- if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
- seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND);
- nanos %= NANOS_PER_SECOND;
- }
- if (nanos < 0) {
- nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding)
- seconds = checkedSubtract(seconds, 1);
- }
- Timestamp timestamp = Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
- return checkValid(timestamp);
- }
-
- private static long parseTimezoneOffset(String value) throws ParseException {
- int pos = value.indexOf(':');
- if (pos == -1) {
- throw new ParseException("Invalid offset value: " + value, 0);
- }
- String hours = value.substring(0, pos);
- String minutes = value.substring(pos + 1);
- return (Long.parseLong(hours) * 60 + Long.parseLong(minutes)) * 60;
- }
-
- static int parseNanos(String value) throws ParseException {
- int result = 0;
- for (int i = 0; i < 9; ++i) {
- result = result * 10;
- if (i < value.length()) {
- if (value.charAt(i) < '0' || value.charAt(i) > '9') {
- throw new ParseException("Invalid nanoseconds.", 0);
- }
- result += value.charAt(i) - '0';
- }
- }
- return result;
- }
-
- /** Format the nano part of a timestamp or a duration. */
- static String formatNanos(int nanos) {
- // Determine whether to use 3, 6, or 9 digits for the nano part.
- if (nanos % NANOS_PER_MILLISECOND == 0) {
- return String.format("%1$03d", nanos / NANOS_PER_MILLISECOND);
- } else if (nanos % NANOS_PER_MICROSECOND == 0) {
- return String.format("%1$06d", nanos / NANOS_PER_MICROSECOND);
- } else {
- return String.format("%1$09d", nanos);
- }
- }
-}