diff options
Diffstat (limited to 'third_party/protobuf/3.2.0/java/util/src/main/java/com/google')
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); - } - } -} |