Merge branch 'master' into patch-1

This commit is contained in:
Alex Konradi 2019-06-20 14:10:06 -04:00 committed by GitHub
commit 619ffac4f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
166 changed files with 3313 additions and 2861 deletions

2
BUILD
View File

@ -115,8 +115,8 @@ cc_library(
"src/google/protobuf/generated_message_util.cc",
"src/google/protobuf/implicit_weak_message.cc",
"src/google/protobuf/io/coded_stream.cc",
"src/google/protobuf/io/strtod.cc",
"src/google/protobuf/io/io_win32.cc",
"src/google/protobuf/io/strtod.cc",
"src/google/protobuf/io/zero_copy_stream.cc",
"src/google/protobuf/io/zero_copy_stream_impl.cc",
"src/google/protobuf/io/zero_copy_stream_impl_lite.cc",

View File

@ -1,3 +1,74 @@
2019-04-29 version 3.8.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
C++
* Use std::atomic<int32> in case of myriad2 platform
* Always declare enums to be int-sized
* Added DebugString() and ShortDebugString() methods on MessageLite
* Specialized different parse loop control flows
* Make hasbits potentially in register. The or's start forming an obstacle because it's a read modify store on the same mem address on each iteration.
* Move to an internal MACRO for parser validity checks.
* Improve map parsing performance.
* Make MergePartialFromCodedStream non virtual. This allows direct calls, potential inlining and is also a code health improvement
* Add an overall limit to parse_context to prevent reading past it. This allows to remove a annoying level of indirection.
* Fix a mistake, we shouldn't verify map key/value strings for utf8 in opt mode for proto2.
* Further improvements to cut binary size.
* Prepare to make MergePartialFromCodedStream non-virtual.
* A report on some interesting behavior change in python (caused by b/27494216) made me realize there is a check that needs to be done in case the parse ended on a end group tag.
* Add a note of caution to the comments around skip in CodedOutputStream.
* Simplify end check.
* Add overload for ParseMessage for MessageLite/Message types. If the explicit type is not known inlining won't help de-virtualizing the virtual call.
* Reduce linker input. It turns out that ParseMessage is not inlined, producing template instantiations that are used only once and save nothing but cost more.
* Improve the parser.
* [c++17] Changed proto2::RepeatedPtrField iterators to no longer derive from the deprecated std::iterator class.
* Change the default value of case_insensitive_enum_parsing to false for JsonStringToMessage.
* Add a warning if a field name doesn't match the style guide.
* Fix TextFormat not round-trip correctly when float value is max float.
* Added locationed info for some errors at compiler
* Python reserved keywords are now working with getattr()/setattr() for most descriptors.
* Added AllowUnknownField() in text_format
* Append '_' to C++ reserved keywords for message, enum, extension
* Fix MSVC warning C4244 in protobuf's parse_context.h.
* Updating Iterators to be compatible with C++17 in MSVC.
* Use capability annotation in mutex.h
* Fix "UndefinedBehaviorSanitizer: cfi-bad-type"
* CriticalSectionLock class as a lightweight replacement for std::mutex on Windows platforms.
* Removed vestigial wire_format_lite_inl.h
C#
* Added System.Memory dependency.
Java
* Make Java protoc code generator ignore optimize_for LITE_RUNTIME. Users should instead use the Java lite protoc plugin.
* Change Extension getMessageDefaultInstance() to return Message instead of MessageLite.
* Prevent malicious input streams from leaking buffers for ByteString or ByteBuffer parsing.
* Release new Javalite runtime.
* Show warning in case potential file name conflict.
* Allow Java reserved keywords to be used in extensions.
* Added setAllowUnknownFields() in text format
* Add memoization to ExtensionRegistryLite.getEmptyRegistry()
* Improve performance of CodedOutputStream.writeUInt32NoTag
* Add an optimized mismatch-finding algorithm to UnsafeUtil.
* When serializing uint32 varints, check that we have MAX_VARINT32_SIZE bytes left, not just MAX_VARINT_SIZE.
* Minor optimization to RopeByteString.PieceIterator
JavaScript
* Simplify generated toObject code when the default value is used.
Python
* Changes implementation of Name() for enums that allow aliases in proto2 in Python to be in line with claims in C++ implementation (to return first value).
* Added double_format option in text format printer.
* Added iter and __contains__ to extension dict
* Added allow_unknown_field option in python text format parser
* Fixed Timestamp.ToDatetime() loses precision issue
* Support unknown field in text format printer.
* Float field will be convert to inf if bigger than struct.unpack('f', b'\xff\xff\x7f\x7f')[0] which is about 3.4028234664e+38,
convert to -inf if smaller than -3.4028234664e+38
* Allowed casting str->bytes in Message.__setstate__
Ruby
* Helper methods to get enum name for Ruby.
2019-01-24 version 3.7.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
C++

View File

@ -83,6 +83,10 @@ the final release.
Ultimately, the green signal will be provided by our testing infrastructure.
The reviewer will help you if there are test failures that seem not related
to the change you are making.
## Reviewer Guidelines
* Make sure that all tests are passing before approval.
* Apply the "release notes: yes" label if the pull request's description should
be included in the next release (e.g., any new feature / bug fix).
Apply the "release notes: no" label if the pull request's description should
@ -92,4 +96,3 @@ the final release.
pull request. This will make it easier to identify which languages the pull
request affects, allowing us to better identify appropriate reviewer, create
a better release note, and make it easier to identify issues in the future.

View File

@ -493,11 +493,15 @@ java_EXTRA_DIST=
java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java \
java/util/src/main/java/com/google/protobuf/util/JsonFormat.java \
java/util/src/main/java/com/google/protobuf/util/TimeUtil.java \
java/util/src/main/java/com/google/protobuf/util/Structs.java \
java/util/src/main/java/com/google/protobuf/util/Timestamps.java \
java/util/src/main/java/com/google/protobuf/util/Values.java \
java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java \
java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java \
java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java \
java/util/src/test/java/com/google/protobuf/util/StructsTest.java \
java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java \
java/util/src/test/java/com/google/protobuf/util/ValuesTest.java \
java/util/src/test/proto/com/google/protobuf/util/json_test.proto
objectivec_EXTRA_DIST= \
@ -1231,6 +1235,7 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
python/release/wheel/protobuf_optimized_pip.sh \
python/release/wheel/README.md \
six.BUILD \
third_party/zlib.BUILD \
util/python/BUILD

View File

@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
s.version = '3.7.1'
s.version = '3.8.0'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/protocolbuffers/protobuf'
s.license = '3-Clause BSD License'

View File

@ -33,7 +33,7 @@ if (protobuf_BUILD_PROTOC_BINARIES)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
if (UNIX AND NOT APPLE)
set_property(TARGET protoc
PROPERTY INSTALL_RPATH "$ORIGIN/../lib")
PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
elseif (APPLE)
set_property(TARGET protoc
PROPERTY INSTALL_RPATH "@loader_path/../lib")

View File

@ -17,7 +17,7 @@ AC_PREREQ(2.59)
# In the SVN trunk, the version should always be the next anticipated release
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
# the size of one file name in the dist tarfile over the 99-char limit.)
AC_INIT([Protocol Buffers],[3.7.1],[protobuf@googlegroups.com],[protobuf])
AC_INIT([Protocol Buffers],[3.8.0],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])
@ -47,6 +47,11 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
# Silent rules enabled: the output is minimal but informative.
# In particular, the warnings from the compiler stick out very clearly.
# To see all logs, use the --disable-silent-rules on configure or via make V=1
AM_SILENT_RULES([yes])
AC_ARG_WITH([zlib],
[AS_HELP_STRING([--with-zlib],
[include classes for streaming compressed data in and out @<:@default=check@:>@])],

View File

@ -1980,12 +1980,12 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
"repeated_timestamp: {seconds: 253402300799 nanos: 999999999}");
RunValidJsonTest(
"TimestampWithPositiveOffset", REQUIRED,
R"({"optionalTimestamp": "1970-01-01T08:00:00+08:00"})",
"optional_timestamp: {seconds: 0}");
R"({"optionalTimestamp": "1970-01-01T08:00:01+08:00"})",
"optional_timestamp: {seconds: 1}");
RunValidJsonTest(
"TimestampWithNegativeOffset", REQUIRED,
R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
"optional_timestamp: {seconds: 0}");
R"({"optionalTimestamp": "1969-12-31T16:00:01-08:00"})",
"optional_timestamp: {seconds: 1}");
RunValidJsonTest(
"TimestampNull", REQUIRED,
R"({"optionalTimestamp": null})",

View File

@ -3,10 +3,6 @@ Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Required.Proto3.JsonInput.FloatFieldTooLarge
Required.Proto3.JsonInput.FloatFieldTooSmall

View File

@ -51,11 +51,6 @@ Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.Proto3.JsonInput.TimestampJsonInputTooSmall
Required.Proto3.JsonInput.TimestampMinValue.JsonOutput
Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput
Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput

View File

@ -5,7 +5,7 @@
<title>Google Protocol Buffers tools</title>
<summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description>
<version>3.7.1</version>
<version>3.8.0</version>
<authors>Google Inc.</authors>
<owners>protobuf-packages</owners>
<licenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</licenseUrl>

View File

@ -4,7 +4,7 @@
<Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
<Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.7.1</VersionPrefix>
<VersionPrefix>3.8.0</VersionPrefix>
<LangVersion>6</LangVersion>
<Authors>Google Inc.</Authors>
<TargetFrameworks>netstandard1.0;netstandard2.0;net45</TargetFrameworks>
@ -32,11 +32,11 @@
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Memory" Version="4.5.2" />
<PackageReference Include="System.Memory" Version="4.5.2"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-18618-05" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0-beta2-18618-05"/>
</ItemGroup>
</Project>

View File

@ -41,15 +41,11 @@ namespace Google.Protobuf.Reflection
/// </summary>
public class ExtensionCollection
{
private readonly FileDescriptor file;
private readonly MessageDescriptor message;
private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInDeclarationOrder;
private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInNumberOrder;
internal ExtensionCollection(FileDescriptor file, Extension[] extensions)
{
this.file = file;
UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly(
file.Proto.Extension,
(extension, i) => new FieldDescriptor(extension, file, null, i, null, extensions?[i]));
@ -57,7 +53,6 @@ namespace Google.Protobuf.Reflection
internal ExtensionCollection(MessageDescriptor message, Extension[] extensions)
{
this.message = message;
UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly(
message.Proto.Extension,
(extension, i) => new FieldDescriptor(extension, message.File, message, i, null, extensions?[i]));

View File

@ -197,7 +197,11 @@ with info about your project (name and website) so we can add an entry for you.
* Website: https://github.com/container-storage-interface/spec
* Extensions: 1059-1069
1. TwirpQL Plugin
* Website: https://twirpql.dev
* Extensions: 1070
1. Protoc-gen-validate
* Website: https://github.com/envoyproxy/protoc-gen-validate
* Extensions: 1070
* Extensions: 1071

2
examples/README.md Normal file → Executable file
View File

@ -38,7 +38,7 @@ and the protobuf runtime for the language you want to build.
You can simply run "make" to build the example for all languages (except for
Go). However, since different language has different installation requirement,
it will likely fail. It's better to follow individual instrutions below to
it will likely fail. It's better to follow individual instructions below to
build only the language you are interested in.
### C++

View File

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-bom</artifactId>
<version>3.7.1</version>
<version>3.8.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [BOM]</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.7.1</version>
<version>3.8.0</version>
</parent>
<artifactId>protobuf-java</artifactId>

View File

@ -108,7 +108,7 @@ public abstract class AbstractMessage
@Override
public final String toString() {
return TextFormat.printToString(this);
return TextFormat.printer().printToString(this);
}
@Override
@ -468,7 +468,7 @@ public abstract class AbstractMessage
@Override
public String toString() {
return TextFormat.printToString(this);
return TextFormat.printer().printToString(this);
}
/** Construct an UninitializedMessageException reporting missing fields in the given message. */

View File

@ -76,6 +76,10 @@ public class ExtensionRegistryLite {
// applications. Need to support this feature on smaller granularity.
private static volatile boolean eagerlyParseMessageSets = false;
// short circuit the ExtensionRegistryFactory via assumevalues trickery
@SuppressWarnings("JavaOptionalSuggestions")
private static boolean doFullRuntimeInheritanceCheck = true;
// Visible for testing.
static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension";
@ -107,7 +111,9 @@ public class ExtensionRegistryLite {
* available.
*/
public static ExtensionRegistryLite newInstance() {
return ExtensionRegistryFactory.create();
return doFullRuntimeInheritanceCheck
? ExtensionRegistryFactory.create()
: new ExtensionRegistryLite();
}
private static volatile ExtensionRegistryLite emptyRegistry;
@ -122,7 +128,11 @@ public class ExtensionRegistryLite {
synchronized (ExtensionRegistryLite.class) {
result = emptyRegistry;
if (result == null) {
result = emptyRegistry = ExtensionRegistryFactory.createEmpty();
result =
emptyRegistry =
doFullRuntimeInheritanceCheck
? ExtensionRegistryFactory.createEmpty()
: EMPTY_REGISTRY_LITE;
}
}
}
@ -163,7 +173,7 @@ public class ExtensionRegistryLite {
if (GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom(extension.getClass())) {
add((GeneratedMessageLite.GeneratedExtension<?, ?>) extension);
}
if (ExtensionRegistryFactory.isFullRegistry(this)) {
if (doFullRuntimeInheritanceCheck && ExtensionRegistryFactory.isFullRegistry(this)) {
try {
this.getClass().getMethod("add", extensionClass).invoke(this, extension);
} catch (Exception e) {

View File

@ -85,7 +85,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
/**
* Converts the message to a string in protocol buffer text format. This is just a trivial wrapper
* around {@link TextFormat#printToString(MessageOrBuilder)}.
* around {@link TextFormat.Printer#printToString(MessageOrBuilder)}.
*/
@Override
String toString();

View File

@ -61,135 +61,132 @@ public final class TextFormat {
* Outputs a textual representation of the Protocol Message supplied into the parameter output.
* (This representation is the new version of the classic "ProtocolPrinter" output from the
* original Protocol Buffer system)
*
* @deprecated Use {@code printer().print(MessageOrBuilder, Appendable)}
*/
@Deprecated
public static void print(final MessageOrBuilder message, final Appendable output)
throws IOException {
Printer.DEFAULT.print(message, multiLineOutput(output));
printer().print(message, output);
}
/** Outputs a textual representation of {@code fields} to {@code output}. */
/**
* Outputs a textual representation of {@code fields} to {@code output}.
*
* @deprecated Use {@code printer().print(UnknownFieldSet, Appendable)}
*/
@Deprecated
public static void print(final UnknownFieldSet fields, final Appendable output)
throws IOException {
Printer.DEFAULT.printUnknownFields(fields, multiLineOutput(output));
printer().print(fields, output);
}
/** Same as {@code print()}, except that non-ASCII characters are not escaped. */
/**
* Same as {@code print()}, except that non-ASCII characters are not escaped.
*
* @deprecated Use {@code printer().escapingNonAscii(false).print(MessageOrBuilder, Appendable)}
*/
@Deprecated
public static void printUnicode(final MessageOrBuilder message, final Appendable output)
throws IOException {
Printer.UNICODE.print(message, multiLineOutput(output));
printer().escapingNonAscii(false).print(message, output);
}
/** Same as {@code print()}, except that non-ASCII characters are not escaped. */
/**
* Same as {@code print()}, except that non-ASCII characters are not escaped.
*
* @deprecated Use {@code printer().escapingNonAscii(false).print(UnknownFieldSet, Appendable)}
*/
@Deprecated
public static void printUnicode(final UnknownFieldSet fields, final Appendable output)
throws IOException {
Printer.UNICODE.printUnknownFields(fields, multiLineOutput(output));
printer().escapingNonAscii(false).print(fields, output);
}
/**
* Generates a human readable form of this message, useful for debugging and other purposes, with
* no newline characters.
* no newline characters. This is just a trivial wrapper around
* {@link TextFormat.Printer#shortDebugString(MessageOrBuilder)}.
*/
public static String shortDebugString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
Printer.DEFAULT.print(message, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().shortDebugString(message);
}
/**
* Generates a human readable form of the field, useful for debugging and other purposes, with no
* newline characters.
*
* @deprecated Use {@code printer().shortDebugString(FieldDescriptor, Object)}
*/
@Deprecated
public static String shortDebugString(final FieldDescriptor field, final Object value) {
try {
final StringBuilder text = new StringBuilder();
Printer.DEFAULT.printField(field, value, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().shortDebugString(field, value);
}
/**
* Generates a human readable form of the unknown fields, useful for debugging and other purposes,
* with no newline characters.
*
* @deprecated Use {@code printer().shortDebugString(UnknownFieldSet)}
*/
@Deprecated
public static String shortDebugString(final UnknownFieldSet fields) {
try {
final StringBuilder text = new StringBuilder();
Printer.DEFAULT.printUnknownFields(fields, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().shortDebugString(fields);
}
/** Like {@code print()}, but writes directly to a {@code String} and returns it. */
/**
* Like {@code print()}, but writes directly to a {@code String} and returns it.
*
* @deprecated Use {@link MessageOrBuilder#toString()}
*/
@Deprecated
public static String printToString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
print(message, text);
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().printToString(message);
}
/** Like {@code print()}, but writes directly to a {@code String} and returns it. */
/**
* Like {@code print()}, but writes directly to a {@code String} and returns it.
*
* @deprecated Use {@link UnknownFieldSet#toString()}
*/
@Deprecated
public static String printToString(final UnknownFieldSet fields) {
try {
final StringBuilder text = new StringBuilder();
print(fields, text);
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().printToString(fields);
}
/**
* Same as {@code printToString()}, except that non-ASCII characters in string type fields are not
* escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printToString(MessageOrBuilder)}
*/
@Deprecated
public static String printToUnicodeString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
Printer.UNICODE.print(message, multiLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().escapingNonAscii(false).printToString(message);
}
/**
* Same as {@code printToString()}, except that non-ASCII characters in string type fields are not
* escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printToString(UnknownFieldSet)}
*/
@Deprecated
public static String printToUnicodeString(final UnknownFieldSet fields) {
try {
final StringBuilder text = new StringBuilder();
Printer.UNICODE.printUnknownFields(fields, multiLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().escapingNonAscii(false).printToString(fields);
}
/** @deprecated Use {@code printer().printField(FieldDescriptor, Object, Appendable)} */
@Deprecated
public static void printField(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
Printer.DEFAULT.printField(field, value, multiLineOutput(output));
printer().printField(field, value, output);
}
/** @deprecated Use {@code printer().printFieldToString(FieldDescriptor, Object)} */
@Deprecated
public static String printFieldToString(final FieldDescriptor field, final Object value) {
try {
final StringBuilder text = new StringBuilder();
printField(field, value, text);
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return printer().printFieldToString(field, value);
}
/**
@ -198,29 +195,34 @@ public final class TextFormat {
* <p>Same as {@code printFieldValue()}, except that non-ASCII characters in string type fields
* are not escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printFieldValue(FieldDescriptor,
* Object, Appendable)}
* @param field the descriptor of the field
* @param value the value of the field
* @param output the output to which to append the formatted value
* @throws ClassCastException if the value is not appropriate for the given field descriptor
* @throws IOException if there is an exception writing to the output
*/
@Deprecated
public static void printUnicodeFieldValue(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
Printer.UNICODE.printFieldValue(field, value, multiLineOutput(output));
printer().escapingNonAscii(false).printFieldValue(field, value, output);
}
/**
* Outputs a textual representation of the value of given field value.
*
* @deprecated Use {@code printer().printFieldValue(FieldDescriptor, Object, Appendable)}
* @param field the descriptor of the field
* @param value the value of the field
* @param output the output to which to append the formatted value
* @throws ClassCastException if the value is not appropriate for the given field descriptor
* @throws IOException if there is an exception writing to the output
*/
@Deprecated
public static void printFieldValue(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
Printer.DEFAULT.printFieldValue(field, value, multiLineOutput(output));
printer().printFieldValue(field, value, output);
}
/**
@ -256,7 +258,7 @@ public final class TextFormat {
generator.print("{");
generator.eol();
generator.indent();
Printer.DEFAULT.printUnknownFields(message, generator);
Printer.printUnknownFields(message, generator);
generator.outdent();
generator.print("}");
} catch (InvalidProtocolBufferException e) {
@ -267,19 +269,23 @@ public final class TextFormat {
}
break;
case WireFormat.WIRETYPE_START_GROUP:
Printer.DEFAULT.printUnknownFields((UnknownFieldSet) value, generator);
Printer.printUnknownFields((UnknownFieldSet) value, generator);
break;
default:
throw new IllegalArgumentException("Bad tag: " + tag);
}
}
/** Printer instance which escapes non-ASCII characters. */
public static Printer printer() {
return Printer.DEFAULT;
}
/** Helper class for converting protobufs to text. */
private static final class Printer {
public static final class Printer {
// Printer instance which escapes non-ASCII characters.
static final Printer DEFAULT = new Printer(true);
// Printer instance which emits Unicode (it still escapes newlines and quotes in strings).
static final Printer UNICODE = new Printer(false);
private static final Printer DEFAULT = new Printer(true);
/** Whether to escape non ASCII characters with backslash and octal. */
private final boolean escapeNonAscii;
@ -288,12 +294,51 @@ public final class TextFormat {
this.escapeNonAscii = escapeNonAscii;
}
/**
* Return a new Printer instance with the specified escape mode.
*
* @param escapeNonAscii If true, the new Printer will escape non-ASCII characters (this is the
* default behavior. If false, the new Printer will print non-ASCII characters as is. In
* either case, the new Printer still escapes newlines and quotes in strings.
* @return a new Printer that clones all other configurations from the current {@link Printer},
* with the escape mode set to the given parameter.
*/
public Printer escapingNonAscii(boolean escapeNonAscii) {
return new Printer(escapeNonAscii);
}
/**
* Outputs a textual representation of the Protocol Message supplied into the parameter output.
* (This representation is the new version of the classic "ProtocolPrinter" output from the
* original Protocol Buffer system)
*/
public void print(final MessageOrBuilder message, final Appendable output) throws IOException {
print(message, multiLineOutput(output));
}
/** Outputs a textual representation of {@code fields} to {@code output}. */
public void print(final UnknownFieldSet fields, final Appendable output) throws IOException {
printUnknownFields(fields, multiLineOutput(output));
}
private void print(final MessageOrBuilder message, final TextGenerator generator)
throws IOException {
for (Map.Entry<FieldDescriptor, Object> field : message.getAllFields().entrySet()) {
printField(field.getKey(), field.getValue(), generator);
printMessage(message, generator);
}
public String printFieldToString(final FieldDescriptor field, final Object value) {
try {
final StringBuilder text = new StringBuilder();
printField(field, value, text);
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
printUnknownFields(message.getUnknownFields(), generator);
}
public void printField(final FieldDescriptor field, final Object value, final Appendable output)
throws IOException {
printField(field, value, multiLineOutput(output));
}
private void printField(
@ -309,46 +354,19 @@ public final class TextFormat {
}
}
private void printSingleField(
final FieldDescriptor field, final Object value, final TextGenerator generator)
/**
* Outputs a textual representation of the value of given field value.
*
* @param field the descriptor of the field
* @param value the value of the field
* @param output the output to which to append the formatted value
* @throws ClassCastException if the value is not appropriate for the given field descriptor
* @throws IOException if there is an exception writing to the output
*/
public void printFieldValue(
final FieldDescriptor field, final Object value, final Appendable output)
throws IOException {
if (field.isExtension()) {
generator.print("[");
// We special-case MessageSet elements for compatibility with proto1.
if (field.getContainingType().getOptions().getMessageSetWireFormat()
&& (field.getType() == FieldDescriptor.Type.MESSAGE)
&& (field.isOptional())
// object equality
&& (field.getExtensionScope() == field.getMessageType())) {
generator.print(field.getMessageType().getFullName());
} else {
generator.print(field.getFullName());
}
generator.print("]");
} else {
if (field.getType() == FieldDescriptor.Type.GROUP) {
// Groups must be serialized with their original capitalization.
generator.print(field.getMessageType().getName());
} else {
generator.print(field.getName());
}
}
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
generator.print(" {");
generator.eol();
generator.indent();
} else {
generator.print(": ");
}
printFieldValue(field, value, generator);
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
generator.outdent();
generator.print("}");
}
generator.eol();
printFieldValue(field, value, multiLineOutput(output));
}
private void printFieldValue(
@ -419,7 +437,157 @@ public final class TextFormat {
}
}
private void printUnknownFields(
/** Like {@code print()}, but writes directly to a {@code String} and returns it. */
public String printToString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
print(message, text);
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/** Like {@code print()}, but writes directly to a {@code String} and returns it. */
public String printToString(final UnknownFieldSet fields) {
try {
final StringBuilder text = new StringBuilder();
print(fields, text);
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* Generates a human readable form of this message, useful for debugging and other purposes,
* with no newline characters.
*/
public String shortDebugString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
print(message, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* Generates a human readable form of the field, useful for debugging and other purposes, with
* no newline characters.
*/
public String shortDebugString(final FieldDescriptor field, final Object value) {
try {
final StringBuilder text = new StringBuilder();
printField(field, value, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* Generates a human readable form of the unknown fields, useful for debugging and other
* purposes, with no newline characters.
*/
public String shortDebugString(final UnknownFieldSet fields) {
try {
final StringBuilder text = new StringBuilder();
printUnknownFields(fields, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static void printUnknownFieldValue(
final int tag, final Object value, final TextGenerator generator) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
generator.print(unsignedToString((Long) value));
break;
case WireFormat.WIRETYPE_FIXED32:
generator.print(String.format((Locale) null, "0x%08x", (Integer) value));
break;
case WireFormat.WIRETYPE_FIXED64:
generator.print(String.format((Locale) null, "0x%016x", (Long) value));
break;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
try {
// Try to parse and print the field as an embedded message
UnknownFieldSet message = UnknownFieldSet.parseFrom((ByteString) value);
generator.print("{");
generator.eol();
generator.indent();
printUnknownFields(message, generator);
generator.outdent();
generator.print("}");
} catch (InvalidProtocolBufferException e) {
// If not parseable as a message, print as a String
generator.print("\"");
generator.print(escapeBytes((ByteString) value));
generator.print("\"");
}
break;
case WireFormat.WIRETYPE_START_GROUP:
printUnknownFields((UnknownFieldSet) value, generator);
break;
default:
throw new IllegalArgumentException("Bad tag: " + tag);
}
}
private void printMessage(final MessageOrBuilder message, final TextGenerator generator)
throws IOException {
for (Map.Entry<FieldDescriptor, Object> field : message.getAllFields().entrySet()) {
printField(field.getKey(), field.getValue(), generator);
}
printUnknownFields(message.getUnknownFields(), generator);
}
private void printSingleField(
final FieldDescriptor field, final Object value, final TextGenerator generator)
throws IOException {
if (field.isExtension()) {
generator.print("[");
// We special-case MessageSet elements for compatibility with proto1.
if (field.getContainingType().getOptions().getMessageSetWireFormat()
&& (field.getType() == FieldDescriptor.Type.MESSAGE)
&& (field.isOptional())
// object equality
&& (field.getExtensionScope() == field.getMessageType())) {
generator.print(field.getMessageType().getFullName());
} else {
generator.print(field.getFullName());
}
generator.print("]");
} else {
if (field.getType() == FieldDescriptor.Type.GROUP) {
// Groups must be serialized with their original capitalization.
generator.print(field.getMessageType().getName());
} else {
generator.print(field.getName());
}
}
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
generator.print(" {");
generator.eol();
generator.indent();
} else {
generator.print(": ");
}
printFieldValue(field, value, generator);
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
generator.outdent();
generator.print("}");
}
generator.eol();
}
private static void printUnknownFields(
final UnknownFieldSet unknownFields, final TextGenerator generator) throws IOException {
for (Map.Entry<Integer, UnknownFieldSet.Field> entry : unknownFields.asMap().entrySet()) {
final int number = entry.getKey();
@ -445,7 +613,7 @@ public final class TextFormat {
}
}
private void printUnknownField(
private static void printUnknownField(
final int number, final int wireType, final List<?> values, final TextGenerator generator)
throws IOException {
for (final Object value : values) {
@ -1994,7 +2162,7 @@ public final class TextFormat {
return escapeBytes(ByteString.copyFromUtf8(input));
}
/** Escape double quotes and backslashes in a String for unicode output of a message. */
/** Escape double quotes and backslashes in a String for emittingUnicode output of a message. */
public static String escapeDoubleQuotesAndBackslashes(final String input) {
return TextFormatEscaper.escapeDoubleQuotesAndBackslashes(input);
}

View File

@ -140,11 +140,11 @@ public final class UnknownFieldSet implements MessageLite {
/**
* Converts the set to a string in protocol buffer text format. This is just a trivial wrapper
* around {@link TextFormat#printToString(UnknownFieldSet)}.
* around {@link TextFormat.Printer#printToString(UnknownFieldSet)}.
*/
@Override
public String toString() {
return TextFormat.printToString(this);
return TextFormat.printer().printToString(this);
}
/**

View File

@ -766,7 +766,7 @@ public class MapForProto2Test extends TestCase {
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
String textData = TextFormat.printToString(message);
String textData = TextFormat.printer().printToString(message);
builder = TestMap.newBuilder();
TextFormat.merge(textData, builder);

View File

@ -857,7 +857,7 @@ public class MapTest extends TestCase {
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
String textData = TextFormat.printToString(message);
String textData = TextFormat.printer().printToString(message);
builder = TestMap.newBuilder();
TextFormat.merge(textData, builder);

View File

@ -147,7 +147,7 @@ public class TextFormatTest extends TestCase {
/** Print TestAllTypes and compare with golden file. */
public void testPrintMessage() throws Exception {
String javaText = TextFormat.printToString(TestUtil.getAllSet());
String javaText = TextFormat.printer().printToString(TestUtil.getAllSet());
// Java likes to add a trailing ".0" to floats and doubles. C printf
// (with %g format) does not. Our golden files are used for both
@ -159,7 +159,7 @@ public class TextFormatTest extends TestCase {
/** Print TestAllTypes as Builder and compare with golden file. */
public void testPrintMessageBuilder() throws Exception {
String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
String javaText = TextFormat.printer().printToString(TestUtil.getAllSetBuilder());
// Java likes to add a trailing ".0" to floats and doubles. C printf
// (with %g format) does not. Our golden files are used for both
@ -171,7 +171,7 @@ public class TextFormatTest extends TestCase {
/** Print TestAllExtensions and compare with golden file. */
public void testPrintExtensions() throws Exception {
String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
String javaText = TextFormat.printer().printToString(TestUtil.getAllExtensionsSet());
// Java likes to add a trailing ".0" to floats and doubles. C printf
// (with %g format) does not. Our golden files are used for both
@ -237,12 +237,13 @@ public class TextFormatTest extends TestCase {
+ "15: 12379813812177893520\n"
+ "15: 0xabcd1234\n"
+ "15: 0xabcdef1234567890\n",
TextFormat.printToString(message));
TextFormat.printer().printToString(message));
}
public void testPrintField() throws Exception {
final FieldDescriptor dataField = OneString.getDescriptor().findFieldByName("data");
assertEquals("data: \"test data\"\n", TextFormat.printFieldToString(dataField, "test data"));
assertEquals(
"data: \"test data\"\n", TextFormat.printer().printFieldToString(dataField, "test data"));
final FieldDescriptor optionalField =
TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
@ -250,7 +251,7 @@ public class TextFormatTest extends TestCase {
assertEquals(
"optional_nested_message {\n bb: 42\n}\n",
TextFormat.printFieldToString(optionalField, value));
TextFormat.printer().printFieldToString(optionalField, value));
}
/**
@ -885,7 +886,8 @@ public class TextFormatTest extends TestCase {
private void assertPrintFieldValue(String expect, Object value, String fieldName)
throws Exception {
StringBuilder sb = new StringBuilder();
TextFormat.printFieldValue(TestAllTypes.getDescriptor().findFieldByName(fieldName), value, sb);
TextFormat.printer()
.printFieldValue(TestAllTypes.getDescriptor().findFieldByName(fieldName), value, sb);
assertEquals(expect, sb.toString());
}
@ -902,14 +904,17 @@ public class TextFormatTest extends TestCase {
public void testShortDebugString_field() {
final FieldDescriptor dataField = OneString.getDescriptor().findFieldByName("data");
assertEquals("data: \"test data\"", TextFormat.shortDebugString(dataField, "test data"));
assertEquals(
"data: \"test data\"",
TextFormat.printer().shortDebugString(dataField, "test data"));
final FieldDescriptor optionalField =
TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
final Object value = NestedMessage.newBuilder().setBb(42).build();
assertEquals(
"optional_nested_message { bb: 42 }", TextFormat.shortDebugString(optionalField, value));
"optional_nested_message { bb: 42 }",
TextFormat.printer().shortDebugString(optionalField, value));
}
public void testShortDebugString_unknown() {
@ -917,7 +922,7 @@ public class TextFormatTest extends TestCase {
"5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5: { 12: 6 } 5 { 10: 5 }"
+ " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
+ " 0xabcdef1234567890",
TextFormat.shortDebugString(makeUnknownFieldSet()));
TextFormat.printer().shortDebugString(makeUnknownFieldSet()));
}
public void testPrintToUnicodeString() throws Exception {
@ -925,23 +930,26 @@ public class TextFormatTest extends TestCase {
"optional_string: \"abc\u3042efg\"\n"
+ "optional_bytes: \"\\343\\201\\202\"\n"
+ "repeated_string: \"\u3093XYZ\"\n",
TextFormat.printToUnicodeString(
TestAllTypes.newBuilder()
.setOptionalString("abc\u3042efg")
.setOptionalBytes(bytes(0xe3, 0x81, 0x82))
.addRepeatedString("\u3093XYZ")
.build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(
TestAllTypes.newBuilder()
.setOptionalString("abc\u3042efg")
.setOptionalBytes(bytes(0xe3, 0x81, 0x82))
.addRepeatedString("\u3093XYZ")
.build()));
// Double quotes and backslashes should be escaped
assertEquals(
"optional_string: \"a\\\\bc\\\"ef\\\"g\"\n",
TextFormat.printToUnicodeString(
TestAllTypes.newBuilder().setOptionalString("a\\bc\"ef\"g").build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(TestAllTypes.newBuilder().setOptionalString("a\\bc\"ef\"g").build()));
// Test escaping roundtrip
TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("a\\bc\\\"ef\"g").build();
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), builder);
assertEquals(message.getOptionalString(), builder.getOptionalString());
}
@ -949,48 +957,61 @@ public class TextFormatTest extends TestCase {
// No newlines at start and end
assertEquals(
"optional_string: \"test newlines\\n\\nin\\nstring\"\n",
TextFormat.printToUnicodeString(
TestAllTypes.newBuilder().setOptionalString("test newlines\n\nin\nstring").build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(
TestAllTypes.newBuilder()
.setOptionalString("test newlines\n\nin\nstring")
.build()));
// Newlines at start and end
assertEquals(
"optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n",
TextFormat.printToUnicodeString(
TestAllTypes.newBuilder()
.setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
.build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(
TestAllTypes.newBuilder()
.setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
.build()));
// Strings with 0, 1 and 2 newlines.
assertEquals(
"optional_string: \"\"\n",
TextFormat.printToUnicodeString(TestAllTypes.newBuilder().setOptionalString("").build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(TestAllTypes.newBuilder().setOptionalString("").build()));
assertEquals(
"optional_string: \"\\n\"\n",
TextFormat.printToUnicodeString(TestAllTypes.newBuilder().setOptionalString("\n").build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(TestAllTypes.newBuilder().setOptionalString("\n").build()));
assertEquals(
"optional_string: \"\\n\\n\"\n",
TextFormat.printToUnicodeString(
TestAllTypes.newBuilder().setOptionalString("\n\n").build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(TestAllTypes.newBuilder().setOptionalString("\n\n").build()));
// Test escaping roundtrip
TestAllTypes message =
TestAllTypes.newBuilder().setOptionalString("\ntest\nnewlines\n\nin\nstring\n").build();
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), builder);
assertEquals(message.getOptionalString(), builder.getOptionalString());
}
public void testPrintToUnicodeString_unknown() {
assertEquals(
"1: \"\\343\\201\\202\"\n",
TextFormat.printToUnicodeString(
UnknownFieldSet.newBuilder()
.addField(
1,
UnknownFieldSet.Field.newBuilder()
.addLengthDelimited(bytes(0xe3, 0x81, 0x82))
.build())
.build()));
TextFormat.printer()
.escapingNonAscii(false)
.printToString(
UnknownFieldSet.newBuilder()
.addField(
1,
UnknownFieldSet.Field.newBuilder()
.addLengthDelimited(bytes(0xe3, 0x81, 0x82))
.build())
.build()));
}
@ -1120,7 +1141,7 @@ public class TextFormatTest extends TestCase {
TestUtil.setOneof(builder);
TestOneof2 message = builder.build();
TestOneof2.Builder dest = TestOneof2.newBuilder();
TextFormat.merge(TextFormat.printToUnicodeString(message), dest);
TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), dest);
TestUtil.assertOneofSet(dest.build());
}
@ -1159,7 +1180,7 @@ public class TextFormatTest extends TestCase {
.putInt32ToStringField(20, "banana")
.putInt32ToStringField(30, "cherry")
.build();
String text = TextFormat.printToUnicodeString(message);
String text = TextFormat.printer().escapingNonAscii(false).printToString(message);
{
TestMap.Builder dest = TestMap.newBuilder();
TextFormat.merge(text, dest);

View File

@ -234,7 +234,7 @@ public class UnknownEnumValueTest extends TestCase {
TestAllTypes message = builder.build();
// We can print a message with unknown enum values.
String textData = TextFormat.printToString(message);
String textData = TextFormat.printer().printToString(message);
assertEquals(
"optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n"
+ "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n"

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.7.0</version>
<version>3.8.0-rc-1</version>
</parent>
<artifactId>protobuf-javalite</artifactId>

View File

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.7.1</version>
<version>3.8.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [Parent]</name>
@ -101,6 +101,12 @@
<version>26.0-jre</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>0.45</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -1,134 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.7.1</version>
</parent>
<artifactId>protobuf-java-util</artifactId>
<packaging>bundle</packaging>
<name>Protocol Buffers [Util]</name>
<description>Utilities for Protocol Buffers</description>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
</dependency>
</dependencies>
<properties>
<!-- Use the core proto dir so that we can call the core generation script -->
<test.proto.dir>../core/src/test/proto</test.proto.dir>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Generate the test protos -->
<execution>
<id>generate-test-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<target>
<!-- Generate all of the test protos from the core module -->
<ant antfile="../core/generate-test-sources-build.xml"/>
<!-- Generate additional test protos for this module -->
<exec executable="${protoc}">
<arg value="--java_out=${generated.testsources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=src/test/proto"/>
<arg value="src/test/proto/com/google/protobuf/util/json_test.proto"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add the generated test sources to the build -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-generated-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${generated.testsources.dir}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Configure the OSGI bundle -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf.util</Bundle-SymbolicName>
<Export-Package>com.google.protobuf.util;version=${project.version}</Export-Package>
</instructions>
</configuration>
</plugin>
<!-- Configure the fat jar to include all dependencies -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.8.0</version>
</parent>
<artifactId>protobuf-java-util</artifactId>
<packaging>bundle</packaging>
<name>Protocol Buffers [Util]</name>
<description>Utilities for Protocol Buffers</description>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<!-- Use the core proto dir so that we can call the core generation script -->
<test.proto.dir>../core/src/test/proto</test.proto.dir>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- Generate the test protos -->
<execution>
<id>generate-test-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<target>
<!-- Generate all of the test protos from the core module -->
<ant antfile="../core/generate-test-sources-build.xml"/>
<!-- Generate additional test protos for this module -->
<exec executable="${protoc}">
<arg value="--java_out=${generated.testsources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=src/test/proto"/>
<arg value="src/test/proto/com/google/protobuf/util/json_test.proto"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add the generated test sources to the build -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-generated-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${generated.testsources.dir}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Configure the OSGI bundle -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf.util</Bundle-SymbolicName>
<Export-Package>com.google.protobuf.util;version=${project.version}</Export-Package>
</instructions>
</configuration>
</plugin>
<!-- Configure the fat jar to include all dependencies -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,65 @@
// 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.Struct;
import com.google.protobuf.Value;
/** Utilities to help create {@code google.protobuf.Struct} messages. */
public final class Structs {
/**
* Returns a struct containing the key-value pair.
*/
public static Struct of(String k1, Value v1) {
return Struct.newBuilder().putFields(k1, v1).build();
}
/**
* Returns a struct containing each of the key-value pairs.
*
* <p>Providing duplicate keys is undefined behavior.
*/
public static Struct of(String k1, Value v1, String k2, Value v2) {
return Struct.newBuilder().putFields(k1, v1).putFields(k2, v2).build();
}
/**
* Returns a struct containing each of the key-value pairs.
*
* <p>Providing duplicate keys is undefined behavior.
*/
public static Struct of(String k1, Value v1, String k2, Value v2, String k3, Value v3) {
return Struct.newBuilder().putFields(k1, v1).putFields(k2, v2).putFields(k3, v3).build();
}
private Structs() {}
}

View File

@ -0,0 +1,85 @@
// 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.ListValue;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
/** Utilities to help create {@code google.protobuf.Value} messages. */
public final class Values {
private static final Value NULL_VALUE =
Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build();
public static Value ofNull() {
return NULL_VALUE;
}
/** Returns a Value object with number set to value. */
public static Value of(boolean value) {
return Value.newBuilder().setBoolValue(value).build();
}
/** Returns a Value object with number set to value. */
public static Value of(double value) {
return Value.newBuilder().setNumberValue(value).build();
}
/** Returns a Value object with string set to value. */
public static Value of(String value) {
return Value.newBuilder().setStringValue(value).build();
}
/** Returns a Value object with struct set to value. */
public static Value of(Struct value) {
return Value.newBuilder().setStructValue(value).build();
}
/** Returns a Value with ListValue set to value. */
public static Value of(ListValue value) {
return Value.newBuilder().setListValue(value).build();
}
/**
* Returns a Value with ListValue set to the appending the result of calling {@link #of(Object)}
* on each element in the iterable.
*/
public static Value of(Iterable<Value> values) {
Value.Builder valueBuilder = Value.newBuilder();
ListValue.Builder listValue = valueBuilder.getListValueBuilder();
listValue.addAllValues(values);
return valueBuilder.build();
}
private Values() {}
}

View File

@ -0,0 +1,59 @@
// 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.truth.Truth.assertThat;
import com.google.protobuf.Struct;
import junit.framework.TestCase;
public final class StructsTest extends TestCase {
public void test1pair_constructsObject() throws Exception {
Struct.Builder expected = Struct.newBuilder();
JsonFormat.parser().merge("{\"k1\": 1}", expected);
assertThat(Structs.of("k1", Values.of(1))).isEqualTo(expected.build());
}
public void test2pair_constructsObject() throws Exception {
Struct.Builder expected = Struct.newBuilder();
JsonFormat.parser().merge("{\"k1\": 1, \"k2\": 2}", expected);
assertThat(Structs.of("k1", Values.of(1), "k2", Values.of(2))).isEqualTo(expected.build());
}
public void test3pair_constructsObject() throws Exception {
Struct.Builder expected = Struct.newBuilder();
JsonFormat.parser().merge("{\"k1\": 1, \"k2\": 2, \"k3\": 3}", expected);
assertThat(Structs.of("k1", Values.of(1), "k2", Values.of(2), "k3", Values.of(3)))
.isEqualTo(expected.build());
}
}

View File

@ -0,0 +1,102 @@
// 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.truth.Truth.assertThat;
import com.google.protobuf.ListValue;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
public final class ValuesTest extends TestCase {
public void testOfNull_IsNullValue() throws Exception {
assertThat(Values.ofNull())
.isEqualTo(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build());
}
public void testOfBoolean_ConstructsValue() {
assertThat(Values.of(true)).isEqualTo(Value.newBuilder().setBoolValue(true).build());
assertThat(Values.of(false)).isEqualTo(Value.newBuilder().setBoolValue(false).build());
}
public void testOfNumeric_ConstructsValue() {
assertThat(Values.of(100)).isEqualTo(Value.newBuilder().setNumberValue(100).build());
assertThat(Values.of(1000L)).isEqualTo(Value.newBuilder().setNumberValue(1000).build());
assertThat(Values.of(1000.23f)).isEqualTo(Value.newBuilder().setNumberValue(1000.23f).build());
assertThat(Values.of(10000.23)).isEqualTo(Value.newBuilder().setNumberValue(10000.23).build());
}
public void testOfString_ConstructsValue() {
assertThat(Values.of("")).isEqualTo(Value.newBuilder().setStringValue("").build());
assertThat(Values.of("foo")).isEqualTo(Value.newBuilder().setStringValue("foo").build());
}
public void testOfStruct_ConstructsValue() {
Struct.Builder builder = Struct.newBuilder();
builder.putFields("a", Values.of("a"));
builder.putFields("b", Values.of("b"));
assertThat(Values.of(builder.build()))
.isEqualTo(Value.newBuilder().setStructValue(builder.build()).build());
}
public void testOfListValue_ConstructsInstance() {
ListValue.Builder builder = ListValue.newBuilder();
builder.addValues(Values.of(1));
builder.addValues(Values.of(2));
assertThat(Values.of(builder.build()))
.isEqualTo(Value.newBuilder().setListValue(builder.build()).build());
}
public void testOfIterable_ReturnsTheValue() {
ListValue.Builder builder = ListValue.newBuilder();
builder.addValues(Values.of(1));
builder.addValues(Values.of(2));
builder.addValues(Values.of(true));
builder.addValues(Value.newBuilder().setListValue(builder.build()).build());
List<Value> list = new ArrayList<>();
list.add(Values.of(1));
list.add(Values.of(2));
list.add(Values.of(true));
List<Value> copyList = new ArrayList<>(list);
list.add(Values.of(copyList));
assertThat(Values.of(list)).isEqualTo(Value.newBuilder().setListValue(builder).build());
assertThat(Values.of(new ArrayList<Value>()))
.isEqualTo(Value.newBuilder().setListValue(ListValue.getDefaultInstance()).build());
}
}

View File

@ -958,19 +958,19 @@ jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
// If we already have a map in the map wrappers, return that.
if (fieldNumber in msg.wrappers_) {
return msg.wrappers_[fieldNumber];
} else if (noLazyCreate) {
return undefined;
} else {
// Wrap the underlying elements array with a Map.
var arr = jspb.Message.getField(msg, fieldNumber);
if (!arr) {
arr = [];
jspb.Message.setField(msg, fieldNumber, arr);
}
return msg.wrappers_[fieldNumber] =
new jspb.Map(
/** @type {!Array<!Array<!Object>>} */ (arr), opt_valueCtor);
}
var arr = jspb.Message.getField(msg, fieldNumber);
// Wrap the underlying elements array with a Map.
if (!arr) {
if (noLazyCreate) {
return undefined;
}
arr = [];
jspb.Message.setField(msg, fieldNumber, arr);
}
return msg.wrappers_[fieldNumber] =
new jspb.Map(
/** @type {!Array<!Array<!Object>>} */ (arr), opt_valueCtor);
};

View File

@ -1,6 +1,6 @@
{
"name": "google-protobuf",
"version": "3.7.1",
"version": "3.8.0",
"description": "Protocol Buffers for JavaScript",
"main": "google-protobuf.js",
"files": [

View File

@ -41,7 +41,7 @@ OPTIONS:
Skip the Xcode Debug configuration.
--skip-xcode-release
Skip the Xcode Release configuration.
--skip-xcode-osx
--skip-xcode-osx | --skip-xcode-macos
Skip the invoke of Xcode to test the runtime on OS X.
--skip-xcode-tvos
Skip the invoke of Xcode to test the runtime on tvOS.
@ -119,7 +119,7 @@ while [[ $# != 0 ]]; do
--skip-xcode-ios )
DO_XCODE_IOS_TESTS=no
;;
--skip-xcode-osx )
--skip-xcode-osx | --skip-xcode-macos)
DO_XCODE_OSX_TESTS=no
;;
--skip-xcode-tvos )
@ -280,7 +280,16 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
-disable-concurrent-testing
)
;;
10.[0-1]* )
10.*)
XCODEBUILD_TEST_BASE_IOS+=(
-destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
-destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
# 10.x also seems to often fail running destinations in parallel (with
# 32bit one include atleast)
-disable-concurrent-destination-testing
)
;;
11.0* )
XCODEBUILD_TEST_BASE_IOS+=(
-destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
-destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
@ -340,10 +349,27 @@ if [[ "${DO_XCODE_TVOS_TESTS}" == "yes" ]] ; then
xcodebuild
-project objectivec/ProtocolBuffers_tvOS.xcodeproj
-scheme ProtocolBuffers
# Test on the oldest and current.
-destination "platform=tvOS Simulator,name=Apple TV 1080p,OS=9.0"
-destination "platform=tvOS Simulator,name=Apple TV,OS=latest"
)
case "${XCODE_VERSION}" in
[6-9].* )
echo "ERROR: Xcode 10.0 or higher is required to build the test suite." 1>&2
exit 11
;;
10.* | 11.* )
XCODEBUILD_TEST_BASE_TVOS+=(
# Test on the oldest and current.
-destination "platform=tvOS Simulator,name=Apple TV,OS=11.0"
-destination "platform=tvOS Simulator,name=Apple TV 4K,OS=latest"
)
;;
* )
echo ""
echo "ATTENTION: Time to update the simulator targets for Xcode ${XCODE_VERSION}"
echo ""
echo "ERROR: Build aborted!"
exit 2
;;
esac
if [[ "${XCODE_QUIET}" == "yes" ]] ; then
XCODEBUILD_TEST_BASE_TVOS+=( -quiet )
fi

View File

@ -75,7 +75,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/** Number of extension ranges declared for the message. */
@property(nonatomic, readonly) uint32_t extensionRangesCount;
/** Descriptor for the file where the message was defined. */
@property(nonatomic, readonly, assign) GPBFileDescriptor *file;
@property(nonatomic, readonly) GPBFileDescriptor *file;
/** Whether the message is in wire format or not. */
@property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat;
@ -188,10 +188,10 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
@property(nonatomic, readonly, getter=isPackable) BOOL packable;
/** The containing oneof if this field is part of one, nil otherwise. */
@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof;
@property(nonatomic, readonly, nullable) GPBOneofDescriptor *containingOneof;
/** Class of the message if the field is of message type. */
@property(nonatomic, readonly, assign, nullable) Class msgClass;
@property(nonatomic, readonly, nullable) Class msgClass;
/** Descriptor for the enum if this field is an enum. */
@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor;
@ -305,7 +305,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/** Whether the extension is packable. */
@property(nonatomic, readonly, getter=isPackable) BOOL packable;
/** The class of the message if the extension is of message type. */
@property(nonatomic, readonly, assign) Class msgClass;
@property(nonatomic, readonly) Class msgClass;
/** The singleton name for the extension. */
@property(nonatomic, readonly) NSString *singletonName;
/** The enum descriptor if the extension is of enum type. */

View File

@ -1482,7 +1482,7 @@
[msg release];
msg = [[Message2 alloc] init];
uint32_t values[] = {
int32_t values[] = {
Message2_O_OneOfCase_OneofInt32,
Message2_O_OneOfCase_OneofInt64,
Message2_O_OneOfCase_OneofUint32,
@ -1992,7 +1992,7 @@
[msg release];
msg = [[Message3 alloc] init];
uint32_t values[] = {
int32_t values[] = {
Message3_O_OneOfCase_OneofInt32,
Message3_O_OneOfCase_OneofInt64,
Message3_O_OneOfCase_OneofUint32,
@ -2113,7 +2113,7 @@
Message2 *msg = [[Message2 alloc] init];
uint32_t values[] = {
int32_t values[] = {
Message2_O_OneOfCase_OneofInt32,
Message2_O_OneOfCase_OneofInt64,
Message2_O_OneOfCase_OneofUint32,
@ -2242,7 +2242,7 @@
Message3 *msg = [[Message3 alloc] init];
uint32_t values[] = {
int32_t values[] = {
Message3_O_OneOfCase_OneofInt32,
Message3_O_OneOfCase_OneofInt64,
Message3_O_OneOfCase_OneofUint32,

View File

@ -10,11 +10,11 @@
<email>protobuf-opensource@google.com</email>
<active>yes</active>
</lead>
<date>2019-03-25</date>
<time>13:23:39</time>
<date>2019-05-21</date>
<time>14:07:13</time>
<version>
<release>3.7.1</release>
<api>3.7.1</api>
<release>3.8.0</release>
<api>3.8.0</api>
</version>
<stability>
<release>stable</release>
@ -26,6 +26,7 @@
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="config.m4" role="src"/>
<file baseinstalldir="/" name="array.c" role="src"/>
<file baseinstalldir="/" name="builtin_descriptors.inc" role="src"/>
<file baseinstalldir="/" name="def.c" role="src"/>
<file baseinstalldir="/" name="encode_decode.c" role="src"/>
<file baseinstalldir="/" name="map.c" role="src"/>
@ -318,5 +319,33 @@ G A release.
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>GA release.</notes>
</release>
<release>
<version>
<release>3.8.0RC1</release>
<api>3.8.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2019-04-23</date>
<time>16:14:52</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>GA release.</notes>
</release>
<release>
<version>
<release>3.8.0</release>
<api>3.8.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2019-05-21</date>
<time>14:07:13</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>GA release.</notes>
</release>
</changelog>
</package>

View File

@ -37,7 +37,7 @@
#include "upb.h"
#define PHP_PROTOBUF_EXTNAME "protobuf"
#define PHP_PROTOBUF_VERSION "3.7.1"
#define PHP_PROTOBUF_VERSION "3.8.0"
#define MAX_LENGTH_OF_INT64 20
#define SIZEOF_INT64 8

View File

@ -10460,6 +10460,48 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
#define EPOCH_YEAR 1970
#define TM_YEAR_BASE 1900
static bool isleap(int year) {
return (year % 4) == 0 && (year % 100 != 0 || (year % 400) == 0);
}
const unsigned short int __mon_yday[2][13] = {
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int64_t epoch(int year, int yday, int hour, int min, int sec) {
int64_t years = year - EPOCH_YEAR;
int64_t leap_days = years / 4 - years / 100 + years / 400;
int64_t days = years * 365 + yday + leap_days;
int64_t hours = days * 24 + hour;
int64_t mins = hours * 60 + min;
int64_t secs = mins * 60 + sec;
return secs;
}
static int64_t upb_mktime(const struct tm *tp) {
int sec = tp->tm_sec;
int min = tp->tm_min;
int hour = tp->tm_hour;
int mday = tp->tm_mday;
int mon = tp->tm_mon;
int year = tp->tm_year + TM_YEAR_BASE;
/* Calculate day of year from year, month, and day of month. */
int mon_yday = ((__mon_yday[isleap(year)][mon]) - 1);
int yday = mon_yday + mday;
return epoch(year, yday, hour, min, sec);
}
static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
size_t len;
const char *buf;
@ -10487,7 +10529,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
}
/* Normalize tm */
seconds = mktime(&p->tm);
seconds = upb_mktime(&p->tm);
/* Check timestamp boundary */
if (seconds < -62135596800) {

View File

@ -55,7 +55,7 @@ class DescriptorPool
return self::$pool;
}
public function internalAddGeneratedFile($data)
public function internalAddGeneratedFile($data, $use_nested = false)
{
$files = new FileDescriptorSet();
$files->mergeFromString($data);

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.DescriptorProto</code>
*/
class DescriptorProto extends \Google\Protobuf\Internal\Message
final class DescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.DescriptorProto.ExtensionRange</code>
*/
class ExtensionRange extends \Google\Protobuf\Internal\Message
final class ExtensionRange extends \Google\Protobuf\Internal\Message
{
/**
* Inclusive.

View File

@ -17,7 +17,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.DescriptorProto.ReservedRange</code>
*/
class ReservedRange extends \Google\Protobuf\Internal\Message
final class ReservedRange extends \Google\Protobuf\Internal\Message
{
/**
* Inclusive.

View File

@ -39,17 +39,26 @@ class EnumDescriptor
public function getValueByNumber($number)
{
return $this->value[$number];
if (isset($this->value[$number])) {
return $this->value[$number];
}
return null;
}
public function getValueByName($name)
{
return $this->name_to_value[$name];
if (isset($this->name_to_value[$name])) {
return $this->name_to_value[$name];
}
return null;
}
public function getValueDescriptorByIndex($index)
{
return $this->value_descriptor[$index];
if (isset($this->value_descriptor[$index])) {
return $this->value_descriptor[$index];
}
return null;
}
public function getValueCount()

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.EnumDescriptorProto</code>
*/
class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
final class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -19,7 +19,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.EnumDescriptorProto.EnumReservedRange</code>
*/
class EnumReservedRange extends \Google\Protobuf\Internal\Message
final class EnumReservedRange extends \Google\Protobuf\Internal\Message
{
/**
* Inclusive.

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.EnumOptions</code>
*/
class EnumOptions extends \Google\Protobuf\Internal\Message
final class EnumOptions extends \Google\Protobuf\Internal\Message
{
/**
* Set this option to true to allow mapping different tag names to the same

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.EnumValueDescriptorProto</code>
*/
class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
final class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.EnumValueOptions</code>
*/
class EnumValueOptions extends \Google\Protobuf\Internal\Message
final class EnumValueOptions extends \Google\Protobuf\Internal\Message
{
/**
* Is this enum value deprecated?

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.ExtensionRangeOptions</code>
*/
class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message
final class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message
{
/**
* The parser stores options it doesn't recognize here. See above.

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.FieldDescriptorProto</code>
*/
class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
final class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.FieldOptions</code>
*/
class FieldOptions extends \Google\Protobuf\Internal\Message
final class FieldOptions extends \Google\Protobuf\Internal\Message
{
/**
* The ctype option instructs the C++ code generator to use a different

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.FileDescriptorProto</code>
*/
class FileDescriptorProto extends \Google\Protobuf\Internal\Message
final class FileDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* file name, relative to root of source tree

View File

@ -16,7 +16,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.FileDescriptorSet</code>
*/
class FileDescriptorSet extends \Google\Protobuf\Internal\Message
final class FileDescriptorSet extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.FileOptions</code>
*/
class FileOptions extends \Google\Protobuf\Internal\Message
final class FileOptions extends \Google\Protobuf\Internal\Message
{
/**
* Sets the Java package where classes generated from this .proto will be

View File

@ -504,18 +504,30 @@ class GPBUtil
public static function formatDuration($value)
{
if (bccomp($value->getSeconds(), "315576000001") != -1) {
throw new GPBDecodeException("Duration number too large.");
if (bccomp($value->getSeconds(), '315576000001') != -1) {
throw new GPBDecodeException('Duration number too large.');
}
if (bccomp($value->getSeconds(), "-315576000001") != 1) {
throw new GPBDecodeException("Duration number too small.");
if (bccomp($value->getSeconds(), '-315576000001') != 1) {
throw new GPBDecodeException('Duration number too small.');
}
return strval(bcadd($value->getSeconds(),
$value->getNanos() / 1000000000.0, 9));
$nanos = $value->getNanos();
if ($nanos === 0) {
return (string) $value->getSeconds();
}
if ($nanos % 1000000 === 0) {
$digits = 3;
} elseif ($nanos % 1000 === 0) {
$digits = 6;
} else {
$digits = 9;
}
$nanos = bcdiv($nanos, '1000000000', $digits);
return bcadd($value->getSeconds(), $nanos, $digits);
}
public static function parseFieldMask($paths_string)
{
$field_mask = new FieldMask();

View File

@ -17,7 +17,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.GeneratedCodeInfo</code>
*/
class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
final class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
{
/**
* An Annotation connects some span of text in generated code to an element

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.GeneratedCodeInfo.Annotation</code>
*/
class Annotation extends \Google\Protobuf\Internal\Message
final class Annotation extends \Google\Protobuf\Internal\Message
{
/**
* Identifies the element in the original source .proto file. This field

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.MessageOptions</code>
*/
class MessageOptions extends \Google\Protobuf\Internal\Message
final class MessageOptions extends \Google\Protobuf\Internal\Message
{
/**
* Set true to use the old proto1 MessageSet wire format for extensions.

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.MethodDescriptorProto</code>
*/
class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
final class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.MethodOptions</code>
*/
class MethodOptions extends \Google\Protobuf\Internal\Message
final class MethodOptions extends \Google\Protobuf\Internal\Message
{
/**
* Is this method deprecated?

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.OneofDescriptorProto</code>
*/
class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
final class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.OneofOptions</code>
*/
class OneofOptions extends \Google\Protobuf\Internal\Message
final class OneofOptions extends \Google\Protobuf\Internal\Message
{
/**
* The parser stores options it doesn't recognize here. See above.

View File

@ -15,7 +15,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.ServiceDescriptorProto</code>
*/
class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
final class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>optional string name = 1;</code>

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.ServiceOptions</code>
*/
class ServiceOptions extends \Google\Protobuf\Internal\Message
final class ServiceOptions extends \Google\Protobuf\Internal\Message
{
/**
* Is this service deprecated?

View File

@ -16,7 +16,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.SourceCodeInfo</code>
*/
class SourceCodeInfo extends \Google\Protobuf\Internal\Message
final class SourceCodeInfo extends \Google\Protobuf\Internal\Message
{
/**
* A Location identifies a piece of source code in a .proto file which

View File

@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>google.protobuf.SourceCodeInfo.Location</code>
*/
class Location extends \Google\Protobuf\Internal\Message
final class Location extends \Google\Protobuf\Internal\Message
{
/**
* Identifies which part of the FileDescriptorProto was defined at this

View File

@ -20,7 +20,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.UninterpretedOption</code>
*/
class UninterpretedOption extends \Google\Protobuf\Internal\Message
final class UninterpretedOption extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>

View File

@ -19,7 +19,7 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.UninterpretedOption.NamePart</code>
*/
class NamePart extends \Google\Protobuf\Internal\Message
final class NamePart extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>required string name_part = 1;</code>

View File

@ -24,3 +24,14 @@ message TestWrapperSetters {
map<string, google.protobuf.StringValue> map_string_value = 13;
}
message TestWrapperAccessorConflicts {
int32 normal_vs_wrapper_value = 1;
google.protobuf.Int32Value normal_vs_wrapper = 2;
int32 normal_vs_normal_value = 3;
int32 normal_vs_normal = 4;
google.protobuf.Int32Value wrapper_vs_wrapper_value = 5;
google.protobuf.Int32Value wrapper_vs_wrapper = 6;
}

View File

@ -16,6 +16,44 @@ use Google\Protobuf\UInt64Value;
class WrapperTypeSettersTest extends TestBase
{
public function testConflictNormalVsWrapper()
{
$m = new Foo\TestWrapperAccessorConflicts();
$m->setNormalVsWrapperValue1(1);
$this->assertSame(1, $m->getNormalVsWrapperValue1());
$m->setNormalVsWrapperValue2(1);
$this->assertSame(1, $m->getNormalVsWrapperValue2());
$wrapper = new Int32Value(["value" => 1]);
$m->setNormalVsWrapper($wrapper);
$this->assertSame(1, $m->getNormalVsWrapper()->getValue());
}
public function testConflictNormalVsNormal()
{
$m = new Foo\TestWrapperAccessorConflicts();
$m->setNormalVsNormalValue(1);
$this->assertSame(1, $m->getNormalVsNormalValue());
$m->setNormalVsNormal(1);
$this->assertSame(1, $m->getNormalVsNormal());
}
public function testConflictWrapperVsWrapper()
{
$m = new Foo\TestWrapperAccessorConflicts();
$m->setWrapperVsWrapperValueValue(1);
$this->assertSame(1, $m->getWrapperVsWrapperValueValue());
$wrapper = new Int32Value(["value" => 1]);
$m->setWrapperVsWrapperValue5($wrapper);
$this->assertSame(1, $m->getWrapperVsWrapperValue5()->getValue());
}
/**
* @dataProvider gettersAndSettersDataProvider
*/

View File

@ -117,6 +117,7 @@ def _proto_gen_impl(ctx):
outs = [ctx.actions.declare_file(out, sibling = src) for out in outs]
inputs = [src] + deps
tools = [ctx.executable.protoc]
if ctx.executable.plugin:
plugin = ctx.executable.plugin
lang = ctx.attr.plugin_language
@ -131,11 +132,12 @@ def _proto_gen_impl(ctx):
outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
args += [("--plugin=protoc-gen-%s=" + path_tpl) % (lang, plugin.path)]
args += ["--%s_out=%s" % (lang, outdir)]
inputs += [plugin]
tools.append(plugin)
if not in_gen_dir:
ctx.actions.run(
inputs = inputs,
tools = tools,
outputs = outs,
arguments = args + import_flags + [src.path],
executable = ctx.executable.protoc,
@ -158,10 +160,11 @@ def _proto_gen_impl(ctx):
if generated_out != out.path:
command += ";mv %s %s" % (generated_out, out.path)
ctx.actions.run_shell(
inputs = inputs + [ctx.executable.protoc],
inputs = inputs,
outputs = [out],
command = command,
mnemonic = "ProtoCompile",
tools = tools,
use_default_shell_env = True,
)

View File

@ -8,7 +8,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId>
<version>3.7.1</version>
<version>3.8.0</version>
<packaging>pom</packaging>
<name>Protobuf Compiler</name>
<description>

View File

@ -1,7 +1,7 @@
Protocol Buffers - Google's data interchange format
===================================================
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_cpp%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_cpp%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous) [![Compat check PyPI](https://python-compatibility-tools.appspot.com/one_badge_image?package=protobuf)](https://python-compatibility-tools.appspot.com/one_badge_target?package=protobuf)
Copyright 2008 Google Inc.

View File

@ -30,7 +30,7 @@
# Copyright 2007 Google Inc. All Rights Reserved.
__version__ = '3.7.1'
__version__ = '3.8.0'
if __name__ != '__main__':
try:

View File

@ -99,8 +99,6 @@ def _IsMessageSetExtension(field):
field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL)
class DescriptorPool(object):
"""A collection of protobufs dynamically constructed by descriptor protos."""

View File

@ -615,18 +615,86 @@ class SecondaryDescriptorFromDescriptorDB(DescriptorPoolTestBase,
factory_test1_pb2.DESCRIPTOR.serialized_pb)
self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
factory_test2_pb2.DESCRIPTOR.serialized_pb)
db = descriptor_database.DescriptorDatabase()
db.Add(self.factory_test1_fd)
db.Add(self.factory_test2_fd)
db.Add(descriptor_pb2.FileDescriptorProto.FromString(
self.db = descriptor_database.DescriptorDatabase()
self.db.Add(self.factory_test1_fd)
self.db.Add(self.factory_test2_fd)
self.db.Add(descriptor_pb2.FileDescriptorProto.FromString(
unittest_import_public_pb2.DESCRIPTOR.serialized_pb))
db.Add(descriptor_pb2.FileDescriptorProto.FromString(
self.db.Add(descriptor_pb2.FileDescriptorProto.FromString(
unittest_import_pb2.DESCRIPTOR.serialized_pb))
db.Add(descriptor_pb2.FileDescriptorProto.FromString(
self.db.Add(descriptor_pb2.FileDescriptorProto.FromString(
unittest_pb2.DESCRIPTOR.serialized_pb))
db.Add(descriptor_pb2.FileDescriptorProto.FromString(
self.db.Add(descriptor_pb2.FileDescriptorProto.FromString(
no_package_pb2.DESCRIPTOR.serialized_pb))
self.pool = descriptor_pool.DescriptorPool(descriptor_db=db)
self.pool = descriptor_pool.DescriptorPool(descriptor_db=self.db)
def testErrorCollector(self):
file_proto = descriptor_pb2.FileDescriptorProto()
file_proto.package = 'collector'
file_proto.name = 'error_file'
message_type = file_proto.message_type.add()
message_type.name = 'ErrorMessage'
field = message_type.field.add()
field.number = 1
field.name = 'nested_message_field'
field.label = descriptor.FieldDescriptor.LABEL_OPTIONAL
field.type = descriptor.FieldDescriptor.TYPE_MESSAGE
field.type_name = 'SubMessage'
oneof = message_type.oneof_decl.add()
oneof.name = 'MyOneof'
enum_type = file_proto.enum_type.add()
enum_type.name = 'MyEnum'
enum_value = enum_type.value.add()
enum_value.name = 'MyEnumValue'
enum_value.number = 0
self.db.Add(file_proto)
self.assertRaisesRegexp(KeyError, 'SubMessage',
self.pool.FindMessageTypeByName,
'collector.ErrorMessage')
self.assertRaisesRegexp(KeyError, 'SubMessage',
self.pool.FindFileByName, 'error_file')
with self.assertRaises(KeyError) as exc:
self.pool.FindFileByName('none_file')
self.assertIn(str(exc.exception), ('\'none_file\'',
'\"Couldn\'t find file none_file\"'))
# Pure python _ConvertFileProtoToFileDescriptor() method has side effect
# that all the symbols found in the file will load into the pool even the
# file can not build. So when FindMessageTypeByName('ErrorMessage') was
# called the first time, a KeyError will be raised but call the find
# method later will return a descriptor which is not build.
# TODO(jieluo): fix pure python to revert the load if file can not be build
if api_implementation.Type() == 'cpp':
error_msg = ('Invalid proto descriptor for file "error_file":\\n '
'collector.ErrorMessage.nested_message_field: "SubMessage" '
'is not defined.\\n collector.ErrorMessage.MyOneof: Oneof '
'must have at least one field.\\n\'')
with self.assertRaises(KeyError) as exc:
self.pool.FindMessageTypeByName('collector.ErrorMessage')
self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for '
'message collector.ErrorMessage\\n' + error_msg)
with self.assertRaises(KeyError) as exc:
self.pool.FindFieldByName('collector.ErrorMessage.nested_message_field')
self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for field'
' collector.ErrorMessage.nested_message_field\\n'
+ error_msg)
with self.assertRaises(KeyError) as exc:
self.pool.FindEnumTypeByName('collector.MyEnum')
self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for enum'
' collector.MyEnum\\n' + error_msg)
with self.assertRaises(KeyError) as exc:
self.pool.FindFileContainingSymbol('collector.MyEnumValue')
self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for symbol'
' collector.MyEnumValue\\n' + error_msg)
with self.assertRaises(KeyError) as exc:
self.pool.FindOneofByName('collector.ErrorMessage.MyOneof')
self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for oneof'
' collector.ErrorMessage.MyOneof\\n' + error_msg)
class ProtoFile(object):

View File

@ -54,6 +54,7 @@ from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pool
from google.protobuf import json_format
from google.protobuf.util import json_format_pb2
from google.protobuf.util import json_format_proto3_pb2
@ -247,6 +248,22 @@ class JsonFormatTest(JsonFormatBase):
}
self.assertEqual(golden_dict, message_dict)
def testExtensionSerializationDictMatchesProto3SpecMore(self):
"""See go/proto3-json-spec for spec.
"""
message = json_format_pb2.TestMessageWithExtension()
ext = json_format_pb2.TestExtension.ext
message.Extensions[ext].value = 'stuff'
message_dict = json_format.MessageToDict(
message
)
expected_dict = {
'[protobuf_unittest.TestExtension.ext]': {
'value': u'stuff',
},
}
self.assertEqual(expected_dict, message_dict)
def testExtensionSerializationJsonMatchesProto3Spec(self):
"""See go/proto3-json-spec for spec.

View File

@ -1725,6 +1725,7 @@ class Proto3Test(unittest.TestCase):
self.assertIsNone(msg.map_int32_int32.get(5))
self.assertEqual(10, msg.map_int32_int32.get(5, 10))
self.assertEqual(10, msg.map_int32_int32.get(key=5, default=10))
self.assertIsNone(msg.map_int32_int32.get(5))
msg.map_int32_int32[5] = 15
@ -1735,6 +1736,7 @@ class Proto3Test(unittest.TestCase):
self.assertIsNone(msg.map_int32_foreign_message.get(5))
self.assertEqual(10, msg.map_int32_foreign_message.get(5, 10))
self.assertEqual(10, msg.map_int32_foreign_message.get(key=5, default=10))
submsg = msg.map_int32_foreign_message[5]
self.assertIs(submsg, msg.map_int32_foreign_message.get(5))

View File

@ -233,12 +233,8 @@ class _Printer(object):
js[name] = [self._FieldToJsonObject(field, k)
for k in value]
elif field.is_extension:
f = field
if (f.containing_type.GetOptions().message_set_wire_format and
f.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
f.label == descriptor.FieldDescriptor.LABEL_OPTIONAL):
f = f.message_type
name = '[%s.%s]' % (f.full_name, name)
full_qualifier = field.full_name[:-len(field.name)]
name = '[%s%s]' % (full_qualifier, name)
js[name] = self._FieldToJsonObject(field, value)
else:
js[name] = self._FieldToJsonObject(field, value)
@ -493,10 +489,16 @@ class _Parser(object):
raise ParseError('Message type {0} does not have extensions'.format(
message_descriptor.full_name))
identifier = name[1:-1] # strip [] brackets
identifier = '.'.join(identifier.split('.')[:-1])
# pylint: disable=protected-access
field = message.Extensions._FindExtensionByName(identifier)
# pylint: enable=protected-access
if not field:
# Try looking for extension by the message type name, dropping the
# field name following the final . separator in full_name.
identifier = '.'.join(identifier.split('.')[:-1])
# pylint: disable=protected-access
field = message.Extensions._FindExtensionByName(identifier)
# pylint: enable=protected-access
if not field:
if self.ignore_unknown_fields:
continue

View File

@ -67,6 +67,38 @@ static std::unordered_map<const DescriptorPool*, PyDescriptorPool*>*
namespace cdescriptor_pool {
// Collects errors that occur during proto file building to allow them to be
// propagated in the python exception instead of only living in ERROR logs.
class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
public:
BuildFileErrorCollector() : error_message(""), had_errors_(false) {}
void AddError(const string& filename, const string& element_name,
const Message* descriptor, ErrorLocation location,
const string& message) override {
// Replicates the logging behavior that happens in the C++ implementation
// when an error collector is not passed in.
if (!had_errors_) {
error_message +=
("Invalid proto descriptor for file \"" + filename + "\":\n");
had_errors_ = true;
}
// As this only happens on failure and will result in the program not
// running at all, no effort is made to optimize this string manipulation.
error_message += (" " + element_name + ": " + message + "\n");
}
void Clear() {
had_errors_ = false;
error_message = "";
}
string error_message;
private:
bool had_errors_;
};
// Create a Python DescriptorPool object, but does not fill the "pool"
// attribute.
static PyDescriptorPool* _CreateDescriptorPool() {
@ -76,6 +108,7 @@ static PyDescriptorPool* _CreateDescriptorPool() {
return NULL;
}
cpool->error_collector = nullptr;
cpool->underlay = NULL;
cpool->database = NULL;
@ -124,7 +157,8 @@ static PyDescriptorPool* PyDescriptorPool_NewWithDatabase(
return NULL;
}
if (database != NULL) {
cpool->pool = new DescriptorPool(database);
cpool->error_collector = new BuildFileErrorCollector();
cpool->pool = new DescriptorPool(database, cpool->error_collector);
cpool->database = database;
} else {
cpool->pool = new DescriptorPool();
@ -167,6 +201,7 @@ static void Dealloc(PyObject* pself) {
delete self->descriptor_options;
delete self->database;
delete self->pool;
delete self->error_collector;
Py_TYPE(self)->tp_free(pself);
}
@ -182,6 +217,20 @@ static int GcClear(PyObject* pself) {
return 0;
}
PyObject* SetErrorFromCollector(DescriptorPool::ErrorCollector* self,
char* name, char* error_type) {
BuildFileErrorCollector* error_collector =
reinterpret_cast<BuildFileErrorCollector*>(self);
if (error_collector && !error_collector->error_message.empty()) {
PyErr_Format(PyExc_KeyError, "Couldn't build file for %s %.200s\n%s",
error_type, name, error_collector->error_message.c_str());
error_collector->Clear();
return NULL;
}
PyErr_Format(PyExc_KeyError, "Couldn't find %s %.200s", error_type, name);
return NULL;
}
static PyObject* FindMessageByName(PyObject* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
@ -194,8 +243,9 @@ static PyObject* FindMessageByName(PyObject* self, PyObject* arg) {
string(name, name_size));
if (message_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name);
return NULL;
return SetErrorFromCollector(
reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
"message");
}
@ -212,12 +262,12 @@ static PyObject* FindFileByName(PyObject* self, PyObject* arg) {
return NULL;
}
PyDescriptorPool* py_pool = reinterpret_cast<PyDescriptorPool*>(self);
const FileDescriptor* file_descriptor =
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileByName(
string(name, name_size));
py_pool->pool->FindFileByName(string(name, name_size));
if (file_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", name);
return NULL;
return SetErrorFromCollector(py_pool->error_collector, name, "file");
}
return PyFileDescriptor_FromDescriptor(file_descriptor);
}
@ -232,9 +282,7 @@ PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
const FieldDescriptor* field_descriptor =
self->pool->FindFieldByName(string(name, name_size));
if (field_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find field %.200s",
name);
return NULL;
return SetErrorFromCollector(self->error_collector, name, "field");
}
@ -255,8 +303,8 @@ PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
const FieldDescriptor* field_descriptor =
self->pool->FindExtensionByName(string(name, name_size));
if (field_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find extension field %.200s", name);
return NULL;
return SetErrorFromCollector(self->error_collector, name,
"extension field");
}
@ -277,8 +325,7 @@ PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
const EnumDescriptor* enum_descriptor =
self->pool->FindEnumTypeByName(string(name, name_size));
if (enum_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find enum %.200s", name);
return NULL;
return SetErrorFromCollector(self->error_collector, name, "enum");
}
@ -299,8 +346,7 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
const OneofDescriptor* oneof_descriptor =
self->pool->FindOneofByName(string(name, name_size));
if (oneof_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find oneof %.200s", name);
return NULL;
return SetErrorFromCollector(self->error_collector, name, "oneof");
}
@ -322,8 +368,9 @@ static PyObject* FindServiceByName(PyObject* self, PyObject* arg) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName(
string(name, name_size));
if (service_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find service %.200s", name);
return NULL;
return SetErrorFromCollector(
reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
"service");
}
@ -341,8 +388,9 @@ static PyObject* FindMethodByName(PyObject* self, PyObject* arg) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMethodByName(
string(name, name_size));
if (method_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
return NULL;
return SetErrorFromCollector(
reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
"method");
}
@ -360,8 +408,9 @@ static PyObject* FindFileContainingSymbol(PyObject* self, PyObject* arg) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileContainingSymbol(
string(name, name_size));
if (file_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name);
return NULL;
return SetErrorFromCollector(
reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
"symbol");
}
@ -384,7 +433,16 @@ static PyObject* FindExtensionByNumber(PyObject* self, PyObject* args) {
reinterpret_cast<PyDescriptorPool*>(self)->pool->FindExtensionByNumber(
descriptor, number);
if (extension_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find extension %d", number);
BuildFileErrorCollector* error_collector =
reinterpret_cast<BuildFileErrorCollector*>(
reinterpret_cast<PyDescriptorPool*>(self)->error_collector);
if (error_collector && !error_collector->error_message.empty()) {
PyErr_Format(PyExc_KeyError, "Couldn't build file for Extension %.d\n%s",
number, error_collector->error_message.c_str());
error_collector->Clear();
return NULL;
}
PyErr_Format(PyExc_KeyError, "Couldn't find Extension %d", number);
return NULL;
}
@ -511,32 +569,6 @@ static PyObject* AddServiceDescriptor(PyObject* self, PyObject* descriptor) {
}
// The code below loads new Descriptors from a serialized FileDescriptorProto.
// Collects errors that occur during proto file building to allow them to be
// propagated in the python exception instead of only living in ERROR logs.
class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
public:
BuildFileErrorCollector() : error_message(""), had_errors(false) {}
void AddError(const string& filename, const string& element_name,
const Message* descriptor, ErrorLocation location,
const string& message) {
// Replicates the logging behavior that happens in the C++ implementation
// when an error collector is not passed in.
if (!had_errors) {
error_message +=
("Invalid proto descriptor for file \"" + filename + "\":\n");
had_errors = true;
}
// As this only happens on failure and will result in the program not
// running at all, no effort is made to optimize this string manipulation.
error_message += (" " + element_name + ": " + message + "\n");
}
string error_message;
bool had_errors;
};
static PyObject* AddSerializedFile(PyObject* pself, PyObject* serialized_pb) {
PyDescriptorPool* self = reinterpret_cast<PyDescriptorPool*>(pself);
char* message_type;

View File

@ -59,6 +59,10 @@ typedef struct PyDescriptorPool {
// The C++ pool containing Descriptors.
DescriptorPool* pool;
// The error collector to store error info. Can be NULL. This pointer is
// owned.
DescriptorPool::ErrorCollector* error_collector;
// The C++ pool acting as an underlay. Can be NULL.
// This pointer is not owned and must stay alive.
const DescriptorPool* underlay;

View File

@ -464,10 +464,13 @@ int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key,
}
}
static PyObject* ScalarMapGet(PyObject* self, PyObject* args) {
static PyObject* ScalarMapGet(PyObject* self, PyObject* args,
PyObject* kwargs) {
static char* kwlist[] = {"key", "default", nullptr};
PyObject* key;
PyObject* default_value = NULL;
if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
&default_value)) {
return NULL;
}
@ -532,23 +535,23 @@ static void ScalarMapDealloc(PyObject* _self) {
}
static PyMethodDef ScalarMapMethods[] = {
{ "__contains__", MapReflectionFriend::Contains, METH_O,
"Tests whether a key is a member of the map." },
{ "clear", (PyCFunction)Clear, METH_NOARGS,
"Removes all elements from the map." },
{ "get", ScalarMapGet, METH_VARARGS,
"Gets the value for the given key if present, or otherwise a default" },
{ "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
"Return the class used to build Entries of (key, value) pairs." },
{ "MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
"Merges a map into the current map." },
/*
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
"Outputs picklable representation of the repeated field." },
*/
{NULL, NULL},
{"__contains__", MapReflectionFriend::Contains, METH_O,
"Tests whether a key is a member of the map."},
{"clear", (PyCFunction)Clear, METH_NOARGS,
"Removes all elements from the map."},
{"get", (PyCFunction)ScalarMapGet, METH_VARARGS | METH_KEYWORDS,
"Gets the value for the given key if present, or otherwise a default"},
{"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
"Return the class used to build Entries of (key, value) pairs."},
{"MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
"Merges a map into the current map."},
/*
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
"Outputs picklable representation of the repeated field." },
*/
{NULL, NULL},
};
PyTypeObject *ScalarMapContainer_Type;
@ -773,10 +776,12 @@ PyObject* MapReflectionFriend::MessageMapToStr(PyObject* _self) {
return PyObject_Repr(dict.get());
}
PyObject* MessageMapGet(PyObject* self, PyObject* args) {
PyObject* MessageMapGet(PyObject* self, PyObject* args, PyObject* kwargs) {
static char* kwlist[] = {"key", "default", nullptr};
PyObject* key;
PyObject* default_value = NULL;
if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
&default_value)) {
return NULL;
}
@ -810,25 +815,25 @@ static void MessageMapDealloc(PyObject* _self) {
}
static PyMethodDef MessageMapMethods[] = {
{ "__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O,
"Tests whether the map contains this element."},
{ "clear", (PyCFunction)Clear, METH_NOARGS,
"Removes all elements from the map."},
{ "get", MessageMapGet, METH_VARARGS,
"Gets the value for the given key if present, or otherwise a default" },
{ "get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O,
"Alias for getitem, useful to make explicit that the map is mutated." },
{ "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
"Return the class used to build Entries of (key, value) pairs." },
{ "MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
"Merges a map into the current map." },
/*
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
"Outputs picklable representation of the repeated field." },
*/
{NULL, NULL},
{"__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O,
"Tests whether the map contains this element."},
{"clear", (PyCFunction)Clear, METH_NOARGS,
"Removes all elements from the map."},
{"get", (PyCFunction)MessageMapGet, METH_VARARGS | METH_KEYWORDS,
"Gets the value for the given key if present, or otherwise a default"},
{"get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O,
"Alias for getitem, useful to make explicit that the map is mutated."},
{"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
"Return the class used to build Entries of (key, value) pairs."},
{"MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
"Merges a map into the current map."},
/*
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
"Outputs picklable representation of the repeated field." },
*/
{NULL, NULL},
};
PyTypeObject *MessageMapContainer_Type;

View File

@ -92,6 +92,7 @@ def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/unittest_mset_wire_format.proto", False)
generate_proto("../src/google/protobuf/unittest_no_generic_services.proto", False)
generate_proto("../src/google/protobuf/unittest_proto3_arena.proto", False)
generate_proto("../src/google/protobuf/util/json_format.proto", False)
generate_proto("../src/google/protobuf/util/json_format_proto3.proto", False)
generate_proto("google/protobuf/internal/any_test.proto", False)
generate_proto("google/protobuf/internal/descriptor_pool_test1.proto", False)

View File

@ -389,6 +389,9 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
mapdata->value_field_type == UPB_TYPE_ENUM) {
value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
if (mapdata->value_field_type == UPB_TYPE_ENUM) {
value_field_typeclass = EnumDescriptor_enummodule(value_field_typeclass);
}
}
value = native_slot_get(

View File

@ -847,7 +847,6 @@ void Map_register(VALUE module) {
rb_define_method(klass, "dup", Map_dup, 0);
rb_define_method(klass, "==", Map_eq, 1);
rb_define_method(klass, "hash", Map_hash, 0);
rb_define_method(klass, "to_hash", Map_to_h, 0);
rb_define_method(klass, "to_h", Map_to_h, 0);
rb_define_method(klass, "inspect", Map_inspect, 0);
rb_define_method(klass, "merge", Map_merge, 1);

View File

@ -737,7 +737,6 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
rb_define_method(klass, "eql?", Message_eq, 1);
rb_define_method(klass, "hash", Message_hash, 0);
rb_define_method(klass, "to_h", Message_to_h, 0);
rb_define_method(klass, "to_hash", Message_to_h, 0);
rb_define_method(klass, "inspect", Message_inspect, 0);
rb_define_method(klass, "to_s", Message_inspect, 0);
rb_define_method(klass, "[]", Message_index, 1);

View File

@ -14299,6 +14299,47 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
#define EPOCH_YEAR 1970
#define TM_YEAR_BASE 1900
static bool isleap(int year) {
return (year % 4) == 0 && (year % 100 != 0 || (year % 400) == 0);
}
const unsigned short int __mon_yday[2][13] = {
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int64_t epoch(int year, int yday, int hour, int min, int sec) {
int64_t years = year - EPOCH_YEAR;
int64_t leap_days = years / 4 - years / 100 + years / 400;
int64_t days = years * 365 + yday + leap_days;
int64_t hours = days * 24 + hour;
int64_t mins = hours * 60 + min;
int64_t secs = mins * 60 + sec;
return secs;
}
static int64_t upb_mktime(const struct tm *tp) {
int sec = tp->tm_sec;
int min = tp->tm_min;
int hour = tp->tm_hour;
int mday = tp->tm_mday;
int mon = tp->tm_mon;
int year = tp->tm_year + TM_YEAR_BASE;
/* Calculate day of year from year, month, and day of month. */
int mon_yday = ((__mon_yday[isleap(year)][mon]) - 1);
int yday = mon_yday + mday;
return epoch(year, yday, hour, min, sec);
}
static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
size_t len;
const char *buf;
@ -14325,7 +14366,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
}
/* Normalize tm */
seconds = mktime(&p->tm) - timezone;
seconds = upb_mktime(&p->tm);
seconds += 3600 * hours;
/* Check timestamp boundary */

View File

@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "google-protobuf"
s.version = "3.7.1"
s.version = "3.8.0"
s.licenses = ["BSD-3-Clause"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
@ -20,6 +20,7 @@ Gem::Specification.new do |s|
s.test_files = ["tests/basic.rb",
"tests/stress.rb",
"tests/generated_code_test.rb"]
s.required_ruby_version = '>= 2.3'
s.add_development_dependency "rake-compiler", "~> 0.9.5"
s.add_development_dependency "test-unit", '~> 3.0', '>= 3.0.9'
s.add_development_dependency "rubygems-tasks", "~> 0.2.4"

View File

@ -338,7 +338,7 @@ public class RubyMap extends RubyObject {
return newMap;
}
@JRubyMethod(name = {"to_h", "to_hash"})
@JRubyMethod(name = "to_h")
public RubyHash toHash(ThreadContext context) {
return RubyHash.newHash(context.runtime, table, context.runtime.getNil());
}

View File

@ -368,7 +368,7 @@ public class RubyMessage extends RubyObject {
return ret;
}
@JRubyMethod(name = {"to_h", "to_hash"})
@JRubyMethod(name = "to_h")
public IRubyObject toHash(ThreadContext context) {
Ruby runtime = context.runtime;
RubyHash ret = RubyHash.newHash(runtime);

View File

@ -170,10 +170,12 @@ module BasicTest
m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)})
"b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
assert m.map_string_int32.keys.sort == ["a", "b"]
assert m.map_string_int32["a"] == 1
assert m.map_string_msg["b"].foo == 2
assert m.map_string_enum["a"] == :A
m.map_string_int32["c"] = 3
assert m.map_string_int32["c"] == 3
@ -206,8 +208,9 @@ module BasicTest
m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)})
expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}>"
"b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
assert_equal expected, m.inspect
end
@ -237,7 +240,8 @@ module BasicTest
m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)})
"b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
m2 = MapMessage.decode(MapMessage.encode(m))
assert m == m2
@ -298,10 +302,12 @@ module BasicTest
m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)})
"b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
expected_result = {
:map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}
:map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
:map_string_enum => {"a" => :A, "b" => :B}
}
assert_equal expected_result, m.to_h
end
@ -311,26 +317,26 @@ module BasicTest
# TODO: Fix JSON in JRuby version.
return if RUBY_PLATFORM == "java"
m = MapMessage.new(:map_string_int32 => {"a" => 1})
expected = {mapStringInt32: {a: 1}, mapStringMsg: {}}
expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}}
assert JSON.parse(MapMessage.encode_json(m), :symbolize_names => true) == expected
expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
assert_equal JSON.parse(MapMessage.encode_json(m), :symbolize_names => true), expected
json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
assert JSON.parse(json, :symbolize_names => true) == expected_preserve
assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
m2 = MapMessage.decode_json(MapMessage.encode_json(m))
assert m == m2
assert_equal m, m2
end
def test_json_maps_emit_defaults_submsg
# TODO: Fix JSON in JRuby version.
return if RUBY_PLATFORM == "java"
m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}}
expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
actual = MapMessage.encode_json(m, :emit_defaults => true)
assert JSON.parse(actual, :symbolize_names => true) == expected
assert_equal JSON.parse(actual, :symbolize_names => true), expected
end
def test_respond_to

View File

@ -80,6 +80,7 @@ message Recursive2 {
message MapMessage {
map<string, int32> map_string_int32 = 1;
map<string, TestMessage2> map_string_msg = 2;
map<string, TestEnum> map_string_enum = 3;
}
message MapMessageWireEquiv {

View File

@ -18,7 +18,7 @@ else
PTHREAD_DEF =
endif
PROTOBUF_VERSION = 18:1:0
PROTOBUF_VERSION = 19:0:0
if GCC
# Turn on all warnings except for sign comparison (we ignore sign comparison

View File

@ -111,15 +111,10 @@ bool Any::ParseAnyTypeUrl(const string& type_url,
full_type_name);
}
class Any::HasBitSetters {
class Any::_Internal {
public:
};
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Any::kTypeUrlFieldNumber;
const int Any::kValueFieldNumber;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
Any::Any()
: ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr), _any_metadata_(&type_url_, &value_) {
SharedCtor();
@ -131,11 +126,11 @@ Any::Any(const Any& from)
_any_metadata_(&type_url_, &value_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.type_url().size() > 0) {
if (!from.type_url().empty()) {
type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.type_url_);
}
value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.value().size() > 0) {
if (!from.value().empty()) {
value_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.value_);
}
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
@ -419,10 +414,6 @@ bool Any::IsInitialized() const {
return true;
}
void Any::Swap(Any* other) {
if (other == this) return;
InternalSwap(other);
}
void Any::InternalSwap(Any* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);

View File

@ -8,12 +8,12 @@
#include <string>
#include <google/protobuf/port_def.inc>
#if PROTOBUF_VERSION < 3007000
#if PROTOBUF_VERSION < 3008000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3007001 < PROTOBUF_MIN_PROTOC_VERSION
#if 3008000 < PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
@ -126,10 +126,13 @@ class PROTOBUF_EXPORT Any :
}
static bool ParseAnyTypeUrl(const string& type_url,
std::string* full_type_name);
void Swap(Any* other);
friend void swap(Any& a, Any& b) {
a.Swap(&b);
}
inline void Swap(Any* other) {
if (other == this) return;
InternalSwap(other);
}
// implements Message ----------------------------------------------
@ -191,9 +194,12 @@ class PROTOBUF_EXPORT Any :
// accessors -------------------------------------------------------
enum : int {
kTypeUrlFieldNumber = 1,
kValueFieldNumber = 2,
};
// string type_url = 1;
void clear_type_url();
static const int kTypeUrlFieldNumber = 1;
const std::string& type_url() const;
void set_type_url(const std::string& value);
void set_type_url(std::string&& value);
@ -205,7 +211,6 @@ class PROTOBUF_EXPORT Any :
// bytes value = 2;
void clear_value();
static const int kValueFieldNumber = 2;
const std::string& value() const;
void set_value(const std::string& value);
void set_value(std::string&& value);
@ -217,7 +222,7 @@ class PROTOBUF_EXPORT Any :
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
private:
class HasBitSetters;
class _Internal;
::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_;
::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_;

View File

@ -178,13 +178,13 @@ void Api::InitAsDefaultInstance() {
PROTOBUF_NAMESPACE_ID::_Api_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>(
PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance());
}
class Api::HasBitSetters {
class Api::_Internal {
public:
static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Api* msg);
};
const PROTOBUF_NAMESPACE_ID::SourceContext&
Api::HasBitSetters::source_context(const Api* msg) {
Api::_Internal::source_context(const Api* msg) {
return *msg->source_context_;
}
void Api::clear_options() {
@ -196,16 +196,6 @@ void Api::clear_source_context() {
}
source_context_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Api::kNameFieldNumber;
const int Api::kMethodsFieldNumber;
const int Api::kOptionsFieldNumber;
const int Api::kVersionFieldNumber;
const int Api::kSourceContextFieldNumber;
const int Api::kMixinsFieldNumber;
const int Api::kSyntaxFieldNumber;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
Api::Api()
: ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) {
SharedCtor();
@ -219,11 +209,11 @@ Api::Api(const Api& from)
mixins_(from.mixins_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.name().size() > 0) {
if (!from.name().empty()) {
name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.name_);
}
version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.version().size() > 0) {
if (!from.version().empty()) {
version_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.version_);
}
if (from.has_source_context()) {
@ -542,7 +532,7 @@ void Api::SerializeWithCachedSizes(
// .google.protobuf.SourceContext source_context = 5;
if (this->has_source_context()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray(
5, HasBitSetters::source_context(this), output);
5, _Internal::source_context(this), output);
}
// repeated .google.protobuf.Mixin mixins = 6;
@ -615,7 +605,7 @@ void Api::SerializeWithCachedSizes(
if (this->has_source_context()) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(
5, HasBitSetters::source_context(this), target);
5, _Internal::source_context(this), target);
}
// repeated .google.protobuf.Mixin mixins = 6;
@ -777,10 +767,6 @@ bool Api::IsInitialized() const {
return true;
}
void Api::Swap(Api* other) {
if (other == this) return;
InternalSwap(other);
}
void Api::InternalSwap(Api* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);
@ -804,23 +790,13 @@ void Api::InternalSwap(Api* other) {
void Method::InitAsDefaultInstance() {
}
class Method::HasBitSetters {
class Method::_Internal {
public:
};
void Method::clear_options() {
options_.Clear();
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Method::kNameFieldNumber;
const int Method::kRequestTypeUrlFieldNumber;
const int Method::kRequestStreamingFieldNumber;
const int Method::kResponseTypeUrlFieldNumber;
const int Method::kResponseStreamingFieldNumber;
const int Method::kOptionsFieldNumber;
const int Method::kSyntaxFieldNumber;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
Method::Method()
: ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) {
SharedCtor();
@ -832,15 +808,15 @@ Method::Method(const Method& from)
options_(from.options_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.name().size() > 0) {
if (!from.name().empty()) {
name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.name_);
}
request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.request_type_url().size() > 0) {
if (!from.request_type_url().empty()) {
request_type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.request_type_url_);
}
response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.response_type_url().size() > 0) {
if (!from.response_type_url().empty()) {
response_type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.response_type_url_);
}
::memcpy(&request_streaming_, &from.request_streaming_,
@ -1374,10 +1350,6 @@ bool Method::IsInitialized() const {
return true;
}
void Method::Swap(Method* other) {
if (other == this) return;
InternalSwap(other);
}
void Method::InternalSwap(Method* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);
@ -1402,15 +1374,10 @@ void Method::InternalSwap(Method* other) {
void Mixin::InitAsDefaultInstance() {
}
class Mixin::HasBitSetters {
class Mixin::_Internal {
public:
};
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Mixin::kNameFieldNumber;
const int Mixin::kRootFieldNumber;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
Mixin::Mixin()
: ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) {
SharedCtor();
@ -1421,11 +1388,11 @@ Mixin::Mixin(const Mixin& from)
_internal_metadata_(nullptr) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.name().size() > 0) {
if (!from.name().empty()) {
name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.name_);
}
root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (from.root().size() > 0) {
if (!from.root().empty()) {
root_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.root_);
}
// @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin)
@ -1721,10 +1688,6 @@ bool Mixin::IsInitialized() const {
return true;
}
void Mixin::Swap(Mixin* other) {
if (other == this) return;
InternalSwap(other);
}
void Mixin::InternalSwap(Mixin* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);

Some files were not shown because too many files have changed in this diff Show More